Bladeren bron

add the guess_next_pos algo

olinox 6 jaren geleden
bovenliggende
commit
064d84e2b2
1 gewijzigde bestanden met toevoegingen van 100 en 45 verwijderingen
  1. 100 45
      carribean/script.py

+ 100 - 45
carribean/script.py

@@ -193,6 +193,8 @@ class Grid(Base):
                 obj.eval(s.next_pos, s.orientation)
                 s.ennemies.put(obj)
 
+        self.update_moving_costs()
+
 
     def at(self, x, y):
         try:
@@ -217,12 +219,13 @@ class Grid(Base):
         
         for x in range(-1, self.w + 1):
             for y in range(-1, self.h + 1):
-                if x in (0, self.w) or y in (0, self.h):
-                    base_costs[(x, y)] = 15 # borders are a little more expensive
-                elif x in (-1, self.w + 1) or y in (-1, self.h + 1):
-                    base_costs[(x, y)] = 1000 # out of the map
-                else:
-                    base_costs[(x, y)] = 10 # base moving cost
+                base_costs[(x, y)] = 10 # base moving cost
+                
+        for x, y in base_costs:
+            if x in (-1, self.w + 1) or y in (-1, self.h):
+                base_costs[(x, y)] = 1000 # out of the map
+            elif x in (0, self.w - 1) or y in (0, self.h - 1):
+                base_costs[(x, y)] = 15 # borders are a little more expensive     
         
         for m in self.mines:
             for n in self.neighbors(*m.pos):
@@ -233,7 +236,8 @@ class Grid(Base):
             base_costs[c.pos] += (100 + (5 - c.countdown) * 200)
         
         for ship in self.ships:
-            ship._moving_costs = base_costs
+            ship._moving_costs = {}
+            ship._moving_costs.update(base_costs)
             for other in self.ships:
                 if other is ship:
                     continue
@@ -328,6 +332,15 @@ class Grid(Base):
             else:
                 return 1 if y0 % 2 == 0 else 2
 
+    @staticmethod
+    def add_directions(d1, d2):
+        d = d2 + d1
+        if d <= -3:
+            d += 6
+        elif d > 3:
+            d -= 6
+        return d
+    
     @staticmethod
     def diff_directions(d1, d2):
         d = d2 - d1
@@ -526,9 +539,18 @@ class Ship(Entity):
     def state(self):
         return (self.x, self.y, self.orientation, self.speed)
 
+    @classmethod
+    def get_pos_in(cls, current, speed, orientation, in_=1):
+        x, y = current
+        for _ in range(in_):
+            for _ in range(speed):
+                dx, dy = Grid.directions(y)[orientation]
+                x, y = x + dx, y + dy
+        return x, y
+
     @classmethod
     def get_area(cls, x, y, orientation):
-        dx, dy = Grid.directions(y)[((orientation + 3) % 6)]
+        dx, dy = Grid.directions(y)[Grid.add_directions(orientation, 3)]
         stern = (x + dx, y + dy)
         
         dx, dy = Grid.directions(y)[orientation]
@@ -537,12 +559,43 @@ class Ship(Entity):
         return [prow, (x, y), stern]
 
     def get_next_pos(self, in_=1):
-        x, y = self.x, self.y
-        for _ in range(in_):
-            for _ in range(self.speed):
-                dx, dy = Grid.directions(y)[self.orientation]
-                x, y = x + dx, y + dy
-        return x, y
+        return self.get_pos_in(self.pos, self.speed, self.orientation, in_)
+    
+    def guess_next_pos(self):
+        proba = {}
+        
+        # wait (or fire or mine)
+        for c in self.next_area:
+            proba[c] = proba.get(c, 10)
+        
+        # turn left
+        area = self.get_area(*self.pos, Grid.add_directions(self.orientation, 1))
+        for c in area:
+            proba[c] = proba.get(c, 0) + 10
+            
+        # turn right
+        area = self.get_area(*self.pos, Grid.add_directions(self.orientation, -1))
+        for c in area:
+            proba[c] = proba.get(c, 0) + 10
+            
+        # speed up
+        if self.speed < self.MAX_SPEED:
+            area = self.get_area(*self.get_pos_in(self.pos, self.speed + 1, self.orientation), self.orientation)
+            for c in area:
+                proba[c] = proba.get(c, 0) + 10
+        
+        # slow down
+        if self.speed > 0:
+            area = self.get_area(*self.get_pos_in(self.pos, self.speed + 1, self.orientation), self.orientation)
+            for c in area:
+                proba[c] = proba.get(c, 0) + 10
+            
+        for c in proba:
+            proba[c] -= self.moving_cost(*c)
+
+        best = max(proba.items(), key=lambda x: x[1])
+
+        return best[0]
     
     def get_next_cell(self, in_=1):
         x, y = self.x, self.y
@@ -629,43 +682,48 @@ class Ship(Entity):
         if not self.can_fire():
             raise DidNotAct()
         
-        log("** fire at will")
-        
-        next_positions = [target.get_next_pos(i) for i in range(1, 3)]
-        log(f"ennemy next pos: {next_positions}")
-        
         avoid = []
         if not self in allies:
             allies.append(self)
         for ally in allies:
             avoid += ally.mobility_zone
-
-        log(f"avoid: {avoid}")
-
-        for i, p in enumerate(next_positions):
-            turn = i + 1
-            
-            if p in avoid:
-                continue
-            
-            dist_p = Grid.manhattan(self.prow, p)
+        
+        dist = Grid.manhattan(self.prow, target.next_pos)
+        if dist <= 4:
+            # precise algo
+            shoot_at = target.guess_next_pos()
+            log(f"most probable position: {shoot_at}")
+            ship.fire(*shoot_at)
             
-            if dist_p > self.SCOPE:
-                continue
+        elif dist <= self.SCOPE:
+
+            # anticipate            
+            next_positions = [target.get_next_pos(i) for i in range(1, 3)]
+            for i, p in enumerate(next_positions):
+                turn = i + 1
+                
+                if p in avoid:
+                    continue
+                
+                dist_p = Grid.manhattan(self.prow, p)
+                
+                if dist_p > self.SCOPE:
+                    continue
+                
+                if (1 + round(dist_p / 3)) == turn:
+                    log(f"Precision: {p}, {dist_p}, {turn}")
+                    ship.fire(*p)
+                    return
             
-            if (1 + round(dist_p / 3)) == turn:
-                log(f"Precision: {p}, {dist_p}, {turn}")
+            # give a try
+            next_pos = next_positions[0]
+            dist_p = Grid.manhattan(self.prow, next_pos)
+            if dist_p <= self.SCOPE:
                 ship.fire(*p)
-                return
-        
-        next_pos = next_positions[0]
-        dist_p = Grid.manhattan(self.prow, next_pos)
-        if dist_p <= self.SCOPE:
-            ship.fire(*p)
-            return
-        
-        raise DidNotAct()
             
+        else:
+            raise DidNotAct()
+        
     def can_mine(self):
         return self.last_mining is None or (current_turn - self.last_mining) >= 4
         
@@ -781,9 +839,6 @@ while True:
     log(f"Cannonballs: {grid.cannonballs}")
 
 
-    ### Evaluate
-    grid.update_moving_costs()
-    
     ### Acquire
     log("# Acquiring")