cli-arcade 2026.2.0__tar.gz → 2026.2.1__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 (53) hide show
  1. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/PKG-INFO +4 -1
  2. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/PYPI_README.md +3 -0
  3. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/cli_arcade.egg-info/SOURCES.txt +9 -0
  4. cli_arcade-2026.2.1/game_classes/__pycache__/__init__.cpython-312.pyc +0 -0
  5. cli_arcade-2026.2.1/game_classes/__pycache__/game_base.cpython-312.pyc +0 -0
  6. cli_arcade-2026.2.1/game_classes/__pycache__/highscores.cpython-312.pyc +0 -0
  7. cli_arcade-2026.2.1/game_classes/__pycache__/menu.cpython-312.pyc +0 -0
  8. cli_arcade-2026.2.1/game_classes/__pycache__/ptk.cpython-312.pyc +0 -0
  9. cli_arcade-2026.2.1/game_classes/__pycache__/ptk.cpython-313.pyc +0 -0
  10. cli_arcade-2026.2.1/game_classes/__pycache__/tools.cpython-312.pyc +0 -0
  11. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/ptk.py +122 -6
  12. cli_arcade-2026.2.1/games/byte_bouncer/__pycache__/game.cpython-312.pyc +0 -0
  13. cli_arcade-2026.2.1/games/star_ship/__pycache__/game.cpython-312.pyc +0 -0
  14. cli_arcade-2026.2.1/games/terminal_tumble/__pycache__/game.cpython-312.pyc +0 -0
  15. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/setup.cfg +1 -1
  16. cli_arcade-2026.2.0/game_classes/__pycache__/ptk.cpython-313.pyc +0 -0
  17. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/LICENSE +0 -0
  18. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/MANIFEST.in +0 -0
  19. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/README.md +0 -0
  20. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/cli.py +0 -0
  21. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__init__.py +0 -0
  22. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/__init__.cpython-313.pyc +0 -0
  23. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/game_base.cpython-313.pyc +0 -0
  24. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/highscores.cpython-313.pyc +0 -0
  25. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/menu.cpython-313.pyc +0 -0
  26. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/ptk_curses.cpython-313.pyc +0 -0
  27. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/ptk_game_base.cpython-313.pyc +0 -0
  28. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/ptk_menu.cpython-313.pyc +0 -0
  29. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/ptk_tools.cpython-313.pyc +0 -0
  30. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/__pycache__/tools.cpython-313.pyc +0 -0
  31. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/game_base.py +0 -0
  32. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/highscores.py +0 -0
  33. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/menu.py +0 -0
  34. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/game_classes/tools.py +0 -0
  35. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/__init__.py +0 -0
  36. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/byte_bouncer/__init__.py +0 -0
  37. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/byte_bouncer/__pycache__/byte_bouncer.cpython-313.pyc +0 -0
  38. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/byte_bouncer/__pycache__/game.cpython-313.pyc +0 -0
  39. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/byte_bouncer/__pycache__/highscores.cpython-313.pyc +0 -0
  40. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/byte_bouncer/game.py +0 -0
  41. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/star_ship/__init__.py +0 -0
  42. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/star_ship/__pycache__/game.cpython-313.pyc +0 -0
  43. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/star_ship/__pycache__/highscores.cpython-313.pyc +0 -0
  44. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/star_ship/__pycache__/nibbles.cpython-313.pyc +0 -0
  45. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/star_ship/__pycache__/snek.cpython-313.pyc +0 -0
  46. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/star_ship/__pycache__/star_ship.cpython-313.pyc +0 -0
  47. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/star_ship/game.py +0 -0
  48. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/terminal_tumble/__init__.py +0 -0
  49. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/terminal_tumble/__pycache__/game.cpython-313.pyc +0 -0
  50. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/terminal_tumble/__pycache__/highscores.cpython-313.pyc +0 -0
  51. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/terminal_tumble/__pycache__/terminal_tumble.cpython-313.pyc +0 -0
  52. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/games/terminal_tumble/game.py +0 -0
  53. {cli_arcade-2026.2.0 → cli_arcade-2026.2.1}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cli-arcade
