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.
- numberlink-0.1.0/.gitignore +24 -0
- numberlink-0.1.0/LICENSE +21 -0
- numberlink-0.1.0/PKG-INFO +203 -0
- numberlink-0.1.0/README.md +177 -0
- numberlink-0.1.0/numberlink/__init__.py +37 -0
- numberlink-0.1.0/numberlink/__main__.py +19 -0
- numberlink-0.1.0/numberlink/assets/levels/5x5_ha_4c_016.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/5x5_ha_4c_016.txt +5 -0
- numberlink-0.1.0/numberlink/assets/levels/5x5_ha_4c_026.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/5x5_ha_4c_026.txt +5 -0
- numberlink-0.1.0/numberlink/assets/levels/5x5_ra_4c_011.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/5x5_ra_4c_011.txt +5 -0
- numberlink-0.1.0/numberlink/assets/levels/5x5_ra_4c_021.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/5x5_ra_4c_021.txt +5 -0
- numberlink-0.1.0/numberlink/assets/levels/6x6_ha_5c_012.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/6x6_ha_5c_012.txt +6 -0
- numberlink-0.1.0/numberlink/assets/levels/6x6_ha_5c_022.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/6x6_ha_5c_022.txt +6 -0
- numberlink-0.1.0/numberlink/assets/levels/6x6_ra_5c_017.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/6x6_ra_5c_017.txt +6 -0
- numberlink-0.1.0/numberlink/assets/levels/6x6_ra_5c_027.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/6x6_ra_5c_027.txt +6 -0
- numberlink-0.1.0/numberlink/assets/levels/7x7_ha_6c_018.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/7x7_ha_6c_018.txt +7 -0
- numberlink-0.1.0/numberlink/assets/levels/7x7_ha_6c_028.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/7x7_ha_6c_028.txt +7 -0
- numberlink-0.1.0/numberlink/assets/levels/7x7_ra_6c_013.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/7x7_ra_6c_013.txt +7 -0
- numberlink-0.1.0/numberlink/assets/levels/7x7_ra_6c_023.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/7x7_ra_6c_023.txt +7 -0
- numberlink-0.1.0/numberlink/assets/levels/8x8_ha_6c_014.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/8x8_ha_6c_014.txt +8 -0
- numberlink-0.1.0/numberlink/assets/levels/8x8_ha_6c_024.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/8x8_ha_6c_024.txt +8 -0
- numberlink-0.1.0/numberlink/assets/levels/8x8_ra_6c_019.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/8x8_ra_6c_019.txt +8 -0
- numberlink-0.1.0/numberlink/assets/levels/8x8_ra_6c_029.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/8x8_ra_6c_029.txt +8 -0
- numberlink-0.1.0/numberlink/assets/levels/9x9_ha_7c_020.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/9x9_ha_7c_020.txt +9 -0
- numberlink-0.1.0/numberlink/assets/levels/9x9_ha_7c_030.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/9x9_ha_7c_030.txt +9 -0
- numberlink-0.1.0/numberlink/assets/levels/9x9_ra_7c_015.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/9x9_ra_7c_015.txt +9 -0
- numberlink-0.1.0/numberlink/assets/levels/9x9_ra_7c_025.sol.json +1 -0
- numberlink-0.1.0/numberlink/assets/levels/9x9_ra_7c_025.txt +9 -0
- numberlink-0.1.0/numberlink/assets/numberlink-logo.png +0 -0
- numberlink-0.1.0/numberlink/cli.py +489 -0
- numberlink-0.1.0/numberlink/config.py +237 -0
- numberlink-0.1.0/numberlink/env.py +1441 -0
- numberlink-0.1.0/numberlink/generator.py +1308 -0
- numberlink-0.1.0/numberlink/level_setup.py +524 -0
- numberlink-0.1.0/numberlink/levels.py +302 -0
- numberlink-0.1.0/numberlink/main.py +24 -0
- numberlink-0.1.0/numberlink/number_render.py +381 -0
- numberlink-0.1.0/numberlink/py.typed +0 -0
- numberlink-0.1.0/numberlink/registration.py +62 -0
- numberlink-0.1.0/numberlink/render_utils.py +76 -0
- numberlink-0.1.0/numberlink/types.py +137 -0
- numberlink-0.1.0/numberlink/vector_env.py +1406 -0
- numberlink-0.1.0/numberlink/viewer.py +1425 -0
- 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/
|
numberlink-0.1.0/LICENSE
ADDED
|
@@ -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
|
+
[](https://pypi.python.org/pypi/numberlink)
|
|
30
|
+
[](https://github.com/misaghsoltani/NumberLink/blob/main/LICENSE)
|
|
31
|
+
[](https://pypi.python.org/pypi/numberlink)
|
|
32
|
+
[](https://pixi.sh)
|
|
33
|
+
[](https://github.com/astral-sh/ruff)
|
|
34
|
+
[](https://microsoft.github.io/pyright/)
|
|
35
|
+

|
|
36
|
+
[](https://github.com/misaghsoltani/NumberLink/actions/workflows/publish_to_pypi.yml)
|
|
37
|
+
[](https://github.com/misaghsoltani/NumberLink/actions/workflows/docs.yml)
|
|
38
|
+
[](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
|
+
|  |  |  |  |
|
|
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
|
+
[](https://pypi.python.org/pypi/numberlink)
|
|
4
|
+
[](https://github.com/misaghsoltani/NumberLink/blob/main/LICENSE)
|
|
5
|
+
[](https://pypi.python.org/pypi/numberlink)
|
|
6
|
+
[](https://pixi.sh)
|
|
7
|
+
[](https://github.com/astral-sh/ruff)
|
|
8
|
+
[](https://microsoft.github.io/pyright/)
|
|
9
|
+

|
|
10
|
+
[](https://github.com/misaghsoltani/NumberLink/actions/workflows/publish_to_pypi.yml)
|
|
11
|
+
[](https://github.com/misaghsoltani/NumberLink/actions/workflows/docs.yml)
|
|
12
|
+
[](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
|
+
|  |  |  |  |
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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]]]
|