瀏覽代碼

add the 'avoid collision' algo

olinox 6 年之前
父節點
當前提交
3c659b91c1
共有 1 個文件被更改,包括 58 次插入42 次删除
  1. 58 42
      carribean/script.py

+ 58 - 42
carribean/script.py

@@ -11,9 +11,9 @@ import sys
 # * if an enemy is near a mine, shoot the mine instead of the ship
 # * find a way to change direction without slowing down if possible
 # * avoid getting blocked by a side-by-side with an ennemy
-# * priorize targetting blocked ennemies
 # * improve the 'avoid' part of the 'fire_at_will' method
 # * use a queue to choose the best shoot instead of a strict equality
+# * why do mines explode when turning around?
 
 debug = True
 
@@ -23,7 +23,7 @@ def log(*msg):
 
 current_turn = 0
 
-class DidNotAct(Exception):
+class CollisionAlert(Exception):
     pass
 
 class Queue():
@@ -232,6 +232,7 @@ class Grid(Base):
 
     def update_moving_costs(self):
         base_costs = {}
+        self.collisions = []
         
         for x in range(-1, self.w + 1):
             for y in range(-1, self.h + 1):
@@ -276,7 +277,7 @@ class Grid(Base):
         for x, y in self.zone(target_pos, 10):
             if ship.moving_cost(x, y) > 100:
                 continue
-            if self.manhattan((x, y), target_pos) <= 1:
+            if self.manhattan((x, y), target_pos) <= 2:
                 continue
             
             interest = 0 # the lower the better
@@ -284,17 +285,20 @@ class Grid(Base):
             interest += ship.moving_cost(x, y)
             
             # avoid cells too close from borders
-            if not (3 <= x <= (self.w - 3) and 3 <= y < (self.h - 3)):
-                interest += 30
+            if not 3 < x < (self.w - 3):
+                interest += 50
+            if not 3 <= y < (self.h - 3):
+                interest += 50
             
-            diff = Grid.direction_to(*ship.prow, x, y)
-            interest += 10 * abs(diff)
+            diff = abs(Grid.direction_to(*ship.prow, x, y))
+            if diff > 1:
+                interest += 15 * abs(diff)
             
             # priorize spots at distance 5 from active ship
             interest += (10 * abs(5 - self.manhattan((x, y), ship.pos)))
             
-            shooting_spots.put((x, y), interest)
             
+            shooting_spots.put((x, y), interest)
         return shooting_spots.get()
     
     # geometrical algorithms
@@ -520,6 +524,7 @@ class Ship(Entity):
     TURN_LEFT = 3
     TURN_RIGHT = 4
     MOVES = [SLOW_DOWN, SPEED_UP, TURN_LEFT, TURN_RIGHT]
+    COMMANDS = {SLOW_DOWN: "SLOWER", SPEED_UP: "FASTER", TURN_LEFT: "PORT", TURN_RIGHT: "STARBOARD"}
     
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -703,7 +708,7 @@ class Ship(Entity):
     
     def can_move(self):
         return self.can_move_fwd() or self.can_turn_left() or self.can_turn_left()
-        
+    
     def move(self, path):
             
         if path is None:
@@ -715,32 +720,43 @@ class Ship(Entity):
                 return False
         elif not path:
             return False
-            
+        
         planned = self._plan_move(path)
+        next_move = planned
+        available_moves = [next_move] + [m for m in Ship.MOVES if m != planned]
         
-        if planned is None:
-            future_pos = self.get_next_cell()
-            future_d = self.orientation
-        else:
+        for move in available_moves:
+            
             new_speed = self.speed
-            if planned == Ship.SPEED_UP:
+            new_orientation = self.orientation
+            if move == Ship.SPEED_UP:
                 new_speed += 1
-            elif planned == Ship.SLOW_DOWN:
+            elif move == Ship.SLOW_DOWN:
                 new_speed -= 1
