schachnovelle 1.1.0 → 1.1.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/README.md CHANGED
@@ -4,8 +4,8 @@ _»Um Gottes Willen! Nicht!«_
4
4
  [![Find the code on GitLab](https://upload.wikimedia.org/wikipedia/commons/d/d9/Chess_clt45.svg)](https://gitlab.com/manegame/schachnovelle)
5
5
 
6
6
 
7
+ _[manusnijhoff.nl](https://manusnijhoff.nl)_,
7
8
  _[Read the book](https://en.wikipedia.org/wiki/The_Royal_Game)_, _[Play me on lichess](https://lichess.org/@/manegame)_,
8
- _[Check out my website](https://manusnijhoff.nl)_
9
9
 
10
10
 
11
11
  ## Installation
@@ -23,13 +23,11 @@ or npm
23
23
  ...And play!
24
24
 
25
25
  ## Features
26
- There is no check detection yet. Play with your head! For now...
27
-
28
26
  You can play against yourself or a friend on the same keyboard.
29
27
 
30
28
  ## Roadmap
31
29
 
32
- I'm slowly working on connecting this to the [lichess](https://lichess.org/) API, so you can play others from the comfort of the command line!
30
+ I'd love to connect this to the [lichess](https://lichess.org/) API, so you can play others from the comfort of the command line!
33
31
 
34
32
  ## Changelog
35
33
 
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "schachnovelle",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Chess to play on the command line",
5
5
  "main": "index.js",
6
+ "exports": {
7
+ ".": "./index.js",
8
+ "./web": "./web.js"
9
+ },
6
10
  "scripts": {
7
11
  "play": "node index.js",
8
12
  "serve": "node server/index.js"
package/ui/Board.js CHANGED
@@ -1,5 +1,4 @@
1
1
  const chalk = require('chalk')
2
-
3
2
  const Printer = require('./Printer')
4
3
  const Utils = require('./Utils')
5
4
 
@@ -20,7 +19,8 @@ class Board {
20
19
  this.ranks = ranks
21
20
  }
22
21
 
23
- this.printer = new Printer(options.spacing)
22
+ this.chalk = options.chalk || chalk
23
+ this.printer = options.printer || new Printer(options.spacing)
24
24
  this.utils = new Utils()
25
25
  }
26
26
 
@@ -45,9 +45,9 @@ class Board {
45
45
  })
46
46
  if (this.options.mode === 'color') {
47
47
  if (activeWhitePiece) {
48
- return chalk` {whiteBright ${activeWhitePiece.piece}} `
48
+ return this.chalk` {whiteBright ${activeWhitePiece.piece}} `
49
49
  } else if (activeBlackPiece) {
50
- return chalk` {black ${activeBlackPiece.piece}} `
50
+ return this.chalk` {black ${activeBlackPiece.piece}} `
51
51
  }
52
52
  return ` `
53
53
  } else if (this.options.mode === 'bare') {
@@ -56,15 +56,15 @@ class Board {
56
56
  */
57
57
  if (activeWhitePiece) {
58
58
  if (activeWhitePiece.type === 'King' && this.white.inCheck) {
59
- return chalk`{red ${activeWhitePiece.piece}} `
59
+ return this.chalk`{red ${activeWhitePiece.piece}} `
60
60
  } else {
61
- return chalk`{black ${activeWhitePiece.piece}} `
61
+ return this.chalk`{black ${activeWhitePiece.piece}} `
62
62
  }
63
63
  } else if (activeBlackPiece) {
64
64
  if (activeBlackPiece.type === 'King' && this.black.inCheck) {
65
- return chalk`{red ${activeBlackPiece.piece}} `
65
+ return this.chalk`{red ${activeBlackPiece.piece}} `
66
66
  } else {
67
- return chalk`{black ${activeBlackPiece.piece}} `
67
+ return this.chalk`{black ${activeBlackPiece.piece}} `
68
68
  }
69
69
  }
70
70
  /**
@@ -74,9 +74,9 @@ class Board {
74
74
  const rankParity = this.ranks.indexOf(rank) % 2 === 0 // the rank is odd
75
75
  const fileParity = this.files.indexOf(file) % 2 === 0 // the file is odd
76
76
  if (rankParity && fileParity || !rankParity && !fileParity) {
77
- return chalk`{white .} `
77
+ return this.chalk`{white .} `
78
78
  } else {
79
- return chalk`{black .} `
79
+ return this.chalk`{black .} `
80
80
  }
81
81
  }
82
82
  }
@@ -174,16 +174,16 @@ class Board {
174
174
  // if rank is even, start with white
175
175
  if (rank % 2 === 0) {
176
176
  if (file % 2 === 0) {
177
- renderRank += chalk.bgKeyword('darkgrey')(this.getPiece(this.files[file], this.ranks[rank]))
177
+ renderRank += this.chalk.bgKeyword('darkgrey')(this.getPiece(this.files[file], this.ranks[rank]))
178
178
  } else {
179
- renderRank += chalk.bgBlackBright(this.getPiece(this.files[file], this.ranks[rank]))
179
+ renderRank += this.chalk.bgBlackBright(this.getPiece(this.files[file], this.ranks[rank]))
180
180
  }
181
181
  renderRank = this.printer.addSpace('x', renderRank)
182
182
  } else {
183
183
  if (file % 2 === 0) {
184
- renderRank += chalk.bgBlackBright(this.getPiece(this.files[file], this.ranks[rank]))
184
+ renderRank += this.chalk.bgBlackBright(this.getPiece(this.files[file], this.ranks[rank]))
185
185
  } else {
186
- renderRank += chalk.bgKeyword('darkgrey')(this.getPiece(this.files[file], this.ranks[rank]))
186
+ renderRank += this.chalk.bgKeyword('darkgrey')(this.getPiece(this.files[file], this.ranks[rank]))
187
187
  }
188
188
  renderRank = this.printer.addSpace('x', renderRank)
189
189
  }
@@ -208,4 +208,4 @@ class Board {
208
208
  }
209
209
  }
210
210
 
211
- module.exports = Board
211
+ module.exports = Board
package/ui/Game.js CHANGED
@@ -20,13 +20,14 @@ class Game {
20
20
 
21
21
  // Initialize the board
22
22
  this.board = new Board(this.white, this.black, {
23
- mode: "pieces", // possibly add text mode
23
+ mode: options.mode || "pieces", // possibly add text mode
24
24
  orientation: this.playingAs,
25
25
  spacing: options.spacing,
26
- mode: options.mode,
26
+ printer: options.printer,
27
+ chalk: options.chalk
27
28
  })
28
29
 
29
- this.enquirer = new Enquirer()
30
+ this.enquirer = options.enquirer || new Enquirer()
30
31
  this.printer = new Printer(options.spacing)
31
32
  this.utils = new Utils()
32
33
  }
@@ -0,0 +1,51 @@
1
+ class WebPrinter {
2
+ constructor (spacing, io) {
3
+ this.spacing = spacing
4
+ this.io = io
5
+ this.tab = ' '
6
+ this.lineCount = 0
7
+ }
8
+
9
+ clearView () {
10
+ if (this.io && this.io.clear) {
11
+ this.io.clear()
12
+ }
13
+ }
14
+
15
+ clearForward () {}
16
+
17
+ printLine (value) {
18
+ if (this.io && this.io.write) {
19
+ this.io.write(value + '\n')
20
+ this.lineCount++
21
+ }
22
+ }
23
+
24
+ print (value) {
25
+ if (this.io && this.io.write) {
26
+ this.io.write(value)
27
+ }
28
+ }
29
+
30
+ addSpace (direction, string) {
31
+ if (direction === 'x') {
32
+ for (let i = 0; i < this.spacing; i++) {
33
+ string += ' '
34
+ }
35
+ } else {
36
+ for (let i = 0; i < this.spacing; i++) {
37
+ this.printLine('')
38
+ }
39
+ }
40
+ return string
41
+ }
42
+
43
+ addSpaceBefore (string) {
44
+ for (let i = 0; i < this.spacing; i++) {
45
+ string = ' ' + string
46
+ }
47
+ return string
48
+ }
49
+ }
50
+
51
+ module.exports = WebPrinter
package/ui/index.js CHANGED
@@ -19,6 +19,9 @@ exports.welcomeMessage = () => {
19
19
  printer.addSpace('y')
20
20
  printer.printLine(printer.addSpaceBefore(' >>Um Gottes Willen! Nicht!<<'))
21
21
  printer.addSpace('y')
22
+ printer.printLine(printer.addSpaceBefore(' Public Service Announcement '))
23
+ printer.printLine(printer.addSpaceBefore(' I run best on a white terminal '))
24
+ printer.addSpace('y')
22
25
  }
23
26
 
24
27
  //
@@ -91,25 +94,25 @@ exports.init = () => {
91
94
  // Don't be shy, say hello to that person!
92
95
  this.welcomeMessage()
93
96
 
97
+ this.localGame()
94
98
 
95
- const what = new Select({
96
- name: 'todo',
97
- message: 'How do you want to play?',
98
- choices: ['local', 'on lichess (beta)']
99
- })
99
+ // const what = new Select({
100
+ // name: 'todo',
101
+ // message: 'How do you want to play?',
102
+ // choices: ['local', 'on lichess (beta)']
103
+ // })
100
104
 
101
- what.run()
102
- .then((answer) => {
103
- printer.addSpace('y')
105
+ // what.run()
106
+ // .then((answer) => {
107
+ // printer.addSpace('y')
104
108
 
105
- if (answer === 'local') {
106
- this.localGame()
107
- } else {
108
- this.spawnServer()
109
+ // if (answer === 'local') {
110
+ // } else {
111
+ // this.spawnServer()
109
112
 
110
- printer.addSpace('y')
111
- printer.printLine(printer.addSpaceBefore(' Log in with Lichess to begin'))
112
- printer.addSpace('y')
113
- }
114
- })
113
+ // printer.addSpace('y')
114
+ // printer.printLine(printer.addSpaceBefore(' Log in with Lichess to begin'))
115
+ // printer.addSpace('y')
116
+ // }
117
+ // })
115
118
  }
@@ -0,0 +1,19 @@
1
+ const stripChalkMarkup = (value) => {
2
+ return value.replace(/\{[^}\s]*\s/g, '').replace(/\}/g, '')
3
+ }
4
+
5
+ const plainChalk = (strings, ...values) => {
6
+ let output = ''
7
+ for (let i = 0; i < strings.length; i++) {
8
+ output += strings[i]
9
+ if (i < values.length) {
10
+ output += values[i]
11
+ }
12
+ }
13
+ return stripChalkMarkup(output)
14
+ }
15
+
16
+ plainChalk.bgKeyword = () => (value) => stripChalkMarkup(value)
17
+ plainChalk.bgBlackBright = (value) => stripChalkMarkup(value)
18
+
19
+ module.exports = plainChalk
package/ui/web.js ADDED
@@ -0,0 +1,53 @@
1
+ const Game = require('./Game')
2
+ const WebPrinter = require('./WebPrinter')
3
+ const createWebPrompt = require('./webPrompt')
4
+ const plainChalk = require('./plainChalk')
5
+
6
+ const spacing = 1
7
+
8
+ const welcomeMessage = (printer) => {
9
+ printer.addSpace('y')
10
+ printer.printLine(printer.addSpaceBefore('S . C . V . E'))
11
+ printer.printLine(printer.addSpaceBefore(' C A H O E L '))
12
+ printer.printLine(printer.addSpaceBefore('. H . N . L .'))
13
+ printer.addSpace('y')
14
+ printer.printLine(printer.addSpaceBefore(' >>Um Gottes Willen! Nicht!<<'))
15
+ printer.addSpace('y')
16
+ printer.printLine(printer.addSpaceBefore(' Public Service Announcement '))
17
+ printer.printLine(printer.addSpaceBefore(' I run best on a white terminal '))
18
+ printer.addSpace('y')
19
+ }
20
+
21
+ const createWebGame = (io, options = {}) => {
22
+ const prompt = createWebPrompt(io)
23
+ const printer = new WebPrinter(options.spacing || spacing, io)
24
+
25
+ welcomeMessage(printer)
26
+
27
+ prompt.prompt([{
28
+ type: 'select',
29
+ name: 'color',
30
+ message: 'Play as',
31
+ choices: ['white', 'black']
32
+ }]).then((answer) => {
33
+ const game = new Game({
34
+ playingAs: answer.color,
35
+ spacing: options.spacing || spacing,
36
+ mode: 'bare',
37
+ enquirer: prompt,
38
+ printer,
39
+ chalk: plainChalk
40
+ })
41
+
42
+ printer.clearView()
43
+ game.init()
44
+ }).catch((error) => {
45
+ if (io && io.write) {
46
+ io.write(`Error starting game: ${error?.message || error}\n`)
47
+ }
48
+ })
49
+ }
50
+
51
+ module.exports = {
52
+ createWebGame
53
+ }
@@ -0,0 +1,59 @@
1
+ const createWebPrompt = (io) => {
2
+ let pendingResolve = null
3
+
4
+ if (io && io.onLine) {
5
+ io.onLine((line) => {
6
+ if (pendingResolve) {
7
+ const resolve = pendingResolve
8
+ pendingResolve = null
9
+ resolve(line)
10
+ }
11
+ })
12
+ }
13
+
14
+ const ask = (question) => {
15
+ const choices = question.choices || []
16
+ io.write(`${question.message}\n`)
17
+ choices.forEach((choice, index) => {
18
+ io.write(` ${index + 1}) ${choice}\n`)
19
+ })
20
+ io.write('> ')
21
+
22
+ return new Promise((resolve) => {
23
+ const resolveChoice = (line) => {
24
+ const trimmed = `${line}`.trim()
25
+ let selection = choices.find(choice => choice === trimmed)
26
+ if (!selection) {
27
+ const index = Number(trimmed)
28
+ if (index >= 1 && index <= choices.length) {
29
+ selection = choices[index - 1]
30
+ }
31
+ }
32
+
33
+ if (!selection) {
34
+ io.write('Invalid choice, try again.\n')
35
+ io.write('> ')
36
+ pendingResolve = resolveChoice
37
+ return
38
+ }
39
+
40
+ const result = question.result ? question.result(selection) : selection
41
+ resolve({ [question.name]: result })
42
+ }
43
+
44
+ pendingResolve = resolveChoice
45
+ })
46
+ }
47
+
48
+ return {
49
+ prompt: async (questions) => {
50
+ if (!Array.isArray(questions) || questions.length === 0) {
51
+ return {}
52
+ }
53
+
54
+ return ask(questions[0])
55
+ }
56
+ }
57
+ }
58
+
59
+ module.exports = createWebPrompt
package/web.js ADDED
@@ -0,0 +1,5 @@
1
+ const { createWebGame } = require('./ui/web')
2
+
3
+ module.exports = {
4
+ createWebGame
5
+ }