par-infini-sweeper 0.2.9__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.
- par_infini_sweeper-0.2.9/.gitignore +81 -0
- par_infini_sweeper-0.2.9/LICENSE +21 -0
- par_infini_sweeper-0.2.9/PKG-INFO +214 -0
- par_infini_sweeper-0.2.9/README.md +149 -0
- par_infini_sweeper-0.2.9/pyproject.toml +119 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/__init__.py +31 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/__main__.py +52 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/data_structures.py +690 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/db.py +232 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/db_migrations.py +98 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/__init__.py +5 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/difficulty_dialog.py +86 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/error_dialog.py +28 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/help_dialog.py +75 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/information.py +15 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/input_dialog.py +106 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/password_dialog.py +88 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/text_dialog.py +79 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/theme_dialog.py +107 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/dialogs/yes_no_dialog.py +112 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/enums.py +13 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/help.md +35 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/main_grid.py +215 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/minesweeper_app.py +111 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/pim.tcss +29 -0
- par_infini_sweeper-0.2.9/src/par_infini_sweeper/py.typed +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
### PythonVanilla template
|
|
2
|
+
# Byte-compiled / optimized / DLL files
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.py[cod]
|
|
5
|
+
*$py.class
|
|
6
|
+
|
|
7
|
+
# C extensions
|
|
8
|
+
*.so
|
|
9
|
+
|
|
10
|
+
# Distribution / packaging
|
|
11
|
+
.Python
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# Installer logs
|
|
30
|
+
pip-log.txt
|
|
31
|
+
pip-delete-this-directory.txt
|
|
32
|
+
|
|
33
|
+
# Unit test / coverage reports
|
|
34
|
+
htmlcov/
|
|
35
|
+
.tox/
|
|
36
|
+
.nox/
|
|
37
|
+
.coverage
|
|
38
|
+
.coverage.*
|
|
39
|
+
.cache
|
|
40
|
+
nosetests.xml
|
|
41
|
+
coverage.xml
|
|
42
|
+
*.cover
|
|
43
|
+
*.py,cover
|
|
44
|
+
.hypothesis/
|
|
45
|
+
.pytest_cache/
|
|
46
|
+
cover/
|
|
47
|
+
|
|
48
|
+
# Translations
|
|
49
|
+
*.mo
|
|
50
|
+
*.pot
|
|
51
|
+
|
|
52
|
+
# pyenv
|
|
53
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
54
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
55
|
+
# .python-version
|
|
56
|
+
|
|
57
|
+
# pipenv
|
|
58
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
59
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
60
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
61
|
+
# install all needed dependencies.
|
|
62
|
+
#Pipfile.lock
|
|
63
|
+
|
|
64
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
65
|
+
__pypackages__/
|
|
66
|
+
.ruff_Cache
|
|
67
|
+
|
|
68
|
+
.aider*
|
|
69
|
+
**/venv
|
|
70
|
+
**/.venv
|
|
71
|
+
**/.env
|
|
72
|
+
**/.idea
|
|
73
|
+
/config.json
|
|
74
|
+
/output/
|
|
75
|
+
/history.json
|
|
76
|
+
**/.ruff_cache/
|
|
77
|
+
**/*~
|
|
78
|
+
**/.DS_Store
|
|
79
|
+
**/ls_volume
|
|
80
|
+
**/.terraform
|
|
81
|
+
/game_state.json
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Paul Robello
|
|
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,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: par_infini_sweeper
|
|
3
|
+
Version: 0.2.9
|
|
4
|
+
Summary: Par Infinite Minesweeper
|
|
5
|
+
Project-URL: Homepage, https://github.com/paulrobello/par_infini_sweeper
|
|
6
|
+
Project-URL: Documentation, https://github.com/paulrobello/par_infini_sweeper/blob/main/README.md
|
|
7
|
+
Project-URL: Repository, https://github.com/paulrobello/par_infini_sweeper
|
|
8
|
+
Project-URL: Issues, https://github.com/paulrobello/par_infini_sweeper/issues
|
|
9
|
+
Project-URL: Discussions, https://github.com/paulrobello/par_infini_sweeper/discussions
|
|
10
|
+
Project-URL: Wiki, https://github.com/paulrobello/par_infini_sweeper/wiki
|
|
11
|
+
Author-email: Paul Robello <probello@gmail.com>
|
|
12
|
+
Maintainer-email: Paul Robello <probello@gmail.com>
|
|
13
|
+
License: MIT License
|
|
14
|
+
|
|
15
|
+
Copyright (c) 2024 Paul Robello
|
|
16
|
+
|
|
17
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
18
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
19
|
+
in the Software without restriction, including without limitation the rights
|
|
20
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
21
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
22
|
+
furnished to do so, subject to the following conditions:
|
|
23
|
+
|
|
24
|
+
The above copyright notice and this permission notice shall be included in all
|
|
25
|
+
copies or substantial portions of the Software.
|
|
26
|
+
|
|
27
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
28
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
29
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
30
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
31
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
32
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
33
|
+
SOFTWARE.
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Keywords: minesweeper,tui
|
|
36
|
+
Classifier: Development Status :: 4 - Beta
|
|
37
|
+
Classifier: Environment :: Console
|
|
38
|
+
Classifier: Intended Audience :: Developers
|
|
39
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
40
|
+
Classifier: Intended Audience :: Other Audience
|
|
41
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
42
|
+
Classifier: Operating System :: MacOS
|
|
43
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
|
|
44
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
|
|
45
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
46
|
+
Classifier: Programming Language :: Python :: 3
|
|
47
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
48
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
49
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
50
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
51
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
52
|
+
Classifier: Typing :: Typed
|
|
53
|
+
Requires-Python: >=3.11
|
|
54
|
+
Requires-Dist: asyncio>=3.4.3
|
|
55
|
+
Requires-Dist: orjson>=3.10.15
|
|
56
|
+
Requires-Dist: pydantic-core>=2.27.2
|
|
57
|
+
Requires-Dist: pydantic>=2.10.6
|
|
58
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
59
|
+
Requires-Dist: requests>=2.32.3
|
|
60
|
+
Requires-Dist: rich>=13.9.4
|
|
61
|
+
Requires-Dist: textual-serve>=1.1.1
|
|
62
|
+
Requires-Dist: textual>=2.1.0
|
|
63
|
+
Requires-Dist: typer>=0.15.1
|
|
64
|
+
Description-Content-Type: text/markdown
|
|
65
|
+
|
|
66
|
+
# Par Infinite Minesweeper
|
|
67
|
+
|
|
68
|
+
## Description
|
|
69
|
+
|
|
70
|
+
Infinite Minesweeper TUI. Play a game of minesweeper with infinite board size!
|
|
71
|
+
|
|
72
|
+

