schachnovelle 1.0.1 → 1.1.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/package.json +3 -1
- package/server/api.js +119 -11
- package/server/index.js +331 -31
- package/ui/Board.js +25 -4
- package/ui/Fen.js +5 -0
- package/ui/Game.js +405 -332
- package/ui/LichessGame.js +11 -0
- package/ui/Side.js +10 -9
- package/ui/Utils.js +3 -2
- package/ui/index.js +69 -8
- package/ui/moves.js +0 -0
- package/views/error.pug +6 -0
- package/views/index.pug +6 -0
- package/views/layout.pug +6 -0
- package/views/welcome.pug +6 -0
- package/yarn-error.log +0 -367
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "schachnovelle",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Chess to play on the command line",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -25,8 +25,10 @@
|
|
|
25
25
|
"express": "^4.17.1",
|
|
26
26
|
"express-session": "^1.17.1",
|
|
27
27
|
"memorystore": "^1.6.4",
|
|
28
|
+
"ndjson": "^2.0.0",
|
|
28
29
|
"node-fetch": "^2.6.0",
|
|
29
30
|
"open": "^7.3.0",
|
|
31
|
+
"pug": "^3.0.0",
|
|
30
32
|
"simple-oauth2": "^4.1.0"
|
|
31
33
|
}
|
|
32
34
|
}
|
package/server/api.js
CHANGED
|
@@ -1,24 +1,132 @@
|
|
|
1
1
|
const axios = require('axios')
|
|
2
|
+
const https = require('https')
|
|
3
|
+
const ndjson = require('ndjson')
|
|
2
4
|
|
|
3
5
|
module.exports = {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* get the user's information
|
|
9
|
+
* @param {*} token
|
|
10
|
+
*/
|
|
4
11
|
getUserInfo (token) {
|
|
5
|
-
return
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
axios.get('/api/account', {
|
|
14
|
+
baseURL: 'https://lichess.org/',
|
|
15
|
+
headers: { 'Authorization': 'Bearer ' + token.access_token }
|
|
16
|
+
})
|
|
17
|
+
.then((response) => {
|
|
18
|
+
resolve(response)
|
|
19
|
+
})
|
|
20
|
+
.catch((error) => {
|
|
21
|
+
reject(error)
|
|
22
|
+
})
|
|
8
23
|
})
|
|
9
24
|
},
|
|
10
25
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Create an event stream
|
|
28
|
+
* @param {*} token
|
|
29
|
+
*/
|
|
30
|
+
createEventStream (token) {
|
|
31
|
+
const options = {
|
|
32
|
+
headers: {
|
|
33
|
+
'Authorization': 'Bearer ' + token.access_token
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
const req = https.get('https://lichess.org/api/stream/event', options)
|
|
39
|
+
|
|
40
|
+
req
|
|
41
|
+
.on('response', (stream) => {
|
|
42
|
+
const { statusCode } = stream
|
|
43
|
+
|
|
44
|
+
if (statusCode >= 200 && statusCode < 300) {
|
|
45
|
+
resolve(stream)
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.on('error', (error) => {
|
|
49
|
+
reject(error)
|
|
50
|
+
})
|
|
15
51
|
})
|
|
16
52
|
},
|
|
53
|
+
|
|
54
|
+
createGameStream (token, gameId) {
|
|
55
|
+
const options = {
|
|
56
|
+
headers: {
|
|
57
|
+
'Authorization': 'Bearer ' + token.access_token
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const req = https.get(`https://lichess.org/api/board/game/stream/${gameId}`, options)
|
|
17
63
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
64
|
+
req
|
|
65
|
+
.on('response', (stream) => {
|
|
66
|
+
const { statusCode } = stream
|
|
67
|
+
|
|
68
|
+
if (statusCode >= 200 && statusCode < 300) {
|
|
69
|
+
resolve(stream)
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
.on('error', (error) => {
|
|
73
|
+
reject(error)
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
// Commence play after the user has been identified
|
|
79
|
+
startPlay (req, res) {
|
|
80
|
+
return new Promise(async (resolve, reject) => {
|
|
81
|
+
try {
|
|
82
|
+
const stream = await this.createEventStream(req.session.accessToken)
|
|
83
|
+
stream
|
|
84
|
+
.pipe(ndjson.parse())
|
|
85
|
+
.on('data', (data) => {
|
|
86
|
+
// Always write the data type to the stream
|
|
87
|
+
process.stdout.write(data.type)
|
|
88
|
+
|
|
89
|
+
// Hook into events from event stream!
|
|
90
|
+
if (data.type === 'gameStart') {
|
|
91
|
+
req.session.currentGame = data.game
|
|
92
|
+
this.openGameStream(req)
|
|
93
|
+
} else {
|
|
94
|
+
console.log('!!! unhandled data type !!!')
|
|
95
|
+
console.log(data)
|
|
96
|
+
console.log('!!! end unhandled data type !!!')
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
} catch (error) {
|
|
100
|
+
reject(error)
|
|
101
|
+
} finally {
|
|
102
|
+
resolve({ status: 200 })
|
|
103
|
+
}
|
|
22
104
|
})
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
// Tryout to follow a game
|
|
108
|
+
async openGameStream (req) {
|
|
109
|
+
try {
|
|
110
|
+
const stream = await this.createGameStream(req.session.accessToken, req.session.currentGame.id)
|
|
111
|
+
|
|
112
|
+
stream
|
|
113
|
+
.pipe(ndjson.parse())
|
|
114
|
+
.on('data', (data) => {
|
|
115
|
+
// Write data type to stdout
|
|
116
|
+
process.stdout.write(data.type)
|
|
117
|
+
|
|
118
|
+
if (data.type === 'gameFull') {
|
|
119
|
+
req.session.currentGame.data = data
|
|
120
|
+
} else if (data.type === 'gameState') {
|
|
121
|
+
req.session.currentGame.data.gameState = data
|
|
122
|
+
} else {
|
|
123
|
+
console.log('UNUSED DATA TYPE', data.type)
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error(error)
|
|
128
|
+
}
|
|
23
129
|
}
|
|
130
|
+
|
|
131
|
+
|
|
24
132
|
}
|
package/server/index.js
CHANGED
|
@@ -1,30 +1,41 @@
|
|
|
1
1
|
require('dotenv').config()
|
|
2
2
|
|
|
3
|
+
//
|
|
4
|
+
//
|
|
5
|
+
// Imports
|
|
3
6
|
const express = require('express')
|
|
4
|
-
|
|
7
|
+
// Storage
|
|
5
8
|
const open = require('open')
|
|
9
|
+
const session = require('express-session')
|
|
6
10
|
const MemoryStore = require('memorystore')(session)
|
|
7
|
-
|
|
8
|
-
const
|
|
11
|
+
// Lichess
|
|
12
|
+
const lichess = require('./api')
|
|
9
13
|
|
|
10
14
|
/* Create your lichess OAuth app on https://lichess.org/account/oauth/app/create
|
|
11
15
|
* Homepage URL: http://localhost:3000
|
|
12
16
|
* Callback URL: http://localhost:3000/callback
|
|
13
17
|
*/
|
|
14
18
|
|
|
19
|
+
|
|
20
|
+
|
|
15
21
|
//
|
|
16
22
|
//
|
|
17
23
|
// Server + Auth config
|
|
18
24
|
const port = 3000
|
|
25
|
+
const host = process.env.NODE_ENV === 'production' ? 'https://schachnovelle.online' : 'http://localhost'
|
|
19
26
|
const clientId = process.env.LICHESS_ID
|
|
20
27
|
const clientSecret = process.env.LICHESS_SECRET
|
|
21
28
|
const redirectUri = `http://localhost:${port}/callback`
|
|
22
29
|
|
|
30
|
+
// Scopes
|
|
23
31
|
const scopes = [
|
|
24
32
|
'preference:read',
|
|
25
33
|
'challenge:read',
|
|
26
|
-
'board:play'
|
|
27
|
-
|
|
34
|
+
'board:play',
|
|
35
|
+
'bot:play'
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
|
|
28
39
|
|
|
29
40
|
//
|
|
30
41
|
//
|
|
@@ -45,13 +56,25 @@ const oAuthConfig = {
|
|
|
45
56
|
}
|
|
46
57
|
}
|
|
47
58
|
|
|
48
|
-
const {
|
|
59
|
+
const { AuthorizationCode } = require('simple-oauth2')
|
|
49
60
|
const client = new AuthorizationCode(oAuthConfig)
|
|
50
61
|
|
|
62
|
+
|
|
63
|
+
|
|
51
64
|
//
|
|
52
65
|
//
|
|
53
66
|
// Initialize the server
|
|
54
67
|
const app = express();
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
//
|
|
72
|
+
//
|
|
73
|
+
// Set things
|
|
74
|
+
app.set('view engine', 'pug')
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
55
78
|
//
|
|
56
79
|
//
|
|
57
80
|
// Session
|
|
@@ -70,7 +93,15 @@ app.use(session({
|
|
|
70
93
|
//
|
|
71
94
|
//
|
|
72
95
|
// Show the "log in with lichess" button
|
|
73
|
-
app.get('/', (req, res) =>
|
|
96
|
+
app.get('/', (req, res) => {
|
|
97
|
+
if (req.session.userInfo) {
|
|
98
|
+
res.redirect('/welcome')
|
|
99
|
+
} else {
|
|
100
|
+
res.render('../views/index')
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
|
|
74
105
|
|
|
75
106
|
//
|
|
76
107
|
//
|
|
@@ -85,7 +116,8 @@ app.get('/auth', (req, res) => {
|
|
|
85
116
|
})
|
|
86
117
|
|
|
87
118
|
res.redirect(authorizationUri)
|
|
88
|
-
})
|
|
119
|
+
})
|
|
120
|
+
|
|
89
121
|
|
|
90
122
|
//
|
|
91
123
|
//
|
|
@@ -98,10 +130,10 @@ app.get('/callback', async (req, res) => {
|
|
|
98
130
|
}
|
|
99
131
|
|
|
100
132
|
try {
|
|
101
|
-
console.log('creating token')
|
|
102
133
|
const result = await client.getToken(tokenParams)
|
|
103
134
|
const accessToken = client.createToken(result)
|
|
104
|
-
|
|
135
|
+
|
|
136
|
+
// Save token to the session
|
|
105
137
|
req.session.accessToken = accessToken.token.token
|
|
106
138
|
|
|
107
139
|
res.redirect('/welcome')
|
|
@@ -110,35 +142,303 @@ app.get('/callback', async (req, res) => {
|
|
|
110
142
|
}
|
|
111
143
|
})
|
|
112
144
|
|
|
145
|
+
|
|
146
|
+
|
|
113
147
|
//
|
|
114
148
|
//
|
|
115
149
|
// Welcome page
|
|
116
150
|
app.get('/welcome', async (req, res) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const userInfo = await
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
151
|
+
if (req.session.accessToken) {
|
|
152
|
+
try {
|
|
153
|
+
const userInfo = await lichess.getUserInfo(req.session.accessToken)
|
|
154
|
+
req.session.userInfo = userInfo.data
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error(error)
|
|
157
|
+
} finally {
|
|
158
|
+
if (req.session.userInfo) {
|
|
159
|
+
lichess.startPlay(req, res)
|
|
160
|
+
.then((response) => {
|
|
161
|
+
if (response.status === 200) {
|
|
162
|
+
// This goes to the UI
|
|
163
|
+
process.stdout.write('streamReady')
|
|
164
|
+
// This to the browser
|
|
165
|
+
res.render('../views/welcome', { user: req.session.userInfo })
|
|
166
|
+
} else {
|
|
167
|
+
res.render('../views/error', response)
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
.catch((error) => {
|
|
171
|
+
console.error(error)
|
|
172
|
+
res.render('../views/error', error)
|
|
173
|
+
})
|
|
174
|
+
} else {
|
|
175
|
+
res.render('../views/error')
|
|
176
|
+
}
|
|
137
177
|
}
|
|
178
|
+
|
|
179
|
+
} else {
|
|
180
|
+
res.redirect('/')
|
|
181
|
+
}
|
|
138
182
|
})
|
|
139
183
|
|
|
140
184
|
app.listen(port, async () => {
|
|
141
|
-
await open(
|
|
185
|
+
await open(`${host}:${port}`)
|
|
142
186
|
});
|
|
143
187
|
|
|
144
188
|
|
|
189
|
+
|
|
190
|
+
// SAMPLE DATA
|
|
191
|
+
|
|
192
|
+
// { type: 'gameStart', game: { id: 'Wmv3QOtD' } }
|
|
193
|
+
// {
|
|
194
|
+
// id: 'Wmv3QOtD',
|
|
195
|
+
// variant: { key: 'standard', name: 'Standard', short: 'Std' },
|
|
196
|
+
// clock: { initial: 600000, increment: 3000 },
|
|
197
|
+
// speed: 'rapid',
|
|
198
|
+
// perf: { name: 'Rapid' },
|
|
199
|
+
// rated: false,
|
|
200
|
+
// createdAt: 1612916752568,
|
|
201
|
+
// white: { id: 'manegame', name: 'manegame', title: null, rating: 1155 },
|
|
202
|
+
// black: {
|
|
203
|
+
// id: 'schachnovelle-online',
|
|
204
|
+
// name: 'schachnovelle-online',
|
|
205
|
+
// title: null,
|
|
206
|
+
// rating: 1500,
|
|
207
|
+
// provisional: true
|
|
208
|
+
// },
|
|
209
|
+
// initialFen: 'startpos',
|
|
210
|
+
// type: 'gameFull',
|
|
211
|
+
// state: {
|
|
212
|
+
// type: 'gameState',
|
|
213
|
+
// moves: '',
|
|
214
|
+
// wtime: 600000,
|
|
215
|
+
// btime: 600000,
|
|
216
|
+
// winc: 3000,
|
|
217
|
+
// binc: 3000,
|
|
218
|
+
// wdraw: false,
|
|
219
|
+
// bdraw: false,
|
|
220
|
+
// status: 'started'
|
|
221
|
+
// }
|
|
222
|
+
// }
|
|
223
|
+
// {
|
|
224
|
+
// type: 'gameState',
|
|
225
|
+
// moves: 'e2e4',
|
|
226
|
+
// wtime: 600000,
|
|
227
|
+
// btime: 600000,
|
|
228
|
+
// winc: 3000,
|
|
229
|
+
// binc: 3000,
|
|
230
|
+
// wdraw: false,
|
|
231
|
+
// bdraw: false,
|
|
232
|
+
// status: 'started'
|
|
233
|
+
// }
|
|
234
|
+
// {
|
|
235
|
+
// type: 'gameState',
|
|
236
|
+
// moves: 'e2e4 e7e5',
|
|
237
|
+
// wtime: 600000,
|
|
238
|
+
// btime: 600000,
|
|
239
|
+
// winc: 3000,
|
|
240
|
+
// binc: 3000,
|
|
241
|
+
// wdraw: false,
|
|
242
|
+
// bdraw: false,
|
|
243
|
+
// status: 'started'
|
|
244
|
+
// }
|
|
245
|
+
// {
|
|
246
|
+
// type: 'gameState',
|
|
247
|
+
// moves: 'e2e4 e7e5 g1f3',
|
|
248
|
+
// wtime: 599590,
|
|
249
|
+
// btime: 600000,
|
|
250
|
+
// winc: 3000,
|
|
251
|
+
// binc: 3000,
|
|
252
|
+
// wdraw: false,
|
|
253
|
+
// bdraw: false,
|
|
254
|
+
// status: 'started'
|
|
255
|
+
// }
|
|
256
|
+
// {
|
|
257
|
+
// type: 'gameState',
|
|
258
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6',
|
|
259
|
+
// wtime: 599590,
|
|
260
|
+
// btime: 597200,
|
|
261
|
+
// winc: 3000,
|
|
262
|
+
// binc: 3000,
|
|
263
|
+
// wdraw: false,
|
|
264
|
+
// bdraw: false,
|
|
265
|
+
// status: 'started'
|
|
266
|
+
// }
|
|
267
|
+
// {
|
|
268
|
+
// type: 'gameState',
|
|
269
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4',
|
|
270
|
+
// wtime: 598580,
|
|
271
|
+
// btime: 597200,
|
|
272
|
+
// winc: 3000,
|
|
273
|
+
// binc: 3000,
|
|
274
|
+
// wdraw: false,
|
|
275
|
+
// bdraw: false,
|
|
276
|
+
// status: 'started'
|
|
277
|
+
// }
|
|
278
|
+
// {
|
|
279
|
+
// type: 'gameState',
|
|
280
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5',
|
|
281
|
+
// wtime: 598580,
|
|
282
|
+
// btime: 595560,
|
|
283
|
+
// winc: 3000,
|
|
284
|
+
// binc: 3000,
|
|
285
|
+
// wdraw: false,
|
|
286
|
+
// bdraw: false,
|
|
287
|
+
// status: 'started'
|
|
288
|
+
// }
|
|
289
|
+
// {
|
|
290
|
+
// type: 'gameState',
|
|
291
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5',
|
|
292
|
+
// wtime: 592540,
|
|
293
|
+
// btime: 595560,
|
|
294
|
+
// winc: 3000,
|
|
295
|
+
// binc: 3000,
|
|
296
|
+
// wdraw: false,
|
|
297
|
+
// bdraw: false,
|
|
298
|
+
// status: 'started'
|
|
299
|
+
// }
|
|
300
|
+
// {
|
|
301
|
+
// type: 'gameState',
|
|
302
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5',
|
|
303
|
+
// wtime: 592540,
|
|
304
|
+
// btime: 595370,
|
|
305
|
+
// winc: 3000,
|
|
306
|
+
// binc: 3000,
|
|
307
|
+
// wdraw: false,
|
|
308
|
+
// bdraw: false,
|
|
309
|
+
// status: 'started'
|
|
310
|
+
// }
|
|
311
|
+
// {
|
|
312
|
+
// type: 'gameState',
|
|
313
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5',
|
|
314
|
+
// wtime: 591460,
|
|
315
|
+
// btime: 595370,
|
|
316
|
+
// winc: 3000,
|
|
317
|
+
// binc: 3000,
|
|
318
|
+
// wdraw: false,
|
|
319
|
+
// bdraw: false,
|
|
320
|
+
// status: 'started'
|
|
321
|
+
// }
|
|
322
|
+
// {
|
|
323
|
+
// type: 'gameState',
|
|
324
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4',
|
|
325
|
+
// wtime: 591460,
|
|
326
|
+
// btime: 594720,
|
|
327
|
+
// winc: 3000,
|
|
328
|
+
// binc: 3000,
|
|
329
|
+
// wdraw: false,
|
|
330
|
+
// bdraw: false,
|
|
331
|
+
// status: 'started'
|
|
332
|
+
// }
|
|
333
|
+
// {
|
|
334
|
+
// type: 'gameState',
|
|
335
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3',
|
|
336
|
+
// wtime: 578720,
|
|
337
|
+
// btime: 594720,
|
|
338
|
+
// winc: 3000,
|
|
339
|
+
// binc: 3000,
|
|
340
|
+
// wdraw: false,
|
|
341
|
+
// bdraw: false,
|
|
342
|
+
// status: 'started'
|
|
343
|
+
// }
|
|
344
|
+
// {
|
|
345
|
+
// type: 'gameState',
|
|
346
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2',
|
|
347
|
+
// wtime: 578720,
|
|
348
|
+
// btime: 597720,
|
|
349
|
+
// winc: 3000,
|
|
350
|
+
// binc: 3000,
|
|
351
|
+
// wdraw: false,
|
|
352
|
+
// bdraw: false,
|
|
353
|
+
// status: 'started'
|
|
354
|
+
// }
|
|
355
|
+
// {
|
|
356
|
+
// type: 'gameState',
|
|
357
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2 e1f1',
|
|
358
|
+
// wtime: 565650,
|
|
359
|
+
// btime: 597720,
|
|
360
|
+
// winc: 3000,
|
|
361
|
+
// binc: 3000,
|
|
362
|
+
// wdraw: false,
|
|
363
|
+
// bdraw: false,
|
|
364
|
+
// status: 'started'
|
|
365
|
+
// }
|
|
366
|
+
// {
|
|
367
|
+
// type: 'gameState',
|
|
368
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2 e1f1 e4e3',
|
|
369
|
+
// wtime: 565650,
|
|
370
|
+
// btime: 595360,
|
|
371
|
+
// winc: 3000,
|
|
372
|
+
// binc: 3000,
|
|
373
|
+
// wdraw: false,
|
|
374
|
+
// bdraw: false,
|
|
375
|
+
// status: 'started'
|
|
376
|
+
// }
|
|
377
|
+
// {
|
|
378
|
+
// type: 'gameState',
|
|
379
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2 e1f1 e4e3 c2c3',
|
|
380
|
+
// wtime: 556810,
|
|
381
|
+
// btime: 595360,
|
|
382
|
+
// winc: 3000,
|
|
383
|
+
// binc: 3000,
|
|
384
|
+
// wdraw: false,
|
|
385
|
+
// bdraw: false,
|
|
386
|
+
// status: 'started'
|
|
387
|
+
// }
|
|
388
|
+
// {
|
|
389
|
+
// type: 'gameState',
|
|
390
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2 e1f1 e4e3 c2c3 c8h3',
|
|
391
|
+
// wtime: 556810,
|
|
392
|
+
// btime: 587450,
|
|
393
|
+
// winc: 3000,
|
|
394
|
+
// binc: 3000,
|
|
395
|
+
// wdraw: false,
|
|
396
|
+
// bdraw: false,
|
|
397
|
+
// status: 'started'
|
|
398
|
+
// }
|
|
399
|
+
// {
|
|
400
|
+
// type: 'gameState',
|
|
401
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2 e1f1 e4e3 c2c3 c8h3 f1g1',
|
|
402
|
+
// wtime: 547270,
|
|
403
|
+
// btime: 587450,
|
|
404
|
+
// winc: 3000,
|
|
405
|
+
// binc: 3000,
|
|
406
|
+
// wdraw: false,
|
|
407
|
+
// bdraw: false,
|
|
408
|
+
// status: 'started'
|
|
409
|
+
// }
|
|
410
|
+
// {
|
|
411
|
+
// type: 'gameState',
|
|
412
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2 e1f1 e4e3 c2c3 c8h3 f1g1 h3g2',
|
|
413
|
+
// wtime: 547270,
|
|
414
|
+
// btime: 581970,
|
|
415
|
+
// winc: 3000,
|
|
416
|
+
// binc: 3000,
|
|
417
|
+
// wdraw: false,
|
|
418
|
+
// bdraw: false,
|
|
419
|
+
// status: 'started'
|
|
420
|
+
// }
|
|
421
|
+
// {
|
|
422
|
+
// type: 'gameState',
|
|
423
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2 e1f1 e4e3 c2c3 c8h3 f1g1 h3g2 b2b3',
|
|
424
|
+
// wtime: 543850,
|
|
425
|
+
// btime: 581970,
|
|
426
|
+
// winc: 3000,
|
|
427
|
+
// binc: 3000,
|
|
428
|
+
// wdraw: false,
|
|
429
|
+
// bdraw: false,
|
|
430
|
+
// status: 'started'
|
|
431
|
+
// }
|
|
432
|
+
// { type: 'gameFinish', game: { id: 'Wmv3QOtD' } }
|
|
433
|
+
// {
|
|
434
|
+
// type: 'gameState',
|
|
435
|
+
// moves: 'e2e4 e7e5 g1f3 c7c6 f1c4 d7d5 c4d5 c6d5 f3e5 d5e4 g2g3 d8d2 e1f1 e4e3 c2c3 c8h3 f1g1 h3g2 b2b3 d2f2',
|
|
436
|
+
// wtime: 543850,
|
|
437
|
+
// btime: 574250,
|
|
438
|
+
// winc: 3000,
|
|
439
|
+
// binc: 3000,
|
|
440
|
+
// wdraw: false,
|
|
441
|
+
// bdraw: false,
|
|
442
|
+
// status: 'mate',
|
|
443
|
+
// winner: 'black'
|
|
444
|
+
// }
|
package/ui/Board.js
CHANGED
|
@@ -29,9 +29,11 @@ class Board {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
render () {
|
|
32
|
+
// this.topCheck()
|
|
32
33
|
this.topRank()
|
|
33
34
|
this.board()
|
|
34
35
|
this.bottomRank()
|
|
36
|
+
// this.bottomCheck()
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
getPiece (file, rank) {
|
|
@@ -53,13 +55,13 @@ class Board {
|
|
|
53
55
|
* Pieces
|
|
54
56
|
*/
|
|
55
57
|
if (activeWhitePiece) {
|
|
56
|
-
if (activeWhitePiece.
|
|
58
|
+
if (activeWhitePiece.type === 'King' && this.white.inCheck) {
|
|
57
59
|
return chalk`{red ${activeWhitePiece.piece}} `
|
|
58
60
|
} else {
|
|
59
61
|
return chalk`{black ${activeWhitePiece.piece}} `
|
|
60
62
|
}
|
|
61
63
|
} else if (activeBlackPiece) {
|
|
62
|
-
if (activeBlackPiece.
|
|
64
|
+
if (activeBlackPiece.type === 'King' && this.black.inCheck) {
|
|
63
65
|
return chalk`{red ${activeBlackPiece.piece}} `
|
|
64
66
|
} else {
|
|
65
67
|
return chalk`{black ${activeBlackPiece.piece}} `
|
|
@@ -92,7 +94,7 @@ class Board {
|
|
|
92
94
|
scoreBoard (side) {
|
|
93
95
|
let scoreBoard = ''
|
|
94
96
|
let score = 0
|
|
95
|
-
const opponent = this.utils.
|
|
97
|
+
const opponent = this.utils.opposingColor(side)
|
|
96
98
|
const pieces = this.capturedPieces(opponent)
|
|
97
99
|
|
|
98
100
|
if (pieces.length > 0) {
|
|
@@ -110,11 +112,30 @@ class Board {
|
|
|
110
112
|
this.printer.addSpace('y')
|
|
111
113
|
}
|
|
112
114
|
|
|
115
|
+
/**
|
|
116
|
+
* For development only. Display if the king is in check
|
|
117
|
+
*/
|
|
118
|
+
topCheck () {
|
|
119
|
+
const side = this.utils.opposingColor(this.options.orientation)
|
|
120
|
+
this.printer.print(side + ' king in check: ' + this[side].inCheck)
|
|
121
|
+
this.printer.addSpace('y')
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* For development only. Display if the king is in check
|
|
126
|
+
*/
|
|
127
|
+
bottomCheck () {
|
|
128
|
+
const side = this.options.orientation
|
|
129
|
+
this.printer.print(side + ' king in check: ' + this[side].inCheck)
|
|
130
|
+
this.printer.addSpace('y')
|
|
131
|
+
}
|
|
132
|
+
|
|
113
133
|
/**
|
|
114
134
|
* Top signage
|
|
115
135
|
*/
|
|
116
136
|
topRank () {
|
|
117
|
-
this.
|
|
137
|
+
const side = this.utils.opposingColor(this.options.orientation)
|
|
138
|
+
this.scoreBoard(side)
|
|
118
139
|
let renderTopRank = this.printer.tab
|
|
119
140
|
renderTopRank = this.printer.addSpace('x', renderTopRank)
|
|
120
141
|
for (let file in this.files) {
|