| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- '''
- @author: olivier.massot, 2019
- '''
- from collections import Counter
- import time
- class Node():
- def __init__(self, pos, path=[]):
- self.pos = pos
- self.path = path
- class Grid():
- dim = 12
- owned = 3
- def __init__(self):
-
- self.cells = [(x, y) for x in range(Grid.dim) for y in range(Grid.dim)]
- def print_grid(self):
- grid = [["" for _ in range(Grid.dim)] for _ in range(Grid.dim)]
- for x, y in self.cells:
- grid[y][x] = f"({x:02d}, {y:02d})" if self._active_owned((x, y), 0) else "________"
- return "\n".join(["".join([c for c in row]) for row in grid])
-
- @staticmethod
- def manhattan(from_, to_):
- xa, ya = from_
- xb, yb = to_
- return abs(xa - xb) + abs(ya - yb)
-
- def neighbors(self, x, y, diags=False):
- neighs = [(x, y - 1), (x - 1, y), (x + 1, y), (x, y + 1)]
- if diags:
- neighs += [(x - 1, y - 1), (x + 1, y - 1), (x - 1, y + 1), (x + 1, y + 1)]
- return [(x, y) for x, y in neighs if 0 <= x < Grid.dim and 0 <= y < Grid.dim]
-
- def oriented_neighbors(self, x, y, orient):
- return [(x + 1, y), (x, y + 1)] if orient > 0 else [(x - 1, y), (x, y - 1)]
-
- def update_frontlines(self):
- self.frontline = []
-
- for p in self.cells:
- if self._active_owned(p, 0):
- if any(not self._active_owned(n, 0) for n in self.neighbors(*p)):
- # cell.update_threat()
- self.frontline.append(p)
-
- def _active_owned(self, pos, player_id):
- return pos in [(11,11), (10,11), (9,11), (8,11), (7,11), (6,11), (5,11), (4,11),
- (11,10), (10,10), (9,10), (8,10), (7,10), (6,10), (5,10), (4,10),
- (11,9), (10,9), (9,9), (8,9), (7,9), (6,9), (5,9),
- (7,8), (6,8), (5,8), (4,8),
- (7,7), (4,7)]
-
- def __active_owned(self, pos, player_id):
- return pos[0] < 12 and pos[1] < 12
- def update_pivot_for(self, player_id):
- # start = self.get_hq(player_id).pos
- start = (11,11)
- start_node = Node(start)
-
- buffer = [start_node]
- nodes = {start_node}
- 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]
-
- while buffer:
- new_buffer = []
- for node in buffer:
- neighbors = [p for p in self.neighbors(*node.pos) if self._active_owned(p, player_id)]
- if node.pos in ignored:
- continue
- for n in neighbors:
- if not n in node.path:
- new_node = Node(n, node.path + [node.pos])
- nodes.add(new_node)
- new_buffer.append(new_node)
-
- buffer = new_buffer
-
- paths_to = {}
-
- for node in nodes:
- if not node.pos in paths_to:
- paths_to[node.pos] = []
- paths_to[node.pos].append(node.path)
- print(paths_to)
-
- pivots = {}
-
- for candidate in paths_to:
- if candidate == start:
- continue
- for p, paths in paths_to.items():
- if not paths or not paths[0] or p in ignored:
- continue
- if all(candidate in path for path in paths):
- if not candidate in pivots:
- pivots[candidate] = []
- pivots[candidate].append(p)
-
- occurrences = Counter(sum(sum(paths_to.values(), []), []))
- while ignored:
- new_ignored = []
- for p in ignored:
- occured_neighbors = [occurrences[n] for n in self.neighbors(*p) if n in occurrences]
- if not occured_neighbors:
- new_ignored.append(p)
- continue
- occurrences[p] = 2 * sum(occured_neighbors) // len(occured_neighbors)
- ignored = new_ignored
-
- print(occurrences)
- return pivots
- def __update_pivot_for(self, player_id):
- # start = self.get_hq(player_id).pos
- start = (11,11)
- orient = 1
- buffer = [(None, start)]
- bounds = []
-
- while buffer:
- new_buffer = []
- for o, p in buffer:
- for n in self.oriented_neighbors(*p, orient):
- if self._active_owned(n, player_id) and not (p, n) in bounds and n != o:
- bounds.append((p, n))
- new_buffer.append((p, n))
- buffer = new_buffer
-
- print(bounds)
-
- parents_number = Counter()
- for parent, child in bounds:
- parents_number[child] += 1
- print(parents_number)
-
- pivots = set()
- for parent, child in bounds:
- if parent == start:
- continue
- if parents_number[child] == 1:
- pivots |= {parent}
-
- return pivots
-
- grid = Grid()
- Grid.owned = 5
- print(grid.print_grid())
- print()
- t0 = time.time()
- a = grid.update_pivot_for(0)
- print(a)
- print(time.time() - t0)
|