ability to create new games as white or black

This commit is contained in:
Rudis Muiznieks 2022-04-24 15:43:34 -05:00
parent 7e721e7940
commit 39a3e33a06
Signed by: rudism
GPG Key ID: CABF2F86EF7884F9
3 changed files with 83 additions and 10 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
__pycache__/ __pycache__/
data/

View File

@ -1,20 +1,36 @@
from cinput import ControlInput, Button from os import path
from enum import Enum, auto from enum import Enum, auto
import re
import itertools
from cinput import ControlInput, Button
from graphics import Graphics from graphics import Graphics
from .draw import Draw from .draw import Draw
from .sunfish import initial from . import sunfish
class GameState(Enum): class GameState(Enum):
MAIN_MENU = auto() MAIN_MENU = auto()
PLAYING = auto()
THINKING = auto() THINKING = auto()
CHOOSE_ROW = auto() CHOOSE_ROW = auto()
CHOOSE_COL = auto() CHOOSE_COL = auto()
GAME_OVER = auto() GAME_OVER = auto()
SAVE_FILE = path.join("data", "chess_state.fen")
def execute(cinput: ControlInput, graphics: Graphics, _): def execute(cinput: ControlInput, graphics: Graphics, _):
graphics.clear() graphics.clear()
draw = Draw(graphics) draw = Draw(graphics)
draw.draw_board(initial) pos: sunfish.Position
if path.exists(SAVE_FILE):
with open(SAVE_FILE, "r") as fen:
fenstr = fen.read()
pos = parseFEN(fenstr)
else:
pos = sunfish.Position(
sunfish.initial, 0, (True,True), (True,True), 0, 0)
draw.draw_board(pos.board)
state = GameState.MAIN_MENU state = GameState.MAIN_MENU
menu_index = 0 menu_index = 0
@ -22,6 +38,8 @@ def execute(cinput: ControlInput, graphics: Graphics, _):
while True: while True:
if state == GameState.MAIN_MENU: if state == GameState.MAIN_MENU:
draw.draw_menu(menu_index) draw.draw_menu(menu_index)
elif state == GameState.PLAYING:
draw.draw_state()
key = cinput.get_one_shot() key = cinput.get_one_shot()
if state == GameState.MAIN_MENU: if state == GameState.MAIN_MENU:
@ -31,5 +49,52 @@ def execute(cinput: ControlInput, graphics: Graphics, _):
menu_index = 0 menu_index = 0
elif key == Button.DIR_D: elif key == Button.DIR_D:
menu_index += 1 menu_index += 1
if menu_index > 2: if menu_index > 3:
menu_index = 2 menu_index = 3
elif key == Button.BTN_B:
if menu_index == 0:
state = GameState.PLAYING
elif menu_index == 1:
with open(SAVE_FILE, "w") as fen:
fen.write(renderFEN(pos))
return
elif menu_index == 2 or menu_index == 3:
pos = sunfish.Position(
sunfish.initial, 0, (True,True), (True,True), 0, 0)
if menu_index == 3:
pos = pos.rotate()
draw.draw_board(pos.board)
state = GameState.PLAYING
elif state == GameState.PLAYING:
if key == Button.BTN_A:
state = GameState.MAIN_MENU
def get_color(pos):
return 1 if pos.board.startswith('\n') else 0
def parseFEN(fen):
""" Parses a string in Forsyth-Edwards Notation into a Position """
board, color, castling, enpas, _, _ = fen.split()
board = re.sub(r'\d', (lambda m: '.'*int(m.group(0))), board)
board = list(21*' ' + ' '.join(board.split('/')) + 21*' ')
board[9::10] = ['\n']*12
board = ''.join(board)
wc = ('Q' in castling, 'K' in castling)
bc = ('k' in castling, 'q' in castling)
ep = sunfish.parse(enpas) if enpas != '-' else 0
score = sum(sunfish.pst[p][i] for i,p in enumerate(board) if p.isupper())
score -= sum(sunfish.pst[p.upper()][119-i] for i,p in enumerate(board) if p.islower())
pos = sunfish.Position(board, score, wc, bc, ep, 0)
return pos if color == 'w' else pos.rotate()
def renderFEN(pos, half_move_clock=0, full_move_clock=1):
color = 'wb'[get_color(pos)]
if get_color(pos) == 1:
pos = pos.rotate()
board = '/'.join(pos.board.split())
board = re.sub(r'\.+', (lambda m: str(len(m.group(0)))), board)
castling = ''.join(itertools.compress('KQkq', pos.wc[::-1]+pos.bc)) or '-'
ep = sunfish.render(pos.ep) if not pos.board[pos.ep].isspace() else '-'
clock = '{} {}'.format(half_move_clock, full_move_clock)
return ' '.join((board, color, castling, ep, clock))

View File

@ -52,9 +52,10 @@ class Draw:
} }
MENU = [ MENU = [
"Play",
"Quit",
"New (W)", "New (W)",
"New (B)", "New (B)"]
"Quit"]
def __init__(self, graphics: Graphics): def __init__(self, graphics: Graphics):
self._graphics = graphics self._graphics = graphics
@ -78,11 +79,12 @@ class Draw:
self.BOARD_SIZE, 0, self.BOARD_SIZE, self.BOARD_SIZE, 0) self.BOARD_SIZE, 0, self.BOARD_SIZE, self.BOARD_SIZE, 0)
def draw_board(self, board: str): def draw_board(self, board: str):
ic(board)
is_black = board.startswith('\n')
self._graphics.fill_rect(0, 0, self.BOARD_SIZE, self.BOARD_SIZE, 0) self._graphics.fill_rect(0, 0, self.BOARD_SIZE, self.BOARD_SIZE, 0)
nb = "".join(board.split()) nb = "".join(board.split())
c = True c = True
for row in range(8): for row in range(8):
c = not c
for col in range(8): for col in range(8):
if c: if c:
x = col * self.SQUARE_SIZE x = col * self.SQUARE_SIZE
@ -90,9 +92,10 @@ class Draw:
self._graphics.fill_rect(x, y, self.SQUARE_SIZE, self.SQUARE_SIZE, 1) self._graphics.fill_rect(x, y, self.SQUARE_SIZE, self.SQUARE_SIZE, 1)
p = nb[(row * 8) + col] p = nb[(row * 8) + col]
if p.lower() in self.PIECES: if p.lower() in self.PIECES:
self._draw_piece(self.PIECES[p.lower()], p.isupper(), col, row, c) self._draw_piece(
self.PIECES[p.lower()], p.isupper() if not is_black else p.islower(), col, row, c)
c = not c c = not c
c = not c
self._graphics.show() self._graphics.show()
def draw_menu(self, menu_index: int): def draw_menu(self, menu_index: int):
@ -102,3 +105,7 @@ class Draw:
marker = "> " if i == menu_index else " " marker = "> " if i == menu_index else " "
self._graphics.text(marker + self.MENU[i], 12, i + 2, 1) self._graphics.text(marker + self.MENU[i], 12, i + 2, 1)
self._graphics.show() self._graphics.show()
def draw_state(self):
self._clear_info()
self._graphics.show()