Explorar el Código

add the blocks concept

olinox14 hace 3 años
padre
commit
0bc1558cfc
Se han modificado 1 ficheros con 91 adiciones y 14 borrados
  1. 91 14
      fall2022/fall2022.py

+ 91 - 14
fall2022/fall2022.py

@@ -7,7 +7,6 @@ debug = True
 t0 = time.time()
 
 
-# Debugger : il y a des mouvements qui ne se font pas, faut tout vérifier
 # Faire des zones à l'intérieur des contigs, pour attirer le mouvement vers les zones à coloniser
 # Limiter les constructions agressives en fonction de ces zones
 # penser les recycleurs comme des obstacles!
@@ -17,7 +16,6 @@ t0 = time.time()
 # si la tension autour d'une case est trop forte et que cette case est un "noeud" question passage,
 #     ne pas bouger et défendre!
 
-
 def log(*msg):
     if debug:
         print("{} - ".format(str(time.time() - t0)[1:5]), *msg, file=sys.stderr, flush=True)
@@ -120,7 +118,7 @@ class Cell(BaseClass):
 
     @property
     def lifetime(self):
-        return 10000 if not self.in_range_of_recycler else self.amount
+        return 10000000 if not self.in_range_of_recycler else self.amount
 
     @property
     def unmovable_next_round(self):
@@ -190,6 +188,14 @@ class Recycler(BaseClass):
                f"{self.immediately_available_amount}, {self.total_available_amount}, {self.lifetime()}>"
 
 
+class Block(BaseClass):
+    def __init__(self, id_, start):
+        self.id = id_
+        self.start = start
+        self.area = [start]
+        self.owner = Player.NONE
+
+
 class Contig(BaseClass):
     UNKNOWN = 'U'
     OWNED = 'O'
@@ -197,11 +203,13 @@ class Contig(BaseClass):
     CONFLICTUAL = 'C'
     NOT_OWNED = 'N'
 
-    def __init__(self, start):
+    def __init__(self, id_, start):
+        self.id = id_
         self.start = start
         self.area = [start]
         self.status = Contig.UNKNOWN
         self.has_robots = False
+        self.blocks = []
 
     def __repr__(self):
         return f"<Contig(start: {self.start}, size: {len(self.area)}, status: {self.status}, robots: {self.has_robots})>"
@@ -221,10 +229,11 @@ class MoveOrder(BaseClass):
 
 
 class MoveOrderCandidate(BaseClass):
-    def __init__(self, order, unit, destination):
+    def __init__(self, order, unit, destination, next_pos=None):
         self.order = order
         self.unit = unit
         self.destination = destination
+        self.next_pos = next_pos
 
 
 class Action(BaseClass):
@@ -295,6 +304,7 @@ class Grid(BaseClass):
         self._neighbors_cache = {}
         self._distance_cache = {}
         self.index_contigs = {}
+        self.index_blocks = {}
         self.index_tensions = {}
         self.index_threats = {}
         self.index_nearest_enemy = {}
@@ -322,8 +332,8 @@ class Grid(BaseClass):
         return dist
 
     def neighbors(self, x, y, diags=False):
-        # if (x, y, diags) in self._neighbors_cache:
-        #     return self._neighbors_cache[(x, y, diags)]
+        if (x, y, diags) in self._neighbors_cache:
+            return self._neighbors_cache[(x, y, diags)]
 
         n = [(x, y - 1), (x - 1, y), (x + 1, y), (x, y + 1)]
         if diags:
@@ -351,6 +361,8 @@ class Grid(BaseClass):
         self.me.matter = my_matter
         self.opponent.matter = opp_matter
 
