Skip to main content

Small Othello/Reversi utilities and sample players for Python lessons.

Project description

othellopy

PyPI Python License CI

othellopy is a small Python package for Othello/Reversi exercises. It provides a board model, a game runner, move validation helpers, and sample players ranging from random play to alpha-beta search.

The package is currently 0.x alpha software. Public APIs may change before 1.0.0.

Official distribution:

Requirements

  • Python 3.10 or later
  • No runtime dependencies

Installation

Install from PyPI:

python -m pip install othellopy

Upgrade an existing PyPI installation:

python -m pip install --upgrade othellopy

Check the installed version:

python -m pip show othellopy

Install an unreleased branch from GitHub only when you intentionally need development code, for example in Google Colab:

!pip install git+https://github.com/Hietan/othellopy.git@main

Quick Start

Run a complete game between two sample players:

from othellopy.board import print_board
from othellopy.game import OthelloGame
from othellopy.players import BeginnerPlayer, IntermediatePlayer

result = OthelloGame(BeginnerPlayer, IntermediatePlayer).play()

print(result.winner)
print(result.black_score, result.white_score)
print_board(result.board)

Writing a Player

Subclass BasePlayer and implement next_move().

from othellopy.core import Board, Cell, Move
from othellopy.players import BasePlayer


class MyPlayer(BasePlayer):
    def __init__(self, color: Cell) -> None:
        super().__init__(color)

    def next_move(self, board: Board) -> Move:
        return self.get_moves(board)[0]

Coordinates are zero-based (row, col) pairs. next_move() is called only when the player has at least one legal move.

Pre-Submission Player Check

Use validate() before submitting a custom player from Google Colab or another notebook environment.

from othellopy.validation import validate, validate_detail

if validate(MyPlayer):
    print("OK to submit")
else:
    result = validate_detail(MyPlayer)
    for issue in result.errors:
        print(issue.code, issue.message)

The validator checks that the class inherits from BasePlayer, can be constructed for black and white, returns legal moves on several board states, does not mutate the board, does not print during next_move(), and returns within one second by default.

It also performs static checks on the class source. External packages such as numpy are not allowed for this course. Safe standard library modules such as random and math are allowed, while file, process, network, import-system, and arbitrary-code execution APIs are rejected.

This is a pre-submission screen, not a security sandbox. Evaluation servers should run the same validation again and execute submitted players in an isolated sandbox.

Manual CLI Play

Use ManualPlayer to enter moves interactively from a terminal. Input is two digits in row-column order, such as 07.

from othellopy.game import OthelloGame
from othellopy.players import BeginnerPlayer, ManualPlayer

result = OthelloGame(ManualPlayer, BeginnerPlayer).play()

Equivalent one-off command:

uv run python - <<'PY'
from othellopy.game import OthelloGame
from othellopy.players import BeginnerPlayer, ManualPlayer

result = OthelloGame(ManualPlayer, BeginnerPlayer).play()
print(result.winner, result.black_score, result.white_score)
PY

Sample Players

Import sample players from othellopy.players:

from othellopy.players import (
    AdvancedPlayer,
    BeginnerPlayer,
    IntermediatePlayer,
    ManualPlayer,
)
  • BeginnerPlayer: chooses a legal move randomly.
  • IntermediatePlayer: scores legal moves with a simple one-ply heuristic.
  • AdvancedPlayer: searches ahead with alpha-beta pruning.
  • ManualPlayer: asks for row-column input in a CLI.

Board Display

Board helpers render stones as ⚫️ and ⚪️ when the output encoding supports them. If the output cannot encode those emoji, display falls back to B and W.

Use display_board() in Google Colab or Jupyter notebooks. It renders a fixed HTML table so emoji stones stay aligned even when the notebook font gives emoji a different display width from ASCII characters.

from othellopy.board import display_board, initial_board

display_board(initial_board())

Use print_board() for terminal output.

from othellopy.board import initial_board, print_board

print_board(initial_board())

Use board_to_str(..., use_emoji=False) when you need stable ASCII output.

Invalid Moves and Forfeits

If a player returns an invalid move, the player forfeits and the opponent wins. The game still returns a GameResult.

result = OthelloGame(MyPlayer, BeginnerPlayer).play()

if result.forfeit is not None:
    print(result.winner)
    print(result.forfeit.color)
    print(result.forfeit.move)
    print(result.forfeit.valid_moves)

API Overview

othellopy.core

Cell : IntEnum representing board cell values.

Cell.EMPTY
Cell.BLACK
Cell.WHITE

Board : Type alias for list[list[Cell]].

Move : Type alias for tuple[int, int].

