From 0fc4d40b785ee1a7151e6b3aacc2f7f2c7f93795 Mon Sep 17 00:00:00 2001 From: Vasyl Horbachenko Date: Wed, 6 Jun 2018 00:18:25 +0300 Subject: [PATCH] canvas map overview WIP --- .idea/dcs_pmcliberation.iml | 2 +- .idea/misc.xml | 2 +- game/event.py | 7 ++++- game/game.py | 11 ++++--- game/operation.py | 5 ++- shop/db.py | 2 +- theater/caucasus.py | 35 ++++++++++++++++++--- ui/mainmenu.py | 22 +++++-------- ui/overviewcanvas.py | 62 +++++++++++++++++++++++++++++++++++++ 9 files changed, 119 insertions(+), 29 deletions(-) create mode 100644 ui/overviewcanvas.py diff --git a/.idea/dcs_pmcliberation.iml b/.idea/dcs_pmcliberation.iml index 9eedabcf..1f377c84 100644 --- a/.idea/dcs_pmcliberation.iml +++ b/.idea/dcs_pmcliberation.iml @@ -4,7 +4,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index e524f659..65531ca9 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/game/event.py b/game/event.py index cb23bbf0..c2b475a3 100644 --- a/game/event.py +++ b/game/event.py @@ -92,6 +92,7 @@ class InterceptEvent(Event): ESCORT_AMOUNT_FACTOR = 2 BONUS_BASE = 5 STRENGTH_INFLUENCE = 0.25 + AIRDEFENSE_COUNT = 3 def __str__(self): return "Intercept at {} ({})".format(self.to_cp, "*" * self.difficulty) @@ -112,6 +113,8 @@ class InterceptEvent(Event): transport_unit = random.choice(db.find_unittype(Transport, self.defender.name)) assert transport_unit is not None + airdefense_unit = db.find_unittype(AirDefence, self.defender.name)[0] + self.operation = InterceptOperation(mission=self.mission, attacker=self.attacker, defender=self.defender, @@ -121,6 +124,7 @@ class InterceptEvent(Event): destination_port=self.to_cp.airport, escort=escort, transport={transport_unit: 1}, + airdefense={airdefense_unit: self.AIRDEFENSE_COUNT}, interceptors=interceptors) def player_defending(self, escort: db.PlaneDict, clients: db.PlaneDict): @@ -137,7 +141,8 @@ class InterceptEvent(Event): destination_port=self.to_cp.airport, escort=escort, transport={transport_unit: 1}, - interceptors=interceptors) + interceptors=interceptors, + airdefense={}) class CaptureEvent(Event): diff --git a/game/game.py b/game/game.py index f4e24584..18a770c2 100644 --- a/game/game.py +++ b/game/game.py @@ -24,7 +24,7 @@ COMMISION_AMOUNTS_FACTORS = { ENEMY_INTERCEPT_PROBABILITY_BASE = 25 -ENEMY_CAPTURE_PROBABILITY_BASE = 15 +ENEMY_CAPTURE_PROBABILITY_BASE = 5 PLAYER_INTERCEPT_PROBABILITY_BASE = 30 PLAYER_GROUNDINTERCEPT_PROBABILITY_BASE = 30 @@ -49,10 +49,11 @@ class Game: def _fill_cap_events(self): for from_cp, to_cp in self.theater.conflicts(True): - self.events.append(CaptureEvent(attacker_name=self.player, - defender_name=self.enemy, - from_cp=from_cp, - to_cp=to_cp)) + if to_cp not in [x.to_cp for x in self.events]: + self.events.append(CaptureEvent(attacker_name=self.player, + defender_name=self.enemy, + from_cp=from_cp, + to_cp=to_cp)) def _generate_enemy_caps(self): for from_cp, to_cp in self.theater.conflicts(False): diff --git a/game/operation.py b/game/operation.py index 23232449..18e1cd01 100644 --- a/game/operation.py +++ b/game/operation.py @@ -48,7 +48,7 @@ class CaptureOperation(Operation): attack: db.ArmorDict, intercept: db.PlaneDict, defense: db.ArmorDict, - aa: db.AADict): + aa: db.AirDefenseDict): conflict = to_cp.conflict_attack(from_cp, attacker, defender) super(CaptureOperation, self).__init__(mission, conflict) @@ -84,6 +84,7 @@ class InterceptOperation(Operation): destination_port: Airport, escort: db.PlaneDict, transport: db.PlaneDict, + airdefense: db.AirDefenseDict, interceptors: db.PlaneDict): conflict = Conflict.intercept_conflict( attacker=attacker, @@ -99,12 +100,14 @@ class InterceptOperation(Operation): self.defender_clients = defender_clients self.escort = escort self.transport = transport + self.airdefense = airdefense self.interceptors = interceptors def generate(self): self.airgen.generate_transport(self.transport, self.destination_port) self.airgen.generate_transport_escort(self.escort, clients=self.defender_clients) self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients) + self.aagen.generate(self.airdefense) class GroundInterceptOperation(Operation): diff --git a/shop/db.py b/shop/db.py index f1fc416a..50941400 100644 --- a/shop/db.py +++ b/shop/db.py @@ -60,7 +60,7 @@ UNIT_BY_COUNTRY = { UnitsDict = typing.Dict[UnitType, int] PlaneDict = typing.Dict[PlaneType, int] ArmorDict = typing.Dict[VehicleType, int] -AADict = typing.Dict[AirDefence, int] +AirDefenseDict = typing.Dict[AirDefence, int] def unit_task(unit: UnitType) -> Task: diff --git a/theater/caucasus.py b/theater/caucasus.py index aaae9885..c1e8fc5e 100644 --- a/theater/caucasus.py +++ b/theater/caucasus.py @@ -5,6 +5,7 @@ from .base import * class CaucasusTheater(ConflictTheater): + soganlug = ControlPoint(caucasus.Soganlug, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW) kutaisi = ControlPoint(caucasus.Kutaisi, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW) senaki = ControlPoint(caucasus.Senaki, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_LOW) kobuleti = ControlPoint(caucasus.Kobuleti, COAST_VERTICAL, SIZE_SMALL, IMPORTANCE_LOW) @@ -13,14 +14,38 @@ class CaucasusTheater(ConflictTheater): gudauta = ControlPoint(caucasus.Gudauta, COAST_VERTICAL, SIZE_REGULAR, IMPORTANCE_MEDIUM) sochi = ControlPoint(caucasus.Sochi, COAST_VERTICAL, SIZE_BIG, IMPORTANCE_HIGH) - def __init__(self): - self.kutaisi.captured = True + maykop = ControlPoint(caucasus.Maykop, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) + krasnodar = ControlPoint(caucasus.KrasnodarCenter, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) + novorossiysk = ControlPoint(caucasus.Novorossiysk, COAST_VERTICAL, SIZE_BIG, IMPORTANCE_HIGH) + gelendzhik = ControlPoint(caucasus.Gelendzhik, COAST_VERTICAL, SIZE_BIG, IMPORTANCE_HIGH) + krymsk = ControlPoint(caucasus.Krymsk, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) + anapa = ControlPoint(caucasus.Anapa, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) - self.add_controlpoint(self.kutaisi, connected_to=[self.senaki]) + beslan = ControlPoint(caucasus.Beslan, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_MEDIUM) + nalchik = ControlPoint(caucasus.Nalchik, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_MEDIUM) + mineralnye = ControlPoint(caucasus.Mineralnye, ALL_RADIALS, SIZE_BIG, IMPORTANCE_HIGH) + mozdok = ControlPoint(caucasus.Mozdok, ALL_RADIALS, SIZE_BIG, IMPORTANCE_HIGH) + + def __init__(self): + self.soganlug.captured = True + + self.add_controlpoint(self.soganlug, connected_to=[self.kutaisi, self.beslan]) + self.add_controlpoint(self.beslan, connected_to=[self.soganlug, self.mozdok, self.nalchik]) + self.add_controlpoint(self.nalchik, connected_to=[self.beslan, self.mozdok, self.mineralnye]) + self.add_controlpoint(self.mozdok, connected_to=[self.nalchik, self.beslan, self.mineralnye]) + self.add_controlpoint(self.mineralnye, connected_to=[self.nalchik, self.mozdok, self.maykop]) + self.add_controlpoint(self.maykop, connected_to=[self.mineralnye, self.krasnodar]) + + self.add_controlpoint(self.kutaisi, connected_to=[self.soganlug, self.senaki]) self.add_controlpoint(self.senaki, connected_to=[self.kobuleti, self.sukhumi, self.kutaisi]) self.add_controlpoint(self.kobuleti, connected_to=[self.batumi, self.senaki]) self.add_controlpoint(self.batumi, connected_to=[self.kobuleti]) - self.add_controlpoint(self.sukhumi, connected_to=[self.gudauta, self.senaki]) self.add_controlpoint(self.gudauta, connected_to=[self.sochi, self.sukhumi]) - self.add_controlpoint(self.sochi, connected_to=[self.gudauta]) + self.add_controlpoint(self.sochi, connected_to=[self.gudauta, self.gelendzhik]) + + self.add_controlpoint(self.gelendzhik, connected_to=[self.sochi, self.novorossiysk]) + self.add_controlpoint(self.novorossiysk, connected_to=[self.gelendzhik, self.anapa]) + self.add_controlpoint(self.krymsk, connected_to=[self.novorossiysk, self.anapa, self.krasnodar]) + self.add_controlpoint(self.anapa, connected_to=[self.novorossiysk, self.krymsk]) + self.add_controlpoint(self.krasnodar, connected_to=[self.krymsk, self.maykop]) diff --git a/ui/mainmenu.py b/ui/mainmenu.py index be03dd02..fc794ca8 100644 --- a/ui/mainmenu.py +++ b/ui/mainmenu.py @@ -4,6 +4,7 @@ from tkinter.ttk import * from ui.window import * from ui.eventmenu import * from ui.basemenu import * +from ui.overviewcanvas import * from game.game import * @@ -12,15 +13,19 @@ class MainMenu(Menu): def __init__(self, window: Window, parent, game: Game): super(MainMenu, self).__init__(window, parent, game) - self.image = PhotoImage(file="resources/caumap.gif") - map = Label(window.left_pane, image=self.image) - map.grid() + #self.image = PhotoImage(file="resources/caumap.gif") + #map = Label(window.left_pane, image=self.image) + #map.grid() + + self.upd = OverviewCanvas(self.window.left_pane, game) + self.upd.update() self.frame = self.window.right_pane self.frame.grid_columnconfigure(0, weight=1) def display(self): self.window.clear_right_pane() + self.upd.update() row = 1 @@ -63,17 +68,6 @@ class MainMenu(Menu): for cp in self.game.theater.player_points(): cp_button(cp) - Separator(self.frame, orient='horizontal').grid(row=row, sticky=EW); row += 1 - for cp in self.game.theater.enemy_bases(): - title = "[{}] {}{}{}{}".format( - int(cp.base.strength * 10), - cp.name, - "^" * cp.base.total_planes, - "." * cp.base.total_armor, - "*" * cp.base.total_aa) - Label(self.frame, text=title).grid(row=row, sticky=NE) - row += 1 - def pass_turn(self): self.game.pass_turn(no_action=True) self.display() diff --git a/ui/overviewcanvas.py b/ui/overviewcanvas.py new file mode 100644 index 00000000..b22f6825 --- /dev/null +++ b/ui/overviewcanvas.py @@ -0,0 +1,62 @@ +from tkinter import * +from tkinter.ttk import * + +from ui.window import * + +from game.game import * + + +class OverviewCanvas: + def __init__(self, frame: Frame, game: Game): + self.canvas = Canvas(frame, width=600, height=400) + self.canvas.grid(column=0, row=0, sticky=NSEW) + self.image = PhotoImage(file="resources/caumap.gif") + + self.game = game + + def cp_coordinates(self, cp: ControlPoint) -> (int, int): + point_a = (-317948.32727306, 635639.37385346) + point_a_img = 361 - 60, 306 + 20 + + point_b = (-355692.3067714, 617269.96285781) + point_b_img = 345 - 59.5, 339 + 19.5 + + x_dist = point_a_img[0] - point_b_img[0] + lon_dist = point_a[1] - point_b[1] + + y_dist = point_a_img[1] - point_b_img[1] + lat_dist = point_b[0] - point_a[0] + + x_scale = float(x_dist) / float(lon_dist) + y_scale = float(y_dist) / float(lat_dist) + + # --- + x_offset = cp.position.x - point_a[0] + y_offset = cp.position.y - point_a[1] + + return point_b_img[1] + y_offset * y_scale, point_a_img[0] - x_offset * x_scale + + def update(self): + self.canvas.delete(ALL) + self.canvas.create_image((self.image.width()/2, self.image.height()/2), image=self.image) + + for cp in self.game.theater.controlpoints: + coords = self.cp_coordinates(cp) + for connected_cp in cp.connected_points: + connected_coords = self.cp_coordinates(connected_cp) + if connected_cp.captured != cp.captured: + color = "red" + elif connected_cp.captured and cp.captured: + color = "blue" + else: + color = "black" + + self.canvas.create_line((coords[0], coords[1], connected_coords[0], connected_coords[1]), width=3, fill=color) + + for cp in self.game.theater.controlpoints: + coords = self.cp_coordinates(cp) + arc_size = 12 * math.pow(cp.importance, 1) + self.canvas.create_arc((coords[0] - arc_size/2, coords[1] - arc_size/2), + (coords[0]+arc_size, coords[1]+arc_size), + fill='red') +