@slugbugblue/trax 0.16.0 → 0.17.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 +7 -3
- package/README.md +8 -7
- package/package.json +1 -1
- package/src/cmds/import-export.js +87 -33
- package/src/cmds/play-try.js +1 -1
- package/src/version.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# @slugbugblue/trax
|
|
2
2
|
|
|
3
|
+
## 0.17.0 - 2022-12-29
|
|
4
|
+
|
|
5
|
+
- The `import` CLI command now loads comments from a .trx file
|
|
6
|
+
|
|
3
7
|
## 0.16.0 - 2022-12-27
|
|
4
8
|
|
|
5
9
|
- Added a `notes` command to the CLI to add comments to a game
|
|
6
10
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
11
|
+
- all comments are included in the output generated by the `export` command
|
|
12
|
+
- the latest comment can be used as a text filter by the `list` command
|
|
13
|
+
- the latest comment is displayed by the `view` and `list` commands
|
|
10
14
|
|
|
11
15
|
- Minor analysis improvements
|
|
12
16
|
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Trax is a two-player boardless board game invented by David Smith. For more
|
|
|
13
13
|
information about Trax, including its [rules][traxrules] and
|
|
14
14
|
[history][traxhistory], see the official website at [traxgame.com][traxgame].
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
The goal of this javascript project is to allow Trax to be played
|
|
17
17
|
programmatically. It can be used as an engine in a web browser, for example at
|
|
18
18
|
[slugbugblue.com][sbb]; or in nodejs, for example by using the `trax` CLI
|
|
19
19
|
provided as part of this project.
|
|
@@ -27,7 +27,7 @@ changes to the engine should meet the same standard.
|
|
|
27
27
|
# Install into a javascript project
|
|
28
28
|
npm install @slugbugblue/trax
|
|
29
29
|
|
|
30
|
-
# Or install globally to use the trax CLI
|
|
30
|
+
# Or install globally to use the trax CLI more easily
|
|
31
31
|
npm install -g @slugbugblue/trax
|
|
32
32
|
```
|
|
33
33
|
|
|
@@ -43,11 +43,12 @@ avoid worries about the need to escape certain characters from the shell, and it
|
|
|
43
43
|
can be easier to run multiple commands back to back.
|
|
44
44
|
|
|
45
45
|
Help is available for the CLI through the use of the `help` command. Type
|
|
46
|
-
`trax help`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
`trax help` (or `npx trax help` with a local installation, or simply `help` if
|
|
47
|
+
run interactively) to see a list of the available commands, and `trax help play`
|
|
48
|
+
to see information about the `play` command. Aliases and abbreviations are
|
|
49
|
+
provided to minimize typing and to try to avoid the requirement of memorizing
|
|
50
|
+
the commands. For example, the `list` command has an alias of `ls`, and the
|
|
51
|
+
`select` command can be activated using `#`.
|
|
51
52
|
|
|
52
53
|
When you first launch the CLI, you can create a new game using the `new`
|
|
53
54
|
command, and then enter moves for that game using `play`. Since `play` is likely
|
package/package.json
CHANGED
|
@@ -137,6 +137,79 @@ export const exportCmd = {
|
|
|
137
137
|
],
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
/** Interpret the rules string of a .trx file.
|
|
141
|
+
* @arg {string} r - rules string in lower case
|
|
142
|
+
* @returns {TraxVariant}
|
|
143
|
+
*/
|
|
144
|
+
const getRules = (r) =>
|
|
145
|
+
r.includes('loop') ? 'traxloop' : r.includes('8x8') ? 'trax8' : 'trax'
|
|
146
|
+
|
|
147
|
+
/** Decode a .trx formatted string into a game, preserving players and comments.
|
|
148
|
+
* @arg {any} CLI - the CLI object
|
|
149
|
+
* @arg {string} content - the contents of the .trx file
|
|
150
|
+
* @returns {boolean} - true if a game was created
|
|
151
|
+
*/
|
|
152
|
+
const interpretFile = (CLI, content) => {
|
|
153
|
+
let rules
|
|
154
|
+
let trax
|
|
155
|
+
let players = []
|
|
156
|
+
const moves = []
|
|
157
|
+
const comments = []
|
|
158
|
+
for (const line of content.split('\n')) {
|
|
159
|
+
if (!line) continue
|
|
160
|
+
const [ln, ...comment] = line.split(/[#;]/)
|
|
161
|
+
if (ln) {
|
|
162
|
+
const lower = ln.toLowerCase()
|
|
163
|
+
if (!rules && lower.includes('trax')) {
|
|
164
|
+
rules = getRules(lower)
|
|
165
|
+
} else if (players.length === 0 && lower.includes(' vs ')) {
|
|
166
|
+
players = ln.split(' ').filter(Boolean)
|
|
167
|
+
} else {
|
|
168
|
+
moves.push(...ln.split(' '))
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (!trax && rules && (players.length > 0 || moves.length > 0)) {
|
|
173
|
+
trax = new Trax(rules)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (moves.length > 0) {
|
|
177
|
+
if (!trax) return false
|
|
178
|
+
if (trax.gameOver) {
|
|
179
|
+
comments.push({
|
|
180
|
+
note: moves.map((c) => c.trim()).join(' '),
|
|
181
|
+
move: trax.move,
|
|
182
|
+
})
|
|
183
|
+
} else {
|
|
184
|
+
trax.playMoves(moves.filter(Boolean))
|
|
185
|
+
moves.splice(0, moves.length)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (comment.length > 0) {
|
|
190
|
+
const note = comment.map((c) => c.trim()).join(' ')
|
|
191
|
+
if (!/^@slugbugblue\/trax cli\.js v/.test(note)) {
|
|
192
|
+
comments.push({
|
|
193
|
+
note,
|
|
194
|
+
move: trax?.move || 0,
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!trax) return false
|
|
201
|
+
|
|
202
|
+
CLI.do('new', rules, ...players)
|
|
203
|
+
CLI.GAMES[String(CLI.GAME.id)].notes = comments
|
|
204
|
+
if (trax.moves.length > 0) {
|
|
205
|
+
CLI.do('play', ...trax.moves)
|
|
206
|
+
} else {
|
|
207
|
+
CLI.save()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return true
|
|
211
|
+
}
|
|
212
|
+
|
|
140
213
|
importCmd.fn = async (CLI, filename) => {
|
|
141
214
|
cli = CLI
|
|
142
215
|
if (!filename) {
|
|
@@ -156,35 +229,11 @@ importCmd.fn = async (CLI, filename) => {
|
|
|
156
229
|
}
|
|
157
230
|
}
|
|
158
231
|
|
|
159
|
-
if (!content) CLI.error(fsError.toString())
|
|
232
|
+
if (!content) return CLI.error(fsError.toString())
|
|
160
233
|
}
|
|
161
234
|
|
|
162
|
-
if (content) {
|
|
163
|
-
|
|
164
|
-
let players = []
|
|
165
|
-
const moves = []
|
|
166
|
-
for (const line of content.split('\n')) {
|
|
167
|
-
if (!line) continue
|
|
168
|
-
const ln = line.split(/[#;]/)[0]
|
|
169
|
-
if (!ln) continue
|
|
170
|
-
const lower = ln.toLowerCase()
|
|
171
|
-
if (!game && lower.includes('trax')) {
|
|
172
|
-
game = 'trax'
|
|
173
|
-
if (lower.includes('loop')) game = 'traxloop'
|
|
174
|
-
if (lower.includes('8x8')) game = 'trax8'
|
|
175
|
-
} else if (players.length === 0 && lower.includes(' vs ')) {
|
|
176
|
-
players = ln.split(' ').filter(Boolean)
|
|
177
|
-
} else {
|
|
178
|
-
moves.push(...ln.split(' '))
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (game) {
|
|
183
|
-
CLI.do('new', game, ...players)
|
|
184
|
-
CLI.do('play', ...moves.filter(Boolean))
|
|
185
|
-
} else {
|
|
186
|
-
CLI.error(filename + ' does not appear to be formatted correctly.')
|
|
187
|
-
}
|
|
235
|
+
if (!interpretFile(CLI, content)) {
|
|
236
|
+
CLI.error(filename + ' does not appear to be formatted correctly.')
|
|
188
237
|
}
|
|
189
238
|
}
|
|
190
239
|
|
|
@@ -204,6 +253,15 @@ const gameNotes = (move, notes) => {
|
|
|
204
253
|
)
|
|
205
254
|
}
|
|
206
255
|
|
|
256
|
+
/** Join two strings together with a character with the appropriate joining
|
|
257
|
+
* character depending on the length of the strings.
|
|
258
|
+
* @arg {string} a - the first string
|
|
259
|
+
* @arg {string} b - the second string
|
|
260
|
+
* @returns {string} - both strings correctly joined
|
|
261
|
+
*/
|
|
262
|
+
const join = (a, b) =>
|
|
263
|
+
a.length === 0 ? b : a.length + b.length > 78 ? a + '\n' + b : a + ' ' + b
|
|
264
|
+
|
|
207
265
|
/** Interleave the game moves with any notes, formatted for the export file.
|
|
208
266
|
* @arg {string[]} moves - an array of move notations
|
|
209
267
|
* @arg {GameNotes} notes? - The notes for a game
|
|
@@ -216,9 +274,7 @@ const interleaveNotation = (moves, notes) => {
|
|
|
216
274
|
for (const move of moves) {
|
|
217
275
|
const comments = gameNotes(moveNumber, notes)
|
|
218
276
|
if (comments) {
|
|
219
|
-
|
|
220
|
-
const space = lengthA > 0 ? (lengthA + lengthC < 78 ? ' ' : '\n') : ''
|
|
221
|
-
content += space + annotation + comments
|
|
277
|
+
content += join(annotation, comments)
|
|
222
278
|
annotation = ''
|
|
223
279
|
}
|
|
224
280
|
|
|
@@ -234,9 +290,7 @@ const interleaveNotation = (moves, notes) => {
|
|
|
234
290
|
|
|
235
291
|
const comments = gameNotes(moveNumber, notes)
|
|
236
292
|
if (comments) {
|
|
237
|
-
|
|
238
|
-
const space = lengthA > 0 ? (lengthA + lengthC < 78 ? ' ' : '\n') : ''
|
|
239
|
-
content += space + annotation + comments
|
|
293
|
+
content += join(annotation, comments)
|
|
240
294
|
annotation = ''
|
|
241
295
|
}
|
|
242
296
|
|
package/src/cmds/play-try.js
CHANGED
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.17.0'
|