First draft of Hex game
[xogo.git] / variants / Hex / class.js
1 // https://www.boardspace.net/hex/english/Rules%20-%20HexWiki.htm
2 export default class HexRules extends ChessRules {
3
4 static get Options() {
5 return {
6 input: [
7 {
8 label: "Board size",
9 type: "number",
10 defaut: 11,
11 variable: "bsize"
12 }
13 ],
14 check: [
15 {
16 label: "Swap",
17 defaut: true,
18 variable: "swap"
19 }
20 ]
21 };
22 }
23
24 get hasReserve() {
25 return false;
26 }
27
28 get noAnimate() {
29 return true;
30 }
31
32 doClick(coords) {
33 if (
34 this.board[coords.x][coords.y] != "" &&
35 (!this.swap || this.movesCount >= 2)
36 ) {
37 return null;
38 }
39 let res = new Move({
40 start: {x: coords.x, y: coords.y},
41 appear: [
42 new PiPo({
43 x: coords.x,
44 y: coords.y,
45 c: this.turn,
46 p: 'p'
47 })
48 ],
49 vanish: []
50 });
51 if (this.board[coords.x][coords.y] != "") {
52 res.vanish.push(
53 new PiPo({
54 x: coords.x,
55 y: coords.y,
56 c: C.GetOppCol(this.turn),
57 p: 'p'
58 })
59 );
60 }
61 return res;
62 }
63
64 genRandInitFen() {
65 // NOTE: size.x == size.y (square boards)
66 const emptyCount = C.FenEmptySquares(this.size.x.repeat);
67 return (emptyCount + "/").repeat(this.size.x).slice(0, -1);
68 }
69
70 getPieceWidth(rwidth) {
71 return (rwidth / this.size.y); //TODO
72 }
73
74 // TODO
75 getSvgChessboard() {
76 let board = `
77 <svg
78 width="2771.2px" height="1700px"
79 class="chessboard_SVG">
80 <defs>
81 <g id="hexa">
82 <polygon
83 style="fill:none;stroke:#000000;stroke-width:1px"
84 points="0,-100.0 86.6,-50.0 86.6,50.0 0,100.0 -86.6,50.0 -86.6,-50.0"
85 />
86 </g>
87 </defs>`;
88 for (let i=0; i < this.size.x; i++) {
89 for (let j=0; j < this.size.y; j++) {
90 let classes = this.getSquareColorClass(i, j);
91 board += `<rect
92 class="neutral-square"
93 id="${this.coordsToId([i, j])}"
94 width="10"
95 height="10"
96 x="${10*j}" ///////////// + resize ! ratio
97 y="${10*i}" />`;
98 }
99 }
100 board += "</g></svg>";
101 return board;
102 }
103
104 setupPieces() {
105 // TODO: just scan board and get IDs, and addClass "bg-white" or "bg-black"
106 }
107
108 // TODO (NOTE: no flip here, always same view)
109 getPixelPosition(i, j, r) {
110 if (i < 0 || j < 0)
111 return [0, 0]; //piece vanishes
112 let x, y;
113 const sqSize = r.width / this.size.y;
114 const flipped = (this.playerColor == 'b');
115 const x = (flipped ? this.size.y - 1 - j : j) * sqSize,
116 y = (flipped ? this.size.x - 1 - i : i) * sqSize;
117 return [r.x + x, r.y + y];
118 }
119
120 initMouseEvents() {
121 const mousedown = (e) => {
122 if (e.touches && e.touches.length > 1)
123 e.preventDefault();
124 const cd = this.idToCoords(e.target.id);
125 if (cd) {
126 const move = this.doClick(cd);
127 if (move)
128 this.playPlusVisual(move);
129 }
130 };
131
132 if ('onmousedown' in window)
133 document.addEventListener("mousedown", mousedown);
134 if ('ontouchstart' in window)
135 document.addEventListener("touchstart", mousedown, {passive: false});
136 }
137
138 get size() {
139 return {
140 x: this.bsize,
141 y: this.bsize,
142 ratio: 1.630118
143 };
144 }
145
146 pieces() {
147 return {
148 'p': {
149 "class": "pawn",
150 }
151 };
152 }
153
154 play(move) {
155 super.playOnBoard(move);
156 }
157
158 // TODO:
159 getCurrentScore(move) {
160 const oppCol = C.GetOppCol(this.turn);
161 // Search for connecting path of opp color: TODO
162 // ...
163 if (path found)
164 return (oppCol == "w" ? "1-0" : "0-1");
165 return "*";
166 }
167
168 playVisual(move) {
169 move.vanish.forEach(v => {
170 // TODO: just get ID, and remClass "bg-white" or "bg-black" (in CSS: TODO)
171 });
172 move.appear.forEach(a => {
173 // TODO: just get ID, and addClass "bg-white" or "bg-black" (in CSS: TODO)
174 // this.g_pieces[a.x][a.y] = document.createElement("piece");
175 // this.g_pieces[a.x][a.y].classList.add(this.pieces()[a.p]["class"]);
176 // this.g_pieces[a.x][a.y].classList.add(a.c == "w" ? "white" : "black");
177 // this.g_pieces[a.x][a.y].style.width = pieceWidth + "px";
178 // this.g_pieces[a.x][a.y].style.height = pieceWidth + "px";
179 });
180 }
181
182 };