Restructured project from nested workspace pattern to flat single-repo layout. This eliminates redundant nesting and consolidates all project files under version control. ## Migration Summary **Before:** ``` alex/ (workspace, not versioned) ├── chess-game/ (git repo) │ ├── js/, css/, tests/ │ └── index.html └── docs/ (planning, not versioned) ``` **After:** ``` alex/ (git repo, everything versioned) ├── js/, css/, tests/ ├── index.html ├── docs/ (project documentation) ├── planning/ (historical planning docs) ├── .gitea/ (CI/CD) └── CLAUDE.md (configuration) ``` ## Changes Made ### Structure Consolidation - Moved all chess-game/ contents to root level - Removed redundant chess-game/ subdirectory - Flattened directory structure (eliminated one nesting level) ### Documentation Organization - Moved chess-game/docs/ → docs/ (project documentation) - Moved alex/docs/ → planning/ (historical planning documents) - Added CLAUDE.md (workspace configuration) - Added IMPLEMENTATION_PROMPT.md (original project prompt) ### Version Control Improvements - All project files now under version control - Planning documents preserved in planning/ folder - Merged .gitignore files (workspace + project) - Added .claude/ agent configurations ### File Updates - Updated .gitignore to include both workspace and project excludes - Moved README.md to root level - All import paths remain functional (relative paths unchanged) ## Benefits ✅ **Simpler Structure** - One level of nesting removed ✅ **Complete Versioning** - All documentation now in git ✅ **Standard Layout** - Matches open-source project conventions ✅ **Easier Navigation** - Direct access to all project files ✅ **CI/CD Compatible** - All workflows still functional ## Technical Validation - ✅ Node.js environment verified - ✅ Dependencies installed successfully - ✅ Dev server starts and responds - ✅ All core files present and accessible - ✅ Git repository functional ## Files Preserved **Implementation Files:** - js/ (3,517 lines of code) - css/ (4 stylesheets) - tests/ (87 test cases) - index.html - package.json **CI/CD Pipeline:** - .gitea/workflows/ci.yml - .gitea/workflows/release.yml **Documentation:** - docs/ (12+ documentation files) - planning/ (historical planning materials) - README.md **Configuration:** - jest.config.js, babel.config.cjs, playwright.config.js - .gitignore (merged) - CLAUDE.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
185 lines
4.5 KiB
JavaScript
185 lines
4.5 KiB
JavaScript
/**
|
|
* @file knight-king-pattern.js
|
|
* @description Pattern for implementing non-sliding pieces (Knight, King)
|
|
* These pieces jump to specific positions
|
|
*/
|
|
|
|
import Piece from '../models/Piece.js';
|
|
import { DIRECTIONS } from '../utils/Constants.js';
|
|
import { isValidPosition } from '../utils/Helpers.js';
|
|
|
|
/**
|
|
* @class Knight
|
|
* @extends Piece
|
|
* @description Knight implementation using jump pattern
|
|
*
|
|
* Knight moves in L-shape: 2 squares in one direction, 1 square perpendicular
|
|
* Can jump over other pieces
|
|
*/
|
|
class Knight extends Piece {
|
|
constructor(color, position) {
|
|
super(color, position, 'knight');
|
|
}
|
|
|
|
/**
|
|
* Gets all valid moves for this knight
|
|
*
|
|
* @param {Board} board - Current board state
|
|
* @returns {Array<Object>} Array of valid positions
|
|
*/
|
|
getValidMoves(board) {
|
|
const moves = [];
|
|
const { row, col } = this.position;
|
|
|
|
// Knight has 8 possible L-shaped moves
|
|
const knightMoves = DIRECTIONS.KNIGHT;
|
|
|
|
// Check each possible move
|
|
for (const move of knightMoves) {
|
|
const newPos = {
|
|
row: row + move.row,
|
|
col: col + move.col
|
|
};
|
|
|
|
// Check if position is valid (on board)
|
|
if (!isValidPosition(newPos.row, newPos.col)) {
|
|
continue;
|
|
}
|
|
|
|
const piece = board.getPieceAt(newPos);
|
|
|
|
// Can move to empty square or capture enemy
|
|
if (!piece || piece.color !== this.color) {
|
|
moves.push(newPos);
|
|
}
|
|
}
|
|
|
|
return moves;
|
|
}
|
|
|
|
clone() {
|
|
const clone = new Knight(this.color, { ...this.position });
|
|
clone.hasMoved = this.hasMoved;
|
|
return clone;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @class King
|
|
* @extends Piece
|
|
* @description King implementation using adjacent square pattern
|
|
*
|
|
* King moves one square in any direction
|
|
* Special move: Castling (handled separately)
|
|
*/
|
|
class King extends Piece {
|
|
constructor(color, position) {
|
|
super(color, position, 'king');
|
|
}
|
|
|
|
/**
|
|
* Gets all valid moves for this king
|
|
*
|
|
* @param {Board} board - Current board state
|
|
* @returns {Array<Object>} Array of valid positions
|
|
*/
|
|
getValidMoves(board) {
|
|
const moves = [];
|
|
const { row, col } = this.position;
|
|
|
|
// King can move one square in 8 directions
|
|
const directions = [...DIRECTIONS.ORTHOGONAL, ...DIRECTIONS.DIAGONAL];
|
|
|
|
// Check each adjacent square
|
|
for (const direction of directions) {
|
|
const newPos = {
|
|
row: row + direction.row,
|
|
col: col + direction.col
|
|
};
|
|
|
|
// Check if position is valid
|
|
if (!isValidPosition(newPos.row, newPos.col)) {
|
|
continue;
|
|
}
|
|
|
|
const piece = board.getPieceAt(newPos);
|
|
|
|
// Can move to empty square or capture enemy
|
|
if (!piece || piece.color !== this.color) {
|
|
moves.push(newPos);
|
|
}
|
|
}
|
|
|
|
// TODO: Add castling moves
|
|
// Only if king hasn't moved
|
|
// Only if rook hasn't moved
|
|
// Only if squares between are empty
|
|
// Only if king is not in check
|
|
// Only if king doesn't pass through check
|
|
// See castling example in special-moves.js
|
|
|
|
return moves;
|
|
}
|
|
|
|
/**
|
|
* Checks if king can castle kingside
|
|
*
|
|
* @param {Board} board - Current board state
|
|
* @returns {boolean} True if kingside castling is legal
|
|
*/
|
|
canCastleKingside(board) {
|
|
// TODO: Implement castling validation
|
|
// This is complex and often handled in RuleEngine
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Checks if king can castle queenside
|
|
*
|
|
* @param {Board} board - Current board state
|
|
* @returns {boolean} True if queenside castling is legal
|
|
*/
|
|
canCastleQueenside(board) {
|
|
// TODO: Implement castling validation
|
|
return false;
|
|
}
|
|
|
|
clone() {
|
|
const clone = new King(this.color, { ...this.position });
|
|
clone.hasMoved = this.hasMoved;
|
|
return clone;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PATTERN SUMMARY - NON-SLIDING PIECES:
|
|
*
|
|
* Unlike sliding pieces, these pieces:
|
|
* 1. Have a fixed set of possible moves (no sliding)
|
|
* 2. Can't be blocked (Knight) or move only 1 square (King)
|
|
* 3. Check each possible position directly
|
|
*
|
|
* Algorithm:
|
|
* 1. Get all possible move offsets
|
|
* 2. For each offset:
|
|
* a. Calculate new position
|
|
* b. Validate position is on board
|
|
* c. Check if square is empty or has enemy
|
|
* d. Add to moves if valid
|
|
*
|
|
* DIFFERENCE FROM SLIDING:
|
|
* - Sliding: Loop until blocked
|
|
* - Non-sliding: Check each position once
|
|
*
|
|
* KNIGHT SPECIAL:
|
|
* - Only piece that can jump over others
|
|
* - Don't need to check path, only destination
|
|
*
|
|
* KING SPECIAL:
|
|
* - Must not move into check (validated elsewhere)
|
|
* - Castling is complex special move
|
|
* - Usually limited to 8 moves, but critical to protect
|
|
*/
|
|
|
|
export { Knight, King };
|