Metadata-Version: 2.4
Name: gymnasium-orchard
Version: 0.1.0
Summary: Gymnasium environments for the Orchard cooperative dice game
Project-URL: Repository, https://gitlab.com/recommend.games/orchard
Project-URL: Homepage, https://blog.recommend.games/posts/orchard/
Author-email: Markus Shepherd <markus@recommend.games>
License: MIT License
        
        Copyright (c) 2026 Markus Shepherd
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Games/Entertainment :: Board Games
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.12
Requires-Dist: gymnasium>=1.3.0
Requires-Dist: matplotlib
Requires-Dist: numpy
Requires-Dist: polars[pandas]
Requires-Dist: scipy
Requires-Dist: seaborn
Requires-Dist: tqdm
Description-Content-Type: text/markdown

# gymnasium-orchard

[Gymnasium](https://gymnasium.farama.org) environments for the cooperative dice game [Orchard (First Orchard)](https://www.haba.de/en_GB/toys/HABA-First-Orchard--lia-1004363/).

Background and analysis: [Recommend.Games blog](https://blog.recommend.games/posts/orchard/)

## Installation

```bash
pip install gymnasium-orchard
```

## Usage

```python
import gymnasium as gym
import orchard  # registers the environments

env = gym.make("Orchard-round")
obs, info = env.reset(seed=42)

terminated = False
while not terminated:
    action = env.action_space.sample()  # or your policy
    obs, reward, terminated, truncated, info = env.step(action)
```

## Environments

### `Orchard-round`

One `step()` = one die roll. The agent provides an action every step; it is only applied when the basket face is rolled.

### `Orchard-decision`

One `step()` = one basket decision. The environment advances automatically through fruit-tree and raven rolls, pausing only when a basket is rolled or the game ends. Cleaner for tabular RL methods.

## Observation space

Both environments use the same observation space:

| Key | Space | Description |
|---|---|---|
| `fruits` | `Box(int8, shape=(num_trees,))` | Fruits remaining on each tree |
| `raven` | `Discrete(raven_steps + 1)` | Raven's distance from the orchard |

## Action space

`Discrete(num_trees)` — which tree to pick from on a basket roll. Ignored on all other rolls; falls back to the tree with the most fruit if the chosen tree is empty.

## Reward

Sparse: `+1` on win (all fruit picked), `-1` on loss (raven reaches the orchard), `0` otherwise.

## Info dict

Both environments include an `action_mask` in `info` on every step:

```python
info["action_mask"]  # np.int8 array, 1 = tree has fruit, 0 = empty
```

`Orchard-round` additionally includes the die result:

```python
info["die"]             # int, face rolled
info["basket"]          # bool, whether it was a basket roll
info["action_applied"]  # bool, whether the action was used
```

`Orchard-decision` includes the rolls that were skipped:

```python
info["auto_rolls"]  # list[int], die values of non-basket rolls since last step
```

## Configuration

Pass an `OrchardGameConfig` to customise the game:

```python
from orchard.game import OrchardGameConfig

config = OrchardGameConfig(
    num_trees=4,
    fruits_per_tree=10,
    fruits_per_basket_roll=2,
    raven_steps=9,
)
env = gym.make("Orchard-round", config=config)
```

## Licence

MIT
