Finish base_rules.js refactoring
[xogo.git] / variants / Ambiguous / class.js
1 import ChessRules from "/base_rules.js";
2 import GiveawayRules from "/variants/Giveaway/class.js";
3
4 export default class AmbiguousRules extends ChessRules {
5
6 static get Options() {
7 return {
8 select: C.Options.select,
9 styles: ["cylinder"]
10 };
11 }
12
13 get hasFlags() {
14 return false;
15 }
16
17 setOtherVariables(fenParsed) {
18 super.setOtherVariables(fenParsed);
19 if (this.movesCount == 0)
20 this.subTurn = 2;
21 else
22 this.subTurn = 1;
23 }
24
25 genRandInitFen(seed) {
26 const options = Object.assign({mode: "suicide"}, this.options);
27 const gr = new GiveawayRules({options: options, genFenOnly: true});
28 return gr.genRandInitFen(seed);
29 }
30
31 canStepOver(x, y) {
32 return this.board[x][y] == "" || this.getPiece(x, y) == V.GOAL;
33 }
34
35 // Subturn 1: play a move for the opponent on the designated square.
36 // Subturn 2: play a move for me (which just indicate a square).
37 getPotentialMovesFrom([x, y]) {
38 const color = this.turn;
39 const oppCol = C.GetOppCol(color);
40 if (this.subTurn == 2) {
41 // Just play a normal move (which in fact only indicate a square)
42 let movesHash = {};
43 return (
44 super.getPotentialMovesFrom([x, y])
45 .filter(m => {
46 // Filter promotions: keep only one, since no choice for now.
47 if (m.appear[0].p != m.vanish[0].p) {
48 const hash = C.CoordsToSquare(m.start) + C.CoordsToSquare(m.end);
49 if (!movesHash[hash]) {
50 movesHash[hash] = true;
51 return true;
52 }
53 return false;
54 }
55 return true;
56 })
57 .map(m => {
58 if (m.vanish.length == 1)
59 m.appear[0].p = V.GOAL;
60 else
61 m.appear[0].p = V.TARGET_CODE[m.vanish[1].p];
62 m.vanish.shift();
63 return m;
64 })
65 );
66 }
67 // At subTurn == 1, play a targeted move for the opponent.
68 // Search for target (we could also have it in a stack...)
69 let target = {x: -1, y: -1};
70 outerLoop: for (let i = 0; i < this.size.x; i++) {
71 for (let j = 0; j < this.size.y; j++) {
72 if (this.board[i][j] != "") {
73 const piece = this.getPiece(i, j);
74 if (
75 piece == V.GOAL ||
76 Object.keys(V.TARGET_DECODE).includes(piece)
77 ) {
78 target = {x: i, y:j};
79 break outerLoop;
80 }
81 }
82 }
83 }
84 const moves = super.getPotentialMovesFrom([x, y], oppCol);
85 return moves.filter(m => m.end.x == target.x && m.end.y == target.y);
86 }
87
88 canIplay(x, y) {
89 const color = this.getColor(x, y);
90 return (
91 (this.subTurn == 1 && ![this.turn, this.playerColor].includes(color)) ||
92 (this.subTurn == 2 && super.canIplay(x, y))
93 );
94 }
95
96 // Code for empty square target
97 static get GOAL() {
98 return 'g';
99 }
100
101 static get TARGET_DECODE() {
102 return {
103 's': 'p',
104 't': 'q',
105 'u': 'r',
106 'o': 'n',
107 'c': 'b',
108 'l': 'k'
109 };
110 }
111
112 static get TARGET_CODE() {
113 return {
114 'p': 's',
115 'q': 't',
116 'r': 'u',
117 'n': 'o',
118 'b': 'c',
119 'k': 'l'
120 };
121 }
122
123 pieces(color, x, y) {
124 const targets = {
125 's': {"class": "target-pawn", moves: []},
126 'u': {"class": "target-rook", moves: []},
127 'o': {"class": "target-knight", moves: []},
128 'c': {"class": "target-bishop", moves: []},
129 't': {"class": "target-queen", moves: []},
130 'l': {"class": "target-king", moves: []}
131 };
132 return Object.assign({ 'g': {"class": "target", moves: []} },
133 targets, super.pieces(color, x, y));
134 }
135
136 atLeastOneMove() {
137 // Since there are no checks this seems true (same as for Magnetic...)
138 return true;
139 }
140
141 filterValid(moves) {
142 return moves;
143 }
144
145 isKing(symbol) {
146 return ['k', 'l'].includes(symbol);
147 }
148
149 getCurrentScore() {
150 // This function is only called at subTurn 1
151 const color = C.GetOppCol(this.turn);
152 const kingPos = this.searchKingPos(color);
153 if (kingPos[0] < 0)
154 return (color == 'w' ? "0-1" : "1-0");
155 return "*";
156 }
157
158 postPlay(move) {
159 const color = this.turn;
160 if (this.subTurn == 2 || this.searchKingPos(color)[0] < 0) {
161 this.turn = C.GetOppCol(color);
162 this.movesCount++;
163 }
164 this.subTurn = 3 - this.subTurn;
165 }
166
167 };