Add Alice Chess, fix a few things in base_rules.js
[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 // 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], {one: true, oppCol: oppCol}).length == 0
147 );
148 });
149 }
150 if (won['w'] && won['b'])
151 return "?"; //no idea who won, not relevant anyway :)
152 return (won['w'] ? "1-0" : (won['b'] ? "0-1" : "*"));
153 }
154
155 };