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() {
30 static IsGoodPosition(position
) {
31 if (position
.length
== 0) return false;
32 const rows
= position
.split("/");
33 if (rows
.length
!= V
.size
.x
) return false;
34 for (let row
of rows
) {
36 for (let i
= 0; i
< row
.length
; i
++) {
37 if (V
.PIECES
.includes(row
[i
].toLowerCase())) sumElts
++;
39 const num
= parseInt(row
[i
], 10);
40 if (isNaN(num
) || num
<= 0) return false;
44 if (sumElts
!= V
.size
.y
) return false;
49 static GenRandInitFen() {
51 "PpPpPpPp/pPpPpPpP/PpPpPpPp/pPpPpPpP/" +
52 "PpPpPpPp/pPpPpPpP/PpPpPpPp/pPpPpPpP w 0"
56 setOtherVariables(fen
) {
57 this.captures
= []; //reinit for each move
60 hoverHighlight(x
, y
) {
61 if (this.movesCount
>= 2) return false;
63 if (c
== 'w') return (x
== y
&& [0, 3, 4, 7].includes(x
));
64 // "Black": search for empty square and allow nearby
65 for (let i
of [0, 3, 4, 7]) {
66 if (this.board
[i
][i
] == V
.EMPTY
)
67 return (Math
.abs(x
- i
) + Math
.abs(y
- i
) == 1)
73 this.movesCount
<= 1 ||
74 // TODO: next line theoretically shouldn't be required...
75 (this.movesCount
== 2 && this.getColor(x
, y
) != this.turn
)
80 if (this.movesCount
>= 2) return null;
81 const color
= this.turn
;
83 if (x
!= y
|| ![0, 3, 4, 7].includes(x
)) return null;
86 vanish: [ new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}) ],
90 // "Black": search for empty square and allow nearby
91 for (let i
of [0, 3, 4, 7]) {
92 if (this.board
[i
][i
] == V
.EMPTY
) {
93 if (Math
.abs(x
- i
) + Math
.abs(y
- i
) != 1) return null;
96 vanish: [ new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}) ],
103 getPotentialMovesFrom([x
, y
]) {
104 if (this.movesCount
<= 1) {
105 const mv
= this.doClick([x
, y
]);
106 return (!!mv
? [mv
] : []);
108 const L
= this.captures
.length
;
109 const c
= (L
> 0 ? this.captures
[L
-1] : null);
110 const color
= this.turn
;
111 const oppCol
= V
.GetOppCol(color
);
115 if (x
!= c
.end
.x
|| y
!= c
.end
.y
) return [];
116 step
= [(c
.end
.x
- c
.start
.x
) / 2, (c
.end
.y
- c
.start
.y
) / 2];
117 // Add move to adjacent empty square to mark "end of capture"
122 start: { x: x
, y: y
},
123 end: { x: x
- step
[0], y: y
- step
[1] }
127 // Examine captures from here
128 for (let s
of (!!step
? [step
] : V
.steps
[V
.ROOK
])) {
129 let [i
, j
] = [x
+ 2*s
[0], y
+ 2*s
[1]];
131 !!c
|| //avoid redundant checks if continuation
134 this.board
[i
][j
] == V
.EMPTY
&&
135 this.board
[i
- s
[0]][j
- s
[1]] != V
.EMPTY
&&
136 this.getColor(i
- s
[0], j
- s
[1]) == oppCol
141 new PiPo({ x: i
, y: j
, c: color
, p: V
.PAWN
})
144 new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}),
145 new PiPo({ x: i
- s
[0], y: j
- s
[1], c: oppCol
, p: V
.PAWN
})
148 // Is there another capture possible then?
149 [i
, j
] = [i
+ 2*s
[0], j
+ 2*s
[1]];
152 this.board
[i
][j
] == V
.EMPTY
&&
153 this.board
[i
- s
[0]][j
- s
[1]] != V
.EMPTY
&&
154 this.getColor(i
- s
[0], j
- s
[1]) == oppCol
156 mv
.end
.moreCapture
= true;
173 if (this.atLeastOneMove()) return "*";
174 return (this.turn
== "w" ? "0-1" : "1-0");
178 V
.PlayOnBoard(this.board
, move);
179 if (!move.end
.moreCapture
) {
180 this.turn
= V
.GetOppCol(this.turn
);
188 end: { x: move.end
.x
, y: move.end
.y
}
195 V
.UndoOnBoard(this.board
, move);
196 if (!move.end
.moreCapture
) {
197 this.turn
= V
.GetOppCol(this.turn
);
200 else this.captures
.pop();
204 const color
= this.turn
;
207 const undoAll
= () => {
208 for (let i
= mvArray
.length
- 1; i
>= 0; i
--) this.undo(mvArray
[i
]);
210 // Just play random moves (for now at least. TODO?)
211 while (this.turn
== color
) {
212 let moves
= super.getAllValidMoves();
213 if (moves
.length
== 0) {
214 // Shouldn't happen, but...
218 mv
= moves
[randInt(moves
.length
)];
223 return (mvArray
.length
> 1 ? mvArray : mvArray
[0]);
227 if (this.movesCount
<= 1) return V
.CoordsToSquare(move.start
) + "X";
228 if (move.vanish
.length
== 0) return "end";
229 return V
.CoordsToSquare(move.start
) + "x" + V
.CoordsToSquare(move.end
);