|
|
@@ -39,17 +39,6 @@ class PathNode(tuple):
|
|
|
return f"<{self[0]}, {self[1]}, c:{self.cost}>"
|
|
|
|
|
|
|
|
|
-class DiscoverNode(tuple):
|
|
|
- def __new__(cls, x, y, ancestors=None):
|
|
|
- n = tuple.__new__(cls, (x, y))
|
|
|
- n.ancestors = ancestors if ancestors is not None else []
|
|
|
- n.cost = 0
|
|
|
- return n
|
|
|
-
|
|
|
- def __repr__(self):
|
|
|
- return f"<{self[0]}, {self[1]}, c:{self.cost}>"
|
|
|
-
|
|
|
-
|
|
|
class Queue(BaseClass):
|
|
|
def __init__(self):
|
|
|
self.items = []
|
|
|
@@ -196,7 +185,7 @@ class Grid(BaseClass):
|
|
|
|
|
|
for x, y in self.cells:
|
|
|
self._neighbors[(x, y)] = [(xn, yn) for xn, yn in [(x, y - 1), (x - 1, y), (x + 1, y), (x, y + 1)] if
|
|
|
- 0 <= xn < self.width and 0 <= yn < self.height]
|
|
|
+ 0 <= xn < self.width and 0 <= yn < self.height]
|
|
|
|
|
|
def reinit_round(self):
|
|
|
self.units = {}
|
|
|
@@ -293,27 +282,26 @@ class Grid(BaseClass):
|
|
|
k0_position = 50
|
|
|
k_position_distance = 10
|
|
|
k_position_heat = -5
|
|
|
+ k_position_danger = 5
|
|
|
|
|
|
cult_leader = self.cult_leader()
|
|
|
|
|
|
# Conversion des neutres
|
|
|
if cult_leader:
|
|
|
- paths = self.discover(
|
|
|
+ results = self.discover(
|
|
|
cult_leader.pos,
|
|
|
key=(lambda pos: pos in self.index and self.index[pos].neutral),
|
|
|
limit=5
|
|
|
)
|
|
|
- for path in paths:
|
|
|
- log(path)
|
|
|
|
|
|
- for path in paths:
|
|
|
- target = self.index[path[-1]]
|
|
|
+ for path, target_pos in results:
|
|
|
+ target = self.index[target_pos]
|
|
|
|
|
|
priority = 0
|
|
|
priority += k_convert_neutrals * len(path)
|
|
|
priority += k_convert_danger * sum([self.threat[pos] for pos in path])
|
|
|
|
|
|
- if target in self.neighbors(*cult_leader.pos):
|
|
|
+ if target_pos in self.neighbors(*cult_leader.pos):
|
|
|
action = ActionConvert(cult_leader, target)
|
|
|
else:
|
|
|
action = ActionMove(cult_leader, path[0], f'go convert {target.id}')
|
|
|
@@ -336,23 +324,20 @@ class Grid(BaseClass):
|
|
|
# on garde les trois points les plus chauds
|
|
|
hot_spots = sorted(self.heat_map.items(), key=lambda p: p[1], reverse=True)[:3]
|
|
|
|
|
|
- for pos, heat in hot_spots:
|
|
|
- action = ActionMove(a, pos)
|
|
|
+ results = self.discover(a.pos, key=lambda x: x in [s[0] for s in hot_spots])
|
|
|
|
|
|
- path = self.path(a.pos, pos)
|
|
|
+ for path, target_pos in results:
|
|
|
+ if not path:
|
|
|
+ break
|
|
|
|
|
|
- safe_path = []
|
|
|
- for step in path:
|
|
|
- if self.threat[step] > 1:
|
|
|
- break
|
|
|
- safe_path.append(step)
|
|
|
-
|
|
|
- if not safe_path:
|
|
|
- continue
|
|
|
+ heat = self.heat_map[target_pos]
|
|
|
|
|
|
priority = k0_position
|
|
|
priority += k_position_heat * heat
|
|
|
priority += k_position_distance * len(path)
|
|
|
+ priority += k_position_danger * sum(self.threat[p] for p in path)
|
|
|
+
|
|
|
+ action = ActionMove(a, path[0], f'pos on {path[0]}')
|
|
|
|
|
|
actions.put(priority, action)
|
|
|
|
|
|
@@ -376,7 +361,7 @@ class Grid(BaseClass):
|
|
|
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())
|
|
|
+ return self.in_grid(pos) and pos not in self.obstacles and pos not in self.index
|
|
|
|
|
|
def can_move_on(self, pos):
|
|
|
return self.in_grid(pos) and pos not in self.obstacles and pos not in self.index
|
|
|
@@ -451,15 +436,15 @@ class Grid(BaseClass):
|
|
|
return result
|
|
|
|
|
|
def line_of_sight(self, from_, to_):
|
|
|
- line = self.line(from_, to_)
|
|
|
- return line if all(self.can_see_trough(c) for c in line) else []
|
|
|
+ line = self.line(from_, to_)[1:]
|
|
|
+ return line if all(self.can_see_trough(c) for c in line[:-1]) else []
|
|
|
|
|
|
def shooting_distance(self, from_, to_):
|
|
|
return len(self.line_of_sight(from_, to_))
|
|
|
|
|
|
def path(self, start, target):
|
|
|
nodes = Queue()
|
|
|
- its, break_on = 0, 300
|
|
|
+ its, break_on = 0, 400
|
|
|
|
|
|
origin = PathNode(*start)
|
|
|
nodes.put(0, origin)
|
|
|
@@ -503,55 +488,45 @@ class Grid(BaseClass):
|
|
|
|
|
|
def discover(self, start, key, limit=5):
|
|
|
paths = []
|
|
|
- found = []
|
|
|
|
|
|
- nodes = Queue()
|
|
|
+ nodes = []
|
|
|
its, break_on = 0, 2000
|
|
|
+ origin = PathNode(*start)
|
|
|
|
|
|
- origin = DiscoverNode(*start)
|
|
|
- nodes.put(0, origin)
|
|
|
+ nodes.append(origin)
|
|
|
|
|
|
while nodes:
|
|
|
- current = nodes.get()
|
|
|
-
|
|
|
- if current not in found and current != start and key(tuple(current)):
|
|
|
- path = []
|
|
|
- previous = current
|
|
|
- while previous.ancestors:
|
|
|
- if previous != start:
|
|
|
- path.insert(0, previous)
|
|
|
- previous = previous.ancestors[-1]
|
|
|
- found.append(path[-1])
|
|
|
- paths.append(path)
|
|
|
-
|
|
|
- if len(paths) >= limit:
|
|
|
- return paths
|
|
|
+ current = nodes.pop(0) # l'ordre est important, pour que les premiers indexés soient les premiers analysés
|
|
|
|
|
|
neighbors = self.neighbors(*current)
|
|
|
|
|
|
- for x, y in neighbors:
|
|
|
+ for pos in neighbors:
|
|
|
its += 1
|
|
|
if its > break_on:
|
|
|
log("<!> discovering ended earlier than expected")
|
|
|
return paths
|
|
|
|
|
|
- if (x, y) in current.ancestors:
|
|
|
+ if key(pos):
|
|
|
+ path = []
|
|
|
+ previous = current
|
|
|
+ while previous:
|
|
|
+ if previous != start:
|
|
|
+ path.insert(0, previous)
|
|
|
+ previous = previous.parent
|
|
|
+ paths.append((path, pos))
|
|
|
+
|
|
|
+ if len(paths) >= limit:
|
|
|
+ return paths
|
|
|
continue
|
|
|
|
|
|
- if not self.can_discover((x, y)):
|
|
|
+ if pos == current.parent:
|
|
|
continue
|
|
|
|
|
|
- moving_cost = self.moving_cost((x, y))
|
|
|
-
|
|
|
- cost = current.cost + moving_cost
|
|
|
- priority = cost + Grid.manhattan((x, y), start)
|
|
|
-
|
|
|
- ancestors = current.ancestors + [current]
|
|
|
-
|
|
|
- node = DiscoverNode(x, y, ancestors)
|
|
|
- node.cost = cost
|
|
|
- nodes.put(priority, node)
|
|
|
+ if not self.can_move_on(pos):
|
|
|
+ continue
|
|
|
|
|
|
+ node = PathNode(*pos, current)
|
|
|
+ nodes.append(node)
|
|
|
return paths
|
|
|
|
|
|
def _repr_cell(self, pos):
|
|
|
@@ -592,8 +567,8 @@ while 1:
|
|
|
|
|
|
actions = GRID.list_actions()
|
|
|
|
|
|
- for action in actions.items:
|
|
|
- log(f"* {action}")
|
|
|
+ # for action in actions.items:
|
|
|
+ # log(f"* {action}")
|
|
|
|
|
|
# print("\n" + GRID.graph(), file=sys.stderr)
|
|
|
|