3
- Version: 2026.2.0
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.
@@ -63,3 +63,6 @@ All notable changes to this project will be documented in this file.
63
63
  - Byte Bouncer & Star Ship: floor + off-screen right wall; left-column bug fixed.
64
64
  - `ptk`: default-attribute/color emission fix; add helper to exit alt screen.
65
65
  - Fixed 180 movement glitch in Star Ship.
66
+
67
+ ### 2026.2.1
68
+ - Updated key mapping to work with Linux and macOS terminals.
@@ -11,24 +11,32 @@ game_classes/highscores.py
11
11
  game_classes/menu.py
12
12
  game_classes/ptk.py
13
13
  game_classes/tools.py
14
+ game_classes/__pycache__/__init__.cpython-312.pyc
14
15
  game_classes/__pycache__/__init__.cpython-313.pyc
16
+ game_classes/__pycache__/game_base.cpython-312.pyc
15
17
  game_classes/__pycache__/game_base.cpython-313.pyc
18
+ game_classes/__pycache__/highscores.cpython-312.pyc
16
19
  game_classes/__pycache__/highscores.cpython-313.pyc
20
+ game_classes/__pycache__/menu.cpython-312.pyc
17
21
  game_classes/__pycache__/menu.cpython-313.pyc
22
+ game_classes/__pycache__/ptk.cpython-312.pyc
18
23
  game_classes/__pycache__/ptk.cpython-313.pyc
19
24
  game_classes/__pycache__/ptk_curses.cpython-313.pyc
20
25
  game_classes/__pycache__/ptk_game_base.cpython-313.pyc
21
26
  game_classes/__pycache__/ptk_menu.cpython-313.pyc
22
27
  game_classes/__pycache__/ptk_tools.cpython-313.pyc
28
+ game_classes/__pycache__/tools.cpython-312.pyc
23
29
  game_classes/__pycache__/tools.cpython-313.pyc
24
30
  games/__init__.py
25
31
  games/byte_bouncer/__init__.py
26
32
  games/byte_bouncer/game.py
27
33
  games/byte_bouncer/__pycache__/byte_bouncer.cpython-313.pyc
34
+ games/byte_bouncer/__pycache__/game.cpython-312.pyc
28
35
  games/byte_bouncer/__pycache__/game.cpython-313.pyc
29
36
  games/byte_bouncer/__pycache__/highscores.cpython-313.pyc
30
37
  games/star_ship/__init__.py
31
38
  games/star_ship/game.py
39
+ games/star_ship/__pycache__/game.cpython-312.pyc
32
40
  games/star_ship/__pycache__/game.cpython-313.pyc
33
41
  games/star_ship/__pycache__/highscores.cpython-313.pyc
34
42
  games/star_ship/__pycache__/nibbles.cpython-313.pyc
@@ -36,6 +44,7 @@ games/star_ship/__pycache__/snek.cpython-313.pyc
36
44
  games/star_ship/__pycache__/star_ship.cpython-313.pyc
37
45
  games/terminal_tumble/__init__.py
38
46
  games/terminal_tumble/game.py
47
+ games/terminal_tumble/__pycache__/game.cpython-312.pyc
39
48
  games/terminal_tumble/__pycache__/game.cpython-313.pyc
40
49
  games/terminal_tumble/__pycache__/highscores.cpython-313.pyc
41
50
  games/terminal_tumble/__pycache__/terminal_tumble.cpython-313.pyc
@@ -5,8 +5,24 @@ import threading
5
5
  import queue
6
6
  import time
7
7
 
8
- from prompt_toolkit.input import create_input
9
- from prompt_toolkit.keys import Keys
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
- self._input = create_input()
97
- self._thread = threading.Thread(target=self._reader, daemon=True)
98
- self._thread.start()
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
 
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = cli-arcade
3
- version = 2026.2.0
3
+ version = 2026.2.1
4
4
  description = Collection of terminal CLI games
5
5
  author = Bro Code Technologies LLC
6
6
  author_email = info@brocodetechnologies.com
File without changes
File without changes
File without changes
File without changes