2022-04-24 15:43:34 -05:00
|
|
|
from os import path
|
2022-04-24 13:32:14 -05:00
|
|
|
from enum import Enum, auto
|
2022-04-24 15:43:34 -05:00
|
|
|
import re
|
|
|
|
import itertools
|
|
|
|
from cinput import ControlInput, Button
|
2022-04-24 10:07:39 -05:00
|
|
|
from graphics import Graphics
|
|
|
|
from .draw import Draw
|
2022-04-24 15:43:34 -05:00
|
|
|
from . import sunfish
|
2022-04-24 10:07:39 -05:00
|
|
|
|
2022-04-24 13:32:14 -05:00
|
|
|
class GameState(Enum):
|
|
|
|
MAIN_MENU = auto()
|
2022-04-24 15:43:34 -05:00
|
|
|
PLAYING = auto()
|
2022-04-24 13:32:14 -05:00
|
|
|
THINKING = auto()
|
|
|
|
CHOOSE_ROW = auto()
|
|
|
|
CHOOSE_COL = auto()
|
|
|
|
GAME_OVER = auto()
|
|
|
|
|
2022-04-24 15:43:34 -05:00
|
|
|
SAVE_FILE = path.join("data", "chess_state.fen")
|
|
|
|
|
2022-04-24 10:07:39 -05:00
|
|
|
def execute(cinput: ControlInput, graphics: Graphics, _):
|
2022-04-24 13:32:14 -05:00
|
|
|
graphics.clear()
|
2022-04-24 10:07:39 -05:00
|
|
|
draw = Draw(graphics)
|
2022-04-24 15:43:34 -05:00
|
|
|
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)
|
2022-04-24 13:32:14 -05:00
|
|
|
|
|
|
|
state = GameState.MAIN_MENU
|
|
|
|
menu_index = 0
|
2022-04-24 10:07:39 -05:00
|
|
|
|
|
|
|
while True:
|
2022-04-24 13:32:14 -05:00
|
|
|
if state == GameState.MAIN_MENU:
|
|
|
|
draw.draw_menu(menu_index)
|
2022-04-24 15:43:34 -05:00
|
|
|
elif state == GameState.PLAYING:
|
|
|
|
draw.draw_state()
|
2022-04-24 13:32:14 -05:00
|
|
|
|
|
|
|
key = cinput.get_one_shot()
|
|
|
|
if state == GameState.MAIN_MENU:
|
|
|
|
if key == Button.DIR_U:
|
|
|
|
menu_index -= 1
|
|
|
|
if menu_index < 0:
|
|
|
|
menu_index = 0
|
|
|
|
elif key == Button.DIR_D:
|
|
|
|
menu_index += 1
|
2022-04-24 15:43:34 -05:00
|
|
|
if menu_index > 3:
|
|
|
|
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))
|