Try to avoid mines

This commit is contained in:
Gabriel Augendre 2017-08-28 16:41:16 +02:00
parent d7fb6f278a
commit 47fb9df56c
No known key found for this signature in database
GPG key ID: F360212F958357D4

View file

@ -1,19 +1,24 @@
import math import math
import random import random
from enum import Enum
from typing import List, Union, Sequence, TypeVar, Optional, Dict
import sys import sys
from enum import Enum, IntEnum
BARREL = 'BARREL' from typing import List, Sequence, Optional, Dict
SHIP = 'SHIP'
MINE = 'MINE'
CANNONBALL = 'CANNONBALL'
DEFAULT_SHOOT_WAIT = 2 DEFAULT_SHOOT_WAIT = 2
DEFAULT_MINE_WAIT = 4 DEFAULT_MINE_WAIT = 4
class EntityType(Enum):
BARREL = 'BARREL'
SHIP = 'SHIP'
MINE = 'MINE'
CANNONBALL = 'CANNONBALL'
class Orientation(IntEnum):
RIGHT, TOP_RIGHT, TOP_LEFT, LEFT, BOTTOM_LEFT, BOTTOM_RIGHT = range(6)
class Action(Enum): class Action(Enum):
MINE = 'MINE' MINE = 'MINE'
MOVE = 'MOVE' MOVE = 'MOVE'
@ -63,6 +68,8 @@ class GameMap:
def add_my_ship(self, ship: 'Ship'): def add_my_ship(self, ship: 'Ship'):
my_ship = self.my_ships.get(ship.id, None) my_ship = self.my_ships.get(ship.id, None)
if my_ship: if my_ship:
my_ship.x = ship.x
my_ship.y = ship.y
my_ship.orientation = ship.orientation my_ship.orientation = ship.orientation
my_ship.speed = ship.speed my_ship.speed = ship.speed
my_ship.stock = ship.stock my_ship.stock = ship.stock
@ -85,6 +92,9 @@ class GameMap:
def _add_to_map(self, entity: 'Entity'): def _add_to_map(self, entity: 'Entity'):
self.map[entity.coord] = entity self.map[entity.coord] = entity
def get_at(self, tile: 'Tile'):
return self.map[tile.coord]
class Tile: class Tile:
def __init__(self, x: int, y: int): def __init__(self, x: int, y: int):
@ -95,6 +105,40 @@ class Tile:
def coord(self): def coord(self):
return '{};{}'.format(self.x, self.y) return '{};{}'.format(self.x, self.y)
def top_left(self):
y = self.y - 1
x = self.x
if self.y % 2 == 0:
x -= 1
return Tile(x, y)
def top_right(self):
y = self.y - 1
x = self.x
if self.y % 2 != 0:
x += 1
return Tile(x, y)
def left(self):
return Tile(self.x - 1, self.y)
def right(self):
return Tile(self.x + 1, self.y)
def bottom_left(self):
y = self.y + 1
x = self.x
if self.y % 2 == 0:
x -= 1
return Tile(x, y)
def bottom_right(self):
y = self.y + 1
x = self.x
if self.y % 2 != 0:
x += 1
return Tile(x, y)
def __repr__(self): def __repr__(self):
return 'Tile(x={}, y={})'.format(self.x, self.y) return 'Tile(x={}, y={})'.format(self.x, self.y)
@ -145,46 +189,97 @@ class Ship(Entity):
entity_id: int, x: int, y: int, entity_id: int, x: int, y: int,
orientation: int, speed: int, stock: int, mine: bool = True): orientation: int, speed: int, stock: int, mine: bool = True):
super().__init__(game_map, entity_id, x, y) super().__init__(game_map, entity_id, x, y)
self.orientation = orientation
self.orientation = Orientation(orientation)
self.speed = speed self.speed = speed
self.stock = stock self.stock = stock
self.mine = mine self.mine = mine
self.mine_wait = DEFAULT_MINE_WAIT self.mine_wait = DEFAULT_MINE_WAIT
self.shoot_wait = DEFAULT_SHOOT_WAIT self.shoot_wait = DEFAULT_SHOOT_WAIT
self.action = None # type: Optional[Action]
self.target = None # type: Optional[Tile]
def play_turn(self): def play_turn(self):
if self.action is Action.MINE: action = None
self.mine_wait = DEFAULT_MINE_WAIT target = None
elif self.action is Action.FIRE:
self.shoot_wait = DEFAULT_SHOOT_WAIT
if self.target: rand = random.random()
print('{} {} {}'.format(self.action.value, self.target.x, self.target.y)) perr('rand', rand)
perr('pos', self.tile)
perr('mine_wait', self.mine_wait)
perr('shoot_wait', self.shoot_wait)
perr('on path', self.tiles_on_path())
for tile in self.tiles_on_path():
if isinstance(tile, Mine) or isinstance(tile, Cannonball):
action, target = self.avoid(tile)
break
if not action:
if (self.mine_wait > 0 and self.shoot_wait > 0) or rand > 0.4:
target = Tile(random.randint(0, 23), random.randint(0, 21))
if self.game_map.barrels:
target = self.nearest_barrel()
action = Action.MOVE
elif rand > 0.2:
action = Action.FIRE
target = self.nearest_opponent()
else:
action = Action.MINE
if action is Action.MINE:
self.mine_wait = DEFAULT_MINE_WAIT
elif action is Action.FIRE:
self.shoot_wait = DEFAULT_SHOOT_WAIT
if target:
print('{} {} {}'.format(action.value, target.x, target.y))
else: else:
print(self.action.value) print(action.value)
self.action = None
self.target = None
self.mine_wait -= 1 self.mine_wait -= 1
self.shoot_wait -= 1 self.shoot_wait -= 1
def drop_mine(self): def avoid(self, tile: Tile):
self.action = Action.MINE action = Action.MOVE
target = None
if self.orientation is Orientation.RIGHT:
target = tile.top_right()
elif self.orientation is Orientation.TOP_RIGHT:
target = tile.right()
elif self.orientation is Orientation.TOP_LEFT:
target = tile.left()
elif self.orientation is Orientation.LEFT:
target = tile.top_left()
elif self.orientation is Orientation.BOTTOM_LEFT:
target = tile.left()
elif self.orientation is Orientation.BOTTOM_RIGHT:
target = tile.right()
return action, target
def wait(self): @property
self.action = Action.WAIT def tile(self):
return Tile(self.x, self.y)
def slower(self): def tiles_on_path(self):
self.action = Action.SLOWER tile = self.tile
perr('tile', tile)
tiles = []
for _ in range(self.speed + 1):
if self.orientation is Orientation.RIGHT:
tile = tile.right()
elif self.orientation is Orientation.TOP_RIGHT:
tile = tile.top_right()
elif self.orientation is Orientation.TOP_LEFT:
tile = tile.top_left()
elif self.orientation is Orientation.LEFT:
tile = tile.left()
elif self.orientation is Orientation.BOTTOM_LEFT:
tile = tile.bottom_left()
elif self.orientation is Orientation.BOTTOM_RIGHT:
tile = tile.bottom_right()
tiles.append(tile)
def shoot(self, target: 'Entity'): return tiles
self.action = Action.FIRE
self.target = target
def move(self, target: Tile):
self.action = Action.MOVE
self.target = target
def __repr__(self): def __repr__(self):
return ('Ship(id={}, x={}, y={}, orientation={}, speed={}, stock={}, mine={})' return ('Ship(id={}, x={}, y={}, orientation={}, speed={}, stock={}, mine={})'
@ -226,12 +321,13 @@ def main():
entity_id = int(entity_id) entity_id = int(entity_id)
x = int(x) x = int(x)
y = int(y) y = int(y)
entity_type = EntityType(entity_type)
if entity_type == BARREL: if entity_type is EntityType.BARREL:
rhum_quantity = int(arg_1) rhum_quantity = int(arg_1)
game_map.add_barrel(Barrel(game_map, entity_id, x, y, rhum_quantity)) game_map.add_barrel(Barrel(game_map, entity_id, x, y, rhum_quantity))
elif entity_type == SHIP: elif entity_type is EntityType.SHIP:
orientation = int(arg_1) orientation = int(arg_1)
speed = int(arg_2) speed = int(arg_2)
rhum_stock = int(arg_3) rhum_stock = int(arg_3)
@ -242,10 +338,10 @@ def main():
else: else:
game_map.add_opponent_ship(ship) game_map.add_opponent_ship(ship)
elif entity_type == MINE: elif entity_type is EntityType.MINE:
game_map.add_mine(Mine(game_map, entity_id, x, y)) game_map.add_mine(Mine(game_map, entity_id, x, y))
elif entity_type == CANNONBALL: elif entity_type is EntityType.CANNONBALL:
shooter_id = int(arg_1) shooter_id = int(arg_1)
turns_before_impact = int(arg_2) turns_before_impact = int(arg_2)
game_map.add_cannonball(Cannonball(game_map, entity_id, x, y, shooter_id, turns_before_impact)) game_map.add_cannonball(Cannonball(game_map, entity_id, x, y, shooter_id, turns_before_impact))
@ -254,24 +350,6 @@ def main():
# Play # Play
for ship in game_map.my_ships.values(): for ship in game_map.my_ships.values():
rand = random.random()
perr('rand', rand)
perr('mine_wait', ship.mine_wait)
perr('shoot_wait', ship.shoot_wait)
if (ship.mine_wait > 0 and ship.shoot_wait > 0) or rand > 0.4:
target = Tile(random.randint(0, 23), random.randint(0, 21))
if game_map.barrels:
target = ship.nearest_barrel()
ship.move(target)
elif rand > 0.2:
opponent = ship.nearest_opponent()
ship.shoot(opponent)
else:
ship.drop_mine()
ship.play_turn() ship.play_turn()