1 class ZenRules
extends ChessRules
3 // NOTE: enPassant, if enabled, would need to redefine carefully getEpSquare
9 // TODO(?): some duplicated code in 2 next functions
10 getSlideNJumpMoves([x
,y
], steps
, oneStep
)
12 const color
= this.getColor(x
,y
);
15 for (let loop
=0; loop
<steps
.length
; loop
++)
17 const step
= steps
[loop
];
20 while (V
.OnBoard(i
,j
) && this.board
[i
][j
] == V
.EMPTY
)
22 moves
.push(this.getBasicMove([x
,y
], [i
,j
]));
28 // No capture check: handled elsewhere (next method)
33 // follow steps from x,y until something is met.
34 // if met piece is opponent and same movement (asA): eat it!
35 findCaptures_aux([x
,y
], asA
)
37 const color
= this.getColor(x
,y
);
39 const steps
= asA
!= V
.PAWN
40 ? (asA
==V
.QUEEN
? V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]) : V
.steps
[asA
])
41 : color
=='w' ? [[-1,-1],[-1,1]] : [[1,-1],[1,1]];
42 const oneStep
= (asA
==V
.KNIGHT
|| asA
==V
.PAWN
); //we don't capture king
43 const lastRank
= (color
== 'w' ? 0 : V
.size
.x
-1);
44 const promotionPieces
= [V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
46 for (let loop
=0; loop
<steps
.length
; loop
++)
48 const step
= steps
[loop
];
51 while (V
.OnBoard(i
,j
) && this.board
[i
][j
] == V
.EMPTY
)
58 if (V
.OnBoard(i
,j
) && this.getColor(i
,j
) == this.getOppCol(color
)
59 && this.getPiece(i
,j
) == asA
)
62 if (this.getPiece(x
,y
) == V
.PAWN
&& i
== lastRank
)
64 // Special case of promotion:
65 promotionPieces
.forEach(p
=> {
66 moves
.push(this.getBasicMove([x
,y
], [i
,j
], {c:color
,p:p
}));
72 moves
.push(this.getBasicMove([x
,y
], [i
,j
]));
79 // Find possible captures from a square: look in every direction!
84 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.PAWN
));
85 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.ROOK
));
86 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.KNIGHT
));
87 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.BISHOP
));
88 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.QUEEN
));
93 getPotentialPawnMoves([x
,y
])
95 const color
= this.getColor(x
,y
);
97 const [sizeX
,sizeY
] = [V
.size
.x
,V
.size
.y
];
98 const shift
= (color
== 'w' ? -1 : 1);
99 const startRank
= (color
== 'w' ? sizeY
-2 : 1);
100 const firstRank
= (color
== 'w' ? sizeY
-1 : 0);
101 const lastRank
= (color
== "w" ? 0 : sizeY
-1);
103 if (x
+shift
>= 0 && x
+shift
< sizeX
&& x
+shift
!= lastRank
)
106 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
108 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
]));
109 if ([startRank
,firstRank
].includes(x
) && this.board
[x
+2*shift
][y
] == V
.EMPTY
)
112 moves
.push(this.getBasicMove([x
,y
], [x
+2*shift
,y
]));
117 if (x
+shift
== lastRank
)
120 let promotionPieces
= [V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
121 promotionPieces
.forEach(p
=> {
123 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
124 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
], {c:color
,p:p
}));
128 // No en passant here
130 // Add "zen" captures
131 Array
.prototype.push
.apply(moves
, this.findCaptures([x
,y
]));
136 getPotentialRookMoves(sq
)
138 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
]);
139 let captures
= this.findCaptures(sq
);
140 return noCaptures
.concat(captures
);
143 getPotentialKnightMoves(sq
)
145 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep");
146 let captures
= this.findCaptures(sq
);
147 return noCaptures
.concat(captures
);
150 getPotentialBishopMoves(sq
)
152 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]);
153 let captures
= this.findCaptures(sq
);
154 return noCaptures
.concat(captures
);
157 getPotentialQueenMoves(sq
)
159 let noCaptures
= this.getSlideNJumpMoves(
160 sq
, V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]));
161 let captures
= this.findCaptures(sq
);
162 return noCaptures
.concat(captures
);
165 getPotentialKingMoves(sq
)
167 // Initialize with normal moves
168 let noCaptures
= this.getSlideNJumpMoves(sq
,
169 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]), "oneStep");
170 let captures
= this.findCaptures(sq
);
171 return noCaptures
.concat(captures
).concat(this.getCastleMoves(sq
));
176 // Recognize special moves first
177 if (move.appear
.length
== 2)
180 if (move.end
.y
< move.start
.y
)
186 // Translate initial square (because pieces may fly unusually in this variant!)
187 const initialSquare
=
188 String
.fromCharCode(97 + move.start
.y
) + (V
.size
.x
-move.start
.x
);
190 // Translate final square
192 String
.fromCharCode(97 + move.end
.y
) + (V
.size
.x
-move.end
.x
);
195 const piece
= this.getPiece(move.start
.x
, move.start
.y
);
198 // pawn move (TODO: enPassant indication)
199 if (move.vanish
.length
> 1)
202 notation
= initialSquare
+ "x" + finalSquare
;
205 notation
= finalSquare
;
206 if (piece
!= move.appear
[0].p
) //promotion
207 notation
+= "=" + move.appear
[0].p
.toUpperCase();
213 notation
= piece
.toUpperCase();
214 if (move.vanish
.length
> 1)
215 notation
+= initialSquare
+ "x";
216 notation
+= finalSquare
;
221 static get VALUES() { //TODO: experimental