implemented bisic moves
This commit is contained in:
parent
97ef669cbe
commit
0a8507b90c
5 changed files with 240 additions and 1 deletions
|
|
@ -89,4 +89,6 @@ La position de toutes les pièces sont échangées aléatoirement.
|
||||||
### La parrure
|
### La parrure
|
||||||
Une reine est dégradée en pion
|
Une reine est dégradée en pion
|
||||||
### Tricherie
|
### Tricherie
|
||||||
Regarde les trois prochaines cartes de la pioche
|
Regarde les trois prochaines cartes de la pioche
|
||||||
|
### Tout ou rien
|
||||||
|
Une pièce choisie ne peut maintenant se déplacer que si elle capture
|
||||||
50
engine/core/movement/generateMoves.js
Normal file
50
engine/core/movement/generateMoves.js
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Utilities for movement generation
|
||||||
|
// The movement modules receive a context object with at least:
|
||||||
|
// - board: instance exposing getWidth(), getHeight(), getCell(x,y) and setPiece(x,y,piece)
|
||||||
|
// - from: { x, y }
|
||||||
|
// - piece: the moving piece (with getColor())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Walk in linear directions (array of dx,dy) until blocked.
|
||||||
|
* Returns an array of move objects: { x, y, capture: boolean }
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
* - maxSteps (default: Infinity)
|
||||||
|
* - allowCapture=true
|
||||||
|
* - allowEmpty=true
|
||||||
|
*/
|
||||||
|
export function generateLinearMoves({ board, from, piece, directions, maxSteps = Infinity, allowCapture = true, allowEmpty = true }) {
|
||||||
|
const moves = [];
|
||||||
|
const w = board.getWidth();
|
||||||
|
const h = board.getHeight();
|
||||||
|
const color = piece.getColor();
|
||||||
|
|
||||||
|
for (const [dx, dy] of directions) {
|
||||||
|
let steps = 0;
|
||||||
|
let x = from.x + dx;
|
||||||
|
let y = from.y + dy;
|
||||||
|
|
||||||
|
while (x >= 0 && x < w && y >= 0 && y < h && steps < maxSteps) {
|
||||||
|
const cell = board.getCell(x, y);
|
||||||
|
const target = cell?.piece ?? null;
|
||||||
|
|
||||||
|
if (target == null) {
|
||||||
|
if (allowEmpty) moves.push({ x, y, capture: false });
|
||||||
|
// continue along this direction
|
||||||
|
} else {
|
||||||
|
// occupied
|
||||||
|
if (target.getColor() !== color) {
|
||||||
|
if (allowCapture) moves.push({ x, y, capture: true });
|
||||||
|
}
|
||||||
|
// stop after encountering any piece
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
steps++;
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return moves;
|
||||||
|
}
|
||||||
13
engine/core/movement/index.js
Normal file
13
engine/core/movement/index.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Central export for movement modules
|
||||||
|
import {RookMove, BishopMove, KnightMove, QueenMove, KingMove, PawnMove} from './moves.js';
|
||||||
|
import { generateLinearMoves } from './generateMoves.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
RookMove,
|
||||||
|
BishopMove,
|
||||||
|
KnightMove,
|
||||||
|
QueenMove,
|
||||||
|
KingMove,
|
||||||
|
PawnMove,
|
||||||
|
generateLinearMoves,
|
||||||
|
};
|
||||||
172
engine/core/movement/moves.js
Normal file
172
engine/core/movement/moves.js
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
import { generateLinearMoves } from './generateMoves.js';
|
||||||
|
|
||||||
|
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 }
|
||||||
|
*/
|
||||||
|
static moves(ctx) {
|
||||||
|
const orthogonals = [
|
||||||
|
[1, 0],
|
||||||
|
[-1, 0],
|
||||||
|
[0, 1],
|
||||||
|
[0, -1],
|
||||||
|
];
|
||||||
|
|
||||||
|
return generateLinearMoves({
|
||||||
|
board: ctx.board,
|
||||||
|
from: ctx.from,
|
||||||
|
piece: ctx.piece,
|
||||||
|
directions: orthogonals,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BishopMove {
|
||||||
|
/**
|
||||||
|
* Return possible moves for a bishop-like piece from `from` on the given `board`.
|
||||||
|
* The move format is { x, y, capture: boolean }
|
||||||
|
*
|
||||||
|
* ctx: { board, from: {x,y}, piece }
|
||||||
|
*/
|
||||||
|
static moves(ctx) {
|
||||||
|
const diagonals = [
|
||||||
|
[1, 1],
|
||||||
|
[1, -1],
|
||||||
|
[-1, 1],
|
||||||
|
[-1, -1],
|
||||||
|
];
|
||||||
|
|
||||||
|
return generateLinearMoves({
|
||||||
|
board: ctx.board,
|
||||||
|
from: ctx.from,
|
||||||
|
piece: ctx.piece,
|
||||||
|
directions: diagonals,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KnightMove {
|
||||||
|
/**
|
||||||
|
* Return possible moves for a knight-like piece from `from` on the given `board`.
|
||||||
|
* The move format is { x, y, capture: boolean }
|
||||||
|
*
|
||||||
|
* ctx: { board, from: {x,y}, piece }
|
||||||
|
*/
|
||||||
|
static moves(ctx) {
|
||||||
|
const knightMoves = [
|
||||||
|
[2, 1], [2, -1], [-2, 1], [-2, -1],
|
||||||
|
[1, 2], [1, -2], [-1, 2], [-1, -2],
|
||||||
|
];
|
||||||
|
|
||||||
|
return generateLinearMoves({
|
||||||
|
board: ctx.board,
|
||||||
|
from: ctx.from,
|
||||||
|
piece: ctx.piece,
|
||||||
|
directions: knightMoves,
|
||||||
|
maxSteps: 1,
|
||||||
|
allowEmpty: true,
|
||||||
|
allowCapture: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class QueenMove {
|
||||||
|
/**
|
||||||
|
* Return possible moves for a queen-like piece from `from` on the given `board`.
|
||||||
|
* The move format is { x, y, capture: boolean }
|
||||||
|
*
|
||||||
|
* ctx: { board, from: {x,y}, piece }
|
||||||
|
*/
|
||||||
|
static moves(ctx) {
|
||||||
|
const directions = [
|
||||||
|
[1, 0], [-1, 0], [0, 1], [0, -1], // orthogonals
|
||||||
|
[1, 1], [1, -1], [-1, 1], [-1, -1], // diagonals
|
||||||
|
];
|
||||||
|
|
||||||
|
return generateLinearMoves({
|
||||||
|
board: ctx.board,
|
||||||
|
from: ctx.from,
|
||||||
|
piece: ctx.piece,
|
||||||
|
directions: directions,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KingMove {
|
||||||
|
/**
|
||||||
|
* Return possible moves for a king-like piece from `from` on the given `board`.
|
||||||
|
* The move format is { x, y, capture: boolean }
|
||||||
|
*
|
||||||
|
* ctx: { board, from: {x,y}, piece }
|
||||||
|
*/
|
||||||
|
static moves(ctx) {
|
||||||
|
const directions = [
|
||||||
|
[1, 0], [-1, 0], [0, 1], [0, -1], // orthogonals
|
||||||
|
[1, 1], [1, -1], [-1, 1], [-1, -1], // diagonals
|
||||||
|
];
|
||||||
|
|
||||||
|
return generateLinearMoves({
|
||||||
|
board: ctx.board,
|
||||||
|
from: ctx.from,
|
||||||
|
piece: ctx.piece,
|
||||||
|
directions: directions,
|
||||||
|
maxSteps: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PawnMove {
|
||||||
|
/**
|
||||||
|
* Return possible moves for a pawn-like piece from `from` on the given `board`.
|
||||||
|
* The move format is { x, y, capture: boolean }
|
||||||
|
*
|
||||||
|
* ctx: { board, from: {x,y}, piece }
|
||||||
|
*/
|
||||||
|
static moves(ctx) {
|
||||||
|
const color = ctx.piece.getColor();
|
||||||
|
const forward = (color === 'white') ? -1 : 1; // assuming y=0 is top
|
||||||
|
|
||||||
|
const moves = [];
|
||||||
|
const w = ctx.board.getWidth();
|
||||||
|
const h = ctx.board.getHeight();
|
||||||
|
const x = ctx.from.x;
|
||||||
|
const y = ctx.from.y;
|
||||||
|
|
||||||
|
// Forward move
|
||||||
|
if (y + forward >= 0 && y + forward < h) {
|
||||||
|
const forwardCell = ctx.board.getCell(x, y + forward);
|
||||||
|
if (forwardCell?.piece == null) {
|
||||||
|
moves.push({ x: x, y: y + forward, capture: false });
|
||||||
|
|
||||||
|
// Double step from starting position
|
||||||
|
const startingRow = (color === 'white') ? h - 2 : 1;
|
||||||
|
if (!ctx.piece.hasMoved) {
|
||||||
|
const doubleForwardCell = ctx.board.getCell(x, y + 2 * forward);
|
||||||
|
if (doubleForwardCell?.piece == null) {
|
||||||
|
moves.push({ x: x, y: y + 2 * forward, capture: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Captures
|
||||||
|
for (const dx of [-1, 1]) {
|
||||||
|
if (x + dx >= 0 && x + dx < w && y + forward >= 0 && y + forward < h) {
|
||||||
|
const diagCell = ctx.board.getCell(x + dx, y + forward);
|
||||||
|
const target = diagCell?.piece ?? null;
|
||||||
|
if (target != null && target.getColor() !== color) {
|
||||||
|
moves.push({ x: x + dx, y: y + forward, capture: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return moves;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { RookMove, BishopMove, KnightMove, QueenMove, KingMove, PawnMove };
|
||||||
|
|
@ -22,6 +22,8 @@ class Piece {
|
||||||
this.color = color;
|
this.color = color;
|
||||||
/** @type {PieceType} */
|
/** @type {PieceType} */
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
/** @type {boolean} */
|
||||||
|
this.hasMoved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue