bytestorm commited on
Commit
54099ef
·
verified ·
1 Parent(s): 400c218

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +1006 -19
index.html CHANGED
@@ -1,19 +1,1006 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Adaptive Chess - Learn With Me</title>
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ :root {
16
+ --primary: #2c3e50;
17
+ --secondary: #3498db;
18
+ --accent: #e74c3c;
19
+ --light: #ecf0f1;
20
+ --dark: #1a252f;
21
+ --light-square: #f0d9b5;
22
+ --dark-square: #b58863;
23
+ --highlight: rgba(255, 255, 0, 0.4);
24
+ --possible-move: rgba(0, 0, 0, 0.2);
25
+ }
26
+
27
+ body {
28
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
29
+ background: linear-gradient(135deg, var(--dark) 0%, var(--primary) 100%);
30
+ min-height: 100vh;
31
+ color: var(--light);
32
+ overflow-x: hidden;
33
+ }
34
+
35
+ header {
36
+ text-align: center;
37
+ padding: 1.5rem;
38
+ background: rgba(0, 0, 0, 0.3);
39
+ backdrop-filter: blur(10px);
40
+ }
41
+
42
+ header h1 {
43
+ font-size: clamp(1.5rem, 4vw, 2.5rem);
44
+ margin-bottom: 0.5rem;
45
+ background: linear-gradient(90deg, var(--secondary), var(--accent));
46
+ -webkit-background-clip: text;
47
+ -webkit-text-fill-color: transparent;
48
+ background-clip: text;
49
+ }
50
+
51
+ .built-with {
52
+ font-size: 0.85rem;
53
+ color: var(--light);
54
+ opacity: 0.8;
55
+ }
56
+
57
+ .built-with a {
58
+ color: var(--secondary);
59
+ text-decoration: none;
60
+ transition: color 0.3s;
61
+ }
62
+
63
+ .built-with a:hover {
64
+ color: var(--accent);
65
+ }
66
+
67
+ .container {
68
+ display: flex;
69
+ flex-wrap: wrap;
70
+ justify-content: center;
71
+ align-items: flex-start;
72
+ gap: 2rem;
73
+ padding: 2rem;
74
+ max-width: 1400px;
75
+ margin: 0 auto;
76
+ }
77
+
78
+ .game-section {
79
+ display: flex;
80
+ flex-direction: column;
81
+ align-items: center;
82
+ gap: 1rem;
83
+ }
84
+
85
+ .board-container {
86
+ position: relative;
87
+ padding: 10px;
88
+ background: linear-gradient(145deg, #34495e, #2c3e50);
89
+ border-radius: 12px;
90
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
91
+ }
92
+
93
+ .board {
94
+ display: grid;
95
+ grid-template-columns: repeat(8, 1fr);
96
+ width: clamp(280px, 80vw, 560px);
97
+ aspect-ratio: 1;
98
+ border-radius: 8px;
99
+ overflow: hidden;
100
+ }
101
+
102
+ .square {
103
+ aspect-ratio: 1;
104
+ display: flex;
105
+ justify-content: center;
106
+ align-items: center;
107
+ font-size: clamp(2rem, 8vw, 4rem);
108
+ cursor: pointer;
109
+ position: relative;
110
+ transition: transform 0.1s;
111
+ user-select: none;
112
+ }
113
+
114
+ .square.light {
115
+ background: var(--light-square);
116
+ }
117
+
118
+ .square.dark {
119
+ background: var(--dark-square);
120
+ }
121
+
122
+ .square.selected {
123
+ background: var(--highlight) !important;
124
+ }
125
+
126
+ .square.possible-move::after {
127
+ content: '';
128
+ position: absolute;
129
+ width: 30%;
130
+ height: 30%;
131
+ background: var(--possible-move);
132
+ border-radius: 50%;
133
+ }
134
+
135
+ .square.possible-capture::after {
136
+ content: '';
137
+ position: absolute;
138
+ width: 90%;
139
+ height: 90%;
140
+ border: 4px solid var(--possible-move);
141
+ border-radius: 50%;
142
+ background: transparent;
143
+ }
144
+
145
+ .square.last-move {
146
+ background: rgba(155, 199, 0, 0.4) !important;
147
+ }
148
+
149
+ .square.check {
150
+ background: radial-gradient(circle, var(--accent) 0%, transparent 70%) !important;
151
+ }
152
+
153
+ .piece {
154
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
155
+ transition: transform 0.15s;
156
+ }
157
+
158
+ .square:hover .piece {
159
+ transform: scale(1.1);
160
+ }
161
+
162
+ .info-panel {
163
+ background: rgba(0, 0, 0, 0.4);
164
+ backdrop-filter: blur(10px);
165
+ border-radius: 12px;
166
+ padding: 1.5rem;
167
+ width: clamp(280px, 80vw, 350px);
168
+ display: flex;
169
+ flex-direction: column;
170
+ gap: 1rem;
171
+ }
172
+
173
+ .stat-card {
174
+ background: rgba(255, 255, 255, 0.1);
175
+ border-radius: 8px;
176
+ padding: 1rem;
177
+ }
178
+
179
+ .stat-card h3 {
180
+ font-size: 0.85rem;
181
+ text-transform: uppercase;
182
+ letter-spacing: 1px;
183
+ color: var(--secondary);
184
+ margin-bottom: 0.5rem;
185
+ }
186
+
187
+ .stat-value {
188
+ font-size: 1.8rem;
189
+ font-weight: bold;
190
+ }
191
+
192
+ .level-bar {
193
+ width: 100%;
194
+ height: 10px;
195
+ background: rgba(255, 255, 255, 0.2);
196
+ border-radius: 5px;
197
+ overflow: hidden;
198
+ margin-top: 0.5rem;
199
+ }
200
+
201
+ .level-fill {
202
+ height: 100%;
203
+ background: linear-gradient(90deg, var(--secondary), var(--accent));
204
+ transition: width 0.5s ease;
205
+ border-radius: 5px;
206
+ }
207
+
208
+ .status {
209
+ text-align: center;
210
+ padding: 0.75rem;
211
+ border-radius: 8px;
212
+ font-weight: bold;
213
+ background: rgba(255, 255, 255, 0.1);
214
+ }
215
+
216
+ .status.your-turn {
217
+ background: rgba(46, 204, 113, 0.3);
218
+ color: #2ecc71;
219
+ }
220
+
221
+ .status.ai-turn {
222
+ background: rgba(231, 76, 60, 0.3);
223
+ color: #e74c3c;
224
+ }
225
+
226
+ .status.game-over {
227
+ background: rgba(155, 89, 182, 0.3);
228
+ color: #9b59b6;
229
+ }
230
+
231
+ .buttons {
232
+ display: flex;
233
+ gap: 0.5rem;
234
+ flex-wrap: wrap;
235
+ }
236
+
237
+ button {
238
+ flex: 1;
239
+ min-width: 100px;
240
+ padding: 0.75rem 1rem;
241
+ border: none;
242
+ border-radius: 8px;
243
+ font-size: 0.9rem;
244
+ font-weight: bold;
245
+ cursor: pointer;
246
+ transition: all 0.3s;
247
+ text-transform: uppercase;
248
+ letter-spacing: 1px;
249
+ }
250
+
251
+ .btn-primary {
252
+ background: linear-gradient(135deg, var(--secondary), #2980b9);
253
+ color: white;
254
+ }
255
+
256
+ .btn-secondary {
257
+ background: rgba(255, 255, 255, 0.2);
258
+ color: white;
259
+ }
260
+
261
+ button:hover {
262
+ transform: translateY(-2px);
263
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
264
+ }
265
+
266
+ .move-history {
267
+ max-height: 200px;
268
+ overflow-y: auto;
269
+ background: rgba(0, 0, 0, 0.2);
270
+ border-radius: 8px;
271
+ padding: 0.75rem;
272
+ }
273
+
274
+ .move-history::-webkit-scrollbar {
275
+ width: 6px;
276
+ }
277
+
278
+ .move-history::-webkit-scrollbar-track {
279
+ background: rgba(255, 255, 255, 0.1);
280
+ border-radius: 3px;
281
+ }
282
+
283
+ .move-history::-webkit-scrollbar-thumb {
284
+ background: var(--secondary);
285
+ border-radius: 3px;
286
+ }
287
+
288
+ .move-row {
289
+ display: flex;
290
+ padding: 0.25rem 0;
291
+ font-family: 'Courier New', monospace;
292
+ font-size: 0.9rem;
293
+ }
294
+
295
+ .move-number {
296
+ width: 30px;
297
+ color: var(--secondary);
298
+ }
299
+
300
+ .move-white,
301
+ .move-black {
302
+ flex: 1;
303
+ }
304
+
305
+ .thinking {
306
+ display: flex;
307
+ align-items: center;
308
+ gap: 0.5rem;
309
+ justify-content: center;
310
+ }
311
+
312
+ .thinking-dots {
313
+ display: flex;
314
+ gap: 4px;
315
+ }
316
+
317
+ .thinking-dots span {
318
+ width: 8px;
319
+ height: 8px;
320
+ background: var(--secondary);
321
+ border-radius: 50%;
322
+ animation: bounce 1.4s infinite ease-in-out both;
323
+ }
324
+
325
+ .thinking-dots span:nth-child(1) {
326
+ animation-delay: -0.32s;
327
+ }
328
+
329
+ .thinking-dots span:nth-child(2) {
330
+ animation-delay: -0.16s;
331
+ }
332
+
333
+ @keyframes bounce {
334
+
335
+ 0%,
336
+ 80%,
337
+ 100% {
338
+ transform: scale(0);
339
+ }
340
+
341
+ 40% {
342
+ transform: scale(1);
343
+ }
344
+ }
345
+
346
+ .promotion-modal {
347
+ position: fixed;
348
+ top: 0;
349
+ left: 0;
350
+ width: 100%;
351
+ height: 100%;
352
+ background: rgba(0, 0, 0, 0.8);
353
+ display: none;
354
+ justify-content: center;
355
+ align-items: center;
356
+ z-index: 1000;
357
+ }
358
+
359
+ .promotion-modal.active {
360
+ display: flex;
361
+ }
362
+
363
+ .promotion-options {
364
+ display: flex;
365
+ gap: 1rem;
366
+ background: var(--primary);
367
+ padding: 1.5rem;
368
+ border-radius: 12px;
369
+ }
370
+
371
+ .promotion-piece {
372
+ font-size: 3rem;
373
+ padding: 0.5rem 1rem;
374
+ background: rgba(255, 255, 255, 0.1);
375
+ border-radius: 8px;
376
+ cursor: pointer;
377
+ transition: all 0.3s;
378
+ }
379
+
380
+ .promotion-piece:hover {
381
+ background: var(--secondary);
382
+ transform: scale(1.1);
383
+ }
384
+
385
+ .performance-graph {
386
+ height: 80px;
387
+ display: flex;
388
+ align-items: flex-end;
389
+ gap: 2px;
390
+ padding: 0.5rem;
391
+ background: rgba(0, 0, 0, 0.2);
392
+ border-radius: 8px;
393
+ }
394
+
395
+ .graph-bar {
396
+ flex: 1;
397
+ background: var(--secondary);
398
+ border-radius: 2px 2px 0 0;
399
+ transition: height 0.3s;
400
+ min-height: 4px;
401
+ }
402
+
403
+ .graph-bar.win {
404
+ background: #2ecc71;
405
+ }
406
+
407
+ .graph-bar.loss {
408
+ background: #e74c3c;
409
+ }
410
+
411
+ .graph-bar.draw {
412
+ background: #f39c12;
413
+ }
414
+
415
+ @media (max-width: 768px) {
416
+ .container {
417
+ padding: 1rem;
418
+ gap: 1rem;
419
+ }
420
+
421
+ .info-panel {
422
+ width: 100%;
423
+ }
424
+
425
+ header {
426
+ padding: 1rem;
427
+ }
428
+ }
429
+
430
+ .captured-pieces {
431
+ display: flex;
432
+ flex-wrap: wrap;
433
+ gap: 2px;
434
+ min-height: 30px;
435
+ font-size: 1.2rem;
436
+ }
437
+
438
+ .advantage {
439
+ font-size: 0.9rem;
440
+ color: var(--secondary);
441
+ }
442
+ </style>
443
+ </head>
444
+
445
+ <body>
446
+ <header>
447
+ <h1>♔ Adaptive Chess</h1>
448
+ <p class="built-with">Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder"
449
+ target="_blank">anycoder</a></p>
450
+ </header>
451
+
452
+ <div class="container">
453
+ <div class="game-section">
454
+ <div class="captured-pieces" id="captured-black"></div>
455
+ <div class="board-container">
456
+ <div class="board" id="board"></div>
457
+ </div>
458
+ <div class="captured-pieces" id="captured-white"></div>
459
+ </div>
460
+
461
+ <div class="info-panel">
462
+ <div id="status" class="status your-turn">Your Turn (White)</div>
463
+
464
+ <div class="stat-card">
465
+ <h3>AI Skill Level</h3>
466
+ <div class="stat-value" id="skill-level">1</div>
467
+ <div class="level-bar">
468
+ <div class="level-fill" id="level-fill" style="width: 5%"></div>
469
+ </div>
470
+ <small style="opacity: 0.7">Adapts to your play style</small>
471
+ </div>
472
+
473
+ <div class="stat-card">
474
+ <h3>Your Performance</h3>
475
+ <div style="display: flex; justify-content: space-between; margin-bottom: 0.5rem;">
476
+ <span>Wins: <strong id="wins">0</strong></span>
477
+ <span>Draws: <strong id="draws">0</strong></span>
478
+ <span>Losses: <strong id="losses">0</strong></span>
479
+ </div>
480
+ <div class="performance-graph" id="performance-graph"></div>
481
+ </div>
482
+
483
+ <div class="stat-card">
484
+ <h3>Move History</h3>
485
+ <div class="move-history" id="move-history"></div>
486
+ </div>
487
+
488
+ <div class="buttons">
489
+ <button class="btn-primary" onclick="newGame()">New Game</button>
490
+ <button class="btn-secondary" onclick="undoMove()">Undo</button>
491
+ </div>
492
+
493
+ <div class="buttons">
494
+ <button class="btn-secondary" onclick="flipBoard()">Flip Board</button>
495
+ <button class="btn-secondary" onclick="resetProgress()">Reset AI</button>
496
+ </div>
497
+ </div>
498
+ </div>
499
+
500
+ <div class="promotion-modal" id="promotion-modal">
501
+ <div class="promotion-options" id="promotion-options"></div>
502
+ </div>
503
+
504
+ <script>
505
+ // Chess piece unicode symbols
506
+ const PIECES = {
507
+ 'K': '♔', 'Q': '♕', 'R': '♖', 'B': '♗', 'N': '♘', 'P': '♙',
508
+ 'k': '♚', 'q': '♛', 'r': '♜', 'b': '♝', 'n': '♞', 'p': '♟'
509
+ };
510
+
511
+ // Game state
512
+ let board = [];
513
+ let selectedSquare = null;
514
+ let possibleMoves = [];
515
+ let currentTurn = 'white';
516
+ let moveHistory = [];
517
+ let gameHistory = [];
518
+ let castlingRights = { K: true, Q: true, k: true, q: true };
519
+ let enPassantSquare = null;
520
+ let halfMoveClock = 0;
521
+ let fullMoveNumber = 1;
522
+ let isFlipped = false;
523
+ let lastMove = null;
524
+ let capturedPieces = { white: [], black: [] };
525
+
526
+ // AI and adaptive learning state
527
+ let skillLevel = 1;
528
+ let maxSkillLevel = 20;
529
+ let playerStats = { wins: 0, draws: 0, losses: 0 };
530
+ let gameResults = [];
531
+ let playerMoveQuality = [];
532
+ let isAIThinking = false;
533
+
534
+ // Piece values for evaluation
535
+ const PIECE_VALUES = {
536
+ 'p': 100, 'n': 320, 'b': 330, 'r': 500, 'q': 900, 'k': 20000,
537
+ 'P': 100, 'N': 320, 'B': 330, 'R': 500, 'Q': 900, 'K': 20000
538
+ };
539
+
540
+ // Position tables for piece-square evaluation
541
+ const PAWN_TABLE = [
542
+ 0, 0, 0, 0, 0, 0, 0, 0,
543
+ 50, 50, 50, 50, 50, 50, 50, 50,
544
+ 10, 10, 20, 30, 30, 20, 10, 10,
545
+ 5, 5, 10, 25, 25, 10, 5, 5,
546
+ 0, 0, 0, 20, 20, 0, 0, 0,
547
+ 5, -5,-10, 0, 0,-10, -5, 5,
548
+ 5, 10, 10,-20,-20, 10, 10, 5,
549
+ 0, 0, 0, 0, 0, 0, 0, 0
550
+ ];
551
+
552
+ const KNIGHT_TABLE = [
553
+ -50,-40,-30,-30,-30,-30,-40,-50,
554
+ -40,-20, 0, 0, 0, 0,-20,-40,
555
+ -30, 0, 10, 15, 15, 10, 0,-30,
556
+ -30, 5, 15, 20, 20, 15, 5,-30,
557
+ -30, 0, 15, 20, 20, 15, 0,-30,
558
+ -30, 5, 10, 15, 15, 10, 5,-30,
559
+ -40,-20, 0, 5, 5, 0,-20,-40,
560
+ -50,-40,-30,-30,-30,-30,-40,-50
561
+ ];
562
+
563
+ const BISHOP_TABLE = [
564
+ -20,-10,-10,-10,-10,-10,-10,-20,
565
+ -10, 0, 0, 0, 0, 0, 0,-10,
566
+ -10, 0, 5, 10, 10, 5, 0,-10,
567
+ -10, 5, 5, 10, 10, 5, 5,-10,
568
+ -10, 0, 10, 10, 10, 10, 0,-10,
569
+ -10, 10, 10, 10, 10, 10, 10,-10,
570
+ -10, 5, 0, 0, 0, 0, 5,-10,
571
+ -20,-10,-10,-10,-10,-10,-10,-20
572
+ ];
573
+
574
+ const ROOK_TABLE = [
575
+ 0, 0, 0, 0, 0, 0, 0, 0,
576
+ 5, 10, 10, 10, 10, 10, 10, 5,
577
+ -5, 0, 0, 0, 0, 0, 0, -5,
578
+ -5, 0, 0, 0, 0, 0, 0, -5,
579
+ -5, 0, 0, 0, 0, 0, 0, -5,
580
+ -5, 0, 0, 0, 0, 0, 0, -5,
581
+ -5, 0, 0, 0, 0, 0, 0, -5,
582
+ 0, 0, 0, 5, 5, 0, 0, 0
583
+ ];
584
+
585
+ const QUEEN_TABLE = [
586
+ -20,-10,-10, -5, -5,-10,-10,-20,
587
+ -10, 0, 0, 0, 0, 0, 0,-10,
588
+ -10, 0, 5, 5, 5, 5, 0,-10,
589
+ -5, 0, 5, 5, 5, 5, 0, -5,
590
+ 0, 0, 5, 5, 5, 5, 0, -5,
591
+ -10, 5, 5, 5, 5, 5, 0,-10,
592
+ -10, 0, 5, 0, 0, 0, 0,-10,
593
+ -20,-10,-10, -5, -5,-10,-10,-20
594
+ ];
595
+
596
+ const KING_TABLE = [
597
+ -30,-40,-40,-50,-50,-40,-40,-30,
598
+ -30,-40,-40,-50,-50,-40,-40,-30,
599
+ -30,-40,-40,-50,-50,-40,-40,-30,
600
+ -30,-40,-40,-50,-50,-40,-40,-30,
601
+ -20,-30,-30,-40,-40,-30,-30,-20,
602
+ -10,-20,-20,-20,-20,-20,-20,-10,
603
+ 20, 20, 0, 0, 0, 0, 20, 20,
604
+ 20, 30, 10, 0, 0, 10, 30, 20
605
+ ];
606
+
607
+ const KING_ENDGAME_TABLE = [
608
+ -50,-40,-30,-20,-20,-30,-40,-50,
609
+ -30,-20,-10, 0, 0,-10,-20,-30,
610
+ -30,-10, 20, 30, 30, 20,-10,-30,
611
+ -30,-10, 30, 40, 40, 30,-10,-30,
612
+ -30,-10, 30, 40, 40, 30,-10,-30,
613
+ -30,-10, 20, 30, 30, 20,-10,-30,
614
+ -30,-30, 0, 0, 0, 0,-30,-30,
615
+ -50,-30,-30,-30,-30,-30,-30,-50
616
+ ];
617
+
618
+ // Initialize the game
619
+ function initGame() {
620
+ loadProgress();
621
+ setupBoard();
622
+ renderBoard();
623
+ updateUI();
624
+ }
625
+
626
+ function setupBoard() {
627
+ board = [
628
+ ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'],
629
+ ['p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'],
630
+ [null, null, null, null, null, null, null, null],
631
+ [null, null, null, null, null, null, null, null],
632
+ [null, null, null, null, null, null, null, null],
633
+ [null, null, null, null, null, null, null, null],
634
+ ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'],
635
+ ['R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R']
636
+ ];
637
+ currentTurn = 'white';
638
+ selectedSquare = null;
639
+ possibleMoves = [];
640
+ moveHistory = [];
641
+ gameHistory = [];
642
+ castlingRights = { K: true, Q: true, k: true, q: true };
643
+ enPassantSquare = null;
644
+ halfMoveClock = 0;
645
+ fullMoveNumber = 1;
646
+ lastMove = null;
647
+ capturedPieces = { white: [], black: [] };
648
+ playerMoveQuality = [];
649
+ }
650
+
651
+ function renderBoard() {
652
+ const boardEl = document.getElementById('board');
653
+ boardEl.innerHTML = '';
654
+
655
+ for (let row = 0; row < 8; row++) {
656
+ for (let col = 0; col < 8; col++) {
657
+ const displayRow = isFlipped ? 7 - row : row;
658
+ const displayCol = isFlipped ? 7 - col : col;
659
+
660
+ const square = document.createElement('div');
661
+ const isLight = (displayRow + displayCol) % 2 === 0;
662
+ square.className = `square ${isLight ? 'light' : 'dark'}`;
663
+ square.dataset.row = displayRow;
664
+ square.dataset.col = displayCol;
665
+
666
+ // Highlight last move
667
+ if (lastMove) {
668
+ if ((displayRow === lastMove.fromRow && displayCol === lastMove.fromCol) ||
669
+ (displayRow === lastMove.toRow && displayCol === lastMove.toCol)) {
670
+ square.classList.add('last-move');
671
+ }
672
+ }
673
+
674
+ // Highlight selected square
675
+ if (selectedSquare && selectedSquare.row === displayRow && selectedSquare.col === displayCol) {
676
+ square.classList.add('selected');
677
+ }
678
+
679
+ // Show possible moves
680
+ const isPossibleMove = possibleMoves.some(m => m.toRow === displayRow && m.toCol === displayCol);
681
+ if (isPossibleMove) {
682
+ const targetPiece = board[displayRow][displayCol];
683
+ if (targetPiece) {
684
+ square.classList.add('possible-capture');
685
+ } else {
686
+ square.classList.add('possible-move');
687
+ }
688
+ }
689
+
690
+ // Check highlight
691
+ const piece = board[displayRow][displayCol];
692
+ if (piece && piece.toLowerCase() === 'k') {
693
+ const pieceColor = piece === piece.toUpperCase() ? 'white' : 'black';
694
+ if (isInCheck(pieceColor)) {
695
+ square.classList.add('check');
696
+ }
697
+ }
698
+
699
+ // Add piece
700
+ if (piece) {
701
+ const pieceEl = document.createElement('span');
702
+ pieceEl.className = 'piece';
703
+ pieceEl.textContent = PIECES[piece];
704
+ square.appendChild(pieceEl);
705
+ }
706
+
707
+ square.addEventListener('click', () => handleSquareClick(displayRow, displayCol));
708
+ boardEl.appendChild(square);
709
+ }
710
+ }
711
+
712
+ updateCapturedPieces();
713
+ }
714
+
715
+ function updateCapturedPieces() {
716
+ const whiteEl = document.getElementById('captured-white');
717
+ const blackEl = document.getElementById('captured-black');
718
+
719
+ whiteEl.innerHTML = capturedPieces.white.map(p => PIECES[p]).join(' ');
720
+ blackEl.innerHTML = capturedPieces.black.map(p => PIECES[p]).join(' ');
721
+
722
+ // Calculate material advantage
723
+ const whiteValue = capturedPieces.black.reduce((sum, p) => sum + PIECE_VALUES[p], 0);
724
+ const blackValue = capturedPieces.white.reduce((sum, p) => sum + PIECE_VALUES[p], 0);
725
+ const diff = whiteValue - blackValue;
726
+
727
+ if (diff > 0) {
728
+ whiteEl.innerHTML += ` <span class="advantage">+${Math.floor(diff/100)}</span>`;
729
+ } else if (diff < 0) {
730
+ blackEl.innerHTML += ` <span class="advantage">+${Math.floor(-diff/100)}</span>`;
731
+ }
732
+ }
733
+
734
+ function handleSquareClick(row, col) {
735
+ if (isAIThinking) return;
736
+ if (currentTurn !== 'white') return;
737
+
738
+ const piece = board[row][col];
739
+
740
+ if (selectedSquare) {
741
+ // Check if clicking on a possible move
742
+ const move = possibleMoves.find(m => m.toRow === row && m.toCol === col);
743
+ if (move) {
744
+ makeMove(move);
745
+ return;
746
+ }
747
+ }
748
+
749
+ // Select a new piece
750
+ if (piece && isWhitePiece(piece)) {
751
+ selectedSquare = { row, col };
752
+ possibleMoves = getLegalMoves(row, col);
753
+ renderBoard();
754
+ } else {
755
+ selectedSquare = null;
756
+ possibleMoves = [];
757
+ renderBoard();
758
+ }
759
+ }
760
+
761
+ function isWhitePiece(piece) {
762
+ return piece && piece === piece.toUpperCase();
763
+ }
764
+
765
+ function isBlackPiece(piece) {
766
+ return piece && piece === piece.toLowerCase();
767
+ }
768
+
769
+ function getPieceColor(piece) {
770
+ if (!piece) return null;
771
+ return piece === piece.toUpperCase() ? 'white' : 'black';
772
+ }
773
+
774
+ function getLegalMoves(row, col) {
775
+ const piece = board[row][col];
776
+ if (!piece) return [];
777
+
778
+ const moves = getPseudoLegalMoves(row, col);
779
+ const color = getPieceColor(piece);
780
+
781
+ // Filter out moves that leave king in check
782
+ return moves.filter(move => {
783
+ const testBoard = JSON.parse(JSON.stringify(board));
784
+ testBoard[move.toRow][move.toCol] = testBoard[move.fromRow][move.fromCol];
785
+ testBoard[move.fromRow][move.fromCol] = null;
786
+
787
+ // Handle en passant capture
788
+ if (move.enPassant) {
789
+ testBoard[move.fromRow][move.toCol] = null;
790
+ }
791
+
792
+ // Handle castling - move rook
793
+ if (move.castling) {
794
+ if (move.toCol === 6) { // Kingside
795
+ testBoard[move.toRow][5] = testBoard[move.toRow][7];
796
+ testBoard[move.toRow][7] = null;
797
+ } else { // Queenside
798
+ testBoard[move.toRow][3] = testBoard[move.toRow][0];
799
+ testBoard[move.toRow][0] = null;
800
+ }
801
+ }
802
+
803
+ return !isInCheckWithBoard(color, testBoard);
804
+ });
805
+ }
806
+
807
+ function getPseudoLegalMoves(row, col) {
808
+ const piece = board[row][col];
809
+ if (!piece) return [];
810
+
811
+ const pieceType = piece.toLowerCase();
812
+ const color = getPieceColor(piece);
813
+ const moves = [];
814
+
815
+ switch (pieceType) {
816
+ case 'p':
817
+ moves.push(...getPawnMoves(row, col, color));
818
+ break;
819
+ case 'n':
820
+ moves.push(...getKnightMoves(row, col, color));
821
+ break;
822
+ case 'b':
823
+ moves.push(...getBishopMoves(row, col, color));
824
+ break;
825
+ case 'r':
826
+ moves.push(...getRookMoves(row, col, color));
827
+ break;
828
+ case 'q':
829
+ moves.push(...getQueenMoves(row, col, color));
830
+ break;
831
+ case 'k':
832
+ moves.push(...getKingMoves(row, col, color));
833
+ break;
834
+ }
835
+
836
+ return moves;
837
+ }
838
+
839
+ function getPawnMoves(row, col, color) {
840
+ const moves = [];
841
+ const direction = color === 'white' ? -1 : 1;
842
+ const startRow = color === 'white' ? 6 : 1;
843
+ const promotionRow = color === 'white' ? 0 : 7;
844
+
845
+ // Forward move
846
+ if (isValidSquare(row + direction, col) && !board[row + direction][col]) {
847
+ if (row + direction === promotionRow) {
848
+ moves.push({ fromRow: row, fromCol: col, toRow: row + direction, toCol: col, promotion: true });
849
+ } else {
850
+ moves.push({ fromRow: row, fromCol: col, toRow: row + direction, toCol: col });
851
+ }
852
+
853
+ // Double move from start
854
+ if (row === startRow && !board[row + 2 * direction][col]) {
855
+ moves.push({ fromRow: row, fromCol: col, toRow: row + 2 * direction, toCol: col, doublePawn: true });
856
+ }
857
+ }
858
+
859
+ // Captures
860
+ for (const dc of [-1, 1]) {
861
+ const newCol = col + dc;
862
+ if (isValidSquare(row + direction, newCol)) {
863
+ const target = board[row + direction][newCol];
864
+ if (target && getPieceColor(target) !== color) {
865
+ if (row + direction === promotionRow) {
866
+ moves.push({ fromRow: row, fromCol: col, toRow: row + direction, toCol: newCol, promotion: true });
867
+ } else {
868
+ moves.push({ fromRow: row, fromCol: col, toRow: row + direction, toCol: newCol });
869
+ }
870
+ }
871
+
872
+ // En passant
873
+ if (enPassantSquare && enPassantSquare.row === row + direction && enPassantSquare.col === newCol) {
874
+ moves.push({ fromRow: row, fromCol: col, toRow: row + direction, toCol: newCol, enPassant: true });
875
+ }
876
+ }
877
+ }
878
+
879
+ return moves;
880
+ }
881
+
882
+ function getKnightMoves(row, col, color) {
883
+ const moves = [];
884
+ const offsets = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]];
885
+
886
+ for (const [dr, dc] of offsets) {
887
+ const newRow = row + dr;
888
+ const newCol = col + dc;
889
+ if (isValidSquare(newRow, newCol)) {
890
+ const target = board[newRow][newCol];
891
+ if (!target || getPieceColor(target) !== color) {
892
+ moves.push({ fromRow: row, fromCol: col, toRow: newRow, toCol: newCol });
893
+ }
894
+ }
895
+ }
896
+
897
+ return moves;
898
+ }
899
+
900
+ function getSlidingMoves(row, col, color, directions) {
901
+ const moves = [];
902
+
903
+ for (const [dr, dc] of directions) {
904
+ let newRow = row + dr;
905
+ let newCol = col + dc;
906
+
907
+ while (isValidSquare(newRow, newCol)) {
908
+ const target = board[newRow][newCol];
909
+ if (!target) {
910
+ moves.push({ fromRow: row, fromCol: col, toRow: newRow, toCol: newCol });
911
+ } else {
912
+ if (getPieceColor(target) !== color) {
913
+ moves.push({ fromRow: row, fromCol: col, toRow: newRow, toCol: newCol });
914
+ }
915
+ break;
916
+ }
917
+ newRow += dr;
918
+ newCol += dc;
919
+ }
920
+ }
921
+
922
+ return moves;
923
+ }
924
+
925
+ function getBishopMoves(row, col, color) {
926
+ return getSlidingMoves(row, col, color, [[-1, -1], [-1, 1], [1, -1], [1, 1]]);
927
+ }
928
+
929
+ function getRookMoves(row, col, color) {
930
+ return getSlidingMoves(row, col, color, [[-1, 0], [1, 0], [0, -1], [0, 1]]);
931
+ }
932
+
933
+ function getQueenMoves(row, col, color) {
934
+ return [...getBishopMoves(row, col, color), ...getRookMoves(row, col, color)];
935
+ }
936
+
937
+ function getKingMoves(row, col, color) {
938
+ const moves = [];
939
+ const offsets = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
940
+
941
+ for (const [dr, dc] of offsets) {
942
+ const newRow = row + dr;
943
+ const newCol = col + dc;
944
+ if (isValidSquare(newRow, newCol)) {
945
+ const target = board[newRow][newCol];
946
+ if (!target || getPieceColor(target) !== color) {
947
+ moves.push({ fromRow: row, fromCol: col, toRow: newRow, toCol: newCol });
948
+ }
949
+ }
950
+ }
951
+
952
+ // Castling
953
+ if (!isInCheck(color)) {
954
+ const kingRow = color === 'white' ? 7 : 0;
955
+ if (row === kingRow && col === 4) {
956
+ // Kingside
957
+ const kingSideRight = color === 'white' ? castlingRights.K : castlingRights.k;
958
+ if (kingSideRight && !board[kingRow][5] && !board[kingRow][6]) {
959
+ if (!isSquareAttacked(kingRow, 5, color) && !isSquareAttacked(kingRow, 6, color)) {
960
+ moves.push({ fromRow: row, fromCol: col, toRow: kingRow, toCol: 6, castling: true });
961
+ }
962
+ }
963
+
964
+ // Queenside
965
+ const queenSideRight = color === 'white' ? castlingRights.Q : castlingRights.q;
966
+ if (queenSideRight && !board[kingRow][1] && !board[kingRow][2] && !board[kingRow][3]) {
967
+ if (!isSquareAttacked(kingRow, 2, color) && !isSquareAttacked(kingRow, 3, color)) {
968
+ moves.push({ fromRow: row, fromCol: col, toRow: kingRow, toCol: 2, castling: true });
969
+ }
970
+ }
971
+ }
972
+ }
973
+
974
+ return moves;
975
+ }
976
+
977
+ function isValidSquare(row, col) {
978
+ return row >= 0 && row < 8 && col >= 0 && col < 8;
979
+ }
980
+
981
+ function isInCheck(color) {
982
+ return isInCheckWithBoard(color, board);
983
+ }
984
+
985
+ function isInCheckWithBoard(color, testBoard) {
986
+ // Find king
987
+ let kingRow, kingCol;
988
+ for (let r = 0; r < 8; r++) {
989
+ for (let c = 0; c < 8; c++) {
990
+ const piece = testBoard[r][c];
991
+ if (piece && piece.toLowerCase() === 'k' && getPieceColor(piece) === color) {
992
+ kingRow = r;
993
+ kingCol = c;
994
+ break;
995
+ }
996
+ }
997
+ }
998
+
999
+ return isSquareAttackedWithBoard(kingRow, kingCol, color, testBoard);
1000
+ }
1001
+
1002
+ function isSquareAttacked(row, col, defendingColor) {
1003
+ return isSquareAttackedWithBoard(row, col, defendingColor, board);
1004
+ }
1005
+
1006
+ function isSquareAttackedWithBoard(row, col, defendingColor, testBoard) {