瀏覽代碼

various fixes

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

+ 56 - 51
carribean/script.py

@@ -243,8 +243,9 @@ class Grid(Base):
         except KeyError:
             return None
         
-    def borderline(self, x, y):
-        return x == -1 or y == -1 or x == self.w or y == self.h
+    @classmethod
+    def is_border(cls, x, y):
+        return x == -1 or y == -1 or x == cls.w or y == cls.h
         
     def collision_at(self, x, y):
         e = self.at(x, y)
@@ -291,12 +292,10 @@ class Grid(Base):
                     continue
                 for c in self.zone(other.pos, 3):
                     ship._moving_costs[c] += 25
+                    
                 next_positions = other.next_pos_proba()
                 for c, proba in next_positions[1].items():
-                    if proba > 20 and not c in ship.area:
-                        ship._moving_costs[c] += 1000
-                    else:
-                        ship._moving_costs[c] += 100
+                    ship._moving_costs[c] = ship._moving_costs.get(c, 0) + 40 * proba
 
     def shooting_spot(self, ship, target):
         shooting_spots = Queue()
@@ -521,7 +520,7 @@ class Grid(Base):
                     continue
                     
                 area = Ship.get_area(x, y, d)
-                if any(moving_costs.get(c, 1000) >= 1000 for c in area):
+                if any((moving_costs.get(c, 1000) >= 1000 and not Grid.is_border(*c)) for c in area):
                     continue
                     
                 cost = current.cost + moving_cost + diff * 10
@@ -558,21 +557,24 @@ class Entity(Base):
     
     
 class Position(Base):
-    def __init__(self, pos, d, speed):
+    def __init__(self, pos, d, speed, weight=10):
         self.pos = pos
         self.d = d
         self.speed = speed
+        self.weight = weight
+        self.area = Ship.get_area(*self.pos, self.d)
     
 class Ship(Entity):
     MAX_SPEED = 2
     SCOPE = 10
     
+    WAIT = 0
     SLOW_DOWN = 1
     SPEED_UP = 2
     TURN_LEFT = 3
     TURN_RIGHT = 4
-    MOVES = [SPEED_UP, TURN_LEFT, TURN_RIGHT, SLOW_DOWN]
-    COMMANDS = {SLOW_DOWN: "SLOWER", SPEED_UP: "FASTER", TURN_LEFT: "PORT", TURN_RIGHT: "STARBOARD", None: "NONE"}
+    MOVES = [WAIT, SPEED_UP, TURN_LEFT, TURN_RIGHT, SLOW_DOWN]
+    COMMANDS = {SLOW_DOWN: "SLOWER", SPEED_UP: "FASTER", TURN_LEFT: "PORT", TURN_RIGHT: "STARBOARD", WAIT: "WAIT", None: "NONE"}
     
     areas = {}
     
@@ -593,7 +595,6 @@ class Ship(Entity):
         self.last_action = ""
         self.allies = []
         self._moving_costs = {}
-        self.cached_next_pos_proba = {}
         
         self.objectives = ObjectivesQueue()
         self.ennemies = ObjectivesQueue()
@@ -610,6 +611,10 @@ class Ship(Entity):
     def __repr__(self):
         return f"<Ship {self.id}: pos=({self.x}, {self.y}), orientation={self.orientation}, speed={self.speed}, blocked={self.blocked_since}, last_fire={self.last_fire}, next_pos={self.next_pos}, area={self.area}>"
 
+    @classmethod
+    def abs_area(cls, x, y, d):
+        return [Grid.next_cell(x, y, d), (x, y), Grid.next_cell(x, y, Grid.add_directions(d, 3))]
+
     @classmethod
     def cache_area(cls, x, y):
         for d in range(3):
@@ -622,8 +627,7 @@ class Ship(Entity):
         try:
             return list(Ship.areas[(x, y, d)])
         except KeyError:
-            log(f"Error: area key missing {(x, y, d)}")
-            return []
+            return cls.abs_area(x, y, d)
         
     def update(self, x, y, *args):
         previous_state = self.state()
@@ -641,7 +645,7 @@ class Ship(Entity):
         
         self.goto = None
         self.path = []
-        self.next_positions = {}
+        self.cached_next_pos_proba = {}
         
         self.area = Ship.get_area(self.x, self.y, self.orientation)
         self.prow, _, self.stern = self.area
@@ -702,26 +706,34 @@ class Ship(Entity):
                 # next pos with inertia
                 inertia = Grid.next_cell(*pos, d, repeat=speed)
                 
-                # wait (doubled)
-                positions[i + 1].append(Position(inertia, d, speed))
-                positions[i + 1].append(Position(inertia, d, speed))
-                
-                # fire or mine
-                positions[i + 1].append(Position(inertia, d, speed))
+                # wait, fire or mine
+                p = Position(inertia, d, speed, 30)
+                if self.moving_cost(*p.pos) >= 1000:
+                    p.weight = 10
+                positions[i + 1].append(p)
                 
                 # turn left
