manage pieces movements

This commit is contained in:
Didictateur 2025-10-20 13:23:22 +02:00
parent ce81438c48
commit 3544e4dc7a
12 changed files with 160 additions and 99 deletions

View file

@ -96,3 +96,9 @@ Une pièce choisie ne peut maintenant se déplacer que si elle capture.
Au yeux de l'ennemie, toutes les pièces se ressemblent pendant 2 tours.
### Petit pion
Le joueur choisit un pion. À partir du prochain tour, il est promu en reine dès qu'il capture un pièce non pion.
### Révolution
Tous les pions sont aléatoirement changés en Cavalier, Fou ou Tour et les Cavaliers, Fous et Tours sont changés en pions.
### Doppelganger
Choisis une pièce. À partir de maintenant, devient chacune des pièces qu'elle capture.
### Kurby
Choisis une pièce. À sa prochaine capture, récupère les mouvements de la pièce capturée.

View file

@ -21,29 +21,6 @@ class Board {
this.setupInitialPieces();
}
/**
* @returns {number}
*/
getWidth() {
return this.width;
}
/**
* @returns {number}
*/
getHeight() {
return this.height;
}
/**
* @param {number} x
* @param {number} y
* @returns {Cell}
*/
getCell(x, y) {
return this.grid[y][x];
}
/**
* @param {number} x
* @param {number} y
@ -56,33 +33,33 @@ class Board {
setupInitialPieces() {
// Pawns
for (let x = 0; x < this.width; x++) {
this.setPiece(x, 1, new Piece(PieceColor.WHITE, PieceType.PAWN, [Movement.PawnMove]));
this.setPiece(x, 6, new Piece(PieceColor.BLACK, PieceType.PAWN, [Movement.PawnMove]));
this.setPiece(x, 1, new Piece(PieceColor.WHITE, PieceType.PAWN, [Movement.PawnMove], x, 1));
this.setPiece(x, 6, new Piece(PieceColor.BLACK, PieceType.PAWN, [Movement.PawnMove], x, 6));
}
// Rooks
this.setPiece(0, 0, new Piece(PieceColor.WHITE, PieceType.ROOK, [Movement.RookMove]));
this.setPiece(7, 0, new Piece(PieceColor.WHITE, PieceType.ROOK, [Movement.RookMove]));
this.setPiece(0, 7, new Piece(PieceColor.BLACK, PieceType.ROOK, [Movement.RookMove]));
this.setPiece(7, 7, new Piece(PieceColor.BLACK, PieceType.ROOK, [Movement.RookMove]));
this.setPiece(0, 0, new Piece(PieceColor.WHITE, PieceType.ROOK, [Movement.RookMove], 0, 0));
this.setPiece(7, 0, new Piece(PieceColor.WHITE, PieceType.ROOK, [Movement.RookMove], 7, 0));
this.setPiece(0, 7, new Piece(PieceColor.BLACK, PieceType.ROOK, [Movement.RookMove], 0, 7));
this.setPiece(7, 7, new Piece(PieceColor.BLACK, PieceType.ROOK, [Movement.RookMove], 7, 7));
// Knights
this.setPiece(1, 0, new Piece(PieceColor.WHITE, PieceType.KNIGHT, [Movement.KnightMove]));
this.setPiece(6, 0, new Piece(PieceColor.WHITE, PieceType.KNIGHT, [Movement.KnightMove]));
this.setPiece(1, 7, new Piece(PieceColor.BLACK, PieceType.KNIGHT, [Movement.KnightMove]));
this.setPiece(6, 7, new Piece(PieceColor.BLACK, PieceType.KNIGHT, [Movement.KnightMove]));
this.setPiece(1, 0, new Piece(PieceColor.WHITE, PieceType.KNIGHT, [Movement.KnightMove], 1, 0));
this.setPiece(6, 0, new Piece(PieceColor.WHITE, PieceType.KNIGHT, [Movement.KnightMove], 6, 0));
this.setPiece(1, 7, new Piece(PieceColor.BLACK, PieceType.KNIGHT, [Movement.KnightMove], 1, 7));
this.setPiece(6, 7, new Piece(PieceColor.BLACK, PieceType.KNIGHT, [Movement.KnightMove], 6, 7));
// Bishops
this.setPiece(2, 0, new Piece(PieceColor.WHITE, PieceType.BISHOP, [Movement.BishopMove]));
this.setPiece(5, 0, new Piece(PieceColor.WHITE, PieceType.BISHOP, [Movement.BishopMove]));
this.setPiece(2, 7, new Piece(PieceColor.BLACK, PieceType.BISHOP, [Movement.BishopMove]));
this.setPiece(5, 7, new Piece(PieceColor.BLACK, PieceType.BISHOP, [Movement.BishopMove]));
this.setPiece(2, 0, new Piece(PieceColor.WHITE, PieceType.BISHOP, [Movement.BishopMove], 2, 0));
this.setPiece(5, 0, new Piece(PieceColor.WHITE, PieceType.BISHOP, [Movement.BishopMove], 5, 0));
this.setPiece(2, 7, new Piece(PieceColor.BLACK, PieceType.BISHOP, [Movement.BishopMove], 2, 7));
this.setPiece(5, 7, new Piece(PieceColor.BLACK, PieceType.BISHOP, [Movement.BishopMove], 5, 7));
// Queens and Kings
this.setPiece(3, 0, new Piece(PieceColor.WHITE, PieceType.QUEEN, [Movement.QueenMove]));
this.setPiece(4, 0, new Piece(PieceColor.WHITE, PieceType.KING, [Movement.KingMove]));
this.setPiece(3, 7, new Piece(PieceColor.BLACK, PieceType.QUEEN, [Movement.QueenMove]));
this.setPiece(4, 7, new Piece(PieceColor.BLACK, PieceType.KING, [Movement.KingMove]));
this.setPiece(3, 0, new Piece(PieceColor.WHITE, PieceType.QUEEN, [Movement.QueenMove], 3, 0));
this.setPiece(4, 0, new Piece(PieceColor.WHITE, PieceType.KING, [Movement.KingMove], 4, 0));
this.setPiece(3, 7, new Piece(PieceColor.BLACK, PieceType.QUEEN, [Movement.QueenMove], 3, 7));
this.setPiece(4, 7, new Piece(PieceColor.BLACK, PieceType.KING, [Movement.KingMove], 4, 7));
}
}

View file

@ -1,6 +1,8 @@
import Board from './board.js';
import Board, { Piece } from './board.js';
import Team from './team.js';
import Stack from './stack.js';
import PieceColor from './board.js';
import Piece from './board.js';
class GameState {
constructor() {
@ -14,34 +16,10 @@ class GameState {
this.blackTeam = new Team("black");
/** @type {number} */
this.turn = 0;
}
/**
* @returns {Board}
*/
getBoard() {
return this.board;
}
/**
* @returns {Team}
*/
getWhiteTeam() {
return this.whiteTeam;
}
/**
* @returns {Team}
*/
getBlackTeam() {
return this.blackTeam;
}
/**
* @returns {number}
*/
getTurn() {
return this.turn;
/** @type {Piece|null} */
this.whiteSelectedPiece = null;
/** @type {Piece|null} */
this.blackSelectedPiece = null;
}
/**
@ -59,6 +37,97 @@ class GameState {
const team = color === PieceColor.WHITE ? this.whiteTeam : this.blackTeam;
return team.hasKing();
}
/**
* @param {PieceColor}
* @returns {Array<>}
*/
getMoves(team) {
if (team == WHITE && this.whiteSelectedPiece != null) {
if (this.whiteSelectedPiece.priorityMovements.length > 0) {
return this.whiteSelectedPiece.priorityMovements.flatmap((m) => m.moves());
} else {
return this.whiteSelectedPiece.movements.flatMap((m) => m.moves());
}
} else if (team == BLACK && this.blackSelectedPiece != null) {
if (this.blackSelectedPiece.priorityMovements.length > 0) {
return this.blackSelectedPiece.priorityMovements.flatmap((m) => m.moves());
} else {
return this.blackSelectedPiece.movements.flatMap((m) => m.moves());
}
} else {
return [];
}
}
/**
* @param {number}
* @param {number}
* @param {PieceColor}
* @returns {boolean}
*/
click(x, y, team) {
selectedPiece = this.board.grid[x][y];
// White team
if (team == WHITE) {
// one empty cell
if (this.whiteSelectedPiece == null) {
this.whiteSelectedPiece = this.board.grid[x][y].piece;
// previous one was black
} else if (this.whiteSelectedPiece.color == BLACK) {
this.whiteSelectedPiece = this.board.grid[x][y].piece;
// select a white piece
} else if (selectedPiece.color == WHITE) {
this.whiteSelectedPiece = this.board.grid[x][y].piece;
// possible move
} else {
// authorized move
if (this.getMoves(team).filter(({x_, y_, _}) => x == x_ && y == y_).length > 0) {
if (selectedPiece != null) {
this.whiteTeam.capture.push(selectedPiece);
}
this.board.grid[x][y] = this.whiteSelectedPiece;
this.board.grid[this.whiteSelectedPiece.x][this.whiteSelectedPiece.y] = null;
this.whiteSelectedPiece.x = x;
this.whiteSelectedPiece.y = y;
return true;
} else {
this.whiteSelectedPiece = this.board.grid[x][y].piece;
}
}
// black team
} else {
// one empty cell
if (this.blackSelectedPiece == null) {
this.blackSelectedPiece = this.board.grid[x][y].piece;
// previous one was white
} else if (this.blackSelectedPiece.color == WHITE) {
this.blackSelectedPiece = this.board.grid[x][y].piece;
// select a black piece
} else if (selectedPiece.color == BLACK) {
this.blackSelectedPiece = this.board.grid[x][y].piece;
// possible move
} else {
// authorized move
if (this.getMoves(team).filter(({x_, y_, _}) => x == x_ && y == y_).length > 0) {
if (selectedPiece != null) {
this.blackTeam.capture.push(selectedPiece);
}
this.board.grid[x][y] = this.blackSelectedPiece;
this.board.grid[this.blackSelectedPiece.x][this.blackSelectedPiece.y] = null;
this.blackSelectedPiece.x = x;
this.blackSelectedPiece.y = y;
return true;
} else {
this.blackSelectedPiece = this.board.grid[x][y].piece;
}
}
}
// no move done
return false;
}
}
export default GameState;