+        self.path_cache = {}
+
         for y in range(self.height):
             for x in range(self.width):
                 scrap_amount, owner, units, recycler, can_build, can_spawn, in_range_of_recycler = [int(k) for k in
@@ -382,6 +394,7 @@ class Grid(BaseClass):
 
         self.update_possessions()
         self.update_contigs()
+        self.update_blocks()
         self.update_tension_map()
         self.update_threat_map()
         self.update_nearest_enemy()
@@ -428,12 +441,14 @@ class Grid(BaseClass):
         self.index_contigs = {}
 
         seen = []
+        id_ = 0
         # build contigs
         for c in self.cells.values():
             if c.pos in seen or c.is_grass:
                 continue
 
-            contig = Contig(c.pos)
+            id_ += 1
+            contig = Contig(id_, c.pos)
 
             candidates = self.neighbors(*c.pos)
 
@@ -477,6 +492,35 @@ class Grid(BaseClass):
             else:
                 contig.status = Contig.NOT_OWNED
 
+    def update_blocks(self):
+        id_ = 0
+
+        for contig in self.contigs:
+            seen = []
+
+            for pos in contig.area:
+                if pos in seen:
+                    continue
+
+                buffer = {pos}
+                id_ += 1
+                block = Block(id_, pos)
+                block.owner = self.cells[pos].owner
+                seen.append(pos)
+
+                while buffer:
+                    p = buffer.pop()
+                    for candidate in self.neighbors(*p):
+                        if not candidate in block.area and self.cells[candidate].owner == block.owner:
+                            buffer.add(candidate)
+                            block.area.append(candidate)
+                            seen.append(candidate)
+
+                contig.blocks.append(block)
+
+                for p in block.area:
+                    self.index_blocks[p] = block
+
     def update_tension_map(self):
         self.index_tensions = {}
 
@@ -525,8 +569,11 @@ class Grid(BaseClass):
                     self.index_nearest_enemy[c.pos] = nearest[1]
 
     def path(self, start, target):
+        if (start, target) in self.path_cache:
+            return self.path_cache[(start, target)]
+
         nodes = Queue()
-        its, break_on = 0, 500
+        its, break_on = 0, 150
 
         origin = PathNode(*start)
         nodes.put(0, origin)
@@ -757,9 +804,9 @@ class Grid(BaseClass):
         k_position_distance = 3000
         k_position_opponents = -5000
         k_position_destroy = -3000
-        k_dist_to_enemy = 1000
-        k_colonize = -5000
-        k_consolidate = -2000
+        k_dist_to_enemy = 2000
+        k_colonize = -100 * self.width
+        k_consolidate = -50 * self.width
         k_expand = -600
         k_threat = -1500
         ki = 0  # little hack to avoid the while in queue.put
@@ -817,12 +864,33 @@ class Grid(BaseClass):
                         continue
                     units.append(unit)
 
+            # limit pathfinding to the priority orders
+            pathfinding_limit = 4
+            pathfinding_dist_limit = 5
+
             q = Queue()
             for unit in units:
+                if not unit.initial_amount:
+                    continue
+
+                pathfinding_it = 0
+
                 for order in orders:
                     destination = order.pos
+
+                    next_pos = None
                     dist = self.manhattan(unit.pos, destination)
 
+                    if dist == 1:
+                        next_pos = order.pos
+
+                    elif pathfinding_it < pathfinding_limit and dist <= pathfinding_dist_limit:
+                        pathfinding_it += 1
+                        path = self.path(unit.pos, order.pos)
+                        if path is not None:
+                            dist = len(path)
+                            next_pos = path[0]
+
                     priority = order.priority
                     priority += k_position_distance * dist
 
@@ -837,7 +905,7 @@ class Grid(BaseClass):
                                 or self.me.side == Player.SIDE_EAST and order.pos[0] == unit.pos[0]:
                             priority += k_consolidate
 
-                    candidate = MoveOrderCandidate(order, unit, destination)
+                    candidate = MoveOrderCandidate(order, unit, destination, next_pos)
 
                     q.put(priority, candidate)
 
@@ -914,6 +982,15 @@ class Grid(BaseClass):
 
         print(";".join([a.do() for a in actions]))
 
+    @staticmethod
+    def debug_print_block(cell):
+        if cell.pos in grid.index_contigs and grid.index_contigs[cell.pos]:
+            contig_id = f"{grid.index_contigs[cell.pos].id:02d}"
+            block_id = f"{grid.index_blocks[cell.pos].id:02d}" if contig_id != 'xx' else 'xx'
+            return f"{contig_id}.{block_id}"
+        else:
+            return 'xx.xx'
+
 
 grid = Grid.create()
 
@@ -922,6 +999,6 @@ while True:
     log(f"round {grid.round}")
     # for contig in grid.contigs:
     #     log(contig)
-    # grid.print(lambda x: f"{grid.threat(x):02d}")
+    grid.print(grid.debug_print_block)
 
     grid.act()