A few fixes, specify Apocalypse rules, draft Arena
[xogo.git] / variants / Refusal / class.js
1 import ChessRules from "/base_rules.js";
2
3 export default class RefusalRules extends ChessRules {
4
5 static get Options() {
6 return {
7 select: C.Options.select,
8 input: [
9 {
10 label: "Refuse any",
11 variable: "refuseany",
12 type: "checkbox",
13 defaut: true
14 }
15 ],
16 styles: ["cylinder"]
17 };
18 }
19
20 get hasFlags() {
21 return false;
22 }
23
24 getPartFen(o) {
25 let parts = super.getPartFen(o);
26 parts["lastmove"] = o.init ? null : this.lastMove;
27 return parts;
28 }
29
30 setOtherVariables(fenParsed) {
31 super.setOtherVariables(fenParsed);
32 this.lastMove = JSON.parse(fenParsed.lastmove);
33 if (!this.lastMove) {
34 // Fill with empty values to avoid checking lastMove != null
35 this.lastMove = {
36 start: {x: -1, y: -1}, end: {x: -1, y: -1}, vanish: [{c: ''}]
37 };
38 }
39 }
40
41 canIplay(x, y) {
42 if (super.canIplay(x, y))
43 return true;
44 // Check if playing last move, reversed:
45 const lm = this.lastMove;
46 return (!lm.noRef && x == lm.end.x && y == lm.end.y);
47 }
48
49 getPotentialMovesFrom([x, y]) {
50 const moveColor = this.getColor(x, y);
51 if (moveColor != this.turn) {
52 let revLm = JSON.parse(JSON.stringify(this.lastMove));
53 [revLm.appear, revLm.vanish] = [revLm.vanish, revLm.appear];
54 [revLm.start, revLm.end] = [revLm.end, revLm.start];
55 if (!this.options["refuseany"]) {
56 // After refusing this move, can my opponent play a different move?
57 this.playOnBoard(revLm);
58 let totOppMoves = 0;
59 outerLoop: for (let i=0; i<this.size.x; i++) {
60 for (let j=0; j<this.size.y; j++) {
61 if (this.getColor(i, j) == moveColor) {
62 const potentialOppMoves = super.getPotentialMovesFrom([i, j]);
63 totOppMoves +=
64 super.filterValid(potentialOppMoves, moveColor).length;
65 if (totOppMoves >= 2)
66 break outerLoop;
67 }
68 }
69 }
70 this.undoOnBoard(revLm);
71 if (totOppMoves <= 1)
72 return [];
73 }
74 // Also reverse segments in Cylinder mode:
75 if (this.options["cylinder"])
76 revLm.segments = revLm.segments.map(seg => [seg[1], seg[0]]);
77 else
78 delete revLm["segments"];
79 revLm.refusal = true;
80 revLm.noRef = true; //cannot refuse a refusal move :)
81 return [revLm];
82 }
83 return super.getPotentialMovesFrom([x, y]);
84 }
85
86 getEpSquare(move) {
87 if (!move.refusal)
88 return super.getEpSquare(move);
89 return null;
90 }
91
92 filterValid(moves) {
93 const color = this.turn;
94 const lm = this.lastMove;
95 let rMoves = moves.filter(m => {
96 return (
97 !lm.refusal || //it's my first move attempt on this turn
98 m.start.x != lm.end.x || m.start.y != lm.end.y ||
99 m.end.x != lm.start.x || m.end.y != lm.start.y ||
100 // Doing the same move again: maybe pawn promotion?
101 (m.vanish[0].p == 'p' && m.appear[0].p != lm.appear[0].p)
102 );
103 });
104 return super.filterValid(rMoves);
105 }
106
107 prePlay(move) {
108 if (!move.noRef)
109 // My previous move was already refused?
110 move.noRef = this.lastMove.vanish[0].c == this.turn;
111 }
112
113 postPlay(move) {
114 this.lastMove = move;
115 super.postPlay(move);
116 }
117
118 atLeastOneMove(color) {
119 if (!this.lastMove.noRef)
120 return true;
121 return super.atLeastOneMove(color);
122 }
123
124 };