Browse Source

resolve discvover and line of sight bugs

olinox14 3 years ago
parent
commit
1c708fca90
1 changed files with 41 additions and 66 deletions
  1. 41 66
      cultist_war/main.py

+ 41 - 66
cultist_war/main.py

@@ -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)