numberlink 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. numberlink-0.1.0/.gitignore +24 -0
  2. numberlink-0.1.0/LICENSE +21 -0
  3. numberlink-0.1.0/PKG-INFO +203 -0
  4. numberlink-0.1.0/README.md +177 -0
  5. numberlink-0.1.0/numberlink/__init__.py +37 -0
  6. numberlink-0.1.0/numberlink/__main__.py +19 -0
  7. numberlink-0.1.0/numberlink/assets/levels/5x5_ha_4c_016.sol.json +1 -0
  8. numberlink-0.1.0/numberlink/assets/levels/5x5_ha_4c_016.txt +5 -0
  9. numberlink-0.1.0/numberlink/assets/levels/5x5_ha_4c_026.sol.json +1 -0
  10. numberlink-0.1.0/numberlink/assets/levels/5x5_ha_4c_026.txt +5 -0
  11. numberlink-0.1.0/numberlink/assets/levels/5x5_ra_4c_011.sol.json +1 -0
  12. numberlink-0.1.0/numberlink/assets/levels/5x5_ra_4c_011.txt +5 -0
  13. numberlink-0.1.0/numberlink/assets/levels/5x5_ra_4c_021.sol.json +1 -0
  14. numberlink-0.1.0/numberlink/assets/levels/5x5_ra_4c_021.txt +5 -0
  15. numberlink-0.1.0/numberlink/assets/levels/6x6_ha_5c_012.sol.json +1 -0
  16. numberlink-0.1.0/numberlink/assets/levels/6x6_ha_5c_012.txt +6 -0
  17. numberlink-0.1.0/numberlink/assets/levels/6x6_ha_5c_022.sol.json +1 -0
  18. numberlink-0.1.0/numberlink/assets/levels/6x6_ha_5c_022.txt +6 -0
  19. numberlink-0.1.0/numberlink/assets/levels/6x6_ra_5c_017.sol.json +1 -0
  20. numberlink-0.1.0/numberlink/assets/levels/6x6_ra_5c_017.txt +6 -0
  21. numberlink-0.1.0/numberlink/assets/levels/6x6_ra_5c_027.sol.json +1 -0
  22. numberlink-0.1.0/numberlink/assets/levels/6x6_ra_5c_027.txt +6 -0
  23. numberlink-0.1.0/numberlink/assets/levels/7x7_ha_6c_018.sol.json +1 -0
  24. numberlink-0.1.0/numberlink/assets/levels/7x7_ha_6c_018.txt +7 -0
  25. numberlink-0.1.0/numberlink/assets/levels/7x7_ha_6c_028.sol.json +1 -0
  26. numberlink-0.1.0/numberlink/assets/levels/7x7_ha_6c_028.txt +7 -0
  27. numberlink-0.1.0/numberlink/assets/levels/7x7_ra_6c_013.sol.json +1 -0
  28. numberlink-0.1.0/numberlink/assets/levels/7x7_ra_6c_013.txt +7 -0
  29. numberlink-0.1.0/numberlink/assets/levels/7x7_ra_6c_023.sol.json +1 -0
  30. numberlink-0.1.0/numberlink/assets/levels/7x7_ra_6c_023.txt +7 -0
  31. numberlink-0.1.0/numberlink/assets/levels/8x8_ha_6c_014.sol.json +1 -0
  32. numberlink-0.1.0/numberlink/assets/levels/8x8_ha_6c_014.txt +8 -0
  33. numberlink-0.1.0/numberlink/assets/levels/8x8_ha_6c_024.sol.json +1 -0
  34. numberlink-0.1.0/numberlink/assets/levels/8x8_ha_6c_024.txt +8 -0
  35. numberlink-0.1.0/numberlink/assets/levels/8x8_ra_6c_019.sol.json +1 -0
  36. numberlink-0.1.0/numberlink/assets/levels/8x8_ra_6c_019.txt +8 -0
  37. numberlink-0.1.0/numberlink/assets/levels/8x8_ra_6c_029.sol.json +1 -0
  38. numberlink-0.1.0/numberlink/assets/levels/8x8_ra_6c_029.txt +8 -0
  39. numberlink-0.1.0/numberlink/assets/levels/9x9_ha_7c_020.sol.json +1 -0
  40. numberlink-0.1.0/numberlink/assets/levels/9x9_ha_7c_020.txt +9 -0
  41. numberlink-0.1.0/numberlink/assets/levels/9x9_ha_7c_030.sol.json +1 -0
  42. numberlink-0.1.0/numberlink/assets/levels/9x9_ha_7c_030.txt +9 -0
  43. numberlink-0.1.0/numberlink/assets/levels/9x9_ra_7c_015.sol.json +1 -0
  44. numberlink-0.1.0/numberlink/assets/levels/9x9_ra_7c_015.txt +9 -0
  45. numberlink-0.1.0/numberlink/assets/levels/9x9_ra_7c_025.sol.json +1 -0
  46. numberlink-0.1.0/numberlink/assets/levels/9x9_ra_7c_025.txt +9 -0
  47. numberlink-0.1.0/numberlink/assets/numberlink-logo.png +0 -0
  48. numberlink-0.1.0/numberlink/cli.py +489 -0
  49. numberlink-0.1.0/numberlink/config.py +237 -0
  50. numberlink-0.1.0/numberlink/env.py +1441 -0
  51. numberlink-0.1.0/numberlink/generator.py +1308 -0
  52. numberlink-0.1.0/numberlink/level_setup.py +524 -0
  53. numberlink-0.1.0/numberlink/levels.py +302 -0
  54. numberlink-0.1.0/numberlink/main.py +24 -0
  55. numberlink-0.1.0/numberlink/number_render.py +381 -0
  56. numberlink-0.1.0/numberlink/py.typed +0 -0
  57. numberlink-0.1.0/numberlink/registration.py +62 -0
  58. numberlink-0.1.0/numberlink/render_utils.py +76 -0
  59. numberlink-0.1.0/numberlink/types.py +137 -0
  60. numberlink-0.1.0/numberlink/vector_env.py +1406 -0
  61. numberlink-0.1.0/numberlink/viewer.py +1425 -0
  62. numberlink-0.1.0/pyproject.toml +138 -0
