cli-arcade 2026.2.0__py3-none-any.whl → 2026.2.1__py3-none-any.whl
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.
- {cli_arcade-2026.2.0.dist-info → cli_arcade-2026.2.1.dist-info}/METADATA +4 -1
- {cli_arcade-2026.2.0.dist-info → cli_arcade-2026.2.1.dist-info}/RECORD +17 -8
- game_classes/__pycache__/__init__.cpython-312.pyc +0 -0
- game_classes/__pycache__/game_base.cpython-312.pyc +0 -0
- game_classes/__pycache__/highscores.cpython-312.pyc +0 -0
- game_classes/__pycache__/menu.cpython-312.pyc +0 -0
- game_classes/__pycache__/ptk.cpython-312.pyc +0 -0
- game_classes/__pycache__/ptk.cpython-313.pyc +0 -0
- game_classes/__pycache__/tools.cpython-312.pyc +0 -0
- game_classes/ptk.py +122 -6
- games/byte_bouncer/__pycache__/game.cpython-312.pyc +0 -0
- games/star_ship/__pycache__/game.cpython-312.pyc +0 -0
- games/terminal_tumble/__pycache__/game.cpython-312.pyc +0 -0
- {cli_arcade-2026.2.0.dist-info → cli_arcade-2026.2.1.dist-info}/WHEEL +0 -0
- {cli_arcade-2026.2.0.dist-info → cli_arcade-2026.2.1.dist-info}/entry_points.txt +0 -0
- {cli_arcade-2026.2.0.dist-info → cli_arcade-2026.2.1.dist-info}/licenses/LICENSE +0 -0
- {cli_arcade-2026.2.0.dist-info → cli_arcade-2026.2.1.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cli-arcade
|
|
3
|
-
Version: 2026.2.
|
|
3
|
+
Version: 2026.2.1
|
|
4
4
|
Summary: Collection of terminal CLI games
|
|
5
5
|
Home-page: https://github.com/Bro-Code-Technologies/cli-arcade/tree/main/windows
|
|
6
6
|
Author: Bro Code Technologies LLC
|
|
@@ -96,3 +96,6 @@ All notable changes to this project will be documented in this file.
|
|
|
96
96
|
- Byte Bouncer & Star Ship: floor + off-screen right wall; left-column bug fixed.
|
|
97
97
|
- `ptk`: default-attribute/color emission fix; add helper to exit alt screen.
|
|
98
98
|
- Fixed 180 movement glitch in Star Ship.
|
|
99
|
+
|
|
100
|
+
### 2026.2.1
|
|
101
|
+
- Updated key mapping to work with Linux and macOS terminals.
|
|
@@ -1,29 +1,37 @@
|
|
|
1
1
|
cli.py,sha256=sf70SoYU89X2b5CENYvqC7z8KntRadlV3IQHJXrgkw0,19567
|
|
2
|
-
cli_arcade-2026.2.
|
|
2
|
+
cli_arcade-2026.2.1.dist-info/licenses/LICENSE,sha256=1PLSNFyGPi9COkVEeNYcUTuRLqGxzMLLTah05tByD4s,1099
|
|
3
3
|
game_classes/__init__.py,sha256=A0o4vBUktOiONToIJb0hACalszBnFS9ls9WXPn3-KH0,28
|
|
4
4
|
game_classes/game_base.py,sha256=8OaMHwPE6KKhwRCbUoI0Kypf2CN6RVxze_zdqaw7HhE,3499
|
|
5
5
|
game_classes/highscores.py,sha256=dDK-7lFXSMwIqExXGp6_-7QfQz6CIf12lJ22poeCdh4,4061
|
|
6
6
|
game_classes/menu.py,sha256=wx-dITSozG1VCfyFeFKgooRXEijQygDCTBRvoKnd7-8,2798
|
|
7
|
-
game_classes/ptk.py,sha256=
|
|
7
|
+
game_classes/ptk.py,sha256=v7vXIJVaJUc5JdDtUSyD6QLDJnybXY_ueDEatRqAFuI,12977
|
|
8
8
|
game_classes/tools.py,sha256=sZR4m8NSil4UhmZ2qDsl1iEi1hZMwUPVBFR5hSmiEBc,5106
|
|
9
|
+
game_classes/__pycache__/__init__.cpython-312.pyc,sha256=R0jJUxI2JIcXR4r34VwLgaPHHUCRZBwegLXmlZ2n2LM,197
|
|
9
10
|
game_classes/__pycache__/__init__.cpython-313.pyc,sha256=zSl9ESMUQn5Vo_XXAA8DD7lpFHOtOwBruGvCOJ5qeuo,192
|
|
11
|
+
game_classes/__pycache__/game_base.cpython-312.pyc,sha256=oeqYvfMbSDgwzZ3x2-lnuOVHSo2QWZQgbbYU9j3A8qY,6765
|
|
10
12
|
game_classes/__pycache__/game_base.cpython-313.pyc,sha256=NKAgCBXxM7nZ8mt6wFy1MxUW6DK7EBhqXiLr1sVmtiA,6977
|
|
13
|
+
game_classes/__pycache__/highscores.cpython-312.pyc,sha256=uaBo2z_TbERpOR1V-7oiVyt9iNu2Q1-WtMRuUb5FTY8,6942
|
|
11
14
|
game_classes/__pycache__/highscores.cpython-313.pyc,sha256=0rYMYs6NOzT-f00Me20F-46kUR_x8ZXk2jngO5amLy4,7080
|
|
15
|
+
game_classes/__pycache__/menu.cpython-312.pyc,sha256=fQ-AFhkA97IM3aauTx1J8huAXEcwELuc8QzO589o7ms,4424
|
|
12
16
|
game_classes/__pycache__/menu.cpython-313.pyc,sha256=urqSfGlJJdfTKI1kqXOT0oPXjo1Ny9MyYA8QroVQHzQ,4488
|
|
13
|
-
game_classes/__pycache__/ptk.cpython-
|
|
17
|
+
game_classes/__pycache__/ptk.cpython-312.pyc,sha256=h5ShTY7g8zjU1d3bJZkbcdtJGN6CVvB1IIDL7WNozOk,18602
|
|
18
|
+
game_classes/__pycache__/ptk.cpython-313.pyc,sha256=oSVDS5Cfugqn-cCsLjdoB7upFo6CgYSC5PwVaufS0hI,19240
|
|
14
19
|
game_classes/__pycache__/ptk_curses.cpython-313.pyc,sha256=XqhJ78tqyT0HFd5UV_1_IrGl-W5PuW4WyJve5RiY3uo,13820
|
|
15
20
|
game_classes/__pycache__/ptk_game_base.cpython-313.pyc,sha256=tRzGtoCErAHsUpoEWVjQN4PQ0Gw5N9RW3nJHJW2IT24,6915
|
|
16
21
|
game_classes/__pycache__/ptk_menu.cpython-313.pyc,sha256=jyBSuLVxNm7ueGjAIKhd7D_ZEFpwLv9U1iim_ElClHk,2448
|
|
17
22
|
game_classes/__pycache__/ptk_tools.cpython-313.pyc,sha256=Y-lBpAMlt8HfgQEio4isDGpwXclYUsyzs9wGoeGJkmE,5061
|
|
23
|
+
game_classes/__pycache__/tools.cpython-312.pyc,sha256=X_qDsJLFe5_Y29l4MlH_RuM46dOxvunIUTyBsvYj85o,7273
|
|
18
24
|
game_classes/__pycache__/tools.cpython-313.pyc,sha256=0MS9Cai_D0LaIQ6w6c6BLSJ45XvnUr4BjHSQdFYnQ7Y,7316
|
|
19
25
|
games/__init__.py,sha256=Rg46lnLj_sezpnXaQTS1NXX5OaRhR_EWpNTyYUxycj4,21
|
|
20
26
|
games/byte_bouncer/__init__.py,sha256=8hxIHRyUPB-X6vJXh1432ytKjOcfIzCbdpO5mmWA7iQ,33
|
|
21
27
|
games/byte_bouncer/game.py,sha256=EpTzObLNF_cGfB-xRkUlqCwYt7A7IGk8nENkOdqoV3c,8877
|
|
22
28
|
games/byte_bouncer/__pycache__/byte_bouncer.cpython-313.pyc,sha256=JSTB6-_KCukAAVaZz9TpJ3V4gif_M3n_L5X1KOviSJ8,24605
|
|
29
|
+
games/byte_bouncer/__pycache__/game.cpython-312.pyc,sha256=ITr1oNdZ7TQiDAw_suY1bFHQaiydXB_I7-TMMJMN5h8,13709
|
|
23
30
|
games/byte_bouncer/__pycache__/game.cpython-313.pyc,sha256=0H66QPFncbxvKVlMRPKEXjJDYtw1pPAw5I9sz3kWdIA,13965
|
|
24
31
|
games/byte_bouncer/__pycache__/highscores.cpython-313.pyc,sha256=g3FozKpWGDVsTVETNpb6lRHcKA3ZIsQio8Kh7KCGVCI,3125
|
|
25
32
|
games/star_ship/__init__.py,sha256=X8AdhoccmNVu6yl7MalsxIsMxuEsddRdlvEQmhZMD0A,30
|
|
26
33
|
games/star_ship/game.py,sha256=aN3LVh-kaYppAy-J259Y6XROT5pvEAFDjGd1404oWBw,10992
|
|
34
|
+
games/star_ship/__pycache__/game.cpython-312.pyc,sha256=lOScasiJ9VaNlCua45m_jejQPetUQGROhCxlV_aKi1I,15712
|
|
27
35
|
games/star_ship/__pycache__/game.cpython-313.pyc,sha256=hWqwV12a1VF-_Lc8Uzd7ono4ZN3gNJ4RQ-gK69OayVw,15922
|
|
28
36
|
games/star_ship/__pycache__/highscores.cpython-313.pyc,sha256=nHbEOTWeX0U9D47K2EP5S5uDPI0WW52Eg7h_NesG1OU,3148
|
|
29
37
|
games/star_ship/__pycache__/nibbles.cpython-313.pyc,sha256=Yv2P-GwEc30zA24aO7k0hkk1AOja6K85AFvmjLIffqQ,20510
|
|
@@ -31,11 +39,12 @@ games/star_ship/__pycache__/snek.cpython-313.pyc,sha256=3Mwyy6vjGFRmNyAWSqV5JRil
|
|
|
31
39
|
games/star_ship/__pycache__/star_ship.cpython-313.pyc,sha256=9gJt10MTzVTSwsc4I16TDZTaAXclfhfGTzgfYgZNOKo,28021
|
|
32
40
|
games/terminal_tumble/__init__.py,sha256=axTd7hCgnLRNU8QS73NnQY3q5xjIb3ZYQORJ9Lz8l_E,36
|
|
33
41
|
games/terminal_tumble/game.py,sha256=UbtrMS4wi5MiIMHfreP51VlrHHlfxEPJpFmsLgdUgWs,15633
|
|
42
|
+
games/terminal_tumble/__pycache__/game.cpython-312.pyc,sha256=44n4iwM1rIjtMyeyITib1ewnGqOcI8p-npdpSErJQUs,23684
|
|
34
43
|
games/terminal_tumble/__pycache__/game.cpython-313.pyc,sha256=DrjmLzJYY5QoYXghGh-ORn26Yax9Gmd6fSCZGdgYbRQ,24073
|
|
35
44
|
games/terminal_tumble/__pycache__/highscores.cpython-313.pyc,sha256=UPnU9Zq88q2TZq1qXyo8e2Y_PdOgwvu5mncIkunFah8,3154
|
|
36
45
|
games/terminal_tumble/__pycache__/terminal_tumble.cpython-313.pyc,sha256=7oLpmmkYjpLYRC0bjRoEkHbIUNq7FZVJToGoja94m0o,38016
|
|
37
|
-
cli_arcade-2026.2.
|
|
38
|
-
cli_arcade-2026.2.
|
|
39
|
-
cli_arcade-2026.2.
|
|
40
|
-
cli_arcade-2026.2.
|
|
41
|
-
cli_arcade-2026.2.
|
|
46
|
+
cli_arcade-2026.2.1.dist-info/METADATA,sha256=zD5GPdMYROphM5_bhvgOHKbA_kTOdBe65-l6UZWSQOg,3308
|
|
47
|
+
cli_arcade-2026.2.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
48
|
+
cli_arcade-2026.2.1.dist-info/entry_points.txt,sha256=nNElhZv4nM_lrOYpvnOChtJn1XsWwQr8sI344flzzTQ,56
|
|
49
|
+
cli_arcade-2026.2.1.dist-info/top_level.txt,sha256=gTfYlz7gHYgPY0ugfJivukCOkNzmOisNR6VuJjAXPF4,23
|
|
50
|
+
cli_arcade-2026.2.1.dist-info/RECORD,,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
game_classes/ptk.py
CHANGED
|
@@ -5,8 +5,24 @@ import threading
|
|
|
5
5
|
import queue
|
|
6
6
|
import time
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
_HAS_PROMPT_TOOLKIT = True
|
|
9
|
+
try:
|
|
10
|
+
from prompt_toolkit.input import create_input
|
|
11
|
+
from prompt_toolkit.keys import Keys
|
|
12
|
+
except Exception:
|
|
13
|
+
create_input = None
|
|
14
|
+
Keys = None
|
|
15
|
+
_HAS_PROMPT_TOOLKIT = False
|
|
16
|
+
import select
|
|
17
|
+
|
|
18
|
+
_HAS_TERMIOS = True
|
|
19
|
+
try:
|
|
20
|
+
import termios
|
|
21
|
+
import tty
|
|
22
|
+
except Exception:
|
|
23
|
+
termios = None
|
|
24
|
+
tty = None
|
|
25
|
+
_HAS_TERMIOS = False
|
|
10
26
|
|
|
11
27
|
# basic color constants (match curses style usage)
|
|
12
28
|
COLOR_BLACK = 0
|
|
@@ -92,10 +108,29 @@ class _Screen:
|
|
|
92
108
|
self._use_msvcrt = os.name == "nt"
|
|
93
109
|
self._input = None
|
|
94
110
|
self._thread = None
|
|
111
|
+
self._posix_fd = None
|
|
112
|
+
self._orig_term_attrs = None
|
|
95
113
|
if not self._use_msvcrt:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
114
|
+
# Prefer a simple termios-based reader on POSIX for raw key capture
|
|
115
|
+
if _HAS_TERMIOS:
|
|
116
|
+
try:
|
|
117
|
+
self._posix_fd = sys.stdin.fileno()
|
|
118
|
+
self._orig_term_attrs = termios.tcgetattr(self._posix_fd)
|
|
119
|
+
tty.setcbreak(self._posix_fd)
|
|
120
|
+
self._thread = threading.Thread(target=self._posix_reader, daemon=True)
|
|
121
|
+
self._thread.start()
|
|
122
|
+
except Exception:
|
|
123
|
+
# fall back to prompt_toolkit if termios fails
|
|
124
|
+
self._posix_fd = None
|
|
125
|
+
self._orig_term_attrs = None
|
|
126
|
+
if self._posix_fd is None and _HAS_PROMPT_TOOLKIT and create_input is not None:
|
|
127
|
+
try:
|
|
128
|
+
self._input = create_input()
|
|
129
|
+
self._thread = threading.Thread(target=self._reader, daemon=True)
|
|
130
|
+
self._thread.start()
|
|
131
|
+
except Exception as e:
|
|
132
|
+
self._input = None
|
|
133
|
+
sys.stderr.write(f"[ptk] create_input failed: {e}\n")
|
|
99
134
|
self._timeout = 0.0
|
|
100
135
|
self._buffer = []
|
|
101
136
|
self._attrs = []
|
|
@@ -126,9 +161,81 @@ class _Screen:
|
|
|
126
161
|
try:
|
|
127
162
|
for key in self._input.read_keys():
|
|
128
163
|
self._queue.put(key)
|
|
129
|
-
except Exception:
|
|
164
|
+
except Exception as e:
|
|
165
|
+
# log and continue — don't let the thread die silently
|
|
166
|
+
sys.stderr.write(f"[ptk] reader exception: {e}\n")
|
|
130
167
|
time.sleep(0.01)
|
|
131
168
|
|
|
169
|
+
def _posix_reader(self):
|
|
170
|
+
if not _HAS_TERMIOS:
|
|
171
|
+
return
|
|
172
|
+
fd = self._posix_fd
|
|
173
|
+
buf = b""
|
|
174
|
+
while not self._stop.is_set():
|
|
175
|
+
try:
|
|
176
|
+
r, _, _ = select.select([fd], [], [], 0.1)
|
|
177
|
+
if not r:
|
|
178
|
+
continue
|
|
179
|
+
chunk = os.read(fd, 32)
|
|
180
|
+
if not chunk:
|
|
181
|
+
continue
|
|
182
|
+
buf += chunk
|
|
183
|
+
# process buffer for known sequences
|
|
184
|
+
while buf:
|
|
185
|
+
# single-byte control checks
|
|
186
|
+
if buf.startswith(b"\x1b"):
|
|
187
|
+
# escape sequences: try to consume common sequences
|
|
188
|
+
if buf.startswith(b"\x1b[A"):
|
|
189
|
+
self._queue.put(KEY_UP)
|
|
190
|
+
buf = buf[3:]
|
|
191
|
+
continue
|
|
192
|
+
if buf.startswith(b"\x1b[B"):
|
|
193
|
+
self._queue.put(KEY_DOWN)
|
|
194
|
+
buf = buf[3:]
|
|
195
|
+
continue
|
|
196
|
+
if buf.startswith(b"\x1b[C"):
|
|
197
|
+
self._queue.put(KEY_RIGHT)
|
|
198
|
+
buf = buf[3:]
|
|
199
|
+
continue
|
|
200
|
+
if buf.startswith(b"\x1b[D"):
|
|
201
|
+
self._queue.put(KEY_LEFT)
|
|
202
|
+
buf = buf[3:]
|
|
203
|
+
continue
|
|
204
|
+
# PageUp/PageDown common sequences
|
|
205
|
+
if buf.startswith(b"\x1b[5~"):
|
|
206
|
+
self._queue.put(KEY_PPAGE)
|
|
207
|
+
buf = buf[4:]
|
|
208
|
+
continue
|
|
209
|
+
if buf.startswith(b"\x1b[6~"):
|
|
210
|
+
self._queue.put(KEY_NPAGE)
|
|
211
|
+
buf = buf[4:]
|
|
212
|
+
continue
|
|
213
|
+
# unknown escape: drop single ESC
|
|
214
|
+
self._queue.put(27)
|
|
215
|
+
buf = buf[1:]
|
|
216
|
+
continue
|
|
217
|
+
# newline / carriage return
|
|
218
|
+
if buf[0] in (10, 13):
|
|
219
|
+
self._queue.put(10)
|
|
220
|
+
buf = buf[1:]
|
|
221
|
+
continue
|
|
222
|
+
# backspace (DEL or BS)
|
|
223
|
+
if buf[0] in (8, 127):
|
|
224
|
+
self._queue.put(KEY_BACKSPACE)
|
|
225
|
+
buf = buf[1:]
|
|
226
|
+
continue
|
|
227
|
+
# regular printable character
|
|
228
|
+
ch = buf[0]
|
|
229
|
+
if 32 <= ch <= 126:
|
|
230
|
+
self._queue.put(ch)
|
|
231
|
+
buf = buf[1:]
|
|
232
|
+
continue
|
|
233
|
+
# unhandled byte: drop
|
|
234
|
+
buf = buf[1:]
|
|
235
|
+
except Exception as e:
|
|
236
|
+
sys.stderr.write(f"[ptk] posix_reader exception: {e}\n")
|
|
237
|
+
time.sleep(0.01)
|
|
238
|
+
|
|
132
239
|
def stop(self):
|
|
133
240
|
self._stop.set()
|
|
134
241
|
try:
|
|
@@ -136,6 +243,12 @@ class _Screen:
|
|
|
136
243
|
self._input.close()
|
|
137
244
|
except Exception:
|
|
138
245
|
pass
|
|
246
|
+
# restore termios attrs if we changed them
|
|
247
|
+
try:
|
|
248
|
+
if self._orig_term_attrs is not None and _HAS_TERMIOS:
|
|
249
|
+
termios.tcsetattr(self._posix_fd, termios.TCSANOW, self._orig_term_attrs)
|
|
250
|
+
except Exception:
|
|
251
|
+
pass
|
|
139
252
|
|
|
140
253
|
def nodelay(self, _flag=True):
|
|
141
254
|
return None
|
|
@@ -221,6 +334,9 @@ class _Screen:
|
|
|
221
334
|
key = self._queue.get(timeout=self._timeout)
|
|
222
335
|
except Exception:
|
|
223
336
|
return -1
|
|
337
|
+
# key may be an int from posix reader or a keypress object from prompt_toolkit
|
|
338
|
+
if isinstance(key, int):
|
|
339
|
+
return key
|
|
224
340
|
return _map_keypress(key)
|
|
225
341
|
|
|
226
342
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|