-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstate.js
More file actions
116 lines (95 loc) · 2.53 KB
/
state.js
File metadata and controls
116 lines (95 loc) · 2.53 KB
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
goog.provide('soko.State');
goog.require('soko.types.GridPoint');
goog.scope(function() {
/**
* @typedef {number|string}
*/
soko.StateId;
/**
* @param {!soko.types.GridPoint} pos
* @param {!soko.types.GridPointArray} boxes
* @constructor
*/
soko.State = function(pos, boxes) {
/** @type {!soko.types.GridPoint} */
this.pos = [pos[0], pos[1]];
/** @type {!soko.types.GridPointArray} */
this.boxes = boxes.map(function(x) {
return x;
});
};
var State = soko.State;
/**
* Maximum width (and height) of the indexable board points.
* This is used when packing the grid points and the state.
* @const {number}
*/
State.MAX_WIDTH = 8; // 2^6
/**
* Number of bits required to pack a grid point.
* @const {number}
*/
State.NBITS = 6; // Should be log2(MAX_WIDTH^2);
/**
* Converts a point to a single index number.
* @param {!soko.types.GridPoint} pos
* @return {number}
*/
State.pointToIndex = function(pos) {
return (pos[1] - 1) * State.MAX_WIDTH + (pos[0] - 1);
};
/**
* Creates an state abstraction using the slice from start to end.
* @param {number} start
* @param {number} end
* @return {!soko.State}
*/
State.prototype.createAbstraction = function(start, end) {
return new State(this.pos, this.boxes.slice(start, end));
};
/**
* Packs the state into a compact integer representation.
* @return {soko.StateId}
*/
State.prototype.pack = function() {
var sorted = this.boxes.sort(function(a, b) {
return State.pointToIndex(b) - State.pointToIndex(a);
});
var value = State.pointToIndex(this.pos);
var top = Math.min(sorted.length, 4);
for (var i = 0; i < top; i++) {
value += State.pointToIndex(sorted[i]) << ((i + 1) * State.NBITS);
}
if (sorted.length <= 4) {
return value;
}
// TODO(birkbeck): handle case with more than 10 boxes.
var hex = value.toString(16);
value = 0;
for (var i = top; i < sorted.length; ++i) {
value += State.pointToIndex(sorted[i]) << ((i - top) * State.NBITS);
}
return hex + "," + value.toString(16);
};
/**
* Gets the block index for the given grid point. Returns -1 if there
* is nothing at the given point.
* @param {!soko.types.GridPoint} pos
* @return {number}
*/
State.prototype.getBlockIndex = function(pos) {
for (var i = 0; i < this.boxes.length; i++) {
if (this.boxes[i][0] == pos[0] && this.boxes[i][1] == pos[1]) {
return i;
}
}
return -1;
};
/**
* Gets a unique id for this state. Used for keeping track of visibility.
* @return {soko.StateId}
*/
State.prototype.id = function() {
return this.pack();
};
});