1 import { ChessRules
} from "@/base_rules";
3 export class Pacifist1Rules
extends ChessRules
{
5 static get PawnSpecs() {
13 static get HasEnpassant() {
17 static IsGoodPosition(position
) {
18 if (position
.length
== 0) return false;
19 const rows
= position
.split("/");
20 if (rows
.length
!= V
.size
.x
) return false;
22 for (let row
of rows
) {
24 for (let i
= 0; i
< row
.length
; i
++) {
25 if (['K','k'].includes(row
[i
])) kingsCount
++;
26 if (V
.PIECES
.includes(row
[i
].toLowerCase())) sumElts
++;
28 const num
= parseInt(row
[i
], 10);
29 if (isNaN(num
)) return false;
33 if (sumElts
!= V
.size
.y
) return false;
35 // Both kings should be on board. May be of the same color.
36 if (kingsCount
!= 2) return false;
40 // Kings may be swapped, so they are not tracked (no kingPos)
43 // Sum white pieces attacking a square, and remove black pieces count.
45 const getSign
= (color
) => {
46 return (color
== 'w' ? 1 : -1);
50 V
.steps
[V
.KNIGHT
].forEach(s
=> {
51 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
52 if (V
.OnBoard(i
, j
) && this.getPiece(i
, j
) == V
.KNIGHT
)
53 res
+= getSign(this.getColor(i
, j
));
56 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]).forEach(s
=> {
57 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
58 if (V
.OnBoard(i
, j
) && this.getPiece(i
, j
) == V
.KING
)
59 res
+= getSign(this.getColor(i
, j
));
62 for (let c
of ['w', 'b']) {
63 for (let shift
of [-1, 1]) {
64 const sign
= getSign(c
);
65 const [i
, j
] = [x
+ sign
, y
+ shift
];
68 this.getPiece(i
, j
) == V
.PAWN
&&
69 this.getColor(i
, j
) == c
75 // Other pieces (sliders):
76 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]).forEach(s
=> {
77 let [i
, j
] = [x
+ s
[0], y
+ s
[1]];
78 let compatible
= [V
.QUEEN
];
79 compatible
.push(s
[0] == 0 || s
[1] == 0 ? V
.ROOK : V
.BISHOP
);
80 let firstCol
= undefined;
81 while (V
.OnBoard(i
, j
)) {
82 if (this.board
[i
][j
] != V
.EMPTY
) {
83 if (!(compatible
.includes(this.getPiece(i
, j
)))) break;
84 const colIJ
= this.getColor(i
, j
);
85 if (!firstCol
) firstCol
= colIJ
;
86 if (colIJ
== firstCol
) res
+= getSign(colIJ
);
96 getPotentialMovesFrom([x
, y
]) {
97 let moves
= super.getPotentialMovesFrom([x
, y
]);
98 const color
= this.turn
;
99 const oppCol
= V
.GetOppCol(color
);
100 if (this.getPiece(x
, y
) == V
.PAWN
) {
101 // Pawns cannot move 2 squares if the intermediate is overly persuaded
102 moves
= moves
.filter(m
=> {
103 if (Math
.abs(m
.end
.x
- m
.start
.x
) == 2) {
104 const [i
, j
] = [(m
.start
.x
+ m
.end
.x
) / 2, y
];
105 const persuasion
= this.sumAttacks([i
, j
]);
107 color
== 'w' && persuasion
>= 0 ||
108 color
== 'b' && persuasion
<= 0
114 // Potentially flipped (opp) pieces
116 for (let i
=0; i
<8; i
++) {
117 for (let j
=0; j
<8; j
++) {
118 if (this.board
[i
][j
] != V
.EMPTY
&& this.getColor(i
, j
) == oppCol
)
119 targets
.push([i
, j
]);
123 // Start persuading other pieces: loop until nothing changes
124 V
.PlayOnBoard(this.board
, m
);
127 targets
.forEach(t
=> {
128 if (this.getColor(t
[0], t
[1]) == oppCol
) {
129 const sqAttacks
= this.sumAttacks([t
[0], t
[1]]);
131 (oppCol
== 'w' && sqAttacks
< 0) ||
132 (oppCol
== 'b' && sqAttacks
> 0)
138 if (persuaded
.length
== 0) break;
139 persuaded
.forEach(p
=> {
140 this.board
[p
[0]][p
[1]] = color
+ this.getPiece(p
[0], p
[1]);
143 V
.UndoOnBoard(this.board
, m
);
144 // Reset pieces colors + adjust move (flipped pieces)
145 targets
.forEach(t
=> {
146 if (this.getColor(t
[0], t
[1]) == color
) {
147 const piece
= this.getPiece(t
[0], t
[1]);
148 m
.appear
.push({ x: t
[0], y: t
[1], c: color
, p: piece
});
149 m
.vanish
.push({ x: t
[0], y: t
[1], c: oppCol
, p: piece
});
150 this.board
[t
[0]][t
[1]] = oppCol
+ piece
;
163 // Find the king(s) and determine if it (both) is persuaded.
164 // If yes, "under check"
166 for (let i
=0; i
<8; i
++) {
167 for (let j
=0; j
<8; j
++) {
168 if (this.getPiece(i
, j
) == V
.KING
&& this.getColor(i
, j
) == color
)
169 kingPos
.push([i
, j
]);
172 return kingPos
.every(kp
=> {
173 const persuasion
= this.sumAttacks(kp
);
175 (color
== 'w' && persuasion
< 0) ||
176 (color
== 'b' && persuasion
> 0)
182 const fmoves
= super.filterValid(moves
);
183 const color
= this.turn
;
184 // If the king isn't here, only moves persuading a king are valid
185 const kingHere
= this.board
.some(b
=>
186 b
.some(cell
=> cell
[0] == color
&& cell
[1] == V
.KING
)
190 fmoves
.filter(m
=> m
.appear
.some(a
=> a
.c
== color
&& a
.p
== V
.KING
))
197 // There are not really "checks": just color change
202 const color
= this.turn
;
203 // TODO: if no king of turn color, and no move to get one, then it's lost
204 // otherwise 1/2 if no moves, or "*"
205 const kingHere
= this.board
.some(b
=>
206 b
.some(cell
=> cell
[0] == color
&& cell
[1] == V
.KING
)
209 if (this.atLeastOneMove()) return "*";
212 // No king was found: try to convert one
213 const moves
= this.getAllValidMoves();
215 moves
.some(m
=> m
.appear
.some(a
=> a
.c
== color
&& a
.p
== V
.KING
))
217 : (color
== 'w' ? "0-1" : "1-0")
222 this.updateCastleFlags(move, move.vanish
[0].p
);
227 static get SEARCH_DEPTH() {