Several small improvements + integrate options + first working draft of Cwda
[vchess.git] / client / src / variants / Benedict.js
1 import { ChessRules, PiPo, Move } from "@/base_rules";
2
3 export class BenedictRules extends ChessRules {
4
5 static get HasEnpassant() {
6 return false;
7 }
8
9 static get PawnSpecs() {
10 return Object.assign(
11 {},
12 ChessRules.PawnSpecs,
13 { canCapture: false }
14 );
15 }
16
17 canTake() {
18 return false;
19 }
20
21 // Find possible captures from a square
22 // follow steps from x,y until something is met.
23 findCaptures([x, y]) {
24 const color = this.getColor(x, y);
25 const piece = this.getPiece(x, y);
26 let squares = [];
27 const steps =
28 piece != V.PAWN
29 ? [V.QUEEN,V.KING].includes(piece)
30 ? V.steps[V.ROOK].concat(V.steps[V.BISHOP])
31 : V.steps[piece]
32 : color == "w"
33 ? [
34 [-1, -1],
35 [-1, 1]
36 ]
37 : [
38 [1, -1],
39 [1, 1]
40 ];
41 const oneStep = [V.KNIGHT,V.PAWN,V.KING].includes(piece);
42 outerLoop: for (let loop = 0; loop < steps.length; loop++) {
43 const step = steps[loop];
44 let i = x + step[0];
45 let j = y + step[1];
46 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
47 if (oneStep) continue outerLoop;
48 i += step[0];
49 j += step[1];
50 }
51 if (
52 V.OnBoard(i, j) &&
53 this.getColor(i, j) == V.GetOppCol(color)
54 ) {
55 // eat!
56 squares.push([i, j]);
57 }
58 }
59 return squares;
60 }
61
62 // TODO: appear/vanish description of a move is too verbose for Benedict.
63 // => Would need a new "flipped" array, to be passed in Game.vue...
64 getPotentialMovesFrom([x, y]) {
65 const color = this.turn;
66 const oppCol = V.GetOppCol(color);
67 // Get all moves from x,y without captures:
68 let moves = super.getPotentialMovesFrom([x, y]);
69 // Add flips:
70 moves.forEach(m => {
71 let newAppear = [];
72 let newVanish = [];
73 V.PlayOnBoard(this.board, m);
74 // If castling, m.appear has 2 elements.
75 // In this case, consider the attacks of moving units only.
76 // (Sometimes the king or rook doesn't move).
77 for (let i = 0; i < m.appear.length; i++) {
78 const a = m.appear[i];
79 if (m.vanish[i].x != a.x || m.vanish[i].y != a.y) {
80 const flipped = this.findCaptures([a.x, a.y]);
81 flipped.forEach(sq => {
82 const piece = this.getPiece(sq[0],sq[1]);
83 const pipoA = new PiPo({
84 x:sq[0],
85 y:sq[1],
86 c:color,
87 p:piece
88 });
89 const pipoV = new PiPo({
90 x:sq[0],
91 y:sq[1],
92 c:oppCol,
93 p:piece
94 });
95 newAppear.push(pipoA);
96 newVanish.push(pipoV);
97 });
98 }
99 }
100 Array.prototype.push.apply(m.appear, newAppear);
101 Array.prototype.push.apply(m.vanish, newVanish);
102 V.UndoOnBoard(this.board, m);
103 });
104 return moves;
105 }
106
107 // Moves cannot flip our king's color, so all are valid
108 filterValid(moves) {
109 return moves;
110 }
111
112 // Since it's used just for the king, and there are no captures:
113 isAttacked(sq, color) {
114 return false;
115 }
116
117 // No notion of check here:
118 getCheckSquares() {
119 return [];
120 }
121
122 // Stop at the first move found
123 atLeastOneMove() {
124 const color = this.turn;
125 for (let i = 0; i < V.size.x; i++) {
126 for (let j = 0; j < V.size.y; j++) {
127 if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == color) {
128 if (this.getPotentialMovesFrom([i, j]).length > 0) return true;
129 }
130 }
131 }
132 return false;
133 }
134
135 getCurrentScore() {
136 const color = this.turn;
137 // Did a king change color?
138 const kp = this.kingPos[color];
139 if (this.getColor(kp[0], kp[1]) != color)
140 return color == "w" ? "0-1" : "1-0";
141 if (this.atLeastOneMove()) return "*";
142 // Stalemate:
143 return "1/2";
144 }
145
146 getNotation(move) {
147 // Just remove flips:
148 const basicMove = {
149 appear: [move.appear[0]],
150 vanish: [move.vanish[0]],
151 start: move.start,
152 end: move.end
153 };
154 return super.getNotation(basicMove);
155 }
156
157 };