Fix parseInt() usage, rename Doubleorda --> Ordamirror, implement Clorange variant
[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++) {
e50a8025 19 if (isNaN(parseInt(row[i], 10)) && !pieces[row[i]])
d7c00f6a
BA
20 pieces[row[i]] = true;
21 }
22 }
6f2f9437 23 if (Object.keys(pieces).length != 12) return false;
d7c00f6a
BA
24 return true;
25 }
26
6808d7a1 27 setOtherVariables(fen) {
dac39588
BA
28 super.setOtherVariables(fen);
29 const pos = V.ParseFen(fen).position;
2c5d7b20 30 // NOTE: no need for safety "|| []", because each piece type is present
dac39588 31 // (otherwise game is already over!)
6808d7a1
BA
32 this.material = {
33 w: {
dac39588
BA
34 [V.KING]: pos.match(/K/g).length,
35 [V.QUEEN]: pos.match(/Q/g).length,
36 [V.ROOK]: pos.match(/R/g).length,
37 [V.KNIGHT]: pos.match(/N/g).length,
38 [V.BISHOP]: pos.match(/B/g).length,
39 [V.PAWN]: pos.match(/P/g).length
40 },
6808d7a1 41 b: {
dac39588
BA
42 [V.KING]: pos.match(/k/g).length,
43 [V.QUEEN]: pos.match(/q/g).length,
44 [V.ROOK]: pos.match(/r/g).length,
45 [V.KNIGHT]: pos.match(/n/g).length,
46 [V.BISHOP]: pos.match(/b/g).length,
47 [V.PAWN]: pos.match(/p/g).length
48 }
49 };
50 }
a6abf094 51
dac39588 52 // TODO: verify this assertion
6808d7a1 53 atLeastOneMove() {
dac39588
BA
54 return true; //always at least one possible move
55 }
a6abf094 56
6b7b2cf7
BA
57 filterValid(moves) {
58 return moves; //there is no check
dac39588 59 }
a6abf094 60
6808d7a1 61 getCheckSquares() {
dac39588
BA
62 return [];
63 }
a6abf094 64
3a2a7b5f
BA
65 postPlay(move) {
66 super.postPlay(move);
dac39588 67 // Treat the promotion case: (not the capture part)
6808d7a1 68 if (move.appear[0].p != move.vanish[0].p) {
dac39588
BA
69 this.material[move.appear[0].c][move.appear[0].p]++;
70 this.material[move.appear[0].c][V.PAWN]--;
71 }
6808d7a1
BA
72 if (move.vanish.length == 2 && move.appear.length == 1)
73 //capture
dac39588
BA
74 this.material[move.vanish[1].c][move.vanish[1].p]--;
75 }
a6abf094 76
3a2a7b5f
BA
77 postUndo(move) {
78 super.postUndo(move);
6808d7a1 79 if (move.appear[0].p != move.vanish[0].p) {
dac39588
BA
80 this.material[move.appear[0].c][move.appear[0].p]--;
81 this.material[move.appear[0].c][V.PAWN]++;
82 }
6808d7a1 83 if (move.vanish.length == 2 && move.appear.length == 1)
dac39588
BA
84 this.material[move.vanish[1].c][move.vanish[1].p]++;
85 }
a6abf094 86
6808d7a1
BA
87 getCurrentScore() {
88 if (this.atLeastOneMove()) {
6b7b2cf7 89 // Game not over?
dac39588 90 const color = this.turn;
6808d7a1
BA
91 if (
92 Object.keys(this.material[color]).some(p => {
93 return this.material[color][p] == 0;
94 })
95 ) {
96 return this.turn == "w" ? "0-1" : "1-0";
dac39588
BA
97 }
98 return "*";
99 }
6808d7a1 100 return this.turn == "w" ? "0-1" : "1-0"; //NOTE: currently unreachable...
dac39588 101 }
a6abf094 102
6808d7a1 103 evalPosition() {
dac39588 104 const color = this.turn;
6808d7a1
BA
105 if (
106 Object.keys(this.material[color]).some(p => {
107 return this.material[color][p] == 0;
108 })
109 ) {
2c5d7b20
BA
110 // Very negative (resp. positive)
111 // if white (reps. black) pieces set is incomplete
6808d7a1 112 return (color == "w" ? -1 : 1) * V.INFINITY;
dac39588
BA
113 }
114 return super.evalPosition();
115 }
6808d7a1 116};