Draft Ball variant + some fixes, enhancements and code cleaning
[vchess.git] / client / src / variants / Extinction.js
CommitLineData
0c3fe8a6
BA
1import { ChessRules } from "@/base_rules";
2
32f6285e
BA
3export class ExtinctionRules extends ChessRules {
4 static get PawnSpecs() {
5 return Object.assign(
6 {},
7 ChessRules.PawnSpecs,
8 { promotions: ChessRules.PawnSpecs.promotions.concat([V.KING]) }
9 );
10 }
11
d7c00f6a 12 static IsGoodPosition(position) {
6f2f9437 13 if (!ChessRules.IsGoodPosition(position)) return false;
d7c00f6a
BA
14 // Also check that each piece type is present
15 const rows = position.split("/");
16 let pieces = {};
17 for (let row of rows) {
18 for (let i = 0; i < row.length; i++) {
19 if (isNaN(parseInt(row[i])) && !pieces[row[i]])
20 pieces[row[i]] = true;
21 }
22 }
6f2f9437 23 if (Object.keys(pieces).length != 12) return false;
d7c00f6a
BA
24 return true;
25 }
26
6f2f9437
BA
27 scanKings() {}
28
6808d7a1 29 setOtherVariables(fen) {
dac39588
BA
30 super.setOtherVariables(fen);
31 const pos = V.ParseFen(fen).position;
32 // NOTE: no need for safety "|| []", because each piece type must be present
33 // (otherwise game is already over!)
6808d7a1
BA
34 this.material = {
35 w: {
dac39588
BA
36 [V.KING]: pos.match(/K/g).length,
37 [V.QUEEN]: pos.match(/Q/g).length,
38 [V.ROOK]: pos.match(/R/g).length,
39 [V.KNIGHT]: pos.match(/N/g).length,
40 [V.BISHOP]: pos.match(/B/g).length,
41 [V.PAWN]: pos.match(/P/g).length
42 },
6808d7a1 43 b: {
dac39588
BA
44 [V.KING]: pos.match(/k/g).length,
45 [V.QUEEN]: pos.match(/q/g).length,
46 [V.ROOK]: pos.match(/r/g).length,
47 [V.KNIGHT]: pos.match(/n/g).length,
48 [V.BISHOP]: pos.match(/b/g).length,
49 [V.PAWN]: pos.match(/p/g).length
50 }
51 };
52 }
a6abf094 53
dac39588 54 // TODO: verify this assertion
6808d7a1 55 atLeastOneMove() {
dac39588
BA
56 return true; //always at least one possible move
57 }
a6abf094 58
6b7b2cf7
BA
59 filterValid(moves) {
60 return moves; //there is no check
dac39588 61 }
a6abf094 62
6808d7a1 63 getCheckSquares() {
dac39588
BA
64 return [];
65 }
a6abf094 66
3a2a7b5f
BA
67 postPlay(move) {
68 super.postPlay(move);
dac39588 69 // Treat the promotion case: (not the capture part)
6808d7a1 70 if (move.appear[0].p != move.vanish[0].p) {
dac39588
BA
71 this.material[move.appear[0].c][move.appear[0].p]++;
72 this.material[move.appear[0].c][V.PAWN]--;
73 }
6808d7a1
BA
74 if (move.vanish.length == 2 && move.appear.length == 1)
75 //capture
dac39588
BA
76 this.material[move.vanish[1].c][move.vanish[1].p]--;
77 }
a6abf094 78
3a2a7b5f
BA
79 postUndo(move) {
80 super.postUndo(move);
6808d7a1 81 if (move.appear[0].p != move.vanish[0].p) {
dac39588
BA
82 this.material[move.appear[0].c][move.appear[0].p]--;
83 this.material[move.appear[0].c][V.PAWN]++;
84 }
6808d7a1 85 if (move.vanish.length == 2 && move.appear.length == 1)
dac39588
BA
86 this.material[move.vanish[1].c][move.vanish[1].p]++;
87 }
a6abf094 88
6808d7a1
BA
89 getCurrentScore() {
90 if (this.atLeastOneMove()) {
6b7b2cf7 91 // Game not over?
dac39588 92 const color = this.turn;
6808d7a1
BA
93 if (
94 Object.keys(this.material[color]).some(p => {
95 return this.material[color][p] == 0;
96 })
97 ) {
98 return this.turn == "w" ? "0-1" : "1-0";
dac39588
BA
99 }
100 return "*";
101 }
6808d7a1 102 return this.turn == "w" ? "0-1" : "1-0"; //NOTE: currently unreachable...
dac39588 103 }
a6abf094 104
6808d7a1 105 evalPosition() {
dac39588 106 const color = this.turn;
6808d7a1
BA
107 if (
108 Object.keys(this.material[color]).some(p => {
109 return this.material[color][p] == 0;
110 })
111 ) {
dac39588 112 // Very negative (resp. positive) if white (reps. black) pieces set is incomplete
6808d7a1 113 return (color == "w" ? -1 : 1) * V.INFINITY;
dac39588
BA
114 }
115 return super.evalPosition();
116 }
6808d7a1 117};