This repository has been archived by the owner on Jun 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Merwane Hamadi <[email protected]>
- Loading branch information
1 parent
99bbed2
commit 3b0284f
Showing
17 changed files
with
1,098 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,4 +75,5 @@ def gamePlay(): | |
if winner(board) == 0: | ||
print("Draw") | ||
|
||
gamePlay() | ||
if __name__ == '__main__': | ||
gamePlay() |
Empty file.
107 changes: 107 additions & 0 deletions
107
agbenchmark/challenges/verticals/code/5_battleship/artifacts_in/abstract_class.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
from abc import ABC, abstractmethod | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel, validator | ||
|
||
|
||
# Models for the request and response payloads | ||
class ShipPlacement(BaseModel): | ||
ship_type: str | ||
start: dict # {"row": int, "column": str} | ||
direction: str | ||
|
||
@validator("start") | ||
def validate_start(cls, start): | ||
row, column = start.get("row"), start.get("column") | ||
|
||
if not (1 <= row <= 10): | ||
raise ValueError("Row must be between 1 and 10 inclusive.") | ||
|
||
if column not in list("ABCDEFGHIJ"): | ||
raise ValueError("Column must be one of A, B, C, D, E, F, G, H, I, J.") | ||
|
||
return start | ||
|
||
|
||
class Turn(BaseModel): | ||
target: dict # {"row": int, "column": str} | ||
|
||
|
||
class TurnResponse(BaseModel): | ||
result: str | ||
ship_type: Optional[str] # This would be None if the result is a miss | ||
|
||
|
||
class GameStatus(BaseModel): | ||
is_game_over: bool | ||
winner: Optional[str] | ||
|
||
|
||
from typing import List | ||
|
||
|
||
class Game(BaseModel): | ||
game_id: str | ||
players: List[str] | ||
board: dict # This could represent the state of the game board, you might need to flesh this out further | ||
ships: List[ShipPlacement] # List of ship placements for this game | ||
turns: List[Turn] # List of turns that have been taken | ||
|
||
|
||
class AbstractBattleship(ABC): | ||
SHIP_LENGTHS = { | ||
"carrier": 5, | ||
"battleship": 4, | ||
"cruiser": 3, | ||
"submarine": 3, | ||
"destroyer": 2, | ||
} | ||
|
||
@abstractmethod | ||
def create_ship_placement(self, game_id: str, placement: ShipPlacement) -> None: | ||
""" | ||
Place a ship on the grid. | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def create_turn(self, game_id: str, turn: Turn) -> TurnResponse: | ||
""" | ||
Players take turns to target a grid cell. | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def get_game_status(self, game_id: str) -> GameStatus: | ||
""" | ||
Check if the game is over and get the winner if there's one. | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def get_winner(self, game_id: str) -> str: | ||
""" | ||
Get the winner of the game. | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def get_game(self) -> Game: | ||
""" | ||
Retrieve the state of the game. | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def delete_game(self, game_id: str) -> None: | ||
""" | ||
Delete a game given its ID. | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def create_game(self, game_id: str) -> None: | ||
""" | ||
Create a new game. | ||
""" | ||
pass |
62 changes: 62 additions & 0 deletions
62
agbenchmark/challenges/verticals/code/5_battleship/artifacts_in/conftest.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import pytest | ||
|
||
from abstract_class import ShipPlacement, Turn | ||
|
||
from battleship import Battleship | ||
|
||
@pytest.fixture | ||
def battleship_game(): | ||
return Battleship() | ||
|
||
|
||
@pytest.fixture | ||
def initialized_game_id(battleship_game): | ||
# Create a game instance | ||
game_id = battleship_game.create_game() | ||
|
||
# Place all the ships using battleship_game's methods | ||
sample_ship_placements = [ | ||
ShipPlacement( | ||
ship_type="carrier", start={"row": 1, "column": "A"}, direction="horizontal" | ||
), | ||
ShipPlacement( | ||
ship_type="battleship", | ||
start={"row": 2, "column": "A"}, | ||
direction="horizontal", | ||
), | ||
ShipPlacement( | ||
ship_type="cruiser", start={"row": 3, "column": "A"}, direction="horizontal" | ||
), | ||
ShipPlacement( | ||
ship_type="submarine", | ||
start={"row": 4, "column": "A"}, | ||
direction="horizontal", | ||
), | ||
ShipPlacement( | ||
ship_type="destroyer", | ||
start={"row": 5, "column": "A"}, | ||
direction="horizontal", | ||
), | ||
] | ||
|
||
for ship_placement in sample_ship_placements: | ||
# Place ship using battleship_game's methods | ||
battleship_game.create_ship_placement(game_id, ship_placement) | ||
|
||
return game_id | ||
|
||
|
||
@pytest.fixture | ||
def game_over_fixture(battleship_game, initialized_game_id): | ||
# Assuming 10x10 grid, target all possible positions | ||
for row in range(1, 11): | ||
for column in list("ABCDEFGHIJ"): | ||
# Player 1 takes a turn | ||
turn = Turn(target={"row": row, "column": column}) | ||
battleship_game.create_turn(initialized_game_id, turn) | ||
|
||
# Player 2 takes a turn, targeting the same position as Player 1 | ||
battleship_game.create_turn(initialized_game_id, turn) | ||
|
||
# At the end of this fixture, the game should be over | ||
return initialized_game_id |
30 changes: 30 additions & 0 deletions
30
agbenchmark/challenges/verticals/code/5_battleship/artifacts_in/product_requirements.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Specifications for Battleship | ||
|
||
Overview: Battleship is a two-player strategy game where each player places their fleet of ships on a grid and tries to sink the opponent's fleet by guessing their locations. | ||
Players take turns calling out a row and column, attempting to name a square containing one of the opponent's ships. | ||
|
||
The Grid: Each player's grid is a 10x10 grid, identified by rows (using numbers 1-10) and columns (using letters A-J). | ||
|
||
Ships: | ||
|
||
Carrier - 5 squares | ||
Battleship - 4 squares | ||
Cruiser - 3 squares | ||
Submarine - 3 squares | ||
Destroyer - 2 squares | ||
Each ship occupies contiguous squares on the grid, arranged either horizontally or vertically. | ||
|
||
Setup: | ||
|
||
At the start of the game, each player places their fleet on their grid. This setup is hidden from the opponent. | ||
The game begins with Player 1, followed by Player 2, and so on. | ||
Taking Turns: | ||
|
||
On a player's turn, they announce a grid square (e.g., "D5"). | ||
The opponent announces whether that square is a "hit" (if there's a part of a ship on that square) or "miss" (if the square is empty). | ||
If a player hits a square occupied by a ship, they get another turn to guess. This continues until they make a miss, at which point their turn ends. | ||
If a player hits all the squares occupied by a ship, the opponent must announce the sinking of that specific ship, e.g., "You sank my Battleship!" | ||
|
||
Objective: The goal is to sink all of your opponent's ships before they sink yours. | ||
|
||
End of the Game: The game ends when one player has sunk all of the opponent's ships. The winner is the player who sinks all the opposing fleet first. |
103 changes: 103 additions & 0 deletions
103
agbenchmark/challenges/verticals/code/5_battleship/artifacts_in/test_negative.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import pytest | ||
from pydantic import ValidationError | ||
|
||
from abstract_class import ShipPlacement, Turn | ||
|
||
|
||
def test_ship_placement_out_of_bounds(battleship_game): | ||
game_id = battleship_game.create_game() | ||
|
||
try: | ||
out_of_bounds_ship = ShipPlacement( | ||
ship_type="battleship", | ||
start={"row": 11, "column": "Z"}, | ||
direction="horizontal", | ||
) | ||
except ValidationError: # Use the directly imported ValidationError class | ||
pass | ||
else: | ||
with pytest.raises(ValueError, match="Placement out of bounds"): | ||
battleship_game.create_ship_placement(game_id, out_of_bounds_ship) | ||
|
||
|
||
def test_no_ship_overlap(battleship_game): | ||
game_id = battleship_game.create_game() | ||
placement1 = ShipPlacement( | ||
ship_type="battleship", start={"row": 1, "column": "A"}, direction="horizontal" | ||
) | ||
battleship_game.create_ship_placement(game_id, placement1) | ||
placement2 = ShipPlacement( | ||
ship_type="cruiser", start={"row": 1, "column": "A"}, direction="horizontal" | ||
) | ||
with pytest.raises(ValueError): | ||
battleship_game.create_ship_placement(game_id, placement2) | ||
|
||
|
||
def test_cant_hit_before_ships_placed(battleship_game): | ||
game_id = battleship_game.create_game() | ||
placement1 = ShipPlacement( | ||
ship_type="battleship", start={"row": 1, "column": "A"}, direction="horizontal" | ||
) | ||
battleship_game.create_ship_placement(game_id, placement1) | ||
placement2 = ShipPlacement( | ||
ship_type="cruiser", start={"row": 4, "column": "D"}, direction="horizontal" | ||
) | ||
battleship_game.create_ship_placement(game_id, placement2) | ||
turn = Turn(target={"row": 1, "column": "A"}) | ||
with pytest.raises( | ||
ValueError, match="All ships must be placed before starting turns" | ||
): | ||
battleship_game.create_turn(game_id, turn) | ||
|
||
|
||
def test_cant_place_ship_after_all_ships_placed(battleship_game, initialized_game_id): | ||
game = battleship_game.get_game( | ||
initialized_game_id | ||
) | ||
additional_ship = ShipPlacement( | ||
ship_type="carrier", start={"row": 2, "column": "E"}, direction="horizontal" | ||
) | ||
|
||
with pytest.raises( | ||
ValueError, match="All ships are already placed. Cannot place more ships." | ||
): | ||
battleship_game.create_ship_placement(initialized_game_id, additional_ship) | ||
|
||
|
||
def test_ship_placement_invalid_direction(battleship_game): | ||
game_id = battleship_game.create_game() | ||
|
||
with pytest.raises(ValueError, match="Invalid ship direction"): | ||
invalid_direction_ship = ShipPlacement( | ||
ship_type="battleship", | ||
start={"row": 1, "column": "A"}, | ||
direction="diagonal", | ||
) | ||
battleship_game.create_ship_placement(game_id, invalid_direction_ship) | ||
|
||
|
||
def test_invalid_ship_type(battleship_game): | ||
game_id = battleship_game.create_game() | ||
invalid_ship = ShipPlacement( | ||
ship_type="spacecraft", start={"row": 1, "column": "A"}, direction="horizontal" | ||
) | ||
with pytest.raises(ValueError, match="Invalid ship type"): | ||
battleship_game.create_ship_placement(game_id, invalid_ship) | ||
|
||
|
||
def test_ship_placement_extends_beyond_boundaries(battleship_game): | ||
game_id = battleship_game.create_game() | ||
|
||
with pytest.raises(ValueError, match="Ship extends beyond board boundaries"): | ||
ship_extending_beyond = ShipPlacement( | ||
ship_type="battleship", | ||
start={"row": 1, "column": "H"}, | ||
direction="horizontal", | ||
) | ||
battleship_game.create_ship_placement(game_id, ship_extending_beyond) | ||
|
||
with pytest.raises(ValueError, match="Ship extends beyond board boundaries"): | ||
ship_extending_beyond = ShipPlacement( | ||
ship_type="cruiser", start={"row": 9, "column": "A"}, direction="vertical" | ||
) | ||
battleship_game.create_ship_placement(game_id, ship_extending_beyond) |
Oops, something went wrong.