Metadata-Version: 2.1
Name: codenames
Version: 5.0.2
Summary: Codenames board game logic implementation in python.
Author: Asaf Kali
Author-email: asaf.kali@mail.huji.ac.il
Requires-Python: >=3.12,<4.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Provides-Extra: web
Requires-Dist: beautifultable (>=1.0,<2.0)
Requires-Dist: pydantic (>=2.0,<3.0)
Requires-Dist: selenium (>=4.1,<5.0) ; extra == "web"
Project-URL: Homepage, https://github.com/asaf-kali/codenames
Project-URL: Issues, https://github.com/asaf-kali/codenames/issues
Project-URL: Repository, https://github.com/asaf-kali/codenames
Description-Content-Type: text/markdown

# Codenames

[![PyPI version](https://badge.fury.io/py/codenames.svg)](https://badge.fury.io/py/codenames)
[![Pipeline](https://github.com/asaf-kali/codenames/actions/workflows/pipeline.yml/badge.svg)](https://github.com/asaf-kali/codenames/actions/workflows/pipeline.yml)
[![codecov](https://codecov.io/github/asaf-kali/codenames/graph/badge.svg?token=HET5E8P1UK)](https://codecov.io/github/asaf-kali/codenames)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Code style: black](https://img.shields.io/badge/code%20style-black-111111.svg)](https://github.com/psf/black)
[![Imports: isort](https://img.shields.io/badge/imports-isort-%231674b1)](https://pycqa.github.io/isort/)
[![Type checked: mypy](https://img.shields.io/badge/type%20check-mypy-22aa11)](http://mypy-lang.org/)
[![Linting: pylint](https://img.shields.io/badge/linting-pylint-22aa11)](https://github.com/pylint-dev/pylint)

Code infrastructure for the Codenames board game. \
Designed to serve as a base for implementing players (agents) with different strategies and algorithms. \
See the [codenames-solvers](https://github.com/asaf-kali/codenames-solvers) repository for such examples.


### Installation

Install from PyPI using pip: `pip install codenames`

### Usage
Here is a simple example of command-line based players, and a `GameRunner` that runs a game between them:

```python
import logging
import sys

from codenames.classic.builder import generate_board
from codenames.classic.color import ClassicTeam
from codenames.classic.runner.models import GamePlayers
from codenames.classic.runner.runner import ClassicGameRunner
from codenames.generic.move import Clue, Guess
from codenames.generic.player import Operative, Spymaster
from codenames.generic.state import OperativeState, SpymasterState

logging.basicConfig(level=logging.INFO, format="%(message)s", stream=sys.stdout)

####################################
# Naive CLI players implementation #
####################################


class CLISpymaster(Spymaster):
    def give_clue(self, game_state: SpymasterState) -> Clue:
        print("\nGive a hint. Board: \n" + game_state.board.printable_string)
        print(f"Revealed cards: {list(game_state.board.revealed_card_indexes)}")
        hint_word = input("Enter hint word: ")
        card_amount = int(input("Enter card amount: "))
        return Clue(word=hint_word, card_amount=card_amount)


class CLIOperative(Operative):
    def guess(self, game_state: OperativeState) -> Guess:
        print(f"\nGuess a card. Given clue: {game_state.current_clue}. Current board state: ")
        print(game_state.board.printable_string)
        card_word = input("Enter card word: ")
        card_index = game_state.board.find_card_index(word=card_word)
        return Guess(card_index=card_index)


def run_cli_game():
    language = "english"
    board = generate_board(language=language)
    blue_spymaster = CLISpymaster("Yoda", ClassicTeam.BLUE)
    blue_operative = CLIOperative("Luke", ClassicTeam.BLUE)
    red_spymaster = CLISpymaster("Einstein", ClassicTeam.RED)
    red_operative = CLIOperative("Newton", ClassicTeam.RED)
    players = GamePlayers.from_collection([blue_spymaster, blue_operative, red_spymaster, red_operative])
    runner = ClassicGameRunner(players=players, board=board)
    winner = runner.run_game()
    print(f"Winner: {winner}")


if __name__ == "__main__":
    run_cli_game()
```

Example output:
```
-----
[RED] turn.

Give a hint. Board:
+-----------+-------------+------------+-----------------+------------+
| ‎🟦 pretty |  ‎⬜ young   |  ‎⬜ essay  |    ‎🟥 apple     |  ‎⬜ kiss   |
+-----------+-------------+------------+-----------------+------------+
|  ‎⬜ poem  |  ‎🟦 solve   |   ‎🟥 pan   | ‎🟦 organization |  ‎🟦 union  |
+-----------+-------------+------------+-----------------+------------+
|  ‎🟥 myth  |   ‎🟥 neck   | ‎🟥 shelter |    ‎🟦 locate    |   ‎🟥 pet   |
+-----------+-------------+------------+-----------------+------------+
| ‎🟥 react  |  ‎⬜ person  |  ‎⬜ mood   |    ‎🟥 heart     | ‎⬜ breath  |
+-----------+-------------+------------+-----------------+------------+
|  ‎🟥 rich  | ‎🟦 standard |  ‎🟦 crop   |   ‎💀 chicken    | ‎🟦 wedding |
+-----------+-------------+------------+-----------------+------------+
Revealed cards: []
Enter hint word: example
Enter card amount: 2
Spymaster: [example] 2 card(s)

Guess a card. Given clue: [example] [2]. Current board state:
+--------+----------+---------+--------------+---------+
| ‎pretty |  ‎young   |  ‎essay  |    ‎apple     |  ‎kiss   |
+--------+----------+---------+--------------+---------+
|  ‎poem  |  ‎solve   |   ‎pan   | ‎organization |  ‎union  |
+--------+----------+---------+--------------+---------+
|  ‎myth  |   ‎neck   | ‎shelter |    ‎locate    |   ‎pet   |
+--------+----------+---------+--------------+---------+
| ‎react  |  ‎person  |  ‎mood   |    ‎heart     | ‎breath  |
+--------+----------+---------+--------------+---------+
|  ‎rich  | ‎standard |  ‎crop   |   ‎chicken    | ‎wedding |
+--------+----------+---------+--------------+---------+
Enter card word: heart
Operative: '🟥 heart', correct!

Guess a card. Given clue: [example] [2]. Current board state:
+--------+----------+---------+--------------+---------+
| ‎pretty |  ‎young   |  ‎essay  |    ‎apple     |  ‎kiss   |
+--------+----------+---------+--------------+---------+
|  ‎poem  |  ‎solve   |   ‎pan   | ‎organization |  ‎union  |
+--------+----------+---------+--------------+---------+
|  ‎myth  |   ‎neck   | ‎shelter |    ‎locate    |   ‎pet   |
+--------+----------+---------+--------------+---------+
| ‎react  |  ‎person  |  ‎mood   |   ‎🟥 heart   | ‎breath  |
+--------+----------+---------+--------------+---------+
|  ‎rich  | ‎standard |  ‎crop   |   ‎chicken    | ‎wedding |
+--------+----------+---------+--------------+---------+
Enter card word: pet
Operative: '🟥 pet', correct!

Guess a card. Given clue: [example] [2]. Current board state:
+--------+----------+---------+--------------+---------+
| ‎pretty |  ‎young   |  ‎essay  |    ‎apple     |  ‎kiss   |
+--------+----------+---------+--------------+---------+
|  ‎poem  |  ‎solve   |   ‎pan   | ‎organization |  ‎union  |
+--------+----------+---------+--------------+---------+
|  ‎myth  |   ‎neck   | ‎shelter |    ‎locate    | ‎🟥 pet  |
+--------+----------+---------+--------------+---------+
| ‎react  |  ‎person  |  ‎mood   |   ‎🟥 heart   | ‎breath  |
+--------+----------+---------+--------------+---------+
|  ‎rich  | ‎standard |  ‎crop   |   ‎chicken    | ‎wedding |
+--------+----------+---------+--------------+---------+
Enter card word: mood
Operative: '⬜ mood', wrong!
Operative wrong, turn is over

-----
[BLUE] turn.

Give a hint. Board:
+-----------+-------------+------------+-----------------+------------+
| ‎🟦 pretty |  ‎⬜ young   |  ‎⬜ essay  |    ‎🟥 apple     |  ‎⬜ kiss   |
+-----------+-------------+------------+-----------------+------------+
|  ‎⬜ poem  |  ‎🟦 solve   |   ‎🟥 pan   | ‎🟦 organization |  ‎🟦 union  |
+-----------+-------------+------------+-----------------+------------+
|  ‎🟥 myth  |   ‎🟥 neck   | ‎🟥 shelter |    ‎🟦 locate    |   ‎🟥 pet   |
+-----------+-------------+------------+-----------------+------------+
| ‎🟥 react  |  ‎⬜ person  |  ‎⬜ mood   |    ‎🟥 heart     | ‎⬜ breath  |
+-----------+-------------+------------+-----------------+------------+
|  ‎🟥 rich  | ‎🟦 standard |  ‎🟦 crop   |   ‎💀 chicken    | ‎🟦 wedding |
+-----------+-------------+------------+-----------------+------------+
Revealed cards: [14, 17, 18]
Enter hint word:
......
```

