@slugbugblue/trax 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/docs/point.md +2 -1
- package/package.json +1 -1
- package/src/analyst.js +67 -11
- package/src/cmds/analyze.js +1 -1
- package/src/point.js +10 -7
- package/src/version.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# @slugbugblue/trax
|
|
2
2
|
|
|
3
|
+
## 0.12.0 - 2022-10-28
|
|
4
|
+
|
|
5
|
+
- `point.in()` now accepts any two opposing corners to define the bounding box
|
|
6
|
+
- Fleshing out testing and debugging of `analyst.js`
|
|
7
|
+
|
|
3
8
|
## 0.11.0 - 2022-09-22
|
|
4
9
|
|
|
5
10
|
- Breaking change: Refactor `play()` and `playMove()` into a single function
|
package/docs/point.md
CHANGED
|
@@ -89,9 +89,10 @@ Returns the distance between two points. This will never be a negative number.
|
|
|
89
89
|
Returns `true` if the given point or point-like object is at the same location
|
|
90
90
|
as the existing point.
|
|
91
91
|
|
|
92
|
-
##### `in(
|
|
92
|
+
##### `in(a, b)`
|
|
93
93
|
|
|
94
94
|
Pass in two points (or point-like objects) to define a rectangular bounding box.
|
|
95
|
+
Each point represents opposite corners of the box.
|
|
95
96
|
|
|
96
97
|
Returns `true` if the calling point is located inside the box or along any of
|
|
97
98
|
its edges (ie, both bounding points are considered "inside").
|
package/package.json
CHANGED
package/src/analyst.js
CHANGED
|
@@ -21,6 +21,15 @@ import { Trax } from '@slugbugblue/trax'
|
|
|
21
21
|
import { threats } from '@slugbugblue/trax/threats.js'
|
|
22
22
|
|
|
23
23
|
// Helpers
|
|
24
|
+
const id = () => {
|
|
25
|
+
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
|
|
26
|
+
let code = ''
|
|
27
|
+
while (code.length < 6) {
|
|
28
|
+
code += chars[Math.floor(Math.random() * chars.length)]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return 'analysis-' + code
|
|
32
|
+
}
|
|
24
33
|
|
|
25
34
|
// Make parseInt Array.map()-friendly
|
|
26
35
|
const int = (s) => Number.parseInt(s, 10)
|
|
@@ -163,24 +172,28 @@ const threatCount = (from) =>
|
|
|
163
172
|
|
|
164
173
|
// Analysis class
|
|
165
174
|
export const Analysis = class {
|
|
175
|
+
#rules = 'trax'
|
|
176
|
+
#id = 'analysis'
|
|
177
|
+
#moves = []
|
|
178
|
+
#notation = ''
|
|
166
179
|
#edge = undefined
|
|
167
180
|
#game = {}
|
|
168
|
-
#move = 0
|
|
169
|
-
#save = {}
|
|
170
181
|
#scores = {}
|
|
171
182
|
#threats = undefined
|
|
172
183
|
|
|
173
184
|
constructor(game) {
|
|
174
185
|
// Make a copy of the game
|
|
175
|
-
this.#
|
|
176
|
-
this.#
|
|
177
|
-
this.#
|
|
186
|
+
this.#rules = game.rules
|
|
187
|
+
this.#moves = game.moves
|
|
188
|
+
this.#id = id()
|
|
189
|
+
this.#notation = game.notation
|
|
190
|
+
this.#game = new Trax(this.#rules, this.#moves, this.#id)
|
|
178
191
|
}
|
|
179
192
|
|
|
180
193
|
get game() {
|
|
181
194
|
// Return a fresh copy of the game as presented on init
|
|
182
|
-
if (this.#game.
|
|
183
|
-
this.#game = new Trax(
|
|
195
|
+
if (this.#game.notation !== this.#notation) {
|
|
196
|
+
this.#game = new Trax(this.#rules, this.#moves, this.#id)
|
|
184
197
|
}
|
|
185
198
|
|
|
186
199
|
return this.#game
|
|
@@ -217,7 +230,7 @@ export const Analysis = class {
|
|
|
217
230
|
|
|
218
231
|
for (const dir of Point.dirs) {
|
|
219
232
|
let look = loc.dir(dir)
|
|
220
|
-
while (look.in(topLeft, bottomRight) && !game.tileAt(
|
|
233
|
+
while (look.in(topLeft, bottomRight) && !game.tileAt(look)) {
|
|
221
234
|
look = look.dir(dir)
|
|
222
235
|
}
|
|
223
236
|
|
|
@@ -287,7 +300,7 @@ export const Analysis = class {
|
|
|
287
300
|
// c = in a cave but has no restrictions (converted to n in edge)
|
|
288
301
|
// C = a cave where some moves are not allowed (converted to c in edge)
|
|
289
302
|
// n = normal space
|
|
290
|
-
// x =
|
|
303
|
+
// x = no tile can be played here
|
|
291
304
|
spaceType(loc) {
|
|
292
305
|
const { game } = this
|
|
293
306
|
|
|
@@ -300,13 +313,25 @@ export const Analysis = class {
|
|
|
300
313
|
}
|
|
301
314
|
|
|
302
315
|
// Check to see if we have an invalid move
|
|
316
|
+
let someValid = false
|
|
317
|
+
let someInvalid = false
|
|
303
318
|
for (const tile of game.possibleTiles(loc)) {
|
|
304
319
|
const drop = game.dropTile(tile, loc, 'tentative')
|
|
305
|
-
if (
|
|
306
|
-
|
|
320
|
+
if (drop.valid) {
|
|
321
|
+
someValid = true
|
|
322
|
+
} else {
|
|
323
|
+
someInvalid = true
|
|
307
324
|
}
|
|
308
325
|
}
|
|
309
326
|
|
|
327
|
+
if (!someValid) {
|
|
328
|
+
return 'x'
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (someInvalid) {
|
|
332
|
+
return 'C'
|
|
333
|
+
}
|
|
334
|
+
|
|
310
335
|
return 'c'
|
|
311
336
|
}
|
|
312
337
|
|
|
@@ -390,6 +415,37 @@ export const Analysis = class {
|
|
|
390
415
|
|
|
391
416
|
return matches
|
|
392
417
|
}
|
|
418
|
+
|
|
419
|
+
// Make a reasonable inspect representation of the analysis
|
|
420
|
+
[Symbol.for('nodejs.util.inspect.custom')](depth, options, inspect) {
|
|
421
|
+
const sub = (object) => inspect(object, options).replace(/\n/g, '\n ')
|
|
422
|
+
const style = options.stylize
|
|
423
|
+
if (depth < 0) return style('<Analysis>', 'special')
|
|
424
|
+
if (options.depth !== null) options.depth -= 1
|
|
425
|
+
const tbd = style('tbd', 'undefined')
|
|
426
|
+
let custom = style('Analysis', 'special') + ' {\n'
|
|
427
|
+
custom += ' game: ' + style(this.#rules, 'special')
|
|
428
|
+
custom += '(' + style(this.#moves, 'string') + '),\n'
|
|
429
|
+
custom += ' edge: '
|
|
430
|
+
if (this.#edge) {
|
|
431
|
+
custom += '{\n w: ' + style(this.#edge.w, 'string')
|
|
432
|
+
custom += ',\n b: ' + style(this.#edge.b, 'string')
|
|
433
|
+
custom += ',\n edge: ' + style('[rawEdge]', 'special')
|
|
434
|
+
custom += '\n }'
|
|
435
|
+
} else {
|
|
436
|
+
custom += tbd
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
custom += ',\n threats: '
|
|
440
|
+
custom += this.#threats ? sub(this.#threats) : tbd
|
|
441
|
+
custom += ',\n scores: '
|
|
442
|
+
custom += 'w' in this.#scores ? sub(this.#scores) : tbd
|
|
443
|
+
custom += ',\n score: '
|
|
444
|
+
const score = 'w' in this.#scores ? this.score : null
|
|
445
|
+
custom += score === null ? tbd : style(score, 'number')
|
|
446
|
+
|
|
447
|
+
return custom + '\n}'
|
|
448
|
+
}
|
|
393
449
|
}
|
|
394
450
|
|
|
395
451
|
export const analyze = (game) => new Analysis(game)
|
package/src/cmds/analyze.js
CHANGED
|
@@ -40,7 +40,7 @@ const threatNames = {
|
|
|
40
40
|
const listThreats = (threats, detailed) => {
|
|
41
41
|
const summary = []
|
|
42
42
|
for (const level of Object.keys(threats || {})) {
|
|
43
|
-
const name = (threatNames[level] ||
|
|
43
|
+
const name = (threatNames[level] || `${level}-stage threats`) + ': '
|
|
44
44
|
const items = []
|
|
45
45
|
if (detailed) {
|
|
46
46
|
for (const item of threats[level]) {
|
package/src/point.js
CHANGED
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
|
|
16
16
|
const is = (v, s) => (typeof v).slice(0, 3) === s // Sigh
|
|
17
17
|
|
|
18
|
+
const between = (end1, mid, end2) => {
|
|
19
|
+
const low = Math.min(end1, end2)
|
|
20
|
+
const high = Math.max(end1, end2)
|
|
21
|
+
return low <= mid && mid <= high
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
// Are you tired of doing x,y movements in multiple statements? I am.
|
|
19
25
|
|
|
20
26
|
// Point: an immutable two-dimensional location (x,y)
|
|
@@ -102,13 +108,10 @@ export const Point = class {
|
|
|
102
108
|
return this.#x === that.x && this.#y === that.y
|
|
103
109
|
}
|
|
104
110
|
|
|
105
|
-
in(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.y >= topLeft.y &&
|
|
110
|
-
this.y <= bottomRight.y
|
|
111
|
-
)
|
|
111
|
+
in(a, b) {
|
|
112
|
+
// Allow for the bounding points to be passed in any order
|
|
113
|
+
// as long as they are opposite corners:
|
|
114
|
+
return between(a.x, this.x, b.x) && between(a.y, this.y, b.y)
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
// Play nicely with the rest of the world
|
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.12.0'
|