Add Ambiguous. Fix a few issues with FEN generation / options
[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].c = 'a'; //a-color
60 m.appear[0].p = V.GOAL;
61 }
62 else {
63 m.appear[0].p = V.TARGET_CODE[m.vanish[1].p];
64 m.appear[0].c = oppCol;
65 }
66 m.vanish.shift();
67 return m;
68 })
69 );
70 }
71 // At subTurn == 1, play a targeted move for the opponent.
72 // Search for target (we could also have it in a stack...)
73 let target = {x: -1, y: -1};
74 outerLoop: for (let i = 0; i < this.size.x; i++) {
75 for (let j = 0; j < this.size.y; j++) {
76 if (this.board[i][j] != "") {
77 const piece = this.getPiece(i, j);
78 if (
79 piece == V.GOAL ||
80 Object.keys(V.TARGET_DECODE).includes(piece)
81 ) {
82 target = {x: i, y:j};
83 break outerLoop;
84 }
85 }
86 }
87 }
88 const moves = super.getPotentialMovesFrom([x, y], oppCol);
89 return moves.filter(m => m.end.x == target.x && m.end.y == target.y);
90 }
91
92 canIplay(x, y) {
93 const color = this.getColor(x, y);
94 return (
95 (this.subTurn == 1 && ![this.turn, this.playerColor].includes(color)) ||
96 (this.subTurn == 2 && super.canIplay(x, y))
97 );
98 }
99
100 // Code for empty square target
101 static get GOAL() {
102 return 'g';
103 }
104
105 static get TARGET_DECODE() {
106 return {
107 's': 'p',
108 't': 'q',
109 'u': 'r',
110 'o': 'n',
111 'c': 'b',
112 'l': 'k'
113 };
114 }
115
116 static get TARGET_CODE() {
117 return {
118 'p': 's',
119 'q': 't',
120 'r': 'u',
121 'n': 'o',
122 'b': 'c',
123 'k': 'l'
124 };
125 }
126
127 pieces(color, x, y) {
128 const targets = {
129 's': {"class": "target-pawn", moves: []},
130 'u': {"class": "target-rook", moves: []},
131 'o': {"class": "target-knight", moves: []},
132 'c': {"class": "target-bishop", moves: []},
133 't': {"class": "target-queen", moves: []},
134 'l': {"class": "target-king", moves: []}
135 };
136 return Object.assign(
137 { 'g': {"class": "target"} }, targets, super.pieces(color, x, y));
138 }
139
140 atLeastOneMove() {
141 // Since there are no checks this seems true (same as for Magnetic...)
142 return true;
143 }
144
145 filterValid(moves) {
146 return moves;
147 }
148
149 isKing(symbol) {
150 return ['k', 'l'].includes(symbol);
151 }
152
153 getCurrentScore() {
154 // This function is only called at subTurn 1
155 const color = C.GetOppCol(this.turn);
156 const kingPos = this.searchKingPos(color);
157 if (kingPos[0] < 0)
158 return (color == 'w' ? "0-1" : "1-0");
159 return "*";
160 }
161
162 postPlay(move) {
163 const color = this.turn;
164 if (this.subTurn == 2 || this.searchKingPos(color)[0] < 0) {
165 this.turn = C.GetOppCol(color);
166 this.movesCount++;
167 }
168 this.subTurn = 3 - this.subTurn;
169 }
170
171 };