1 import { ChessRules
, Move
, PiPo
} from "@/base_rules";
3 // TODO: Maybe more flexible end of game messages (V.ColorsReversed ?!)
5 export class KonaneRules
extends ChessRules
{
7 static get HasFlags() {
11 static get HasEnpassant() {
23 static IsGoodPosition(position
) {
24 if (position
.length
== 0) return false;
25 const rows
= position
.split("/");
26 if (rows
.length
!= V
.size
.x
) return false;
27 for (let row
of rows
) {
29 for (let i
= 0; i
< row
.length
; i
++) {
30 if (V
.PIECES
.includes(row
[i
].toLowerCase())) sumElts
++;
32 const num
= parseInt(row
[i
], 10);
33 if (isNaN(num
) || num
<= 0) return false;
37 if (sumElts
!= V
.size
.y
) return false;
42 static GenRandInitFen() {
44 "PpPpPpPp/pPpPpPpP/PpPpPpPp/pPpPpPpP/" +
45 "PpPpPpPp/pPpPpPpP/PpPpPpPp/pPpPpPpP w 0"
49 setOtherVariables(fen
) {
50 this.captures
= []; //reinit for each move
53 hoverHighlight(x
, y
) {
54 if (this.movesCount
>= 2) return false;
56 if (c
== 'w') return (x
== y
&& [0, 3, 4, 7].includes(x
));
57 // "Black": search for empty square and allow nearby
58 for (let i
of [0, 3, 4, 7]) {
59 if (this.board
[i
][i
] == V
.EMPTY
)
60 return (Math
.abs(x
- i
) + Math
.abs(y
- i
) == 1)
66 this.movesCount
<= 1 ||
67 // TODO: next line theoretically shouldn't be required...
68 (this.movesCount
== 2 && this.getColor(x
, y
) != this.turn
)
73 if (this.movesCount
>= 2) return null;
74 const color
= this.turn
;
76 if (x
!= y
|| ![0, 3, 4, 7].includes(x
)) return null;
79 vanish: [ new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}) ],
83 // "Black": search for empty square and allow nearby
84 for (let i
of [0, 3, 4, 7]) {
85 if (this.board
[i
][i
] == V
.EMPTY
) {
86 if (Math
.abs(x
- i
) + Math
.abs(y
- i
) != 1) return null;
89 vanish: [ new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}) ],
96 getPotentialMovesFrom([x
, y
]) {
97 if (this.movesCount
<= 1) {
98 const mv
= this.doClick([x
, y
]);
99 return (!!mv
? [mv
] : []);
101 const L
= this.captures
.length
;
102 const c
= (L
> 0 ? this.captures
[L
-1] : null);
103 const color
= this.turn
;
104 const oppCol
= V
.GetOppCol(color
);
108 if (x
!= c
.end
.x
|| y
!= c
.end
.y
) return [];
109 step
= [(c
.end
.x
- c
.start
.x
) / 2, (c
.end
.y
- c
.start
.y
) / 2];
110 // Add move to adjacent empty square to mark "end of capture"
115 start: { x: x
, y: y
},
116 end: { x: x
- step
[0], y: y
- step
[1] }
120 // Examine captures from here
121 for (let s
of (!!step
? [step
] : V
.steps
[V
.ROOK
])) {
122 let [i
, j
] = [x
+ 2*s
[0], y
+ 2*s
[1]];
124 !!c
|| //avoid redundant checks if continuation
127 this.board
[i
][j
] == V
.EMPTY
&&
128 this.board
[i
- s
[0]][j
- s
[1]] != V
.EMPTY
&&
129 this.getColor(i
- s
[0], j
- s
[1]) == oppCol
134 new PiPo({ x: i
, y: j
, c: color
, p: V
.PAWN
})
137 new PiPo({ x: x
, y: y
, c: color
, p: V
.PAWN
}),
138 new PiPo({ x: i
- s
[0], y: j
- s
[1], c: oppCol
, p: V
.PAWN
})
141 // Is there another capture possible then?
142 [i
, j
] = [i
+ 2*s
[0], j
+ 2*s
[1]];
145 this.board
[i
][j
] == V
.EMPTY
&&
146 this.board
[i
- s
[0]][j
- s
[1]] != V
.EMPTY
&&
147 this.getColor(i
- s
[0], j
- s
[1]) == oppCol
149 mv
.end
.moreCapture
= true;
166 if (this.atLeastOneMove()) return "*";
167 return (this.turn
== "w" ? "0-1" : "1-0");
171 V
.PlayOnBoard(this.board
, move);
172 if (!move.end
.moreCapture
) {
173 this.turn
= V
.GetOppCol(this.turn
);
181 end: { x: move.end
.x
, y: move.end
.y
}
188 V
.UndoOnBoard(this.board
, move);
189 if (!move.end
.moreCapture
) {
190 this.turn
= V
.GetOppCol(this.turn
);
193 else this.captures
.pop();
196 static get SEARCH_DEPTH() {
201 if (this.movesCount
<= 1) return V
.CoordsToSquare(move.start
) + "X";
202 if (move.vanish
.length
== 0) return "end";
203 return V
.CoordsToSquare(move.start
) + "x" + V
.CoordsToSquare(move.end
);