Try to avoid mines
This commit is contained in:
parent
d7fb6f278a
commit
47fb9df56c
1 changed files with 133 additions and 55 deletions
|
@ -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()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue