199a169b82a2c4404e697d7b7c299af401fe2f08
[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 genRandInitBaseFen() {
32 let fen = "";
33 if (this.options["randomness"] == 0)
34 fen = "rbqqbr/tcssct/6/6/TCSSCT/RBQQBR";
35 else {
36 const piece2pawn = {
37 r: 't',
38 q: 's',
39 b: 'c'
40 };
41 let pieces = { w: new Array(6), b: new Array(6) };
42 // Shuffle pieces on first (and last rank if randomness == 2)
43 for (let c of ["w", "b"]) {
44 if (c == 'b' && this.options["randomness"] == 1) {
45 pieces['b'] = pieces['w'];
46 break;
47 }
48 let positions = ArrayFun.range(6);
49 // Get random squares for bishops
50 let randIndex = 2 * Random.randInt(3);
51 const bishop1Pos = positions[randIndex];
52 let randIndex_tmp = 2 * Random.randInt(3) + 1;
53 const bishop2Pos = positions[randIndex_tmp];
54 positions.splice(Math.max(randIndex, randIndex_tmp), 1);
55 positions.splice(Math.min(randIndex, randIndex_tmp), 1);
56 // Get random square for queens
57 randIndex = Random.randInt(4);
58 const queen1Pos = positions[randIndex];
59 positions.splice(randIndex, 1);
60 randIndex = Random.randInt(3);
61 const queen2Pos = positions[randIndex];
62 positions.splice(randIndex, 1);
63 // Rooks positions are now fixed,
64 const rook1Pos = positions[0];
65 const rook2Pos = positions[1];
66 pieces[c][rook1Pos] = "r";
67 pieces[c][bishop1Pos] = "b";
68 pieces[c][queen1Pos] = "q";
69 pieces[c][queen2Pos] = "q";
70 pieces[c][bishop2Pos] = "b";
71 pieces[c][rook2Pos] = "r";
72 }
73 fen = (
74 pieces["b"].join("") + "/" +
75 pieces["b"].map(p => piece2pawn[p]).join("") +
76 "/6/6/" +
77 pieces["w"].map(p => piece2pawn[p].toUpperCase()).join("") + "/" +
78 pieces["w"].join("").toUpperCase()
79 );
80 }
81 return { fen: fen, o: {} };
82 }
83
84 // Triangles are rotated from opponent viewpoint (=> suffix "_inv")
85 pieces(color, x, y) {
86 const allSpecs = super.pieces(color, x, y);
87 return {
88 'r': allSpecs['r'],
89 'q': allSpecs['q'],
90 'b': Object.assign({}, allSpecs['b'],
91 {"class": "bishop" + (this.playerColor != color ? "_inv" : "")}),
92 's': { //"square"
93 "class": "babyrook",
94 moves: [
95 {
96 steps: [[0, 1], [0, -1], [1, 0], [-1, 0]],
97 range: 1
98 }
99 ]
100 },
101 'c': { //"circle"
102 "class": "babyqueen",
103 moves: [
104 {
105 steps: [
106 [0, 1], [0, -1], [1, 0], [-1, 0],
107 [1, 1], [1, -1], [-1, 1], [-1, -1]
108 ],
109 range: 1
110 }
111 ]
112 },
113 't': { //"triangle"
114 "class": "babybishop" + (this.playerColor != color ? "_inv" : ""),
115 moves: [
116 {
117 steps: [[1, 1], [1, -1], [-1, 1], [-1, -1]],
118 range: 1
119 }
120 ]
121 }
122 };
123 }
124
125 get size() {
126 return {
127 x: 6,
128 y: 6
129 };
130 }
131
132 filterValid(moves) {
133 return moves;
134 }
135
136 getCurrentScore() {
137 // Try both colors (to detect potential suicides)
138 let won = {};
139 for (let c of ['w', 'b']) {
140 const oppCol = C.GetOppCol(c);
141 const goal = (c == 'w' ? 0 : 5);
142 won[c] = this.board[goal].some((b,j) => {
143 return (
144 this.getColor(goal, j) == c &&
145 !this.findCapturesOn(
146 [goal, j],
147 {
148 one: true,
149 oppCol: oppCol,
150 segments: this.options["cylinder"]
151 }
152 )
153 );
154 });
155 }
156 if (won['w'] && won['b'])
157 return "?"; //no idea who won, not relevant anyway :)
158 return (won['w'] ? "1-0" : (won['b'] ? "0-1" : "*"));
159 }
160
161 };