1 import { ChessRules
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { randInt
} from "@/utils/alea";
5 export const VariantRules
= class GrasshopperRules
extends ChessRules
{
6 static get GRASSHOPPER() {
11 return ChessRules
.PIECES
.concat([V
.GRASSHOPPER
]);
15 return (b
[1] == V
.GRASSHOPPER
? "Grasshopper/" : "") + b
;
18 getPotentialMovesFrom([x
, y
]) {
19 switch (this.getPiece(x
, y
)) {
21 return this.getPotentialGrasshopperMoves([x
, y
]);
23 return super.getPotentialMovesFrom([x
, y
]);
27 getPotentialGrasshopperMoves([x
, y
]) {
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
])) {
33 while (V
.OnBoard(i
, j
) && this.board
[i
][j
] == V
.EMPTY
) {
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
));
45 isAttacked(sq
, colors
) {
47 super.isAttacked(sq
, colors
) ||
48 this.isAttackedByGrasshopper(sq
, colors
)
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]];
58 V
.OnBoard(nextSq
[0], nextSq
[1]) &&
59 this.board
[nextSq
[0]][nextSq
[1]] != V
.EMPTY
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
) {
69 this.getPiece(i
, j
) == V
.GRASSHOPPER
&&
70 colors
.includes(this.getColor(i
, j
))
81 // TODO: grasshoppers power decline when less pieces on board...
87 static GenRandInitFen() {
88 let pieces
= { w: new Array(10), b: new Array(10) };
89 for (let c
of ["w", "b"]) {
90 let positions
= ArrayFun
.range(8);
92 // Get random squares for grasshoppers (unconstrained)
93 let randIndex
= randInt(8);
94 const grasshopper1Pos
= positions
[randIndex
];
95 positions
.splice(randIndex
, 1);
96 randIndex
= randInt(7);
97 const grasshopper2Pos
= positions
[randIndex
];
98 positions
.splice(randIndex
, 1);
101 randIndex
= randInt(6);
102 let knight1Pos
= positions
[randIndex
];
103 positions
.splice(randIndex
, 1);
104 randIndex
= randInt(5);
105 let knight2Pos
= positions
[randIndex
];
106 positions
.splice(randIndex
, 1);
109 randIndex
= randInt(4);
110 let queenPos
= positions
[randIndex
];
111 positions
.splice(randIndex
, 1);
113 let rook1Pos
= positions
[0];
114 let kingPos
= positions
[1];
115 let rook2Pos
= positions
[2];
117 pieces
[c
][rook1Pos
] = "r";
118 pieces
[c
][knight1Pos
] = "n";
119 pieces
[c
][grasshopper1Pos
] = "g";
120 pieces
[c
][queenPos
] = "q";
121 pieces
[c
][kingPos
] = "k";
122 pieces
[c
][grasshopper2Pos
] = "g";
123 pieces
[c
][knight2Pos
] = "n";
124 pieces
[c
][rook2Pos
] = "r";
127 pieces
["b"].join("") +
128 "/pppppppp/8/8/8/8/PPPPPPPP/" +
129 pieces
["w"].join("").toUpperCase() +