|
|
73
|
+
|
|
74
|
+
## Technology
|
|
75
|
+
- Python
|
|
76
|
+
- Textual
|
|
77
|
+
- Sqlite3
|
|
78
|
+
|
|
79
|
+
## Objective
|
|
80
|
+
The goal of the game is to uncover all the cells that do not contain mines.
|
|
81
|
+
If you uncover a mine, you lose the game.
|
|
82
|
+
If you uncover a cell that is not a mine, it will show a number indicating how many mines are in the neighboring cells.
|
|
83
|
+
Use this information to determine which cells are safe to uncover.
|
|
84
|
+
|
|
85
|
+
## Controls
|
|
86
|
+
|
|
87
|
+
* Left click to uncover a cell. If a cell is flagged as a mine, it will not be uncovered.
|
|
88
|
+
* Sub grids can only be unlocked when cells neighboring the sub grid are uncovered.
|
|
89
|
+
* Shift or Ctrl + Left-click to toggle flagging a covered cell as a mine.
|
|
90
|
+
* Shift or Ctrl + Left-click on an uncovered cell it will uncover all neighboring cells.
|
|
91
|
+
* As a safety you must have same number of flags as mines in the neighboring cells.
|
|
92
|
+
* Drag to pan the board.
|
|
93
|
+
* Keys:
|
|
94
|
+
* `F1` Help.
|
|
95
|
+
* `N` New game.
|
|
96
|
+
* `O` Move view to origin.
|
|
97
|
+
* `C` Move view to board center (computed as center of exposed sub grids).
|
|
98
|
+
* `P` Pause.
|
|
99
|
+
* `H` Highscores.
|
|
100
|
+
* `T` Change theme.
|
|
101
|
+
* `Q` Quit.
|
|
102
|
+
|
|
103
|
+
## Scoring
|
|
104
|
+
|
|
105
|
+
The main grid consists of 8x8 sub grids.
|
|
106
|
+
Depending the difficulty level, the number of mines in each sub grid will vary.
|
|
107
|
+
* Easy: 8 mines
|
|
108
|
+
* Medium: 12 mines
|
|
109
|
+
* Hard: 16 mines
|
|
110
|
+
|
|
111
|
+
When all cells that are not mines in a sub grid are uncovered the sub grid is marked solved and flags are placed on any mines that are not already flagged.
|
|
112
|
+
Your score is the sum of all mines in the solved sub grids.
|
|
113
|
+
|
|
114
|
+
## Storage
|
|
115
|
+
|
|
116
|
+
All data for the application is stored in a sqlite3 database located in `~/.pim/game_data.sqlite`
|
|
117
|
+
The database is backed up daily to `~/.pim/game_data.sqlite.bak`
|
|
118
|
+
|
|
119
|
+
## Prerequisites
|
|
120
|
+
|
|
121
|
+
The instructions assume you have `uv` installed.
|
|
122
|
+
|
|
123
|
+
## Installation
|
|
124
|
+
|
|
125
|
+
### PyPi
|
|
126
|
+
```shell
|
|
127
|
+
uv tool install par_infini_sweeper
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### GitHub
|
|
131
|
+
```shell
|
|
132
|
+
uv tool install git+https://github.com/paulrobello/par_infini_sweeper
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Update
|
|
136
|
+
|
|
137
|
+
### PyPi
|
|
138
|
+
```shell
|
|
139
|
+
uv tool install par_infini_sweeper -U --force
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### GitHub
|
|
143
|
+
```shell
|
|
144
|
+
uv tool install git+https://github.com/paulrobello/par_infini_sweeper -U --force
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
## Installed Usage
|
|
149
|
+
```shell
|
|
150
|
+
pim [OPTIONS]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## From source Usage
|
|
154
|
+
```shell
|
|
155
|
+
uv run pim [OPTIONS]
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
### CLI Options
|
|
160
|
+
```
|
|
161
|
+
--server -s Start webserver that allows app to be played in a browser
|
|
162
|
+
--user -u TEXT User name to use [default: logged in username]
|
|
163
|
+
--nick -n TEXT Set user nickname [default: None]
|
|
164
|
+
--version -v Show version and exit.
|
|
165
|
+
--help Show this message and exit.
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Roadmap
|
|
169
|
+
|
|
170
|
+
- Global Leaderboard
|
|
171
|
+
- More game modes
|
|
172
|
+
- Optimize for more performance
|
|
173
|
+
|
|
174
|
+
## Whats New
|
|
175
|
+
- Version 0.2.9:
|
|
176
|
+
- Fixed some first run db issues
|
|
177
|
+
- Version 0.2.8:
|
|
178
|
+
- Addata game data backup
|
|
179
|
+
- Updated readme and help
|
|
180
|
+
- Version 0.2.7:
|
|
181
|
+
- Added pause key `p`
|
|
182
|
+
- Fixed bug where sometimes newly generated sub grids would not get saved if no cells were uncovered
|
|
183
|
+
- More optimizations
|
|
184
|
+
- Support for future game modes
|
|
185
|
+
- Version 0.2.6:
|
|
186
|
+
- Now only highlights unrevealed surrounding cells when shift/ctrl + left-click on uncovered cells
|
|
187
|
+
- Version 0.2.6:
|
|
188
|
+
- Now stops timer on game over
|
|
189
|
+
- Now highlights surrounding cells when shift/ctrl + left-click on uncovered cells
|
|
190
|
+
- Version 0.2.5:
|
|
191
|
+
- Disabled some toasts to reduce clutter
|
|
192
|
+
- Moved middle click function to shift/ctrl + left-click on uncovered cells
|
|
193
|
+
- Version 0.2.3:
|
|
194
|
+
- Enabled multi user support
|
|
195
|
+
- Version 0.2.0:
|
|
196
|
+
- Added webserver to play in a browser
|
|
197
|
+
- Version 0.1.0:
|
|
198
|
+
- Initial release
|
|
199
|
+
|
|
200
|
+
## Contributing
|
|
201
|
+
|
|
202
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
203
|
+
|
|
204
|
+
## Shoutout
|
|
205
|
+
|
|
206
|
+
I would like to thank [Edward Jazzhands](http://edward-jazzhands.github.io/) for all his help testing and feedback / feature requests!
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
211
|
+
|
|
212
|
+
## Author
|
|
213
|
+
|
|
214
|
+
Paul Robello - probello@gmail.com
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Par Infinite Minesweeper
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Infinite Minesweeper TUI. Play a game of minesweeper with infinite board size!
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Technology
|
|
10
|
+
- Python
|
|
11
|
+
- Textual
|
|
12
|
+
- Sqlite3
|
|
13
|
+
|
|
14
|
+
## Objective
|
|
15
|
+
The goal of the game is to uncover all the cells that do not contain mines.
|
|
16
|
+
If you uncover a mine, you lose the game.
|
|
17
|
+
If you uncover a cell that is not a mine, it will show a number indicating how many mines are in the neighboring cells.
|
|
18
|
+
Use this information to determine which cells are safe to uncover.
|
|
19
|
+
|
|
20
|
+
## Controls
|
|
21
|
+
|
|
22
|
+
* Left click to uncover a cell. If a cell is flagged as a mine, it will not be uncovered.
|
|
23
|
+
* Sub grids can only be unlocked when cells neighboring the sub grid are uncovered.
|
|
24
|
+
* Shift or Ctrl + Left-click to toggle flagging a covered cell as a mine.
|
|
25
|
+
* Shift or Ctrl + Left-click on an uncovered cell it will uncover all neighboring cells.
|
|
26
|
+
* As a safety you must have same number of flags as mines in the neighboring cells.
|
|
27
|
+
* Drag to pan the board.
|
|
28
|
+
* Keys:
|
|
29
|
+
* `F1` Help.
|
|
30
|
+
* `N` New game.
|
|
31
|
+
* `O` Move view to origin.
|
|
32
|
+
* `C` Move view to board center (computed as center of exposed sub grids).
|
|
33
|
+
* `P` Pause.
|
|
34
|
+
* `H` Highscores.
|
|
35
|
+
* `T` Change theme.
|
|
36
|
+
* `Q` Quit.
|
|
37
|
+
|
|
38
|
+
## Scoring
|
|
39
|
+
|
|
40
|
+
The main grid consists of 8x8 sub grids.
|
|
41
|
+
Depending the difficulty level, the number of mines in each sub grid will vary.
|
|
42
|
+
* Easy: 8 mines
|
|
43
|
+
* Medium: 12 mines
|
|
44
|
+
* Hard: 16 mines
|
|
45
|
+
|
|
46
|
+
When all cells that are not mines in a sub grid are uncovered the sub grid is marked solved and flags are placed on any mines that are not already flagged.
|
|
47
|
+
Your score is the sum of all mines in the solved sub grids.
|
|
48
|
+
|
|
49
|
+
## Storage
|
|
50
|
+
|
|
51
|
+
All data for the application is stored in a sqlite3 database located in `~/.pim/game_data.sqlite`
|
|
52
|
+
The database is backed up daily to `~/.pim/game_data.sqlite.bak`
|
|
53
|
+
|
|
54
|
+
## Prerequisites
|
|
55
|
+
|
|
56
|
+
The instructions assume you have `uv` installed.
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
### PyPi
|
|
61
|
+
```shell
|
|
62
|
+
uv tool install par_infini_sweeper
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### GitHub
|
|
66
|
+
```shell
|
|
67
|
+
uv tool install git+https://github.com/paulrobello/par_infini_sweeper
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Update
|
|
71
|
+
|
|
72
|
+
### PyPi
|
|
73
|
+
```shell
|
|
74
|
+
uv tool install par_infini_sweeper -U --force
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### GitHub
|
|
78
|
+
```shell
|
|
79
|
+
uv tool install git+https://github.com/paulrobello/par_infini_sweeper -U --force
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
## Installed Usage
|
|
84
|
+
```shell
|
|
85
|
+
pim [OPTIONS]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## From source Usage
|
|
89
|
+
```shell
|
|
90
|
+
uv run pim [OPTIONS]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
### CLI Options
|
|
95
|
+
```
|
|
96
|
+
--server -s Start webserver that allows app to be played in a browser
|
|
97
|
+
--user -u TEXT User name to use [default: logged in username]
|
|
98
|
+
--nick -n TEXT Set user nickname [default: None]
|
|
99
|
+
--version -v Show version and exit.
|
|
100
|
+
--help Show this message and exit.
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Roadmap
|
|
104
|
+
|
|
105
|
+
- Global Leaderboard
|
|
106
|
+
- More game modes
|
|
107
|
+
- Optimize for more performance
|
|
108
|
+
|
|
109
|
+
## Whats New
|
|
110
|
+
- Version 0.2.9:
|
|
111
|
+
- Fixed some first run db issues
|
|
112
|
+
- Version 0.2.8:
|
|
113
|
+
- Addata game data backup
|
|
114
|
+
- Updated readme and help
|
|
115
|
+
- Version 0.2.7:
|
|
116
|
+
- Added pause key `p`
|
|
117
|
+
- Fixed bug where sometimes newly generated sub grids would not get saved if no cells were uncovered
|
|
118
|
+
- More optimizations
|
|
119
|
+
- Support for future game modes
|
|
120
|
+
- Version 0.2.6:
|
|
121
|
+
- Now only highlights unrevealed surrounding cells when shift/ctrl + left-click on uncovered cells
|
|
122
|
+
- Version 0.2.6:
|
|
123
|
+
- Now stops timer on game over
|
|
124
|
+
- Now highlights surrounding cells when shift/ctrl + left-click on uncovered cells
|
|
125
|
+
- Version 0.2.5:
|
|
126
|
+
- Disabled some toasts to reduce clutter
|
|
127
|
+
- Moved middle click function to shift/ctrl + left-click on uncovered cells
|
|
128
|
+
- Version 0.2.3:
|
|
129
|
+
- Enabled multi user support
|
|
130
|
+
- Version 0.2.0:
|
|
131
|
+
- Added webserver to play in a browser
|
|
132
|
+
- Version 0.1.0:
|
|
133
|
+
- Initial release
|
|
134
|
+
|
|
135
|
+
## Contributing
|
|
136
|
+
|
|
137
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
138
|
+
|
|
139
|
+
## Shoutout
|
|
140
|
+
|
|
141
|
+
I would like to thank [Edward Jazzhands](http://edward-jazzhands.github.io/) for all his help testing and feedback / feature requests!
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
146
|
+
|
|
147
|
+
## Author
|
|
148
|
+
|
|
149
|
+
Paul Robello - probello@gmail.com
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "par_infini_sweeper"
|
|
3
|
+
dynamic = [
|
|
4
|
+
"version",
|
|
5
|
+
]
|
|
6
|
+
description = "Par Infinite Minesweeper"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Paul Robello", email = "probello@gmail.com" },
|
|
11
|
+
]
|
|
12
|
+
maintainers = [
|
|
13
|
+
{ name = "Paul Robello", email = "probello@gmail.com" },
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Intended Audience :: End Users/Desktop",
|
|
21
|
+
"Intended Audience :: Other Audience",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Operating System :: MacOS",
|
|
28
|
+
"Operating System :: Microsoft :: Windows :: Windows 10",
|
|
29
|
+
"Operating System :: Microsoft :: Windows :: Windows 11",
|
|
30
|
+
"Operating System :: POSIX :: Linux",
|
|
31
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
32
|
+
"Typing :: Typed",
|
|
33
|
+
]
|
|
34
|
+
keywords = [
|
|
35
|
+
"tui",
|
|
36
|
+
"minesweeper",
|
|
37
|
+
]
|
|
38
|
+
dependencies = [
|
|
39
|
+
"asyncio>=3.4.3",
|
|
40
|
+
"pydantic-core>=2.27.2",
|
|
41
|
+
"pydantic>=2.10.6",
|
|
42
|
+
"python-dotenv>=1.0.1",
|
|
43
|
+
"requests>=2.32.3",
|
|
44
|
+
"rich>=13.9.4",
|
|
45
|
+
"orjson>=3.10.15",
|
|
46
|
+
"typer>=0.15.1",
|
|
47
|
+
"textual>=2.1.0",
|
|
48
|
+
"textual-serve>=1.1.1",
|
|
49
|
+
|
|
50
|
+
]
|
|
51
|
+
packages = [
|
|
52
|
+
"src/par_infini_sweeper",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[project.license]
|
|
56
|
+
file = "LICENSE"
|
|
57
|
+
|
|
58
|
+
[project.urls]
|
|
59
|
+
Homepage = "https://github.com/paulrobello/par_infini_sweeper"
|
|
60
|
+
Documentation = "https://github.com/paulrobello/par_infini_sweeper/blob/main/README.md"
|
|
61
|
+
Repository = "https://github.com/paulrobello/par_infini_sweeper"
|
|
62
|
+
Issues = "https://github.com/paulrobello/par_infini_sweeper/issues"
|
|
63
|
+
Discussions = "https://github.com/paulrobello/par_infini_sweeper/discussions"
|
|
64
|
+
Wiki = "https://github.com/paulrobello/par_infini_sweeper/wiki"
|
|
65
|
+
|
|
66
|
+
[project.scripts]
|
|
67
|
+
pim = "par_infini_sweeper.__main__:app"
|
|
68
|
+
|
|
69
|
+
[build-system]
|
|
70
|
+
requires = [
|
|
71
|
+
"hatchling",
|
|
72
|
+
"wheel",
|
|
73
|
+
]
|
|
74
|
+
build-backend = "hatchling.build"
|
|
75
|
+
|
|
76
|
+
[dependency-groups]
|
|
77
|
+
dev = [
|
|
78
|
+
"build>=1.2.1",
|
|
79
|
+
"twine>=6.1.0",
|
|
80
|
+
"pyright>=1.1.379",
|
|
81
|
+
"pre-commit>=4.1.0",
|
|
82
|
+
"ruff>=0.9.3",
|
|
83
|
+
"pyinstrument>=5.0.1",
|
|
84
|
+
"ruff>=0.7.0",
|
|
85
|
+
"types-orjson>=3.6.2",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
[tool.hatch.version]
|
|
89
|
+
path = "src/par_infini_sweeper/__init__.py"
|
|
90
|
+
|
|
91
|
+
[tool.hatch.build.targets.wheel]
|
|
92
|
+
packages = [
|
|
93
|
+
"src/par_infini_sweeper",
|
|
94
|
+
]
|
|
95
|
+
include = [
|
|
96
|
+
"py.typed",
|
|
97
|
+
"**/*.py",
|
|
98
|
+
"**/*.html",
|
|
99
|
+
"**/*.gif",
|
|
100
|
+
"**/*.jpg",
|
|
101
|
+
"**/*.png",
|
|
102
|
+
"**/*.md",
|
|
103
|
+
"**/*.tcss",
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
[tool.hatch.build.targets.sdist]
|
|
107
|
+
include = [
|
|
108
|
+
"src/par_infini_sweeper",
|
|
109
|
+
"LICENSE",
|
|
110
|
+
"README.md",
|
|
111
|
+
"extraction_prompt.md",
|
|
112
|
+
"pyproject.toml",
|
|
113
|
+
]
|
|
114
|
+
exclude = [
|
|
115
|
+
"*.pyc",
|
|
116
|
+
"__pycache__",
|
|
117
|
+
"*.so",
|
|
118
|
+
"*.dylib",
|
|
119
|
+
]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Par Infinite Minesweeper."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
__author__ = "Paul Robello"
|
|
8
|
+
__credits__ = ["Paul Robello"]
|
|
9
|
+
__maintainer__ = "Paul Robello"
|
|
10
|
+
__email__ = "probello@gmail.com"
|
|
11
|
+
__version__ = "0.2.9"
|
|
12
|
+
__application_title__ = "Par Infinite Minesweeper"
|
|
13
|
+
__application_binary__ = "pim"
|
|
14
|
+
__licence__ = "MIT"
|
|
15
|
+
|
|
16
|
+
from par_infini_sweeper.minesweeper_app import MinesweeperApp
|
|
17
|
+
|
|
18
|
+
os.environ["USER_AGENT"] = f"{__application_title__} {__version__}"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__all__: list[str] = [
|
|
22
|
+
"__author__",
|
|
23
|
+
"__credits__",
|
|
24
|
+
"__maintainer__",
|
|
25
|
+
"__email__",
|
|
26
|
+
"__version__",
|
|
27
|
+
"__application_binary__",
|
|
28
|
+
"__licence__",
|
|
29
|
+
"__application_title__",
|
|
30
|
+
"MinesweeperApp",
|
|
31
|
+
]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Main application"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import Annotated
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
from dotenv import load_dotenv
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
from textual_serve.server import Server
|
|
12
|
+
|
|
13
|
+
from par_infini_sweeper import __application_title__, __version__
|
|
14
|
+
from par_infini_sweeper.minesweeper_app import MinesweeperApp
|
|
15
|
+
|
|
16
|
+
app = typer.Typer()
|
|
17
|
+
console = Console(stderr=True)
|
|
18
|
+
|
|
19
|
+
load_dotenv()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def version_callback(value: bool) -> None:
|
|
23
|
+
"""Print version and exit."""
|
|
24
|
+
if value:
|
|
25
|
+
print(f"{__application_title__}: {__version__}")
|
|
26
|
+
raise typer.Exit()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@app.command()
|
|
30
|
+
def main(
|
|
31
|
+
start_server: Annotated[
|
|
32
|
+
bool, typer.Option("--server", "-s", help="Start webserver that allows app to be played in a browser")
|
|
33
|
+
] = False,
|
|
34
|
+
user_name: Annotated[str, typer.Option("--user", "-u", help="User name to use")] = os.environ.get("USER", "user"),
|
|
35
|
+
nickname: Annotated[str | None, typer.Option("--nick", "-n", help="Set user nickname")] = None,
|
|
36
|
+
version: Annotated[ # pylint: disable=unused-argument
|
|
37
|
+
bool | None,
|
|
38
|
+
typer.Option("--version", "-v", callback=version_callback, is_eager=True),
|
|
39
|
+
] = None,
|
|
40
|
+
) -> None:
|
|
41
|
+
"""Main function."""
|
|
42
|
+
if start_server:
|
|
43
|
+
server = Server("pim")
|
|
44
|
+
server.serve()
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
sweeper_app: MinesweeperApp = MinesweeperApp(user_name, nickname)
|
|
48
|
+
sweeper_app.run()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
app()
|