opponent(cell: Cell) -> Cell : Returns Cell.WHITE for Cell.BLACK, and Cell.BLACK for Cell.WHITE. Passing Cell.EMPTY raises ValueError.

othellopy.board

initial_board() -> Board : Returns the standard 8x8 initial Othello board.

copy_board(board: Board) -> Board : Returns a row-by-row copy of a board.

board_to_str(board: Board, *, use_emoji: bool | None = None) -> str : Converts a board to readable text.

board_to_html(board: Board, *, use_emoji: bool | None = None) -> str : Converts a board to a fixed-cell HTML table for notebook display.

display_board(board: Board, *, use_emoji: bool | None = None) -> None : Displays a board as HTML in IPython notebooks, falling back to text output outside IPython.

print_board(board: Board, *, use_emoji: bool | None = None) -> None : Prints a readable board.

othellopy.players

BasePlayer : Base class for custom players. Provides:

  • color
  • opponent_color
  • get_moves(board)
  • is_valid_move(board, row, col)
  • get_flips(board, row, col)

BeginnerPlayer : Random legal move player.

IntermediatePlayer : Simple heuristic player.

AdvancedPlayer : Alpha-beta search player. Accepts depth= in the constructor.

ManualPlayer : Interactive CLI player. Accepts optional input_func, output, and use_emoji parameters for testing or custom IO.

othellopy.game

OthelloGame(black_player_class, white_player_class) : Runs one game between two BasePlayer subclasses.

GameResult : Return value from OthelloGame(...).play().

Fields:

  • winner: Cell
  • black_score: int
  • white_score: int
  • board: Board
  • moves: list[tuple[Cell, int, int]]
  • turns: list[TurnRecord]
  • forfeit: ForfeitRecord | None

TurnRecord : Per-turn debug information.

Fields:

  • color: Cell
  • board: Board
  • valid_moves: list[tuple[int, int]]
  • move: tuple[int, int] | None
  • black_score: int
  • white_score: int

ForfeitRecord : Invalid-move forfeit information.

Fields:

  • color: Cell
  • move: object
  • valid_moves: list[tuple[int, int]]
  • board: Board
  • message: str

othellopy.validation

validate(player_class, *, max_seconds=1.0) -> bool : Returns True when a submitted player class passes pre-submission checks.

validate_detail(player_class, *, max_seconds=1.0) -> ValidationResult : Returns detailed errors, warnings, and runtime case details.

ValidationResult : Detailed validation result.

Fields:

  • passed: bool
  • issues: list[ValidationIssue]
  • errors: list[ValidationIssue]
  • warnings: list[ValidationIssue]
  • details: dict[str, object]

ValidationIssue : One validation issue.

Fields:

  • code: str
  • message: str
  • severity: ValidationSeverity

Development

uv venv
uv pip install -e ".[dev]"

Run checks:

uv run --extra dev ruff check .
uv run --extra dev mypy src/othellopy
uv run --extra dev pytest
uv build

Release Policy

othellopy is published on PyPI from GitHub tags named vX.Y.Z. Published PyPI files are immutable, so a broken release is fixed by publishing a newer version instead of replacing an existing one.

The release checklist is documented in RELEASE.md.

Contributing

Contributions must follow the GitFlow rules in CONTRIBUTING.md:

  • feat/* pull requests target dev.
  • release/* pull requests target main.
  • Direct pushes to main and dev are not allowed.
  • Required checks must pass before merge.

Security

Please do not report vulnerabilities in public issues. See SECURITY.md.

License

Licensed under the Apache License, Version 2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

othellopy-0.2.1.tar.gz (55.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

othellopy-0.2.1-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file othellopy-0.2.1.tar.gz.

File metadata

  • Download URL: othellopy-0.2.1.tar.gz
  • Upload date:
  • Size: 55.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for othellopy-0.2.1.tar.gz
Algorithm Hash digest
SHA256 43e11bc79b3fb3dc6997371447fe2060a7fe27c4a4e19106292b223443a41350
MD5 ad5beb737351684ce4782af3aa521fa3
BLAKE2b-256 7339fd4fb96ec457375d62c5908c4c63222fe84ab3e2423e8ea357940c6b7070

See more details on using hashes here.

File details

Details for the file othellopy-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: othellopy-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 23.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for othellopy-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e447c5dd5e71f0df093583b15f9316acd4ecb20167711b8bfa9c2e7bb3f8ceef
MD5 aa93d54acbea5d1acd1a860cc25da62f
BLAKE2b-256 32ba6c24aa12eb696fad25e5239364b8f2e691c65067f4892edc10afe4be68f1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page