Skip to content

Commit

Permalink
Cached get_fog_fen()
Browse files Browse the repository at this point in the history
  • Loading branch information
gbtami committed Jan 2, 2025
1 parent bebec50 commit d3c897e
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 35 deletions.
2 changes: 1 addition & 1 deletion client/roundCtrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ export class RoundController extends GameController {
fen: parts[0],
turnColor: this.turnColor,
check: msg.check,
lastMove: (this.fog) ? undefined : lastMove,
lastMove: lastMove,
});

// This have to be here, because in case of takeback
Expand Down
54 changes: 29 additions & 25 deletions server/fairy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import logging
import re
import random
from functools import cache

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -228,31 +229,6 @@ def game_result_no_history(self):
def piece_to_partner(self, move):
return self.sf.piece_to_partner(self.variant, self.fen, [move], self.chess960)

def get_fog_fen(self, persp_color):
fen = self.fen
fen_color = "w" if self.color == WHITE else "b"
other_color = "w" if persp_color == WHITE else "b"

# set the perspective color to sf.get_fog_fen()
parts = self.fen.split(" ")
parts[1] = parts[1].replace(fen_color, other_color)

# remove castling right of the player in fog
if persp_color == WHITE:
parts[2] = "".join((letter for letter in parts[2] if letter.isupper()))
else:
parts[2] = "".join((letter for letter in parts[2] if letter.islower()))
fen = " ".join(parts)

fen = sf.get_fog_fen(fen, "fogofwar")

# restore original FEN color
parts = fen.split(" ")
parts[1] = parts[1].replace(other_color, fen_color)
fen = " ".join(parts)

return fen

def print_pos(self):
print()
uni_pieces = {
Expand Down Expand Up @@ -437,6 +413,34 @@ def shuffle_start(variant):
return fen


@cache
def get_fog_fen(fen, persp_color):
parts = fen.split(" ")

fen_color = "w" if parts[1] == "w" else "b"
opp_color = "w" if persp_color == WHITE else "b"

# set the perspective color to sf.get_fog_fen()
parts[1] = parts[1].replace(fen_color, opp_color)

# remove castling rights of the player in fog
# because the resulting fog FEN may have no king
if persp_color == WHITE:
parts[2] = "".join((letter for letter in parts[2] if letter.isupper()))
else:
parts[2] = "".join((letter for letter in parts[2] if letter.islower()))
fen = " ".join(parts)

fen = sf.get_fog_fen(fen, "fogofwar")

# restore original FEN color
parts = fen.split(" ")
parts[1] = parts[1].replace(opp_color, fen_color)
fen = " ".join(parts)

return fen


def get_san_moves(variant, fen, mlist, chess960, notation):
if variant == "alice":
return sf_alice.get_san_moves(variant, fen, mlist, chess960, notation)
Expand Down
26 changes: 17 additions & 9 deletions server/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
TYPE_CHECKING,
)
from convert import grand2zero, uci2usi, mirror5, mirror9
from fairy import get_san_moves, NOTATION_SAN, FairyBoard, BLACK, WHITE
from fairy import get_fog_fen, get_san_moves, NOTATION_SAN, FairyBoard, BLACK, WHITE
from glicko2.glicko2 import gl2
from draw import reject_draw
from settings import URI
Expand Down Expand Up @@ -1125,14 +1125,10 @@ def get_board(self, full=False, persp_color=None):
crosstable = self.crosstable if self.status > STARTED else ""

if self.fow and self.status <= STARTED:
if persp_color is not None:
fen = self.board.get_fog_fen(persp_color)
else:
fen = DARK_FEN

steps[-1]["fen"] = fen
steps[-1]["move"] = ""
lastmove = ""
steps = get_fog_steps(steps, persp_color)
fen = steps[-1]["fen"]
if (persp_color is None) or (persp_color == self.board.color):
lastmove = ""

if self.corr:
clock_mins = self.stopwatch.mins * 60 * 1000
Expand Down Expand Up @@ -1235,3 +1231,15 @@ def takeback(self):

def handle_chat_message(self, chat_message):
self.messages.append(chat_message)


def get_fog_steps(steps, persp_color):
if persp_color is None:
return [
{"fen": DARK_FEN} for step in steps
]
else:
return [
{"fen": get_fog_fen(step["fen"], persp_color), "san": "?", "turnColor": step["turnColor"]}
for step in steps
]
4 changes: 4 additions & 0 deletions server/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,10 @@ async def play_move(app_state: PychessGlobalAppState, user, game, move, clocks=N
await users[opp_name].send_game_message(gameId, response)

if not invalid_move:
# FEN sent to visitors is different in fogofwar games!
if game.fow:
board_response = game.get_board(full=game.board.ply == 1, persp_color=None)

await round_broadcast(game, board_response, channels=app_state.game_channels)

if game.tournamentId is not None:
Expand Down

0 comments on commit d3c897e

Please sign in to comment.