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