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 HasEnpassant() {
10 static get GRASSHOPPER() {
15 return ChessRules
.PIECES
.concat([V
.GRASSHOPPER
]);
19 return (b
[1] == V
.GRASSHOPPER
? "Grasshopper/" : "") + b
;
22 getPotentialMovesFrom([x
, y
]) {
23 switch (this.getPiece(x
, y
)) {
25 return this.getPotentialGrasshopperMoves([x
, y
]);
27 return super.getPotentialMovesFrom([x
, y
]);
31 getPotentialPawnMoves([x
, y
]) {
32 const color
= this.turn
;
34 const [sizeX
, sizeY
] = [V
.size
.x
, V
.size
.y
];
35 const shiftX
= color
== "w" ? -1 : 1;
36 const lastRank
= color
== "w" ? 0 : sizeX
- 1;
39 x
+ shiftX
== lastRank
40 ? [V
.ROOK
, V
.KNIGHT
, V
.BISHOP
, V
.QUEEN
, V
.GRASSHOPPER
]
42 if (this.board
[x
+ shiftX
][y
] == V
.EMPTY
) {
44 for (let piece
of finalPieces
) {
46 this.getBasicMove([x
, y
], [x
+ shiftX
, y
], {
55 for (let shiftY
of [-1, 1]) {
59 this.board
[x
+ shiftX
][y
+ shiftY
] != V
.EMPTY
&&
60 this.canTake([x
, y
], [x
+ shiftX
, y
+ shiftY
])
62 for (let piece
of finalPieces
) {
64 this.getBasicMove([x
, y
], [x
+ shiftX
, y
+ shiftY
], {
76 getPotentialGrasshopperMoves([x
, y
]) {
78 // Look in every direction until an obstacle (to jump) is met
79 for (const step
of V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
])) {
82 while (V
.OnBoard(i
, j
) && this.board
[i
][j
] == V
.EMPTY
) {
86 // Move is valid if the next square is empty or occupied by enemy
87 const nextSq
= [i
+step
[0], j
+step
[1]];
88 if (V
.OnBoard(nextSq
[0], nextSq
[1]) && this.canTake([x
, y
], nextSq
))
89 moves
.push(this.getBasicMove([x
, y
], nextSq
));
94 isAttacked(sq
, colors
) {
96 super.isAttacked(sq
, colors
) ||
97 this.isAttackedByGrasshopper(sq
, colors
)
101 isAttackedByGrasshopper([x
, y
], colors
) {
102 // Reversed process: is there an adjacent obstacle,
103 // and a grasshopper next in the same line?
104 for (const step
of V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
])) {
105 const nextSq
= [x
+step
[0], y
+step
[1]];
107 V
.OnBoard(nextSq
[0], nextSq
[1]) &&
108 this.board
[nextSq
[0]][nextSq
[1]] != V
.EMPTY
110 let i
= nextSq
[0] + step
[0];
111 let j
= nextSq
[1] + step
[1];
112 while (V
.OnBoard(i
, j
) && this.board
[i
][j
] == V
.EMPTY
) {
118 this.getPiece(i
, j
) == V
.GRASSHOPPER
&&
119 colors
.includes(this.getColor(i
, j
))
128 static get VALUES() {
129 return Object
.assign(
130 // TODO: grasshoppers power decline with less pieces on board...
136 static get SEARCH_DEPTH() {
140 static GenRandInitFen(randomness
) {
141 return ChessRules
.GenRandInitFen(randomness
)
142 .replace("w 0 1111 -", "w 0 1111")
144 "/pppppppp/8/8/8/8/PPPPPPPP/",
145 "/gggggggg/pppppppp/8/8/PPPPPPPP/GGGGGGGG/"