1 import { ChessRules
, Move
, PiPo
} from "@/base_rules";
2 import { randInt
} from "@/utils/alea";
4 export class KonaneRules
extends ChessRules
{
6 static get HasFlags() {
10 static get HasEnpassant() {
14 static get ReverseColors() {
26 static IsGoodPosition(position
) {
27 if (position
.length
== 0) return false;
28 const rows
= position
.split("/");
29 if (rows
.length
!= V
.size
.x
) return false;
30 for (let row
of rows
) {
32 for (let i
= 0; i
< row
.length
; i
++) {
33 if (row
[i
].toLowerCase() == V
.PAWN
) sumElts
++;
35 const num
= parseInt(row
[i
], 10);
36 if (isNaN(num
) || num
<= 0) return false;
40 if (sumElts
!= V
.size
.y
) return false;
45 static GenRandInitFen() {
47 "PpPpPpPp/pPpPpPpP/PpPpPpPp/pPpPpPpP/" +
48 "PpPpPpPp/pPpPpPpP/PpPpPpPp/pPpPpPpP w 0"
52 setOtherVariables(fen
) {
53 this.captures
= []; //reinit for each move
56 hoverHighlight([x
, y
], side
) {
58 if (this.movesCount
>= 2 || (!!side
&& side
!= c
)) return false;
59 if (c
== 'w') return (x
== y
&& [0, 3, 4, 7].includes(x
));
60 // "Black": search for empty square and allow nearby
61 for (let i
of [0, 3, 4, 7]) {
62 if (this.board
[i
][i
] == V
.EMPTY
)
63 return (Math
.abs(x
- i
) + Math
.abs(y
- i
) == 1)
69 this.movesCount
<= 1 ||
70 // TODO: next line theoretically shouldn't be required...
71 (this.movesCount
== 2 && this.getColor(x
, y
) != this.turn
)
76 if (this.movesCount
>= 2) return null;
77 const color
= this.turn
;
79 if (x
!= y
|| ![0, 3, 4, 7].includes(x
)) return null;
82 vanish: [ new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}) ],
86 // "Black": search for empty square and allow nearby
87 for (let i
of [0, 3, 4, 7]) {
88 if (this.board
[i
][i
] == V
.EMPTY
) {
89 if (Math
.abs(x
- i
) + Math
.abs(y
- i
) != 1) return null;
92 vanish: [ new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}) ],
99 getPotentialMovesFrom([x
, y
]) {
100 if (this.movesCount
<= 1) {
101 const mv
= this.doClick([x
, y
]);
102 return (!!mv
? [mv
] : []);
104 const L
= this.captures
.length
;
105 const c
= (L
> 0 ? this.captures
[L
-1] : null);
106 const color
= this.turn
;
107 const oppCol
= V
.GetOppCol(color
);
111 if (x
!= c
.end
.x
|| y
!= c
.end
.y
) return [];
112 step
= [(c
.end
.x
- c
.start
.x
) / 2, (c
.end
.y
- c
.start
.y
) / 2];
113 // Add move to adjacent empty square to mark "end of capture"
118 start: { x: x
, y: y
},
119 end: { x: x
- step
[0], y: y
- step
[1] }
123 // Examine captures from here
124 for (let s
of (!!step
? [step
] : V
.steps
[V
.ROOK
])) {
125 let [i
, j
] = [x
+ 2*s
[0], y
+ 2*s
[1]];
127 !!c
|| //avoid redundant checks if continuation
130 this.board
[i
][j
] == V
.EMPTY
&&
131 this.board
[i
- s
[0]][j
- s
[1]] != V
.EMPTY
&&
132 this.getColor(i
- s
[0], j
- s
[1]) == oppCol
137 new PiPo({ x: i
, y: j
, c: color
, p: V
.PAWN
})
140 new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}),
141 new PiPo({ x: i
- s
[0], y: j
- s
[1], c: oppCol
, p: V
.PAWN
})
144 // Is there another capture possible then?
145 [i
, j
] = [i
+ 2*s
[0], j
+ 2*s
[1]];
148 this.board
[i
][j
] == V
.EMPTY
&&
149 this.board
[i
- s
[0]][j
- s
[1]] != V
.EMPTY
&&
150 this.getColor(i
- s
[0], j
- s
[1]) == oppCol
152 mv
.end
.moreCapture
= true;
169 if (this.atLeastOneMove()) return "*";
170 return (this.turn
== "w" ? "0-1" : "1-0");
174 V
.PlayOnBoard(this.board
, move);
175 if (!move.end
.moreCapture
) {
176 this.turn
= V
.GetOppCol(this.turn
);
184 end: { x: move.end
.x
, y: move.end
.y
}
191 V
.UndoOnBoard(this.board
, move);
192 if (!move.end
.moreCapture
) {
193 this.turn
= V
.GetOppCol(this.turn
);
196 else this.captures
.pop();
200 const color
= this.turn
;
203 const undoAll
= () => {
204 for (let i
= mvArray
.length
- 1; i
>= 0; i
--) this.undo(mvArray
[i
]);
206 // Just play random moves (for now at least. TODO?)
207 while (this.turn
== color
) {
208 let moves
= super.getAllValidMoves();
209 if (moves
.length
== 0) {
210 // Shouldn't happen, but...
214 mv
= moves
[randInt(moves
.length
)];
219 return (mvArray
.length
> 1 ? mvArray : mvArray
[0]);
223 if (this.movesCount
<= 1) return V
.CoordsToSquare(move.start
) + "X";
224 if (move.vanish
.length
== 0) return "end";
225 return V
.CoordsToSquare(move.start
) + "x" + V
.CoordsToSquare(move.end
);