View file

@ -13,7 +13,16 @@
* - allowCapture=true
* - allowEmpty=true
*/
export function generateLinearMoves({ board, from, piece, directions, maxSteps = Infinity, allowCapture = true, allowEmpty = true }) {
export function generateLinearMoves({
board,
from,
piece,
directions,
maxSteps = Infinity,
allowCapture = true,
allowEmpty = true,
allowRing = false
}) {
const moves = [];
const w = board.getWidth();
const h = board.getHeight();

View file

@ -1,11 +1,12 @@
import { generateLinearMoves } from './generateMoves.js';
// basic moves
class RookMove {
/**
* Return possible moves for a rook-like piece from `from` on the given `board`.
* The move format is { x, y, capture: boolean }
*
* ctx: { board, from: {x,y}, piece }
* ctx: { board, from: {x,y}, piece, allowRing }
*/
static moves(ctx) {
const orthogonals = [
@ -20,6 +21,7 @@ class RookMove {
from: ctx.from,
piece: ctx.piece,
directions: orthogonals,
allowRing: ctx.allowRing
});
}
}
@ -44,6 +46,7 @@ class BishopMove {
from: ctx.from,
piece: ctx.piece,
directions: diagonals,
allowRing: ctx.allowRing
});
}
}
@ -69,6 +72,7 @@ class KnightMove {
maxSteps: 1,
allowEmpty: true,
allowCapture: true,
allowRing: ctx.allowRing
});
}
@ -92,6 +96,7 @@ class QueenMove {
from: ctx.from,
piece: ctx.piece,
directions: directions,
allowRing: ctx.allowRing
});
}
}
@ -115,6 +120,7 @@ class KingMove {
piece: ctx.piece,
directions: directions,
maxSteps: 1,
allowRing: ctx.allowRing
});
}
}

View file

@ -17,8 +17,10 @@ class Piece {
* @param {PieceColor} color
* @param {PieceType} type
* @param {Array<import('./movement/index.js').default>} movements
* @param {number} x
* @param {number} y
*/
constructor(color, type, movements) {
constructor(color, type, movements, x, y) {
/** @type {PieceColor} */
this.color = color;
/** @type {PieceType} */
@ -29,20 +31,10 @@ class Piece {
this.movements = movements;
/** @type {Array<import('./movement/index.js').default>} */
this.priorityMovements = [];
}
/**
* @returns {PieceColor}
*/
getColor() {
return this.color;
}
/**
* @returns {PieceType}
*/
getType() {
return this.type;
/** @type {number} */
this.x = x;
/** @type {number} */
this.y = y;
}
}

View file

@ -15,6 +15,8 @@ class Team {
this.hand = new Hand();
/** @type {boolean} */
this.hasMadeAction = false;
/** @type {Array<Piece>} */
this.capture = [];
}
/**