1 //https://www.chessvariants.com/large.dir/wildebeest.html
2 class WildebeestRules
extends ChessRules
6 const V
= VariantRules
;
7 return ([V
.CAMEL
,V
.WILDEBEEST
].includes(b
[1]) ? "Wildebeest/" : "") + b
;
10 static get size() { return [10,11]; }
12 static get CAMEL() { return 'c'; }
13 static get WILDEBEEST() { return 'w'; }
17 ChessRules
.steps
, //add camel moves:
18 {'c': [ [-3,-1],[-3,1],[-1,-3],[-1,3],[1,-3],[1,3],[3,-1],[3,1] ]}
22 // En-passant after 2-sq or 3-sq jumps
25 const [sx
,sy
,ex
] = [move.start
.x
,move.start
.y
,move.end
.x
];
26 if (this.getPiece(sx
,sy
) == VariantRules
.PAWN
&& Math
.abs(sx
- ex
) >= 2)
28 const step
= (ex
-sx
) / Math
.abs(ex
-sx
);
33 if (sx
+ 2*step
!= ex
) //3-squares move
42 return undefined; //default
45 getPotentialMovesFrom([x
,y
])
47 switch (this.getPiece(x
,y
))
49 case VariantRules
.CAMEL:
50 return this.getPotentialCamelMoves([x
,y
]);
51 case VariantRules
.WILDEBEEST:
52 return this.getPotentialWildebeestMoves([x
,y
]);
54 return super.getPotentialMovesFrom([x
,y
])
58 // Pawns jump 2 or 3 squares, and promote to queen or wildebeest
59 getPotentialPawnMoves([x
,y
])
61 const color
= this.turn
;
63 const V
= VariantRules
;
64 const [sizeX
,sizeY
] = VariantRules
.size
;
65 const shift
= (color
== "w" ? -1 : 1);
66 const startRanks
= (color
== "w" ? [sizeX
-2,sizeX
-3] : [1,2]);
67 const lastRank
= (color
== "w" ? 0 : sizeX
-1);
69 if (x
+shift
>= 0 && x
+shift
< sizeX
&& x
+shift
!= lastRank
)
72 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
74 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
]));
75 if (startRanks
.includes(x
) && this.board
[x
+2*shift
][y
] == V
.EMPTY
)
78 moves
.push(this.getBasicMove([x
,y
], [x
+2*shift
,y
]));
79 if (x
== startRanks
[0] && this.board
[x
+3*shift
][y
] == V
.EMPTY
)
82 moves
.push(this.getBasicMove([x
,y
], [x
+3*shift
,y
]));
87 if (y
>0 && this.canTake([x
,y
], [x
+shift
,y
-1]) && this.board
[x
+shift
][y
-1] != V
.EMPTY
)
88 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
-1]));
89 if (y
<sizeY
-1 && this.canTake([x
,y
], [x
+shift
,y
+1]) && this.board
[x
+shift
][y
+1] != V
.EMPTY
)
90 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
+1]));
93 if (x
+shift
== lastRank
)
96 let promotionPieces
= [V
.QUEEN
,V
.WILDEBEEST
];
97 promotionPieces
.forEach(p
=> {
99 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
100 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
], {c:color
,p:p
}));
102 if (y
>0 && this.canTake([x
,y
], [x
+shift
,y
-1]) && this.board
[x
+shift
][y
-1] != V
.EMPTY
)
103 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
-1], {c:color
,p:p
}));
104 if (y
<sizeY
-1 && this.canTake([x
,y
], [x
+shift
,y
+1]) && this.board
[x
+shift
][y
+1] != V
.EMPTY
)
105 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
+1], {c:color
,p:p
}));
110 const Lep
= this.epSquares
.length
;
111 const epSquare
= Lep
>0 ? this.epSquares
[Lep
-1] : undefined;
114 for (let epsq
of epSquare
)
116 // TODO: some redundant checks
117 if (epsq
.x
== x
+shift
&& Math
.abs(epsq
.y
- y
) == 1)
119 let epStep
= epsq
.y
- y
;
120 var enpassantMove
= this.getBasicMove([x
,y
], [x
+shift
,y
+epStep
]);
121 enpassantMove
.vanish
.push({
125 c: this.getColor(x
,y
+epStep
)
127 moves
.push(enpassantMove
);
135 // TODO: wildebeest castle
137 getPotentialCamelMoves(sq
)
139 return this.getSlideNJumpMoves(sq
, VariantRules
.steps
[VariantRules
.CAMEL
], "oneStep");
142 getPotentialWildebeestMoves(sq
)
144 const V
= VariantRules
;
145 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
].concat(V
.steps
[V
.CAMEL
]), "oneStep");
148 isAttacked(sq
, colors
)
150 return super.isAttacked(sq
, colors
)
151 || this.isAttackedByCamel(sq
, colors
)
152 || this.isAttackedByWildebeest(sq
, colors
);
155 isAttackedByCamel(sq
, colors
)
157 return this.isAttackedBySlideNJump(sq
, colors
,
158 VariantRules
.CAMEL
, VariantRules
.steps
[VariantRules
.CAMEL
], "oneStep");
161 isAttackedByWildebeest(sq
, colors
)
163 const V
= VariantRules
;
164 return this.isAttackedBySlideNJump(sq
, colors
, V
.WILDEBEEST
,
165 V
.steps
[V
.KNIGHT
].concat(V
.steps
[V
.CAMEL
]), "oneStep");
170 // No valid move: game is lost (stalemate is a win)
171 return this.turn
== "w" ? "0-1" : "1-0";
174 static get VALUES() {
175 return Object
.assign(
177 {'c': 3, 'w': 7} //experimental
181 static get SEARCH_DEPTH() { return 2; }
183 static GenRandInitFen()
185 let pieces
= [new Array(10), new Array(10)];
186 // Shuffle pieces on first and last rank
187 for (let c
= 0; c
<= 1; c
++)
189 let positions
= _
.range(11);
191 // Get random squares for bishops
192 let randIndex
= 2 * _
.random(5);
193 let bishop1Pos
= positions
[randIndex
];
194 // The second bishop must be on a square of different color
195 let randIndex_tmp
= 2 * _
.random(4) + 1;
196 let bishop2Pos
= positions
[randIndex_tmp
];
197 // Remove chosen squares
198 positions
.splice(Math
.max(randIndex
,randIndex_tmp
), 1);
199 positions
.splice(Math
.min(randIndex
,randIndex_tmp
), 1);
201 // Get random squares for knights
202 randIndex
= _
.random(8);
203 let knight1Pos
= positions
[randIndex
];
204 positions
.splice(randIndex
, 1);
205 randIndex
= _
.random(7);
206 let knight2Pos
= positions
[randIndex
];
207 positions
.splice(randIndex
, 1);
209 // Get random square for queen
210 randIndex
= _
.random(6);
211 let queenPos
= positions
[randIndex
];
212 positions
.splice(randIndex
, 1);
214 // ...random square for camels
215 randIndex
= _
.random(5);
216 let camel1Pos
= positions
[randIndex
];
217 positions
.splice(randIndex
, 1);
218 randIndex
= _
.random(4);
219 let camel2Pos
= positions
[randIndex
];
220 positions
.splice(randIndex
, 1);
222 // ...random square for wildebeest
223 randIndex
= _
.random(3);
224 let wildebeestPos
= positions
[randIndex
];
225 positions
.splice(randIndex
, 1);
227 // Rooks and king positions are now fixed, because of the ordering rook-king-rook
228 let rook1Pos
= positions
[0];
229 let kingPos
= positions
[1];
230 let rook2Pos
= positions
[2];
232 // Finally put the shuffled pieces in the board array
233 pieces
[c
][rook1Pos
] = 'r';
234 pieces
[c
][knight1Pos
] = 'n';
235 pieces
[c
][bishop1Pos
] = 'b';
236 pieces
[c
][queenPos
] = 'q';
237 pieces
[c
][camel1Pos
] = 'c';
238 pieces
[c
][camel2Pos
] = 'c';
239 pieces
[c
][wildebeestPos
] = 'w';
240 pieces
[c
][kingPos
] = 'k';
241 pieces
[c
][bishop2Pos
] = 'b';
242 pieces
[c
][knight2Pos
] = 'n';
243 pieces
[c
][rook2Pos
] = 'r';
245 let fen
= pieces
[0].join("") +
246 "/ppppppppppp/11/11/11/11/11/11/PPPPPPPPPPP/" +
247 pieces
[1].join("").toUpperCase() +