|
|
@@ -1,3 +1,4 @@
|
|
|
+import heapq
|
|
|
import sys
|
|
|
import math
|
|
|
import time
|
|
|
@@ -22,6 +23,31 @@ class BaseClass:
|
|
|
return f"<{self.__class__.__name__}: {self.__dict__}>"
|
|
|
|
|
|
|
|
|
+class Queue(BaseClass):
|
|
|
+ def __init__(self):
|
|
|
+ self.items = []
|
|
|
+
|
|
|
+ def __bool__(self):
|
|
|
+ return bool(self.items)
|
|
|
+
|
|
|
+ def __repr__(self):
|
|
|
+ return str(self.items)
|
|
|
+
|
|
|
+ def values(self):
|
|
|
+ return (v for _, v in self.items)
|
|
|
+
|
|
|
+ def put(self, priority, item):
|
|
|
+ while priority in [p for p, _ in self.items]:
|
|
|
+ priority += 1
|
|
|
+ heapq.heappush(self.items, (priority, item))
|
|
|
+
|
|
|
+ def get(self):
|
|
|
+ return heapq.heappop(self.items)[1]
|
|
|
+
|
|
|
+ def get_items(self):
|
|
|
+ return heapq.heappop(self.items)
|
|
|
+
|
|
|
+
|
|
|
class Player(BaseClass):
|
|
|
def __init__(self, id_):
|
|
|
self.id = id_
|
|
|
@@ -52,6 +78,10 @@ class Unit(BaseClass):
|
|
|
self.y = None
|
|
|
self.owner = None
|
|
|
|
|
|
+ @property
|
|
|
+ def pos(self):
|
|
|
+ return self.x, self.y
|
|
|
+
|
|
|
@property
|
|
|
def owned(self):
|
|
|
return self.owner == ME.id
|
|
|
@@ -69,6 +99,42 @@ class CultLeader(Unit):
|
|
|
pass
|
|
|
|
|
|
|
|
|
+class Action(BaseClass):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+class ActionWait(Action):
|
|
|
+ def exec(self):
|
|
|
+ print("WAIT")
|
|
|
+
|
|
|
+
|
|
|
+class ActionMove(Action):
|
|
|
+ def __init__(self, unit, pos):
|
|
|
+ self.unit = unit
|
|
|
+ self.pos = pos
|
|
|
+
|
|
|
+ def exec(self):
|
|
|
+ print(f"{self.unit.id} MOVE {self.pos[0]} {self.pos[1]}")
|
|
|
+
|
|
|
+
|
|
|
+class ActionShoot(Action):
|
|
|
+ def __init__(self, unit, target):
|
|
|
+ self.unit = unit
|
|
|
+ self.target = target
|
|
|
+
|
|
|
+ def exec(self, id_, target_id):
|
|
|
+ print(f"{self.unit.id} SHOOT {self.target.id}")
|
|
|
+
|
|
|
+
|
|
|
+class ActionConvert(Action):
|
|
|
+ def __init__(self, unit, target):
|
|
|
+ self.unit = unit
|
|
|
+ self.target = target
|
|
|
+
|
|
|
+ def exec(self):
|
|
|
+ print(f"{self.unit.id} CONVERT {self.target.id}")
|
|
|
+
|
|
|
+
|
|
|
class Grid(BaseClass):
|
|
|
def __init__(self, width, height):
|
|
|
self.width = width
|
|
|
@@ -90,9 +156,36 @@ class Grid(BaseClass):
|
|
|
|
|
|
def update_index(self):
|
|
|
self.index = {}
|
|
|
- for unit in self.units:
|
|
|
+ for unit in self.units.values():
|
|
|
self.index[(unit.x, unit.y)] = unit
|
|
|
|
|
|
+ def own_cult_leader(self):
|
|
|
+ return next(u for u in self.units.values() if type(u) is CultLeader and u.owned)
|
|
|
+
|
|
|
+ def opponent_cult_leader(self):
|
|
|
+ return [u for u in self.units.values() if type(u) is CultLeader and not u.owned]
|
|
|
+
|
|
|
+ def allied_cultists(self):
|
|
|
+ return [u for u in self.units.values() if type(u) is not CultLeader and u.owned]
|
|
|
+
|
|
|
+ def opponent_cultists(self):
|
|
|
+ return [u for u in self.units.values() if type(u) is not CultLeader and not u.owned]
|
|
|
+
|
|
|
+ def neutrals(self):
|
|
|
+ return [u for u in self.units.values() if u.neutral]
|
|
|
+
|
|
|
+ def list_actions(self):
|
|
|
+ actions = Queue()
|
|
|
+
|
|
|
+ cult_leader = self.own_cult_leader()
|
|
|
+
|
|
|
+ for n in self.neutrals():
|
|
|
+ action = ActionConvert(cult_leader, n)
|
|
|
+ distance = self.manhattan(cult_leader.pos, n.pos)
|
|
|
+ actions.put(distance, action)
|
|
|
+
|
|
|
+ return actions
|
|
|
+
|
|
|
def in_grid(self, pos):
|
|
|
return 0 <= pos[0] < self.width and 0 <= pos[1] < self.height
|
|
|
|
|
|
@@ -153,38 +246,18 @@ class Grid(BaseClass):
|
|
|
GRID = Grid(*[int(i) for i in input().split()])
|
|
|
GRID.obstacles = [(i, j) for i in range(GRID.height) for j, val in enumerate(input()) if val == 'x']
|
|
|
|
|
|
-
|
|
|
-class Action(BaseClass):
|
|
|
- pass
|
|
|
-
|
|
|
-
|
|
|
-class ActionWait(Action):
|
|
|
- def exec(self):
|
|
|
- print("WAIT")
|
|
|
-
|
|
|
-
|
|
|
-class ActionMove(Action):
|
|
|
- def exec(self, id_, pos):
|
|
|
- x, y = pos
|
|
|
- print(f"{id_} MOVE {x} {y}")
|
|
|
-
|
|
|
-
|
|
|
-class ActionShoot(Action):
|
|
|
- def exec(self, id_, target_id):
|
|
|
- print(f"{id_} SHOOT {target_id}")
|
|
|
-
|
|
|
-
|
|
|
-class ActionConvert(Action):
|
|
|
- def exec(self, id_, target_id):
|
|
|
- print(f"{id_} CONVERT {target_id}")
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
while 1:
|
|
|
for _ in range(int(input())):
|
|
|
GRID.update_unit(*[int(j) for j in input().split()])
|
|
|
GRID.update_index()
|
|
|
|
|
|
- log(GRID.units)
|
|
|
+ actions = GRID.list_actions()
|
|
|
+ log(actions)
|
|
|
+
|
|
|
+ try:
|
|
|
+ action = actions.get()
|
|
|
+ except IndexError:
|
|
|
+ action = ActionWait()
|
|
|
|
|
|
+ action.exec()
|
|
|
GRID.round += 1
|