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
);
14 const [sizeX
,sizeY
] = VariantRules
.size
;
16 for (let loop
=0; loop
<steps
.length
; loop
++)
18 const step
= steps
[loop
];
21 while (i
>=0 && i
<sizeX
&& j
>=0 && j
<sizeY
22 && this.board
[i
][j
] == VariantRules
.EMPTY
)
24 moves
.push(this.getBasicMove([x
,y
], [i
,j
]));
30 // No capture check: handled elsewhere (next method)
35 // follow steps from x,y until something is met.
36 // if met piece is opponent and same movement (asA): eat it!
37 findCaptures_aux([x
,y
], asA
)
39 const color
= this.getColor(x
,y
);
41 const V
= VariantRules
;
42 const steps
= asA
!= V
.PAWN
43 ? (asA
==V
.QUEEN
? V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]) : V
.steps
[asA
])
44 : color
=='w' ? [[-1,-1],[-1,1]] : [[1,-1],[1,1]];
45 const oneStep
= (asA
==V
.KNIGHT
|| asA
==V
.PAWN
); //we don't capture king
46 const [sizeX
,sizeY
] = V
.size
;
47 const lastRank
= (color
== 'w' ? 0 : sizeY
-1);
48 const promotionPieces
= [V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
50 for (let loop
=0; loop
<steps
.length
; loop
++)
52 const step
= steps
[loop
];
55 while (i
>=0 && i
<sizeX
&& j
>=0 && j
<sizeY
&& this.board
[i
][j
] == V
.EMPTY
)
62 if (i
>=0 && i
<sizeX
&& j
>=0 && j
<sizeY
&&
63 this.getColor(i
,j
) == this.getOppCol(color
) && this.getPiece(i
,j
) == asA
)
66 if (this.getPiece(x
,y
) == V
.PAWN
&& i
== lastRank
)
68 // Special case of promotion:
69 promotionPieces
.forEach(p
=> {
70 moves
.push(this.getBasicMove([x
,y
], [i
,j
], {c:color
,p:p
}));
76 moves
.push(this.getBasicMove([x
,y
], [i
,j
]));
83 // Find possible captures from a square: look in every direction!
88 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, VariantRules
.PAWN
));
89 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, VariantRules
.ROOK
));
90 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, VariantRules
.KNIGHT
));
91 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, VariantRules
.BISHOP
));
92 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, VariantRules
.QUEEN
));
97 getPotentialPawnMoves([x
,y
])
99 const color
= this.getColor(x
,y
);
101 var V
= VariantRules
;
102 let [sizeX
,sizeY
] = VariantRules
.size
;
103 let shift
= (color
== 'w' ? -1 : 1);
104 let startRank
= (color
== 'w' ? sizeY
-2 : 1);
105 let firstRank
= (color
== 'w' ? sizeY
-1 : 0);
106 let lastRank
= (color
== "w" ? 0 : sizeY
-1);
108 if (x
+shift
>= 0 && x
+shift
< sizeX
&& x
+shift
!= lastRank
)
111 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
113 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
]));
114 if ([startRank
,firstRank
].includes(x
) && this.board
[x
+2*shift
][y
] == V
.EMPTY
)
117 moves
.push(this.getBasicMove([x
,y
], [x
+2*shift
,y
]));
122 if (x
+shift
== lastRank
)
125 let promotionPieces
= [V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
126 promotionPieces
.forEach(p
=> {
128 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
129 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
], {c:color
,p:p
}));
133 // No en passant here
135 // Add "zen" captures
136 Array
.prototype.push
.apply(moves
, this.findCaptures([x
,y
]));
141 getPotentialRookMoves(sq
)
143 let noCaptures
= this.getSlideNJumpMoves(
144 sq
, VariantRules
.steps
[VariantRules
.ROOK
]);
145 let captures
= this.findCaptures(sq
);
146 return noCaptures
.concat(captures
);
149 getPotentialKnightMoves(sq
)
151 let noCaptures
= this.getSlideNJumpMoves(
152 sq
, VariantRules
.steps
[VariantRules
.KNIGHT
], "oneStep");
153 let captures
= this.findCaptures(sq
);
154 return noCaptures
.concat(captures
);
157 getPotentialBishopMoves(sq
)
159 let noCaptures
= this.getSlideNJumpMoves(
160 sq
, VariantRules
.steps
[VariantRules
.BISHOP
]);
161 let captures
= this.findCaptures(sq
);
162 return noCaptures
.concat(captures
);
165 getPotentialQueenMoves(sq
)
167 const V
= VariantRules
;
168 let noCaptures
= this.getSlideNJumpMoves(
169 sq
, V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]));
170 let captures
= this.findCaptures(sq
);
171 return noCaptures
.concat(captures
);
174 getPotentialKingMoves(sq
)
176 const V
= VariantRules
;
177 // Initialize with normal moves
178 let noCaptures
= this.getSlideNJumpMoves(sq
,
179 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]), "oneStep");
180 let captures
= this.findCaptures(sq
);
181 return noCaptures
.concat(captures
).concat(this.getCastleMoves(sq
));
186 // Recognize special moves first
187 if (move.appear
.length
== 2)
190 if (move.end
.y
< move.start
.y
)
196 // Translate initial square (because pieces may fly unusually in this variant!)
198 String
.fromCharCode(97 + move.start
.y
) + (VariantRules
.size
[0]-move.start
.x
);
200 // Translate final square
202 String
.fromCharCode(97 + move.end
.y
) + (VariantRules
.size
[0]-move.end
.x
);
205 let piece
= this.getPiece(move.start
.x
, move.start
.y
);
206 if (piece
== VariantRules
.PAWN
)
208 // pawn move (TODO: enPassant indication)
209 if (move.vanish
.length
> 1)
212 notation
= initialSquare
+ "x" + finalSquare
;
215 notation
= finalSquare
;
216 if (piece
!= move.appear
[0].p
) //promotion
217 notation
+= "=" + move.appear
[0].p
.toUpperCase();
223 notation
= piece
.toUpperCase();
224 if (move.vanish
.length
> 1)
225 notation
+= initialSquare
+ "x";
226 notation
+= finalSquare
;
231 static get VALUES() { //TODO: experimental