Improve Switching chess: avoid duplicate moves for analysis, better notation
[vchess.git] / public / javascripts / variants / Switching.js
CommitLineData
a6abf094
BA
1class SwitchingRules extends ChessRules
2{
1221ac47
BA
3 // Build switch move between squares x1,y1 and x2,y2
4 getSwitchMove_s([x1,y1],[x2,y2])
5 {
1221ac47
BA
6 const c = this.getColor(x1,y1); //same as color at square 2
7 const p1 = this.getPiece(x1,y1);
8 const p2 = this.getPiece(x2,y2);
6752407b
BA
9 const V = VariantRules;
10 if (p1 == V.KING && p2 == V.ROOK)
11 return []; //avoid duplicate moves (potential conflict with castle)
1221ac47
BA
12 let move = new Move({
13 appear: [
14 new PiPo({x:x2,y:y2,c:c,p:p1}),
15 new PiPo({x:x1,y:y1,c:c,p:p2})
16 ],
17 vanish: [
18 new PiPo({x:x1,y:y1,c:c,p:p1}),
19 new PiPo({x:x2,y:y2,c:c,p:p2})
20 ],
21 start: {x:x1,y:y1},
22 end: {x:x2,y:y2}
23 });
24 // Move completion: promote switched pawns (as in Magnetic)
25 const sizeX = VariantRules.size[0];
26 const lastRank = (c == "w" ? 0 : sizeX-1);
1221ac47 27 let moves = [];
9f18af3b 28 if ((p1==V.PAWN && x2==lastRank) || (p2==V.PAWN && x1==lastRank))
1221ac47 29 {
9f18af3b
BA
30 const idx = (p1==V.PAWN ? 0 : 1);
31 move.appear[idx].p = V.ROOK;
1221ac47
BA
32 moves.push(move);
33 for (let piece of [V.KNIGHT, V.BISHOP, V.QUEEN])
34 {
35 let cmove = JSON.parse(JSON.stringify(move));
9f18af3b 36 cmove.appear[idx].p = piece;
1221ac47
BA
37 moves.push(cmove);
38 }
9f18af3b
BA
39 if (idx == 1)
40 {
41 // Swap moves[i].appear[0] and [1] for moves presentation [TODO...]
42 moves.forEach(m => {
43 let tmp = m.appear[0];
44 m.appear[0] = m.appear[1];
45 m.appear[1] = tmp;
46 });
47 }
1221ac47
BA
48 }
49 else //other cases
50 moves.push(move);
51 return moves;
52 }
a6abf094 53
15952ada 54 getPotentialMovesFrom([x,y], computer)
1221ac47
BA
55 {
56 let moves = super.getPotentialMovesFrom([x,y]);
15952ada 57 // Add switches: respecting chessboard ordering if "computer" is on
1221ac47
BA
58 const V = VariantRules;
59 const color = this.turn;
60 const piece = this.getPiece(x,y);
61 const [sizeX,sizeY] = V.size;
62 const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
63 const kp = this.kingPos[color];
64 const oppCol = this.getOppCol(color);
65 for (let step of steps)
66 {
67 let [i,j] = [x+step[0],y+step[1]];
15952ada
BA
68 if (!!computer && (i<x || (i==x && j<y)))
69 continue; //only switch with superior indices
1221ac47
BA
70 if (i>=0 && i<sizeX && j>=0 && j<sizeY && this.board[i][j]!=V.EMPTY
71 && this.getColor(i,j)==color && this.getPiece(i,j)!=piece
72 // No switching under check (theoretically non-king pieces could, but not)
73 && !this.isAttacked(kp, [oppCol]))
74 {
75 let switchMove_s = this.getSwitchMove_s([x,y],[i,j]);
76 if (switchMove_s.length == 1)
77 moves.push(switchMove_s[0]);
78 else //promotion
79 moves = moves.concat(switchMove_s);
80 }
81 }
82 return moves;
83 }
84
15952ada
BA
85 getAllValidMoves(computer)
86 {
87 const color = this.turn;
88 const oppCol = this.getOppCol(color);
89 let potentialMoves = [];
90 const [sizeX,sizeY] = VariantRules.size;
91 for (let i=0; i<sizeX; i++)
92 {
93 for (let j=0; j<sizeY; j++)
94 {
95 if (this.board[i][j] != VariantRules.EMPTY && this.getColor(i,j) == color)
96 {
97 Array.prototype.push.apply(potentialMoves,
98 this.getPotentialMovesFrom([i,j], computer));
99 }
100 }
101 }
102 return this.filterValid(potentialMoves);
103 }
104
9f18af3b
BA
105 updateVariables(move)
106 {
107 super.updateVariables(move);
108 if (move.appear.length == 2 && move.vanish.length == 2
109 && move.appear[1].p == VariantRules.KING)
110 {
111 // Switch with the king; not castle, and not handled by main class
112 const color = this.getColor(move.start.x, move.start.y);
113 this.kingPos[color] = [move.appear[1].x, move.appear[1].y];
114 }
115 }
116
117 unupdateVariables(move)
118 {
119 super.unupdateVariables(move);
120 if (move.appear.length == 2 && move.vanish.length == 2
121 && move.appear[1].p == VariantRules.KING)
122 {
123 const color = this.getColor(move.start.x, move.start.y);
124 this.kingPos[color] = [move.appear[0].x, move.appear[0].y];
125 }
126 }
127
15952ada
BA
128 static get SEARCH_DEPTH() { return 2; } //high branching factor
129
130 getNotation(move)
131 {
132 if (move.appear.length == 1)
133 return super.getNotation(move); //no switch
134 // Switch or castle
135 if (move.appear[0].p == VariantRules.KING && move.appear[1].p == VariantRules.ROOK)
136 return (move.end.y < move.start.y ? "0-0-0" : "0-0");
137 // Switch:
138 const startSquare =
139 String.fromCharCode(97 + move.start.y) + (VariantRules.size[0]-move.start.x);
140 const finalSquare =
141 String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x);
142 return "S" + startSquare + finalSquare;
143 }
a6abf094 144}