Add Forward + Doubleorda variants
[vchess.git] / client / src / variants / Grasshopper.js
CommitLineData
a97bdbda
BA
1import { ChessRules } from "@/base_rules";
2import { ArrayFun } from "@/utils/array";
3import { randInt } from "@/utils/alea";
4
32f6285e 5export class GrasshopperRules extends ChessRules {
b627d118
BA
6 static get HasEnpassant() {
7 return false;
8 }
9
32f6285e
BA
10 static get PawnSpecs() {
11 return Object.assign(
12 {},
13 ChessRules.PawnSpecs,
1c15969e 14 { promotions: ChessRules.PawnSpecs.promotions.concat([V.GRASSHOPPER]) }
32f6285e
BA
15 );
16 }
17
a97bdbda
BA
18 static get GRASSHOPPER() {
19 return "g";
20 }
21
22 static get PIECES() {
23 return ChessRules.PIECES.concat([V.GRASSHOPPER]);
24 }
25
26 getPpath(b) {
27 return (b[1] == V.GRASSHOPPER ? "Grasshopper/" : "") + b;
28 }
29
30 getPotentialMovesFrom([x, y]) {
31 switch (this.getPiece(x, y)) {
32 case V.GRASSHOPPER:
33 return this.getPotentialGrasshopperMoves([x, y]);
34 default:
35 return super.getPotentialMovesFrom([x, y]);
36 }
37 }
38
39 getPotentialGrasshopperMoves([x, y]) {
40 let moves = [];
41 // Look in every direction until an obstacle (to jump) is met
42 for (const step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) {
43 let i = x + step[0];
44 let j = y + step[1];
45 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
46 i += step[0];
47 j += step[1];
48 }
49 // Move is valid if the next square is empty or occupied by enemy
50 const nextSq = [i+step[0], j+step[1]];
51 if (V.OnBoard(nextSq[0], nextSq[1]) && this.canTake([x, y], nextSq))
52 moves.push(this.getBasicMove([x, y], nextSq));
53 }
54 return moves;
55 }
56
68e19a44 57 isAttacked(sq, color) {
a97bdbda 58 return (
68e19a44
BA
59 super.isAttacked(sq, color) ||
60 this.isAttackedByGrasshopper(sq, color)
a97bdbda
BA
61 );
62 }
63
68e19a44 64 isAttackedByGrasshopper([x, y], color) {
a97bdbda
BA
65 // Reversed process: is there an adjacent obstacle,
66 // and a grasshopper next in the same line?
67 for (const step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) {
68 const nextSq = [x+step[0], y+step[1]];
69 if (
70 V.OnBoard(nextSq[0], nextSq[1]) &&
71 this.board[nextSq[0]][nextSq[1]] != V.EMPTY
72 ) {
73 let i = nextSq[0] + step[0];
74 let j = nextSq[1] + step[1];
75 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
76 i += step[0];
77 j += step[1];
78 }
79 if (
80 V.OnBoard(i, j) &&
81 this.getPiece(i, j) == V.GRASSHOPPER &&
68e19a44 82 this.getColor(i, j) == color
a97bdbda
BA
83 ) {
84 return true;
85 }
86 }
87 }
88 return false;
89 }
90
91 static get VALUES() {
92 return Object.assign(
1eb6c9dd
BA
93 // TODO: grasshoppers power decline with less pieces on board...
94 { g: 2 },
a97bdbda
BA
95 ChessRules.VALUES
96 );
97 }
98
b83a675a
BA
99 static get SEARCH_DEPTH() {
100 return 2;
101 }
102
7ba4a5bc
BA
103 static GenRandInitFen(randomness) {
104 return ChessRules.GenRandInitFen(randomness)
3a2a7b5f 105 .slice(0, -2)
1eb6c9dd
BA
106 .replace(
107 "/pppppppp/8/8/8/8/PPPPPPPP/",
108 "/gggggggg/pppppppp/8/8/PPPPPPPP/GGGGGGGG/"
109 );
a97bdbda
BA
110 }
111};