1 class WildebeestRules
extends ChessRules
5 const V
= VariantRules
;
6 return ([V
.CAMEL
,V
.WILDEBEEST
].includes(b
[1]) ? "Wildebeest/" : "") + b
;
9 static get size() { return [10,11]; }
11 static get CAMEL() { return 'c'; }
12 static get WILDEBEEST() { return 'w'; }
16 ChessRules
.steps
, //add camel moves:
17 {'c': [ [-3,-1],[-3,1],[-1,-3],[-1,3],[1,-3],[1,3],[3,-1],[3,1] ]}
21 // En-passant after 2-sq or 3-sq jumps
24 const [sx
,sy
,ex
] = [move.start
.x
,move.start
.y
,move.end
.x
];
25 if (this.getPiece(sx
,sy
) == VariantRules
.PAWN
&& Math
.abs(sx
- ex
) >= 2)
27 const step
= (ex
-sx
) / Math
.abs(ex
-sx
);
32 if (sx
+ 2*step
!= ex
) //3-squares move
41 return undefined; //default
44 getPotentialMovesFrom([x
,y
])
46 switch (this.getPiece(x
,y
))
48 case VariantRules
.CAMEL:
49 return this.getPotentialCamelMoves([x
,y
]);
50 case VariantRules
.WILDEBEEST:
51 return this.getPotentialWildebeestMoves([x
,y
]);
53 return super.getPotentialMovesFrom([x
,y
])
57 // Pawns jump 2 or 3 squares, and promote to queen or wildebeest
58 getPotentialPawnMoves([x
,y
])
60 const color
= this.turn
;
62 const V
= VariantRules
;
63 const [sizeX
,sizeY
] = VariantRules
.size
;
64 const shift
= (color
== "w" ? -1 : 1);
65 const startRanks
= (color
== "w" ? [sizeX
-2,sizeX
-3] : [1,2]);
66 const lastRank
= (color
== "w" ? 0 : sizeX
-1);
68 if (x
+shift
>= 0 && x
+shift
< sizeX
&& x
+shift
!= lastRank
)
71 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
73 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
]));
74 if (startRanks
.includes(x
) && this.board
[x
+2*shift
][y
] == V
.EMPTY
)
77 moves
.push(this.getBasicMove([x
,y
], [x
+2*shift
,y
]));
78 if (x
== startRanks
[0] && this.board
[x
+3*shift
][y
] == V
.EMPTY
)
81 moves
.push(this.getBasicMove([x
,y
], [x
+3*shift
,y
]));
86 if (y
>0 && this.canTake([x
,y
], [x
+shift
,y
-1])
87 && this.board
[x
+shift
][y
-1] != V
.EMPTY
)
89 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
-1]));
91 if (y
<sizeY
-1 && this.canTake([x
,y
], [x
+shift
,y
+1])
92 && this.board
[x
+shift
][y
+1] != V
.EMPTY
)
94 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
+1]));
98 if (x
+shift
== lastRank
)
101 let promotionPieces
= [V
.QUEEN
,V
.WILDEBEEST
];
102 promotionPieces
.forEach(p
=> {
104 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
105 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
], {c:color
,p:p
}));
107 if (y
>0 && this.canTake([x
,y
], [x
+shift
,y
-1])
108 && this.board
[x
+shift
][y
-1] != V
.EMPTY
)
110 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
-1], {c:color
,p:p
}));
112 if (y
<sizeY
-1 && this.canTake([x
,y
], [x
+shift
,y
+1])
113 && this.board
[x
+shift
][y
+1] != V
.EMPTY
)
115 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
+1], {c:color
,p:p
}));
121 const Lep
= this.epSquares
.length
;
122 const epSquare
= Lep
>0 ? this.epSquares
[Lep
-1] : undefined;
125 for (let epsq
of epSquare
)
127 // TODO: some redundant checks
128 if (epsq
.x
== x
+shift
&& Math
.abs(epsq
.y
- y
) == 1)
130 let epStep
= epsq
.y
- y
;
131 var enpassantMove
= this.getBasicMove([x
,y
], [x
+shift
,y
+epStep
]);
132 enpassantMove
.vanish
.push({
136 c: this.getColor(x
,y
+epStep
)
138 moves
.push(enpassantMove
);
146 // TODO: wildebeest castle
148 getPotentialCamelMoves(sq
)
150 return this.getSlideNJumpMoves(
151 sq
, VariantRules
.steps
[VariantRules
.CAMEL
], "oneStep");
154 getPotentialWildebeestMoves(sq
)
156 const V
= VariantRules
;
157 return this.getSlideNJumpMoves(
158 sq
, V
.steps
[V
.KNIGHT
].concat(V
.steps
[V
.CAMEL
]), "oneStep");
161 isAttacked(sq
, colors
)
163 return super.isAttacked(sq
, colors
)
164 || this.isAttackedByCamel(sq
, colors
)
165 || this.isAttackedByWildebeest(sq
, colors
);
168 isAttackedByCamel(sq
, colors
)
170 return this.isAttackedBySlideNJump(sq
, colors
,
171 VariantRules
.CAMEL
, VariantRules
.steps
[VariantRules
.CAMEL
], "oneStep");
174 isAttackedByWildebeest(sq
, colors
)
176 const V
= VariantRules
;
177 return this.isAttackedBySlideNJump(sq
, colors
, V
.WILDEBEEST
,
178 V
.steps
[V
.KNIGHT
].concat(V
.steps
[V
.CAMEL
]), "oneStep");
183 // No valid move: game is lost (stalemate is a win)
184 return this.turn
== "w" ? "0-1" : "1-0";
187 static get VALUES() {
188 return Object
.assign(
190 {'c': 3, 'w': 7} //experimental
194 static get SEARCH_DEPTH() { return 2; }
196 static GenRandInitFen()
198 let pieces
= { "w": new Array(10), "b": new Array(10) };
199 for (let c
of ["w","b"])
201 let positions
= _
.range(11);
203 // Get random squares for bishops + camels (different colors)
204 let randIndexes
= _
.sample(_
.range(6), 2).map(i
=> { return 2*i
; });
205 let bishop1Pos
= positions
[randIndexes
[0]];
206 let camel1Pos
= positions
[randIndexes
[1]];
207 // The second bishop (camel) must be on a square of different color
208 let randIndexes_tmp
= _
.sample(_
.range(5), 2).map(i
=> { return 2*i
+1; });
209 let bishop2Pos
= positions
[randIndexes_tmp
[0]];
210 let camel2Pos
= positions
[randIndexes_tmp
[1]];
211 for (let idx
of randIndexes
.concat(randIndexes_tmp
)
212 .sort((a
,b
) => { return b
-a
; })) //largest indices first
214 positions
.splice(idx
, 1);
217 let randIndex
= _
.random(6);
218 let knight1Pos
= positions
[randIndex
];
219 positions
.splice(randIndex
, 1);
220 randIndex
= _
.random(5);
221 let knight2Pos
= positions
[randIndex
];
222 positions
.splice(randIndex
, 1);
224 randIndex
= _
.random(4);
225 let queenPos
= positions
[randIndex
];
226 positions
.splice(randIndex
, 1);
228 // Random square for wildebeest
229 randIndex
= _
.random(3);
230 let wildebeestPos
= positions
[randIndex
];
231 positions
.splice(randIndex
, 1);
233 let rook1Pos
= positions
[0];
234 let kingPos
= positions
[1];
235 let rook2Pos
= positions
[2];
237 pieces
[c
][rook1Pos
] = 'r';
238 pieces
[c
][knight1Pos
] = 'n';
239 pieces
[c
][bishop1Pos
] = 'b';
240 pieces
[c
][queenPos
] = 'q';
241 pieces
[c
][camel1Pos
] = 'c';
242 pieces
[c
][camel2Pos
] = 'c';
243 pieces
[c
][wildebeestPos
] = 'w';
244 pieces
[c
][kingPos
] = 'k';
245 pieces
[c
][bishop2Pos
] = 'b';
246 pieces
[c
][knight2Pos
] = 'n';
247 pieces
[c
][rook2Pos
] = 'r';
249 let fen
= pieces
["b"].join("") +
250 "/ppppppppppp/11/11/11/11/11/11/PPPPPPPPPPP/" +
251 pieces
["w"].join("").toUpperCase() +