1 import { ChessRules
} from "@/base_rules";
3 export const VariantRules
= class ZenRules
extends ChessRules
{
4 // NOTE: enPassant, if enabled, would need to redefine carefully getEpSquare
5 static get HasEnpassant() {
9 // TODO(?): some duplicated code in 2 next functions
10 getSlideNJumpMoves([x
, y
], steps
, oneStep
) {
12 outerLoop: for (let loop
= 0; loop
< steps
.length
; loop
++) {
13 const step
= steps
[loop
];
16 while (V
.OnBoard(i
, j
) && this.board
[i
][j
] == V
.EMPTY
) {
17 moves
.push(this.getBasicMove([x
, y
], [i
, j
]));
18 if (oneStep
) continue outerLoop
;
22 // No capture check: handled elsewhere (next method)
27 // follow steps from x,y until something is met.
28 // if met piece is opponent and same movement (asA): eat it!
29 findCaptures_aux([x
, y
], asA
) {
30 const color
= this.getColor(x
, y
);
35 ? V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
])
46 const oneStep
= [V
.KNIGHT
,V
.PAWN
].includes(asA
); //we don't capture king
47 const lastRank
= color
== "w" ? 0 : V
.size
.x
- 1;
48 const promotionPieces
= [V
.ROOK
, V
.KNIGHT
, V
.BISHOP
, V
.QUEEN
];
49 outerLoop: for (let loop
= 0; loop
< steps
.length
; loop
++) {
50 const step
= steps
[loop
];
53 while (V
.OnBoard(i
, j
) && this.board
[i
][j
] == V
.EMPTY
) {
54 if (oneStep
) continue outerLoop
;
60 this.getColor(i
, j
) == V
.GetOppCol(color
) &&
61 this.getPiece(i
, j
) == asA
64 if (this.getPiece(x
, y
) == V
.PAWN
&& i
== lastRank
) {
65 // Special case of promotion:
66 promotionPieces
.forEach(p
=> {
67 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!
82 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.PAWN
));
83 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.ROOK
));
84 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.KNIGHT
));
85 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.BISHOP
));
86 Array
.prototype.push
.apply(moves
, this.findCaptures_aux(sq
, V
.QUEEN
));
91 getPotentialPawnMoves([x
, y
]) {
92 const color
= this.getColor(x
, y
);
94 const sizeY
= V
.size
.y
;
95 const shift
= color
== "w" ? -1 : 1;
96 const startRank
= color
== "w" ? sizeY
- 2 : 1;
97 const firstRank
= color
== "w" ? sizeY
- 1 : 0;
98 const lastRank
= color
== "w" ? 0 : sizeY
- 1;
100 if (x
+ shift
!= lastRank
) {
102 if (this.board
[x
+ shift
][y
] == V
.EMPTY
) {
103 moves
.push(this.getBasicMove([x
, y
], [x
+ shift
, y
]));
105 [startRank
, firstRank
].includes(x
) &&
106 this.board
[x
+ 2 * shift
][y
] == V
.EMPTY
109 moves
.push(this.getBasicMove([x
, y
], [x
+ 2 * shift
, y
]));
115 let promotionPieces
= [V
.ROOK
, V
.KNIGHT
, V
.BISHOP
, V
.QUEEN
];
116 promotionPieces
.forEach(p
=> {
118 if (this.board
[x
+ shift
][y
] == V
.EMPTY
)
120 this.getBasicMove([x
, y
], [x
+ shift
, y
], { c: color
, p: p
})
125 // No en passant here
127 // Add "zen" captures
128 Array
.prototype.push
.apply(moves
, this.findCaptures([x
, y
]));
133 getPotentialRookMoves(sq
) {
134 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
]);
135 let captures
= this.findCaptures(sq
);
136 return noCaptures
.concat(captures
);
139 getPotentialKnightMoves(sq
) {
140 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep");
141 let captures
= this.findCaptures(sq
);
142 return noCaptures
.concat(captures
);
145 getPotentialBishopMoves(sq
) {
146 let noCaptures
= this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]);
147 let captures
= this.findCaptures(sq
);
148 return noCaptures
.concat(captures
);
151 getPotentialQueenMoves(sq
) {
152 let noCaptures
= this.getSlideNJumpMoves(
154 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
])
156 let captures
= this.findCaptures(sq
);
157 return noCaptures
.concat(captures
);
160 getPotentialKingMoves(sq
) {
161 // Initialize with normal moves
162 let noCaptures
= this.getSlideNJumpMoves(
164 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]),
167 let captures
= this.findCaptures(sq
);
168 return noCaptures
.concat(captures
).concat(this.getCastleMoves(sq
));
172 // Recognize special moves first
173 if (move.appear
.length
== 2) {
175 if (move.end
.y
< move.start
.y
) return "0-0-0";
179 // Translate initial square (because pieces may fly unusually in this variant!)
180 const initialSquare
= V
.CoordsToSquare(move.start
);
182 // Translate final square
183 const finalSquare
= V
.CoordsToSquare(move.end
);
186 const piece
= this.getPiece(move.start
.x
, move.start
.y
);
187 if (piece
== V
.PAWN
) {
188 // pawn move (TODO: enPassant indication)
189 if (move.vanish
.length
> 1) {
191 notation
= initialSquare
+ "x" + finalSquare
;
193 else notation
= finalSquare
;
194 if (piece
!= move.appear
[0].p
)
196 notation
+= "=" + move.appear
[0].p
.toUpperCase();
199 notation
= piece
.toUpperCase();
200 if (move.vanish
.length
> 1) notation
+= initialSquare
+ "x";
201 notation
+= finalSquare
;
206 static get VALUES() {