58b1240679720a64edd26cc708d74ef01930c9eb
[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 const VariantRules = class GrasshopperRules extends ChessRules {
6 static get GRASSHOPPER() {
7 return "g";
8 }
9
10 static get PIECES() {
11 return ChessRules.PIECES.concat([V.GRASSHOPPER]);
12 }
13
14 getPpath(b) {
15 return (b[1] == V.GRASSHOPPER ? "Grasshopper/" : "") + b;
16 }
17
18 getPotentialMovesFrom([x, y]) {
19 switch (this.getPiece(x, y)) {
20 case V.GRASSHOPPER:
21 return this.getPotentialGrasshopperMoves([x, y]);
22 default:
23 return super.getPotentialMovesFrom([x, y]);
24 }
25 }
26
27 getPotentialGrasshopperMoves([x, y]) {
28 let moves = [];
29 // Look in every direction until an obstacle (to jump) is met
30 for (const step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) {
31 let i = x + step[0];
32 let j = y + step[1];
33 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
34 i += step[0];
35 j += step[1];
36 }
37 // Move is valid if the next square is empty or occupied by enemy
38 const nextSq = [i+step[0], j+step[1]];
39 if (V.OnBoard(nextSq[0], nextSq[1]) && this.canTake([x, y], nextSq))
40 moves.push(this.getBasicMove([x, y], nextSq));
41 }
42 return moves;
43 }
44
45 isAttacked(sq, colors) {
46 return (
47 super.isAttacked(sq, colors) ||
48 this.isAttackedByGrasshopper(sq, colors)
49 );
50 }
51
52 isAttackedByGrasshopper([x, y], colors) {
53 // Reversed process: is there an adjacent obstacle,
54 // and a grasshopper next in the same line?
55 for (const step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) {
56 const nextSq = [x+step[0], y+step[1]];
57 if (
58 V.OnBoard(nextSq[0], nextSq[1]) &&
59 this.board[nextSq[0]][nextSq[1]] != V.EMPTY
60 ) {
61 let i = nextSq[0] + step[0];
62 let j = nextSq[1] + step[1];
63 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
64 i += step[0];
65 j += step[1];
66 }
67 if (
68 V.OnBoard(i, j) &&
69 this.getPiece(i, j) == V.GRASSHOPPER &&
70 colors.includes(this.getColor(i, j))
71 ) {
72 return true;
73 }
74 }
75 }
76 return false;
77 }
78
79 static get VALUES() {
80 return Object.assign(
81 // TODO: grasshoppers power decline with less pieces on board...
82 { g: 2 },
83 ChessRules.VALUES
84 );
85 }
86
87 static GenRandInitFen() {
88 return ChessRules.GenRandInitFen()
89 .replace(
90 "/pppppppp/8/8/8/8/PPPPPPPP/",
91 "/gggggggg/pppppppp/8/8/PPPPPPPP/GGGGGGGG/"
92 );
93 }
94 };