-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
Summary
Add FEN (Forsyth-Edwards Notation) support to enable loading arbitrary board positions. This is critical infrastructure for testing new features without playing through complete games, and provides a debugging interface for development.
What is FEN?
FEN is a standard notation for describing chess positions in a single line string.
Example: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
Format: [piece placement] [active color] [castling rights] [en passant] [halfmove] [fullmove]
- Piece placement: 8 ranks separated by
/, lowercase = black, uppercase = white - Active color:
worb - Castling rights:
KQkq(King/Queenside for white/black) or-if none - En passant: Target square (e.g.,
e3) or-if none - Halfmove clock: Moves since last pawn move or capture (for 50-move rule)
- Fullmove number: Increments after black's move
Implementation Requirements
Backend (Python)
1. Add load_fen(fen_string) method to ChessBoard
def load_fen(self, fen_string):
"""
Parse FEN string and initialize board state.
Args:
fen_string: Valid FEN notation string
Returns:
Game state JSON (same as game_to_json)
Raises:
ValueError: If FEN string is invalid
"""Must handle:
- Parse piece placement and create appropriate Piece objects
- Set
self.turnbased on active color - Set castling flags (
white_king_moved,white_rook_a_moved, etc.) - Store en passant target square for pawn validation
- Clear and rebuild
self.moveshistory (or mark as loaded position)
2. Add to_fen() method to ChessBoard
def to_fen(self):
"""
Export current board state as FEN string.
Returns:
str: Valid FEN notation of current position
"""3. Add WebSocket callbacks
self.add_callback("load_fen", lambda obj: self.load_fen(obj['fen']))
self.add_callback("get_fixtures", lambda obj: self.get_fixtures())4. Create test fixtures module
Create engine/fixtures.py:
POSITIONS = {
# Basic positions
"starting": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"empty": "8/8/8/8/8/8/8/8 w - - 0 1",
# Checkmate positions
"fools_mate": "rnb1kbnr/pppp1ppp/4p3/8/6Pq/5P2/PPPPP2P/RNBQKBNR w KQkq - 1 3",
"scholars_mate": "r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4",
"back_rank_mate": "6k1/5ppp/8/8/8/8/8/R3K3 b Q - 0 1",
# Special moves
"en_passant_white": "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 3",
"en_passant_black": "rnbqkbnr/pppp1ppp/8/8/3Pp3/8/PPP1PPPP/RNBQKBNR b KQkq d3 0 3",
"castling_available": "r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R w KQkq - 0 1",
"castling_kingside_only": "r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R w Kk - 0 1",
# Check scenarios
"white_in_check": "rnbqkbnr/ppppp1pp/8/5p1Q/4P3/8/PPPP1PPP/RNB1KBNR b KQkq - 1 2",
"double_check": "rnbqkb1r/pppp1ppp/5n2/4N3/2B1P3/8/PPPP1PPP/RNBQK2R b KQkq - 0 1",
"pinned_piece": "rnb1kbnr/pppp1ppp/8/4p3/7q/5NP1/PPPPP2P/RNBQKB1R w KQkq - 0 1",
# Pawn promotion
"promotion_ready_white": "8/P7/8/8/8/8/8/4K2k w - - 0 1",
"promotion_ready_black": "4K2k/8/8/8/8/8/p7/8 b - - 0 1",
# Stalemate
"stalemate": "k7/8/1K6/8/8/8/8/8 b - - 0 1",
}Frontend (Vue.js)
5. Update chess.js composable
Add methods for FEN operations:
const loadFen = (fen) => {
send(JSON.stringify({ load_fen: { fen } }));
};
// Export in useChess()
return {
// ... existing exports
loadFen,
};6. Create DebugPanel.vue component
Replace or enhance existing Debug.vue with a debugging interface:
Features:
- Text input for pasting FEN strings with "Load" button
- "Copy Current FEN" button to export current position
- Dropdown/select menu with categorized test fixtures:
- Checkmates (Fool's Mate, Scholar's Mate, Back Rank)
- Special Moves (En Passant, Castling scenarios)
- Check Scenarios (In Check, Pinned Piece, Double Check)
- Endgames (Stalemate, Promotion Ready)
- Display current game state (turn, move count)
- Reset button
7. Add toggle for debug panel
In App.vue:
- Add keyboard shortcut (press
Dkey) to show/hide debug panel - Or add a gear/debug icon button
- Only render in development mode using
import.meta.env.DEV
Testing
Unit Tests (Python)
Create tests/test_fen.py:
import pytest
from board import ChessBoard
from fixtures import POSITIONS
class TestFenParsing:
def test_load_starting_position(self):
board = ChessBoard()
board.load_fen(POSITIONS["starting"])
assert board.board[0][0].type == "Rook"
assert board.board[0][0].color == "dark"
assert board.board[7][4].type == "King"
assert board.board[7][4].color == "light"
assert board.turn == 0 # White to move
def test_roundtrip_fen(self):
board = ChessBoard()
original_fen = POSITIONS["starting"]
board.load_fen(original_fen)
exported_fen = board.to_fen()
assert exported_fen == original_fen
def test_castling_rights_parsed(self):
board = ChessBoard()
board.load_fen(POSITIONS["castling_kingside_only"])
assert board.white_king_moved == False
assert board.white_rook_h_moved == False
assert board.white_rook_a_moved == True # No Q in FEN
def test_en_passant_square_parsed(self):
board = ChessBoard()
board.load_fen(POSITIONS["en_passant_white"])
# Verify en passant capture is valid
result = board.can_move_piece("E5", "D6")
assert result['valid'] == True
assert result['special'] == 'en_passant'
def test_invalid_fen_raises_error(self):
board = ChessBoard()
with pytest.raises(ValueError):
board.load_fen("invalid fen string")Integration Tests
class TestFixtureScenarios:
def test_fools_mate_is_checkmate(self):
board = ChessBoard()
board.load_fen(POSITIONS["fools_mate"])
# Once check detection is implemented:
# assert board.is_checkmate('light') == True
def test_stalemate_position(self):
board = ChessBoard()
board.load_fen(POSITIONS["stalemate"])
# Once stalemate detection is implemented:
# assert board.is_stalemate('dark') == TrueAcceptance Criteria
-
load_fen()correctly parses all 6 FEN fields -
to_fen()produces valid FEN that can be re-loaded - Castling rights are correctly set from FEN
- En passant target square is correctly parsed and usable
- WebSocket
load_fenmessage loads position in UI - Debug panel allows loading FEN strings
- Debug panel has dropdown for common test fixtures
- Debug panel is only visible in development mode
- All unit tests pass
- Existing game functionality still works after loading FEN
References
- FEN Specification
- FEN on Wikipedia
- Related: Issue Use Data set to Automate Tests #70 (Use Data set to Automate Tests)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels