483641334b0208537cd75c5968db5b9759ae1ece
[xogo.git] / variants / Alapo / class.js
1 import ChessRules from "/base_rules.js";
2 import {ArrayFun} from "/utils/array.js";
3 import {Random} from "/utils/alea.js";
4
5 export default class AlapoRules extends ChessRules {
6
7 static get Options() {
8 return {
9 select: C.Options.select,
10 styles: C.Options.styles.filter(s => s != "teleport")
11 };
12 }
13
14 get hasFlags() {
15 return false;
16 }
17 get hasEnpassant() {
18 return false;
19 }
20
21 getSvgChessboard() {
22 let board = super.getSvgChessboard().slice(0, -6);
23 // Add lines to delimitate goals
24 board += `
25 <line x1="0" y1="10" x2="60" y2="10" stroke="black" stroke-width="0.1"/>
26 <line x1="0" y1="50" x2="60" y2="50" stroke="black" stroke-width="0.1"/>
27 </svg>`;
28 return board;
29 }
30
31 genRandInitFen(seed) {
32 if (this.options["randomness"] == 0)
33 return "rbqqbr/tcssct/6/6/TCSSCT/RBQQBR w 0";
34
35 Random.setSeed(seed);
36
37 const piece2pawn = {
38 r: 't',
39 q: 's',
40 b: 'c'
41 };
42
43 let pieces = { w: new Array(6), b: new Array(6) };
44 // Shuffle pieces on first (and last rank if randomness == 2)
45 for (let c of ["w", "b"]) {
46 if (c == 'b' && this.options["randomness"] == 1) {
47 pieces['b'] = pieces['w'];
48 break;
49 }
50
51 let positions = ArrayFun.range(6);
52
53 // Get random squares for bishops
54 let randIndex = 2 * Random.randInt(3);
55 const bishop1Pos = positions[randIndex];
56 let randIndex_tmp = 2 * Random.randInt(3) + 1;
57 const bishop2Pos = positions[randIndex_tmp];
58 positions.splice(Math.max(randIndex, randIndex_tmp), 1);
59 positions.splice(Math.min(randIndex, randIndex_tmp), 1);
60
61 // Get random square for queens
62 randIndex = Random.randInt(4);
63 const queen1Pos = positions[randIndex];
64 positions.splice(randIndex, 1);
65 randIndex = Random.randInt(3);
66 const queen2Pos = positions[randIndex];
67 positions.splice(randIndex, 1);
68
69 // Rooks positions are now fixed,
70 const rook1Pos = positions[0];
71 const rook2Pos = positions[1];
72
73 pieces[c][rook1Pos] = "r";
74 pieces[c][bishop1Pos] = "b";
75 pieces[c][queen1Pos] = "q";
76 pieces[c][queen2Pos] = "q";
77 pieces[c][bishop2Pos] = "b";
78 pieces[c][rook2Pos] = "r";
79 }
80
81 return (
82 pieces["b"].join("") + "/" +
83 pieces["b"].map(p => piece2pawn[p]).join("") +
84 "/6/6/" +
85 pieces["w"].map(p => piece2pawn[p].toUpperCase()).join("") + "/" +
86 pieces["w"].join("").toUpperCase() +
87 " w 0"
88 );
89 }
90
91 // Triangles are rotated from opponent viewpoint (=> suffix "_inv")
92 pieces(color, x, y) {
93 const allSpecs = super.pieces(color, x, y);
94 return {
95 'r': allSpecs['r'],
96 'q': allSpecs['q'],
97 'b': Object.assign({}, allSpecs['b'],
98 {"class": "bishop" + (this.playerColor != color ? "_inv" : "")}),
99 's': { //"square"
100 "class": "babyrook",
101 moves: [
102 {
103 steps: [[0, 1], [0, -1], [1, 0], [-1, 0]],
104 range: 1
105 }
106 ]
107 },
108 'c': { //"circle"
109 "class": "babyqueen",
110 moves: [
111 {
112 steps: [
113 [0, 1], [0, -1], [1, 0], [-1, 0],
114 [1, 1], [1, -1], [-1, 1], [-1, -1]
115 ],
116 range: 1
117 }
118 ]
119 },
120 't': { //"triangle"
121 "class": "babybishop" + (this.playerColor != color ? "_inv" : ""),
122 moves: [
123 {
124 steps: [[1, 1], [1, -1], [-1, 1], [-1, -1]],
125 range: 1
126 }
127 ]
128 }
129 };
130 }
131
132 get size() {
133 return {
134 x: 6,
135 y: 6
136 };
137 }
138
139 filterValid(moves) {
140 return moves;
141 }
142
143 getCurrentScore() {
144 // Try both colors (to detect potential suicides)
145 let won = {};
146 for (let c of ['w', 'b']) {
147 const oppCol = C.GetOppCol(c);
148 const goal = (c == 'w' ? 0 : 5);
149 won[c] = this.board[goal].some((b,j) => {
150 return (
151 this.getColor(goal, j) == c &&
152 !this.findCapturesOn(
153 [goal, j],
154 {
155 one: true,
156 oppCol: oppCol,
157 segments: this.options["cylinder"]
158 }
159 )
160 );
161 });
162 }
163 if (won['w'] && won['b'])
164 return "?"; //no idea who won, not relevant anyway :)
165 return (won['w'] ? "1-0" : (won['b'] ? "0-1" : "*"));
166 }
167
168 };