-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdefault_board.js
147 lines (109 loc) · 3.39 KB
/
default_board.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'use strict';
//
// The default star shaped chinese checkers board.
//
class DefaultBoard extends GameBoard {
// Construct a default game board given a canvas size {x, y}.
constructor(canvasSize) {
// Adjust sizes to fit the board in the given height
const approxNumHolesInHeight = 15;
let minSize = Math.min(canvasSize.x, canvasSize.y);
let step = minSize / approxNumHolesInHeight;
let holeSize = 0.85 * 0.5 * step;
super(canvasSize, step, holeSize);
}
// Returns a list of indices for the start location holes for a player p. For now max 2 players are supported
startHolesForPlayer(p) {
console.assert(p >= 0 && p < 2);
const starts = [
[81, 82, 83, 84, 85, 86, 87, 88, 89, 90],
[120, 119, 118, 117, 116, 115, 114, 113, 112, 111],
];
const debugStarts = [
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[77, 82, 83, 78, 85, 86, 87, 88, 89, 90]
];
return starts[p];
}
// Returns a list of indices for the goal location holes for a player p. For now max 2 players are supported
goalHolesForPlayer(p) {
console.assert(p >= 0 && p < 2);
const goals = [
[120, 119, 118, 117, 116, 115, 114, 113, 112, 111],
[81, 82, 83, 84, 85, 86, 87, 88, 89, 90]
]
return goals[p];
}
// Returns a single index for a hole that is a target location for a player p. This could for example be used
// as a target to optimize the distance of marbles to, such as when evaluating a state for minimax.
targetLocationIndexForPlayer(p) {
console.assert(p >= 0 && p < 2);
// Indices of the tips of the triangles where each player needs to get to
const targets = [120, 90];
return targets[p];
}
///////////////////////////////////////
// Hole location creation stuff below
_createHoleLocations(step) {
// Default star can be seen as two overlayed triangles, one rotated 180 degrees
let t1 = this._createTriangle(step);
// Create rotated copy
let t2 = [];
for (let pos of t1) {
t2.push({
x: pos.x * Math.cos(Math.PI) - pos.y * Math.sin(Math.PI),
y: pos.y * Math.cos(Math.PI) + pos.x * Math.sin(Math.PI)
});
}
// Add non-overlapping holes from t2 to the list of locations/holes
const overlapThreshold = 0.5;
let locations = t1;
for (let pos of t2) {
if (this._canAddPositionToBoard(pos, locations, overlapThreshold)) {
locations.push(pos);
}
}
// Offset locations to center of canvas
for (let i = 0; i < locations.length; ++i) {
locations[i].x += 0.5 * this.canvasSize.x;
locations[i].y += 0.5 * this.canvasSize.y;
}
return locations;
}
_canAddPositionToBoard(pos, board, threshold){
for (let i = 0; i < board.length; i++){
let dx = pos.x - board[i].x;
let dy = pos.y - board[i].y;
if (Math.sqrt(dx * dx + dy * dy) < threshold) {
return false;
}
}
return true;
}
_createTriangle(step) {
let positions = [];
let pointer = {x: 0, y:0};
let rowLength = 13;
let xSum = 0;
let ySum = 0;
while (rowLength > 0){
for (let i = 0; i < rowLength; i++) {
positions.push({x: pointer.x, y: pointer.y});
xSum += pointer.x;
ySum += pointer.y;
pointer.x += step;
}
pointer.x -= rowLength * step;
pointer.x += step/2;
pointer.y += Math.sqrt(3 / 4) * step;
rowLength -= 1;
}
let averageX = xSum / positions.length;
let averageY = ySum / positions.length;
for (let i = 0; i < positions.length; i++){
positions[i].x -= averageX;
positions[i].y -= averageY;
}
return positions;
}
}