@slugbugblue/trax 1.1.0 → 1.2.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.
@@ -0,0 +1,456 @@
1
+ /** A digital representation of a Trax game. */
2
+ export class Trax {
3
+ /** @readonly */
4
+ static readonly version: '1.2.0'
5
+ /**
6
+ @readonly
7
+ @type {Record<TraxVariant, string>}
8
+ */
9
+ static readonly names: Record<TraxVariant, string>
10
+ /** @readonly */
11
+ static readonly variants: Set<string>
12
+ /**
13
+ Create an x,y Point object with special functions.
14
+ @param {number|PointLike} x - either the x value, or an object with x,y keys
15
+ @param {number} [y] - if x is a number, y must be provided as well
16
+ @returns {Point} a new Point object
17
+ */
18
+ static point: (x: number | PointLike, y?: number) => Point
19
+ /**
20
+ Given a player number, get the color.
21
+ @param {number} playerNumber - the player number, 1 or 2
22
+ @returns {Color} the color of that player, w or b
23
+ */
24
+ static colorOf: (playerNumber: number) => Color
25
+ /**
26
+ Given a color, get the player number.
27
+ @param {string} color - the color, w or b
28
+ @returns {number} the player number, 1 or 2
29
+ */
30
+ static playerNumber: (color: string) => number
31
+ /**
32
+ Given a color, get the other color.
33
+ @param {string} color - the color, w or b
34
+ @returns {Color} the other color, b or w
35
+ */
36
+ static other: (color: string) => Color
37
+ /**
38
+ Encode a numeric column number into the Trax notation column letter.
39
+ @param {number} col - the column number, with 0 just to the left of the tiles
40
+ @returns {string} the encoded column letter
41
+ */
42
+ static encodeCol: (col: number) => string
43
+ /**
44
+ Decode a Trax notation column letter back to a number.
45
+ @param {string} col - the Trax column letter
46
+ @returns {number} the column number
47
+ */
48
+ static decodeCol: (col: string) => number
49
+ /**
50
+ Create a new Trax game
51
+ @param {TraxVariant} [rules='trax'] - the variant to play
52
+ @param {string|string[]} [moves=''] - the initial moves to pre-play
53
+ @param {string} [id='trax'] - an id used to differentiate tiles from multiple games
54
+ */
55
+ constructor(rules?: TraxVariant, moves?: string | string[], id?: string)
56
+ id: string
57
+ rules: TraxVariant
58
+ turn: number
59
+ over: boolean
60
+ left: number
61
+ right: number
62
+ top: number
63
+ bottom: number
64
+ count: number
65
+ /** @type {string[]} */
66
+ moves: string[]
67
+ /** @type {Map<TileId, Point>} */
68
+ frontier: Map<TileId, Point>
69
+ /** @type {Record<TileId, Tile>} */
70
+ tiles: Record<TileId, Tile>
71
+ /** @type {TileId[]} */
72
+ path: TileId[]
73
+ invalid: boolean
74
+ /**
75
+ Save the current game data to a variable.
76
+ @returns {SaveState} an opaque save state object
77
+ @see restore for restoring the state
78
+ */
79
+ save(): SaveState
80
+ /**
81
+ Restore a previously saved position.
82
+ @param {SaveState} saved - the previously saved state
83
+ @see save for saving the state
84
+ */
85
+ restore(saved: SaveState): void
86
+ /**
87
+ Lightweight checkpoint for internal rollback. Valid only for ancestor restores.
88
+ Callers must be in a non-over, valid game state — rewind() restores those
89
+ fields to those fixed values rather than saving and restoring them.
90
+ @returns {Checkpoint} a lightweight snapshot of mutable board dimensions
91
+ @typedef {{ move: number, count: number, turn: number, left: number, right: number, top: number, bottom: number }} Checkpoint
92
+ */
93
+ checkpoint(): {
94
+ move: number
95
+ count: number
96
+ turn: number
97
+ left: number
98
+ right: number
99
+ top: number
100
+ bottom: number
101
+ }
102
+ /**
103
+ Rewind to a checkpoint. Only valid for ancestor restores.
104
+ @param {Checkpoint} cp - the checkpoint to rewind to
105
+ */
106
+ rewind(cp: {
107
+ move: number
108
+ count: number
109
+ turn: number
110
+ left: number
111
+ right: number
112
+ top: number
113
+ bottom: number
114
+ }): void
115
+ /** The name of this variant. */
116
+ get name(): string
117
+ /** The move number of the last-played move. */
118
+ get move(): number
119
+ /** The color of the current player, w or b. */
120
+ get color(): Color
121
+ /** True if the game is over. */
122
+ get gameOver(): boolean
123
+ /** 1 or 2 for a win, 0 for a tie, false if the game is still in progress. */
124
+ get winner(): number | false
125
+ /**
126
+ Provides the tile ID for the tile at the given location.
127
+ @param {PointLike} loc - the location
128
+ @returns {TileId} a string key encoding this game's id and the location
129
+ */
130
+ tileId(loc: PointLike): TileId
131
+ /**
132
+ Add a tile to the board. Note that no validity checking is done here,
133
+ except that invalid tiles are not actually placed on the board, so this
134
+ should only be called externally.
135
+ @param {TileType} type - letter 'a'-'f' for valid tiles, 'x' for invalid
136
+ @param {Point} loc - the location
137
+ @returns {Tile} the tile placed on the board
138
+ */
139
+ addTile(type: TileType, loc: Point): Tile
140
+ /**
141
+ The type of tile at the given location.
142
+ @param {PointLike} loc - the location the tile is in
143
+ @returns {ValidTiles|undefined} the type of tile, or undefined if no tile
144
+ */
145
+ tileAt(loc: PointLike): ValidTiles | undefined
146
+ validTile(type: string, loc: Point): type is ValidTiles
147
+ /**
148
+ Get a list of possible tiles that can be played in this location.
149
+ @param {Point} loc - the location to check
150
+ @param {string | boolean} [s=false] - if provided, a direction modifier, '/', '\\', or '+'
151
+ @returns {TileType[]} the list of valid tile types for this location
152
+ */
153
+ possibleTiles(loc: Point, s?: string | boolean): TileType[]
154
+ get height(): number
155
+ get width(): number
156
+ /**
157
+ Determine if a location is valid to play in.
158
+ @param {Point} loc - the location to check
159
+ @returns {boolean} true if a tile can be placed here
160
+ */
161
+ validLocation(loc: Point): boolean
162
+ /**
163
+ Find all possible locations to play in. Note that these are not
164
+ necessarily valid locations, just empty ones that border existing tiles.
165
+ @returns {Point[]} all frontier locations
166
+ */
167
+ possibleLocations(): Point[]
168
+ /**
169
+ Find all possible moves as a list of notations,
170
+ ie: ['@1+', '@1/', '@1\\', ...]
171
+
172
+ Note that moves are not guaranteed to be valid.
173
+ @returns {string[]} all valid move notations from the current position
174
+ */
175
+ possibleMoves(): string[]
176
+ /**
177
+ Called after a move was just played, to determine the forced moves.
178
+ @param {Point} loc - the location just played at
179
+ @returns {Tile[]} a list of tiles that should be added as part of the move
180
+ */
181
+ forcedMoves(loc: Point): Tile[]
182
+ /**
183
+ Determine the notation for a move. Note that this must be determined
184
+ BEFORE the move is placed on the board.
185
+ @param {ValidTiles} type - the tile placed on the board
186
+ @param {Point} loc - the location the tile is placed
187
+ @returns {string} the notation of the move
188
+ */
189
+ notate(type: ValidTiles, loc: Point): string
190
+ /**
191
+ Turn a move notation into a tile type and location.
192
+ @param {string} notation - a notation for a single move to be played at
193
+ the current board position
194
+ @returns {RawMove} the tile type and location of the move
195
+ */
196
+ decodeNotation(notation: string): RawMove
197
+ /**
198
+ Follow a color from one location through one or more tiles to the other
199
+ end of the color line.
200
+ @param {Color} color - the color to follow
201
+ @param {Point} loc - the location to start
202
+ @param {string} from - the edge of the tile to start from
203
+ @returns {LineEnd} the ending location and a list of the tile ids the path
204
+ takes to get there
205
+ */
206
+ follow(color: Color, loc: Point, from: string): LineEnd
207
+ /**
208
+ Given a tile and a color, follow the line for that color to each end.
209
+ @param {Color} color - the color of ends of interest
210
+ @param {Point} loc - the location of the tile of interest
211
+ @returns {LineEnd[]} a list of two items, each one end of the line
212
+ */
213
+ findEnds(color: Color, loc: Point): LineEnd[]
214
+ /**
215
+ Determine if a given line ends the game.
216
+ @param {Point} locA - one end of the line
217
+ @param {Point} locB - the other end of the line
218
+ @returns {boolean} true if this line wins the game
219
+ */
220
+ lineWin(locA: Point, locB: Point): boolean
221
+ /**
222
+ Determine if the game has ended.
223
+ @param {Tile[]} tiles - a list of the tiles placed during the last move
224
+ */
225
+ checkWin(tiles: Tile[]): void
226
+ /**
227
+ Play a move. Can be called either as:
228
+ - play(moveNumber, notation) to ensure move safety, or
229
+ - play(notation) for quicker access.
230
+ @param {number|string} moveNumber - the move number or the notation
231
+ @param {string} [notation] - the notation, if a move number was provided
232
+ @returns {{dropped: Tile[], notation: string, valid: boolean}} the result of the move
233
+ */
234
+ play(
235
+ moveNumber: number | string,
236
+ notation?: string,
237
+ ): {
238
+ dropped: Tile[]
239
+ notation: string
240
+ valid: boolean
241
+ }
242
+ /**
243
+ Play one or more moves.
244
+ @param {string|string[]} moves - the list of moves, provided either as a
245
+ space-separated string of notations, or as a list of notations. Move
246
+ numbers are optional, but if provided will be checked for accuracy.
247
+ */
248
+ playMoves(moves: string | string[]): void
249
+ /** The formatted notation string for the current game, wrapped at 80 columns. */
250
+ get notation(): string
251
+ /**
252
+ Drop a tile onto the board. This is a lower level call. Use play() if possible instead.
253
+ @param {string|ValidTiles} type - a special move, a tile type, or a notation
254
+ @param {Point} [loc] - a location if type is a tile type
255
+ @param {string|boolean} [tentative] - if truthy, the move will not be saved
256
+ @returns {TileDrop} an object representing the results of the drop
257
+ */
258
+ dropTile(
259
+ type: string | ValidTiles,
260
+ loc?: Point,
261
+ tentative?: string | boolean,
262
+ ): TileDrop
263
+ /**
264
+ Symmetry helper. Rotates a move around the board in case we are trying to
265
+ play a symmetrical rather than an exact move.
266
+ @param {string} move - the notation of the move to be rotated
267
+ @returns {string[]} the four rotations of this move
268
+ */
269
+ moveRotations(move: string): string[]
270
+ /**
271
+ Play a provisional move if it is valid.
272
+ @param {string} from - the normalized encoding of the starting position
273
+ @param {string} to - the normalized encoding of the ending position
274
+ @param {string} via - the move to be used to transition
275
+ @returns {false|string} if the provisional move is invalid: false; if the
276
+ provisional move will never be valid for any future moves:
277
+ 'delete-provisional'; if the provisional move is valid, the correct
278
+ notation, which may be symmetrically adjusted as needed
279
+ */
280
+ provisionalMove(from: string, to: string, via: string): false | string
281
+ /**
282
+ Get an encoded representation of the current position, useful for drawing
283
+ the board without having to do much analysis.
284
+ @returns {string} the current position code
285
+ */
286
+ get icon(): string
287
+ /**
288
+ Get an encoded representation of the current position, with a set of
289
+ tiles highlighted differently, useful for showing the effects of a move.
290
+ @param {TileDrop} drops - the drops of the most recent play
291
+ @returns {string} the current position code, with drops highlighted
292
+ */
293
+ dropsIcon(drops: TileDrop): string
294
+ /**
295
+ Symmetry helper, draw the board from different angles.
296
+ @param {boolean} [rightToLeft] - reverse order horizontally
297
+ @param {boolean} [bottomToTop] - reverse order vertically
298
+ @param {boolean} [rotate] - rotate the tiles by 90 degrees
299
+ @param {TileDrop} [drops] - the drops of the most recent play, if you want
300
+ them highlighted
301
+ @returns {string} an encoding of the position
302
+ */
303
+ positionCode(
304
+ rightToLeft?: boolean,
305
+ bottomToTop?: boolean,
306
+ rotate?: boolean,
307
+ drops?: TileDrop,
308
+ ): string
309
+ /**
310
+ Trax has the potential for symmetry, so this gives us the ability to
311
+ examine horizontal, vertical, and rotational symmetry for a color.
312
+ @returns {string} a position code that matches all symmetrical positions
313
+ */
314
+ normalize(): string
315
+ /**
316
+ Get the normalized code for this position. All symmetrical positions will
317
+ result in the same normalized code.
318
+ @returns {string} the normalized position code
319
+ */
320
+ get normalized(): string
321
+ }
322
+ export type Color = 'w' | 'b'
323
+ /**
324
+ * One end of a line and the tiles taken to get there.
325
+ */
326
+ export type LineEnd = {
327
+ /**
328
+ * - the ending location
329
+ */
330
+ loc: Point
331
+ /**
332
+ * - tile ids from start to end
333
+ */
334
+ path: TileId[]
335
+ }
336
+ export type Notation = string
337
+ /**
338
+ * A tile type and a location determine a raw move.
339
+ */
340
+ export type RawMove = {
341
+ /**
342
+ * - the tile type
343
+ */
344
+ type: TileType
345
+ /**
346
+ * - the location
347
+ */
348
+ loc: Point
349
+ }
350
+ /**
351
+ * Treat the save state as an opaque object,
352
+ * produced by save() and fed into restore().
353
+ */
354
+ export type SaveState = {
355
+ /**
356
+ * - game id
357
+ */
358
+ id: string
359
+ /**
360
+ * - move number
361
+ */
362
+ move: number
363
+ /**
364
+ * - current player (1 or 2)
365
+ */
366
+ turn: number
367
+ /**
368
+ * - whether the game is over
369
+ */
370
+ over: boolean
371
+ /**
372
+ * - leftmost tile column
373
+ */
374
+ left: number
375
+ /**
376
+ * - rightmost tile column
377
+ */
378
+ right: number
379
+ /**
380
+ * - topmost tile row
381
+ */
382
+ top: number
383
+ /**
384
+ * - bottommost tile row
385
+ */
386
+ bottom: number
387
+ /**
388
+ * - move notations
389
+ */
390
+ moves: string[]
391
+ /**
392
+ * - frontier locations
393
+ */
394
+ frontier: [TileId, Point][]
395
+ /**
396
+ * - serialized tiles
397
+ */
398
+ tiles: string
399
+ /**
400
+ * - serialized winning path
401
+ */
402
+ path: string
403
+ /**
404
+ * - whether an invalid tile was placed
405
+ */
406
+ invalid: boolean
407
+ }
408
+ export type Slash = '/' | '\\' | '+'
409
+ /**
410
+ * A single tile on the board.
411
+ */
412
+ export type Tile = {
413
+ /**
414
+ * - unique tile identifier
415
+ */
416
+ id: TileId
417
+ /**
418
+ * - board location
419
+ */
420
+ loc: Point
421
+ /**
422
+ * - tile type letter
423
+ */
424
+ type: TileType
425
+ /**
426
+ * - move number when placed
427
+ */
428
+ move: number
429
+ /**
430
+ * - sequence number among all tiles
431
+ */
432
+ seq: number
433
+ }
434
+ export type TileId = string
435
+ /**
436
+ * When a tile is dropped, this object represents the results.
437
+ */
438
+ export type TileDrop = {
439
+ /**
440
+ * - all tiles placed, including forced moves
441
+ */
442
+ dropped: Tile[]
443
+ /**
444
+ * - the notation of the played move
445
+ */
446
+ notation: Notation
447
+ /**
448
+ * - whether the move was legal
449
+ */
450
+ valid: boolean
451
+ }
452
+ export type TileType = ValidTiles | 'x'
453
+ export type TraxVariant = 'trax' | 'traxloop' | 'trax8'
454
+ export type ValidTiles = 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
455
+ import { Point } from '@slugbugblue/point'
456
+ import type { PointLike } from '@slugbugblue/point'