test_pivot.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. '''
  2. @author: olivier.massot, 2019
  3. '''
  4. from collections import Counter
  5. import time
  6. class Node():
  7. def __init__(self, pos, path=[]):
  8. self.pos = pos
  9. self.path = path
  10. class Grid():
  11. dim = 12
  12. owned = 3
  13. def __init__(self):
  14. self.cells = [(x, y) for x in range(Grid.dim) for y in range(Grid.dim)]
  15. def print_grid(self):
  16. grid = [["" for _ in range(Grid.dim)] for _ in range(Grid.dim)]
  17. for x, y in self.cells:
  18. grid[y][x] = f"({x:02d}, {y:02d})" if self._active_owned((x, y), 0) else "________"
  19. return "\n".join(["".join([c for c in row]) for row in grid])
  20. @staticmethod
  21. def manhattan(from_, to_):
  22. xa, ya = from_
  23. xb, yb = to_
  24. return abs(xa - xb) + abs(ya - yb)
  25. def neighbors(self, x, y, diags=False):
  26. neighs = [(x, y - 1), (x - 1, y), (x + 1, y), (x, y + 1)]
  27. if diags:
  28. neighs += [(x - 1, y - 1), (x + 1, y - 1), (x - 1, y + 1), (x + 1, y + 1)]
  29. return [(x, y) for x, y in neighs if 0 <= x < Grid.dim and 0 <= y < Grid.dim]
  30. def oriented_neighbors(self, x, y, orient):
  31. return [(x + 1, y), (x, y + 1)] if orient > 0 else [(x - 1, y), (x, y - 1)]
  32. def update_frontlines(self):
  33. self.frontline = []
  34. for p in self.cells:
  35. if self._active_owned(p, 0):
  36. if any(not self._active_owned(n, 0) for n in self.neighbors(*p)):
  37. # cell.update_threat()
  38. self.frontline.append(p)
  39. def _active_owned(self, pos, player_id):
  40. return pos in [(11,11), (10,11), (9,11), (8,11), (7,11), (6,11), (5,11), (4,11),
  41. (11,10), (10,10), (9,10), (8,10), (7,10), (6,10), (5,10), (4,10),
  42. (11,9), (10,9), (9,9), (8,9), (7,9), (6,9), (5,9),
  43. (7,8), (6,8), (5,8), (4,8),
  44. (7,7), (4,7)]
  45. def __active_owned(self, pos, player_id):
  46. return pos[0] < 12 and pos[1] < 12
  47. def update_pivot_for(self, player_id):
  48. # start = self.get_hq(player_id).pos
  49. start = (11,11)
  50. start_node = Node(start)
  51. buffer = [start_node]
  52. nodes = {start_node}
  53. ignored = [p for p in self.cells if len([n for n in self.neighbors(*p, diags=True) if self._active_owned(n, player_id)]) == 8]
  54. while buffer:
  55. new_buffer = []
  56. for node in buffer:
  57. neighbors = [p for p in self.neighbors(*node.pos) if self._active_owned(p, player_id)]
  58. if node.pos in ignored:
  59. continue
  60. for n in neighbors:
  61. if not n in node.path:
  62. new_node = Node(n, node.path + [node.pos])
  63. nodes.add(new_node)
  64. new_buffer.append(new_node)
  65. buffer = new_buffer
  66. paths_to = {}
  67. for node in nodes:
  68. if not node.pos in paths_to:
  69. paths_to[node.pos] = []
  70. paths_to[node.pos].append(node.path)
  71. print(paths_to)
  72. pivots = {}
  73. for candidate in paths_to:
  74. if candidate == start:
  75. continue
  76. for p, paths in paths_to.items():
  77. if not paths or not paths[0] or p in ignored:
  78. continue
  79. if all(candidate in path for path in paths):
  80. if not candidate in pivots:
  81. pivots[candidate] = []
  82. pivots[candidate].append(p)
  83. occurrences = Counter(sum(sum(paths_to.values(), []), []))
  84. while ignored:
  85. new_ignored = []
  86. for p in ignored:
  87. occured_neighbors = [occurrences[n] for n in self.neighbors(*p) if n in occurrences]
  88. if not occured_neighbors:
  89. new_ignored.append(p)
  90. continue
  91. occurrences[p] = 2 * sum(occured_neighbors) // len(occured_neighbors)
  92. ignored = new_ignored
  93. print(occurrences)
  94. return pivots
  95. def __update_pivot_for(self, player_id):
  96. # start = self.get_hq(player_id).pos
  97. start = (11,11)
  98. orient = 1
  99. buffer = [(None, start)]
  100. bounds = []
  101. while buffer:
  102. new_buffer = []
  103. for o, p in buffer:
  104. for n in self.oriented_neighbors(*p, orient):
  105. if self._active_owned(n, player_id) and not (p, n) in bounds and n != o:
  106. bounds.append((p, n))
  107. new_buffer.append((p, n))
  108. buffer = new_buffer
  109. print(bounds)
  110. parents_number = Counter()
  111. for parent, child in bounds:
  112. parents_number[child] += 1
  113. print(parents_number)
  114. pivots = set()
  115. for parent, child in bounds:
  116. if parent == start:
  117. continue
  118. if parents_number[child] == 1:
  119. pivots |= {parent}
  120. return pivots
  121. grid = Grid()
  122. Grid.owned = 5
  123. print(grid.print_grid())
  124. print()
  125. t0 = time.time()
  126. a = grid.update_pivot_for(0)
  127. print(a)
  128. print(time.time() - t0)