Draft Alice rules
[vchess.git] / public / javascripts / variants / Alice.js
... / ...
CommitLineData
1class AliceRules extends ChessRules
2{
3 static get ALICE_PIECES()
4 {
5 return {
6 's': 'p',
7 't': 'q',
8 'u': 'r',
9 'c': 'b',
10 'o': 'n',
11 'l': 'k',
12 };
13 }
14 static get ALICE_CODES()
15 {
16 return {
17 'p': 's',
18 'q': 't',
19 'r': 'u',
20 'b': 'c',
21 'n': 'o',
22 'k': 'l',
23 };
24 }
25
26 static getPpath(b)
27 {
28 return (Object.keys(this.ALICE_PIECES).includes(b[1]) ? "Alice/" : "") + b;
29 }
30
31 getBoardOfPiece([x,y])
32 {
33 const V = VariantRules;
34 // Build board where the piece is
35 const mirrorSide = (Object.keys(V.ALICE_CODES).includes(this.getPiece(x,y)) ? 1 : 2);
36 // Build corresponding board from complete board
37 const [sizeX,sizeY] = V.size;
38 let sideBoard = doubleArray(sizeX, sizeY, "");
39 for (let i=0; i<sizeX; i++)
40 {
41 for (let j=0; j<sizeY; j++)
42 {
43 const piece = this.getPiece(i,j);
44 if (mirrorSide==1 && Object.keys(V.ALICE_CODES).includes(piece))
45 sideBoard[i][j] = this.board[i][j];
46 else if (mirrorSide==2 && Object.keys(V.ALICE_PIECES).includes(piece))
47 sideBoard[i][j] = this.getColor(i,j) + V.ALICE_PIECES[piece];
48 }
49 }
50 return sideBoard;
51 }
52
53 // NOTE: castle & enPassant https://www.chessvariants.com/other.dir/alice.html
54 // --> Should be OK as is.
55 getPotentialMovesFrom([x,y])
56 {
57 let sideBoard = this.getBoardOfPiece([x,y]);
58
59 // Search valid moves on sideBoard
60 let saveBoard = this.board;
61 this.board = sideBoard;
62 let moves = super.getPotentialMovesFrom([x,y]);
63 this.board = saveBoard;
64
65 // Finally filter impossible moves
66 const mirrorSide = (Object.keys(VariantRules.ALICE_CODES).includes(this.getPiece(x,y)) ? 1 : 2);
67 return moves.filter(m => {
68 if (m.appear.length == 2) //castle
69 {
70 // If appear[i] not in vanish array, then must be empty square on other board
71 m.appear.forEach(psq => {
72 if (this.board[psq.x][psq.y] != VariantRules.EMPTY &&
73 ![m.vanish[0].y,m.vanish[1].y].includes(psq.y))
74 {
75 return false;
76 }
77 });
78 }
79 else if (this.board[m.end.x][m.end.y] != VariantRules.EMPTY)
80 {
81 // Attempt to capture
82 const piece = this.getPiece(m.end.x,m.end.y);
83 if ((mirrorSide==1 && Object.keys(VariantRules.ALICE_PIECES).includes(piece))
84 || (mirrorSide==2 && Object.keys(VariantRules.ALICE_CODES).includes(piece)))
85 {
86 return false;
87 }
88 }
89 // If the move is computed on board1, m.appear change for Alice pieces.
90 if (mirrorSide==1)
91 {
92 m.appear.forEach(psq => { //forEach: castling taken into account
93 psq.p = VariantRules.ALICE_CODES[psq.p]; //goto board2
94 });
95 }
96 else //move on board2: mark vanishing piece as Alice
97 m.vanish[0].p = VariantRules.ALICE_CODES[m.vanish[0].p]
98 return true;
99 });
100 }
101
102 underCheck(move)
103 {
104 const color = this.turn;
105 this.play(move);
106 let sideBoard = this.getBoardOfPiece(this.kingPos[color]);
107 let saveBoard = this.board;
108 this.board = sideBoard;
109 let res = this.isAttacked(this.kingPos[color], this.getOppCol(color));
110 this.board = saveBoard;
111 this.undo(move);
112 return res;
113 }
114
115 getCheckSquares(move)
116 {
117 this.play(move);
118 const color = this.turn; //opponent
119 let sideBoard = this.getBoardOfPiece(this.kingPos[color]);
120 let saveBoard = this.board;
121 this.board = sideBoard;
122 let res = this.isAttacked(this.kingPos[color], this.getOppCol(color))
123 ? [ JSON.parse(JSON.stringify(this.kingPos[color])) ]
124 : [ ];
125 this.board = saveBoard;
126 this.undo(move);
127 return res;
128 }
129
130 getNotation(move)
131 {
132 if (move.appear.length == 2 && move.appear[0].p == VariantRules.KING)
133 {
134 if (move.end.y < move.start.y)
135 return "0-0-0";
136 else
137 return "0-0";
138 }
139
140 const finalSquare =
141 String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x);
142 const piece = this.getPiece(move.start.x, move.start.y);
143
144 // Piece or pawn movement
145 let notation = piece.toUpperCase() +
146 (move.vanish.length > move.appear.length ? "x" : "") + finalSquare;
147 if (['s','p'].includes(piece) && !['s','p'].includes(move.appear[0].p))
148 {
149 // Promotion
150 notation += "=" + move.appear[0].p.toUpperCase();
151 }
152 return notation;
153 }
154
155 checkGameEnd()
156 {
157 const color = this.turn;
158 let sideBoard = this.getBoardOfPiece(this.kingPos[color]);
159 let saveBoard = this.board;
160 this.board = sideBoard;
161 let res = "*";
162 if (!this.isAttacked(this.kingPos[color], this.getOppCol(color)))
163 res = "1/2";
164 else
165 res = (color == "w" ? "0-1" : "1-0");
166 this.board = saveBoard;
167 return res;
168 }
169}