diff --git a/cinput.py b/cinput.py index 17c487f..90d2d31 100644 --- a/cinput.py +++ b/cinput.py @@ -30,7 +30,7 @@ class ControlInput: self._buttons[button].direction = Direction.INPUT self._buttons[button].pull = Pull.UP - def get_one_shot(self, timeout = 0): + def get_one_shot(self, timeout: float = 0): started = time.time() while True: time.sleep(0.05) diff --git a/graphics.py b/graphics.py index bde4205..867a116 100644 --- a/graphics.py +++ b/graphics.py @@ -21,8 +21,8 @@ class Graphics: def text(self, text, x, y, c): self._display.text(text, x * self.CHAR_WIDTH, y * self.LINE_HEIGHT, c) - def pixel(self, x, y, c): - self._display.pixel(x, y, c) + def pixel(self, x, y, c = None): + return self._display.pixel(x, y, c) def line(self, x1, y1, x2, y2, c): self._display.line(x1, y1, x2, y2, c) diff --git a/plugin/chess/draw.py b/plugin/chess/draw.py index 1414276..78a92e4 100644 --- a/plugin/chess/draw.py +++ b/plugin/chess/draw.py @@ -1,7 +1,7 @@ from typing import Optional from icecream import ic from graphics import Graphics -from chess import Board, Outcome, Color, WHITE +import chess class Draw: BOARD_SIZE = 64 @@ -85,10 +85,44 @@ class Draw: return move.upper()[:2] + "-" + move.upper()[2:] return move - def draw_board(self, board: Board, player_color: Color): + def _invert_pixel(self, x: int, y: int): + c = self._graphics.pixel(x, y) + c = None if c != None else 1 + self._graphics.pixel(x, y, c) + + def _cursor_clear(self, except_for: list[str], player_color: chess.Color): + c = 0 + for row in range(8): + for col in range(8): + sqx = col if player_color == chess.WHITE else 7 - col + sqy = row if player_color == chess.BLACK else 7 - row + square = chr(sqx + 97) + str(sqy + 1) + if not (square in except_for): + # see if square is right color + sqc = self._graphics.pixel(sqx * 8, sqy * 8) + if sqc != c: + ic(square) + self._cursor(square, player_color); + c = 0 if c == 1 else 1 + c = 0 if c == 1 else 1 + + def _cursor(self, square: str, player_color: chess.Color): + sqx = ord(square[0]) - 97 + sqy = int(square[1]) - 1 + if player_color == chess.WHITE: + sqy = 7 - sqy + else: + sqx = 7 - sqx + for i in range(7): + self._invert_pixel(sqx * 8 + i, sqy * 8) + self._invert_pixel(sqx * 8 + i, sqy * 8 + 7) + self._invert_pixel(sqx * 8, sqy * 8 + i) + self._invert_pixel(sqx * 8 + 7, sqy * 8 + i) + + def draw_board(self, board: chess.Board, player_color: chess.Color): self._graphics.fill_rect(0, 0, self.BOARD_SIZE, self.BOARD_SIZE, 0) nb = "".join(str(board).split()).replace(" ", "") - nb = nb if player_color == WHITE else nb[::-1] + nb = nb if player_color == chess.WHITE else nb[::-1] c = True for row in range(8): for col in range(8): @@ -127,17 +161,25 @@ class Draw: "you win!" if player_won else "you lose!", 12, 2, 1) self._graphics.show() - def draw_select(self, last_move: str, src: str, dst = None): + def draw_select(self, board: chess.Board, last_move: str, player_color: chess.Color, src: Optional[str], dst: Optional[str] = None): self._clear_info() self._graphics.text(self._format_move(last_move), 12, 0, 1) self._graphics.text("You move:", 12, 2, 1) - if dst == None: + if src != None and dst == None: self._graphics.text("<" + src.upper() + "> - __", 12, 3, 1) - else: + #self._cursor_clear([src], player_color) + self._cursor(src, player_color) + elif src != None and dst != None: self._graphics.text(src.upper() + " - <" + dst.upper() + ">", 12, 3, 1) + #self._cursor_clear([src, dst], player_color) + self._cursor(src, player_color) + self._cursor(dst, player_color) + else: + self._cursor_clear(list(), player_color) + self._graphics.show() - def draw_game_over(self, outcome: Optional[Outcome]): + def draw_game_over(self, outcome: Optional[chess.Outcome]): self._clear_info() self._graphics.text("Game over", 12, 0, 1) if outcome != None: @@ -145,6 +187,6 @@ class Draw: self._graphics.text("Draw!", 12, 2, 1) else: self._graphics.text("Winner:", 12, 2, 1) - self._graphics.text("White!" if outcome.winner == WHITE else "Black!", + self._graphics.text("White!" if outcome.winner == chess.WHITE else "Black!", 12, 3, 1) self._graphics.show() diff --git a/plugin/chess/game.py b/plugin/chess/game.py index 2ad3635..f6c870a 100644 --- a/plugin/chess/game.py +++ b/plugin/chess/game.py @@ -1,4 +1,5 @@ from os import path +from typing import Optional from enum import Enum, auto import shutil from icecream import ic @@ -54,6 +55,11 @@ class ChessGame: self._sf.make_moves_from_current_position([move]) self._draw.draw_board(self._board, self._player_color) + def _square_sort_key(self, square: str): + # convert to number between 00 to 88 + key = (int(square[1]) - 1) * 10 + ord(square[0]) - 97 + return key if self._player_color == WHITE else 88 - key + def _get_sources(self): if len(list(self._all_moves)) == 0: moves = self._board.generate_legal_moves() @@ -63,7 +69,7 @@ class ChessGame: if len(list(self._all_moves)) > 0: return sorted( list(self._all_moves), - key=lambda x: x[::-1]) + key=lambda x: self._square_sort_key(x)) return list[str]() def _get_dests(self): @@ -71,7 +77,7 @@ class ChessGame: src = self._get_sources()[self._src_idx] return sorted( self._all_moves[src], - key=lambda x: x[::-1]) + key=lambda x: self._square_sort_key(x)) return list[str]() def run(self): @@ -79,8 +85,8 @@ class ChessGame: self._load_saved_or_init() while True: - key = None - src = None + key: Optional[Button] = None + src: Optional[str] = None ################ # HANDLE STATE # @@ -91,11 +97,13 @@ class ChessGame: # draw menu if self._state == GameState.MAIN_MENU: + self._draw.draw_board(self._board, self._player_color) self._draw.draw_menu(self._menu_index) key = self._cinput.get_one_shot() # computer makes a move elif self._state == GameState.THINKING: + self._draw.draw_board(self._board, self._player_color) self._draw.draw_thinking(self._move) move = self._sf.get_best_move_time(self.STOCKFISH_MOVE_TIME * 1000) if move != None: @@ -113,8 +121,8 @@ class ChessGame: srces = self._get_sources() if len(srces) > 0: src = srces[self._src_idx] - self._draw.draw_select(self._move, src) - key = self._cinput.get_one_shot() + self._draw.draw_select(self._board, self._move, self._player_color, src) + key = self._cinput.get_one_shot(0.1) else: self._state = GameState.GAME_OVER @@ -122,11 +130,12 @@ class ChessGame: elif self._state == GameState.CHOOSE_DST: src = self._get_sources()[self._src_idx] dst = self._get_dests()[self._dst_idx] - self._draw.draw_select(self._move, src, dst) - key = self._cinput.get_one_shot() + self._draw.draw_select(self._board, self._move, self._player_color, src, dst) + key = self._cinput.get_one_shot(0.1) # game has ended else: + self._draw.draw_board(self._board, self._player_color) self._draw.draw_game_over(self._board.outcome()) key = self._cinput.get_one_shot() @@ -134,6 +143,9 @@ class ChessGame: # HANDLE INPUT # ################ + if key == None: + continue + # handle user input on main menu if self._state == GameState.MAIN_MENU: @@ -166,6 +178,8 @@ class ChessGame: # TODO: some kind of cursor indicator on board elif self._state == GameState.CHOOSE_SRC: # move between source pieces + cur_src = self._get_sources()[self._src_idx] + if key == Button.DIR_D or key == Button.DIR_R: self._src_idx += 1 if self._src_idx >= len(self._all_moves.keys()):