Add Forward + Doubleorda variants
[vchess.git] / client / src / variants / Bicolour.js
1 import { ChessRules } from "@/base_rules";
2 import { randInt } from "@/utils/alea";
3 import { ArrayFun } from "@/utils/array";
4
5 export class BicolourRules extends ChessRules {
6 static get HasFlags() {
7 return false;
8 }
9
10 canTake([x1, y1], [x2, y2]) {
11 return (
12 this.getPiece(x1, y1) == V.KING || super.canTake([x1, y1], [x2, y2])
13 );
14 }
15
16 static GenRandInitFen(randomness) {
17 if (randomness == 0)
18 return "rqbnkbnr/pppppppp/8/8/8/8/PPPPPPPP/RQBNKBNR w 0 -";
19
20 // Place pieces at random but the king cannot be next to a rook or queen.
21 // => One bishop and one knight should surround the king.
22 let pieces = { w: new Array(8), b: new Array(8) };
23 let flags = "";
24 for (let c of ["w", "b"]) {
25 if (c == 'b' && randomness == 1) {
26 pieces['b'] = pieces['w'];
27 break;
28 }
29
30 let positions = ArrayFun.range(8);
31
32 const kingPos = randInt(8);
33 let toRemove = [kingPos];
34 let knight1Pos = undefined;
35 let bishop1Pos = undefined;
36 if (kingPos == 0) {
37 if (Math.random() < 0.5) knight1Pos = 1;
38 else bishop1Pos = 1;
39 toRemove.push(1);
40 }
41 else if (kingPos == V.size.y - 1) {
42 if (Math.random() < 0.5) knight1Pos = V.size.y - 2;
43 else bishop1Pos = V.size.y - 2;
44 toRemove.push(V.size.y - 2);
45 }
46 else {
47 knight1Pos = kingPos + (Math.random() < 0.5 ? 1 : -1);
48 bishop1Pos = kingPos + (knight1Pos < kingPos ? 1 : -1);
49 toRemove.push(knight1Pos, bishop1Pos);
50 }
51 const firstPieces = [kingPos, knight1Pos, bishop1Pos]
52 .filter(elt => elt !== undefined);
53 firstPieces
54 .sort((a, b) => b - a)
55 .forEach(elt => positions.splice(elt, 1));
56
57 let randIndex = undefined;
58 if (bishop1Pos === undefined) {
59 const posWithIdx = positions.map((e,i) => { return { e: e, i: i }; });
60 let availableSquares = posWithIdx.filter(p => p.e % 2 == 0);
61 randIndex = randInt(availableSquares.length);
62 bishop1Pos = availableSquares[randIndex].e;
63 positions.splice(availableSquares[randIndex].i, 1);
64 }
65 const posWithIdx = positions.map((e,i) => { return { e: e, i: i }; });
66 const rem1B = bishop1Pos % 2;
67 let availableSquares = posWithIdx.filter(p => p.e % 2 == 1 - rem1B);
68 randIndex = randInt(availableSquares.length);
69 const bishop2Pos = availableSquares[randIndex].e;
70 positions.splice(availableSquares[randIndex].i, 1);
71
72 if (knight1Pos === undefined) {
73 randIndex = randInt(5);
74 knight1Pos = positions[randIndex];
75 positions.splice(randIndex, 1);
76 }
77 randIndex = randInt(4);
78 const knight2Pos = positions[randIndex];
79 positions.splice(randIndex, 1);
80
81 randIndex = randInt(3);
82 const queenPos = positions[randIndex];
83 positions.splice(randIndex, 1);
84
85 const rook1Pos = positions[0];
86 const rook2Pos = positions[1];
87
88 pieces[c][rook1Pos] = "r";
89 pieces[c][knight1Pos] = "n";
90 pieces[c][bishop1Pos] = "b";
91 pieces[c][queenPos] = "q";
92 pieces[c][kingPos] = "k";
93 pieces[c][bishop2Pos] = "b";
94 pieces[c][knight2Pos] = "n";
95 pieces[c][rook2Pos] = "r";
96 }
97 return (
98 pieces["b"].join("") +
99 "/pppppppp/8/8/8/8/PPPPPPPP/" +
100 pieces["w"].join("").toUpperCase() +
101 " w 0 -"
102 );
103 }
104
105 underCheck(color) {
106 return (
107 this.isAttacked(this.kingPos[color], 'w') ||
108 this.isAttacked(this.kingPos[color], 'b')
109 );
110 }
111 };