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,17 +1,22 @@
import math
import random
from enum import Enum
from typing import List, Union, Sequence, TypeVar, Optional, Dict
import sys
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'
DEFAULT_SHOOT_WAIT = 2
DEFAULT_MINE_WAIT = 4
class Orientation(IntEnum):
RIGHT, TOP_RIGHT, TOP_LEFT, LEFT, BOTTOM_LEFT, BOTTOM_RIGHT = range(6)
class Action(Enum):
@ -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()