Metadata-Version: 2.4
Name: valanga
Version: 0.3.0
Summary: Shared types and utilities for evaluation
Author-email: Victor Gabillon <victorgabillon@gmail.com>
License-Expression: GPL-3.0-only
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.14
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: test
Requires-Dist: pytest==9.1.1; extra == "test"
Requires-Dist: coverage==7.17.0; extra == "test"
Requires-Dist: pytest-cov==7.1.0; extra == "test"
Provides-Extra: lint
Requires-Dist: ruff==0.17.3; extra == "lint"
Requires-Dist: pylint==4.1.3; extra == "lint"
Provides-Extra: typecheck
Requires-Dist: mypy==2.4.0; extra == "typecheck"
Requires-Dist: pyright[nodejs]==1.1.414; extra == "typecheck"
Provides-Extra: dev
Requires-Dist: tox==4.67.2; extra == "dev"
Requires-Dist: types-PyYAML==6.0.12.20260906; extra == "dev"
Requires-Dist: ruff==0.17.3; extra == "dev"
Requires-Dist: pylint==4.1.3; extra == "dev"
Requires-Dist: black==26.10.1; extra == "dev"
Requires-Dist: mypy==2.4.0; extra == "dev"
Requires-Dist: pyright[nodejs]==1.1.414; extra == "dev"
Requires-Dist: build==1.6.1; extra == "dev"
Requires-Dist: twine==7.0.0; extra == "dev"
Requires-Dist: sphinx==9.2.0; extra == "dev"
Requires-Dist: sphinx-rtd-theme==3.1.0; extra == "dev"
Requires-Dist: sphinx-autodoc-typehints==3.17.3; extra == "dev"
Requires-Dist: pre-commit==4.7.0; extra == "dev"
Dynamic: license-file

# valanga

![Python 3.14](https://img.shields.io/badge/python-3.14-blue?logo=python)
[![Tests](https://github.com/victorgabillon/valanga/actions/workflows/ci.yaml/badge.svg?label=tests)](https://github.com/victorgabillon/valanga/actions/workflows/ci.yaml)
[![License: GPL v3](https://img.shields.io/github/license/victorgabillon/valanga)](LICENSE)

Shared Python types and lightweight utilities for describing turn-based games and their evaluations. The package exposes protocols for representing states, outcomes, and state representations that other libraries can build on.

## Release 0.3.0

This release requires Python 3.14 and includes native generic protocols with
explicit state and hashable-key bounds, precise representation defaults, and
deferred annotations. Both mypy and Pyright validate the generic contracts;
game primitives and evaluation behavior are preserved.

## Key concepts
- **Game primitives**: `State`, `HasTurn[RoleT]`, and `TurnState[RoleT]` model states and acting roles. `Color` remains the natural role type for black/white games, while `SoloRole` supports single-player sequential games without fake color semantics. 【F:src/valanga/game.py†L1-L189】
- **Evaluations**: `Value` carries a score, certainty level, and optional terminal `OverEvent` metadata. 【F:src/valanga/evaluations.py†L31-L47】
- **Game termination**: `OverEvent` stores `outcome`, `termination`, and optional `winner` metadata. 【F:src/valanga/over_event.py†L1-L99】
- **State representations**: `ContentRepresentation` defines how to turn a `State` into evaluator input, and `RepresentationFactory` builds or updates those representations from states and modifications. 【F:src/valanga/represention_for_evaluation.py†L9-L22】【F:src/valanga/representation_factory.py†L7-L55】
- **Progress reporting**: `PlayerProgressMessage` is a Color-specific helper for per-player progress reporting. It is not part of the core generic role model. 【F:src/valanga/progress_messsage.py†L1-L13】

## Installation
```bash
pip install valanga==0.3.0
```
The project targets Python 3.14 and has no required runtime dependencies.

## Quick start
Below is a minimal example that records both a two-player terminal result and a single-player terminal result:
```python
from enum import Enum, auto

from valanga import Color, Outcome, OverEvent


class ChessTermination(Enum):
    CHECKMATE = auto()


class PuzzleTermination(Enum):
    GOAL_REACHED = auto()


# Two-player result: white wins by checkmate.
checkmate = OverEvent(
    outcome=Outcome.WIN,
    termination=ChessTermination.CHECKMATE,
    winner=Color.WHITE,
)

# Single-player result: the puzzle objective was reached.
puzzle_clear = OverEvent(
    outcome=Outcome.WIN,
    termination=PuzzleTermination.GOAL_REACHED,
)

print(checkmate.is_win_for(Color.WHITE))  # -> True
print(puzzle_clear.is_success())  # -> True
```

To wire in a custom state representation, supply callables to `RepresentationFactory` that know how to build representations from a `State` and its modifications.

## Development
Install the development dependencies and run the test suite:
```bash
uv venv --python 3.14
uv pip install -e '.[test,dev]'
source .venv/bin/activate
tox
```

Python 3.14 uses deferred annotations by default. Runtime consumers should use
`typing.get_type_hints` for resolved types and `annotationlib.get_annotations`
with `Format.STRING` when annotation text is needed. Generic protocols use native
type parameters; acting roles and branch keys retain their hashable bounds.

Generic type contracts are checked by both mypy and Pyright in `tox -e typecheck`.
The fixtures verify key/role covariance, selector/input contravariance, output
covariance, state/transition relationships and undo-token identity. Both checkers
must also reject the marked invalid examples in `tests/typing/invalid.py`.
`Dynamics` and `ReversibleDynamics` require a `State`; tag resolvers require
hashable tags. `ContentRepresentation` defaults to `State` and `EvaluatorInput`.
These bounds and defaults are declared on the native type parameters themselves.
