Add Avalanche, write Avalam rules
[xogo.git] / variants / Avalam / class.js
1 import ChessRules from "/base_rules.js";
2 import {Random} from "/utils/alea.js";
3 import PiPo from "/utils/PiPo.js";
4 import Move from "/utils/Move.js";
5
6 export default class AvalamRules extends ChessRules {
7
8 static get Options() {
9 return {
10 select: [{
11 label: "Randomness",
12 variable: "randomness",
13 defaut: 1,
14 options: [
15 {label: "Deterministic", value: 0},
16 {label: "Random", value: 1},
17 ]
18 }],
19 input: [
20 {
21 label: "Free placement",
22 variable: "freefill",
23 type: "checkbox",
24 defaut: false
25 }
26 ]
27 };
28 }
29
30 get hasFlags() {
31 return false;
32 }
33 get hasEnpassant() {
34 return false;
35 }
36
37 pieces(color, x, y) {
38 const steps = [
39 [1, 0], [0, 1], [-1, 0], [0, -1],
40 [1, 1], [1, -1], [-1, 1], [-1, -1]
41 ];
42 return {
43 'b': {
44 "class": "stack",
45 moves: [{steps: steps, range: 1}]
46 },
47 'c': {
48 "class": "stack2",
49 moveas: 'b'
50 },
51 'd': {
52 "class": "stack3",
53 moveas: 'b'
54 },
55 'e': {
56 "class": "stack4",
57 moveas: 'b'
58 },
59 'f': {
60 "class": "stack5",
61 moveas: 'b'
62 }
63 };
64 }
65
66 genRandInitBaseFen() {
67 let fen = "";
68 if (this.freefill)
69 fen = "9/".repeat(8) + "9 w 0";
70 else if (this.options["randomness"] == 0) {
71 fen = "2Bb5/1BbBb4/1bBbBbB2/1BbBbBbBb/BbBb1bBbB/" +
72 "bBbBbBbB1/2BbBbBb1/4bBbB1/5bB2 w 0";
73 }
74 else {
75 const pieces = ('B'.repeat(24) + 'b'.repeat(24)).split("");
76 const a = Random.shuffle(pieces, 48).join("");
77 fen = (
78 "2" + a.substr(0, 2) + "5/1" + a.substr(2, 4) +
79 "4/1" + a.substr(6, 6) + "2/1" + a.substr(12, 8) +
80 "/" + a.substr(20, 4) + "1" + a.substr(24, 4) +
81 "/" + a.substr(28, 8) + "1/2" + a.substr(36, 6) +
82 "1/4" + a.substr(42, 4) + "1/5" + a.substr(46, 2) +
83 "2 w 0"
84 );
85 }
86 return { fen: fen, o: {} };
87 }
88
89 getSquareColorClass(x, y) {
90 return "board-sq";
91 }
92
93 get size() {
94 return {x: 9, y: 9};
95 }
96
97 onBoard(x, y) {
98 if (!super.onBoard(x, y))
99 return false;
100 switch (x) {
101 case 0:
102 return [2, 3].includes(y);
103 case 1:
104 return [1, 2, 3, 4].includes(y);
105 case 2:
106 return [1, 2, 3, 4, 5, 6].includes(y);
107 case 3:
108 return y >= 1;
109 case 4:
110 return y != 4;
111 case 5:
112 return y <= 7;
113 case 6:
114 return [2, 3, 4, 5, 6, 7].includes(y);
115 case 7:
116 return [4, 5, 6, 7].includes(y);
117 case 8:
118 return [5, 6].includes(y);
119 }
120 return false; //never reached
121 }
122
123 canIplay() {
124 return this.playerColor == this.turn;
125 }
126
127 doClick(coords) {
128 if (!this.freefill || this.board[coords.x][coords.y] != "")
129 return null;
130 return new Move({
131 start: {x: coords.x, y: coords.y},
132 vanish: [],
133 appear: [new PiPo({x: coords.x, y: coords.y, c: this.turn, p: 'b'})]
134 });
135 }
136
137 getBasicMove([x1, y1], [x2, y2]) {
138 const cp1 = this.board[x1][y1],
139 cp2 = this.board[x2][y2];
140 const newPiece =
141 String.fromCharCode(cp1.charCodeAt(1) + cp2.charCodeAt(1) - 97);
142 return (
143 new Move({
144 vanish: [
145 new PiPo({ x: x1, y: y1, c: cp1.charAt(0), p: cp1.charAt(1) }),
146 new PiPo({ x: x2, y: y2, c: cp2.charAt(0), p: cp2.charAt(1) })
147 ],
148 appear: [
149 new PiPo({ x: x2, y: y2, c: cp1.charAt(0), p: newPiece })
150 ]
151 })
152 );
153 }
154
155 getPotentialMovesFrom([x, y]) {
156 const height = this.board[x][y].charCodeAt(1) - 97;
157 if (height == 5)
158 return [];
159 let moves = [];
160 for (let s of this.pieces()['b'].moves[0].steps) {
161 const [i, j] = [x + s[0], y + s[1]];
162 if (
163 this.onBoard(i, j) &&
164 this.board[i][j] != "" &&
165 (height + this.board[i][j].charCodeAt(1) - 97 <= 5)
166 ) {
167 moves.push(this.getBasicMove([x, y], [i, j]));
168 }
169 }
170 return moves;
171 }
172
173 filterValid(moves) {
174 return moves;
175 }
176
177 getCurrentScore() {
178 let towersCount = {w: 0, b: 0};
179 for (let i = 0; i < this.size.x; i++) {
180 for (let j = 0; j < this.size.y; j++) {
181 if (this.board[i][j] != "") {
182 if (this.getPotentialMovesFrom([i, j]).length > 0)
183 return '*';
184 towersCount[ this.board[i][j][0] ]++;
185 }
186 }
187 }
188 if (towersCount['w'] > towersCount['b'])
189 return "1-0";
190 if (towersCount['b'] > towersCount['w'])
191 return "0-1";
192 return "1/2";
193 }
194
195 };