@slugbugblue/trax 0.21.0 → 0.23.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 +23 -6
- package/README.md +9 -175
- package/docs/engine.md +1 -1
- package/package.json +12 -23
- package/src/engine.js +128 -52
- package/src/types.d.ts +23 -131
- package/src/version.js +1 -1
- package/.dockerignore +0 -11
- package/Dockerfile +0 -14
- package/docs/analyst.md +0 -236
- package/docs/lru.md +0 -151
- package/docs/point.md +0 -148
- package/src/analyst.js +0 -858
- package/src/cli.js +0 -732
- package/src/cmds/analyze.js +0 -112
- package/src/cmds/delete.js +0 -71
- package/src/cmds/help.js +0 -81
- package/src/cmds/import-export.js +0 -394
- package/src/cmds/list.js +0 -177
- package/src/cmds/new.js +0 -136
- package/src/cmds/notes.js +0 -37
- package/src/cmds/play-try.js +0 -175
- package/src/cmds/puzzles.js +0 -188
- package/src/cmds/select.js +0 -47
- package/src/cmds/suggest.js +0 -55
- package/src/cmds/undo.js +0 -40
- package/src/cmds/view.js +0 -65
- package/src/lru.js +0 -153
- package/src/point.js +0 -173
- package/src/puzzles.js +0 -1236
- package/src/threats.js +0 -223
- package/src/tty.js +0 -317
- package/src/utils.js +0 -22
package/src/engine.js
CHANGED
|
@@ -1,37 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* You may obtain a copy of the License at
|
|
6
|
-
*
|
|
7
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
*
|
|
9
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
* See the License for the specific language governing permissions and
|
|
13
|
-
* limitations under the License.
|
|
1
|
+
/** Trax engine.
|
|
2
|
+
* @copyright 2019-2022
|
|
3
|
+
* @author Chad Transtrum <chad@transtrum.net>
|
|
4
|
+
* @license Apache-2.0
|
|
14
5
|
*/
|
|
15
6
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
// Tile type names are determined by listing the line color at each edge,
|
|
19
|
-
// starting from the top and going clockwise, and then sorted alphabetically
|
|
20
|
-
// and given a single letter name, so 'bbww' becomes 'a', which gives us six
|
|
21
|
-
// different tile names: a-f
|
|
7
|
+
import { Point } from '@slugbugblue/point'
|
|
22
8
|
|
|
23
|
-
import { Point } from '@slugbugblue/trax/point'
|
|
24
|
-
|
|
25
|
-
// Type definitions
|
|
26
9
|
// Fun trax helper constants
|
|
27
10
|
|
|
28
11
|
const zero = new Point(0, 0)
|
|
29
12
|
const moveNumberRegex = /^(\d+)[.):]?$/
|
|
30
13
|
const notationRegex = /^([@a-z]+)(\d+)([/\\+])$/i
|
|
31
14
|
|
|
32
|
-
/** @type ValidTiles[] */
|
|
33
|
-
const tileTypes = ['a', 'b', 'c', 'd', 'e', 'f']
|
|
34
|
-
|
|
35
15
|
/** Tiles are represented by the letters a-f.
|
|
36
16
|
* a b c d e f
|
|
37
17
|
* +--#--+ +--#--+ +--#--+ +--o--+ +--o--+ +--o--+
|
|
@@ -40,7 +20,14 @@ const tileTypes = ['a', 'b', 'c', 'd', 'e', 'f']
|
|
|
40
20
|
* | o | | # | | o | | # | | o | | # |
|
|
41
21
|
* +--o--+ +--#--+ +--o--+ +--#--+ +--o--+ +--#--+
|
|
42
22
|
*
|
|
43
|
-
*
|
|
23
|
+
* @readonly
|
|
24
|
+
* @type ValidTiles[]
|
|
25
|
+
* */
|
|
26
|
+
const tileTypes = ['a', 'b', 'c', 'd', 'e', 'f']
|
|
27
|
+
|
|
28
|
+
/** Slashes indicate the direction the tile is placed. A forward slash or a
|
|
29
|
+
* backslash indicate the tile is a "curve" and the plus sign indicates the
|
|
30
|
+
* tile is a "straight".
|
|
44
31
|
* @readonly
|
|
45
32
|
* @type {Record<ValidTiles, Slash>}
|
|
46
33
|
*/
|
|
@@ -201,10 +188,10 @@ export class Trax {
|
|
|
201
188
|
// Trax class constructor
|
|
202
189
|
/** Create a new Trax game
|
|
203
190
|
* @arg {TraxVariant} [rules='trax'] - the variant to play
|
|
204
|
-
* @arg {string|string[]} [moves=
|
|
191
|
+
* @arg {string|string[]} [moves=''] - the initial moves to pre-play
|
|
205
192
|
* @arg {string} [id='trax'] - an id used to differentiate tiles from multiple games
|
|
206
193
|
*/
|
|
207
|
-
constructor(rules = 'trax', moves =
|
|
194
|
+
constructor(rules = 'trax', moves = '', id = 'trax') {
|
|
208
195
|
if (!Trax.variants.has(rules)) rules = 'trax'
|
|
209
196
|
this.id = String(id)
|
|
210
197
|
this.rules = rules
|
|
@@ -252,7 +239,6 @@ export class Trax {
|
|
|
252
239
|
/** Restore a previously saved position.
|
|
253
240
|
* @arg {SaveState} saved - the previously saved state
|
|
254
241
|
* @see save for saving the state
|
|
255
|
-
* @returns {void}
|
|
256
242
|
*/
|
|
257
243
|
restore(saved) {
|
|
258
244
|
// So we need to be able to restore it when we are done
|
|
@@ -316,6 +302,7 @@ export class Trax {
|
|
|
316
302
|
*/
|
|
317
303
|
addTile(type, loc) {
|
|
318
304
|
const id = this.tileId(loc)
|
|
305
|
+
/** @type {Tile} */
|
|
319
306
|
const tile = { type, loc, id, move: this.move, seq: this.count }
|
|
320
307
|
if (type === 'x') {
|
|
321
308
|
this.invalid = true // Invalid tile is being played
|
|
@@ -339,7 +326,7 @@ export class Trax {
|
|
|
339
326
|
}
|
|
340
327
|
|
|
341
328
|
/** Is this tile valid?
|
|
342
|
-
* @type {(type: string, loc: Point) => type is
|
|
329
|
+
* @type {(type: string, loc: Point) => type is ValidTiles}
|
|
343
330
|
*/
|
|
344
331
|
validTile(type, loc) {
|
|
345
332
|
if (this.count === 0 && loc.x === 0 && loc.y === 0) {
|
|
@@ -382,6 +369,10 @@ export class Trax {
|
|
|
382
369
|
return this.right - this.left + 1
|
|
383
370
|
}
|
|
384
371
|
|
|
372
|
+
/** Determine if a location is valid to play in.
|
|
373
|
+
* @arg {Point} loc - the location to check
|
|
374
|
+
* @returns {boolean}
|
|
375
|
+
*/
|
|
385
376
|
validLocation(loc) {
|
|
386
377
|
if (this.over) return false
|
|
387
378
|
if (this.tileAt(loc)) return false
|
|
@@ -403,26 +394,31 @@ export class Trax {
|
|
|
403
394
|
return false
|
|
404
395
|
}
|
|
405
396
|
|
|
397
|
+
/** Find all possible locations to play in. Note that these are not
|
|
398
|
+
* necessarily valid locations, just empty ones that border existing tiles.
|
|
399
|
+
*/
|
|
406
400
|
possibleLocations() {
|
|
407
401
|
if (this.count === 0) return [zero]
|
|
408
402
|
/** @type Record<TileId, Point> */
|
|
409
403
|
const possibles = {}
|
|
410
404
|
|
|
411
405
|
for (const tile of Object.values(this.tiles)) {
|
|
412
|
-
tile.loc.around
|
|
406
|
+
for (const loc of tile.loc.around) {
|
|
413
407
|
const id = this.tileId(loc)
|
|
414
408
|
if (!(id in this.tiles)) possibles[id] = loc
|
|
415
|
-
|
|
416
|
-
})
|
|
409
|
+
}
|
|
417
410
|
}
|
|
418
411
|
|
|
419
|
-
// Get rid of all the real tiles and return all the maybes
|
|
420
412
|
return Object.values(possibles)
|
|
421
413
|
}
|
|
422
414
|
|
|
415
|
+
/** Find all possible moves as a list of notations,
|
|
416
|
+
* ie: ['@1+', '@1/', '@1\\', ...]
|
|
417
|
+
*
|
|
418
|
+
* Note that moves are not guaranteed to be valid.
|
|
419
|
+
*/
|
|
423
420
|
possibleMoves() {
|
|
424
|
-
|
|
425
|
-
// as notations, ie ['@1+', '@1/', '@1\\', ...]
|
|
421
|
+
/** @type {string[]} */
|
|
426
422
|
const possibles = []
|
|
427
423
|
if (this.over) return possibles // Shortcut if the game is over
|
|
428
424
|
for (const loc of this.possibleLocations()) {
|
|
@@ -435,9 +431,14 @@ export class Trax {
|
|
|
435
431
|
return possibles
|
|
436
432
|
}
|
|
437
433
|
|
|
434
|
+
/** Called after a move was just played, to determine the forced moves.
|
|
435
|
+
* @arg {Point} loc - the location just played at
|
|
436
|
+
* @returns {Tile[]} a list of tiles that should be added as part of the move
|
|
437
|
+
*/
|
|
438
438
|
forcedMoves(loc) {
|
|
439
|
-
|
|
439
|
+
/** @type {Tile[]} */
|
|
440
440
|
const forced = []
|
|
441
|
+
/** @type {Record<string, boolean>} */
|
|
441
442
|
const invalids = {}
|
|
442
443
|
let check = loc.around
|
|
443
444
|
while (check.length > 0) {
|
|
@@ -460,16 +461,26 @@ export class Trax {
|
|
|
460
461
|
return forced
|
|
461
462
|
}
|
|
462
463
|
|
|
464
|
+
/** Determine the notation for a move. Note that this must be determined
|
|
465
|
+
* BEFORE the move is placed on the board.
|
|
466
|
+
* @arg {ValidTiles} type - the tile placed on the board
|
|
467
|
+
* @arg {Point} loc - the location the tile is placed
|
|
468
|
+
* @returns {string} the notation of the move
|
|
469
|
+
*/
|
|
463
470
|
notate(type, loc) {
|
|
464
|
-
// Notation depends on the position of the board BEFORE the move
|
|
465
471
|
let notation = Trax.encodeCol(loc.x - this.left + 1)
|
|
466
472
|
notation += String(loc.y - this.top + 1)
|
|
467
473
|
notation += slash[type]
|
|
468
474
|
return notation
|
|
469
475
|
}
|
|
470
476
|
|
|
477
|
+
/** Turn a move notation into a tile type and location.
|
|
478
|
+
* @arg {string} notation - a notation for a single move to be played at
|
|
479
|
+
* the current board position
|
|
480
|
+
* @returns {RawMove} the tile type and location of the move
|
|
481
|
+
*/
|
|
471
482
|
decodeNotation(notation) {
|
|
472
|
-
|
|
483
|
+
/** @type {RawMove} */
|
|
473
484
|
const bad = { type: 'x', loc: zero }
|
|
474
485
|
const match = notation.match(notationRegex)
|
|
475
486
|
if (match === null) return bad
|
|
@@ -482,6 +493,14 @@ export class Trax {
|
|
|
482
493
|
return bad
|
|
483
494
|
}
|
|
484
495
|
|
|
496
|
+
/** Follow a color from one location through one or more tiles to the other
|
|
497
|
+
* end of the color line.
|
|
498
|
+
* @arg {Color} color - the color to follow
|
|
499
|
+
* @arg {Point} loc - the location to start
|
|
500
|
+
* @arg {string} from - the edge of the tile to start from
|
|
501
|
+
* @returns {LineEnd} the ending location and a list of the tile ids the path
|
|
502
|
+
* takes to get there.
|
|
503
|
+
*/
|
|
485
504
|
follow(color, loc, from) {
|
|
486
505
|
const path = []
|
|
487
506
|
let id = this.tileId(loc)
|
|
@@ -509,7 +528,13 @@ export class Trax {
|
|
|
509
528
|
return { loc, path }
|
|
510
529
|
}
|
|
511
530
|
|
|
531
|
+
/** Given a tile and a color, follow the line for that color to each end.
|
|
532
|
+
* @arg {Color} color - the color of ends of interest
|
|
533
|
+
* @arg { Point} loc - the location of the tile of interest
|
|
534
|
+
* @returns {LineEnd[]} a list of two items, each one end of the line
|
|
535
|
+
*/
|
|
512
536
|
findEnds(color, loc) {
|
|
537
|
+
/** @type {LineEnd[]} */
|
|
513
538
|
const ends = []
|
|
514
539
|
const tile = this.tileAt(loc)
|
|
515
540
|
if (upColor(tile) === color) ends.push(this.follow(color, loc, 'top'))
|
|
@@ -519,6 +544,11 @@ export class Trax {
|
|
|
519
544
|
return ends
|
|
520
545
|
}
|
|
521
546
|
|
|
547
|
+
/** Determine if a given line ends the game.
|
|
548
|
+
* @arg {Point} locA - one end of the line
|
|
549
|
+
* @arg {Point} locB - the other end of the line
|
|
550
|
+
* @returns {boolean} - true if this line wins the game
|
|
551
|
+
*/
|
|
522
552
|
lineWin(locA, locB) {
|
|
523
553
|
if (this.rules === 'traxloop') return false
|
|
524
554
|
if (this.width > 7 && locA.distX(locB) > this.width) return true
|
|
@@ -526,6 +556,9 @@ export class Trax {
|
|
|
526
556
|
return false
|
|
527
557
|
}
|
|
528
558
|
|
|
559
|
+
/** Determine if the game has ended.
|
|
560
|
+
* @arg {Tile[]} tiles - a list of the tiles placed during the last move.
|
|
561
|
+
*/
|
|
529
562
|
checkWin(tiles) {
|
|
530
563
|
/** @type {Color|false} */
|
|
531
564
|
let winner = false
|
|
@@ -534,13 +567,13 @@ export class Trax {
|
|
|
534
567
|
if (winner) continue // Skip the second player if the first has won
|
|
535
568
|
for (const tile of tiles) {
|
|
536
569
|
if (winner) continue // Skip the remaining tiles once we find a win
|
|
537
|
-
const
|
|
538
|
-
if (
|
|
570
|
+
const [end1, end2] = this.findEnds(color, tile.loc)
|
|
571
|
+
if (end1.loc.eq(end2.loc)) {
|
|
539
572
|
winner = color // Loop win
|
|
540
|
-
this.path =
|
|
541
|
-
} else if (this.lineWin(
|
|
573
|
+
this.path = end1.path // Both paths are essentially the same
|
|
574
|
+
} else if (this.lineWin(end1.loc, end2.loc)) {
|
|
542
575
|
winner = color // Line win, paths need to be combined
|
|
543
|
-
this.path = [...
|
|
576
|
+
this.path = [...end1.path.reverse(), ...end2.path.slice(1)]
|
|
544
577
|
}
|
|
545
578
|
}
|
|
546
579
|
}
|
|
@@ -581,6 +614,11 @@ export class Trax {
|
|
|
581
614
|
return this.dropTile(notation)
|
|
582
615
|
}
|
|
583
616
|
|
|
617
|
+
/** Play one or more moves.
|
|
618
|
+
* @arg {string|string[]} moves - the list of moves, provided either as a
|
|
619
|
+
* space-separated string of notations, or as a list of notations. Move
|
|
620
|
+
* numbers are optional, but if provided will be checked for accuracy.
|
|
621
|
+
*/
|
|
584
622
|
playMoves(moves) {
|
|
585
623
|
// Play one or more moves, from a string or a list of moves
|
|
586
624
|
// If move numbers are included, ensure they are accurate
|
|
@@ -608,6 +646,9 @@ export class Trax {
|
|
|
608
646
|
}
|
|
609
647
|
}
|
|
610
648
|
|
|
649
|
+
/** Add the current move notation to the notation string
|
|
650
|
+
* @arg {string} notation - the notation of the current move
|
|
651
|
+
*/
|
|
611
652
|
updateNotation(notation) {
|
|
612
653
|
this.move++
|
|
613
654
|
let note = this.move + '. ' + notation
|
|
@@ -628,7 +669,7 @@ export class Trax {
|
|
|
628
669
|
}
|
|
629
670
|
|
|
630
671
|
/** Drop a tile onto the board. This is a lower level call. Use play() if possible instead.
|
|
631
|
-
* @arg {string|
|
|
672
|
+
* @arg {string|ValidTiles} type - a special move, a tile type, or a notation
|
|
632
673
|
* @arg {Point} [loc] - a location if type is a tile type
|
|
633
674
|
* @arg {string|boolean} [tentative] - if truthy, the move will not be saved
|
|
634
675
|
* @returns {TileDrop} an object representing the results of the drop
|
|
@@ -678,6 +719,11 @@ export class Trax {
|
|
|
678
719
|
return { dropped, notation, valid }
|
|
679
720
|
}
|
|
680
721
|
|
|
722
|
+
/** Symmetry helper. Rotates a move around the board in case we are trying to
|
|
723
|
+
* play a symmetrical rather than an exact move.
|
|
724
|
+
* @arg {string} move - the notation of the move to be rotated
|
|
725
|
+
* @returns {string[]} the four rotations of this move
|
|
726
|
+
*/
|
|
681
727
|
moveRotations(move) {
|
|
682
728
|
// Symmetry helper, rotate a move around the board
|
|
683
729
|
const match = move.match(notationRegex)
|
|
@@ -700,15 +746,24 @@ export class Trax {
|
|
|
700
746
|
return [...moves]
|
|
701
747
|
}
|
|
702
748
|
|
|
749
|
+
/** Play a provisional move if it is valid.
|
|
750
|
+
* @arg {string} from - the normalized encoding of the starting position
|
|
751
|
+
* @arg {string} to - the normalized encoding of the ending position
|
|
752
|
+
* @arg {string} via - the move to be used to transition
|
|
753
|
+
* @returns {false|string} if the provisional move is invalid: false; if the
|
|
754
|
+
* provisional move will never be valid for any future moves:
|
|
755
|
+
* 'delete-provisional'; if the provisional move is valid, the correct
|
|
756
|
+
* notation, which may be symmetrically adjusted as needed
|
|
757
|
+
*/
|
|
703
758
|
provisionalMove(from, to, via) {
|
|
704
759
|
// Test a provisional move against the current state
|
|
705
|
-
|
|
760
|
+
const lines = from.slice(1).split(':')
|
|
706
761
|
let cols = 0
|
|
707
|
-
for (const
|
|
708
|
-
cols = Math.max(cols, codeRowLength(
|
|
762
|
+
for (const line of lines) {
|
|
763
|
+
cols = Math.max(cols, codeRowLength(line))
|
|
709
764
|
}
|
|
710
765
|
|
|
711
|
-
rows =
|
|
766
|
+
const rows = lines.length
|
|
712
767
|
if (
|
|
713
768
|
(this.width > rows && this.height > cols) ||
|
|
714
769
|
(this.width > cols && this.height > rows)
|
|
@@ -731,15 +786,31 @@ export class Trax {
|
|
|
731
786
|
return false
|
|
732
787
|
}
|
|
733
788
|
|
|
789
|
+
/** Get an encoded representation of the current position, useful for drawing
|
|
790
|
+
* the board without having to do much analysis.
|
|
791
|
+
* @returns {string} the current position code
|
|
792
|
+
*/
|
|
734
793
|
get icon() {
|
|
735
794
|
return this.positionCode()
|
|
736
795
|
}
|
|
737
796
|
|
|
797
|
+
/** Get an encoded representation of the current position, with a set of
|
|
798
|
+
* tiles highlighted differently, useful for showing the effects of a move.
|
|
799
|
+
* @arg {TileDrop} drops - the drops of the most recent play
|
|
800
|
+
* @returns {string} the current position code, with drops highlighted
|
|
801
|
+
*/
|
|
738
802
|
dropsIcon(drops) {
|
|
739
803
|
return this.positionCode(undefined, undefined, undefined, drops)
|
|
740
804
|
}
|
|
741
805
|
|
|
742
|
-
|
|
806
|
+
/** Symmetry helper, draw the board from different angles.
|
|
807
|
+
* @arg {boolean} [rightToLeft] - reverse order horizontally
|
|
808
|
+
* @arg {boolean} [bottomToTop] - reverse order vertically
|
|
809
|
+
* @arg {boolean} [rotate] - rotate the tiles by 90 degrees
|
|
810
|
+
* @arg {TileDrop} [drops] - the drops of the most recent play, if you want
|
|
811
|
+
* them highlighted
|
|
812
|
+
* @returns {string} an encoding of the position
|
|
813
|
+
*/
|
|
743
814
|
positionCode(rightToLeft, bottomToTop, rotate, drops) {
|
|
744
815
|
const startX = rightToLeft ? this.right : this.left
|
|
745
816
|
const startY = bottomToTop ? this.bottom : this.top
|
|
@@ -804,9 +875,11 @@ export class Trax {
|
|
|
804
875
|
return code.join(':')
|
|
805
876
|
}
|
|
806
877
|
|
|
878
|
+
/** Trax has the potential for symmetry, so this gives us the ability to
|
|
879
|
+
* examine horizontal, vertical, and rotational symmetry for a color.
|
|
880
|
+
* @returns {string} a position code that matches all symmetrical positions
|
|
881
|
+
*/
|
|
807
882
|
normalize() {
|
|
808
|
-
// Trax has the potential for symmetry, so this gives us the ability to
|
|
809
|
-
// examine horizontal, vertical, and rotational symmetry for a color
|
|
810
883
|
let norm = 'z'
|
|
811
884
|
const bools = [true, false]
|
|
812
885
|
for (const rightToLeft of bools) {
|
|
@@ -821,6 +894,9 @@ export class Trax {
|
|
|
821
894
|
return (this.color || 't').toUpperCase() + norm
|
|
822
895
|
}
|
|
823
896
|
|
|
897
|
+
/** Get the normalized code for this position. All symmetrical positions will
|
|
898
|
+
* result in the same normalized code.
|
|
899
|
+
*/
|
|
824
900
|
get normalized() {
|
|
825
901
|
return this.normalize()
|
|
826
902
|
}
|
package/src/types.d.ts
CHANGED
|
@@ -7,131 +7,21 @@
|
|
|
7
7
|
/** Color is a single character to represent white or black. */
|
|
8
8
|
type Color = 'w' | 'b'
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
type
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
type Colorer = {
|
|
15
|
-
(text: string, def?: string | number): string
|
|
16
|
-
black: Colorize
|
|
17
|
-
command: Colorize
|
|
18
|
-
default: Colorize
|
|
19
|
-
error: Colorize
|
|
20
|
-
fatal: Colorize
|
|
21
|
-
help: Colorize
|
|
22
|
-
id: Colorize
|
|
23
|
-
variable: Colorize
|
|
24
|
-
optional: Colorize
|
|
25
|
-
short: Colorize
|
|
26
|
-
white: Colorize
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** An object representing a space on the perimeter of a Trax position.
|
|
30
|
-
* x,y: the coordinates of the space
|
|
31
|
-
* c: the color present beside the space (w, b, l: both w and b, r: none)
|
|
32
|
-
* t: the type of possible moves: n-normal, x-none, c-cave, C-restricted cave
|
|
33
|
-
* b,w: if present, the number of the line to match with its other end
|
|
34
|
-
* pb, pw: if present, can pair with the next line in one turn
|
|
35
|
-
* xb, xw: the label of this space for each color
|
|
36
|
-
*/
|
|
37
|
-
type EdgeLocation = {
|
|
38
|
-
x: number
|
|
39
|
-
y: number
|
|
40
|
-
c: string
|
|
41
|
-
t: string
|
|
42
|
-
b?: number
|
|
43
|
-
w?: number
|
|
44
|
-
pb?: boolean
|
|
45
|
-
pw?: boolean
|
|
46
|
-
zb?: string
|
|
47
|
-
zw?: string
|
|
48
|
-
idx?: number
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
type EdgeObject = {
|
|
52
|
-
b: string
|
|
53
|
-
w: string
|
|
54
|
-
edge: RawEdge
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Object representing a concrete threat found in a position. */
|
|
58
|
-
type FoundThreat = {
|
|
59
|
-
threat: string
|
|
60
|
-
match: string
|
|
61
|
-
at: number
|
|
62
|
-
value: number
|
|
63
|
-
level: number
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** Threats found for each color that cannot actually be activated. */
|
|
67
|
-
type FaultyThreats = {
|
|
68
|
-
b: FoundThreat[]
|
|
69
|
-
w: FoundThreat[]
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** An object with keys representing each level, with arrays for each threat of
|
|
73
|
-
* that level. */
|
|
74
|
-
type ColorThreats = Record<string, FoundThreat[]>
|
|
75
|
-
|
|
76
|
-
/** All the threats found for both the white and black player. */
|
|
77
|
-
type FoundThreatsCollection = { b: ColorThreats; w: ColorThreats }
|
|
78
|
-
|
|
79
|
-
/** Scores for each player. */
|
|
80
|
-
type Scores = {
|
|
81
|
-
b: number
|
|
82
|
-
w: number
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** A note with a move number */
|
|
86
|
-
type GameNote = {
|
|
87
|
-
move: number
|
|
88
|
-
note: string
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Notes saved in the game object in the CLI. */
|
|
92
|
-
type GameNotes = GameNote[]
|
|
93
|
-
|
|
94
|
-
/** A point-like object has numerical x and y properties. */
|
|
95
|
-
type PointLike = {
|
|
96
|
-
x: number
|
|
97
|
-
y: number
|
|
10
|
+
/** One end of a line and the tiles taken to get there. */
|
|
11
|
+
type LineEnd = {
|
|
12
|
+
loc: Point
|
|
13
|
+
path: TileId[]
|
|
98
14
|
}
|
|
99
15
|
|
|
100
|
-
/**
|
|
101
|
-
type
|
|
102
|
-
move: string
|
|
103
|
-
score: number
|
|
104
|
-
analysis?: Analysis
|
|
105
|
-
}
|
|
16
|
+
/** A notation of a move. */
|
|
17
|
+
type Notation = string
|
|
106
18
|
|
|
107
|
-
/** A
|
|
108
|
-
type
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
game: TraxVariant
|
|
112
|
-
notation: string
|
|
113
|
-
icon: string
|
|
114
|
-
level: number
|
|
115
|
-
max: number
|
|
116
|
-
player: number
|
|
117
|
-
title?: string
|
|
118
|
-
desc?: string
|
|
119
|
-
hint?: string
|
|
120
|
-
hints?: string[]
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
type PuzzleSource = {
|
|
124
|
-
name: string
|
|
125
|
-
url?: string
|
|
126
|
-
copyright?: string
|
|
127
|
-
license?: string
|
|
128
|
-
licenseUrl?: string
|
|
19
|
+
/** A tile type and a location determine a raw move. */
|
|
20
|
+
type RawMove = {
|
|
21
|
+
type: TileType
|
|
22
|
+
loc: Point
|
|
129
23
|
}
|
|
130
24
|
|
|
131
|
-
/** Array of objects representing the spaces surrounding the perimeter of a
|
|
132
|
-
* Trax position. */
|
|
133
|
-
type RawEdge = EdgeLocation[]
|
|
134
|
-
|
|
135
25
|
/** Treat the save state as an opaque object,
|
|
136
26
|
* produced by save() and fed into restore().
|
|
137
27
|
*/
|
|
@@ -144,7 +34,7 @@ type SaveState = {
|
|
|
144
34
|
right: number
|
|
145
35
|
top: number
|
|
146
36
|
bottom: number
|
|
147
|
-
notation:
|
|
37
|
+
notation: Notation
|
|
148
38
|
tiles: string
|
|
149
39
|
path: string
|
|
150
40
|
invalid: boolean
|
|
@@ -155,14 +45,6 @@ type SaveState = {
|
|
|
155
45
|
*/
|
|
156
46
|
type Slash = '/' | '\\' | '+'
|
|
157
47
|
|
|
158
|
-
/** Threat definition. */
|
|
159
|
-
type Threat = {
|
|
160
|
-
depth: number
|
|
161
|
-
pattern: string
|
|
162
|
-
rx: RegExp
|
|
163
|
-
value: number
|
|
164
|
-
}
|
|
165
|
-
|
|
166
48
|
/** A single tile on the board. */
|
|
167
49
|
type Tile = {
|
|
168
50
|
id: TileId
|
|
@@ -175,7 +57,7 @@ type Tile = {
|
|
|
175
57
|
/** When a tile is dropped, this object represents the results. */
|
|
176
58
|
type TileDrop = {
|
|
177
59
|
dropped: Tile[]
|
|
178
|
-
notation:
|
|
60
|
+
notation: Notation
|
|
179
61
|
valid: boolean
|
|
180
62
|
}
|
|
181
63
|
|
|
@@ -188,5 +70,15 @@ type TileType = ValidTiles | 'x'
|
|
|
188
70
|
/** All of the variants supported by the engine. */
|
|
189
71
|
type TraxVariant = 'trax' | 'traxloop' | 'trax8'
|
|
190
72
|
|
|
191
|
-
/** Tile
|
|
73
|
+
/** Tile type names are determined by listing the line color at each edge,
|
|
74
|
+
* starting from the top and going clockwise, and then sorted alphabetically
|
|
75
|
+
* and given a single letter name, so 'bbww' becomes 'a', which gives us six
|
|
76
|
+
* different tile names: a-f, as follows:
|
|
77
|
+
* a b c d e f
|
|
78
|
+
* +--#--+ +--#--+ +--#--+ +--o--+ +--o--+ +--o--+
|
|
79
|
+
* | # | | # | | # | | o | | o | | o |
|
|
80
|
+
* oo ## ooo#ooo ## oo oo ## ####### ## oo
|
|
81
|
+
* | o | | # | | o | | # | | o | | # |
|
|
82
|
+
* +--o--+ +--#--+ +--o--+ +--#--+ +--o--+ +--#--+
|
|
83
|
+
*/
|
|
192
84
|
type ValidTiles = 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
|
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.23.0'
|
package/.dockerignore
DELETED
package/Dockerfile
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Use the latest nodejs long-term-support release,
|
|
2
|
-
# on the latest Alpine Linux for its small footprint
|
|
3
|
-
FROM node:lts-alpine
|
|
4
|
-
# Install current source code
|
|
5
|
-
WORKDIR /trax
|
|
6
|
-
COPY . .
|
|
7
|
-
RUN npm install
|
|
8
|
-
# Ensure the data files can be persisted
|
|
9
|
-
WORKDIR /mnt/data
|
|
10
|
-
ENV XDG_CONFIG_HOME=/mnt/data
|
|
11
|
-
ENV XDG_DATA_HOME=/mnt/data
|
|
12
|
-
VOLUME /mnt/data
|
|
13
|
-
# Use the trax CLI as the starting point
|
|
14
|
-
ENTRYPOINT ["/trax/src/cli.js"]
|