@slugbugblue/trax 1.0.1 → 1.1.1

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,5 @@
1
+ ## 1.1.1 - 2026-02-28
2
+
3
+ - Clean up typescript with strict tsc option
4
+ - Export typescript types together with the code
5
+
@@ -0,0 +1 @@
1
+ {"version":"15.2.2","vulnerabilities":[],"scan":{"analyzer":{"id":"semgrep","name":"Semgrep","url":"https://gitlab.com/gitlab-org/security-products/analyzers/semgrep","vendor":{"name":"GitLab"},"version":"6.15.1"},"scanner":{"id":"semgrep","name":"Semgrep","url":"https://github.com/returntocorp/semgrep","vendor":{"name":"GitLab"},"version":"1.145.0"},"type":"sast","start_time":"2026-02-28T20:29:59","end_time":"2026-02-28T20:30:11","status":"success","observability":{"events":[{"event":"collect_sast_scan_metrics_from_pipeline","property":"54b1ad92-5d39-416b-9075-916f3da22681","label":"semgrep","value":0,"version":"6.15.1","exit_code":0,"override_count":0,"passthrough_count":0,"custom_exclude_path_count":0,"time_s":12,"file_count":7}]}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slugbugblue/trax",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "Trax game engine",
5
5
  "keywords": [
6
6
  "trax",
@@ -11,20 +11,28 @@
11
11
  "bugs": "https://gitlab.com/slugbugblue/trax/issues",
12
12
  "license": "Apache-2.0",
13
13
  "author": "Chad Transtrum <chad@transtrum.net>",
14
- "types": "./src/types.d.ts",
14
+ "types": "./src/engine.d.ts",
15
+ "typings": "./src/engine.d.ts",
15
16
  "exports": {
16
- ".": "./src/engine.js",
17
+ ".": {
18
+ "types": "./src/engine.d.ts",
19
+ "default": "./src/engine.js"
20
+ },
17
21
  "./version": "./src/version.js",
18
22
  "./version.js": "./src/version.js"
19
23
  },
20
- "repository": "gitlab:slugbugblue/trax",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://gitlab.com/slugbugblue/trax.git"
27
+ },
21
28
  "scripts": {
22
29
  "genversion": "genversion --esm src/version.js",
23
- "git-add": "git add src/version.js",
30
+ "git-add": "git add src/version.js src/engine.d.ts",
31
+ "ts-build": "tsc -p tsconfig.build.json && rm -f src/version.d.ts",
24
32
  "test": "xo && c8 ava",
25
33
  "prepare": "[ -n \"$CI\" ] || husky",
26
- "preversion": "npm test",
27
- "version": "npm run genversion ; npm run git-add",
34
+ "preversion": "npm audit --audit-level=high && npm test",
35
+ "version": "npm run genversion ; npm run ts-build ; npm run git-add",
28
36
  "postversion": "git push && git push --tags"
29
37
  },
30
38
  "dependencies": {
@@ -32,8 +40,8 @@
32
40
  "@slugbugblue/point": "^1.0.0"
33
41
  },
34
42
  "devDependencies": {
35
- "ava": "^6.4.1",
36
- "c8": "^10.1.3",
43
+ "ava": "^7.0.0",
44
+ "c8": "^11.0.0",
37
45
  "genversion": "^3.0.2",
38
46
  "husky": "^9.1.7",
39
47
  "prettier": "^3.6.2",
@@ -57,15 +65,5 @@
57
65
  "singleQuote": true,
58
66
  "trailingComma": "all",
59
67
  "useTabs": false
60
- },
61
- "xo": {
62
- "prettier": true,
63
- "space": true,
64
- "rules": {
65
- "curly": [
66
- "error",
67
- "multi-line"
68
- ]
69
- }
70
68
  }
71
69
  }
@@ -0,0 +1,313 @@
1
+ /** A digital representation of a Trax game. */
2
+ export class Trax {
3
+ /** @readonly */
4
+ static readonly version: '1.1.1'
5
+ /** @readonly @type {Record<TraxVariant, string>} */
6
+ static readonly names: Record<TraxVariant, string>
7
+ /** @readonly */
8
+ static readonly variants: Set<string>
9
+ /** Create an x,y Point object with special functions.
10
+ * @arg {number|PointLike} x - either the x value, or an object with x,y keys
11
+ * @arg {number} [y] - if x is a number, y must be provided as well
12
+ * @returns {Point} a new Point object
13
+ */
14
+ static point: (x: number | PointLike, y?: number) => Point
15
+ /** Given a player number, get the color.
16
+ * @arg {number} playerNumber - the player number, 1 or 2
17
+ * @returns {Color} the color of that player, w or b
18
+ */
19
+ static colorOf: (playerNumber: number) => Color
20
+ /** Given a color, get the player number.
21
+ * @arg {string} color - the color, w or b
22
+ * @returns {number} the player number, 1 or 2
23
+ */
24
+ static playerNumber: (color: string) => number
25
+ /** Given a color, get the other color.
26
+ * @arg {string} color - the color, w or b
27
+ * @returns {Color} the other color, b or w
28
+ */
29
+ static other: (color: string) => Color
30
+ /** Encode a numeric column number into the Trax notation column letter.
31
+ * @arg {number} col - the colum number, with 0 just to the left of the tiles
32
+ * @returns {string} the encoded column letter
33
+ */
34
+ static encodeCol: (col: number) => string
35
+ /** Decode a Trax notation column letter back to a number.
36
+ * @arg {string} col - the Trax column letter
37
+ * @returns {number} the column number
38
+ */
39
+ static decodeCol: (col: string) => number
40
+ /** Create a new Trax game
41
+ * @arg {TraxVariant} [rules='trax'] - the variant to play
42
+ * @arg {string|string[]} [moves=''] - the initial moves to pre-play
43
+ * @arg {string} [id='trax'] - an id used to differentiate tiles from multiple games
44
+ */
45
+ constructor(rules?: TraxVariant, moves?: string | string[], id?: string)
46
+ id: string
47
+ rules: TraxVariant
48
+ move: number
49
+ turn: number
50
+ over: boolean
51
+ left: number
52
+ right: number
53
+ top: number
54
+ bottom: number
55
+ notation: string
56
+ /** @type {Record<TileId, Tile>} */
57
+ tiles: Record<TileId, Tile>
58
+ /** @type TileId[] */
59
+ path: TileId[]
60
+ invalid: boolean
61
+ /** Save the current game data to a variable.
62
+ * @returns {SaveState} an opaque save state object
63
+ * @see restore for restoring the state
64
+ */
65
+ save(): SaveState
66
+ /** Restore a previously saved position.
67
+ * @arg {SaveState} saved - the previously saved state
68
+ * @see save for saving the state
69
+ */
70
+ restore(saved: SaveState): void
71
+ /** The name of this variant. */
72
+ get name(): string
73
+ /** The number of tiles currently in play. */
74
+ get count(): number
75
+ /** The color of the current player, w or b. */
76
+ get color(): Color
77
+ /** True if the game is over. */
78
+ get gameOver(): boolean
79
+ /** 1 or 2 for a win, 0 for a tie, false if the game is still in progress. */
80
+ get winner(): number | false
81
+ /** Provides the tile ID for the tile at the given location.
82
+ * @arg {PointLike} loc
83
+ * returns {TileId}
84
+ */
85
+ tileId(loc: PointLike): string
86
+ /** Add a tile to the board. Note that no validity checking is done here,
87
+ * except that invalid tiles are not actually placed on the board, so this
88
+ * should only be called externally.
89
+ * @arg {TileType} type
90
+ * @arg {Point} loc
91
+ * @returns {Tile} the tile placed on the board.
92
+ */
93
+ addTile(type: TileType, loc: Point): Tile
94
+ /** The type of tile at the given location.
95
+ * @arg {PointLike} loc - the location the tile is in
96
+ * @returns {ValidTiles|undefined} the type of tile, or undefined if no tile
97
+ */
98
+ tileAt(loc: PointLike): ValidTiles | undefined
99
+ validTile(type: string, loc: Point): type is ValidTiles
100
+ /** Get a list of possible tiles that can be played in this location.
101
+ * @arg {Point} loc - the location to check
102
+ * @arg {string | boolean} s=false - if provided, a direction modifier, '/', '\\', or '+'
103
+ * @returns {TileType[]}
104
+ */
105
+ possibleTiles(loc: Point, s?: string | boolean): TileType[]
106
+ get height(): number
107
+ get width(): number
108
+ /** Determine if a location is valid to play in.
109
+ * @arg {Point} loc - the location to check
110
+ * @returns {boolean}
111
+ */
112
+ validLocation(loc: Point): boolean
113
+ /** Find all possible locations to play in. Note that these are not
114
+ * necessarily valid locations, just empty ones that border existing tiles.
115
+ */
116
+ possibleLocations(): Point[]
117
+ /** Find all possible moves as a list of notations,
118
+ * ie: ['@1+', '@1/', '@1\\', ...]
119
+ *
120
+ * Note that moves are not guaranteed to be valid.
121
+ */
122
+ possibleMoves(): string[]
123
+ /** Called after a move was just played, to determine the forced moves.
124
+ * @arg {Point} loc - the location just played at
125
+ * @returns {Tile[]} a list of tiles that should be added as part of the move
126
+ */
127
+ forcedMoves(loc: Point): Tile[]
128
+ /** Determine the notation for a move. Note that this must be determined
129
+ * BEFORE the move is placed on the board.
130
+ * @arg {ValidTiles} type - the tile placed on the board
131
+ * @arg {Point} loc - the location the tile is placed
132
+ * @returns {string} the notation of the move
133
+ */
134
+ notate(type: ValidTiles, loc: Point): string
135
+ /** Turn a move notation into a tile type and location.
136
+ * @arg {string} notation - a notation for a single move to be played at
137
+ * the current board position
138
+ * @returns {RawMove} the tile type and location of the move
139
+ */
140
+ decodeNotation(notation: string): RawMove
141
+ /** Follow a color from one location through one or more tiles to the other
142
+ * end of the color line.
143
+ * @arg {Color} color - the color to follow
144
+ * @arg {Point} loc - the location to start
145
+ * @arg {string} from - the edge of the tile to start from
146
+ * @returns {LineEnd} the ending location and a list of the tile ids the path
147
+ * takes to get there.
148
+ */
149
+ follow(color: Color, loc: Point, from: string): LineEnd
150
+ /** Given a tile and a color, follow the line for that color to each end.
151
+ * @arg {Color} color - the color of ends of interest
152
+ * @arg { Point} loc - the location of the tile of interest
153
+ * @returns {LineEnd[]} a list of two items, each one end of the line
154
+ */
155
+ findEnds(color: Color, loc: Point): LineEnd[]
156
+ /** Determine if a given line ends the game.
157
+ * @arg {Point} locA - one end of the line
158
+ * @arg {Point} locB - the other end of the line
159
+ * @returns {boolean} - true if this line wins the game
160
+ */
161
+ lineWin(locA: Point, locB: Point): boolean
162
+ /** Determine if the game has ended.
163
+ * @arg {Tile[]} tiles - a list of the tiles placed during the last move.
164
+ */
165
+ checkWin(tiles: Tile[]): void
166
+ /** Play a move. Can be called either as:
167
+ * - play(moveNumber, notation) to ensure move safety, or
168
+ * - play(notation) for quicker access.
169
+ * @arg moveNumber {(number|string)} the move number or the notation
170
+ * @arg {string} [notation] - the notation, if a move number was provided
171
+ * @returns {{dropped: Tile[], notation: string, valid: boolean}}
172
+ */
173
+ play(
174
+ moveNumber: number | string,
175
+ notation?: string,
176
+ ): {
177
+ dropped: Tile[]
178
+ notation: string
179
+ valid: boolean
180
+ }
181
+ /** Play one or more moves.
182
+ * @arg {string|string[]} moves - the list of moves, provided either as a
183
+ * space-separated string of notations, or as a list of notations. Move
184
+ * numbers are optional, but if provided will be checked for accuracy.
185
+ */
186
+ playMoves(moves: string | string[]): void
187
+ /** Add the current move notation to the notation string
188
+ * @arg {string} notation - the notation of the current move
189
+ */
190
+ updateNotation(notation: string): void
191
+ /** An array of the moves made in the game. */
192
+ get moves(): string[]
193
+ /** Drop a tile onto the board. This is a lower level call. Use play() if possible instead.
194
+ * @arg {string|ValidTiles} type - a special move, a tile type, or a notation
195
+ * @arg {Point} [loc] - a location if type is a tile type
196
+ * @arg {string|boolean} [tentative] - if truthy, the move will not be saved
197
+ * @returns {TileDrop} an object representing the results of the drop
198
+ */
199
+ dropTile(
200
+ type: string | ValidTiles,
201
+ loc?: Point,
202
+ tentative?: string | boolean,
203
+ ): TileDrop
204
+ /** Symmetry helper. Rotates a move around the board in case we are trying to
205
+ * play a symmetrical rather than an exact move.
206
+ * @arg {string} move - the notation of the move to be rotated
207
+ * @returns {string[]} the four rotations of this move
208
+ */
209
+ moveRotations(move: string): string[]
210
+ /** Play a provisional move if it is valid.
211
+ * @arg {string} from - the normalized encoding of the starting position
212
+ * @arg {string} to - the normalized encoding of the ending position
213
+ * @arg {string} via - the move to be used to transition
214
+ * @returns {false|string} if the provisional move is invalid: false; if the
215
+ * provisional move will never be valid for any future moves:
216
+ * 'delete-provisional'; if the provisional move is valid, the correct
217
+ * notation, which may be symmetrically adjusted as needed
218
+ */
219
+ provisionalMove(from: string, to: string, via: string): false | string
220
+ /** Get an encoded representation of the current position, useful for drawing
221
+ * the board without having to do much analysis.
222
+ * @returns {string} the current position code
223
+ */
224
+ get icon(): string
225
+ /** Get an encoded representation of the current position, with a set of
226
+ * tiles highlighted differently, useful for showing the effects of a move.
227
+ * @arg {TileDrop} drops - the drops of the most recent play
228
+ * @returns {string} the current position code, with drops highlighted
229
+ */
230
+ dropsIcon(drops: TileDrop): string
231
+ /** Symmetry helper, draw the board from different angles.
232
+ * @arg {boolean} [rightToLeft] - reverse order horizontally
233
+ * @arg {boolean} [bottomToTop] - reverse order vertically
234
+ * @arg {boolean} [rotate] - rotate the tiles by 90 degrees
235
+ * @arg {TileDrop} [drops] - the drops of the most recent play, if you want
236
+ * them highlighted
237
+ * @returns {string} an encoding of the position
238
+ */
239
+ positionCode(
240
+ rightToLeft?: boolean,
241
+ bottomToTop?: boolean,
242
+ rotate?: boolean,
243
+ drops?: TileDrop,
244
+ ): string
245
+ /** Trax has the potential for symmetry, so this gives us the ability to
246
+ * examine horizontal, vertical, and rotational symmetry for a color.
247
+ * @returns {string} a position code that matches all symmetrical positions
248
+ */
249
+ normalize(): string
250
+ /** Get the normalized code for this position. All symmetrical positions will
251
+ * result in the same normalized code.
252
+ */
253
+ get normalized(): string
254
+ }
255
+ export type Color = 'w' | 'b'
256
+ /**
257
+ * One end of a line and the tiles taken to get there.
258
+ */
259
+ export type LineEnd = {
260
+ loc: Point
261
+ path: TileId[]
262
+ }
263
+ export type Notation = string
264
+ /**
265
+ * A tile type and a location determine a raw move.
266
+ */
267
+ export type RawMove = {
268
+ type: TileType
269
+ loc: Point
270
+ }
271
+ /**
272
+ * Treat the save state as an opaque object,
273
+ * produced by save() and fed into restore().
274
+ */
275
+ export type SaveState = {
276
+ id: string
277
+ move: number
278
+ turn: number
279
+ over: boolean
280
+ left: number
281
+ right: number
282
+ top: number
283
+ bottom: number
284
+ notation: Notation
285
+ tiles: string
286
+ path: string
287
+ invalid: boolean
288
+ }
289
+ export type Slash = '/' | '\\' | '+'
290
+ /**
291
+ * A single tile on the board.
292
+ */
293
+ export type Tile = {
294
+ id: TileId
295
+ loc: Point
296
+ type: TileType
297
+ move: number
298
+ seq: number
299
+ }
300
+ export type TileId = string
301
+ /**
302
+ * When a tile is dropped, this object represents the results.
303
+ */
304
+ export type TileDrop = {
305
+ dropped: Tile[]
306
+ notation: Notation
307
+ valid: boolean
308
+ }
309
+ export type TileType = ValidTiles | 'x'
310
+ export type TraxVariant = 'trax' | 'traxloop' | 'trax8'
311
+ export type ValidTiles = 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
312
+ import type { PointLike } from '@slugbugblue/point'
313
+ import { Point } from '@slugbugblue/point'
package/src/engine.js CHANGED
@@ -4,9 +4,82 @@
4
4
  * @license Apache-2.0
5
5
  */
6
6
 
7
- /// <reference path="./types.d.ts" />
8
-
7
+ /** @import { PointLike } from '@slugbugblue/point' */
9
8
  import { Point } from '@slugbugblue/point'
9
+ import { version } from './version.js'
10
+
11
+ // Type definitions
12
+
13
+ /** Color is a single character to represent white or black. */
14
+ /** @typedef {'w' | 'b'} Color */
15
+
16
+ /**
17
+ * One end of a line and the tiles taken to get there.
18
+ * @typedef {Object} LineEnd
19
+ * @property {Point} loc
20
+ * @property {TileId[]} path
21
+ */
22
+
23
+ /** A notation of a move. */
24
+ /** @typedef {string} Notation */
25
+
26
+ /**
27
+ * A tile type and a location determine a raw move.
28
+ * @typedef {Object} RawMove
29
+ * @property {TileType} type
30
+ * @property {Point} loc
31
+ */
32
+
33
+ /**
34
+ * Treat the save state as an opaque object,
35
+ * produced by save() and fed into restore().
36
+ * @typedef {Object} SaveState
37
+ * @property {string} id
38
+ * @property {number} move
39
+ * @property {number} turn
40
+ * @property {boolean} over
41
+ * @property {number} left
42
+ * @property {number} right
43
+ * @property {number} top
44
+ * @property {number} bottom
45
+ * @property {Notation} notation
46
+ * @property {string} tiles
47
+ * @property {string} path
48
+ * @property {boolean} invalid
49
+ */
50
+
51
+ /** Representations of the different ways a tile can curve. */
52
+ /** @typedef {'/' | '\\' | '+'} Slash */
53
+
54
+ /**
55
+ * A single tile on the board.
56
+ * @typedef {Object} Tile
57
+ * @property {TileId} id
58
+ * @property {Point} loc
59
+ * @property {TileType} type
60
+ * @property {number} move
61
+ * @property {number} seq
62
+ */
63
+
64
+ /** A TileId is just a string. */
65
+ /** @typedef {string} TileId */
66
+
67
+ /**
68
+ * When a tile is dropped, this object represents the results.
69
+ * @typedef {Object} TileDrop
70
+ * @property {Tile[]} dropped
71
+ * @property {Notation} notation
72
+ * @property {boolean} valid
73
+ */
74
+
75
+ /** Invalid tiles are represented by 'x'. */
76
+ /** @typedef {ValidTiles | 'x'} TileType */
77
+
78
+ /** All of the variants supported by the engine. */
79
+ /** @typedef {'trax' | 'traxloop' | 'trax8'} TraxVariant */
80
+
81
+ /** Tile type names are single letters a-f encoding edge colors. */
82
+ /** @typedef {'a' | 'b' | 'c' | 'd' | 'e' | 'f'} ValidTiles */
10
83
 
11
84
  // Fun trax helper constants
12
85
 
@@ -50,11 +123,11 @@ const symmetry = {
50
123
  // Fun trax helper functions
51
124
 
52
125
  /** Apply certain combinations of symmetry.
53
- * @arg {TileType} tile - the tile to apply symmetry to
126
+ * @arg {ValidTiles} tile - the tile to apply symmetry to
54
127
  * @arg {boolean} [rightToLeft] - mirror the tile
55
128
  * @arg {boolean} [bottomToTop] - flip the tile
56
129
  * @arg {boolean} [rotate] - rotate the tile counterclockwise
57
- * @returns {TileType}
130
+ * @returns {ValidTiles}
58
131
  */
59
132
  const applySymmetry = (tile, rightToLeft, bottomToTop, rotate) => {
60
133
  if (rightToLeft) tile = symmetry.mirror[tile]
@@ -63,34 +136,35 @@ const applySymmetry = (tile, rightToLeft, bottomToTop, rotate) => {
63
136
  return tile
64
137
  }
65
138
 
66
- // Unexpected note: str.includes(t) is true if t is '' but false if t is undefined
139
+ // Note: String(undefined) === 'undefined', which is never a valid tile letter,
140
+ // so these functions correctly return false when t is undefined.
67
141
  /** The color at the top of the tile.
68
- * @arg {string} t - the tile to check
142
+ * @arg {string | undefined} t - the tile to check
69
143
  * @returns {Color|false} the color or false if t is not a valid tile
70
144
  */
71
145
  const upColor = (t) =>
72
- 'abc'.includes(t) ? 'b' : 'def'.includes(t) ? 'w' : false
146
+ 'abc'.includes(String(t)) ? 'b' : 'def'.includes(String(t)) ? 'w' : false
73
147
 
74
148
  /** The color at the bottom of the tile.
75
- * @arg {string} t - the tile to check
149
+ * @arg {string | undefined} t - the tile to check
76
150
  * @returns {Color|false} the color or false if t is not a valid tile
77
151
  */
78
152
  const downColor = (t) =>
79
- 'bdf'.includes(t) ? 'b' : 'ace'.includes(t) ? 'w' : false
153
+ 'bdf'.includes(String(t)) ? 'b' : 'ace'.includes(String(t)) ? 'w' : false
80
154
 
81
155
  /** The color at the right edge of the tile.
82
- * @arg {string} t - the tile to check
156
+ * @arg {string | undefined} t - the tile to check
83
157
  * @returns {Color|false} the color or false if t is not a valid tile
84
158
  */
85
159
  const rightColor = (t) =>
86
- 'ade'.includes(t) ? 'b' : 'bcf'.includes(t) ? 'w' : false
160
+ 'ade'.includes(String(t)) ? 'b' : 'bcf'.includes(String(t)) ? 'w' : false
87
161
 
88
162
  /** The color at the left edge of the tile.
89
- * @arg {string} t - the tile to check
163
+ * @arg {string | undefined} t - the tile to check
90
164
  * @returns {Color|false} the color or false if t is not a valid tile
91
165
  */
92
166
  const leftColor = (t) =>
93
- 'cef'.includes(t) ? 'b' : 'abd'.includes(t) ? 'w' : false
167
+ 'cef'.includes(String(t)) ? 'b' : 'abd'.includes(String(t)) ? 'w' : false
94
168
 
95
169
  /** Add an empty space to the position encoding string.
96
170
  * @arg {string} code - The position encoding string
@@ -98,7 +172,7 @@ const leftColor = (t) =>
98
172
  */
99
173
  const addBlank = (code) => {
100
174
  // Encode missing tiles as digits 0-9, for 1-10 missing
101
- const lastNumber = code.codePointAt(code.length - 1) // This is NaN if code is empty, which is ok
175
+ const lastNumber = /** @type {number} */ (code.codePointAt(code.length - 1)) // Undefined if code is empty, which is ok
102
176
  if (lastNumber > 47 && lastNumber < 57) {
103
177
  return code.slice(0, -1) + String.fromCodePoint(lastNumber + 1)
104
178
  }
@@ -118,6 +192,8 @@ const codeRowLength = (row) =>
118
192
  /** A digital representation of a Trax game. */
119
193
  export class Trax {
120
194
  // Static class properties
195
+ /** @readonly */
196
+ static version = version
121
197
  /** @readonly @type {Record<TraxVariant, string>} */
122
198
  static names = {
123
199
  trax: 'Trax',
@@ -137,17 +213,29 @@ export class Trax {
137
213
  * @arg {number} playerNumber - the player number, 1 or 2
138
214
  * @returns {Color} the color of that player, w or b
139
215
  */
140
- static colorOf = (playerNumber) => ({ 1: 'w', 2: 'b' })[playerNumber]
216
+ static colorOf = (playerNumber) => {
217
+ /** @type {Record<number, Color>} */
218
+ const map = { 1: 'w', 2: 'b' }
219
+ return map[playerNumber]
220
+ }
141
221
  /** Given a color, get the player number.
142
222
  * @arg {string} color - the color, w or b
143
223
  * @returns {number} the player number, 1 or 2
144
224
  */
145
- static playerNumber = (color) => ({ b: 2, w: 1 })[color]
225
+ static playerNumber = (color) => {
226
+ /** @type {Record<string, number>} */
227
+ const map = { b: 2, w: 1 }
228
+ return map[color]
229
+ }
146
230
  /** Given a color, get the other color.
147
231
  * @arg {string} color - the color, w or b
148
232
  * @returns {Color} the other color, b or w
149
233
  */
150
- static other = (color) => ({ b: 'w', w: 'b' })[color]
234
+ static other = (color) => {
235
+ /** @type {Record<string, Color>} */
236
+ const map = { b: 'w', w: 'b' }
237
+ return map[color]
238
+ }
151
239
  /** Encode a numeric column number into the Trax notation column letter.
152
240
  * @arg {number} col - the colum number, with 0 just to the left of the tiles
153
241
  * @returns {string} the encoded column letter
@@ -171,7 +259,8 @@ export class Trax {
171
259
  col = col.toUpperCase()
172
260
  let n = 0
173
261
  while (col.length > 0) {
174
- n += (col.codePointAt(0) - 64) * 26 ** (col.length - 1)
262
+ const cp = /** @type {number} */ (col.codePointAt(0))
263
+ n += (cp - 64) * 26 ** (col.length - 1)
175
264
  col = col.slice(1)
176
265
  }
177
266
 
@@ -312,10 +401,12 @@ export class Trax {
312
401
 
313
402
  /** The type of tile at the given location.
314
403
  * @arg {PointLike} loc - the location the tile is in
315
- * @returns {TileType|undefined} the type of tile, or undefined if no tile
404
+ * @returns {ValidTiles|undefined} the type of tile, or undefined if no tile
316
405
  */
317
406
  tileAt(loc) {
318
- return (this.tiles[this.tileId(loc)] || {}).type
407
+ return /** @type {ValidTiles | undefined} */ (
408
+ (this.tiles[this.tileId(loc)] || {}).type
409
+ )
319
410
  }
320
411
 
321
412
  /** Is this tile valid?
@@ -435,7 +526,7 @@ export class Trax {
435
526
  const invalids = {}
436
527
  let check = loc.around
437
528
  while (check.length > 0) {
438
- const pos = check.shift()
529
+ const pos = /** @type {Point} */ (check.shift())
439
530
  if (this.validLocation(pos)) {
440
531
  const possibles = this.possibleTiles(pos)
441
532
  if (possibles.length === 1) {
@@ -495,6 +586,7 @@ export class Trax {
495
586
  * takes to get there.
496
587
  */
497
588
  follow(color, loc, from) {
589
+ /** @type {TileId[]} */
498
590
  const path = []
499
591
  let id = this.tileId(loc)
500
592
  let tile = this.tileAt(loc)
@@ -820,7 +912,9 @@ export class Trax {
820
912
  /** @type string */
821
913
  let encoded = applySymmetry(tile, rightToLeft, bottomToTop, rotate)
822
914
  if (this.path.includes(this.tileId(loc))) {
823
- encoded = String.fromCodePoint(encoded.codePointAt(0) + this.turn * 6)
915
+ encoded = String.fromCodePoint(
916
+ /** @type {number} */ (encoded.codePointAt(0)) + this.turn * 6,
917
+ )
824
918
  }
825
919
 
826
920
  if (
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '1.0.1'
2
+ export const version = '1.1.1'