@slugbugblue/trax 0.8.0 → 0.9.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,129 @@
1
+ /* Copyright 2022 Chad Transtrum
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
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.
14
+ */
15
+
16
+ // CLI play/try commands
17
+
18
+ const moveRx = /^\d+\.?$/
19
+ const notationRx = /^[@a-z]+\d+[bps/\\+]$/i
20
+
21
+ export const playCmd = {
22
+ name: 'play',
23
+ alt: ['move', 'mv'],
24
+ args: '<move> [...]',
25
+ comp: '<play>',
26
+ desc: 'play a move',
27
+ rx: [moveRx, notationRx],
28
+ help: [
29
+ 'Enter the move in standard Trax notation. The final character of the',
30
+ 'notation can be replaced with a letter for ease of entering at the',
31
+ 'command line. Use <s> for "/", <b> for "\\", and <p> for "+".',
32
+ 'Multiple moves can be submitted at once. Move numbers are optional,',
33
+ 'but if included, they will be checked for accuracy.',
34
+ ],
35
+ }
36
+
37
+ export const tryCmd = {
38
+ name: 'try',
39
+ alt: 'see',
40
+ args: '<move>',
41
+ comp: '<play>',
42
+ desc: 'see the effects of a move',
43
+ help: [
44
+ 'View a move without committing to it. This is useful for seeing the',
45
+ 'effects of forced tiles.',
46
+ ],
47
+ }
48
+
49
+ const fixNotation = (move) => {
50
+ if (move.endsWith('b')) return move.slice(0, -1) + '\\'
51
+ if (move.endsWith('s')) return move.slice(0, -1) + '/'
52
+ if (move.endsWith('p')) return move.slice(0, -1) + '+'
53
+ return move
54
+ }
55
+
56
+ playCmd.fn = (CLI, ...moves) => {
57
+ if (moves.length === 0 || !moves[0]) {
58
+ CLI.error('You must provide a move.')
59
+ return CLI.do('help', 'play')
60
+ }
61
+
62
+ if (!CLI.GAME?.id) {
63
+ CLI.do('new')
64
+ }
65
+
66
+ if (CLI.TRAX.over) {
67
+ return CLI.error('The game is over.')
68
+ }
69
+
70
+ const start = CLI.TRAX.move
71
+ let checkMove
72
+
73
+ for (let move of moves) {
74
+ if (notationRx.test(move)) {
75
+ const moveNumber = CLI.TRAX.move
76
+ move = fixNotation(move)
77
+ if (checkMove) {
78
+ CLI.TRAX.playMove(checkMove, move)
79
+ } else {
80
+ CLI.TRAX.play(move)
81
+ }
82
+
83
+ if (CLI.TRAX.move === moveNumber) {
84
+ CLI.error(
85
+ 'Move "' +
86
+ (checkMove ? checkMove + '. ' : '') +
87
+ move +
88
+ '" is invalid.',
89
+ )
90
+ }
91
+ } else if (moveRx.test(move)) {
92
+ checkMove = Number(move)
93
+ } else if (move) {
94
+ CLI.error('Move "' + move + '" is not in the correct notation.')
95
+ }
96
+ }
97
+
98
+ if (CLI.TRAX.move !== start) {
99
+ CLI.updateGameData()
100
+ CLI.do('view')
101
+ }
102
+ }
103
+
104
+ tryCmd.fn = (CLI, move) => {
105
+ if (move.length === 0) {
106
+ CLI.error('You must provide a move.')
107
+ return CLI.do('help', 'try')
108
+ }
109
+
110
+ if (!CLI.TRAX) {
111
+ CLI.do('new')
112
+ }
113
+
114
+ if (CLI.TRAX.over) {
115
+ return CLI.error('The game is over.')
116
+ }
117
+
118
+ if (notationRx.test(move)) {
119
+ move = fixNotation(move)
120
+ const play = CLI.TRAX.dropTile(move, undefined, 'tentative')
121
+ if (play.valid || play.dropped.length > 0) {
122
+ CLI.display(CLI.TRAX, CLI.GAME.players, move)
123
+ } else {
124
+ CLI.error('Move is invalid.')
125
+ }
126
+ } else {
127
+ CLI.error('Move is invalid.')
128
+ }
129
+ }
@@ -0,0 +1,47 @@
1
+ /* Copyright 2022 Chad Transtrum
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
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.
14
+ */
15
+
16
+ // CLI select command
17
+
18
+ export const selectCmd = {
19
+ name: 'select',
20
+ alt: ['choose', '#'],
21
+ args: '#id [command]',
22
+ comp: '<id> <cmd>',
23
+ desc: 'select a different game',
24
+ rx: /^#\d+$/,
25
+ help: [
26
+ 'Make another game the default game of future commands. If another',
27
+ 'command is included, that command will be run immediately.',
28
+ ],
29
+ }
30
+
31
+ selectCmd.fn = (CLI, id, ...cmds) => {
32
+ if (!id) {
33
+ CLI.error('Missing id.')
34
+ return CLI.do('help', 'select')
35
+ }
36
+
37
+ if (id.startsWith('#')) id = id.slice(1)
38
+ CLI.load(id)
39
+ if (String(CLI.GAME?.id) === id) {
40
+ CLI.out(CLI.color(`Game #${id} selected.`))
41
+ if (cmds.length > 0) {
42
+ CLI.doNext(cmds.join(' '))
43
+ }
44
+ } else {
45
+ CLI.error('Invalid id. Type "list" to see available games.')
46
+ }
47
+ }
@@ -0,0 +1,40 @@
1
+ /* Copyright 2022 Chad Transtrum
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
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.
14
+ */
15
+
16
+ // CLI undo command
17
+
18
+ export const undoCmd = {
19
+ name: 'undo',
20
+ args: '[n]',
21
+ comp: '<move>',
22
+ desc: 'undo the last move in a game',
23
+ help: [
24
+ 'Backtrack one or more moves in a game. Type "undo" to take back the last',
25
+ 'move, or "undo 2" to undo the last two moves.',
26
+ ],
27
+ }
28
+
29
+ undoCmd.fn = (CLI, n) => {
30
+ n = Math.max(1, Math.floor(Number(n) || 1)) // Get an integer 1 or higher
31
+
32
+ const { moves } = CLI.TRAX
33
+ const undo = moves.slice(0, 0 - n)
34
+ if (moves.length === undo.length) {
35
+ CLI.error('Unable to undo.')
36
+ } else {
37
+ CLI.setGame(undo)
38
+ CLI.do('view')
39
+ }
40
+ }
@@ -0,0 +1,53 @@
1
+ /* Copyright 2022 Chad Transtrum
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
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.
14
+ */
15
+
16
+ // CLI view command
17
+
18
+ export const viewCmd = {
19
+ name: 'view',
20
+ alt: ['show', 'display'],
21
+ args: '[move number]',
22
+ comp: '<move>',
23
+ desc: 'show the game board',
24
+ help: [
25
+ 'Show the current game. Include a move number to see the board as it was at',
26
+ 'that move.',
27
+ ],
28
+ }
29
+
30
+ viewCmd.fn = (CLI, move) => {
31
+ if (!CLI.GAME?.id) {
32
+ return CLI.error('No active game. Type "new" to start a game.')
33
+ }
34
+
35
+ const trax = CLI.TRAX
36
+
37
+ let show = Number.POSITIVE_INFINITY
38
+ if (move && Number(move) >= 0 && Number(move) <= trax.moves.length) {
39
+ show = Number(move)
40
+ }
41
+
42
+ const players = CLI.GAME.players || ['white', 'black']
43
+
44
+ CLI.out(
45
+ CLI.color('#' + CLI.ID + ' ') +
46
+ CLI.name(trax.rules) +
47
+ ' ' +
48
+ CLI.bubble('w' + (trax.turn === 1 ? 'h' : ''), players[0]) +
49
+ CLI.color(' vs ') +
50
+ CLI.bubble('b' + (trax.turn === 2 ? 'h' : ''), players[1]),
51
+ )
52
+ CLI.display(trax, players, false, show)
53
+ }
package/src/tty.js CHANGED
@@ -24,12 +24,10 @@ const off = esc + 'm' // Color reset code
24
24
 
