@slugbugblue/trax 0.2.0 → 0.3.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 +34 -0
- package/README.md +13 -10
- package/engine.js +10 -1
- package/package.json +1 -1
- package/tests.js +11 -0
- package/tty.js +32 -11
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# @slugbugblue/trax
|
|
2
|
+
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
Display a tentative move on the screen
|
|
6
|
+
|
|
7
|
+
* Add `trax.tentative_icon()` function
|
|
8
|
+
* `tty.display()` now accepts a tentative move
|
|
9
|
+
|
|
10
|
+
## 0.2.0
|
|
11
|
+
|
|
12
|
+
Breaking changes:
|
|
13
|
+
|
|
14
|
+
* Converted from CommonJS to ESM
|
|
15
|
+
* `trax.normalized` now prepends turn information to the string
|
|
16
|
+
|
|
17
|
+
More convenience:
|
|
18
|
+
|
|
19
|
+
* `trax.color`: the color of the player whose turn it is
|
|
20
|
+
* `Trax.color_of[num]`: go from player number to color
|
|
21
|
+
* `Trax.player_num[color]`: or from color to player number
|
|
22
|
+
* `Trax.other[color]`: easily switch from 'w' to 'b' and back
|
|
23
|
+
|
|
24
|
+
## 0.1.0
|
|
25
|
+
|
|
26
|
+
Initial release:
|
|
27
|
+
|
|
28
|
+
* engine.js
|
|
29
|
+
* create a new Trax game with `trax = new Trax()`
|
|
30
|
+
* play one move at a time with `trax.play('@0/')`
|
|
31
|
+
* ... etc
|
|
32
|
+
|
|
33
|
+
* tty.js
|
|
34
|
+
* display a game with `tty.display(trax)`
|
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ The main Trax engine is provided as `engine.js`,
|
|
|
26
26
|
which can be used as follows:
|
|
27
27
|
|
|
28
28
|
```javascript
|
|
29
|
-
|
|
29
|
+
import Trax from '@slugbugblue/trax'
|
|
30
30
|
|
|
31
31
|
let trax = new Trax()
|
|
32
32
|
|
|
@@ -48,7 +48,7 @@ until I get around to documenting the functionality.
|
|
|
48
48
|
|
|
49
49
|
This project is built by [Chad Transtrum][ctrans]
|
|
50
50
|
for [slugbugblue.com][sbb].
|
|
51
|
-
Issues can be opened on the
|
|
51
|
+
Issues can be opened on the
|
|
52
52
|
[gitlab project page][repo].
|
|
53
53
|
|
|
54
54
|
## Contributing
|
|
@@ -66,18 +66,21 @@ and for his generosity in allowing me to
|
|
|
66
66
|
add the game to [GoldToken.com][goldtoken].
|
|
67
67
|
|
|
68
68
|
Thanks to his widow Colleen Foley-Smith
|
|
69
|
-
for extending that
|
|
70
|
-
to allow me to include Trax on [slugbugblue.com][sbb]
|
|
69
|
+
for extending that courtesy
|
|
70
|
+
to allow me to include Trax on [slugbugblue.com][sbb]
|
|
71
|
+
as well.
|
|
71
72
|
|
|
72
73
|
I would also like to extend a huge heartfelt appreciation
|
|
73
74
|
to the magnanimous [Donald G. Bailey][dgb],
|
|
74
75
|
who, through his excellent [book][traxbook],
|
|
75
|
-
taught me the basics (and more!) of Trax
|
|
76
|
-
|
|
76
|
+
taught me the basics (and more!) of Trax.
|
|
77
|
+
I found him always ready to share his insights
|
|
77
78
|
on the mechanics of the game,
|
|
78
|
-
various approaches to encoding its complexities
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
as well as various approaches to encoding its complexities.
|
|
80
|
+
His undeserved kindness
|
|
81
|
+
and infinite patience
|
|
82
|
+
in indulging my many questions
|
|
83
|
+
can never be repaid.
|
|
81
84
|
|
|
82
85
|
## License
|
|
83
86
|
|
|
@@ -98,7 +101,7 @@ limitations under the License.
|
|
|
98
101
|
|
|
99
102
|
## Trax rules copyright
|
|
100
103
|
|
|
101
|
-
In the United States, game mechanics may not be copyrighted
|
|
104
|
+
In the United States, game mechanics may not be copyrighted;
|
|
102
105
|
however, the specific wording of game rules does fall under copyright law.
|
|
103
106
|
|
|
104
107
|
The official rules for Trax are found at http://traxgame.com/about_rules.php.
|
package/engine.js
CHANGED
|
@@ -431,8 +431,12 @@ const Trax = class {
|
|
|
431
431
|
return this.position_code()
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
+
tentative_icon (drops) {
|
|
435
|
+
return this.position_code(undefined, undefined, undefined, undefined, drops)
|
|
436
|
+
}
|
|
437
|
+
|
|
434
438
|
// symmetry helper
|
|
435
|
-
position_code (right_to_left, bottom_to_top, rotate, swap_colors) {
|
|
439
|
+
position_code (right_to_left, bottom_to_top, rotate, swap_colors, drops) {
|
|
436
440
|
const start_x = right_to_left ? this.right : this.left
|
|
437
441
|
const start_y = bottom_to_top ? this.bottom : this.top
|
|
438
442
|
const inc_x = right_to_left ? -1 : 1
|
|
@@ -451,6 +455,9 @@ const Trax = class {
|
|
|
451
455
|
if (this.path.includes(this.tile_id(x, y))) {
|
|
452
456
|
tile = String.fromCharCode(tile.charCodeAt(0) + this.turn * 6)
|
|
453
457
|
}
|
|
458
|
+
if (drops && drops.dropped) {
|
|
459
|
+
if (drops.dropped.filter(t => t.x === x && t.y === y).length) tile = tile.toUpperCase()
|
|
460
|
+
}
|
|
454
461
|
line += tile
|
|
455
462
|
} else {
|
|
456
463
|
line = add_blank(line)
|
|
@@ -504,6 +511,8 @@ const Trax = class {
|
|
|
504
511
|
|
|
505
512
|
// add class methods
|
|
506
513
|
Trax.column = encode_col
|
|
514
|
+
|
|
515
|
+
// and class constants
|
|
507
516
|
Trax.variants = variants
|
|
508
517
|
Trax.color_of = color_of
|
|
509
518
|
Trax.player_num = player_num
|
package/package.json
CHANGED
package/tests.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import test from 'tape'
|
|
2
|
+
import Trax from './engine.js'
|
|
3
|
+
|
|
4
|
+
test('create trax game', t => {
|
|
5
|
+
let trax = new Trax('trax', '@0/', 'tape')
|
|
6
|
+
t.equal(trax.id, 'tape', 'id is assigned')
|
|
7
|
+
t.equal(trax.count, 1, '1 tile is played')
|
|
8
|
+
t.equal(trax.turn, 2, 'player 2 is next')
|
|
9
|
+
t.equal(trax.color, 'b', 'player 2 is black')
|
|
10
|
+
t.end()
|
|
11
|
+
})
|
package/tty.js
CHANGED
|
@@ -38,6 +38,7 @@ const color_sets = { // Colors for terminal sequence: <Esc>[38;5;<color_num>m
|
|
|
38
38
|
trax: { b: 238, B: 57, e: 19, t: 74, w: 255, W: 184 },
|
|
39
39
|
trax8: { b: 236, B: 21, e: 58, t: 137, w: 254, W: 117 },
|
|
40
40
|
traxloop: { b: 235, B: 20, e: 17, t: 61, w: 253, W: 222 },
|
|
41
|
+
tentative: { b: 235, B: 18, e: 19, t: 244, w: 252, W: 217 },
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
const ln = 'm\u2584' // lower half block -- with the leading m to terminate ansi color escape
|
|
@@ -62,6 +63,10 @@ const tiles = { a: 'bbww', b: 'bwbw', c: 'bwwb', d: 'wbbw', e: 'wbwb', f: 'wwbb'
|
|
|
62
63
|
const tile_tty = (tile, top) => { // top: true for first line, false for second
|
|
63
64
|
// quick access to tile color and its opposite in upper case
|
|
64
65
|
let colors = { b: 'b', w: 'w', B: 'w', W: 'b' }
|
|
66
|
+
let save = set
|
|
67
|
+
let tentative = tile !== tile.toLowerCase()
|
|
68
|
+
if (tentative) set = color_sets.tentative
|
|
69
|
+
tile = tile.toLowerCase()
|
|
65
70
|
if (!(tile in tiles)) { // winning paths are represented by adding 6 to the tile char code
|
|
66
71
|
tile = String.fromCharCode(tile.charCodeAt(0) - 6)
|
|
67
72
|
if (tile in tiles) {
|
|
@@ -73,19 +78,30 @@ const tile_tty = (tile, top) => { // top: true for first line, false for second
|
|
|
73
78
|
colors.W = 'B'
|
|
74
79
|
}
|
|
75
80
|
}
|
|
81
|
+
let val = false
|
|
76
82
|
if (tile in tiles) {
|
|
77
83
|
tile = tiles[tile]
|
|
78
|
-
if (top)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
if (top) {
|
|
85
|
+
val = uptty(colors[tile[0]])
|
|
86
|
+
} else {
|
|
87
|
+
let center_char = tile[1] === tile[2] ? rt : tile[2] === tile[3] ? lt : up
|
|
88
|
+
let centertty = dntty(colors[tile[2]], colors[tile[2].toUpperCase()], center_char)
|
|
89
|
+
val = horiztty(colors[tile[3]]) + centertty + horiztty(colors[tile[1]]) + sp()
|
|
90
|
+
}
|
|
82
91
|
}
|
|
83
|
-
|
|
84
|
-
return '\'\'\' '
|
|
92
|
+
set = save
|
|
93
|
+
return val || (top ? '??? ' : '\'\'\' ')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const merge_tentative = () => {
|
|
97
|
+
color_sets.tentative.e = set.e // copy empty color to tentative set
|
|
98
|
+
color_sets.tentative.W = set.W
|
|
99
|
+
color_sets.tentative.B = set.B
|
|
85
100
|
}
|
|
86
101
|
|
|
87
102
|
const print_icon = (icon, set_name) => {
|
|
88
103
|
set = color_sets[set_name] || color_sets.trax
|
|
104
|
+
merge_tentative(set)
|
|
89
105
|
const on = esc + '38;5;' + String(set.t) + ';48;5;' + String(set.e) + 'm'
|
|
90
106
|
let o1 = ' '
|
|
91
107
|
let o2 = '1 '
|
|
@@ -153,19 +169,24 @@ const trax_game = (game='trax', moves) => {
|
|
|
153
169
|
return trax
|
|
154
170
|
}
|
|
155
171
|
|
|
156
|
-
const display_game = (game='trax', moves='') => {
|
|
172
|
+
const display_game = (game='trax', moves='', tentative) => {
|
|
157
173
|
let trax = trax_game(game, moves)
|
|
174
|
+
let icon = trax.icon
|
|
175
|
+
if (tentative) {
|
|
176
|
+
let drops = trax.drop_tile(tentative)
|
|
177
|
+
icon = trax.tentative_icon(drops)
|
|
178
|
+
}
|
|
158
179
|
console.info(trax.notation)
|
|
159
|
-
print_icon(
|
|
160
|
-
let name = {
|
|
180
|
+
print_icon(icon, trax.rules)
|
|
181
|
+
let name = {1: 'white', 2: 'black'}[trax.turn]
|
|
161
182
|
if (trax.over) {
|
|
162
183
|
if (trax.turn) {
|
|
163
184
|
console.info(name + ' wins')
|
|
164
185
|
} else {
|
|
165
|
-
console.info('game
|
|
186
|
+
console.info('game end' + (tentative ? 's' : 'ed') + ' in a draw')
|
|
166
187
|
}
|
|
167
188
|
} else if (trax.turn) {
|
|
168
|
-
console.info(name +' to play')
|
|
189
|
+
console.info((tentative ? 'tentative position for ' : '') + name +' to play')
|
|
169
190
|
}
|
|
170
191
|
}
|
|
171
192
|
|