Draft Hiddenqueen, Grasshopper and Knightmate chess (rules unwritten)
[vchess.git] / client / src / variants / Knightmate.js
1 import { ChessRules } from "@/base_rules";
2 import { ArrayFun } from "@/utils/array";
3 import { randInt } from "@/utils/alea";
4
5 export const VariantRules = class KnightmateRules extends ChessRules {
6 static get COMMONER() {
7 return "c";
8 }
9
10 static get PIECES() {
11 return ChessRules.PIECES.concat([V.COMMONER]);
12 }
13
14 getPpath(b) {
15 return ([V.KING, V.COMMONER].includes(b[1]) ? "Knightmate/" : "") + b;
16 }
17
18 static GenRandInitFen() {
19 let pieces = { w: new Array(8), b: new Array(8) };
20 // Shuffle pieces on first and last rank
21 for (let c of ["w", "b"]) {
22 let positions = ArrayFun.range(8);
23
24 // Get random squares for bishops
25 let randIndex = 2 * randInt(4);
26 const bishop1Pos = positions[randIndex];
27 let randIndex_tmp = 2 * randInt(4) + 1;
28 const bishop2Pos = positions[randIndex_tmp];
29 positions.splice(Math.max(randIndex, randIndex_tmp), 1);
30 positions.splice(Math.min(randIndex, randIndex_tmp), 1);
31
32 // Get random squares for commoners
33 randIndex = randInt(6);
34 const commoner1Pos = positions[randIndex];
35 positions.splice(randIndex, 1);
36 randIndex = randInt(5);
37 const commoner2Pos = positions[randIndex];
38 positions.splice(randIndex, 1);
39
40 // Get random square for queen
41 randIndex = randInt(4);
42 const queenPos = positions[randIndex];
43 positions.splice(randIndex, 1);
44
45 // Rooks and king positions are now fixed,
46 // because of the ordering rook-king-rook
47 const rook1Pos = positions[0];
48 const kingPos = positions[1];
49 const rook2Pos = positions[2];
50
51 // Finally put the shuffled pieces in the board array
52 pieces[c][rook1Pos] = "r";
53 pieces[c][commoner1Pos] = "c";
54 pieces[c][bishop1Pos] = "b";
55 pieces[c][queenPos] = "q";
56 pieces[c][kingPos] = "k";
57 pieces[c][bishop2Pos] = "b";
58 pieces[c][commoner2Pos] = "c";
59 pieces[c][rook2Pos] = "r";
60 }
61 // Add turn + flags + enpassant
62 return (
63 pieces["b"].join("") +
64 "/pppppppp/8/8/8/8/PPPPPPPP/" +
65 pieces["w"].join("").toUpperCase() +
66 " w 0 1111 -"
67 );
68 }
69
70 getPotentialMovesFrom([x, y]) {
71 switch (this.getPiece(x, y)) {
72 case V.COMMONER:
73 return this.getPotentialCommonerMoves([x, y]);
74 default:
75 return super.getPotentialMovesFrom([x, y]);
76 }
77 }
78
79 getPotentialCommonerMoves(sq) {
80 return this.getSlideNJumpMoves(
81 sq,
82 V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
83 "oneStep"
84 );
85 }
86
87 getPotentialKingMoves(sq) {
88 return super.getPotentialKnightMoves(sq).concat(super.getCastleMoves(sq));
89 }
90
91 isAttacked(sq, colors) {
92 return (
93 this.isAttackedByCommoner(sq, colors) ||
94 this.isAttackedByPawn(sq, colors) ||
95 this.isAttackedByRook(sq, colors) ||
96 this.isAttackedByBishop(sq, colors) ||
97 this.isAttackedByQueen(sq, colors) ||
98 this.isAttackedByKing(sq, colors)
99 );
100 }
101
102 isAttackedByKing(sq, colors) {
103 return this.isAttackedBySlideNJump(
104 sq,
105 colors,
106 V.KING,
107 V.steps[V.KNIGHT],
108 "oneStep"
109 );
110 }
111
112 isAttackedByCommoner(sq, colors) {
113 return this.isAttackedBySlideNJump(
114 sq,
115 colors,
116 V.COMMONER,
117 V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
118 "oneStep"
119 );
120 }
121
122 static get VALUES() {
123 return {
124 p: 1,
125 r: 5,
126 c: 5, //the commoner is valuable
127 b: 3,
128 q: 9,
129 k: 1000
130 };
131 }
132 };