@slugbugblue/trax-cli 0.11.0 → 0.12.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.
- package/CHANGELOG.md +12 -8
- package/README.md +1 -1
- package/package.json +10 -12
- package/src/cli.js +24 -19
- package/src/cmds/delete.js +1 -1
- package/src/cmds/help.js +1 -1
- package/src/cmds/import-export.js +35 -31
- package/src/cmds/list.js +0 -1
- package/src/cmds/new.js +12 -2
- package/src/cmds/notes.js +1 -1
- package/src/cmds/play-try.js +1 -1
- package/src/cmds/puzzles.js +11 -11
- package/src/types.d.ts +2 -74
- package/src/version.js +1 -1
- package/.rgignore +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @slugbugblue/trax
|
|
2
2
|
|
|
3
|
+
## 0.12.1 - 2025-12-02
|
|
4
|
+
|
|
5
|
+
- Bugfix: file read/write broken after migrating to mkdir with different
|
|
6
|
+
signature
|
|
7
|
+
|
|
8
|
+
## 0.12.0 - 2025-11-08
|
|
9
|
+
|
|
10
|
+
- Fix a rare bug that could alter player names of existing games
|
|
11
|
+
- The `version` command now also shows version of some dependencies
|
|
12
|
+
- Update dependencies
|
|
13
|
+
- Update code to meet new xo guidelines
|
|
14
|
+
|
|
3
15
|
## 0.11.0 - 2023-03-25
|
|
4
16
|
|
|
5
17
|
- Pull CLI from `@slugbugblue/trax` into its own repository
|
|
@@ -15,11 +27,9 @@
|
|
|
15
27
|
## 0.9.0 - 2023-02-05
|
|
16
28
|
|
|
17
29
|
- CLI improvements:
|
|
18
|
-
|
|
19
30
|
- Puzzle information is now stored as notes, to make it searchable
|
|
20
31
|
|
|
21
32
|
- More puzzles:
|
|
22
|
-
|
|
23
33
|
- Martin M. S. Pedersen contributed eleven new puzzles
|
|
24
34
|
|
|
25
35
|
## 0.8.0 - 2022-12-29
|
|
@@ -29,7 +39,6 @@
|
|
|
29
39
|
## 0.7.0 - 2022-12-27
|
|
30
40
|
|
|
31
41
|
- Added a `notes` command to the CLI to add comments to a game
|
|
32
|
-
|
|
33
42
|
- all comments are included in the output generated by the `export` command
|
|
34
43
|
- the latest comment can be used as a text filter by the `list` command
|
|
35
44
|
- the latest comment is displayed by the `view` and `list` commands
|
|
@@ -37,32 +46,27 @@
|
|
|
37
46
|
## 0.6.0 - 2022-12-14
|
|
38
47
|
|
|
39
48
|
- Added shared `puzzles` commands to the CLI:
|
|
40
|
-
|
|
41
49
|
- `trax ls puzzles`: see all the puzzles
|
|
42
50
|
- `trax new puzzle`: start a new puzzle
|
|
43
51
|
|
|
44
52
|
## 0.5.0 - 2022-12-05
|
|
45
53
|
|
|
46
54
|
- Added `puzzles` to the CLI:
|
|
47
|
-
|
|
48
55
|
- `trax puzzles ls`: see all the puzzles
|
|
49
56
|
- `trax puzzle new`: start a new puzzle
|
|
50
57
|
|
|
51
58
|
## 0.4.0 - 2022-11-25
|
|
52
59
|
|
|
53
60
|
- Utilize the newly added move suggestions from `trax-analyst` to the CLI
|
|
54
|
-
|
|
55
61
|
- added the `suggest` CLI command for quick access to a random suggestion
|
|
56
62
|
|
|
57
63
|
- Use font glyphs for text bubbles in `tty.js` only if one of the following
|
|
58
64
|
environment variables are defined and non-empty:
|
|
59
|
-
|
|
60
65
|
- `NERDFONT`, `POWERLINE`, `P9K_TTY`, `P9K_SSH`
|
|
61
66
|
|
|
62
67
|
## 0.3.0 - 2022-09-22
|
|
63
68
|
|
|
64
69
|
- Added the initial work on `trax-analyst`
|
|
65
|
-
|
|
66
70
|
- added the `analyze` CLI command to see an analysis
|
|
67
71
|
|
|
68
72
|
## 0.2.0 - 2022-04-24
|
package/README.md
CHANGED
|
@@ -150,7 +150,7 @@ Trax][gnutrax] for over two decades, and has a lot of expertise in this area.
|
|
|
150
150
|
|
|
151
151
|
## License
|
|
152
152
|
|
|
153
|
-
Copyright 2019-
|
|
153
|
+
Copyright 2019-2025 Chad Transtrum
|
|
154
154
|
|
|
155
155
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
156
156
|
the files in this project except in compliance with the License. You may obtain
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slugbugblue/trax-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Trax command line interface",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"trax",
|
|
@@ -15,9 +15,7 @@
|
|
|
15
15
|
"types": "./src/types.d.ts",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": "./src/cli.js",
|
|
18
|
-
"./utils": "./src/utils.js"
|
|
19
|
-
"./version": "./src/version.js",
|
|
20
|
-
"./version.js": "./src/version.js"
|
|
18
|
+
"./utils": "./src/utils.js"
|
|
21
19
|
},
|
|
22
20
|
"repository": "gitlab:slugbugblue/trax-cli",
|
|
23
21
|
"bin": {
|
|
@@ -25,27 +23,26 @@
|
|
|
25
23
|
},
|
|
26
24
|
"scripts": {
|
|
27
25
|
"genversion": "genversion --es6 src/version.js",
|
|
28
|
-
"git-add": "git add src/version.js
|
|
26
|
+
"git-add": "git add src/version.js",
|
|
29
27
|
"test": "xo",
|
|
30
|
-
"prepare": "husky
|
|
28
|
+
"prepare": "husky",
|
|
31
29
|
"preversion": "npm test",
|
|
32
30
|
"version": "npm run genversion ; npm run git-add",
|
|
33
31
|
"postversion": "git push && git push --tags && npm publish"
|
|
34
32
|
},
|
|
35
33
|
"dependencies": {
|
|
36
|
-
"@slugbugblue/trax": "^0.
|
|
37
|
-
"@slugbugblue/trax-analyst": "^0.
|
|
34
|
+
"@slugbugblue/trax": "^1.0.0",
|
|
35
|
+
"@slugbugblue/trax-analyst": "^0.13.0",
|
|
38
36
|
"@slugbugblue/trax-puzzles": "^0.5.0",
|
|
39
37
|
"@slugbugblue/trax-tty": "^1.0.0",
|
|
40
38
|
"env-paths": "^3.0.0",
|
|
41
|
-
"make-dir": "^3.1.0",
|
|
42
39
|
"yaml": "^2.0.0-11"
|
|
43
40
|
},
|
|
44
41
|
"devDependencies": {
|
|
45
42
|
"genversion": "^3.0.2",
|
|
46
|
-
"husky": "^
|
|
47
|
-
"prettier": "^2.
|
|
48
|
-
"xo": "
|
|
43
|
+
"husky": "^9.0.1",
|
|
44
|
+
"prettier": "^3.2.0",
|
|
45
|
+
"xo": "^1.2.3"
|
|
49
46
|
},
|
|
50
47
|
"type": "module",
|
|
51
48
|
"engines": {
|
|
@@ -61,6 +58,7 @@
|
|
|
61
58
|
},
|
|
62
59
|
"xo": {
|
|
63
60
|
"prettier": true,
|
|
61
|
+
"space": true,
|
|
64
62
|
"rules": {
|
|
65
63
|
"curly": [
|
|
66
64
|
"error",
|
package/src/cli.js
CHANGED
|
@@ -18,13 +18,11 @@
|
|
|
18
18
|
|
|
19
19
|
import process from 'node:process'
|
|
20
20
|
import repl from 'node:repl'
|
|
21
|
-
|
|
22
21
|
import YAML from 'yaml'
|
|
23
|
-
|
|
24
22
|
import { Trax } from '@slugbugblue/trax'
|
|
25
|
-
import { version } from '@slugbugblue/trax
|
|
23
|
+
import { version as traxVersion } from '@slugbugblue/trax/version'
|
|
24
|
+
import { version as analystVersion } from '@slugbugblue/trax-analyst'
|
|
26
25
|
import * as tty from '@slugbugblue/trax-tty'
|
|
27
|
-
|
|
28
26
|
// Load all the commands as individual plugins
|
|
29
27
|
import { analyzeCmd } from './cmds/analyze.js'
|
|
30
28
|
import { deleteCmd } from './cmds/delete.js'
|
|
@@ -45,6 +43,7 @@ import { selectCmd } from './cmds/select.js'
|
|
|
45
43
|
import { suggestCmd } from './cmds/suggest.js'
|
|
46
44
|
import { undoCmd } from './cmds/undo.js'
|
|
47
45
|
import { viewCmd } from './cmds/view.js'
|
|
46
|
+
import { version } from './version.js'
|
|
48
47
|
|
|
49
48
|
// Because typeof [] and null are both 'object'. is([], 'arr') => true
|
|
50
49
|
const is = (variable, type) =>
|
|
@@ -60,7 +59,15 @@ const versionCmd = {
|
|
|
60
59
|
opts: ['--version', '-v'],
|
|
61
60
|
desc: 'display version number',
|
|
62
61
|
help: 'Print out the current version of this program.',
|
|
63
|
-
fn: (CLI) =>
|
|
62
|
+
fn: (CLI) =>
|
|
63
|
+
CLI.out(
|
|
64
|
+
[
|
|
65
|
+
`Trax: engine v${traxVersion}`,
|
|
66
|
+
`analyst v${analystVersion}`,
|
|
67
|
+
`tty v${tty.version}`,
|
|
68
|
+
`cli v${version}`,
|
|
69
|
+
].join(' | '),
|
|
70
|
+
),
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
const quitCmd = {
|
|
@@ -121,12 +128,12 @@ const newId = (DATA) => {
|
|
|
121
128
|
* @type Colorer
|
|
122
129
|
*/
|
|
123
130
|
// @ts-ignore
|
|
124
|
-
const color = (text,
|
|
131
|
+
const color = (text, defaultColor) => {
|
|
125
132
|
let out = ''
|
|
126
133
|
let quote = false
|
|
127
134
|
let id = false
|
|
128
|
-
const colors = [
|
|
129
|
-
const c = (t) => tty.color(t, colors
|
|
135
|
+
const colors = [defaultColor]
|
|
136
|
+
const c = (t) => tty.color(t, colors.at(-1) || CLI.COLORS.default)
|
|
130
137
|
const short = (t) => tty.color(t, CLI.COLORS.short) + c()
|
|
131
138
|
for (const char of text) {
|
|
132
139
|
switch (char) {
|
|
@@ -190,7 +197,7 @@ const color = (text, def) => {
|
|
|
190
197
|
}
|
|
191
198
|
}
|
|
192
199
|
|
|
193
|
-
return tty.color(out,
|
|
200
|
+
return tty.color(out, defaultColor || CLI.COLORS.default)
|
|
194
201
|
}
|
|
195
202
|
|
|
196
203
|
// Internal representations of files
|
|
@@ -286,7 +293,7 @@ const CLI = {
|
|
|
286
293
|
},
|
|
287
294
|
|
|
288
295
|
load(id) {
|
|
289
|
-
|
|
296
|
+
id ||= Object.keys(DATA.games || {})[0]
|
|
290
297
|
if (id && DATA.games?.[id] && DATA.games[id].rules) {
|
|
291
298
|
if (id !== String(CONFIG.id)) {
|
|
292
299
|
CONFIG.id = id
|
|
@@ -294,7 +301,7 @@ const CLI = {
|
|
|
294
301
|
}
|
|
295
302
|
|
|
296
303
|
const game = CLI.GAME
|
|
297
|
-
|
|
304
|
+
game.players ||= ['white', 'black']
|
|
298
305
|
CLI.TRAX = new Trax(game.rules, game.moves, 'cli')
|
|
299
306
|
}
|
|
300
307
|
},
|
|
@@ -376,8 +383,8 @@ const CLI = {
|
|
|
376
383
|
},
|
|
377
384
|
|
|
378
385
|
puzzleSolved(id) {
|
|
379
|
-
DATA.puzzles
|
|
380
|
-
DATA.puzzles[id]
|
|
386
|
+
DATA.puzzles ||= {}
|
|
387
|
+
DATA.puzzles[id] ||= { attempts: 1, solved: 0 }
|
|
381
388
|
DATA.puzzles[id].solved += 1
|
|
382
389
|
},
|
|
383
390
|
|
|
@@ -586,7 +593,7 @@ const expand = (completions, match) => {
|
|
|
586
593
|
const completer = (line) => {
|
|
587
594
|
const words = line.split(/\s+/).filter(Boolean)
|
|
588
595
|
|
|
589
|
-
let match = words.
|
|
596
|
+
let match = words.at(-1) || ''
|
|
590
597
|
const previous = new Set(words.slice(1, -1).map((s) => s.toLowerCase()))
|
|
591
598
|
if (line.endsWith(' ')) {
|
|
592
599
|
previous.add(match.toLowerCase())
|
|
@@ -614,11 +621,9 @@ const completer = (line) => {
|
|
|
614
621
|
const word = completions[i]
|
|
615
622
|
if (word.includes('|')) {
|
|
616
623
|
const comps = word.split('|')
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
completions[i] = comps
|
|
621
|
-
}
|
|
624
|
+
completions[i] = comps.some((c) => previous.has(c.toLowerCase()))
|
|
625
|
+
? ''
|
|
626
|
+
: comps
|
|
622
627
|
}
|
|
623
628
|
}
|
|
624
629
|
|
package/src/cmds/delete.js
CHANGED
package/src/cmds/help.js
CHANGED
|
@@ -29,7 +29,7 @@ export const helpCmd = {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// Find the length of the printable characters of the string
|
|
32
|
-
const length = (text) => text.
|
|
32
|
+
const length = (text) => text.replaceAll(/[<">]/g, '').length
|
|
33
33
|
|
|
34
34
|
helpCmd.fn = (CLI, word) => {
|
|
35
35
|
// If we are looking for help on a particular commands, get that command
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Copyright 2022-
|
|
1
|
+
/* Copyright 2022-2025 Chad Transtrum
|
|
2
2
|
*
|
|
3
3
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License.
|
|
@@ -17,10 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import fs from 'node:fs/promises'
|
|
19
19
|
import process from 'node:process'
|
|
20
|
-
|
|
21
20
|
import envPaths from 'env-paths'
|
|
22
|
-
import makeDir from 'make-dir'
|
|
23
|
-
|
|
24
21
|
import { Trax } from '@slugbugblue/trax'
|
|
25
22
|
import { puzzles, sources } from '@slugbugblue/trax-puzzles'
|
|
26
23
|
|
|
@@ -51,7 +48,8 @@ const expandPath = (name) => {
|
|
|
51
48
|
const getPath = async (path) => {
|
|
52
49
|
if (path in PATHS) return PATHS[path]
|
|
53
50
|
if (path in paths) {
|
|
54
|
-
const realPath =
|
|
51
|
+
const realPath = paths[path]
|
|
52
|
+
await fs.mkdir(realPath, { recursive: true })
|
|
55
53
|
PATHS[path] = realPath
|
|
56
54
|
return realPath
|
|
57
55
|
}
|
|
@@ -93,24 +91,21 @@ export const getFile = async (filetype, filename, variable, decode) => {
|
|
|
93
91
|
return variable
|
|
94
92
|
}
|
|
95
93
|
|
|
96
|
-
export const saveFile = (filetype, filename, data) => {
|
|
97
|
-
getPath(filetype)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
.catch(fsOuch)
|
|
110
|
-
})
|
|
111
|
-
.catch(fsOuch)
|
|
94
|
+
export const saveFile = async (filetype, filename, data) => {
|
|
95
|
+
const path = await getPath(filetype)
|
|
96
|
+
if (path) {
|
|
97
|
+
const parts = filename.split('.')
|
|
98
|
+
parts.splice(1, 0, hexy())
|
|
99
|
+
const tmpfile = path + '/' + parts.join('.')
|
|
100
|
+
filename = path + '/' + filename
|
|
101
|
+
try {
|
|
102
|
+
await fs.writeFile(tmpfile, data)
|
|
103
|
+
await fs.rm(filename, { force: true, maxRetries: 5 })
|
|
104
|
+
await fs.rename(tmpfile, filename)
|
|
105
|
+
} catch (error) {
|
|
106
|
+
fsOuch(error)
|
|
112
107
|
}
|
|
113
|
-
}
|
|
108
|
+
}
|
|
114
109
|
}
|
|
115
110
|
|
|
116
111
|
export const importCmd = {
|
|
@@ -182,7 +177,7 @@ const interpretFile = (CLI, content) => {
|
|
|
182
177
|
})
|
|
183
178
|
} else {
|
|
184
179
|
trax.playMoves(moves.filter(Boolean))
|
|
185
|
-
moves.splice(0
|
|
180
|
+
moves.splice(0)
|
|
186
181
|
}
|
|
187
182
|
}
|
|
188
183
|
|
|
@@ -243,12 +238,12 @@ importCmd.fn = async (CLI, filename) => {
|
|
|
243
238
|
* @returns {string} - Notes formatted for this move, or empty string if none
|
|
244
239
|
*/
|
|
245
240
|
const gameNotes = (move, notes) => {
|
|
246
|
-
notes
|
|
241
|
+
notes ||= []
|
|
247
242
|
const moveNotes = notes.filter((n) => n.move === move)
|
|
248
243
|
if (moveNotes.length === 0) return ''
|
|
249
244
|
return (
|
|
250
245
|
'; ' +
|
|
251
|
-
moveNotes.map((n) => n.note.
|
|
246
|
+
moveNotes.map((n) => n.note.replaceAll('\n', '\n; ')).join('\n; ') +
|
|
252
247
|
'\n'
|
|
253
248
|
)
|
|
254
249
|
}
|
|
@@ -299,7 +294,7 @@ const interleaveNotation = (moves, notes) => {
|
|
|
299
294
|
return content
|
|
300
295
|
}
|
|
301
296
|
|
|
302
|
-
exportCmd.fn = (CLI, id, filename) => {
|
|
297
|
+
exportCmd.fn = async (CLI, id, filename) => {
|
|
303
298
|
cli = CLI
|
|
304
299
|
let game = CLI.GAME
|
|
305
300
|
if (id) {
|
|
@@ -345,13 +340,17 @@ exportCmd.fn = (CLI, id, filename) => {
|
|
|
345
340
|
|
|
346
341
|
content += interleaveNotation(trax.moves, game.notes)
|
|
347
342
|
|
|
348
|
-
|
|
343
|
+
filename &&= filename.replaceAll(/[^ a-z\d.~/]/g, '')
|
|
349
344
|
if (filename) {
|
|
350
345
|
const fname = filename.split('/').pop()
|
|
351
346
|
if (!fname) filename += game.rules + game.id
|
|
352
347
|
if (!fname.includes('.')) filename += '.trx'
|
|
353
348
|
CLI.out(CLI.color('Exporting #' + game.id + ' to ') + filename)
|
|
354
|
-
|
|
349
|
+
try {
|
|
350
|
+
fs.writeFile(expandPath(filename), content)
|
|
351
|
+
} catch (error) {
|
|
352
|
+
fsOuch(error)
|
|
353
|
+
}
|
|
355
354
|
} else {
|
|
356
355
|
CLI.out(content)
|
|
357
356
|
}
|
|
@@ -373,9 +372,11 @@ export const findFiles = (path) => {
|
|
|
373
372
|
if (!FOLDERS[prefix]) {
|
|
374
373
|
FOLDERS[prefix] = []
|
|
375
374
|
fs.readdir(folder, { withFileTypes: true })
|
|
375
|
+
// eslint-disable-next-line promise/prefer-await-to-then
|
|
376
376
|
.then((dir) => {
|
|
377
|
-
//
|
|
378
|
-
// at least twice before we
|
|
377
|
+
// At this point, everything is happening asynchronously,
|
|
378
|
+
// so we have to call findFiles at least twice before we
|
|
379
|
+
// get any useful information ...
|
|
379
380
|
const entries = []
|
|
380
381
|
for (const entry of dir) {
|
|
381
382
|
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
@@ -387,7 +388,10 @@ export const findFiles = (path) => {
|
|
|
387
388
|
|
|
388
389
|
FOLDERS[prefix] = entries
|
|
389
390
|
})
|
|
390
|
-
|
|
391
|
+
// eslint-disable-next-line promise/prefer-await-to-then
|
|
392
|
+
.catch(() => {
|
|
393
|
+
// Errors are unimportant and should be silently ignored
|
|
394
|
+
})
|
|
391
395
|
}
|
|
392
396
|
|
|
393
397
|
return FOLDERS[prefix]
|
package/src/cmds/list.js
CHANGED
package/src/cmds/new.js
CHANGED
|
@@ -29,6 +29,7 @@ export const newCmd = {
|
|
|
29
29
|
|
|
30
30
|
// Okay, yes, this is silly
|
|
31
31
|
const pairs = [
|
|
32
|
+
['Aang', 'Katara'],
|
|
32
33
|
['Abbott', 'Costello'],
|
|
33
34
|
['Adam', 'Eve'],
|
|
34
35
|
['Anne Boleyn', 'Henry VIII'],
|
|
@@ -38,14 +39,20 @@ const pairs = [
|
|
|
38
39
|
['Bert', 'Ernie'],
|
|
39
40
|
['Bonnie', 'Clyde'],
|
|
40
41
|
['Calvin', 'Hobbes'],
|
|
42
|
+
['Chandler', 'Monica'],
|
|
43
|
+
['Chewbacca', 'R2-D2'],
|
|
41
44
|
['Chip', 'Dale'],
|
|
42
45
|
['Donald', 'Daisy'],
|
|
46
|
+
['Depp', 'Heard'],
|
|
43
47
|
['Fred', 'Barney'],
|
|
44
48
|
['Fred', 'George'],
|
|
45
49
|
['Frodo', 'Samwise'],
|
|
50
|
+
['Hamilton', 'Burr'],
|
|
46
51
|
['Han', 'Chewie'],
|
|
47
52
|
['Harry', 'Ron'],
|
|
53
|
+
['Holmes', 'Moriarty'],
|
|
48
54
|
['Holmes', 'Watson'],
|
|
55
|
+
['Iñigo', 'Fezzik'],
|
|
49
56
|
['Jekyll', 'Hyde'],
|
|
50
57
|
['Jim', 'Pam'],
|
|
51
58
|
['Joe', 'Volcano'],
|
|
@@ -62,14 +69,16 @@ const pairs = [
|
|
|
62
69
|
['Miss Piggy', 'Kermit'],
|
|
63
70
|
['Mork', 'Mindy'],
|
|
64
71
|
['Obi-Wan', 'Anakin'],
|
|
72
|
+
['p1', 'p2'],
|
|
65
73
|
['Pan', 'Hook'],
|
|
66
74
|
['Phineas', 'Ferb'],
|
|
67
75
|
['player 1', 'player 2'],
|
|
68
|
-
['
|
|
76
|
+
['Potter', 'Voldemort'],
|
|
69
77
|
['R2-D2', 'C-3PO'],
|
|
70
78
|
['Ren', 'Stimpy'],
|
|
71
79
|
['Rick', 'Morty'],
|
|
72
80
|
['Romeo', 'Juliet'],
|
|
81
|
+
['Ross', 'Rachel'],
|
|
73
82
|
['Shaggy', 'Scooby'],
|
|
74
83
|
['Shrek', 'Fiona'],
|
|
75
84
|
['Simon', 'Garfunkel'],
|
|
@@ -84,12 +93,13 @@ const pairs = [
|
|
|
84
93
|
['Tweety', 'Sylvester'],
|
|
85
94
|
['Waldorf', 'Statler'],
|
|
86
95
|
['Wallace', 'Gromit'],
|
|
96
|
+
['Westley', 'Buttercup'],
|
|
87
97
|
['white', 'black'],
|
|
88
98
|
['Woody', 'Buzz'],
|
|
89
99
|
]
|
|
90
100
|
|
|
91
101
|
const pairUp = () => {
|
|
92
|
-
const duo = pairs[Math.floor(Math.random() * pairs.length)]
|
|
102
|
+
const duo = [...pairs[Math.floor(Math.random() * pairs.length)]]
|
|
93
103
|
if (duo[0].toLowerCase() !== duo[0] && Math.random() < 0.5) duo.reverse()
|
|
94
104
|
return duo
|
|
95
105
|
}
|
package/src/cmds/notes.js
CHANGED
package/src/cmds/play-try.js
CHANGED
|
@@ -31,7 +31,7 @@ export const playCmd = {
|
|
|
31
31
|
help: [
|
|
32
32
|
'Enter the move in standard Trax notation. The final character of the',
|
|
33
33
|
'notation can be replaced with a letter for ease of entering at the',
|
|
34
|
-
|
|
34
|
+
String.raw`command line. Use <s> for "/", <b> for "\", and <p> for "+".`,
|
|
35
35
|
'Multiple moves can be submitted at once. Move numbers are optional,',
|
|
36
36
|
'but if included, they will be checked for accuracy.',
|
|
37
37
|
],
|
package/src/cmds/puzzles.js
CHANGED
|
@@ -53,19 +53,19 @@ const showPuzzle = (CLI, id, started = false) => {
|
|
|
53
53
|
if (puzzle.title) out += CLI.color(puzzle.title) + '\n'
|
|
54
54
|
if (puzzle.desc) out += CLI.color.help(puzzle.desc) + '\n'
|
|
55
55
|
out += CLI.color(players[puzzle.player - 1] + ' to win by move ' + puzzle.max)
|
|
56
|
-
const
|
|
56
|
+
const source = sources[puzzle.src]
|
|
57
57
|
|
|
58
|
-
if (
|
|
59
|
-
let
|
|
60
|
-
|
|
61
|
-
? 'copyright ' +
|
|
58
|
+
if (source) {
|
|
59
|
+
let text = '\nPuzzle '
|
|
60
|
+
text += source.copyright
|
|
61
|
+
? 'copyright ' + source.copyright + ' by'
|
|
62
62
|
: 'courtesy of'
|
|
63
|
-
|
|
64
|
-
const url =
|
|
65
|
-
out += CLI.color.white(
|
|
66
|
-
if (
|
|
67
|
-
out += '\n' + CLI.color.optional('License: ' +
|
|
68
|
-
if (
|
|
63
|
+
text += ' ' + source.name
|
|
64
|
+
const url = source.url ? ' ' + CLI.color.help(source.url) : ''
|
|
65
|
+
out += CLI.color.white(text) + url
|
|
66
|
+
if (source.license) {
|
|
67
|
+
out += '\n' + CLI.color.optional('License: ' + source.license)
|
|
68
|
+
if (source.licenseUrl) out += CLI.color.black(' ' + source.licenseUrl)
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
package/src/types.d.ts
CHANGED
|
@@ -4,15 +4,12 @@
|
|
|
4
4
|
* @license Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
/** Color is a single character to represent white or black. */
|
|
8
|
-
type Color = 'w' | 'b'
|
|
9
|
-
|
|
10
7
|
/** Colorize is a fancy function for colorizing text. */
|
|
11
|
-
type Colorize = (text: string,
|
|
8
|
+
type Colorize = (text: string, defaultColor?: string | number) => string
|
|
12
9
|
|
|
13
10
|
/** Colorer is a little too fancy. Hence the gnarly typescript. */
|
|
14
11
|
type Colorer = {
|
|
15
|
-
(text: string,
|
|
12
|
+
(text: string, defaultColor?: string | number): string
|
|
16
13
|
black: Colorize
|
|
17
14
|
command: Colorize
|
|
18
15
|
default: Colorize
|
|
@@ -34,72 +31,3 @@ type GameNote = {
|
|
|
34
31
|
|
|
35
32
|
/** Notes saved in the game object in the CLI. */
|
|
36
33
|
type GameNotes = GameNote[]
|
|
37
|
-
|
|
38
|
-
/** Treat the save state as an opaque object,
|
|
39
|
-
* produced by save() and fed into restore().
|
|
40
|
-
*/
|
|
41
|
-
type SaveState = {
|
|
42
|
-
id: string
|
|
43
|
-
move: number
|
|
44
|
-
turn: number
|
|
45
|
-
over: boolean
|
|
46
|
-
left: number
|
|
47
|
-
right: number
|
|
48
|
-
top: number
|
|
49
|
-
bottom: number
|
|
50
|
-
notation: string
|
|
51
|
-
tiles: string
|
|
52
|
-
path: string
|
|
53
|
-
invalid: boolean
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Representations of the different ways a tile can curve.
|
|
57
|
-
* Matches the symbols used in Trax notation.
|
|
58
|
-
*/
|
|
59
|
-
type Slash = '/' | '\\' | '+'
|
|
60
|
-
|
|
61
|
-
/** Threat definition. */
|
|
62
|
-
type Threat = {
|
|
63
|
-
depth: number
|
|
64
|
-
pattern: string
|
|
65
|
-
rx: RegExp
|
|
66
|
-
value: number
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** A single tile on the board. */
|
|
70
|
-
type Tile = {
|
|
71
|
-
id: TileId
|
|
72
|
-
loc: Point
|
|
73
|
-
type: TileType
|
|
74
|
-
move: number
|
|
75
|
-
seq: number
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** When a tile is dropped, this object represents the results. */
|
|
79
|
-
type TileDrop = {
|
|
80
|
-
dropped: Tile[]
|
|
81
|
-
notation: string
|
|
82
|
-
valid: boolean
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** A TileId is just a string. */
|
|
86
|
-
type TileId = string
|
|
87
|
-
|
|
88
|
-
/** Invalid tiles are represented by 'x'. */
|
|
89
|
-
type TileType = ValidTiles | 'x'
|
|
90
|
-
|
|
91
|
-
/** All of the variants supported by the engine. */
|
|
92
|
-
type TraxVariant = 'trax' | 'traxloop' | 'trax8'
|
|
93
|
-
|
|
94
|
-
/** Tile type names are determined by listing the line color at each edge,
|
|
95
|
-
* starting from the top and going clockwise, and then sorted alphabetically
|
|
96
|
-
* and given a single letter name, so 'bbww' becomes 'a', which gives us six
|
|
97
|
-
* different tile names: a-f, as follows:
|
|
98
|
-
* a b c d e f
|
|
99
|
-
* +--#--+ +--#--+ +--#--+ +--o--+ +--o--+ +--o--+
|
|
100
|
-
* | # | | # | | # | | o | | o | | o |
|
|
101
|
-
* oo ## ooo#ooo ## oo oo ## ####### ## oo
|
|
102
|
-
* | o | | # | | o | | # | | o | | # |
|
|
103
|
-
* +--o--+ +--#--+ +--o--+ +--#--+ +--o--+ +--#--+
|
|
104
|
-
*/
|
|
105
|
-
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.12.1'
|
package/.rgignore
DELETED