Fix Sittuyin promotions notation
[vchess.git] / client / src / variants / Twokings.js
1 import { ChessRules } from "@/base_rules";
2 import { CoregalRules } from "@/variants/Coregal";
3
4 export class TwokingsRules extends CoregalRules {
5 static get PawnSpecs() {
6 return Object.assign(
7 {},
8 ChessRules.PawnSpecs,
9 { promotions: ChessRules.PawnSpecs.promotions.concat([V.KING]) }
10 );
11 }
12
13 static IsGoodPosition(position) {
14 if (position.length == 0) return false;
15 const rows = position.split("/");
16 if (rows.length != V.size.x) return false;
17 let kings = { "w": 0, "b": 0 };
18 for (let row of rows) {
19 let sumElts = 0;
20 for (let i = 0; i < row.length; i++) {
21 if (['K','k'].includes(row[i])) kings[row[i]]++;
22 if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
23 else {
24 const num = parseInt(row[i]);
25 if (isNaN(num)) return false;
26 sumElts += num;
27 }
28 }
29 if (sumElts != V.size.y) return false;
30 }
31 // Two kings (at least) per side should be present:
32 if (Object.values(kings).some(v => v < 2)) return false;
33 return true;
34 }
35
36 // Not scanning king positions. In this variant, scan the board everytime.
37 scanKings() {}
38
39 getCheckSquares() {
40 const color = this.turn;
41 let squares = [];
42 const oppCol = V.GetOppCol(color);
43 for (let i=0; i<V.size.x; i++) {
44 for (let j=0; j<V.size.y; j++) {
45 if (
46 this.getColor(i, j) == color &&
47 this.getPiece(i, j) == V.KING &&
48 this.isAttacked([i, j], oppCol)
49 ) {
50 squares.push([i, j]);
51 }
52 }
53 }
54 return squares;
55 }
56
57 static GenRandInitFen(randomness) {
58 if (randomness == 0)
59 return "rnqkkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNQKKBNR w 0 adehadeh -";
60
61 const replaceBishop = (fen, first, ch1, ch2) => {
62 // Remove and re-add final part:
63 const suffix = fen.substr(-15);
64 fen = fen.slice(0, -15);
65 if (first) fen = fen.replace(ch1, ch2);
66 else {
67 fen =
68 fen.split("").reverse().join("")
69 .replace(ch1, ch2)
70 .split("").reverse().join("")
71 }
72 return fen + suffix;
73 };
74
75 const sameIndexReplace = (fen) => {
76 const first = (Math.random() < 0.5);
77 return replaceBishop(
78 replaceBishop(fen, first, 'B', 'Q'),
79 first,
80 'b',
81 'q'
82 );
83 };
84
85 const fen =
86 CoregalRules.GenRandInitFen(randomness)
87 .replace("q", "k").replace("Q", "K");
88 // Now replace a bishop by the queen,
89 // so that bishops are of different colors:
90 if (randomness == 1) return sameIndexReplace(fen);
91 const wOdd = fen.indexOf('B') % 2;
92 const bOdd = fen.indexOf('b') % 2;
93 // Since there are 7 slashes, different oddities means symmetric
94 if (wOdd != bOdd) return sameIndexReplace(fen);
95 const wFirst = (Math.random() < 0.5);
96 return replaceBishop(
97 replaceBishop(fen, wFirst, 'B', 'Q'),
98 !wFirst,
99 'b',
100 'q'
101 );
102 }
103
104 underCheck(color) {
105 const oppCol = V.GetOppCol(color);
106 for (let i=0; i<V.size.x; i++) {
107 for (let j=0; j<V.size.y; j++) {
108 if (
109 this.getColor(i, j) == color &&
110 this.getPiece(i, j) == V.KING &&
111 this.isAttacked([i, j], oppCol)
112 ) {
113 return true;
114 }
115 }
116 }
117 return false;
118 }
119
120 postPlay(move) {
121 const piece = move.vanish[0].p;
122 super.updateCastleFlags(move, piece, "twoKings");
123 }
124
125 postUndo() {}
126 };