| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- import sys
- import math
- import time
- debug = True
- t0 = time.time()
- def log(*msg):
- if debug:
- print("{} - ".format(str(time.time() - t0)[1:5]), *msg, file=sys.stderr, flush=True)
- def time_to(total, step):
- """ number of steps to reach total """
- return total // step + (1 if total % step > 0 else 0)
- class BaseClass:
- def __repr__(self):
- return f"<{self.__class__.__name__}: {self.__dict__}>"
- class Player(BaseClass):
- def __init__(self, id_):
- self.id = id_
- ME = Player(int(input())) # Input gives the player id: 0 plays first
- OPPONENT = Player(1 - ME.id)
- PLAYERS_INDEX = {p.id: p for p in [ME, OPPONENT]}
- PLAYERS_ORDER = sorted([ME, OPPONENT], key=lambda p: p.id)
- class Unit(BaseClass):
- TYPE_CULTIST = 0
- TYPE_CULT_LEADER = 1
- OWNER_0 = 0
- OWNER_1 = 1
- NO_OWNER = 2
- SHOOTING_RANGE = 6
- SHOOTING_MAX_DAMAGE = 7
- def __init__(self, id_):
- self.id = id_
- self.hp = 10
- self.x = None
- self.y = None
- self.owner = None
- @property
- def owned(self):
- return self.owner == ME.id
- @property
- def opponent(self):
- return self.owner == OPPONENT.id
- @property
- def neutral(self):
- return self.owner == self.NO_OWNER
- class CultLeader(Unit):
- pass
- class Grid(BaseClass):
- def __init__(self, width, height):
- self.width = width
- self.height = height
- self.obstacles = []
- self.index = {}
- self.units = {}
- self.round = 0
- def update_unit(self, id_, type_, hp, x, y, owner):
- if id_ not in self.units:
- self.units[id_] = Unit(id_) if type_ != Unit.TYPE_CULT_LEADER else CultLeader(id_)
- unit = self.units[id_]
- unit.hp = hp
- unit.x = x
- unit.y = y
- unit.owner = owner
- def update_index(self):
- self.index = {}
- for unit in self.units:
- self.index[(unit.x, unit.y)] = unit
- def in_grid(self, pos):
- return 0 <= pos[0] < self.width and 0 <= pos[1] < self.height
- def can_see_trough(self, pos):
- return self.in_grid(pos) and pos not in self.obstacles + list(self.index.values())
- def can_move_on(self, pos):
- return self.in_grid(pos) and pos not in self.obstacles + list(self.index.values())
- @staticmethod
- def manhattan(from_, to_):
- xa, ya = from_
- xb, yb = to_
- return abs(xa - xb) + abs(ya - yb)
- @classmethod
- def line(cls, from_, to_):
- """ Implementation of bresenham's algorithm """
- xa, ya = from_
- xb, yb = to_
- if (xa, ya) == (xb, yb):
- return [(xa, ya)]
- # diagonal symmetry
- vertically_oriented = (abs(yb - ya) > abs(xb - xa))
- if vertically_oriented:
- ya, xa, yb, xb = xa, ya, xb, yb
- # horizontal symmetry
- reversed_sym = (xa > xb)
- if reversed_sym:
- xb, yb, xa, ya = xa, ya, xb, yb
- # angle
- dx, dy = xb - xa, yb - ya
- alpha = (abs(dy) / dx)
- offset = 0.0
- step = 1 if dy > 0 else -1
- result = []
- y_ = ya
- for x_ in range(xa, xb + 1):
- result.append((y_, x_) if vertically_oriented else (x_, y_))
- offset += alpha
- if offset > 0.5:
- y_ += step
- offset -= 1.0
- if reversed_sym:
- result.reverse()
- return result
- # Create grid
- 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)
- GRID.round += 1
|