-            future_pos = path[new_speed]
-            future_d = path[new_speed].orientation
-        
-        future_area = self.get_area(*future_pos, future_d)
-        if any(self.moving_cost(*c) >= 1000 for c in future_area):
-            log("/!\ Danger: planned move would lead to collision")
-
-        if planned == Ship.SPEED_UP:
+            elif move == Ship.TURN_LEFT:
+                new_orientation = Grid.add_directions(self.orientation, 1)
+            elif move == Ship.TURN_RIGHT:
+                new_orientation = Grid.add_directions(self.orientation, -1)
+            
+            new_pos = self.get_next_cell(new_speed)
+            new_area = self.get_area(*new_pos, new_orientation)
+    
+            # special: extra-grid cells are not consider as collisions since a part of the ship can go there
+            if any((self.moving_cost(*c) >= 1000 and c in grid) for c in new_area):
+                log(f"/!\ Danger: planned move <{Ship.COMMANDS[move]}> would lead to collision")
+            else:
+                next_move = move
+                break
+        else:
+            log("* No collision-free move was found, go to the initial one")
+            
+        if next_move == Ship.SPEED_UP:
             self.speed_up()
-        elif planned == Ship.SLOW_DOWN:
+        elif next_move == Ship.SLOW_DOWN:
             self.slow_down()
-        elif planned == Ship.TURN_LEFT:
+        elif next_move == Ship.TURN_LEFT:
             self.turn_left()
-        elif planned == Ship.TURN_RIGHT:
+        elif next_move == Ship.TURN_RIGHT:
             self.turn_right()
         else:
             return False
@@ -754,9 +770,13 @@ class Ship(Entity):
         next_flag = next((i for i, n in enumerate(path) if n.orientation != self.orientation), last_flag)
         afternext_flag = next((i for i, n in enumerate(path[next_flag:]) if n.orientation != path[next_flag].orientation), last_flag)
         
+        
+        
         if not self.speed:
             diff = Grid.diff_directions(self.orientation, path[0].orientation)
             
+            log(self.id, self.speed, self.can_move_fwd(), self.can_turn_left(), self.can_turn_right())
+            
             if diff > 0 and self.last_action == "STARBOARD" or diff < 0 and self.last_action == "PORT":
                 # special: avoid the starting hesitation
                 return Ship.SPEED_UP
@@ -769,10 +789,10 @@ class Ship(Entity):
                 elif diff < 0:
                     if self.can_turn_right():
                         return Ship.TURN_RIGHT
-            else:
-                # start straight
-                if self.can_move_fwd():
-                    return Ship.SPEED_UP
+                    
+            # start straight
+            if self.can_move_fwd():
+                return Ship.SPEED_UP
         
         elif self.speed == self.MAX_SPEED:
             
@@ -803,15 +823,11 @@ class Ship(Entity):
         return None
            
     def fire_at_will(self, *args, **kwargs):
-        try:
-            self._fire_at_will(*args, **kwargs)
-            return True
-        except DidNotAct:
-            return False
+        return self._fire_at_will(*args, **kwargs)
            
     def _fire_at_will(self, target, allies = []):
         if not self.can_fire():
-            raise DidNotAct()
+            return False
         
         avoid = []
         if not self in allies:
@@ -832,7 +848,7 @@ class Ship(Entity):
             if dt == t:
                 log(f"[x] precise shoot: dt={dt}, pos={next_pos}")
                 ship.fire(*next_pos)
-                return
+                return True
             
         # give a try
         next_pos = next_positions[2]
@@ -840,9 +856,9 @@ class Ship(Entity):
             dist_p = Grid.manhattan(self.prow, next_pos)
             if dist_p <= self.SCOPE:
                 ship.fire(*next_pos)
-                return
+                return True
             
-        raise DidNotAct()
+        return False
         
     def can_mine(self):
         return self.last_mining is None or (current_turn - self.last_mining) >= 4
@@ -949,9 +965,8 @@ while True:
     log(f"Barrels: {grid.barrels}")
 #     log(f"Mines: {grid.mines}")
     log(f"Cannonballs: {grid.cannonballs}")
-
     
-    max_it = 9000 // len(grid.owned_ships)
+    max_it = 6000 // len(grid.owned_ships)
 
     ### Acquire
     log("# Acquiring")
@@ -1016,6 +1031,7 @@ while True:
         log(f"ship: {ship}")
         log(f"obj: {ship.objective}; next: {ship.objectives_next}")
         log(f"target: {ship.target_ennemy}")
+        log(f"goto: {ship.goto}")
         log(f"path: {ship.path}")
         
     ### Process