122 lines
2.9 KiB
Python
122 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
from os import system
|
|
from typing import Tuple, List, Set, Optional
|
|
from enum import Enum, auto
|
|
|
|
|
|
class ShipOrientation(Enum):
|
|
RIGHT = auto()
|
|
DOWN = auto()
|
|
|
|
|
|
class ShipType(Enum):
|
|
PATROL_BOAT = (2, "P")
|
|
DESTROYER = (3, "D")
|
|
SUBMARINE = (3, "S")
|
|
BATTLESHIP = (4, "B")
|
|
CARRIER = (5, "C")
|
|
|
|
@property
|
|
def size(self) -> int:
|
|
return self.value[0]
|
|
|
|
@property
|
|
def symbol(self) -> str:
|
|
return self.value[1]
|
|
|
|
|
|
|
|
class Ship:
|
|
x: int
|
|
y: int
|
|
ship_type: ShipType
|
|
orientation: ShipOrientation
|
|
|
|
def __init__(self, x: int, y: int, ship_type: ShipType, orientation: ShipOrientation):
|
|
self.x = x
|
|
self.y = y
|
|
self.ship_type = ship_type
|
|
self.orientation = orientation
|
|
|
|
if self.orientation == ShipOrientation.RIGHT:
|
|
self.squares = {(x_i, self.y) for x_i in range(self.x, self.x+self.ship_type.size)}
|
|
else:
|
|
self.squares = {(self.x, y_i) for y_i in range(self.y, self.y+self.ship_type.size)}
|
|
|
|
|
|
def sunk(self, guesses: Set[Tuple[int, int]]) -> bool:
|
|
return self.squares.issubset(guesses)
|
|
|
|
def hit(self, guess) -> bool:
|
|
return guess in self.squares
|
|
|
|
|
|
|
|
class Player:
|
|
def __init__(self, name: str, board_shape: Tuple[int, int]):
|
|
self.name = name
|
|
self.board_shape = board_shape
|
|
self.guesses = set()
|
|
self.ships: List[Ship] = []
|
|
|
|
def place_ships(self):
|
|
pass
|
|
|
|
def symbol_at(self, position: Tuple[int, int]) -> str:
|
|
pass
|
|
|
|
def guess(self, opponent: Player) -> Tuple[int, int]:
|
|
pass
|
|
|
|
def defeated(self, guesses: Set[Tuple[int, int]]):
|
|
return all(ship.sunk(guesses) for ship in self.ships)
|
|
|
|
def hit(self, position: Tuple[int, int]) -> Optional[Ship]:
|
|
for ship in self.ships:
|
|
if ship.hit(position):
|
|
return ship
|
|
return None
|
|
|
|
|
|
|
|
class HumanPlayer(Player):
|
|
pass
|
|
|
|
|
|
|
|
class AIPlayer(Player):
|
|
pass
|
|
|
|
|
|
def grid_input(prompt: str, board_shape: Tuple[int, int]) -> Tuple[int, int]:
|
|
pass
|
|
|
|
|
|
def format_board(viewer: Player, opponent: Player) -> str:
|
|
pass
|
|
|
|
|
|
def play_turn(player: Player, opponent: Player):
|
|
print(format_board(player, opponent))
|
|
player.guesses.add(player.guess(opponent))
|
|
window if isinstance(player, HumanPlayer) and isinstance(opponent, HumanPlayer):
|
|
system("clear")
|
|
|
|
|
|
def play_battleship(player_1: Player, player_2: Player):
|
|
player_1.place_ships()
|
|
player_2.place_ships()
|
|
|
|
while not (player_1.defeated(player_2.guesses) or player_2.defeated(player_1.guesses)):
|
|
play_turn(player_1, player_2)
|
|
play_turn(player_2, player_1)
|
|
|
|
if player_1.defeated(player_2.guesses) and player_2.defeated(player_1.guesses):
|
|
print("It's a draw!")
|
|
elif player_1.defeated(player_2.guesses):
|
|
print(f"{player_2.name} wins!")
|
|
else:
|
|
print(f"{player_1.name} wins!")
|