Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add JSDoc comments and documentation #184

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
run formatting
  • Loading branch information
StevenStavrakis committed Jun 3, 2024
commit f797aee11bfff73d636202b2e8fdfcb0c898e996
10 changes: 6 additions & 4 deletions src/attacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@ const KNIGHT_ATTACKS: BySquare<SquareSet> = tabulate(sq => computeRange(sq, [-17

/**
* A pre-computed table of pawn attacks for each square on the chessboard, separated by color.
* @type {{ white: BySquare<SquareSet>, black: BySquare<SquareSet> }}
* @type {{ white: BySquare<SquareSet>; black: BySquare<SquareSet> }}
*/
const PAWN_ATTACKS: { white: BySquare<SquareSet>, black: BySquare<SquareSet> } = {
const PAWN_ATTACKS: {
white: BySquare<SquareSet>;
black: BySquare<SquareSet>;
} = {
white: tabulate(sq => computeRange(sq, [7, 9])),
black: tabulate(sq => computeRange(sq, [-7, -9])),
};
Expand All @@ -88,7 +91,6 @@ export const knightAttacks = (square: Square): SquareSet => KNIGHT_ATTACKS[squar
*/
export const pawnAttacks = (color: Color, square: Square): SquareSet => PAWN_ATTACKS[color][square];


/**
* A pre-computed table of file ranges for each square on the chessboard.
*/
Expand Down Expand Up @@ -249,4 +251,4 @@ export const ray = (a: Square, b: Square): SquareSet => {
export const between = (a: Square, b: Square): SquareSet =>
ray(a, b)
.intersect(SquareSet.full().shl64(a).xor(SquareSet.full().shl64(b)))
.withoutFirst();
.withoutFirst();
4 changes: 2 additions & 2 deletions src/board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class Board implements Iterable<[Square, Piece]>, ByRole<SquareSet>, ByCo
/** @type {SquareSet} */
king: SquareSet;

private constructor() { }
private constructor() {}

/**
* Creates a new board with the default starting position for standard chess.
Expand Down Expand Up @@ -233,4 +233,4 @@ export class Board implements Iterable<[Square, Piece]>, ByRole<SquareSet>, ByCo
export const boardEquals = (left: Board, right: Board): boolean =>
left.white.equals(right.white)
&& left.promoted.equals(right.promoted)
&& ROLES.every(role => left[role].equals(right[role]));
&& ROLES.every(role => left[role].equals(right[role]));
122 changes: 59 additions & 63 deletions src/chess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export enum IllegalSetup {
* Custom error class for position errors.
* @extends Error
*/
export class PositionError extends Error { }
export class PositionError extends Error {}

/**
* Calculates the attacking squares for a given square and attacker color.
Expand All @@ -67,10 +67,9 @@ const attacksTo = (square: Square, attacker: Color, board: Board, occupied: Squa
.union(pawnAttacks(opposite(attacker), square).intersect(board.pawn)),
);


/**
* Represents the castling rights and related information for a chess position.
*/
* Represents the castling rights and related information for a chess position.
*/
export class Castles {
/**
* The castling rights as a set of squares.
Expand All @@ -94,7 +93,7 @@ export class Castles {
* Creates a new instance of the Castles class.
* @private
*/
private constructor() { }
private constructor() {}

/**
* Returns the default castling rights and setup.
Expand Down Expand Up @@ -306,7 +305,7 @@ export abstract class Position {
*/
fullmoves: number;

protected constructor(readonly rules: Rules) { }
protected constructor(readonly rules: Rules) {}

/**
* Resets the position to the starting position.
Expand Down Expand Up @@ -445,20 +444,20 @@ export abstract class Position {
}

/**
* Calculates the possible destination squares for a drop move.
* @param {Context} [_ctx] The optional context for the move generation.
* @returns {SquareSet} The set of possible destination squares for a drop move.
*/
* Calculates the possible destination squares for a drop move.
* @param {Context} [_ctx] The optional context for the move generation.
* @returns {SquareSet} The set of possible destination squares for a drop move.
*/
dropDests(_ctx?: Context): SquareSet {
return SquareSet.empty();
}

/**
* Calculates the possible destination squares for a piece on a given square.
* @param {Square} square The square of the piece.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {SquareSet} The set of possible destination squares.
*/
* Calculates the possible destination squares for a piece on a given square.
* @param {Square} square The square of the piece.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {SquareSet} The set of possible destination squares.
*/
dests(square: Square, ctx?: Context): SquareSet {
ctx = ctx || this.ctx();
if (ctx.variantEnd) return SquareSet.empty();
Expand Down Expand Up @@ -520,10 +519,10 @@ export abstract class Position {
}

/**
* Determines the outcome of the variant.
* @param {Context} [_ctx] The optional context for the position.
* @returns {Outcome | undefined} `undefined` by default. Subclasses can override this method.
*/
* Determines the outcome of the variant.
* @param {Context} [_ctx] The optional context for the position.
* @returns {Outcome | undefined} `undefined` by default. Subclasses can override this method.
*/
variantOutcome(_ctx?: Context): Outcome | undefined {
return;
}
Expand Down Expand Up @@ -577,10 +576,10 @@ export abstract class Position {
}

/**
* Checks if there are any possible destination squares for the current player's moves.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if there are possible destination squares, `false` otherwise.
*/
* Checks if there are any possible destination squares for the current player's moves.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if there are possible destination squares, `false` otherwise.
*/
hasDests(ctx?: Context): boolean {
ctx = ctx || this.ctx();
for (const square of this.board[this.turn]) {
Expand All @@ -589,11 +588,11 @@ export abstract class Position {
return this.dropDests(ctx).nonEmpty();
}
/**
* Checks if a given move is legal in the current position.
* @param {Move} move The move to check for legality.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if the move is legal, `false` otherwise.
*/
* Checks if a given move is legal in the current position.
* @param {Move} move The move to check for legality.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if the move is legal, `false` otherwise.
*/
isLegal(move: Move, ctx?: Context): boolean {
if (isDrop(move)) {
if (!this.pockets || this.pockets[this.turn][move.role] <= 0) return false;
Expand All @@ -609,49 +608,49 @@ export abstract class Position {
}

/**
* Checks if the current position is a check.
* @returns {boolean} `true` if the current position is a check, `false` otherwise.
*/
* Checks if the current position is a check.
* @returns {boolean} `true` if the current position is a check, `false` otherwise.
*/
isCheck(): boolean {
const king = this.board.kingOf(this.turn);
return defined(king) && this.kingAttackers(king, opposite(this.turn), this.board.occupied).nonEmpty();
}

/**
* Checks if the current position is an end position.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if the current position is an end position, `false` otherwise.
*/
* Checks if the current position is an end position.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if the current position is an end position, `false` otherwise.
*/
isEnd(ctx?: Context): boolean {
if (ctx ? ctx.variantEnd : this.isVariantEnd()) return true;
return this.isInsufficientMaterial() || !this.hasDests(ctx);
}

/**
* Checks if the current position is a checkmate.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if the current position is a checkmate, `false` otherwise.
*/
* Checks if the current position is a checkmate.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if the current position is a checkmate, `false` otherwise.
*/
isCheckmate(ctx?: Context): boolean {
ctx = ctx || this.ctx();
return !ctx.variantEnd && ctx.checkers.nonEmpty() && !this.hasDests(ctx);
}

/**
* Checks if the current position is a stalemate.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if the current position is a stalemate, `false` otherwise.
*/
* Checks if the current position is a stalemate.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {boolean} `true` if the current position is a stalemate, `false` otherwise.
*/
isStalemate(ctx?: Context): boolean {
ctx = ctx || this.ctx();
return !ctx.variantEnd && ctx.checkers.isEmpty() && !this.hasDests(ctx);
}

/**
* Determines the outcome of the current position.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {Outcome | undefined} The outcome of the current position, or undefined if the position is not an end position.
*/
* Determines the outcome of the current position.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {Outcome | undefined} The outcome of the current position, or undefined if the position is not an end position.
*/
outcome(ctx?: Context): Outcome | undefined {
const variantOutcome = this.variantOutcome(ctx);
if (variantOutcome) return variantOutcome;
Expand All @@ -662,10 +661,10 @@ export abstract class Position {
}

/**
* Calculates all possible destination squares for each piece of the current player.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {Map<Square, SquareSet>} A map of source squares to their corresponding sets of possible destination squares.
*/
* Calculates all possible destination squares for each piece of the current player.
* @param {Context} [ctx] The optional context for the move generation.
* @returns {Map<Square, SquareSet>} A map of source squares to their corresponding sets of possible destination squares.
*/
allDests(ctx?: Context): Map<Square, SquareSet> {
ctx = ctx || this.ctx();
const d = new Map();
Expand Down Expand Up @@ -793,7 +792,7 @@ const validEpSquare = (pos: Position, square: Square | undefined): Square | unde

/**
* Finds and returns all legal en passant squares in the position.
* @param {Position} pos
* @param {Position} pos
* @returns {Square | undefined}
*/
const legalEpSquare = (pos: Position): Square | undefined => {
Expand Down Expand Up @@ -830,12 +829,11 @@ const canCaptureEp = (pos: Position, pawnFrom: Square, ctx: Context): boolean =>
.isEmpty();
};


/**
* Checks various castling conditions and returns a set of squares that can be castled to.
* @param {Position} pos
* @param {CastlingSide} side
* @param {Context} ctx
* @param {Position} pos
* @param {CastlingSide} side
* @param {Context} ctx
* @returns {SquareSet} A set of squares that can be castled to. Can be empty.
*/
const castlingDest = (pos: Position, side: CastlingSide, ctx: Context): SquareSet => {
Expand All @@ -855,12 +853,10 @@ const castlingDest = (pos: Position, side: CastlingSide, ctx: Context): SquareSe
// Remove the king position
const occ = pos.board.occupied.without(ctx.king);


for (const sq of kingPath) {
if (pos.kingAttackers(sq, opposite(pos.turn), occ).nonEmpty()) return SquareSet.empty();
}


const rookTo = rookCastlesTo(pos.turn, side);
const after = pos.board.occupied.toggle(ctx.king).toggle(rook).toggle(rookTo);
if (pos.kingAttackers(kingTo, opposite(pos.turn), after).nonEmpty()) return SquareSet.empty();
Expand All @@ -870,12 +866,12 @@ const castlingDest = (pos: Position, side: CastlingSide, ctx: Context): SquareSe

/**
* Calculates the pseudo-legal destination squares for a given piece on a square.
*
* Pseudo-legal destinations refer to the set of squares that a piece can potentially move to, without
* considering the legality of the move in the context of the current position. They include moves that
* may be illegal, such as leaving the king in check. Pseudo-legal moves need to be further filtered to
*
* Pseudo-legal destinations refer to the set of squares that a piece can potentially move to, without
* considering the legality of the move in the context of the current position. They include moves that
* may be illegal, such as leaving the king in check. Pseudo-legal moves need to be further filtered to
* determine the actual legal moves in the given position.
*
*
* @param {Position} pos The chess position.
* @param {Square} square The square of the piece.
* @param {Context} ctx The context for the position.
Expand Down
8 changes: 4 additions & 4 deletions src/compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface ChessgroundDestsOpts {
* Includes both possible representations of castling moves (unless
* `chess960` mode is enabled), so that the `rookCastles` option will work
* correctly.
* @param {Position} pos
* @param {Position} pos
* @param {ChessgroundDestsOpts} [opts]
*/
export const chessgroundDests = (pos: Position, opts?: ChessgroundDestsOpts): Map<SquareName, SquareName[]> => {
Expand Down Expand Up @@ -68,7 +68,7 @@ export const scalachessCharPair = (move: Move): string =>

/**
* Converts chessops chess variant names to lichess chess rule names
* @param variant
* @param variant
* @returns {Rules}
*/
export const lichessRules = (
Expand Down Expand Up @@ -102,8 +102,8 @@ export const lichessRules = (

/**
* Conversts chessops rule name to lichess variant name.
* @param rules
* @returns
* @param rules
* @returns
*/
export const lichessVariant = (
rules: Rules,
Expand Down
8 changes: 3 additions & 5 deletions src/fen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export enum InvalidFen {
Fullmoves = 'ERR_FULLMOVES',
}

export class FenError extends Error { }
export class FenError extends Error {}

const nthIndexOf = (haystack: string, needle: string, n: number): number => {
let index = haystack.indexOf(needle);
Expand All @@ -48,7 +48,7 @@ const charToPiece = (ch: string): Piece | undefined => {
/**
* TODO: what is a "boardPart"?
* Takes a FEN and produces a Board object representing it
* @param boardPart
* @param boardPart
* @returns {Result<Board, FenError>}
*/
export const parseBoardFen = (boardPart: string): Result<Board, FenError> => {
Expand Down Expand Up @@ -149,7 +149,7 @@ export const parseCastlingFen = (board: Board, castlingPart: string): Result<Squ

/**
* Useful for three-check, four-check, n-check variants.
*
*
* Parses the remaining checks part of a FEN string and returns the corresponding RemainingChecks object.
*
* @param {string} part The remaining checks part of the FEN string.
Expand Down Expand Up @@ -378,7 +378,6 @@ export const makeBoardFen = (board: Board): string => {
return fen;
};


/**
* Converts a MaterialSide object to its string representation.
*
Expand Down Expand Up @@ -433,7 +432,6 @@ export const makeCastlingFen = (board: Board, castlingRights: SquareSet): string
*/
export const makeRemainingChecks = (checks: RemainingChecks): string => `${checks.white}+${checks.black}`;


/**
* Converts a Setup object to its FEN string representation.
*
Expand Down
Loading