From c0424c916f97b4f679592ed68a88f9f1ba530e13 Mon Sep 17 00:00:00 2001 From: Yoann Le Montagner Date: Sun, 1 Sep 2024 12:55:09 +0200 Subject: [PATCH] Code cleaning --- demo/movegeneration.js | 1 - demo/pgnparsing.js | 3 +- src/base_types.ts | 4 +- src/database.ts | 2 +- src/date_value.ts | 2 +- src/game.ts | 2 +- src/game_pojo.ts | 58 ++++++++++---------- src/helper.ts | 22 ++++---- src/i18n.ts | 2 +- src/position.ts | 15 ++--- src/private_game/node_variation_impl.ts | 4 +- src/private_pgn/pgn_read_impl.ts | 14 ++--- src/private_pgn/pgn_write_impl.ts | 4 +- src/private_pgn/token_stream.ts | 49 +++++++++-------- src/private_position/attacks.ts | 24 +++----- src/private_position/base_types_impl.ts | 3 + src/private_position/fen.ts | 4 +- src/private_position/impl.ts | 26 +++++---- src/private_position/legality.ts | 4 +- src/private_position/move_descriptor_impl.ts | 10 ++-- src/private_position/move_generation.ts | 40 +++++++------- src/private_position/notation.ts | 17 +++--- src/private_position/uci.ts | 2 +- test/02_helper.js | 10 ++-- test/03_position_base.js | 26 +++++---- test/04_position_fen.js | 23 ++++---- test/06_position_process.js | 52 +++++++++--------- test/08_movedescriptor.js | 24 ++++++++ test/11_game_tree.js | 6 +- test/common/dumpcastlingflags.js | 2 +- test/common/dumpgame.js | 4 +- test/common/readcsv.js | 2 +- test/common/readtext.js | 2 +- test/common/resourceexists.js | 2 +- 34 files changed, 246 insertions(+), 219 deletions(-) diff --git a/demo/movegeneration.js b/demo/movegeneration.js index 053bc59..e525fac 100644 --- a/demo/movegeneration.js +++ b/demo/movegeneration.js @@ -83,7 +83,6 @@ function run(fen, minDepth, maxDepth, verbose) { } - // ----------------------------------------------------------------------------- // Command line parsing // ----------------------------------------------------------------------------- diff --git a/demo/pgnparsing.js b/demo/pgnparsing.js index 76c83e9..2464044 100644 --- a/demo/pgnparsing.js +++ b/demo/pgnparsing.js @@ -116,13 +116,12 @@ function run(paths, pathAlignment) { 'Loading: ' + alignRight(duration2, 6) + ' ms'); } - for (const [path, error] of errors.entries()) { + for (const [ path, error ] of errors.entries()) { displayInvalidPGNError(path, error); } } - // ----------------------------------------------------------------------------- // Command line parsing // ----------------------------------------------------------------------------- diff --git a/src/base_types.ts b/src/base_types.ts index 41d9a5a..15c5e8c 100644 --- a/src/base_types.ts +++ b/src/base_types.ts @@ -103,7 +103,7 @@ export type Coordinates = { * - ... * - `7` for file H */ - file: number; + file: number, /** * - `0` for rank 1 @@ -111,7 +111,7 @@ export type Coordinates = { * - ... * - `7` for rank 8 */ - rank: number; + rank: number, }; diff --git a/src/database.ts b/src/database.ts index 8c71ae8..86d992a 100644 --- a/src/database.ts +++ b/src/database.ts @@ -82,7 +82,7 @@ export abstract class Database { return { [Symbol.iterator]() { return new GameIteratorImpl(gameCount, gameLoader); - } + }, }; } diff --git a/src/date_value.ts b/src/date_value.ts index e7b83e1..97ddbbf 100644 --- a/src/date_value.ts +++ b/src/date_value.ts @@ -265,7 +265,7 @@ function computeType(year: number, month?: number, day?: number): false | 'y' | return isValidYear(year) && isValidMonth(month) ? 'ym' : false; } else { - return isValidYear(year) ? 'y': false; + return isValidYear(year) ? 'y' : false; } } diff --git a/src/game.ts b/src/game.ts index 73bf282..62ad732 100644 --- a/src/game.ts +++ b/src/game.ts @@ -981,7 +981,7 @@ function formatPlayer(key: string, playerName: string | undefined, playerElo: nu result += ` (${playerElo})`; } else if (playerTitle !== undefined) { - result += ` (${trimCollapseAndMarkEmpty(playerTitle)})`; + result += ` (${trimCollapseAndMarkEmpty(playerTitle)})`; } return result; } diff --git a/src/game_pojo.ts b/src/game_pojo.ts index 4b13f46..7614993 100644 --- a/src/game_pojo.ts +++ b/src/game_pojo.ts @@ -29,9 +29,9 @@ import { GameResult, GameVariant } from './base_types'; * Represent the player-related headers in a {@link GamePOJO}. */ export type PlayerPOJO = { - name?: string; - elo?: number; - title?: string; + name?: string, + elo?: number, + title?: string, }; @@ -42,26 +42,26 @@ export type PlayerPOJO = { export type GamePOJO = { // Headers - white?: PlayerPOJO; - black?: PlayerPOJO; - event?: string; - round?: number; - subRound?: number; - subSubRound?: number; - date?: string; - site?: string; - annotator?: string; - eco?: string; - opening?: string; - openingVariation?: string; - openingSubVariation?: string; - termination?: string; - result?: GameResult; + white?: PlayerPOJO, + black?: PlayerPOJO, + event?: string, + round?: number, + subRound?: number, + subSubRound?: number, + date?: string, + site?: string, + annotator?: string, + eco?: string, + opening?: string, + openingVariation?: string, + openingSubVariation?: string, + termination?: string, + result?: GameResult, // Moves - variant?: GameVariant; - initialPosition?: string; - mainVariation?: VariationPOJO; + variant?: GameVariant, + initialPosition?: string, + mainVariation?: VariationPOJO, }; @@ -69,10 +69,10 @@ export type GamePOJO = { * Represent a {@link AbstractNode} in a {@link GamePOJO}. */ export type AbstractNodePOJO = { - comment?: string; - isLongComment?: boolean; - nags?: number[]; - tags?: Record; + comment?: string, + isLongComment?: boolean, + nags?: number[], + tags?: Record, }; @@ -80,8 +80,8 @@ export type AbstractNodePOJO = { * Represent a {@link Node} in a {@link GamePOJO}. */ export type NodePOJO = string | AbstractNodePOJO & { - notation: string; - variations?: VariationPOJO[]; + notation: string, + variations?: VariationPOJO[], }; @@ -89,6 +89,6 @@ export type NodePOJO = string | AbstractNodePOJO & { * Represent a {@link Variation} in a {@link GamePOJO}. */ export type VariationPOJO = NodePOJO[] | AbstractNodePOJO & { - nodes: NodePOJO[]; - isLongVariation?: boolean; + nodes: NodePOJO[], + isLongVariation?: boolean, }; diff --git a/src/helper.ts b/src/helper.ts index a8b257d..57e03b1 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -201,17 +201,18 @@ export function variantWithCanonicalStartPosition(variant: GameVariant): boolean const NAG_SYMBOLS = new Map(); -NAG_SYMBOLS.set( 1, '!', ); // good move -NAG_SYMBOLS.set( 2, '?', ); // bad move -NAG_SYMBOLS.set( 3, '!!', ); // very good move -NAG_SYMBOLS.set( 4, '??', ); // very bad move -NAG_SYMBOLS.set( 5, '!?', ); // interesting move -NAG_SYMBOLS.set( 6, '?!', ); // questionable move +/* eslint-disable @stylistic/no-multi-spaces, @stylistic/space-in-parens */ +NAG_SYMBOLS.set( 1, '!' ); // good move +NAG_SYMBOLS.set( 2, '?' ); // bad move +NAG_SYMBOLS.set( 3, '!!' ); // very good move +NAG_SYMBOLS.set( 4, '??' ); // very bad move +NAG_SYMBOLS.set( 5, '!?' ); // interesting move +NAG_SYMBOLS.set( 6, '?!' ); // questionable move NAG_SYMBOLS.set( 7, '\u25a1' ); // Only move NAG_SYMBOLS.set( 8, '\u25a1' ); // Only move (ChessBase) NAG_SYMBOLS.set( 9, '\u2612' ); // Worst move (Chess.com) -NAG_SYMBOLS.set( 10, '=', ); // equal position -NAG_SYMBOLS.set( 11, '=', ); // equal position (ChessBase) +NAG_SYMBOLS.set( 10, '=' ); // equal position +NAG_SYMBOLS.set( 11, '=' ); // equal position (ChessBase) NAG_SYMBOLS.set( 13, '\u221e' ); // unclear position NAG_SYMBOLS.set( 14, '\u2a72' ); // White has a slight advantage NAG_SYMBOLS.set( 15, '\u2a71' ); // Black has a slight advantage @@ -232,8 +233,9 @@ NAG_SYMBOLS.set(140, '\u2206' ); // With idea... NAG_SYMBOLS.set(141, '\u2207' ); // Aimed against... NAG_SYMBOLS.set(142, '\u2313' ); // Better is... NAG_SYMBOLS.set(143, '\u2264' ); // Worse is... -NAG_SYMBOLS.set(145, 'RR', ); // Editorial comment -NAG_SYMBOLS.set(146, 'N', ); // Novelty +NAG_SYMBOLS.set(145, 'RR' ); // Editorial comment +NAG_SYMBOLS.set(146, 'N' ); // Novelty +/* eslint-enable */ /** diff --git a/src/i18n.ts b/src/i18n.ts index 3818285..999904f 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -27,7 +27,7 @@ */ export namespace i18n { -/* eslint-disable prefer-const */ +/* eslint-disable prefer-const, @stylistic/indent, @stylistic/no-multi-spaces */ // WARNING: all those constants must be declared with "let" to allow them to be re-defined if necessary by consumer codes. // FEN parsing error messages diff --git a/src/position.ts b/src/position.ts index c4fe5c1..731d516 100644 --- a/src/position.ts +++ b/src/position.ts @@ -52,7 +52,6 @@ export class Position { private _impl: PositionImpl; - // ------------------------------------------------------------------------- // Constructor & reset/clear // ------------------------------------------------------------------------- @@ -267,7 +266,6 @@ export class Position { } - // ------------------------------------------------------------------------- // FEN & ASCII conversion // ------------------------------------------------------------------------- @@ -367,7 +365,6 @@ export class Position { } - // ------------------------------------------------------------------------- // Accessors // ------------------------------------------------------------------------- @@ -579,7 +576,6 @@ export class Position { } - // ------------------------------------------------------------------------- // Legality // ------------------------------------------------------------------------- @@ -621,7 +617,6 @@ export class Position { } - // ------------------------------------------------------------------------- // Move generation // ------------------------------------------------------------------------- @@ -841,7 +836,6 @@ export class Position { } - // ------------------------------------------------------------------------- // Algebraic notation // ------------------------------------------------------------------------- @@ -914,7 +908,6 @@ export class Position { } - // ------------------------------------------------------------------------- // UCI // ------------------------------------------------------------------------- @@ -971,8 +964,8 @@ export class Position { * @see {@link Position.isMoveLegal} */ export type RegularMoveFactory = { - status: 'regular'; - (): MoveDescriptor; + status: 'regular', + (): MoveDescriptor, }; @@ -980,8 +973,8 @@ export type RegularMoveFactory = { * @see {@link Position.isMoveLegal} */ export type PromotionMoveFactory = { - status: 'promotion'; - (promotion: Piece): MoveDescriptor; + status: 'promotion', + (promotion: Piece): MoveDescriptor, }; diff --git a/src/private_game/node_variation_impl.ts b/src/private_game/node_variation_impl.ts index 0eed4ee..afbfb14 100644 --- a/src/private_game/node_variation_impl.ts +++ b/src/private_game/node_variation_impl.ts @@ -654,7 +654,7 @@ function getTagKeys(data: AbstractNodeData) { */ function filterTags(data: AbstractNodeData, filter: (tagKey: string, tagValue: string) => boolean) { const result = new Map(); - for (const [tagKey, tagValue] of data.tags.entries()) { + for (const [ tagKey, tagValue ] of data.tags.entries()) { if (filter(tagKey, tagValue)) { result.set(tagKey, tagValue); } @@ -668,7 +668,7 @@ function filterTags(data: AbstractNodeData, filter: (tagKey: string, tagValue: s */ function getTagRecords(data: AbstractNodeData) { const result: Record = {}; - for (const [tagKey, tagValue] of data.tags.entries()) { + for (const [ tagKey, tagValue ] of data.tags.entries()) { result[tagKey] = tagValue; } return result; diff --git a/src/private_pgn/pgn_read_impl.ts b/src/private_pgn/pgn_read_impl.ts index 20f6395..eda6939 100644 --- a/src/private_pgn/pgn_read_impl.ts +++ b/src/private_pgn/pgn_read_impl.ts @@ -101,12 +101,12 @@ function parseVariant(value: string): GameVariant | undefined { interface InitialPositionFactory { - fen?: string; - fenTokenCharacterIndex?: number; - fenTokenLineIndex?: number; - variant?: GameVariant; - variantTokenCharacterIndex?: number; - variantTokenLineIndex?: number; + fen?: string, + fenTokenCharacterIndex?: number, + fenTokenLineIndex?: number, + variant?: GameVariant, + variantTokenCharacterIndex?: number, + variantTokenLineIndex?: number, } @@ -202,7 +202,7 @@ function doParseGame(stream: TokenStream) { const game = new Game(); // the result let endOfGameEncountered = false; let atLeastOneTokenFound = false; - let node: Node | Variation | null = null; // current node (or variation) to which the next move should be appended + let node: Node | Variation | null = null; // current node (or variation) to which the next move should be appended const nodeStack: (Node | Variation)[] = []; // when starting a variation, its parent node (btw., always a "true" node, not a variation) is stacked here const initialPositionFactory: InitialPositionFactory = {}; diff --git a/src/private_pgn/pgn_write_impl.ts b/src/private_pgn/pgn_write_impl.ts index 09692d0..6afe3e5 100644 --- a/src/private_pgn/pgn_write_impl.ts +++ b/src/private_pgn/pgn_write_impl.ts @@ -103,7 +103,7 @@ function writeAnnotations(node: AbstractNode, skipLineAfterCommentIfLong: boolea // Prepare tags const tags = node.tags(); - const tagValues: Map = new Map(); + const tagValues = new Map(); let nonEmptyTagFound = false; for (const tagKey of tags) { const tagValue = trimAndCollapseSpaces(node.tag(tagKey)!.replace(/[[\]]/g, '')); // Square-brackets are erased in tag values in PGN. @@ -211,7 +211,7 @@ export interface PGNWriteOptions { /** * If `true`, a PGN tag `[PlyCount "..."]` corresponding to the number of half-moves is added to each game in the generated PGN string. `false` by default. */ - withPlyCount?: boolean; + withPlyCount?: boolean, } diff --git a/src/private_pgn/token_stream.ts b/src/private_pgn/token_stream.ts index c1fab4c..8791428 100644 --- a/src/private_pgn/token_stream.ts +++ b/src/private_pgn/token_stream.ts @@ -28,14 +28,14 @@ import { trimAndCollapseSpaces } from '../private_game/common'; interface RegExpWrapper extends RegExp { - needIncrementLineIndex: boolean; - matchedIndex: number; - matched: RegExpExecArray | null; + needIncrementLineIndex: boolean, + matchedIndex: number, + matched: RegExpExecArray | null, } function regExpWrapper(re: RegExp, needIncrementLineIndex?: boolean) { - const result = (re as RegExpWrapper); + const result = re as RegExpWrapper; result.needIncrementLineIndex = needIncrementLineIndex !== undefined && needIncrementLineIndex; result.matchedIndex = -1; result.matched = null; @@ -47,6 +47,7 @@ function regExpWrapper(re: RegExp, needIncrementLineIndex?: boolean) { * Types of tokens that could be encountered in a PGN. */ export const enum TokenType { + /* eslint-disable @stylistic/no-multi-spaces */ INVALID = 0, BEGIN_HEADER = 1, // [ END_HEADER = 2, // ] @@ -59,6 +60,7 @@ export const enum TokenType { BEGIN_VARIATION = 9, // ( END_VARIATION = 10, // ) END_OF_GAME = 11, // 1-0, 0-1, 1/2-1/2 or * + /* eslint-enable */ } @@ -68,7 +70,8 @@ const LAST_MOVE_TEXT_TOKEN = TokenType.END_OF_GAME; // Conversion table NAG -> numeric code -const SPECIAL_NAGS_LOOKUP: Map = new Map(); +const SPECIAL_NAGS_LOOKUP = new Map(); +/* eslint-disable @stylistic/no-multi-spaces, @stylistic/comma-spacing */ SPECIAL_NAGS_LOOKUP.set('!!' , 3); // very good move SPECIAL_NAGS_LOOKUP.set('!' , 1); // good move SPECIAL_NAGS_LOOKUP.set('!?' , 5); // interesting move @@ -88,14 +91,15 @@ SPECIAL_NAGS_LOOKUP.set('-/+', 17); // Black has a moderate advantage SPECIAL_NAGS_LOOKUP.set('-+' , 19); // Black has a decisive advantage SPECIAL_NAGS_LOOKUP.set('RR' , 145); // Editorial comment SPECIAL_NAGS_LOOKUP.set('N' , 146); // Novelty +/* eslint-enable */ /** * Location within a PGN text. */ export interface StreamPosition { - pos: number; - lineIndex: number; + pos: number, + lineIndex: number, } @@ -129,7 +133,7 @@ export class TokenStream { private _emptyLineBeforeToken = false; /** Whether an empty line will be encountered after the current token. */ - private _emptyLineAfterToken = false; + private _emptyLineAfterToken = false; // Space-like matchers private _matchSpaces = regExpWrapper(/[ \f\t\v]+/g); @@ -265,20 +269,21 @@ export class TokenStream { // Match a move number if (this.testAtPos(this._matchMoveNumber)) { - this._token = TokenType.MOVE_NUMBER; + this._token = TokenType.MOVE_NUMBER; this._tokenValue = null; } // Match a move or a null-move else if (this.testAtPos(this._matchMove)) { - this._token = TokenType.MOVE; + this._token = TokenType.MOVE; this._tokenValue = this._matchMove.matched![0]; } // Match a NAG else if (this.testAtPos(this._matchNag)) { - this._token = TokenType.NAG; - this._tokenValue = this._matchNag.matched![2] === undefined ? SPECIAL_NAGS_LOOKUP.get(this._matchNag.matched![1]) : + this._token = TokenType.NAG; + this._tokenValue = this._matchNag.matched![2] === undefined ? + SPECIAL_NAGS_LOOKUP.get(this._matchNag.matched![1]) : parseInt(this._matchNag.matched![2], 10); } @@ -287,43 +292,43 @@ export class TokenStream { if (!this.testAtPos(this._commentMode)) { throw new InvalidPGN(this._text, this._pos, this._lineIndex, i18n.INVALID_PGN_TOKEN); } - this._token = TokenType.COMMENT; + this._token = TokenType.COMMENT; this._tokenValue = parseCommentValue(this._commentMode.matched![1]); } // Match the beginning of a variation else if (this.testAtPos(this._matchBeginVariation)) { - this._token = TokenType.BEGIN_VARIATION; + this._token = TokenType.BEGIN_VARIATION; this._tokenValue = null; } // Match the end of a variation else if (this.testAtPos(this._matchEndVariation)) { - this._token = TokenType.END_VARIATION; + this._token = TokenType.END_VARIATION; this._tokenValue = null; } // Match a end-of-game marker else if (this.testAtPos(this._matchEndOfGame)) { - this._token = TokenType.END_OF_GAME; + this._token = TokenType.END_OF_GAME; this._tokenValue = this._matchEndOfGame.matched![0]; } // Match the beginning of a game header else if (this.testAtPos(this._matchBeginHeader)) { - this._token = TokenType.BEGIN_HEADER; + this._token = TokenType.BEGIN_HEADER; this._tokenValue = null; } // Match the end of a game header else if (this.testAtPos(this._matchEndHeader)) { - this._token = TokenType.END_HEADER; + this._token = TokenType.END_HEADER; this._tokenValue = null; } // Match the ID of a game header else if (this.testAtPos(this._matchHeaderId)) { - this._token = TokenType.HEADER_ID; + this._token = TokenType.HEADER_ID; this._tokenValue = this._matchHeaderId.matched![1]; } @@ -332,7 +337,7 @@ export class TokenStream { if (!this.testAtPos(this._headerValueMode)) { throw new InvalidPGN(this._text, this._pos, this._lineIndex, i18n.INVALID_PGN_TOKEN); } - this._token = TokenType.HEADER_VALUE; + this._token = TokenType.HEADER_VALUE; this._tokenValue = parseHeaderValue(this._headerValueMode.matched![1]); } @@ -445,8 +450,8 @@ export class TokenStream { export interface TokenCommentData { - comment: string | undefined; - tags: Map; + comment: string | undefined, + tags: Map, } diff --git a/src/private_position/attacks.ts b/src/private_position/attacks.ts index 6c2113c..9c22a59 100644 --- a/src/private_position/attacks.ts +++ b/src/private_position/attacks.ts @@ -41,11 +41,10 @@ export const ATTACK_DIRECTIONS = [ [ -33, -31, -18, -14, 14, 18, 31, 33 ], // knight [ -33, -31, -18, -14, 14, 18, 31, 33 ], // knight [ 15, 17 ], // white pawn - [ -17, -15 ] // black pawn + [ -17, -15 ], // black pawn ]; - // ----------------------------------------------------------------------------- // isAttacked // ----------------------------------------------------------------------------- @@ -63,9 +62,8 @@ export function isAttacked(position: PositionImpl, square: number, attackerColor function isAttackedByNonSliding(position: PositionImpl, square: number, nonSlidingAttacker: number) { - const directions = ATTACK_DIRECTIONS[nonSlidingAttacker]; - for (let i = 0; i < directions.length; ++i) { - const sq = square - directions[i]; + for (const attackDirection of ATTACK_DIRECTIONS[nonSlidingAttacker]) { + const sq = square - attackDirection; if ((sq & 0x88) === 0 && position.board[sq] === nonSlidingAttacker) { return true; } @@ -75,11 +73,10 @@ function isAttackedByNonSliding(position: PositionImpl, square: number, nonSlidi function isAttackedBySliding(position: PositionImpl, square: number, slidingAttacker: number, queenAttacker: number) { - const directions = ATTACK_DIRECTIONS[slidingAttacker]; - for (let i = 0; i < directions.length; ++i) { + for (const attackDirection of ATTACK_DIRECTIONS[slidingAttacker]) { let sq = square; while (true) { - sq -= directions[i]; + sq -= attackDirection; if ((sq & 0x88) === 0) { const cp = position.board[sq]; if (cp === SpI.EMPTY) { @@ -96,7 +93,6 @@ function isAttackedBySliding(position: PositionImpl, square: number, slidingAtta } - // ----------------------------------------------------------------------------- // getAttacks // ----------------------------------------------------------------------------- @@ -116,9 +112,8 @@ export function getAttacks(position: PositionImpl, square: number, attackerColor function findNonSlidingAttacks(position: PositionImpl, square: number, result: number[], nonSlidingAttacker: number) { - const directions = ATTACK_DIRECTIONS[nonSlidingAttacker]; - for (let i = 0; i < directions.length; ++i) { - const sq = square - directions[i]; + for (const attackDirection of ATTACK_DIRECTIONS[nonSlidingAttacker]) { + const sq = square - attackDirection; if ((sq & 0x88) === 0 && position.board[sq] === nonSlidingAttacker) { result.push(sq); } @@ -127,11 +122,10 @@ function findNonSlidingAttacks(position: PositionImpl, square: number, result: n function findSlidingAttacks(position: PositionImpl, square: number, result: number[], slidingAttacker: number, queenAttacker: number) { - const directions = ATTACK_DIRECTIONS[slidingAttacker]; - for (let i = 0; i < directions.length; ++i) { + for (const attackDirection of ATTACK_DIRECTIONS[slidingAttacker]) { let sq = square; while (true) { - sq -= directions[i]; + sq -= attackDirection; if ((sq & 0x88) === 0) { const cp = position.board[sq]; if (cp === SpI.EMPTY) { diff --git a/src/private_position/base_types_impl.ts b/src/private_position/base_types_impl.ts index 432a3ee..67b3f72 100644 --- a/src/private_position/base_types_impl.ts +++ b/src/private_position/base_types_impl.ts @@ -24,6 +24,9 @@ import { Color, Piece, ColoredPiece, File, Rank, Square, GameResult, GameVariant } from '../base_types'; +/* eslint-disable @stylistic/computed-property-spacing, @stylistic/no-multi-spaces, @stylistic/no-whitespace-before-property, @stylistic/semi-spacing, +@stylistic/space-before-function-paren, @stylistic/space-in-parens, @stylistic/type-annotation-spacing */ + export const enum ColorImpl { WHITE = 0, diff --git a/src/private_position/fen.ts b/src/private_position/fen.ts index bb8dd06..16a76d7 100644 --- a/src/private_position/fen.ts +++ b/src/private_position/fen.ts @@ -211,7 +211,7 @@ export function parseFEN(variant: number, fen: string, strict: boolean): { posit // Board parsing for (let r = 7; r >= 0; --r) { - const rankField = rankFields[ 7 - r]; + const rankField = rankFields[7 - r]; let i = 0; let c = 0; while (i < rankField.length && c < 8) { @@ -352,7 +352,7 @@ function castlingFromStringXFEN(castling: string, strict: boolean, board: number for (let file = 0; file < 8; ++file) { const s = fileToString(file); if (castling.indexOf(s.toUpperCase()) >= 0) { result[ColorImpl.WHITE] |= 1 << file; } - if (castling.indexOf(s ) >= 0) { result[ColorImpl.BLACK] |= 1 << file; } + if (castling.indexOf(s) >= 0) { result[ColorImpl.BLACK] |= 1 << file; } } return result; } diff --git a/src/private_position/impl.ts b/src/private_position/impl.ts index 6593c6f..bfca32a 100644 --- a/src/private_position/impl.ts +++ b/src/private_position/impl.ts @@ -37,6 +37,7 @@ const EMPTY_BOARD = [ ]; const REGULAR_START_BOARD = [ + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ CpI.WR , CpI.WN , CpI.WB , CpI.WQ , CpI.WK , CpI.WB , CpI.WN , CpI.WR , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, @@ -45,9 +46,11 @@ const REGULAR_START_BOARD = [ SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.BR , CpI.BN , CpI.BB , CpI.BQ , CpI.BK , CpI.BB , CpI.BN , CpI.BR , + /* eslint-enable */ ]; const HORDE_START_BOARD = [ + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, @@ -56,6 +59,7 @@ const HORDE_START_BOARD = [ SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.BR , CpI.BN , CpI.BB , CpI.BQ , CpI.BK , CpI.BB , CpI.BN , CpI.BR , + /* eslint-enable */ ]; @@ -172,6 +176,7 @@ export function make960FromScharnagl(scharnaglCode: number): PositionImpl { const rank8 = info.pieceScheme.map(piece => piece * 2 + ColorImpl.BLACK); return { board: [ + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ rank1[0] , rank1[1] , rank1[2] , rank1[3] , rank1[4] , rank1[5] , rank1[6] , rank1[7] , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , CpI.WP , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, @@ -180,6 +185,7 @@ export function make960FromScharnagl(scharnaglCode: number): PositionImpl { SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.EMPTY, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , CpI.BP , SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, SpI.INVALID, rank8[0] , rank8[1] , rank8[2] , rank8[3] , rank8[4] , rank8[5] , rank8[6] , rank8[7] , + /* eslint-enable */ ], turn: ColorImpl.WHITE, castling: [ info.castling, info.castling ], @@ -261,21 +267,21 @@ function decodeScharnagl(scharnaglCode: number): ScharnaglInfo { return { pieceScheme: scheme, castling: castling, - kingFile: kingFile + kingFile: kingFile, }; } export function makeCopy(position: PositionImpl): PositionImpl { return { - board : position.board.slice(), - turn : position.turn, - castling : position.castling.slice(), - enPassant : position.enPassant, - variant : position.variant, - legal : position.legal, - king : position.king.slice(), - effectiveCastling : position.effectiveCastling === null ? null : position.effectiveCastling.slice(), - effectiveEnPassant : position.effectiveEnPassant, + board: position.board.slice(), + turn: position.turn, + castling: position.castling.slice(), + enPassant: position.enPassant, + variant: position.variant, + legal: position.legal, + king: position.king.slice(), + effectiveCastling: position.effectiveCastling === null ? null : position.effectiveCastling.slice(), + effectiveEnPassant: position.effectiveEnPassant, }; } diff --git a/src/private_position/legality.ts b/src/private_position/legality.ts index 40b8724..f406a79 100644 --- a/src/private_position/legality.ts +++ b/src/private_position/legality.ts @@ -301,14 +301,14 @@ export function refreshEffectiveEnPassant(position: PositionImpl) { // - and there must be at least one black pawn on d4 or f4. const square2 = (6 - position.turn * 5) * 16 + position.enPassant; const square3 = (5 - position.turn * 3) * 16 + position.enPassant; - const square4 = (4 - position.turn ) * 16 + position.enPassant; + const square4 = (4 - position.turn) * 16 + position.enPassant; const capturingPawn = PieceImpl.PAWN * 2 + position.turn; const capturedPawn = PieceImpl.PAWN * 2 + 1 - position.turn; if (position.board[square2] !== SpI.EMPTY || position.board[square3] !== SpI.EMPTY || position.board[square4] !== capturedPawn) { return; } const hasCapturingPawnBefore = ((square4 - 1) & 0x88) === 0 && position.board[square4 - 1] === capturingPawn; - const hasCapturingPawnAfter = ((square4 + 1) & 0x88) === 0 && position.board[square4 + 1] === capturingPawn; + const hasCapturingPawnAfter = ((square4 + 1) & 0x88) === 0 && position.board[square4 + 1] === capturingPawn; if (!hasCapturingPawnBefore && !hasCapturingPawnAfter) { return; } diff --git a/src/private_position/move_descriptor_impl.ts b/src/private_position/move_descriptor_impl.ts index e048e81..ab9377b 100644 --- a/src/private_position/move_descriptor_impl.ts +++ b/src/private_position/move_descriptor_impl.ts @@ -28,10 +28,12 @@ import { IllegalArgument } from '../exception'; import { MoveDescriptor } from '../move_descriptor'; +/* eslint-disable @stylistic/no-multi-spaces */ const CASTLING_FLAG = 0x01; const EN_PASSANT_FLAG = 0x02; const CAPTURE_FLAG = 0x04; const PROMOTION_FLAG = 0x08; +/* eslint-enable */ /** @@ -82,8 +84,8 @@ export class MoveDescriptorImpl extends MoveDescriptor { _movingColoredPiece: number; _finalColoredPiece: number; _optionalColoredPiece: number; // Captured (colored) piece in case of capture, moving (colored) rook in case of castling. - _optionalSquare1: number; // Rook-from or en-passant square. - _optionalSquare2: number; // Rook-to. + _optionalSquare1: number; // Rook-from or en-passant square. + _optionalSquare2: number; // Rook-to. private constructor(flags: number, from: number, to: number, movingColoredPiece: number, finalColoredPiece: number, optionalColoredPiece: number, optionalSquare1: number, optionalSquare2: number) { @@ -94,8 +96,8 @@ export class MoveDescriptorImpl extends MoveDescriptor { this._movingColoredPiece = movingColoredPiece; this._finalColoredPiece = finalColoredPiece; this._optionalColoredPiece = optionalColoredPiece; // Captured (colored) piece in case of capture, moving (colored) rook in case of castling. - this._optionalSquare1 = optionalSquare1; // Rook-from or en-passant square. - this._optionalSquare2 = optionalSquare2; // Rook-to. + this._optionalSquare1 = optionalSquare1; // Rook-from or en-passant square. + this._optionalSquare2 = optionalSquare2; // Rook-to. } isCastling() { diff --git a/src/private_position/move_generation.ts b/src/private_position/move_generation.ts index 9151a88..e6ddbd1 100644 --- a/src/private_position/move_generation.ts +++ b/src/private_position/move_generation.ts @@ -31,12 +31,11 @@ import { MoveDescriptorImpl } from './move_descriptor_impl'; import { MoveDescriptor } from '../move_descriptor'; -/* eslint-disable no-mixed-spaces-and-tabs, indent */ - /** * Displacement lookup per square index difference. */ const DISPLACEMENT_LOOKUP = [ + /* eslint-disable @stylistic/indent, @stylistic/no-multi-spaces */ 204, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 204, 0, 0, 204, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 204, 0, 0, 0, 0, 204, 0, 0, 0, 0, 60, 0, 0, 0, 0, 204, 0, 0, 0, @@ -51,13 +50,15 @@ const DISPLACEMENT_LOOKUP = [ 0, 0, 0, 204, 0, 0, 0, 60, 0, 0, 0, 204, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, 0, 60, 0, 0, 0, 0, 204, 0, 0, 0, 0, 204, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 204, 0, 0, - 204, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 204, 0 + 204, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 204, 0, + /* eslint-enable */ ]; /** * Sliding direction */ const SLIDING_DIRECTION = [ + /* eslint-disable @stylistic/indent, @stylistic/no-multi-spaces */ -17, 0, 0, 0, 0, 0, 0, -16, 0, 0, 0, 0, 0, 0, -15, 0, 0, -17, 0, 0, 0, 0, 0, -16, 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, -17, 0, 0, 0, 0, -16, 0, 0, 0, 0, -15, 0, 0, 0, @@ -72,11 +73,10 @@ const SLIDING_DIRECTION = [ 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 16, 0, 0, 0, 0, 17, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 17, 0, 0, - 15, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 17, 0 + 15, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 17, 0, + /* eslint-enable */ ]; -/* eslint-enable no-mixed-spaces-and-tabs, indent */ - /** * Whether there is at least one piece with the given color in the given position. @@ -245,7 +245,7 @@ export function hasMove(position: PositionImpl) { generateMoves(position, () => { throw new MoveFound(); }); return false; } - catch(err) { + catch (err) { // istanbul ignore else if (err instanceof MoveFound) { return true; @@ -300,7 +300,7 @@ function generateMoves(position: PositionImpl, moveDescriptorConsumer: (moveDesc refreshEffectiveEnPassant(position); if (position.effectiveEnPassant! >= 0) { const square3 = (5 - position.turn * 3) * 16 + position.effectiveEnPassant!; - const square4 = (4 - position.turn ) * 16 + position.effectiveEnPassant!; + const square4 = (4 - position.turn) * 16 + position.effectiveEnPassant!; const capturingPawn = PieceImpl.PAWN * 2 + position.turn; if (((square4 - 1) & 0x88) === 0 && position.board[square4 - 1] === capturingPawn && isKingSafeAfterMove(position, square4 - 1, square3, square4)) { moveDescriptorConsumer(MoveDescriptorImpl.makeEnPassant(square4 - 1, square3, square4, position.turn)); @@ -324,9 +324,8 @@ function generateMoves(position: PositionImpl, moveDescriptorConsumer: (moveDesc if (movingPiece === PieceImpl.PAWN) { // Regular capturing moves (en-passant not handled here) - const attackDirections = ATTACK_DIRECTIONS[fromContent]; - for (let i = 0; i < attackDirections.length; ++i) { - const to = from + attackDirections[i]; + for (const attackDirection of ATTACK_DIRECTIONS[fromContent]) { + const to = from + attackDirection; if ((to & 0x88) === 0 && position.board[to] !== SpI.EMPTY && position.board[to] % 2 !== position.turn && isKingSafeAfterMove(position, from, to)) { generateRegularPawnMoveOrPromotion(position, from, to, moveDescriptorConsumer); } @@ -355,9 +354,8 @@ function generateMoves(position: PositionImpl, moveDescriptorConsumer: (moveDesc // Generate moves for non-sliding non-pawn pieces else if (movingPiece === PieceImpl.KNIGHT || movingPiece === PieceImpl.KING) { - const directions = ATTACK_DIRECTIONS[fromContent]; - for (let i = 0; i < directions.length; ++i) { - const to = from + directions[i]; + for (const attackDirection of ATTACK_DIRECTIONS[fromContent]) { + const to = from + attackDirection; if ((to & 0x88) === 0) { const toContent = position.board[to]; if ((toContent === SpI.EMPTY ? nonCaptureIsAllowed : toContent % 2 !== position.turn) && isKingSafeAfterMove(position, from, to)) { @@ -369,9 +367,8 @@ function generateMoves(position: PositionImpl, moveDescriptorConsumer: (moveDesc // Generate moves for sliding pieces else { - const directions = ATTACK_DIRECTIONS[fromContent]; - for (let i = 0; i < directions.length; ++i) { - for (let to = from + directions[i]; (to & 0x88) === 0; to += directions[i]) { + for (const attackDirection of ATTACK_DIRECTIONS[fromContent]) { + for (let to = from + attackDirection; (to & 0x88) === 0; to += attackDirection) { const toContent = position.board[to]; if ((toContent === SpI.EMPTY ? nonCaptureIsAllowed : toContent % 2 !== position.turn) && isKingSafeAfterMove(position, from, to)) { moveDescriptorConsumer(MoveDescriptorImpl.make(from, to, fromContent, toContent)); @@ -634,7 +631,8 @@ export function isMoveLegal(position: PositionImpl, from: number, to: number): R else { return { type: 'regular', - moveDescriptor: enPassantSquare >= 0 ? MoveDescriptorImpl.makeEnPassant(from, to, enPassantSquare, position.turn) : + moveDescriptor: enPassantSquare >= 0 ? + MoveDescriptorImpl.makeEnPassant(from, to, enPassantSquare, position.turn) : MoveDescriptorImpl.make(from, to, fromContent, toContent), }; } @@ -683,10 +681,10 @@ export function play(position: PositionImpl, descriptor: MoveDescriptorImpl) { if (movingPiece === PieceImpl.KING) { position.effectiveCastling![position.turn] = 0; } - if (descriptor._from < 8) { position.effectiveCastling![ColorImpl.WHITE] &= ~(1 << descriptor._from ); } - if (descriptor._to < 8) { position.effectiveCastling![ColorImpl.WHITE] &= ~(1 << descriptor._to ); } + if (descriptor._from < 8) { position.effectiveCastling![ColorImpl.WHITE] &= ~(1 << descriptor._from); } + if (descriptor._to < 8) { position.effectiveCastling![ColorImpl.WHITE] &= ~(1 << descriptor._to); } if (descriptor._from >= 112) { position.effectiveCastling![ColorImpl.BLACK] &= ~(1 << (descriptor._from % 16)); } - if (descriptor._to >= 112) { position.effectiveCastling![ColorImpl.BLACK] &= ~(1 << (descriptor._to % 16)); } + if (descriptor._to >= 112) { position.effectiveCastling![ColorImpl.BLACK] &= ~(1 << (descriptor._to % 16)); } position.castling[ColorImpl.WHITE] = position.effectiveCastling![ColorImpl.WHITE]; position.castling[ColorImpl.BLACK] = position.effectiveCastling![ColorImpl.BLACK]; diff --git a/src/private_position/notation.ts b/src/private_position/notation.ts index 507e24e..0663363 100644 --- a/src/private_position/notation.ts +++ b/src/private_position/notation.ts @@ -112,8 +112,7 @@ function getDisambiguationSymbol(position: PositionImpl, from: number, to: numbe let foundOnSameFile = false; const rankFrom = Math.trunc(from / 16); const fileFrom = from % 16; - for (let i = 0; i < attackers.length; ++i) { - const sq = attackers[i]; + for (const sq of attackers) { if (sq === from || isPinned(position, sq, to)) { continue; } @@ -157,15 +156,15 @@ function isPinned(position: PositionImpl, sq: number, aimingAtSq: number) { return aimingAtVector >= 8 && pinningLoockup(position, kingSquare, sq, kingSquare < sq ? 1 : -1, pinnerRook, pinnerQueen); } else if (vector % 16 === 0) { - return aimingAtVector % 16 !==0 && pinningLoockup(position, kingSquare, sq, kingSquare < sq ? 16 : -16, pinnerRook, pinnerQueen); + return aimingAtVector % 16 !== 0 && pinningLoockup(position, kingSquare, sq, kingSquare < sq ? 16 : -16, pinnerRook, pinnerQueen); } // Potential pinning on diagonal. else if (vector % 15 === 0) { - return aimingAtVector % 15 !==0 && pinningLoockup(position, kingSquare, sq, kingSquare < sq ? 15 : -15, pinnerBishop, pinnerQueen); + return aimingAtVector % 15 !== 0 && pinningLoockup(position, kingSquare, sq, kingSquare < sq ? 15 : -15, pinnerBishop, pinnerQueen); } else if (vector % 17 === 0) { - return aimingAtVector % 17 !==0 && pinningLoockup(position, kingSquare, sq, kingSquare < sq ? 17 : -17, pinnerBishop, pinnerQueen); + return aimingAtVector % 17 !== 0 && pinningLoockup(position, kingSquare, sq, kingSquare < sq ? 17 : -17, pinnerBishop, pinnerQueen); } // No pinning for sure. @@ -359,12 +358,12 @@ function parseNonPawnNotation(position: PositionImpl, notation: string, strict: // Compute the move descriptor for each remaining "from"-square candidate let descriptor: MoveDescriptorImpl | false = false; - for (let i = 0; i < attackers.length; ++i) { - if (isKingSafeAfterMove(position, attackers[i], to)) { + for (const sq of attackers) { + if (isKingSafeAfterMove(position, sq, to)) { if (descriptor) { throw new InvalidNotation(getFEN(position), notation, i18n.REQUIRE_DISAMBIGUATION, pieceSymbol, destinationSquare); } - descriptor = MoveDescriptorImpl.make(attackers[i], to, movingColoredPiece, toContent); + descriptor = MoveDescriptorImpl.make(sq, to, movingColoredPiece, toContent); } } if (!descriptor) { @@ -399,7 +398,7 @@ function parsePawnMoveNotation(position: PositionImpl, notation: string, strict: const coloredPawn = PieceImpl.PAWN * 2 + position.turn; const to = squareFromString(destinationSquare); const toContent = position.board[to]; - const vector = 16 - position.turn*32; + const vector = 16 - position.turn * 32; let from = to - vector; let enPassantSquare = -1; if (originFile !== undefined) { // Capturing pawn move diff --git a/src/private_position/uci.ts b/src/private_position/uci.ts index 452342b..e41ecdc 100644 --- a/src/private_position/uci.ts +++ b/src/private_position/uci.ts @@ -46,7 +46,7 @@ export function getUCINotation(position: PositionImpl, descriptor: MoveDescripto result += descriptor.to(); } - if(descriptor.isPromotion()) { + if (descriptor.isPromotion()) { result += descriptor.promotion(); } diff --git a/test/02_helper.js b/test/02_helper.js index 0760b42..995f9fe 100644 --- a/test/02_helper.js +++ b/test/02_helper.js @@ -112,11 +112,11 @@ describe('Square color', () => { describe('Square to coordinates', () => { - it('a1', () => { test.value(squareToCoordinates('a1')).is({ file:0, rank:0 }); }); - it('h1', () => { test.value(squareToCoordinates('h1')).is({ file:7, rank:0 }); }); - it('a8', () => { test.value(squareToCoordinates('a8')).is({ file:0, rank:7 }); }); - it('h8', () => { test.value(squareToCoordinates('h8')).is({ file:7, rank:7 }); }); - it('e3', () => { test.value(squareToCoordinates('e3')).is({ file:4, rank:2 }); }); + it('a1', () => { test.value(squareToCoordinates('a1')).is({ file: 0, rank: 0 }); }); + it('h1', () => { test.value(squareToCoordinates('h1')).is({ file: 7, rank: 0 }); }); + it('a8', () => { test.value(squareToCoordinates('a8')).is({ file: 0, rank: 7 }); }); + it('h8', () => { test.value(squareToCoordinates('h8')).is({ file: 7, rank: 7 }); }); + it('e3', () => { test.value(squareToCoordinates('e3')).is({ file: 4, rank: 2 }); }); it('Error with ', () => { test.exception(() => squareToCoordinates('')).isInstanceOf(exception.IllegalArgument); }); it('Error with cc', () => { test.exception(() => squareToCoordinates('cc')).isInstanceOf(exception.IllegalArgument); }); diff --git a/test/03_position_base.js b/test/03_position_base.js index 5be2a6e..29801df 100644 --- a/test/03_position_base.js +++ b/test/03_position_base.js @@ -27,11 +27,11 @@ const dumpCastlingFlags = require('./common/dumpcastlingflags'); const readCSV = require('./common/readcsv'); const test = require('unit.js'); -const startFEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'; +const startFEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'; const startXFEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w AHah - 0 1'; const startFENAntichess = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - - 0 1'; const startFENHorde = 'rnbqkbnr/pppppppp/8/1PP2PP1/PPPPPPPP/PPPPPPPP/PPPPPPPP/PPPPPPPP w kq - 0 1'; -const emptyFEN = '8/8/8/8/8/8/8/8 w - - 0 1'; +const emptyFEN = '8/8/8/8/8/8/8/8 w - - 0 1'; const customFEN = 'r3k2r/pb3pbp/1p4p1/3n4/1PpP4/P4NB1/5PPP/R3KB1R b KQkq d3 0 1'; const customFENNoCastling = 'r3k2r/pb3pbp/1p4p1/3n4/1PpP4/P4NB1/5PPP/R3KB1R b - d3 0 1'; const customFENWhiteCastlingOnly = 'r3k2r/pb3pbp/1p4p1/3n4/1PpP4/P4NB1/5PPP/R3KB1R b KQ d3 0 1'; @@ -40,7 +40,7 @@ const customXFEN = 'qrkbrnbn/pppppppp/8/8/8/8/PPPPPPPP/QRKBRNBN w BEbe - 0 1'; const customXFENAsFEN = 'qrkbrnbn/pppppppp/8/8/8/8/PPPPPPPP/QRKBRNBN w KQkq - 0 1'; const customFENHorde = '1Q3rk1/2P4p/1P2pp2/2PP4/5P1P/2q1PPPP/2P1PPPP/2PPPPPP b - - 0 1'; -const variants = ['regular', 'chess960', 'no-king', 'white-king-only', 'black-king-only', 'antichess', 'horde']; +const variants = [ 'regular', 'chess960', 'no-king', 'white-king-only', 'black-king-only', 'antichess', 'horde' ]; describe('Position constructor', () => { @@ -53,6 +53,8 @@ describe('Position constructor', () => { }); } + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ + doTest('Default constructor' , 'regular', startFEN , () => new Position()); doTest('Constructor \'start\'', 'regular', startFEN , () => new Position('start')); doTest('Constructor \'empty\'', 'regular', emptyFEN , () => new Position('empty')); @@ -89,6 +91,8 @@ describe('Position constructor', () => { doTest('Constructor FEN-based (horde)' , 'horde', customFENHorde, () => new Position('horde', customFENHorde)); doTest('Constructor FEN-based with prefix (horde)', 'horde', customFENHorde, () => new Position('horde:' + customFENHorde)); + /* eslint-enable */ + function doFailureTest(label, fenParsingErrorExpected, positionFactory) { it(label, () => { test.exception(positionFactory).isInstanceOf(fenParsingErrorExpected ? exception.InvalidFEN : exception.IllegalArgument); }); } @@ -197,7 +201,7 @@ describe('Reset 960 mutator', () => { }); } - for (const elem of [960, 18.3, '546']) { + for (const elem of [ 960, 18.3, '546' ]) { it('Error with Scharnagl code ' + elem, () => { const p = new Position(); test.exception(() => p.reset960(elem)).isInstanceOf(exception.IllegalArgument); @@ -281,14 +285,14 @@ describe('Position getters', () => { it('Get en-passant 1', () => { const p = new Position(); test.value(p.enPassant()).is('-'); }); it('Get en-passant 2', () => { const p = new Position(currentFEN); test.value(p.enPassant()).is('e'); }); - for (const elem of ['j1', 'f9']) { + for (const elem of [ 'j1', 'f9' ]) { it('Error for board with ' + elem, () => { const p = new Position(); test.exception(() => p.square(elem)).isInstanceOf(exception.IllegalArgument); }); } - for (const elem of ['bK', 'wa']) { + for (const elem of [ 'bK', 'wa' ]) { it('Error for castling with ' + elem, () => { const p = new Position(); test.exception(() => p.castling(elem)).isInstanceOf(exception.IllegalArgument); @@ -296,7 +300,7 @@ describe('Position getters', () => { }); } - for (const elem of ['wA', 'bq']) { + for (const elem of [ 'wA', 'bq' ]) { it('Error for castling (chess960) with ' + elem, () => { const p = new Position('chess960', 123); test.exception(() => p.castling(elem)).isInstanceOf(exception.IllegalArgument); @@ -374,28 +378,28 @@ describe('Position setters', () => { testCastlingEnPassantFEN(p, 'Fadf', '-', 'rknnbrqb/pppppppp/8/8/8/8/PPPPPPPP/RKNNBRQB w Faf - 0 1'); }); - for (const elem of ['p', 'Q', 'kw']) { + for (const elem of [ 'p', 'Q', 'kw' ]) { it('Error for board with colored piece ' + elem, () => { const p = new Position(); test.exception(() => p.square('d4', elem)).isInstanceOf(exception.IllegalArgument); }); } - for (const elem of ['', 'W', 'bb', 'wb']) { + for (const elem of [ '', 'W', 'bb', 'wb' ]) { it('Error for turn with ' + (elem === '' ? '' : elem), () => { const p = new Position(); test.exception(() => p.turn(elem)).isInstanceOf(exception.IllegalArgument); }); } - for (const elem of [0, 1, 'false', 'true']) { + for (const elem of [ 0, 1, 'false', 'true' ]) { it('Error for set castling with ' + (elem === '' ? '' : elem), () => { const p = new Position(); test.exception(() => p.castling('wk', elem)).isInstanceOf(exception.IllegalArgument); }); } - for (const elem of ['', 'i', 'gg', 'abcdefgh']) { + for (const elem of [ '', 'i', 'gg', 'abcdefgh' ]) { it('Error for en-passant with ' + (elem === '' ? '' : elem), () => { const p = new Position(); test.exception(() => p.enPassant(elem)).isInstanceOf(exception.IllegalArgument); diff --git a/test/04_position_fen.js b/test/04_position_fen.js index aecd9ce..296965a 100644 --- a/test/04_position_fen.js +++ b/test/04_position_fen.js @@ -35,17 +35,17 @@ function itForEach(fun) { return false; } return { - label : fields[ 0], - fenIn : fields[ 1], - variant : fields[ 2], - strict : fields[ 3]==='true', - castling : fields[ 4], - enPassant : fields[ 5], - fiftyMoveClock : parseInt(fields[6]), - fullMoveNumber : parseInt(fields[7]), - fenOutDefault : fields[ 8], - fenOutWithCounters: fields[ 9], - fenOutWithoutXFEN : fields[10], + label: fields[0], + fenIn: fields[1], + variant: fields[2], + strict: fields[3] === 'true', + castling: fields[4], + enPassant: fields[5], + fiftyMoveClock: parseInt(fields[6]), + fullMoveNumber: parseInt(fields[7]), + fenOutDefault: fields[8], + fenOutWithCounters: fields[9], + fenOutWithoutXFEN: fields[10], }; }); @@ -89,7 +89,6 @@ describe('Castling flag parsing', () => { }); - describe('En-passant flag parsing', () => { itForEach(elem => { const position = new Position(elem.variant, 'empty'); diff --git a/test/06_position_process.js b/test/06_position_process.js index 4d7ef19..134af4a 100644 --- a/test/06_position_process.js +++ b/test/06_position_process.js @@ -35,26 +35,26 @@ function itForEach(fun) { return false; } return { - label : label, - constructor : fields[ 1], - variant : fields[ 2], - fen : fields[ 3], - turn : fields[ 4], - isLegal : fields[ 5]==='true', - whiteKing : fields[ 6]==='-' ? false : fields[6], - blackKing : fields[ 7]==='-' ? false : fields[7], - effectiveCastling : fields[ 8], - effectiveEnPassant : fields[ 9], - isCheck : fields[10]==='true', - isCheckmate : fields[11]==='true', - isStalemate : fields[12]==='true', - isDead : fields[13]==='true', - isDeadUSCF : fields[14]==='true', - hasMove : fields[15]==='true', - moves : fields[16], - uciMoves : fields[17], - notations : fields[18], - successors : fields[19], + label: label, + constructor: fields[1], + variant: fields[2], + fen: fields[3], + turn: fields[4], + isLegal: fields[5] === 'true', + whiteKing: fields[6] === '-' ? false : fields[6], + blackKing: fields[7] === '-' ? false : fields[7], + effectiveCastling: fields[8], + effectiveEnPassant: fields[9], + isCheck: fields[10] === 'true', + isCheckmate: fields[11] === 'true', + isStalemate: fields[12] === 'true', + isDead: fields[13] === 'true', + isDeadUSCF: fields[14] === 'true', + hasMove: fields[15] === 'true', + moves: fields[16], + uciMoves: fields[17], + notations: fields[18], + successors: fields[19], }; }); @@ -250,7 +250,7 @@ describe('Standard algebraic notation generation', () => { describe('UCI notation parsing', () => { - const PROMO = ['', 'k', 'q', 'r', 'b', 'n', 'p']; + const PROMO = [ '', 'k', 'q', 'r', 'b', 'n', 'p' ]; itForEach(elem => { const pos = createPosition(elem); let moves = []; @@ -275,7 +275,7 @@ describe('UCI notation parsing', () => { // Sort the moves and remove the duplicates. moves.sort(); - moves = moves.filter((move, index, tab) => index === 0 || move !== tab[index-1]); + moves = moves.filter((move, index, tab) => index === 0 || move !== tab[index - 1]); test.value(moves.join('/')).is(elem.moves); }); @@ -283,8 +283,8 @@ describe('UCI notation parsing', () => { describe('Standard algebraic notation parsing', () => { - const RANK_DISAMBIGUATION = ['', '1', '2', '3', '4', '5', '6', '7', '8']; - const FILE_DISAMBIGUATION = ['', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; + const RANK_DISAMBIGUATION = [ '', '1', '2', '3', '4', '5', '6', '7', '8' ]; + const FILE_DISAMBIGUATION = [ '', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' ]; itForEach(elem => { const pos = createPosition(elem); @@ -310,7 +310,7 @@ describe('Standard algebraic notation parsing', () => { // Pawn move forEachSquare(to => { for (const fd of FILE_DISAMBIGUATION) { - for (const promo of ['', '=K', '=Q', '=R', '=B', '=N', '=P']) { + for (const promo of [ '', '=K', '=Q', '=R', '=B', '=N', '=P' ]) { const text = fd + to + promo; parseNotation(text); } @@ -331,7 +331,7 @@ describe('Standard algebraic notation parsing', () => { // Sort the moves and remove the duplicates. moves.sort(); - moves = moves.filter((move, index, tab) => index === 0 || move !== tab[index-1]); + moves = moves.filter((move, index, tab) => index === 0 || move !== tab[index - 1]); test.value(moves.join('/')).is(elem.moves); }); diff --git a/test/08_movedescriptor.js b/test/08_movedescriptor.js index cff6a55..e86e4e4 100644 --- a/test/08_movedescriptor.js +++ b/test/08_movedescriptor.js @@ -74,6 +74,8 @@ describe('Normal move', () => { }); } + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ + itDescriptor('Is descriptor?', testIsMoveDescriptor); itDescriptor('Is castling?' , descriptor => test.value(descriptor.isCastling()).is(false)); itDescriptor('Is en-passant?', descriptor => test.value(descriptor.isEnPassant()).is(false)); @@ -93,6 +95,8 @@ describe('Normal move', () => { itDescriptor('Promotion' , descriptor => test.exception(() => descriptor.promotion()).isInstanceOf(exception.IllegalArgument)); itDescriptor('Colored promotion' , descriptor => test.exception(() => descriptor.coloredPromotion()).isInstanceOf(exception.IllegalArgument)); itDescriptor('To string' , descriptor => test.value(descriptor.toString()).is('b1a3')); + + /* eslint-enable */ }); @@ -107,6 +111,8 @@ describe('Normal move with capture', () => { }); } + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ + itDescriptor('Is descriptor?', testIsMoveDescriptor); itDescriptor('Is castling?' , descriptor => test.value(descriptor.isCastling()).is(false)); itDescriptor('Is en-passant?', descriptor => test.value(descriptor.isEnPassant()).is(false)); @@ -126,6 +132,8 @@ describe('Normal move with capture', () => { itDescriptor('Promotion' , descriptor => test.exception(() => descriptor.promotion()).isInstanceOf(exception.IllegalArgument)); itDescriptor('Colored promotion' , descriptor => test.exception(() => descriptor.coloredPromotion()).isInstanceOf(exception.IllegalArgument)); itDescriptor('To string' , descriptor => test.value(descriptor.toString()).is('c3c7')); + + /* eslint-enable */ }); @@ -140,6 +148,8 @@ describe('Castling move', () => { }); } + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ + itDescriptor('Is descriptor?', testIsMoveDescriptor); itDescriptor('Is castling?' , descriptor => test.value(descriptor.isCastling()).is(true)); itDescriptor('Is en-passant?', descriptor => test.value(descriptor.isEnPassant()).is(false)); @@ -159,6 +169,8 @@ describe('Castling move', () => { itDescriptor('Promotion' , descriptor => test.exception(() => descriptor.promotion()).isInstanceOf(exception.IllegalArgument)); itDescriptor('Colored promotion' , descriptor => test.exception(() => descriptor.coloredPromotion()).isInstanceOf(exception.IllegalArgument)); itDescriptor('To string' , descriptor => test.value(descriptor.toString()).is('e1g1O')); + + /* eslint-enable */ }); @@ -173,6 +185,8 @@ describe('En-passant move', () => { }); } + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ + itDescriptor('Is descriptor?', testIsMoveDescriptor); itDescriptor('Is castling?' , descriptor => test.value(descriptor.isCastling()).is(false)); itDescriptor('Is en-passant?', descriptor => test.value(descriptor.isEnPassant()).is(true)); @@ -192,6 +206,8 @@ describe('En-passant move', () => { itDescriptor('Promotion' , descriptor => test.exception(() => descriptor.promotion()).isInstanceOf(exception.IllegalArgument)); itDescriptor('Colored promotion' , descriptor => test.exception(() => descriptor.coloredPromotion()).isInstanceOf(exception.IllegalArgument)); itDescriptor('To string' , descriptor => test.value(descriptor.toString()).is('g5f6')); + + /* eslint-enable */ }); @@ -206,6 +222,8 @@ describe('Promotion move', () => { }); } + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ + itDescriptor('Is descriptor?', testIsMoveDescriptor); itDescriptor('Is castling?' , descriptor => test.value(descriptor.isCastling()).is(false)); itDescriptor('Is en-passant?', descriptor => test.value(descriptor.isEnPassant()).is(false)); @@ -225,6 +243,8 @@ describe('Promotion move', () => { itDescriptor('Promotion' , descriptor => test.value(descriptor.promotion()).is('q')); itDescriptor('Colored promotion' , descriptor => test.value(descriptor.coloredPromotion()).is('wq')); itDescriptor('To string' , descriptor => test.value(descriptor.toString()).is('a7a8Q')); + + /* eslint-enable */ }); @@ -239,6 +259,8 @@ describe('Promotion move with capture', () => { }); } + /* eslint-disable @stylistic/comma-spacing, @stylistic/no-multi-spaces */ + itDescriptor('Is descriptor?', testIsMoveDescriptor); itDescriptor('Is castling?' , descriptor => test.value(descriptor.isCastling()).is(false)); itDescriptor('Is en-passant?', descriptor => test.value(descriptor.isEnPassant()).is(false)); @@ -258,4 +280,6 @@ describe('Promotion move with capture', () => { itDescriptor('Promotion' , descriptor => test.value(descriptor.promotion()).is('r')); itDescriptor('Colored promotion' , descriptor => test.value(descriptor.coloredPromotion()).is('wr')); itDescriptor('To string' , descriptor => test.value(descriptor.toString()).is('a7b8R')); + + /* eslint-enable */ }); diff --git a/test/11_game_tree.js b/test/11_game_tree.js index 42ea3d1..5132f01 100644 --- a/test/11_game_tree.js +++ b/test/11_game_tree.js @@ -468,9 +468,9 @@ const oneGamefactories = { const fullPgnFactories = { - 'empty': () => [], + empty: () => [], - 'mini2': () => { + mini2: () => { const game0 = new Game(); game0.event('TV Show'); @@ -486,7 +486,7 @@ const fullPgnFactories = { game1.mainVariation().play('e4').play('e5').play('Bc4').play('Nc6').play('Qh5').play('Nf6').play('Qxf7#'); return [ game0, game1 ]; - } + }, }; diff --git a/test/common/dumpcastlingflags.js b/test/common/dumpcastlingflags.js index 1e8d546..f2716f7 100644 --- a/test/common/dumpcastlingflags.js +++ b/test/common/dumpcastlingflags.js @@ -22,7 +22,7 @@ * -------------------------------------------------------------------------- */ -module.exports = function(position, getter) { +module.exports = function (position, getter) { let result = ''; for (const castle of position.variant() === 'chess960' ? 'abcdefgh' : 'kq') { if (getter(position, 'w' + castle)) { diff --git a/test/common/dumpgame.js b/test/common/dumpgame.js index 9da699c..bc4dcfd 100644 --- a/test/common/dumpgame.js +++ b/test/common/dumpgame.js @@ -31,7 +31,7 @@ const ID_PADDING = ' '; /** * Dump the content of a Game object. */ -module.exports = function(game) { +module.exports = function (game) { let res = '\n'; function dumpHeader(key, value) { @@ -125,7 +125,7 @@ module.exports = function(game) { // Variation header res += formatNodeOrVariationId(variation.id()) + indentFirst + '-+'; - if(variation.isLongVariation()) { + if (variation.isLongVariation()) { res += '