@@ -0,0 +1,24 @@
1
+ **/*.DS_Store
2
+ **/*._.DS_Store
3
+ *.pyc
4
+ **/__pycache__/**
5
+ dist/
6
+ numberlink.egg-info/**
7
+ .pixi/**
8
+ .build-debug
9
+ *.conda
10
+ .mypy_cache
11
+ .ruff_cache
12
+ .tox
13
+ .coverage
14
+
15
+ # Exclude
16
+ !.pixi/config.toml
17
+ docs/_build/
18
+ # Generated _autosummary stubs and Sphinx doctrees
19
+ docs/_autosummary/
20
+ docs/.doctrees/
21
+ docs/apidocs/
22
+ output/
23
+ gifs/
24
+ !docs/_static/gifs/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Misagh Soltani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.4
2
+ Name: numberlink
3
+ Version: 0.1.0
4
+ Summary: NumberLink puzzle environment for Gymnasium
5
+ Project-URL: GitHub, https://github.com/misaghsoltani/NumberLink/
6
+ Project-URL: Documentation, https://misaghsoltani.github.io/NumberLink/
7
+ Author-email: Misagh Soltani <misaghsoltani@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: AI,Game,Gymnasium,NumberLink,OpenAI Gym,Puzzle,deep reinforcement learning,gym,heuristic search,pathfinding,planning,reinforcement learning,search
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: gymnasium<2,>=1.0
23
+ Requires-Dist: numpy<3,>=2.0
24
+ Requires-Dist: pygame<3,>=2.0
25
+ Description-Content-Type: text/markdown
26
+
27
+ # NumberLink Environment for Gymnasium
28
+
29
+ [![image](https://img.shields.io/pypi/v/numberlink.svg)](https://pypi.python.org/pypi/numberlink)
30
+ [![image](https://img.shields.io/pypi/l/numberlink.svg)](https://github.com/misaghsoltani/NumberLink/blob/main/LICENSE)
31
+ [![image](https://img.shields.io/pypi/pyversions/numberlink.svg)](https://pypi.python.org/pypi/numberlink)
32
+ [![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json&label=package%20manager)](https://pixi.sh)
33
+ [![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)
34
+ [![Checked with Pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)
35
+ ![Static Badge](https://img.shields.io/badge/statically%20typed-mypy-039dfc)
36
+ [![Build & Publish](https://github.com/misaghsoltani/NumberLink/actions/workflows/publish_to_pypi.yml/badge.svg)](https://github.com/misaghsoltani/NumberLink/actions/workflows/publish_to_pypi.yml)
37
+ [![Deploy Documentation](https://github.com/misaghsoltani/NumberLink/actions/workflows/docs.yml/badge.svg)](https://github.com/misaghsoltani/NumberLink/actions/workflows/docs.yml)
38
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/misaghsoltani/NumberLink/blob/main/notebooks/numberlink_quickstart.ipynb)
39
+
40
+ <br/>
41
+
42
+ <p align="center">
43
+ <img alt="NumberLink Logo" src="https://raw.githubusercontent.com/misaghsoltani/NumberLink/master/docs/_static/numberlink-logo.svg" />
44
+ </p>
45
+
46
+ <br/>
47
+
48
+ A Gymnasium environment for the NumberLink puzzle game.
49
+
50
+ ## Gameplay Rules
51
+
52
+ NumberLink connects matching endpoints with non overlapping paths on a grid.
53
+
54
+ NumberLink boards follow these invariants:
55
+
56
+ - Every pair of endpoints must be connected by a single path. Endpoints are enumerated in `numberlink.level_setup.LevelTemplate` and copied into the environment state.
57
+ - Paths cannot branch or reuse grid cells. The environment enforces this through the action mask returned by `numberlink.env.NumberLinkRGBEnv.reset` and `numberlink.env.NumberLinkRGBEnv.step`.
58
+ - Unless the chosen variant disables the requirement, every cell must belong to a path. Toggle this rule with `numberlink.config.VariantConfig.must_fill`.
59
+ - Bridge cells yield independent vertical and horizontal lanes governed by `numberlink.config.VariantConfig.bridges_enabled`.
60
+ - Diagonal moves are allowed only when `numberlink.config.VariantConfig.allow_diagonal` is set. Cell switching is controlled by `numberlink.config.VariantConfig.cell_switching_mode`.
61
+
62
+ ## Quick links
63
+
64
+ - Quick start: [Quick Start](#quick-start)
65
+ - Google Colab: [Open in Colab](https://colab.research.google.com/github/misaghsoltani/NumberLink/blob/main/notebooks/numberlink_quickstart.ipynb)
66
+ - Installation guide: [Installation - documentation site](https://misaghsoltani.github.io/NumberLink/installation.html)
67
+ - CLI reference: [CLI - documentation site](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.cli.html)
68
+ - Python usage (API snippets): [API reference - documentation site](https://misaghsoltani.github.io/NumberLink/apidocs/index.html)
69
+ - Citing this project: [Cite this project](#cite-this-work)
70
+ - Contact: [Contact](#contact)
71
+
72
+ ### Demo
73
+
74
+ | ![Must fill](https://raw.githubusercontent.com/misaghsoltani/DeepCubeAI/master/docs/_static/gifs/quickstart_must_fill.gif) | ![Cell switching](https://raw.githubusercontent.com/misaghsoltani/DeepCubeAI/master/docs/_static/gifs/quickstart_cell_switching.gif) | ![Path mode](https://raw.githubusercontent.com/misaghsoltani/DeepCubeAI/master/docs/_static/gifs/quickstart_path.gif) | ![Bridges and diagonal](https://raw.githubusercontent.com/misaghsoltani/DeepCubeAI/master/docs/_static/gifs/quickstart_bridges_diagonal.gif) |
75
+ | :------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------: |
76
+
77
+ ## Quick start
78
+
79
+ The [NumberLink documentation](https://misaghsoltani.github.io/NumberLink/) covers every workflow in detail. The
80
+ highlights below show the recommended [Gymnasium](https://gymnasium.farama.org/) >= 1.0 usage patterns. You can also try it out in the [Google Colab example](https://colab.research.google.com/github/misaghsoltani/NumberLink/blob/main/notebooks/numberlink_quickstart.ipynb).
81
+
82
+ ### Install from PyPI
83
+
84
+ #### Using pip
85
+
86
+ ```bash
87
+ pip install numberlink
88
+ ```
89
+
90
+ #### Install with [uv](https://docs.astral.sh/uv/)
91
+
92
+ ```bash
93
+ uv pip install numberlink
94
+ ```
95
+
96
+ See the [installation guide](https://misaghsoltani.github.io/NumberLink/installation.html) for Pixi, Conda, and source build instructions.
97
+
98
+ ### Create a single environment
99
+
100
+ ```python
101
+ import gymnasium as gym
102
+
103
+ # Gymnasium discovers NumberLinkRGB-v0 from the package entry points
104
+ env = gym.make("NumberLinkRGB-v0", render_mode="rgb_array")
105
+
106
+ observation, info = env.reset(seed=42)
107
+ action_mask = info["action_mask"]
108
+
109
+ terminated = False
110
+ truncated = False
111
+ while not (terminated or truncated):
112
+ action = env.action_space.sample(mask=action_mask)
113
+ observation, reward, terminated, truncated, info = env.step(action)
114
+ action_mask = info["action_mask"]
115
+
116
+ env.close()
117
+ ```
118
+
119
+ Configuration objects such as
120
+ [GeneratorConfig](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.config.html#numberlink.config.GeneratorConfig),
121
+ [VariantConfig](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.config.html#numberlink.config.VariantConfig),
122
+ and [RenderConfig](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.config.html#numberlink.config.RenderConfig)
123
+ customize generation, gameplay rules, and rendering. Examples live in the
124
+ [usage guide](https://misaghsoltani.github.io/NumberLink/usage.html) and the
125
+ [level setup module](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.level_setup.html).
126
+
127
+ ### Run vectorized environments
128
+
129
+ ```python
130
+ import gymnasium as gym
131
+ from numberlink import GeneratorConfig
132
+
133
+ vec_env = gym.make_vec(
134
+ "NumberLinkRGB-v0",
135
+ num_envs=4,
136
+ render_mode="rgb_array",
137
+ generator=GeneratorConfig(width=6, height=6, colors=4),
138
+ )
139
+
140
+ observations, infos = vec_env.reset(seed=0)
141
+ actions = [vec_env.single_action_space.sample(mask=mask) for mask in infos["action_mask"]]
142
+ observations, rewards, terminated, truncated, infos = vec_env.step(actions)
143
+ vec_env.close()
144
+ ```
145
+
146
+ Gymnasium auto resets terminated slots when the vector environment is configured with the default autoreset mode. See
147
+ the [vector API section of the docs](https://misaghsoltani.github.io/NumberLink/usage.html#vector-environment) for
148
+ batched workflows.
149
+
150
+ ### Human render mode
151
+
152
+ ```python
153
+ import gymnasium as gym
154
+ import numberlink
155
+ from numberlink.viewer import NumberLinkViewer
156
+
157
+ numberlink.register_numberlink_v0()
158
+ env = gym.make("NumberLinkRGB-v0", render_mode="human")
159
+ viewer = NumberLinkViewer(env)
160
+ viewer.loop()
161
+ ```
162
+
163
+ The pygame viewer mirrors the CLI command shown in
164
+ [examples/run_human.py](https://github.com/misaghsoltani/NumberLink/blob/main/examples/run_human.py) and is documented
165
+ at [viewer API](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.viewer.html).
166
+
167
+ ## Auto-registration
168
+
169
+ Recommended usage is to install the package (for example via PyPI), and Gymnasium then discovers the environments via
170
+ the package's entry-points and you can call `gymnasium.make(...)` / `gymnasium.make_vec(...)` directly. If you need to
171
+ register the env id in-process (for development or interactive use), call:
172
+
173
+ ```python
174
+ import numberlink
175
+ numberlink.register_numberlink_v0()
176
+ ```
177
+
178
+ See the docs for details on packaging entry-points and the registration helper:
179
+ [https://misaghsoltani.github.io/NumberLink/usage.html](https://misaghsoltani.github.io/NumberLink/usage.html)
180
+ and [https://misaghsoltani.github.io/NumberLink/apidocs/index.html](https://misaghsoltani.github.io/NumberLink/apidocs/index.html).
181
+
182
+ ## License
183
+
184
+ MIT License - see [LICENSE](https://github.com/misaghsoltani/NumberLink/blob/main/LICENSE).
185
+
186
+ ## Cite this work
187
+
188
+ If you use NumberLink in your research, please cite:
189
+
190
+ <!-- CITATION-BIBTEX:START -->
191
+ ```bibtex
192
+ @misc{numberlinkenv2025soltani,
193
+ author = {Soltani, Misagh},
194
+ title = {NumberLink Puzzle},
195
+ url = {https://misaghsoltani.github.io/NumberLink},
196
+ year = {2025}
197
+ }
198
+ ```
199
+ <!-- CITATION-BIBTEX:END -->
200
+
201
+ ## Contact
202
+
203
+ If you have any questions or issues, please contact Misagh Soltani ([misaghsoltani@gmail.com](mailto:misaghsoltani@gmail.com))
@@ -0,0 +1,177 @@
1
+ # NumberLink Environment for Gymnasium
2
+
3
+ [![image](https://img.shields.io/pypi/v/numberlink.svg)](https://pypi.python.org/pypi/numberlink)
4
+ [![image](https://img.shields.io/pypi/l/numberlink.svg)](https://github.com/misaghsoltani/NumberLink/blob/main/LICENSE)
5
+ [![image](https://img.shields.io/pypi/pyversions/numberlink.svg)](https://pypi.python.org/pypi/numberlink)
6
+ [![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json&label=package%20manager)](https://pixi.sh)
7
+ [![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)
8
+ [![Checked with Pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)
9
+ ![Static Badge](https://img.shields.io/badge/statically%20typed-mypy-039dfc)
10
+ [![Build & Publish](https://github.com/misaghsoltani/NumberLink/actions/workflows/publish_to_pypi.yml/badge.svg)](https://github.com/misaghsoltani/NumberLink/actions/workflows/publish_to_pypi.yml)
11
+ [![Deploy Documentation](https://github.com/misaghsoltani/NumberLink/actions/workflows/docs.yml/badge.svg)](https://github.com/misaghsoltani/NumberLink/actions/workflows/docs.yml)
12
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/misaghsoltani/NumberLink/blob/main/notebooks/numberlink_quickstart.ipynb)
13
+
14
+ <br/>
15
+
16
+ <p align="center">
17
+ <img alt="NumberLink Logo" src="https://raw.githubusercontent.com/misaghsoltani/NumberLink/master/docs/_static/numberlink-logo.svg" />
18
+ </p>
19
+
20
+ <br/>
21
+
22
+ A Gymnasium environment for the NumberLink puzzle game.
23
+
24
+ ## Gameplay Rules
25
+
26
+ NumberLink connects matching endpoints with non overlapping paths on a grid.
27
+
28
+ NumberLink boards follow these invariants:
29
+
30
+ - Every pair of endpoints must be connected by a single path. Endpoints are enumerated in `numberlink.level_setup.LevelTemplate` and copied into the environment state.
31
+ - Paths cannot branch or reuse grid cells. The environment enforces this through the action mask returned by `numberlink.env.NumberLinkRGBEnv.reset` and `numberlink.env.NumberLinkRGBEnv.step`.
32
+ - Unless the chosen variant disables the requirement, every cell must belong to a path. Toggle this rule with `numberlink.config.VariantConfig.must_fill`.
33
+ - Bridge cells yield independent vertical and horizontal lanes governed by `numberlink.config.VariantConfig.bridges_enabled`.
34
+ - Diagonal moves are allowed only when `numberlink.config.VariantConfig.allow_diagonal` is set. Cell switching is controlled by `numberlink.config.VariantConfig.cell_switching_mode`.
35
+
36
+ ## Quick links
37
+
38
+ - Quick start: [Quick Start](#quick-start)
39
+ - Google Colab: [Open in Colab](https://colab.research.google.com/github/misaghsoltani/NumberLink/blob/main/notebooks/numberlink_quickstart.ipynb)
40
+ - Installation guide: [Installation - documentation site](https://misaghsoltani.github.io/NumberLink/installation.html)
41
+ - CLI reference: [CLI - documentation site](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.cli.html)
42
+ - Python usage (API snippets): [API reference - documentation site](https://misaghsoltani.github.io/NumberLink/apidocs/index.html)
43
+ - Citing this project: [Cite this project](#cite-this-work)
44
+ - Contact: [Contact](#contact)
45
+
46
+ ### Demo
47
+
48
+ | ![Must fill](https://raw.githubusercontent.com/misaghsoltani/DeepCubeAI/master/docs/_static/gifs/quickstart_must_fill.gif) | ![Cell switching](https://raw.githubusercontent.com/misaghsoltani/DeepCubeAI/master/docs/_static/gifs/quickstart_cell_switching.gif) | ![Path mode](https://raw.githubusercontent.com/misaghsoltani/DeepCubeAI/master/docs/_static/gifs/quickstart_path.gif) | ![Bridges and diagonal](https://raw.githubusercontent.com/misaghsoltani/DeepCubeAI/master/docs/_static/gifs/quickstart_bridges_diagonal.gif) |
49
+ | :------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------: |
50
+
51
+ ## Quick start
52
+
53
+ The [NumberLink documentation](https://misaghsoltani.github.io/NumberLink/) covers every workflow in detail. The
54
+ highlights below show the recommended [Gymnasium](https://gymnasium.farama.org/) >= 1.0 usage patterns. You can also try it out in the [Google Colab example](https://colab.research.google.com/github/misaghsoltani/NumberLink/blob/main/notebooks/numberlink_quickstart.ipynb).
55
+
56
+ ### Install from PyPI
57
+
58
+ #### Using pip
59
+
60
+ ```bash
61
+ pip install numberlink
62
+ ```
63
+
64
+ #### Install with [uv](https://docs.astral.sh/uv/)
65
+
66
+ ```bash
67
+ uv pip install numberlink
68
+ ```
69
+
70
+ See the [installation guide](https://misaghsoltani.github.io/NumberLink/installation.html) for Pixi, Conda, and source build instructions.
71
+
72
+ ### Create a single environment
73
+
74
+ ```python
75
+ import gymnasium as gym
76
+
77
+ # Gymnasium discovers NumberLinkRGB-v0 from the package entry points
78
+ env = gym.make("NumberLinkRGB-v0", render_mode="rgb_array")
79
+
80
+ observation, info = env.reset(seed=42)
81
+ action_mask = info["action_mask"]
82
+
83
+ terminated = False
84
+ truncated = False
85
+ while not (terminated or truncated):
86
+ action = env.action_space.sample(mask=action_mask)
87
+ observation, reward, terminated, truncated, info = env.step(action)
88
+ action_mask = info["action_mask"]
89
+
90
+ env.close()
91
+ ```
92
+
93
+ Configuration objects such as
94
+ [GeneratorConfig](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.config.html#numberlink.config.GeneratorConfig),
95
+ [VariantConfig](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.config.html#numberlink.config.VariantConfig),
96
+ and [RenderConfig](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.config.html#numberlink.config.RenderConfig)
97
+ customize generation, gameplay rules, and rendering. Examples live in the
98
+ [usage guide](https://misaghsoltani.github.io/NumberLink/usage.html) and the
99
+ [level setup module](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.level_setup.html).
100
+
101
+ ### Run vectorized environments
102
+
103
+ ```python
104
+ import gymnasium as gym
105
+ from numberlink import GeneratorConfig
106
+
107
+ vec_env = gym.make_vec(
108
+ "NumberLinkRGB-v0",
109
+ num_envs=4,
110
+ render_mode="rgb_array",
111
+ generator=GeneratorConfig(width=6, height=6, colors=4),
112
+ )
113
+
114
+ observations, infos = vec_env.reset(seed=0)
115
+ actions = [vec_env.single_action_space.sample(mask=mask) for mask in infos["action_mask"]]
116
+ observations, rewards, terminated, truncated, infos = vec_env.step(actions)
117
+ vec_env.close()
118
+ ```
119
+
120
+ Gymnasium auto resets terminated slots when the vector environment is configured with the default autoreset mode. See
121
+ the [vector API section of the docs](https://misaghsoltani.github.io/NumberLink/usage.html#vector-environment) for
122
+ batched workflows.
123
+
124
+ ### Human render mode
125
+
126
+ ```python
127
+ import gymnasium as gym
128
+ import numberlink
129
+ from numberlink.viewer import NumberLinkViewer
130
+
131
+ numberlink.register_numberlink_v0()
132
+ env = gym.make("NumberLinkRGB-v0", render_mode="human")
133
+ viewer = NumberLinkViewer(env)
134
+ viewer.loop()
135
+ ```
136
+
137
+ The pygame viewer mirrors the CLI command shown in
138
+ [examples/run_human.py](https://github.com/misaghsoltani/NumberLink/blob/main/examples/run_human.py) and is documented
139
+ at [viewer API](https://misaghsoltani.github.io/NumberLink/apidocs/numberlink/numberlink.viewer.html).
140
+
141
+ ## Auto-registration
142
+
143
+ Recommended usage is to install the package (for example via PyPI), and Gymnasium then discovers the environments via
144
+ the package's entry-points and you can call `gymnasium.make(...)` / `gymnasium.make_vec(...)` directly. If you need to
145
+ register the env id in-process (for development or interactive use), call:
146
+
147
+ ```python
148
+ import numberlink
149
+ numberlink.register_numberlink_v0()
150
+ ```
151
+
152
+ See the docs for details on packaging entry-points and the registration helper:
153
+ [https://misaghsoltani.github.io/NumberLink/usage.html](https://misaghsoltani.github.io/NumberLink/usage.html)
154
+ and [https://misaghsoltani.github.io/NumberLink/apidocs/index.html](https://misaghsoltani.github.io/NumberLink/apidocs/index.html).
155
+
156
+ ## License
157
+
158
+ MIT License - see [LICENSE](https://github.com/misaghsoltani/NumberLink/blob/main/LICENSE).
159
+
160
+ ## Cite this work
161
+
162
+ If you use NumberLink in your research, please cite:
163
+
164
+ <!-- CITATION-BIBTEX:START -->
165
+ ```bibtex
166
+ @misc{numberlinkenv2025soltani,
167
+ author = {Soltani, Misagh},
168
+ title = {NumberLink Puzzle},
169
+ url = {https://misaghsoltani.github.io/NumberLink},
170
+ year = {2025}
171
+ }
172
+ ```
173
+ <!-- CITATION-BIBTEX:END -->
174
+
175
+ ## Contact
176
+
177
+ If you have any questions or issues, please contact Misagh Soltani ([misaghsoltani@gmail.com](mailto:misaghsoltani@gmail.com))
@@ -0,0 +1,37 @@
1
+ """NumberLink Environment Package for Reinforcement Learning, built on Gymnasium.
2
+
3
+ The package exposes configuration dataclasses, environment classes, and the ``LEVELS`` mapping of built-in levels.
4
+ Import these symbols for your use or to register the environment using :func:`register_numberlink_v0`.
5
+
6
+ By default the package does not automatically register Gymnasium ids on import. Library consumers should prefer
7
+ explicit registration via ``numberlink.register_numberlink_v0()``. When installed from PyPI the package also
8
+ exposes packaging entry-points (``project.entry-points."gymnasium.envs"``) so Gymnasium can auto-discover and
9
+ load the environment without an explicit registration call. See the project ``pyproject.toml`` for the
10
+ ``gymnasium.envs`` entry-point names.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from .config import GeneratorConfig, RenderConfig, RewardConfig, VariantConfig
16
+ from .env import NumberLinkRGBEnv
17
+ from .levels import LEVELS
18
+ from .registration import register_numberlink_v0
19
+ from .vector_env import NumberLinkRGBVectorEnv
20
+ from .viewer import NumberLinkViewer
21
+
22
+ __version__ = "0.1.0"
23
+ __author__ = "Misagh Soltani"
24
+
25
+ __all__: list[str] = [
26
+ "__version__",
27
+ "__author__",
28
+ "NumberLinkRGBEnv",
29
+ "register_numberlink_v0",
30
+ "GeneratorConfig",
31
+ "VariantConfig",
32
+ "RewardConfig",
33
+ "RenderConfig",
34
+ "LEVELS",
35
+ "NumberLinkViewer",
36
+ "NumberLinkRGBVectorEnv",
37
+ ]
@@ -0,0 +1,19 @@
1
+ """Module entry for the package command-line interface.
2
+
3
+ Running ``python -m numberlink`` invokes the CLI implemented in :mod:`numberlink.cli`.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import sys
9
+
10
+ from .cli import main as cli_main
11
+
12
+
13
+ def run() -> None:
14
+ """Entrypoint used by the ``-m`` switch."""
15
+ raise SystemExit(cli_main(sys.argv[1:]))
16
+
17
+
18
+ if __name__ == "__main__":
19
+ run()
@@ -0,0 +1 @@
1
+ [[[1,3],[1,2],[2,2]],[[0,0],[0,1],[0,2],[0,3],[0,4]],[[1,4],[2,4],[3,4],[4,4],[4,3],[4,2],[4,1],[4,0],[3,0],[2,0]],[[1,0],[1,1],[2,1],[3,1],[3,2],[3,3],[2,3]]]
@@ -0,0 +1,5 @@
1
+ B...B
2
+ D..AC
3
+ C.AD.
4
+ .....
5
+ .....
@@ -0,0 +1 @@
1
+ [[[0,0],[0,1],[1,1]],[[0,2],[0,3],[0,4],[1,4],[2,4],[3,4],[4,4],[4,3],[4,2],[4,1]],[[1,2],[2,2],[2,1],[2,0],[1,0]],[[4,0],[3,0],[3,1],[3,2],[3,3],[2,3],[1,3]]]
@@ -0,0 +1,5 @@
1
+ A.B..
2
+ CACD.
3
+ .....
4
+ .....
5
+ DB...
@@ -0,0 +1 @@
1
+ [[[3,1],[2,1],[1,1],[0,1]],[[3,0],[4,0],[4,1],[4,2]],[[1,4],[2,4],[3,4],[4,4],[4,3]],[[0,4],[0,3],[1,3],[2,3],[2,2],[1,2]]]
@@ -0,0 +1,5 @@
1
+ .A..D
2
+ ..D.C
3
+ .....
4
+ BA...
5
+ ..BC.
@@ -0,0 +1 @@
1
+ [[[1,0],[2,0],[3,0],[4,0]],[[3,1],[3,2],[3,3],[4,3],[4,4]],[[2,4],[2,3],[2,2],[2,1]],[[0,0],[0,1],[0,2],[0,3]]]
@@ -0,0 +1,5 @@
1
+ D..D.
2
+ A....
3
+ .C..C
4
+ .B...
5
+ A...B
@@ -0,0 +1 @@
1
+ [[[3,2],[2,2],[2,3]],[[5,5],[5,4],[5,3],[5,2],[5,1],[5,0],[4,0],[3,0],[2,0],[1,0],[0,0],[0,1]],[[1,2],[1,3],[1,4],[2,4],[3,4],[3,3]],[[4,1],[4,2],[4,3],[4,4],[4,5],[3,5],[2,5],[1,5],[0,5],[0,4],[0,3],[0,2]],[[1,1],[2,1],[3,1]]]
@@ -0,0 +1,6 @@
1
+ .BD...
2
+ .EC...
3
+ ...A..
4
+ .EAC..
5
+ .D....
6
+ .....B
@@ -0,0 +1 @@
1
+ [[[4,1],[3,1],[3,0],[2,0],[1,0],[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[1,5],[2,5],[3,5],[4,5],[5,5],[5,4],[5,3],[4,3]],[[4,4],[3,4],[3,3],[3,2],[2,2]],[[2,1],[1,1],[1,2],[1,3]],[[4,2],[5,2],[5,1],[5,0],[4,0]],[[1,4],[2,4],[2,3]]]
@@ -0,0 +1,6 @@
1
+ ......
2
+ ...CE.
3
+ .CBE..
4
+ ......
5
+ DADAB.
6
+ ......
@@ -0,0 +1 @@
1
+ [[[2,5],[1,5],[1,4],[1,3],[0,3]],[[0,2],[0,1],[1,1],[2,1]],[[4,3],[3,3],[3,2],[3,1]],[[3,0],[4,0],[4,1],[5,1]],[[5,3],[5,4],[4,4],[4,5],[3,5],[2,5],[2,4]]]
@@ -0,0 +1,6 @@
1
+ ..BA..
2
+ ......
3
+ .B..EA
4
+ DC....
5
+ ...C..
6
+ .D.E..
@@ -0,0 +1 @@
1
+ [[[0,0],[1,0],[2,0],[3,0],[3,1],[2,1],[2,2]],[[3,0],[4,0],[4,1],[4,2],[5,2],[5,1]],[[2,4],[1,4],[1,3],[1,2],[1,1]],[[0,5],[0,4],[0,3],[0,2]],[[5,3],[4,3],[3,3],[3,4]]]
@@ -0,0 +1,6 @@
1
+ A.D..D
2
+ .C....
3
+ ..A.C.
4
+ B...E.
5
+ ......
6
+ .B.E..
@@ -0,0 +1 @@
1
+ [[[1,5],[0,5],[0,6]],[[2,3],[1,3],[1,2],[1,1],[2,1],[3,1],[4,1],[5,1],[5,2],[5,3],[5,4]],[[3,6],[4,6],[4,5],[5,5]],[[5,6],[6,6],[6,5],[6,4],[6,3],[6,2],[6,1],[6,0],[5,0],[4,0],[3,0],[2,0],[1,0],[0,0],[0,1],[0,2],[0,3],[0,4],[1,4],[2,4],[3,4],[3,3],[3,2],[2,2]],[[1,6],[2,6],[2,5],[3,5]],[[4,4],[4,3],[4,2]]]
@@ -0,0 +1,7 @@
1
+ ......A
2
+ .....AE
3
+ ..DB...
4
+ .....EC
5
+ ..F.F..
6
+ ....BCD
7
+ .......
@@ -0,0 +1 @@
1
+ [[[2,3],[3,3],[3,4]],[[6,2],[5,2],[5,3],[5,4],[5,5],[4,5]],[[2,4],[2,5],[3,5]],[[6,1],[5,1],[4,1],[3,1],[2,1],[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[2,6],[3,6],[4,6],[5,6],[6,6],[6,5],[6,4],[6,3]],[[0,6],[0,5],[0,4],[0,3],[0,2],[0,1],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0]],[[4,4],[4,3],[4,2],[3,2],[2,2]]]
@@ -0,0 +1,7 @@
1
+ ......E
2
+ .......
3
+ ..FAC..
4
+ ....AC.
5
+ ....FB.
6
+ .......
7
+ EDBD...
@@ -0,0 +1 @@
1
+ [[[2,5],[3,5],[3,6],[4,6]],[[0,6],[0,5],[1,5],[1,6],[2,6],[2,5],[2,4]],[[1,2],[0,2],[0,3],[0,4]],[[6,0],[6,1],[6,2],[6,3],[5,3]],[[0,0],[0,1],[1,1],[1,2],[2,2],[3,2]],[[4,1],[3,1],[2,1],[2,0]]]
@@ -0,0 +1,7 @@
1
+ E...C.B
2
+ ..C....
3
+ F...BA.
4
+ ..E....
5
+ .F....A
6
+ ...D...
7
+ D......
@@ -0,0 +1 @@
1
+ [[[5,4],[6,4],[6,5],[6,6]],[[3,6],[3,5],[4,5],[5,5]],[[4,3],[3,3],[3,4],[2,4]],[[6,1],[6,2],[6,3],[5,3]],[[4,2],[5,2],[5,1],[5,0]],[[5,6],[4,6],[3,6],[2,6]]]
@@ -0,0 +1,7 @@
1
+ .......
2
+ .......
3
+ ....C.F
4
+ ......B
5
+ ..EC...
6
+ E..DABF
7
+ .D....A
@@ -0,0 +1 @@
1
+ [[[7,5],[6,5],[6,6],[5,6],[4,6],[3,6],[2,6],[1,6],[1,5],[1,4],[1,3],[1,2]],[[1,1],[2,1],[3,1],[4,1],[5,1],[6,1],[6,2],[6,3],[6,4],[5,4],[5,5],[4,5],[3,5]],[[7,4],[7,3],[7,2],[7,1],[7,0],[6,0],[5,0],[4,0],[3,0],[2,0],[1,0],[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[1,7],[2,7],[3,7],[4,7],[5,7],[6,7],[7,7],[7,6]],[[2,5],[2,4],[3,4],[4,4],[4,3]],[[5,3],[5,2],[4,2],[3,2]],[[2,2],[2,3],[3,3]]]
@@ -0,0 +1,8 @@
1
+ ........
2
+ .BA.....
3
+ ..F..D..
4
+ ..EF.B..
5
+ ...D....
6
+ ...E....
7
+ ........
8
+ ....CAC.
@@ -0,0 +1 @@
1
+ [[[0,6],[0,5],[0,4],[0,3],[0,2],[0,1],[1,1],[2,1],[3,1],[4,1],[5,1],[6,1],[6,2],[6,3],[6,4],[6,5],[6,6],[5,6],[4,6],[3,6],[2,6]],[[1,6],[1,5],[2,5],[3,5],[4,5],[5,5],[5,4],[5,3],[5,2],[4,2]],[[4,3],[4,4],[3,4]],[[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[7,1],[7,2],[7,3],[7,4],[7,5],[7,6],[7,7],[6,7],[5,7],[4,7],[3,7],[2,7],[1,7],[0,7]],[[1,4],[2,4],[2,3]],[[3,3],[3,2],[2,2],[1,2],[1,3]]]
@@ -0,0 +1,8 @@
1
+ D.....AD
2
+ ...FE.B.
3
+ ...E..A.
4
+ ...FC...
5
+ ..BC....
6
+ ........
7
+ ........
8
+ ........
@@ -0,0 +1 @@
1
+ [[[3,7],[3,6],[2,6],[1,6],[1,7],[0,7]],[[7,0],[6,0],[5,0],[5,1]],[[7,6],[6,6],[6,7],[5,7],[5,6],[5,5]],[[7,7],[7,6],[7,5],[6,5]],[[4,2],[3,2],[3,1],[3,0]],[[2,2],[2,3],[3,3],[4,3],[4,4],[3,4]]]