1 import { ChessRules
} from "@/base_rules";
3 export const VariantRules
= class ZenRules
extends ChessRules
5 // NOTE: enPassant, if enabled, would need to redefine carefully getEpSquare
6 static get HasEnpassant() { return false; }
8 // TODO(?): some duplicated code in 2 next functions
9 getSlideNJumpMoves([x
,y
], steps
, oneStep
)
11 const color
= this.getColor(x
,y
);
14 for (let loop
=0; loop
<steps
.length
; loop
++)
16 const step
= steps
[loop
];
19 while (V
.OnBoard(i
,j
) && this.board
[i
][j
] == V
.EMPTY
)
21 moves
.push(this.getBasicMove([x
,y
], [i
,j
]));
27 // No capture check: handled elsewhere (next method)
32 // follow steps from x,y until something is met.
33 // if met piece is opponent and same movement (asA): eat it!
34 findCaptures_aux([x
,y
], asA
)
36 const color
= this.getColor(x
,y
);
38 const steps
= asA
!= V
.PAWN
39 ? (asA
==V
.QUEEN
? V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]) : V
.steps
[asA
])
40 : color
=='w' ? [[-1,-1],[-1,1]] : [[1,-1],[1,1]];
41 const oneStep
= (asA
==V
.KNIGHT
|| asA
==V
.PAWN
); //we don't capture king
42 const lastRank
= (color
== 'w' ? 0 : V
.size
.x
-1);
43 const promotionPieces
= [V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
45 for (let loop
=0; loop
<steps
.length
; loop
++)
47 const step
= steps
[loop
];
50 while (V
.OnBoard(i
,j
) && this.board
[i
][j
] == V
.EMPTY
)
57 if (V
.OnBoard(i
,j
) && this.getColor(i
,j
) == V
.GetOppCol(color
)
58 && this.getPiece(i
,j
) == asA
)
61 if (this.getPiece(x
,y
) == V
.PAWN
&& i
== lastRank
)
63 // Special case of promotion:
64 promotionPieces
.forEach(p
=> {
65 moves
.push(this.getBasicMove([x
,y
], [i
,j
], {c:color
,p:p
}));
71 moves
.push(this.getBasicMove([x
,y
], [i
,j
]));
78 // Find possible captures from a square: look in every direction!
83 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.PAWN
));
84 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.ROOK
));
85 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.KNIGHT
));
86 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.BISHOP
));
87 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.QUEEN
));
92 getPotentialPawnMoves([x
,y
])
94 const color
= this.getColor(x
,y
);
96 const [sizeX
,sizeY
] = [V
.size
.x
,V
.size
.y
];
97 const shift
= (color
== 'w' ? -1 : 1);
98 const startRank
= (color
== 'w' ? sizeY
-2 : 1);
99 const firstRank
= (color
== 'w' ? sizeY
-1 : 0);
100 const lastRank
= (color
== "w" ? 0 : sizeY
-1);
102 if (x
+shift
!= lastRank
)
105 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
107 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
]));
108 if ([startRank
,firstRank
].includes(x
) && this.board
[x
+2*shift
][y
] == V
.EMPTY
)
111 moves
.push(this.getBasicMove([x
,y
], [x
+2*shift
,y
]));
118 let promotionPieces
= [V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
119 promotionPieces
.forEach(p
=> {
121 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
122 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
], {c:color
,p:p
}));
126 // No en passant here
128 // Add "zen" captures
129 Array
.prototype.push
.apply(moves
, this.findCaptures([x
,y
]));
134 getPotentialRookMoves(sq
)
136 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
]);
137 let captures
= this.findCaptures(sq
);
138 return noCaptures
.concat(captures
);
141 getPotentialKnightMoves(sq
)
143 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep");
144 let captures
= this.findCaptures(sq
);
145 return noCaptures
.concat(captures
);
148 getPotentialBishopMoves(sq
)
150 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]);
151 let captures
= this.findCaptures(sq
);
152 return noCaptures
.concat(captures
);
155 getPotentialQueenMoves(sq
)
157 let noCaptures
= this.getSlideNJumpMoves(
158 sq
, V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]));
159 let captures
= this.findCaptures(sq
);
160 return noCaptures
.concat(captures
);
163 getPotentialKingMoves(sq
)
165 // Initialize with normal moves
166 let noCaptures
= this.getSlideNJumpMoves(sq
,
167 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]), "oneStep");
168 let captures
= this.findCaptures(sq
);
169 return noCaptures
.concat(captures
).concat(this.getCastleMoves(sq
));
174 // Recognize special moves first
175 if (move.appear
.length
== 2)
178 if (move.end
.y
< move.start
.y
)
184 // Translate initial square (because pieces may fly unusually in this variant!)
185 const initialSquare
= V
.CoordsToSquare(move.start
);
187 // Translate final square
188 const finalSquare
= V
.CoordsToSquare(move.end
);
191 const piece
= this.getPiece(move.start
.x
, move.start
.y
);
194 // pawn move (TODO: enPassant indication)
195 if (move.vanish
.length
> 1)
198 notation
= initialSquare
+ "x" + finalSquare
;
201 notation
= finalSquare
;
202 if (piece
!= move.appear
[0].p
) //promotion
203 notation
+= "=" + move.appear
[0].p
.toUpperCase();
209 notation
= piece
.toUpperCase();
210 if (move.vanish
.length
> 1)
211 notation
+= initialSquare
+ "x";
212 notation
+= finalSquare
;
219 // TODO: experimental