25
25
  // Colorize a string
26
26
  export const color = (contents = '', fgcolor = '', bgcolor = '') => {
27
- let ansi = esc
28
27
  const c = []
29
28
  if (fgcolor) c.push('38;5;' + fgcolor)
30
29
  if (bgcolor) c.push('48;5;' + bgcolor)
31
- ansi += c.join(';') + 'm'
32
- return ansi + contents
30
+ return esc + c.join(';') + 'm' + contents
33
31
  }
34
32
 
35
33
  // Display a message with optional color
@@ -229,14 +227,14 @@ export const traxGame = (game = 'trax', moves = '') => {
229
227
  return trax
230
228
  }
231
229
 
232
- const printNotation = (trax, tentative) => {
230
+ const printNotation = (trax, tentative, show = Number.POSITIVE_INFINITY) => {
233
231
  let b = false
234
232
  let n = 1
235
233
  let out = ''
236
234
  let length = 0
237
- const t = tentative ? trax.moves.length : 0
235
+ const t = tentative ? trax.moves.length - 1 : show
238
236
  for (const move of trax.moves) {
239
- const c = (b ? 'b' : 'w') + (t === n ? 'd' : '')
237
+ const c = (b ? 'b' : 'w') + (t < n ? 'd' : show === n ? 'h' : '')
240
238
  const notation = String(n) + ' ' + move
241
239
  if (length + notation.length + 3 > process.stdout.columns) {
242
240
  out += '\n'
@@ -252,7 +250,12 @@ const printNotation = (trax, tentative) => {
252
250
  outty(out)
253
251
  }
254
252
 
255
- export const display = (game, players, tentative = false) => {
253
+ export const display = (
254
+ game,
255
+ players,
256
+ tentative = false,
257
+ showMove = Number.POSITIVE_INFINITY,
258
+ ) => {
256
259
  const trax = traxGame(game)
257
260
  const saved = trax.save()
258
261
  const colors = ['white', 'black']
@@ -265,9 +268,13 @@ export const display = (game, players, tentative = false) => {
265
268
  } else {
266
269
  tentative = false
267
270
  }
271
+ } else if (showMove <= trax.moves.length) {
272
+ icon = trax.dropsIcon({
273
+ dropped: Object.values(trax.tiles).filter((t) => t.move > showMove),
274
+ })
268
275
  }
269
276
 
270
- printNotation(trax, tentative)
277
+ printNotation(trax, tentative, showMove)
271
278
  printIcon(icon, trax.rules)
272
279
  const nameColor = { 1: 'w', 2: 'b' }[trax.turn]
273
280
  if (tentative) {
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.8.0'
2
+ export const version = '0.9.0'