1 import { ChessRules
, Move
, PiPo
} from "@/base_rules";
3 export class Cannibal1Rules
extends ChessRules
{
5 static get KING_CODE() {
15 static get KING_DECODE() {
25 // Kings may be disguised:
27 const piece
= this.board
[x
][y
].charAt(1);
28 if (Object
.keys(V
.KING_DECODE
).includes(piece
))
29 return V
.KING_DECODE
[piece
];
34 return (Object
.keys(V
.KING_DECODE
).includes(b
[1]) ? "Cannibal/" : "") + b
;
37 static IsGoodPosition(position
) {
38 if (position
.length
== 0) return false;
39 const rows
= position
.split("/");
40 if (rows
.length
!= V
.size
.x
) return false;
41 let kings
= { "w": 0, "b": 0 };
42 const allPiecesCodes
= V
.PIECES
.concat(Object
.keys(V
.KING_DECODE
));
43 const kingBlackCodes
= Object
.keys(V
.KING_DECODE
).concat(['k']);
44 const kingWhiteCodes
=
45 Object
.keys(V
.KING_DECODE
).map(k
=> k
.toUpperCase()).concat(['K']);
46 for (let row
of rows
) {
48 for (let i
= 0; i
< row
.length
; i
++) {
49 if (kingBlackCodes
.includes(row
[i
])) kings
['b']++;
50 else if (kingWhiteCodes
.includes(row
[i
])) kings
['w']++;
51 if (allPiecesCodes
.includes(row
[i
].toLowerCase())) sumElts
++;
53 const num
= parseInt(row
[i
], 10);
54 if (isNaN(num
)) return false;
58 if (sumElts
!= V
.size
.y
) return false;
60 // Both kings should be on board, only one of each color:
61 if (Object
.values(kings
).some(v
=> v
!= 1)) return false;
65 // Kings may be disguised:
66 setOtherVariables(fen
) {
67 super.setOtherVariables(fen
);
68 const rows
= V
.ParseFen(fen
).position
.split("/");
69 if (this.kingPos
["w"][0] < 0 || this.kingPos
["b"][0] < 0) {
70 for (let i
= 0; i
< rows
.length
; i
++) {
71 let k
= 0; //column index on board
72 for (let j
= 0; j
< rows
[i
].length
; j
++) {
73 const piece
= rows
[i
].charAt(j
);
74 if (Object
.keys(V
.KING_DECODE
).includes(piece
.toLowerCase())) {
75 const color
= (piece
.charCodeAt(0) <= 90 ? 'w' : 'b');
76 this.kingPos
[color
] = [i
, k
];
78 const num
= parseInt(rows
[i
].charAt(j
), 10);
79 if (!isNaN(num
)) k
+= num
- 1;
87 // Because of the disguised kings, getPiece() could be wrong:
88 // use board[x][y][1] instead (always valid).
89 getBasicMove([sx
, sy
], [ex
, ey
], tr
) {
90 let mv
= super.getBasicMove([sx
, sy
], [ex
, ey
], tr
);
92 if (this.board
[ex
][ey
] != V
.EMPTY
) {
93 // If the captured piece has a different nature: take it as well
94 if (mv
.vanish
[0].p
!= mv
.vanish
[1].p
) {
96 mv
.vanish
[0].p
== V
.KING
||
97 Object
.keys(V
.KING_DECODE
).includes(mv
.vanish
[0].p
)
99 mv
.appear
[0].p
= V
.KING_CODE
[mv
.vanish
[1].p
];
101 else mv
.appear
[0].p
= mv
.vanish
[1].p
;
104 else if (!!tr
&& mv
.vanish
[0].p
!= V
.PAWN
)
105 // Special case of a non-capturing king-as-pawn promotion
106 mv
.appear
[0].p
= V
.KING_CODE
[tr
.p
];
111 getPotentialMovesFrom([x
, y
]) {
112 const piece
= this.board
[x
][y
].charAt(1);
113 if (Object
.keys(V
.KING_DECODE
).includes(piece
))
114 return super.getPotentialMovesFrom([x
, y
], V
.KING_DECODE
[piece
]);
115 return super.getPotentialMovesFrom([x
, y
], piece
);
119 const c
= V
.GetOppCol(this.turn
);
120 const piece
= move.appear
[0].p
;
121 // Update king position + flags
122 if (piece
== V
.KING
|| Object
.keys(V
.KING_DECODE
).includes(piece
)) {
123 this.kingPos
[c
][0] = move.appear
[0].x
;
124 this.kingPos
[c
][1] = move.appear
[0].y
;
125 this.castleFlags
[c
] = [V
.size
.y
, V
.size
.y
];
127 // Next call is still required because the king may eat an opponent's rook
128 // TODO: castleFlags will be turned off twice then.
129 super.updateCastleFlags(move, piece
);
133 // (Potentially) Reset king position
134 const c
= this.getColor(move.start
.x
, move.start
.y
);
135 const piece
= move.appear
[0].p
;
136 if (piece
== V
.KING
|| Object
.keys(V
.KING_DECODE
).includes(piece
))
137 this.kingPos
[c
] = [move.start
.x
, move.start
.y
];
140 static get VALUES() {
152 let notation
= super.getNotation(move);
153 const lastRank
= (move.appear
[0].c
== "w" ? 0 : 7);
155 move.end
.x
!= lastRank
&&
156 this.getPiece(move.start
.x
, move.start
.y
) == V
.PAWN
&&
157 move.vanish
.length
== 2 &&
158 move.appear
[0].p
!= V
.PAWN
160 // Fix "promotion" (transform indicator) from base_rules notation
161 notation
= notation
.slice(0, -2);