|
|
@@ -12,8 +12,6 @@ import time
|
|
|
# * find a way to change direction without slowing down if possible
|
|
|
# * avoid getting blocked by a side-by-side with an ennemy
|
|
|
# * use a queue to choose the best shoot instead of a strict equality
|
|
|
-# * why do mines explode when turning around?
|
|
|
-# * improve next_pos_proba: eliminate next positions if not passables
|
|
|
|
|
|
debug = True
|
|
|
|
|
|
@@ -279,7 +277,7 @@ class Grid(Base):
|
|
|
for m in self.mines:
|
|
|
base_costs[m.pos] += 1000
|
|
|
for c in self.cannonballs:
|
|
|
- base_costs[c.pos] += (100 + (6 - c.countdown) * 200)
|
|
|
+ base_costs[c.pos] += (200 + (6 - c.countdown) * 200)
|
|
|
|
|
|
for ship in self.ships:
|
|
|
ship._moving_costs = {}
|
|
|
@@ -568,13 +566,12 @@ class Ship(Entity):
|
|
|
MAX_SPEED = 2
|
|
|
SCOPE = 10
|
|
|
|
|
|
- WAIT = 0
|
|
|
SLOW_DOWN = 1
|
|
|
SPEED_UP = 2
|
|
|
TURN_LEFT = 3
|
|
|
TURN_RIGHT = 4
|
|
|
- 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"}
|
|
|
+ MOVES = [None, SPEED_UP, TURN_LEFT, TURN_RIGHT, SLOW_DOWN]
|
|
|
+ COMMANDS = {SLOW_DOWN: "SLOWER", SPEED_UP: "FASTER", TURN_LEFT: "PORT", TURN_RIGHT: "STARBOARD", None: "NONE"}
|
|
|
|
|
|
areas = {}
|
|
|
|
|
|
@@ -652,6 +649,7 @@ class Ship(Entity):
|
|
|
|
|
|
self.next_cell = self.get_next_cell()
|
|
|
self.next_pos = self.get_next_pos()
|
|
|
+ self.next_move = None
|
|
|
self.next_area = Ship.get_area(*self.next_pos, self.orientation)
|
|
|
|
|
|
self.front = Grid.next_cell(*self.prow, self.orientation)
|
|
|
@@ -664,8 +662,6 @@ class Ship(Entity):
|
|
|
|
|
|
self._can_move = {}
|
|
|
|
|
|
- self.mobility_zone = list(set(self.area + self.next_area))
|
|
|
-
|
|
|
if self.traject() != previous_traject:
|
|
|
self.same_traject_since += 1
|
|
|
else:
|
|
|
@@ -803,18 +799,18 @@ class Ship(Entity):
|
|
|
new_pos = self.get_next_cell(new_speed)
|
|
|
return self.get_area(*new_pos, new_orientation)
|
|
|
|
|
|
- def move(self, path):
|
|
|
+ def plan_next_move(self):
|
|
|
|
|
|
- if path:
|
|
|
- planned = self._plan_move(path)
|
|
|
+ if self.path:
|
|
|
+ planned = self._follow_path(self.path)
|
|
|
|
|
|
- if path is None:
|
|
|
+ if self.path is None:
|
|
|
if self.can_move():
|
|
|
available = {}
|
|
|
|
|
|
if self.can_move_fwd():
|
|
|
if self.speed:
|
|
|
- available[Ship.WAIT] = 0
|
|
|
+ available[None] = 0
|
|
|
else:
|
|
|
available[Ship.SPEED_UP] = 0
|
|
|
if self.can_turn_left():
|
|
|
@@ -829,8 +825,9 @@ class Ship(Entity):
|
|
|
log(f"(!) broken: automove ({Ship.COMMANDS[planned]})")
|
|
|
else:
|
|
|
log(f"(!) broken: can not move")
|
|
|
+ self.next_area = self.area
|
|
|
return False
|
|
|
- elif not path:
|
|
|
+ elif not self.path:
|
|
|
return False
|
|
|
|
|
|
next_move = planned
|
|
|
@@ -838,7 +835,7 @@ class Ship(Entity):
|
|
|
|
|
|
for move in available_moves:
|
|
|
new_area = self.area_after_moving(move)
|
|
|
-
|
|
|
+
|
|
|
# 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")
|
|
|
@@ -848,20 +845,25 @@ class Ship(Entity):
|
|
|
else:
|
|
|
log("* No collision-free move was found, go to the initial one")
|
|
|
|
|
|
- if next_move == Ship.SPEED_UP:
|
|
|
+ self.next_move = next_move
|
|
|
+ self.next_area = new_area
|
|
|
+ return True
|
|
|
+
|
|
|
+
|
|
|
+ def move(self):
|
|
|
+ if self.next_move == Ship.SPEED_UP:
|
|
|
self.speed_up()
|
|
|
- elif next_move == Ship.SLOW_DOWN:
|
|
|
+ elif self.next_move == Ship.SLOW_DOWN:
|
|
|
self.slow_down()
|
|
|
- elif next_move == Ship.TURN_LEFT:
|
|
|
+ elif self.next_move == Ship.TURN_LEFT:
|
|
|
self.turn_left()
|
|
|
- elif next_move == Ship.TURN_RIGHT:
|
|
|
+ elif self.next_move == Ship.TURN_RIGHT:
|
|
|
self.turn_right()
|
|
|
else:
|
|
|
return False
|
|
|
-
|
|
|
return True
|
|
|
|
|
|
- def _plan_move(self, path):
|
|
|
+ def _follow_path(self, path):
|
|
|
|
|
|
# flags represent direction changes or end of the path
|
|
|
last_flag = len(path) - 1
|
|
|
@@ -919,15 +921,13 @@ class Ship(Entity):
|
|
|
def fire_at_will(self, *args, **kwargs):
|
|
|
return self._fire_at_will(*args, **kwargs)
|
|
|
|
|
|
- def _fire_at_will(self, target, allies = []):
|
|
|
+ def _fire_at_will(self, target):
|
|
|
if not self.can_fire():
|
|
|
return False
|
|
|
|
|
|
avoid = []
|
|
|
- if not self in allies:
|
|
|
- allies.append(self)
|
|
|
- for ally in allies:
|
|
|
- avoid += ally.mobility_zone
|
|
|
+ for ally in self.allies:
|
|
|
+ avoid += ally.next_area
|
|
|
|
|
|
next_positions = target.guess_next_positions(4)
|
|
|
for t, next_pos in next_positions.items():
|
|
|
@@ -960,6 +960,13 @@ class Ship(Entity):
|
|
|
def can_fire(self):
|
|
|
return self.last_fire is None or (current_turn - self.last_fire) >= 1
|
|
|
|
|
|
+ def mine_maybe(self):
|
|
|
+ if self.can_mine():
|
|
|
+ if not any(Grid.manhattan(self.pos, ally.pos) <= 5 for ally in self.allies):
|
|
|
+ self.mine()
|
|
|
+ return True
|
|
|
+ return False
|
|
|
+
|
|
|
# --- Basic commands
|
|
|
def _act(self, cmd, *args):
|
|
|
self.last_action = cmd
|
|
|
@@ -1063,7 +1070,7 @@ while True:
|
|
|
# log(f"Mines: {grid.mines}")
|
|
|
log(f"Cannonballs: {grid.cannonballs}")
|
|
|
|
|
|
- max_it = 6000 // len(grid.owned_ships)
|
|
|
+ max_it = 12000 // len(grid.owned_ships)
|
|
|
|
|
|
### Acquire
|
|
|
log("# Acquiring")
|
|
|
@@ -1126,6 +1133,8 @@ while True:
|
|
|
else:
|
|
|
break
|
|
|
|
|
|
+ ship.plan_next_move()
|
|
|
+
|
|
|
for ship in grid.owned_ships:
|
|
|
log(f"---- ship {ship.id} ---")
|
|
|
log(f"ship: {ship}")
|
|
|
@@ -1133,6 +1142,7 @@ while True:
|
|
|
log(f"target: {ship.target_ennemy}")
|
|
|
log(f"goto: {ship.goto}")
|
|
|
log(f"path: {ship.path}")
|
|
|
+ log(f"next_move: {Ship.COMMANDS[ship.next_move]}")
|
|
|
|
|
|
### Process
|
|
|
log("# Processing")
|
|
|
@@ -1143,11 +1153,15 @@ while True:
|
|
|
log("No target: wait")
|
|
|
ship.wait()
|
|
|
|
|
|
- if ship.move(ship.path):
|
|
|
+ if ship.move():
|
|
|
continue
|
|
|
|
|
|
# no movement was required, can fire
|
|
|
- if ship.fire_at_will(ship.target_ennemy.target, allies=grid.owned_ships):
|
|
|
+ if ship.fire_at_will(ship.target_ennemy.target):
|
|
|
+ continue
|
|
|
+
|
|
|
+ # or mine
|
|
|
+ if ship.mine_maybe():
|
|
|
continue
|
|
|
|
|
|
log("ERROR: Did not act, wait")
|