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