script.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. '''
  2. >> https://www.codingame.com/ide/173171838252e7c6fd6f3ff9cb8169431a08eec1
  3. @author: olivier.massot, may 2019
  4. '''
  5. import sys
  6. import time
  7. debug = True
  8. t0 = time.time()
  9. def log(*msg):
  10. if debug:
  11. print("{} - ".format(str(time.time() - t0)[1:5]), *msg, file=sys.stderr)
  12. class Base():
  13. def __repr__(self):
  14. return f"<{self.__class__.__name__}: {self.__dict__}>"
  15. class BaseLoc(Base):
  16. def __init__(self, x, y):
  17. self.x = x
  18. self.y = y
  19. @property
  20. def pos(self):
  21. return self.x, self.y
  22. class Mine(BaseLoc):
  23. def __init__(self, x, y):
  24. super().__init__(x, y)
  25. class BaseOwnedLoc(BaseLoc):
  26. def __init__(self, x, y, owner):
  27. super().__init__(x, y)
  28. self.owner = owner
  29. @property
  30. def owned(self):
  31. return self.owner == 0
  32. class Building(BaseOwnedLoc):
  33. def __init__(self, owner, type_, x, y):
  34. super().__init__(x, y, owner)
  35. self.type_ = type_
  36. class Unit(BaseOwnedLoc):
  37. def __init__(self, owner, id_, level, x, y):
  38. super().__init__(x, y, owner)
  39. self.id_ = id_
  40. self.level = level
  41. class Player(Base):
  42. def __init__(self, id_):
  43. self.id_ = id_
  44. self.gold = 0
  45. self.income = 0
  46. self.units = []
  47. self.buildings = []
  48. self.hq = None
  49. def update(self, gold, income, units, buildings):
  50. self.gold = gold
  51. self.income = income
  52. self.units = [u for u in units if u.owner == self.id_]
  53. self.buildings = [b for b in buildings if b.owner == self.id_]
  54. class Cell(Base):
  55. def __init__(self, x, y):
  56. self.x = x
  57. self.y = y
  58. self._content = "#"
  59. self.unit = None
  60. self.building = None
  61. @property
  62. def pos(self):
  63. return self.x, self.y
  64. @property
  65. def raw_val(self):
  66. return self._content
  67. def update(self, content, unit = None, building = None):
  68. self._content = content
  69. self.unit = unit
  70. self.building = building
  71. @property
  72. def movable(self):
  73. return self._content != "#"
  74. @property
  75. def owned(self):
  76. return self._content.lower() == "o"
  77. @property
  78. def opponents(self):
  79. return self._content.lower() == "x"
  80. @property
  81. def headquarter(self):
  82. return self.pos in Grid.hqs
  83. @property
  84. def occupied(self):
  85. return self.unit or self.building
  86. @property
  87. def is_active(self):
  88. return self._content.isupper()
  89. class Grid(Base):
  90. dim = 12
  91. hqs = [(0,0), (11,11)]
  92. def __init__(self, mines = []):
  93. self.cells = {(x, y): Cell(x, y) for x in range(Grid.dim) for y in range(Grid.dim)}
  94. self.units = {}
  95. self.buildings = {}
  96. self.mines = {(m.x, m.y): m for m in mines}
  97. def print_grid(self):
  98. return "\n".join(["".join([c for c in row]) for row in self.grid])
  99. @property
  100. def pos(self):
  101. return self.x, self.y
  102. @property
  103. def grid(self):
  104. return [[self.cells[(x, y)].raw_val for x in range(Grid.dim)] for y in range(Grid.dim)]
  105. def __getitem__(self, key):
  106. return self.cells[key]
  107. def update(self, grid, buildings, units):
  108. self.buildings = {(b.x, b.y): b for b in buildings}
  109. self.units = {(u.x, u.y): u for u in units}
  110. for y, row in enumerate(grid):
  111. for x, c in enumerate(row):
  112. self.cells[(x, y)].update(c,
  113. self.units.get((x, y), None),
  114. self.buildings.get((x, y), None))
  115. def neighbors(self, x, y, diags=True):
  116. neighs = [(x, y - 1), (x - 1, y), (x + 1, y), (x, y + 1)]
  117. if diags:
  118. neighs += [(x - 1, y - 1), (x + 1, y - 1), (x - 1, y + 1), (x + 1, y + 1)]
  119. return [(x, y) for x, y in neighs if 0 <= x < Grid.dim and 0 <= y < Grid.dim]
  120. def where_to_train(self):
  121. available = set()
  122. for p, c in self.cells.items():
  123. if c.owned:
  124. available.add(p)
  125. available |= set(self.neighbors(*p))
  126. return (self.cells[p] for p in available if not self.cells[p].occupied)
  127. mines = [Mine(*[int(j) for j in input().split()]) for _ in range(int(input()))]
  128. log(f"* mines: {mines}")
  129. grid = Grid()
  130. player = Player(0)
  131. opponent = Player(1)
  132. while True:
  133. # <--- get input
  134. gold, income = int(input()), int(input())
  135. opponent_gold, opponent_income = int(input()), int(input())
  136. new_grid = [list(input()) for _ in range(12)]
  137. buildings = [Building(*[int(j) for j in input().split()]) for _ in range(int(input()))]
  138. log(f"* buildings: {buildings}")
  139. units = [Unit(*[int(j) for j in input().split()]) for _ in range(int(input()))]
  140. log(f"* units: {units}")
  141. # --->
  142. # <--- update data
  143. grid.update(new_grid, buildings, units)
  144. log(f"grid:\n{grid.print_grid()}")
  145. player.update(gold, income, units, buildings)
  146. if player.hq is None:
  147. player.hq = next((c for c in [grid[(x, y)] for x, y in Grid.hqs] if c.owned))
  148. log(f"player:\n{player}")
  149. opponent.update(opponent_gold, opponent_income, units, buildings)
  150. if opponent.hq is None:
  151. opponent.hq = next((c for c in [grid[(x, y)] for x, y in Grid.hqs] if c.opponents))
  152. log(f"opponent:\n{opponent}")
  153. # --->
  154. # start
  155. if not player.units:
  156. c = next(grid.where_to_train())
  157. print(f"TRAIN 1 {c.x} {c.y}")
  158. print("WAIT")