@slugbugblue/trax 0.7.0 → 0.8.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.
@@ -24,7 +24,7 @@ import { Point } from './point.js'
24
24
  // Fun trax helper constants
25
25
 
26
26
  const zero = new Point(0, 0)
27
- const notationRegex = /^ *([@a-z]+) *(\d+) *([/\\+]) *$/i
27
+ const notationRegex = /^([@a-z]+)(\d+)([/\\+])$/i
28
28
 
29
29
  const slash = { a: '\\', b: '+', c: '/', d: '/', e: '+', f: '\\' }
30
30
 
@@ -72,7 +72,13 @@ const codeRowLength = (row) =>
72
72
  // This is where the magic happens
73
73
  export const Trax = class {
74
74
  // Static class properties
75
- static variants = new Set(['trax', 'traxloop', 'trax8']) // Known variants
75
+ static names = {
76
+ trax: 'Trax',
77
+ traxloop: 'Loop Trax',
78
+ trax8: '8x8 Trax',
79
+ }
80
+
81
+ static variants = new Set(Object.keys(this.names)) // Known variants
76
82
 
77
83
  // Static class methods
78
84
  static point = (x, y) => new Point(x, y)
@@ -122,13 +128,9 @@ export const Trax = class {
122
128
  // Moves might be a notation string
123
129
  if (moves) {
124
130
  if (typeof moves === 'string') moves = moves.split(/\s+/)
125
- for (let move of moves) {
126
- if (typeof move === 'string') {
127
- move = { move: this.move, notation: move }
128
- }
129
-
130
- if (notationRegex.test(move.notation)) {
131
- this.playMove(move.move, move.notation)
131
+ for (const move of moves) {
132
+ if (notationRegex.test(move)) {
133
+ this.dropTile(move)
132
134
  }
133
135
  }
134
136
  }
@@ -170,6 +172,11 @@ export const Trax = class {
170
172
  }
171
173
  }
172
174
 
175
+ get name() {
176
+ // Get the name of this variant
177
+ return Trax.names[this.rules]
178
+ }
179
+
173
180
  get count() {
174
181
  // Get the number of tiles currently in play
175
182
  return Object.keys(this.tiles).length
@@ -433,9 +440,9 @@ export const Trax = class {
433
440
  return this.dropTile(notation)
434
441
  }
435
442
 
436
- playMove(currentMoveNumber, nextMoveNotation) {
437
- // Generic API call for dropTile
438
- if (currentMoveNumber === this.move) return this.dropTile(nextMoveNotation)
443
+ playMove(moveNumber, notation) {
444
+ // Generic API call for playing a move with move number safety
445
+ if (moveNumber === this.move + 1) return this.dropTile(notation)
439
446
  return { valid: false }
440
447
  }
441
448
 
@@ -482,7 +489,7 @@ export const Trax = class {
482
489
  loc = decoded.loc
483
490
  }
484
491
 
485
- if (this.validLocation(loc) && this.validTile(type, loc)) {
492
+ if (loc && this.validLocation(loc) && this.validTile(type, loc)) {
486
493
  valid = true
487
494
  const saved = this.save() // Just in case we need to roll back
488
495
  notation = this.notate(type, loc) // Determine notation BEFORE we play the move
File without changes
@@ -22,13 +22,19 @@ import { Trax } from './engine.js'
22
22
  const esc = '\u001B[' // Start of console color escape code
23
23
  const off = esc + 'm' // Color reset code
24
24
 
25
- // display a message with optional color
25
+ // Colorize a string
26
+ export const color = (contents = '', fgcolor = '', bgcolor = '') => {
27
+ let ansi = esc
28
+ const c = []
29
+ if (fgcolor) c.push('38;5;' + fgcolor)
30
+ if (bgcolor) c.push('48;5;' + bgcolor)
31
+ ansi += c.join(';') + 'm'
32
+ return ansi + contents
33
+ }
34
+
35
+ // Display a message with optional color
26
36
  export const outty = (message, fgcolor, bgcolor) => {
27
- let ansi = fgcolor || bgcolor ? esc : ''
28
- if (fgcolor) ansi += '38;5;' + fgcolor
29
- if (bgcolor) ansi += '48;5;' + bgcolor
30
- if (ansi) ansi += 'm'
31
- console.log(ansi + message + off)
37
+ console.log(color(message, fgcolor, bgcolor) + off)
32
38
  }
33
39
 
34
40
  let set = 'trax' // Which color set should we draw with?
@@ -44,6 +50,28 @@ const colorSets = {
44
50
  tentative: { b: 235, B: 18, e: 19, t: 244, w: 252, W: 217 },
45
51
  }
46
52
 
53
+ export const name = (rules) => {
54
+ if (Trax.variants.has(rules)) {
55
+ return color(Trax.names[rules], colorSets[rules].t)
56
+ }
57
+
58
+ return rules
59
+ }
60
+
61
+ export const bubble = (clr, text) => {
62
+ const colors = {
63
+ w: { fg: 236, bg: 153 },
64
+ b: { fg: 250, bg: 18 },
65
+ wd: { fg: 236, bg: 248 },
66
+ bd: { fg: 248, bg: 236 },
67
+ wh: { fg: 63, bg: 123 },
68
+ bh: { fg: 220, bg: 20 },
69
+ }
70
+
71
+ const c = colors[clr]
72
+ return color('', c.bg) + color(text, c.fg, c.bg) + off + color('', c.bg)
73
+ }
74
+
47
75
  const ln = 'm\u2584' // Lower half block -- with the leading m to terminate ansi color escape
48
76
  const up = 'm\u2588' // Full block
49
77
  const lt = 'm\u2599' // Lower half and left half block
@@ -201,29 +229,67 @@ export const traxGame = (game = 'trax', moves = '') => {
201
229
  return trax
202
230
  }
203
231
 
204
- export const displayGame = (game = 'trax', moves = '', tentative = false) => {
205
- const trax = traxGame(game, moves)
232
+ const printNotation = (trax, tentative) => {
233
+ let b = false
234
+ let n = 1
235
+ let out = ''
236
+ let length = 0
237
+ const t = tentative ? trax.moves.length : 0
238
+ for (const move of trax.moves) {
239
+ const c = (b ? 'b' : 'w') + (t === n ? 'd' : '')
240
+ const notation = String(n) + ' ' + move
241
+ if (length + notation.length + 3 > process.stdout.columns) {
242
+ out += '\n'
243
+ length = 0
244
+ }
245
+
246
+ out += bubble(c, notation) + ' '
247
+ length += notation.length + 3
248
+ b = !b
249
+ n++
250
+ }
251
+
252
+ outty(out)
253
+ }
254
+
255
+ export const display = (game, players, tentative = false) => {
256
+ const trax = traxGame(game)
257
+ const saved = trax.save()
258
+ const colors = ['white', 'black']
259
+ if (!Array.isArray(players)) players = colors
206
260
  let { icon } = trax
207
261
  if (tentative) {
208
262
  const drops = trax.dropTile(tentative)
209
- if (drops.valid) {
263
+ if (drops.valid || drops.dropped.length > 0) {
210
264
  icon = trax.dropsIcon(drops)
211
265
  } else {
212
266
  tentative = false
213
267
  }
214
268
  }
215
269
 
216
- console.info(trax.notation)
270
+ printNotation(trax, tentative)
217
271
  printIcon(icon, trax.rules)
218
- if (tentative) console.info('--- tentative position ---')
219
- const name = { 1: 'white', 2: 'black' }[trax.turn]
272
+ const nameColor = { 1: 'w', 2: 'b' }[trax.turn]
273
+ if (tentative) {
274
+ const otherColor = { w: 'bd', b: 'wd' }[nameColor] || 'wd'
275
+ outty('---' + bubble(otherColor, 'tentative position') + off + '---')
276
+ }
277
+
278
+ const name = players[trax.turn - 1] || colors[trax.turn - 1]
220
279
  if (trax.over) {
221
280
  if (trax.turn) {
222
- console.info(name + ' wins')
281
+ outty(bubble(nameColor + 'h', name) + off + ' wins')
223
282
  } else {
224
- console.info('game end' + (tentative ? 's' : 'ed') + ' in a draw')
283
+ outty('game end' + (tentative ? 's' : 'ed') + ' in a draw')
225
284
  }
226
285
  } else if (trax.turn) {
227
- console.info((tentative ? 'leaving ' : '') + name + ' to play')
286
+ outty(
287
+ (tentative ? 'leaving ' : '') +
288
+ bubble(nameColor, name) +
289
+ off +
290
+ ' to play',
291
+ )
228
292
  }
293
+
294
+ if (tentative) trax.restore(saved)
229
295
  }
package/src/version.js ADDED
@@ -0,0 +1,2 @@
1
+ // Generated by genversion.
2
+ export const version = '0.8.0'