1 import { ChessRules
} from "@/base_rules";
3 export const VariantRules
= class ExtinctionRules
extends ChessRules
{
4 static IsGoodPosition(position
) {
5 if (!ChessRules
.IsGoodPosition(position
))
7 // Also check that each piece type is present
8 const rows
= position
.split("/");
10 for (let row
of rows
) {
11 for (let i
= 0; i
< row
.length
; i
++) {
12 if (isNaN(parseInt(row
[i
])) && !pieces
[row
[i
]])
13 pieces
[row
[i
]] = true;
16 if (Object
.keys(pieces
).length
!= 12)
21 setOtherVariables(fen
) {
22 super.setOtherVariables(fen
);
23 const pos
= V
.ParseFen(fen
).position
;
24 // NOTE: no need for safety "|| []", because each piece type must be present
25 // (otherwise game is already over!)
28 [V
.KING
]: pos
.match(/K
/g
).length
,
29 [V
.QUEEN
]: pos
.match(/Q
/g
).length
,
30 [V
.ROOK
]: pos
.match(/R
/g
).length
,
31 [V
.KNIGHT
]: pos
.match(/N
/g
).length
,
32 [V
.BISHOP
]: pos
.match(/B
/g
).length
,
33 [V
.PAWN
]: pos
.match(/P
/g
).length
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
46 getPotentialPawnMoves([x
, y
]) {
47 let moves
= super.getPotentialPawnMoves([x
, y
]);
48 // Add potential promotions into king
49 const color
= this.turn
;
50 const shift
= color
== "w" ? -1 : 1;
51 const lastRank
= color
== "w" ? 0 : V
.size
.x
- 1;
53 if (x
+ shift
== lastRank
) {
55 if (this.board
[x
+ shift
][y
] == V
.EMPTY
)
57 this.getBasicMove([x
, y
], [x
+ shift
, y
], { c: color
, p: V
.KING
})
62 this.board
[x
+ shift
][y
- 1] != V
.EMPTY
&&
63 this.canTake([x
, y
], [x
+ shift
, y
- 1])
66 this.getBasicMove([x
, y
], [x
+ shift
, y
- 1], { c: color
, p: V
.KING
})
71 this.board
[x
+ shift
][y
+ 1] != V
.EMPTY
&&
72 this.canTake([x
, y
], [x
+ shift
, y
+ 1])
75 this.getBasicMove([x
, y
], [x
+ shift
, y
+ 1], { c: color
, p: V
.KING
})
83 // TODO: verify this assertion
85 return true; //always at least one possible move
89 return moves
; //there is no check
98 // Treat the promotion case: (not the capture part)
99 if (move.appear
[0].p
!= move.vanish
[0].p
) {
100 this.material
[move.appear
[0].c
][move.appear
[0].p
]++;
101 this.material
[move.appear
[0].c
][V
.PAWN
]--;
103 if (move.vanish
.length
== 2 && move.appear
.length
== 1)
105 this.material
[move.vanish
[1].c
][move.vanish
[1].p
]--;
109 super.postUndo(move);
110 if (move.appear
[0].p
!= move.vanish
[0].p
) {
111 this.material
[move.appear
[0].c
][move.appear
[0].p
]--;
112 this.material
[move.appear
[0].c
][V
.PAWN
]++;
114 if (move.vanish
.length
== 2 && move.appear
.length
== 1)
115 this.material
[move.vanish
[1].c
][move.vanish
[1].p
]++;
119 if (this.atLeastOneMove()) {
121 const color
= this.turn
;
123 Object
.keys(this.material
[color
]).some(p
=> {
124 return this.material
[color
][p
] == 0;
127 return this.turn
== "w" ? "0-1" : "1-0";
132 return this.turn
== "w" ? "0-1" : "1-0"; //NOTE: currently unreachable...
136 const color
= this.turn
;
138 Object
.keys(this.material
[color
]).some(p
=> {
139 return this.material
[color
][p
] == 0;
142 // Very negative (resp. positive) if white (reps. black) pieces set is incomplete
143 return (color
== "w" ? -1 : 1) * V
.INFINITY
;
145 return super.evalPosition();