Update TODO
[vchess.git] / client / src / variants / Grasshopper.js
1 import { ChessRules } from "@/base_rules";
2 import { ArrayFun } from "@/utils/array";
3 import { randInt } from "@/utils/alea";
4
5 export class GrasshopperRules extends ChessRules {
6 static get HasEnpassant() {
7 return false;
8 }
9
10 static get PawnSpecs() {
11 return Object.assign(
12 {},
13 ChessRules.PawnSpecs,
14 { promotions: ChessRules.PawnSpecs.promotions.concat([V.GRASSHOPPER]) }
15 );
16 }
17
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
57 isAttacked(sq, color) {
58 return (
59 super.isAttacked(sq, color) ||
60 this.isAttackedByGrasshopper(sq, color)
61 );
62 }
63
64 isAttackedByGrasshopper([x, y], color) {
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 &&
82 this.getColor(i, j) == color
83 ) {
84 return true;
85 }
86 }
87 }
88 return false;
89 }
90
91 static get VALUES() {
92 return Object.assign(
93 // TODO: grasshoppers power decline with less pieces on board...
94 { g: 2 },
95 ChessRules.VALUES
96 );
97 }
98
99 static get SEARCH_DEPTH() {
100 return 2;
101 }
102
103 static GenRandInitFen(randomness) {
104 return ChessRules.GenRandInitFen(randomness)
105 .slice(0, -2)
106 .replace(
107 "/pppppppp/8/8/8/8/PPPPPPPP/",
108 "/gggggggg/pppppppp/8/8/PPPPPPPP/GGGGGGGG/"
109 );
110 }
111 };