-                positions[i + 1].append(Position(inertia, Grid.add_directions(d, 1), speed))
+                p = Position(inertia, Grid.add_directions(d, 1), speed)
+                if not self.moving_cost(*p.pos) >= 1000:
+                    positions[i + 1].append(p)
                     
                 # turn right
-                positions[i + 1].append(Position(inertia, Grid.add_directions(d, -1), speed))
+                p = Position(inertia, Grid.add_directions(d, -1), speed)
+                if not self.moving_cost(*p.pos) >= 1000:
+                    positions[i + 1].append(p)
                     
                 # speed up
                 if speed < self.MAX_SPEED:
-                    positions[i + 1].append(Position(Grid.next_cell(*pos, d, repeat=speed + 1), d, speed + 1))
+                    p = Position(Grid.next_cell(*pos, d, repeat=speed + 1), d, speed + 1)
+                    if not self.moving_cost(*p.pos) >= 1000:
+                        positions[i + 1].append(p)
                 
                 # slow down
                 if speed > 1:
-                    positions[i + 1].append(Position(Grid.next_cell(*pos, d, repeat=speed - 1), d, speed - 1))
+                    p = Position(Grid.next_cell(*pos, d, repeat=speed - 1), d, speed - 1)
+                    if not self.moving_cost(*p.pos) >= 1000:
+                        positions[i + 1].append(p)
+        
         
                 # we voluntary ignore the case where a ship at speed 1 would slow down, 
                 # as it is not expected to be a standard behaviour for a ship
@@ -731,19 +743,14 @@ class Ship(Entity):
         for i, plst in positions.items():
             proba[i] = {}
             for p in plst:
-                for c in Ship.get_area(*p.pos, p.d):
-                    if self.moving_cost(*c) >= 1000:
-                        continue
-                    proba[i][c] = proba[i].get(c, 0) + 10
-                    
-        # involve the moving cost
-        for i in proba:
-            for c in proba[i]:
-                proba[i][c] -= (self.moving_cost(*c) // 2)
-        
-            # if ship is blocked, current area is more accurate
-            for c in self.area:
-                proba[i][c] = proba[i].get(c, 0) + 40 * self.blocked_since
+                for c in p.area:
+                    proba[i][c] = proba[i].get(c, 0) + p.weight
+             
+        # if ship is blocked, current area is more accurate       
+        if self.blocked_since:
+            for i in proba:
+                for c in self.area:
+                    proba[i][c] = proba[i].get(c, 0) + 40 * self.blocked_since
                 
         self.cached_next_pos_proba = proba
                 
@@ -766,12 +773,14 @@ class Ship(Entity):
         return self._moving_costs.get((x, y), 1000)
     
     def can_turn_left(self):
-        return (self._can_move[self.left] or grid.borderline(*self.left)) \
-            and (self._can_move[self.back_right] or grid.borderline(*self.right))
+        return (self._can_move[self.left] or grid.is_border(*self.left)) \
+            and (self._can_move[self.right] or grid.is_border(*self.right)) \
+            and (self._can_move[self.back_right] or grid.is_border(*self.back_right))
     
     def can_turn_right(self):
-        return (self._can_move[self.right] or grid.borderline(*self.right)) \
-               and (self._can_move[self.back_left] or grid.borderline(*self.back_left))
+        return (self._can_move[self.right] or grid.is_border(*self.right)) \
+               and (self._can_move[self.left] or grid.is_border(*self.left)) \
+               and (self._can_move[self.back_left] or grid.is_border(*self.back_left))
     
     def can_move_fwd(self):
         return self._can_move[self.front]
@@ -795,7 +804,6 @@ class Ship(Entity):
         return self.get_area(*new_pos, new_orientation)
     
     def move(self, path):
-        broken = False
         
         if path:
             planned = self._plan_move(path)
@@ -804,9 +812,11 @@ class Ship(Entity):
             if self.can_move():
                 available = {}
                 
-                broken = True
-                if not self.speed and self.can_move_fwd():
-                    available[Ship.SPEED_UP] = 0
+                if self.can_move_fwd():
+                    if self.speed:
+                        available[Ship.WAIT] = 0
+                    else:
+                        available[Ship.SPEED_UP] = 0
                 if self.can_turn_left():
                     available[Ship.TURN_LEFT] = 0
                 if self.can_turn_right():
@@ -836,11 +846,6 @@ class Ship(Entity):
                 next_move = move
                 break
         else:
-#             if broken:
-#                 log("* No collision-free move was found, try automove")
-#                 self.auto_move(*self.goto)
-#                 return True
-#             else:
             log("* No collision-free move was found, go to the initial one")
         
         if next_move == Ship.SPEED_UP:
@@ -906,7 +911,7 @@ class Ship(Entity):
                 elif diff < 0:
                     return Ship.TURN_RIGHT
             
-            elif next_flag > 3:
+            elif next_flag >= 4:
                 return Ship.SPEED_UP
         
         return None