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 random
from enum import Enum
from typing import List, Union, Sequence, TypeVar, Optional, Dict
import sys
BARREL = 'BARREL'
SHIP = 'SHIP'
MINE = 'MINE'
CANNONBALL = 'CANNONBALL'
from enum import Enum, IntEnum
from typing import List, Sequence, Optional, Dict
DEFAULT_SHOOT_WAIT = 2
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):
MINE = 'MINE'
MOVE = 'MOVE'
@ -63,6 +68,8 @@ class GameMap:
def add_my_ship(self, ship: 'Ship'):
my_ship = self.my_ships.get(ship.id, None)
if my_ship:
my_ship.x = ship.x
my_ship.y = ship.y
my_ship.orientation = ship.orientation
my_ship.speed = ship.speed
my_ship.stock = ship.stock
@ -85,6 +92,9 @@ class GameMap:
def _add_to_map(self, entity: 'Entity'):
self.map[entity.coord] = entity
def get_at(self, tile: 'Tile'):
return self.map[tile.coord]
class Tile:
def __init__(self, x: int, y: int):
@ -95,6 +105,40 @@ class Tile:
def coord(self):
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):
return 'Tile(x={}, y={})'.format(self.x, self.y)
@ -145,46 +189,97 @@ class Ship(Entity):
entity_id: int, x: int, y: int,
orientation: int, speed: int, stock: int, mine: bool = True):
super().__init__(game_map, entity_id, x, y)
self.orientation = orientation
self.orientation = Orientation(orientation)
self.speed = speed
self.stock = stock
self.mine = mine
self.mine_wait = DEFAULT_MINE_WAIT
self.shoot_wait = DEFAULT_SHOOT_WAIT
self.action = None # type: Optional[Action]
self.target = None # type: Optional[Tile]
def play_turn(self):
if self.action is Action.MINE:
action = None
target = None
rand = random.random()
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 self.action is Action.FIRE:
elif action is Action.FIRE:
self.shoot_wait = DEFAULT_SHOOT_WAIT
if self.target:
print('{} {} {}'.format(self.action.value, self.target.x, self.target.y))
if target:
print('{} {} {}'.format(action.value, target.x, target.y))
else:
print(self.action.value)
self.action = None
self.target = None
print(action.value)
self.mine_wait -= 1
self.shoot_wait -= 1
def drop_mine(self):
self.action = Action.MINE
def avoid(self, tile: Tile):
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):
self.action = Action.WAIT
@property
def tile(self):
return Tile(self.x, self.y)
def slower(self):
self.action = Action.SLOWER
def tiles_on_path(self):
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'):
self.action = Action.FIRE
self.target = target
def move(self, target: Tile):
self.action = Action.MOVE
self.target = target
return tiles
def __repr__(self):
return ('Ship(id={}, x={}, y={}, orientation={}, speed={}, stock={}, mine={})'
@ -226,12 +321,13 @@ def main():
entity_id = int(entity_id)
x = int(x)
y = int(y)
entity_type = EntityType(entity_type)
if entity_type == BARREL:
if entity_type is EntityType.BARREL:
rhum_quantity = int(arg_1)
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)
speed = int(arg_2)
rhum_stock = int(arg_3)
@ -242,10 +338,10 @@ def main():
else:
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))
elif entity_type == CANNONBALL:
elif entity_type is EntityType.CANNONBALL:
shooter_id = int(arg_1)
turns_before_impact = int(arg_2)
game_map.add_cannonball(Cannonball(game_map, entity_id, x, y, shooter_id, turns_before_impact))
@ -254,24 +350,6 @@ def main():
# Play
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()