diff --git a/README.md b/README.md index fb5e7dd..d0191a9 100644 --- a/README.md +++ b/README.md @@ -95,4 +95,10 @@ Une pièce choisie ne peut maintenant se déplacer que si elle capture. ### Tous les mêmes 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. \ No newline at end of file +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. diff --git a/engine/core/board.js b/engine/core/board.js index fd20c08..3883fe0 100644 --- a/engine/core/board.js +++ b/engine/core/board.js @@ -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,35 +33,35 @@ 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)); } } export { Cell, Movement, Piece, PieceColor, PieceType }; -export default Board; \ No newline at end of file +export default Board; diff --git a/engine/core/card.js b/engine/core/card.js index 4d46973..9c40328 100644 --- a/engine/core/card.js +++ b/engine/core/card.js @@ -11,4 +11,4 @@ class Card { } } -export default Card; \ No newline at end of file +export default Card; diff --git a/engine/core/cell.js b/engine/core/cell.js index daf52ff..7967912 100644 --- a/engine/core/cell.js +++ b/engine/core/cell.js @@ -8,4 +8,4 @@ class Cell { } } -export default Cell; \ No newline at end of file +export default Cell; diff --git a/engine/core/effect.js b/engine/core/effect.js index 5582ec3..4f80e3f 100644 --- a/engine/core/effect.js +++ b/engine/core/effect.js @@ -2,4 +2,4 @@ class Effect { constructor() {} } -export default Effect; \ No newline at end of file +export default Effect; diff --git a/engine/core/game_state.js b/engine/core/game_state.js index 145aa7a..abb2bfc 100644 --- a/engine/core/game_state.js +++ b/engine/core/game_state.js @@ -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; \ No newline at end of file +export default GameState; diff --git a/engine/core/hand.js b/engine/core/hand.js index 4091051..ec25070 100644 --- a/engine/core/hand.js +++ b/engine/core/hand.js @@ -28,4 +28,4 @@ class Hand { } } -export default Hand; \ No newline at end of file +export default Hand; diff --git a/engine/core/movement/generateMoves.js b/engine/core/movement/generateMoves.js index 706f863..9431ba7 100644 --- a/engine/core/movement/generateMoves.js +++ b/engine/core/movement/generateMoves.js @@ -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(); diff --git a/engine/core/movement/moves.js b/engine/core/movement/moves.js index 26843f6..9856a41 100644 --- a/engine/core/movement/moves.js +++ b/engine/core/movement/moves.js @@ -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 }); } } diff --git a/engine/core/piece.js b/engine/core/piece.js index 12c5ae6..a3f0168 100644 --- a/engine/core/piece.js +++ b/engine/core/piece.js @@ -17,8 +17,10 @@ class Piece { * @param {PieceColor} color * @param {PieceType} type * @param {Array} 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,22 +31,12 @@ class Piece { this.movements = movements; /** @type {Array} */ this.priorityMovements = []; - } - - /** - * @returns {PieceColor} - */ - getColor() { - return this.color; - } - - /** - * @returns {PieceType} - */ - getType() { - return this.type; + /** @type {number} */ + this.x = x; + /** @type {number} */ + this.y = y; } } export default Piece; -export { PieceColor, PieceType }; \ No newline at end of file +export { PieceColor, PieceType }; diff --git a/engine/core/stack.js b/engine/core/stack.js index 84d1978..2720342 100644 --- a/engine/core/stack.js +++ b/engine/core/stack.js @@ -47,4 +47,4 @@ class Stack { } } -export default Stack; \ No newline at end of file +export default Stack; diff --git a/engine/core/team.js b/engine/core/team.js index 7f4183b..ac75809 100644 --- a/engine/core/team.js +++ b/engine/core/team.js @@ -11,10 +11,12 @@ class Team { this.color = color; /** @type {Piece} */ this.king = king; - /** @type {Hand} */ - this.hand = new Hand(); + /** @type {Hand} */ + this.hand = new Hand(); /** @type {boolean} */ this.hasMadeAction = false; + /** @type {Array} */ + this.capture = []; } /** @@ -25,4 +27,4 @@ class Team { } } -export default Team; \ No newline at end of file +export default Team;