1 import { ChessRules
, Move
, PiPo
} from "@/base_rules";
3 export class Align4Rules
extends ChessRules
{
5 static GenRandInitFen(randomness
) {
6 const baseFen
= ChessRules
.GenRandInitFen(Math
.min(randomness
, 1));
7 return "4k3/8" + baseFen
.substring(17, 50) + " -";
14 static get RESERVE_PIECES() {
15 return [V
.PAWN
]; //only black pawns
19 if (i
>= V
.size
.x
) return "b";
20 return this.board
[i
][j
].charAt(0);
24 if (i
>= V
.size
.x
) return V
.PAWN
;
25 return this.board
[i
][j
].charAt(1);
28 static IsGoodFlags(flags
) {
29 // Only white can castle
30 return !!flags
.match(/^[a-z]{2,2}$/);
34 return this.castleFlags
['w'].map(V
.CoordToColumn
).join("");
38 this.castleFlags
= { 'w': [-1, -1] };
39 for (let i
= 0; i
< 2; i
++)
40 this.castleFlags
['w'][i
] = V
.ColumnToCoord(fenflags
.charAt(i
));
43 setOtherVariables(fen
) {
44 super.setOtherVariables(fen
);
45 this.reserve
= { b: { [V
.PAWN
]: 1 } };
49 if (this.turn
!= 'b') return [];
51 for (let i
= 1; i
<= 6; i
++) {
52 for (let j
= 0; j
< V
.size
.y
; j
++) {
53 if (this.board
[i
][j
] == V
.EMPTY
) {
64 start: { x: 9, y: 0 },
74 getPotentialMovesFrom(sq
) {
75 if (sq
[0] >= V
.size
.x
) return this.getReserveMoves();
76 return super.getPotentialMovesFrom(sq
);
79 getPotentialKingMoves([x
, y
]) {
80 if (this.getColor(x
, y
) == 'w') return super.getPotentialKingMoves([x
, y
]);
81 // Black doesn't castle:
82 return super.getSlideNJumpMoves(
84 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]),
91 super.getAllValidMoves().concat(
92 super.filterValid(this.getReserveMoves()))
97 if (super.atLeastOneMove()) return true;
98 // Search one reserve move
99 if (this.filterValid(this.getReserveMoves()).length
> 0) return true;
103 updateCastleFlags(move, piece
) {
104 // Only white can castle:
106 if (piece
== V
.KING
&& move.appear
[0].c
== 'w')
107 this.castleFlags
['w'] = [8, 8];
109 move.start
.x
== firstRank
&&
110 this.castleFlags
['w'].includes(move.start
.y
)
112 const flagIdx
= (move.start
.y
== this.castleFlags
['w'][0] ? 0 : 1);
113 this.castleFlags
['w'][flagIdx
] = 8;
116 move.end
.x
== firstRank
&&
117 this.castleFlags
['w'].includes(move.end
.y
)
119 const flagIdx
= (move.end
.y
== this.castleFlags
['w'][0] ? 0 : 1);
120 this.castleFlags
['w'][flagIdx
] = 8;
125 const score
= super.getCurrentScore();
126 if (score
!= "*") return score
;
127 // Check pawns connection:
128 for (let i
= 0; i
< V
.size
.x
; i
++) {
129 for (let j
= 0; j
< V
.size
.y
; j
++) {
131 this.board
[i
][j
] != V
.EMPTY
&&
132 this.getColor(i
, j
) == 'b' &&
133 this.getPiece(i
, j
) == V
.PAWN
135 // Exploration "rightward + downward" is enough
136 for (let step
of [[1, 0], [0, 1], [1, 1], [-1, 1]]) {
137 let [ii
, jj
] = [i
+ step
[0], j
+ step
[1]];
141 this.board
[ii
][jj
] != V
.EMPTY
&&
142 this.getColor(ii
, jj
) == 'b' &&
143 this.getPiece(ii
, jj
) != V
.KING
149 if (kounter
== 4) return "0-1";
159 // Count white material + check pawns alignments
161 for (let i
= 0; i
< V
.size
.x
; i
++) {
162 for (let j
= 0; j
< V
.size
.y
; j
++) {
163 if (this.board
[i
][j
] != V
.EMPTY
) {
164 const piece
= this.getPiece(i
, j
);
165 if (piece
!= V
.KING
) {
166 const color
= this.getColor(i
, j
);
167 if (color
== 'w') evaluation
+= V
.VALUES
[piece
];
169 // Exploration "rightward + downward" is enough
170 for (let step
of [[1, 0], [0, 1], [1, 1], [-1, 1]]) {
171 let [ii
, jj
] = [i
+ step
[0], j
+ step
[1]];
175 this.board
[ii
][jj
] != V
.EMPTY
&&
176 this.getColor(ii
, jj
) == 'b' &&
177 this.getPiece(ii
, jj
) != V
.KING
183 if (kounter
> maxAlign
) maxAlign
= kounter
;
190 // -1 for two aligned pawns, -3 for 3 aligned pawns.
191 if ([1, 2].includes(maxAlign
)) maxAlign
--;
192 return evaluation
- maxAlign
;
196 if (move.vanish
.length
== 0) return "@" + V
.CoordsToSquare(move.end
);
197 return super.getNotation(move);