{"id":34674663,"url":"https://github.com/smallgig/pickomino","last_synced_at":"2026-01-19T10:00:58.516Z","repository":{"id":325683721,"uuid":"1040003303","full_name":"smallgig/Pickomino","owner":"smallgig","description":"Reinforcement Learning Environment with Gymnasium API","archived":false,"fork":false,"pushed_at":"2026-01-14T11:26:22.000Z","size":1088,"stargazers_count":1,"open_issues_count":45,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-14T12:19:48.072Z","etag":null,"topics":["api","ci","coverage-testing","gymnasium","mypy","numpy","pip","pre-commit","pycharm","pygame","pylint","pyright","pytest","pytest-cov","python","reinforcement-learning-environments","ruff","toml","xenon"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smallgig.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-18T10:06:32.000Z","updated_at":"2026-01-14T11:23:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/smallgig/Pickomino","commit_stats":null,"previous_names":["smallgig/pickomino"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/smallgig/Pickomino","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallgig%2FPickomino","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallgig%2FPickomino/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallgig%2FPickomino/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallgig%2FPickomino/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smallgig","download_url":"https://codeload.github.com/smallgig/Pickomino/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallgig%2FPickomino/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28565049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-19T08:53:44.001Z","status":"ssl_error","status_checked_at":"2026-01-19T08:52:40.245Z","response_time":67,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","ci","coverage-testing","gymnasium","mypy","numpy","pip","pre-commit","pycharm","pygame","pylint","pyright","pytest","pytest-cov","python","reinforcement-learning-environments","ruff","toml","xenon"],"created_at":"2025-12-24T20:01:08.620Z","updated_at":"2026-01-19T10:00:58.508Z","avatar_url":"https://github.com/smallgig.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pickomino-Env\n\n[![PyPI version](https://img.shields.io/pypi/v/pickomino-env.svg)](https://pypi.org/project/pickomino-env/)\n[![Python 3.8-3.12](https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://www.python.org/downloads/)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://docs.astral.sh/ruff/)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://pre-commit.com/)\n[![Type hints: Pyright](https://img.shields.io/badge/type%20hints-Pyright-brightgreen.svg)](https://github.com/microsoft/pyright)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Gymnasium](https://img.shields.io/badge/API-Gymnasium-brightgreen)](https://gymnasium.farama.org/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![pydocstyle](https://img.shields.io/badge/docstrings-pydocstyle-brightgreen)](http://www.pydocstyle.org/)\n[![Code complexity: radon](https://img.shields.io/badge/code%20complexity-radon-brightgreen)](https://radon.readthedocs.io/)\n[![Complexity: xenon](https://img.shields.io/badge/complexity-xenon-brightgreen)](https://xenon.readthedocs.io/)\n[![Pylint](https://img.shields.io/badge/pylint-checked-brightgreen)](https://pylint.pycqa.org/)\n[![Type hints: mypy](https://img.shields.io/badge/type%20hints-mypy-brightgreen.svg)](http://mypy-lang.org/)\n[![pytest: 95%+ coverage](https://img.shields.io/badge/pytest-95%25%2B%20coverage-brightgreen)](https://pytest.org/)\n\n## Description\n\nAn environment conforming to the **Gymnasium** API for the dice game **Pickomino (Heckmeck am Bratwurmeck)**\nGoal: train a Reinforcement Learning agent for optimal play. Meaning, decide which face of the dice to collect,\nwhen to roll and when to stop.\n\n## Action Space\n\nThe Action space is a tuple with two integers.\nTuple (int, int)\n\nAction = [dice_face (0-5), action_type (0=roll, 1=stop)].\n\n- 0-5: Face of the dice, which you want to take, where:\n    - 0 -\u003e face 1\n    - 1 -\u003e face 2\n    - 2 -\u003e face 3\n    - 3 -\u003e face 4\n    - 4 -\u003e face 5\n    - 5 -\u003e face worm\n\n\n- 0-1: Roll (0) or stop (1).\n\n## Observation Space\n\nThe observation is a `dict` with shape `(4,)` with the values corresponding to the following: dice, table and player.\n\n| Observation    | Min | Max | Shape             |\n|----------------|-----|-----|-------------------|\n| dice_collected | 0   | 8   | (6,)              |\n| dice_rolled    | 0   | 8   | (6,)              |\n| tiles_table    | 0   | 1   | (16,)             |\n| tile_players   | 0   | 36  | number_of_players |\n\n**Note:** There are eight dice to roll and collect. A die has six sides with the number of eyes one through\nfive, but a worm instead of a six.\nThe values correspond to the number of eyes, with the worm also having the value five (and not six!).\nThe 16 tiles are numbered 21 to 36 and have worm values from one to four in spread in four groups.\nThe game is for two to seven players. Here your Reinforcement Learning Agent is the first player. The\nother players are computer bots.\nThe bots play, according to a heuristic. When you create the environment,\nyou have to define the number of bots.\n\nFor a more detailed description of the rules, see the file pickomino-rulebook.pdf.\nYou can play the game online here: https://www.maartenpoirot.com/pickomino/.\nThe heuristic used by the bots is described here: https://frozenfractal.com/blog/2015/5/3/how-to-win-at-pickomino/.\n\n## Rewards\n\nThe goal is to collect tiles in a stack. The winner is the player, which at the end of the game has the most worms\non her tiles. For the Reinforcement Learning Agent a reward equal to the value\n(worms) of a tile is given when the tile is picked. For a failed attempt\n(see rulebook), a corresponding negative reward is given. When a bot steals your\ntile, no negative reward is given. Hence, the total reward at the end of the game\ncan be greater than the score.\n\n## Starting State\n\n* `dice_collected` = [0, 0, 0, 0, 0, 0].\n* `dice_rolled` = [3, 0, 1, 2, 0, 2] Random dice, sum = 8.\n* `tiles_table` = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].\n* `tile_players` = [0, 0, 0] (with number_of_bots = 2).\n\n## Episode End\n\nThe episode ends if one of the following occurs:\n\n1. Termination: If there are no more tiles to take on the table = Game Over.\n2. Termination: Action out of allowed range [0–5, 0-1].\n\n### Truncation\n\nTruncation: Attempt to break the rules, the game continues, and you have to give a new valid action.\n\n### Failed Attempt\n\nNote that a Failed Attempt means: If a tile is present, put it back on the table and get a negative reward.\nHowever, the game continues, so the Episode does not end.\n\n## Arguments\n\nThese must be specified.\n\n| Parameter        | Type        | Default | Description                                                                                |\n|------------------|-------------|---------|--------------------------------------------------------------------------------------------|\n| `number_of_bots` | int         | --      | Number of bot opponents (1-6) you want to play against                                     |\n| `render_mode`    | str or None | None    | Visualization mode:\u003cbr/\u003eNone (training),\u003cbr/\u003e\"human\" (display), or \"rgb_array\" (recording) |\n\n## Setup\n\n`pip install pickomino-env`\n\n## Usage example\n\n```python\nimport gymnasium as gym\n\n# Create environment\nenv = gym.make(\"Pickomino-v0\", render_mode=\"human\", number_of_bots=2)\n\n# Reset and get initial observation\nobs, info = env.reset(seed=42)\n\n# Run one episode\nterminated = False\ntruncated = False\ntotal_reward = 0\n\nwhile not terminated and not truncated:\n    # Agent selects action: (dice_face, roll_choice)\n    action = env.action_space.sample()  # Random action for demo\n\n    # Step environment\n    obs, reward, terminated, truncated, info = env.step(action)\n    total_reward += reward\n\n    if truncated:\n        print(f\"Invalid action: {info['explanation']}\")\n        break\n\nprint(f\"Episode finished. Total reward: {total_reward}\")\nenv.close()\n```\n\n## Resources\n\n- **Game Rules:** [Pickomino Rulebook](https://github.com/smallgig/Pickomino/blob/main/pickomino-rulebook.pdf)\n- **Play Online:** [Maarteen Poirot's Pickomino](https://www.maartenpoirot.com/pickomino/)\n- **Bot Strategy:** [How to Win at Pickomino](https://frozenfractal.com/blog/2015/5/3/how-to-win-at-pickomino/)\n- **Repository:** [smallgig/Pickomino](https://github.com/smallgig/Pickomino)\n- **Gymnasium:** [https://gymnasium.farama.org/](https://gymnasium.farama.org/)\n\n## License\n\nMIT License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmallgig%2Fpickomino","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmallgig%2Fpickomino","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmallgig%2Fpickomino/lists"}