+ static ParseFen(fen) {
+ let res = ChessRules.ParseFen(fen);
+ const fenParts = fen.split(" ");
+ res.stunned = fenParts[4];
+ return res;
+ }
+
+ static IsGoodFen(fen) {
+ if (!ChessRules.IsGoodFen(fen)) return false;
+ const fenParsed = V.ParseFen(fen);
+ // 5) Check "stunned"
+ if (
+ !fenParsed.stunned ||
+ (
+ fenParsed.stunned != "-" &&
+ !fenParsed.stunned.match(/^([a-h][1-8][1-4],?)*$/)
+ )
+ ) {
+ return false;
+ }
+ return true;
+ }
+
+ getPpath(b) {
+ return (V.STUNNED.includes(b[1]) ? "Koopa/" : "") + b;
+ }
+
+ getFen() {
+ return super.getFen() + " " + this.getStunnedFen();
+ }
+
+ getFenForRepeat() {
+ return super.getFenForRepeat() + "_" + this.getStunnedFen();
+ }
+
+ getStunnedFen() {
+ return (
+ Object.keys(this.stunned)
+ .map(square => square + this.stunned[square])
+ .join(",")
+ );
+ }
+
+ // Base GenRandInitFen() is fine because en-passant indicator will
+ // stand for stunned indicator.
+
+ scanKings(fen) {
+ this.INIT_COL_KING = { w: -1, b: -1 };
+ // Squares of white and black king:
+ this.kingPos = { w: [-1, -1], b: [-1, -1] };
+ const fenRows = V.ParseFen(fen).position.split("/");
+ const startRow = { 'w': V.size.x - 1, 'b': 0 };
+ for (let i = 0; i < fenRows.length; i++) {
+ let k = 0; //column index on board
+ for (let j = 0; j < fenRows[i].length; j++) {
+ switch (fenRows[i].charAt(j)) {
+ case "k":
+ case "l":
+ this.kingPos["b"] = [i, k];
+ this.INIT_COL_KING["b"] = k;
+ break;
+ case "K":
+ case "L":
+ this.kingPos["w"] = [i, k];
+ this.INIT_COL_KING["w"] = k;
+ break;
+ default: {
+ const num = parseInt(fenRows[i].charAt(j));
+ if (!isNaN(num)) k += num - 1;
+ }
+ }
+ k++;
+ }
+ }
+ }
+
+ setOtherVariables(fen) {
+ super.setOtherVariables(fen);
+ let stunnedArray = [];
+ const stunnedFen = V.ParseFen(fen).stunned;
+ if (stunnedFen != "-") {
+ stunnedArray =
+ stunnedFen
+ .split(",")
+ .map(s => {
+ return {
+ square: s.substr(0, 2),
+ state: parseInt(s[2])
+ };
+ });
+ }
+ this.stunned = {};
+ stunnedArray.forEach(s => {
+ this.stunned[s.square] = s.state;
+ });