1 //https://www.chessvariants.com/large.dir/wildebeest.html
2 class GrandRules
extends ChessRules
6 const V
= VariantRules
;
7 return ([V
.CAMEL
,V
.WILDEBEEST
].includes(b
[1]) ? "Wildebeest/" : "") + b
;
10 static get CAMEL() { return 'c'; }
11 static get WILDEBEEST() { return 'w'; }
15 ChessRules
.steps
, //add camel moves:
16 {'c': [ [-3,-1],[-3,1],[-1,-3],[-1,3],[1,-3],[1,3],[3,-1],[3,1] ]}
20 // TODO: IN epSquares (return array), not return singleton. Easy. Adapt
21 // just here for now...
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)
32 return undefined; //default
35 getPotentialMovesFrom([x
,y
])
37 switch (this.getPiece(x
,y
))
39 case VariantRules
.CAMEL:
40 return this.getPotentialCamelMoves([x
,y
]);
41 case VariantRules
.WILDEBEEST:
42 return this.getPotentialWildebeestMoves([x
,y
]);
44 return super.getPotentialMovesFrom([x
,y
])
48 // TODO: several changes (promote to queen or wildebeest)
49 getPotentialPawnMoves([x
,y
])
51 const color
= this.turn
;
53 const V
= VariantRules
;
54 const [sizeX
,sizeY
] = VariantRules
.size
;
55 const shift
= (color
== "w" ? -1 : 1);
56 const firstRank
= (color
== 'w' ? sizeY
-1 : 0);
57 const startRank
= (color
== "w" ? sizeY
-2 : 1);
58 const lastRank
= (color
== "w" ? 0 : sizeY
-1);
60 if (x
+shift
>= 0 && x
+shift
< sizeX
&& x
+shift
!= lastRank
)
63 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
65 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
]));
66 // Next condition because variants with pawns on 1st rank generally allow them to jump
67 if ([startRank
,firstRank
].includes(x
) && this.board
[x
+2*shift
][y
] == V
.EMPTY
)
70 moves
.push(this.getBasicMove([x
,y
], [x
+2*shift
,y
]));
74 if (y
>0 && this.canTake([x
,y
], [x
+shift
,y
-1]) && this.board
[x
+shift
][y
-1] != V
.EMPTY
)
75 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
-1]));
76 if (y
<sizeY
-1 && this.canTake([x
,y
], [x
+shift
,y
+1]) && this.board
[x
+shift
][y
+1] != V
.EMPTY
)
77 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
+1]));
80 if (x
+shift
== lastRank
)
83 let promotionPieces
= [V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
84 promotionPieces
.forEach(p
=> {
86 if (this.board
[x
+shift
][y
] == V
.EMPTY
)
87 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
], {c:color
,p:p
}));
89 if (y
>0 && 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], {c:color
,p:p
}));
91 if (y
<sizeY
-1 && this.canTake([x
,y
], [x
+shift
,y
+1]) && this.board
[x
+shift
][y
+1] != V
.EMPTY
)
92 moves
.push(this.getBasicMove([x
,y
], [x
+shift
,y
+1], {c:color
,p:p
}));
97 const Lep
= this.epSquares
.length
;
98 const epSquare
= Lep
>0 ? this.epSquares
[Lep
-1] : undefined;
99 if (!!epSquare
&& epSquare
.x
== x
+shift
&& Math
.abs(epSquare
.y
- y
) == 1)
101 let epStep
= epSquare
.y
- y
;
102 var enpassantMove
= this.getBasicMove([x
,y
], [x
+shift
,y
+epStep
]);
103 enpassantMove
.vanish
.push({
107 c: this.getColor(x
,y
+epStep
)
109 moves
.push(enpassantMove
);
115 getPotentialCamelMoves(sq
)
117 return this.getSlideNJumpMoves(sq
, VariantRules
.steps
[VariantRules
.CAMEL
], "oneStep");
120 getPotentialWildebeestMoves(sq
)
122 const V
= VariantRules
;
123 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
].concat(V
.steps
[V
.CAMEL
]));
126 // TODO: getCastleMoves, generalize a bit to include castleSquares as static variables
127 // ==> but this won't be exactly Wildebeest... think about it.
129 // TODO: also generalize lastRank ==> DO NOT HARDCODE 7 !!!
131 isAttacked(sq
, colors
)
133 return (super.isAttacked(sq
, colors
)
134 || this.isAttackedByCamel(sq
, colors
)
135 || this.isAttackedByWildebeest(sq
, colors
);
138 isAttackedByCamel(sq
, colors
)
140 return this.isAttackedBySlideNJump(sq
, colors
,
141 VariantRules
.CAMEL
, VariantRules
.steps
[VariantRules
.CAMEL
]);
144 isAttackedByWildebeest(sq
, colors
)
146 const V
= VariantRules
;
147 return this.isAttackedBySlideNJump(sq
, colors
, V
.WILDEBEEST
,
148 V
.steps
[V
.KNIGHT
].concat(V
.steps
[V
.CAMEL
]));
151 static get VALUES() {
152 return Object
.assign(
154 {'c': 3, 'w': 7} //experimental
159 static GenRandInitFen()
161 let pieces
= [new Array(8), new Array(8)];
162 // Shuffle pieces on first and last rank
163 for (let c
= 0; c
<= 1; c
++)
165 let positions
= _
.range(8);
167 // Get random squares for bishops
168 let randIndex
= 2 * _
.random(3);
169 let bishop1Pos
= positions
[randIndex
];
170 // The second bishop must be on a square of different color
171 let randIndex_tmp
= 2 * _
.random(3) + 1;
172 let bishop2Pos
= positions
[randIndex_tmp
];
173 // Remove chosen squares
174 positions
.splice(Math
.max(randIndex
,randIndex_tmp
), 1);
175 positions
.splice(Math
.min(randIndex
,randIndex_tmp
), 1);
177 // Get random squares for knights
178 randIndex
= _
.random(5);
179 let knight1Pos
= positions
[randIndex
];
180 positions
.splice(randIndex
, 1);
181 randIndex
= _
.random(4);
182 let knight2Pos
= positions
[randIndex
];
183 positions
.splice(randIndex
, 1);
185 // Get random square for queen
186 randIndex
= _
.random(3);
187 let queenPos
= positions
[randIndex
];
188 positions
.splice(randIndex
, 1);
190 // Rooks and king positions are now fixed, because of the ordering rook-king-rook
191 let rook1Pos
= positions
[0];
192 let kingPos
= positions
[1];
193 let rook2Pos
= positions
[2];
195 // Finally put the shuffled pieces in the board array
196 pieces
[c
][rook1Pos
] = 'r';
197 pieces
[c
][knight1Pos
] = 'n';
198 pieces
[c
][bishop1Pos
] = 'b';
199 pieces
[c
][queenPos
] = 'q';
200 pieces
[c
][kingPos
] = 'k';
201 pieces
[c
][bishop2Pos
] = 'b';
202 pieces
[c
][knight2Pos
] = 'n';
203 pieces
[c
][rook2Pos
] = 'r';
205 let fen
= pieces
[0].join("") +
206 "/pppppppp/8/8/8/8/PPPPPPPP/" +
207 pieces
[1].join("").toUpperCase() +