cli-othello 1.0.1__tar.gz → 1.0.2__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.
- {cli_othello-1.0.1 → cli_othello-1.0.2}/PKG-INFO +1 -1
- {cli_othello-1.0.1 → cli_othello-1.0.2}/pyproject.toml +1 -1
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello/__init__.py +1 -1
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello/ui.py +57 -9
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello.egg-info/PKG-INFO +1 -1
- {cli_othello-1.0.1 → cli_othello-1.0.2}/README.md +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/setup.cfg +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello/ai.py +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello/board.py +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello/cli.py +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello.egg-info/SOURCES.txt +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello.egg-info/dependency_links.txt +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello.egg-info/entry_points.txt +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello.egg-info/requires.txt +0 -0
- {cli_othello-1.0.1 → cli_othello-1.0.2}/src/cli_othello.egg-info/top_level.txt +0 -0
|
@@ -52,8 +52,14 @@ def select_level(stdscr: "curses._CursesWindow") -> int:
|
|
|
52
52
|
"""Let the user pick an AI difficulty level (1-5) with arrow keys."""
|
|
53
53
|
level = 3
|
|
54
54
|
curses.curs_set(0)
|
|
55
|
+
required_rows = 5 + MAX_LEVEL + 3
|
|
56
|
+
required_cols = 36
|
|
55
57
|
while True:
|
|
56
58
|
stdscr.erase()
|
|
59
|
+
max_y, max_x = stdscr.getmaxyx()
|
|
60
|
+
if max_y < required_rows or max_x < required_cols:
|
|
61
|
+
_draw_too_small(stdscr)
|
|
62
|
+
continue
|
|
57
63
|
stdscr.addstr(1, 2, "♟ CLI OTHELLO", curses.color_pair(COLOR_HEADER) | curses.A_BOLD)
|
|
58
64
|
stdscr.addstr(3, 2, "対戦するAIの強さを選んでください", curses.A_BOLD)
|
|
59
65
|
for i in range(MIN_LEVEL, MAX_LEVEL + 1):
|
|
@@ -106,6 +112,28 @@ def _cell_center_attr(cell: int, is_cursor: bool, is_hint: bool) -> tuple[int, s
|
|
|
106
112
|
return fill, " "
|
|
107
113
|
|
|
108
114
|
|
|
115
|
+
def _required_size() -> tuple[int, int]:
|
|
116
|
+
"""Return (rows, cols) needed to draw the board and panel, plus a
|
|
117
|
+
1-line/1-column margin (curses can refuse writes to the very last
|
|
118
|
+
row/column of the screen)."""
|
|
119
|
+
rows = 3 + 1 + SIZE * CELL_H + 6 + 1
|
|
120
|
+
cols = 4 + 3 + SIZE * CELL_W + 1
|
|
121
|
+
return rows, cols
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _draw_too_small(stdscr: "curses._CursesWindow") -> None:
|
|
125
|
+
rows, cols = _required_size()
|
|
126
|
+
stdscr.erase()
|
|
127
|
+
try:
|
|
128
|
+
stdscr.addstr(0, 0, "ターミナルが小さすぎます。")
|
|
129
|
+
stdscr.addstr(1, 0, f"必要サイズ: {cols}列 x {rows}行 以上")
|
|
130
|
+
stdscr.addstr(2, 0, "ウィンドウを大きくしてください。何かキーを押すと終了します。")
|
|
131
|
+
except curses.error:
|
|
132
|
+
pass
|
|
133
|
+
stdscr.refresh()
|
|
134
|
+
stdscr.getch()
|
|
135
|
+
|
|
136
|
+
|
|
109
137
|
def _draw_board(
|
|
110
138
|
stdscr: "curses._CursesWindow",
|
|
111
139
|
board: Board,
|
|
@@ -115,7 +143,15 @@ def _draw_board(
|
|
|
115
143
|
ai_level: int,
|
|
116
144
|
message: str,
|
|
117
145
|
top: int = 0,
|
|
118
|
-
) ->
|
|
146
|
+
) -> bool:
|
|
147
|
+
"""Draw the board. Returns False (and shows a hint) if the terminal is
|
|
148
|
+
too small to fit it."""
|
|
149
|
+
required_rows, required_cols = _required_size()
|
|
150
|
+
max_y, max_x = stdscr.getmaxyx()
|
|
151
|
+
if max_y < required_rows or max_x < required_cols:
|
|
152
|
+
_draw_too_small(stdscr)
|
|
153
|
+
return False
|
|
154
|
+
|
|
119
155
|
stdscr.erase()
|
|
120
156
|
stdscr.addstr(top, 2, "♟ CLI OTHELLO", curses.color_pair(COLOR_HEADER) | curses.A_BOLD)
|
|
121
157
|
stdscr.addstr(
|
|
@@ -184,6 +220,7 @@ def _draw_board(
|
|
|
184
220
|
curses.color_pair(COLOR_STATUS),
|
|
185
221
|
)
|
|
186
222
|
stdscr.refresh()
|
|
223
|
+
return True
|
|
187
224
|
|
|
188
225
|
|
|
189
226
|
def play_game(stdscr: "curses._CursesWindow", human_player: int, ai_level: int) -> None:
|
|
@@ -207,7 +244,10 @@ def play_game(stdscr: "curses._CursesWindow", human_player: int, ai_level: int)
|
|
|
207
244
|
|
|
208
245
|
if turn == human_player:
|
|
209
246
|
message = "あなたの番です"
|
|
210
|
-
|
|
247
|
+
if not _draw_board(
|
|
248
|
+
stdscr, board, tuple(cursor), legal, human_player, ai_level, message
|
|
249
|
+
):
|
|
250
|
+
continue
|
|
211
251
|
key = stdscr.getch()
|
|
212
252
|
if key in (curses.KEY_UP, ord("k")):
|
|
213
253
|
cursor[0] = (cursor[0] - 1) % SIZE
|
|
@@ -228,6 +268,9 @@ def play_game(stdscr: "curses._CursesWindow", human_player: int, ai_level: int)
|
|
|
228
268
|
else:
|
|
229
269
|
message = "AIが考えています…"
|
|
230
270
|
_draw_board(stdscr, board, tuple(cursor), legal, human_player, ai_level, message)
|
|
271
|
+
# If the terminal is too small, _draw_too_small() already
|
|
272
|
+
# blocked on a keypress above; proceed with the AI move
|
|
273
|
+
# regardless so the game keeps progressing once resized.
|
|
231
274
|
move = ai.choose_move(board)
|
|
232
275
|
if move is not None:
|
|
233
276
|
board.play(*move, turn)
|
|
@@ -240,13 +283,18 @@ def play_game(stdscr: "curses._CursesWindow", human_player: int, ai_level: int)
|
|
|
240
283
|
result = "あなたの勝ちです!"
|
|
241
284
|
else:
|
|
242
285
|
result = "AIの勝ちです"
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
)
|
|
286
|
+
|
|
287
|
+
while not _draw_board(
|
|
288
|
+
stdscr, board, tuple(cursor), set(), human_player, ai_level, result
|
|
289
|
+
):
|
|
290
|
+
pass
|
|
291
|
+
|
|
292
|
+
max_y, max_x = stdscr.getmaxyx()
|
|
293
|
+
footer_y = min(SIZE + 8, max_y - 1)
|
|
294
|
+
try:
|
|
295
|
+
stdscr.addstr(footer_y, 4, "何かキーを押すと終了します", curses.color_pair(COLOR_STATUS))
|
|
296
|
+
except curses.error:
|
|
297
|
+
pass
|
|
250
298
|
stdscr.refresh()
|
|
251
299
|
stdscr.getch()
|
|
252
300
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|