Sebastiankay commited on
Commit
c29b222
·
verified ·
1 Parent(s): 43169e0

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +831 -13
index.html CHANGED
@@ -1,19 +1,837 @@
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
  <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Document</title>
 
7
  </head>
8
  <body>
9
+ <style>
10
+ @font-face {
11
+ font-family: "Caveat Brush";
12
+ font-style: normal;
13
+ font-weight: 400;
14
+ font-display: swap;
15
+ src: url(https://fonts.gstatic.com/s/caveatbrush/v11/EYq0maZfwr9S9-ETZc3fKXtMWw.ttf) format("truetype");
16
+ }
17
+
18
+ body {
19
+ background-color: rgba(var(--active-background-color), 1);
20
+ /* background-image: radial-gradient(circle, rgba(var(--active-background-color), 1) 0%, color-mix(in srgb, rgba(var(--active-background-color), 1) 60%, black) 100%); */
21
+ background-image: radial-gradient(circle, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 100%);
22
+ color: #222;
23
+ font-family: Arial, sans-serif;
24
+ margin: 0;
25
+ padding: 0;
26
+ display: flex;
27
+ justify-content: center;
28
+ align-items: center;
29
+ height: 100vh;
30
+ max-height: 100vh;
31
+ width: 100vw;
32
+ max-width: 100vw;
33
+ overflow: hidden;
34
+ transition: background-color 0.6s ease-out;
35
+ }
36
+
37
+ #game-container {
38
+ padding: 20px;
39
+ border-radius: 8px;
40
+ text-align: center;
41
+ position: relative;
42
+ display: flex;
43
+ flex-direction: column;
44
+ justify-content: center;
45
+ align-items: center;
46
+ }
47
+
48
+ .buttons {
49
+ position: relative;
50
+ z-index: 20;
51
+ display: flex;
52
+ flex-wrap: wrap;
53
+ justify-content: center;
54
+ align-items: center;
55
+ gap: 4px;
56
+ margin-top: 15px;
57
+ #new-game {
58
+ padding: 10px 20px;
59
+ background-color: #555;
60
+ border: none;
61
+ color: #fff;
62
+ font-size: 16px;
63
+ border-radius: 4px;
64
+ cursor: pointer;
65
+ }
66
+
67
+ #new-game:hover {
68
+ background-color: #777;
69
+ }
70
+ }
71
+
72
+ #status {
73
+ margin-bottom: 10px;
74
+ font-family: "Caveat Brush", serif;
75
+ font-size: 3rem;
76
+ font-weight: 600;
77
+ color: color-mix(in srgb, rgba(var(--active-background-color), 1) 30%, black);
78
+ }
79
+
80
+ #board {
81
+ display: grid;
82
+ grid-template-columns: repeat(8, 1fr);
83
+ gap: 2px;
84
+ margin: 0;
85
+ background-color: rgba(68, 68, 68, 1);
86
+ border: none;
87
+ border-radius: 0.35rem;
88
+ overflow: hidden;
89
+ padding: 8px;
90
+ width: 90%;
91
+ max-height: 90vw;
92
+ }
93
+
94
+ @media screen and (orientation: landscape) {
95
+ #game-container {
96
+ width: 100vh;
97
+ max-width: 100vh;
98
+ aspect-ratio: 4 / 3;
99
+ }
100
+
101
+ #board {
102
+ display: grid;
103
+ grid-template-columns: repeat(8, 1fr);
104
+ gap: 2px;
105
+ width: 70vh;
106
+ max-width: 70vh;
107
+ }
108
+ }
109
+
110
+ @media screen and (orientation: portrait) {
111
+ #game-container {
112
+ width: 90vw;
113
+ max-width: 90vw;
114
+ aspect-ratio: 4 / 3;
115
+ }
116
+ }
117
+
118
+ .cell {
119
+ width: 100%;
120
+ aspect-ratio: 1 / 1;
121
+ box-sizing: border-box;
122
+ position: relative;
123
+ cursor: pointer;
124
+ }
125
+
126
+ .light {
127
+ background-color: #666;
128
+ }
129
+
130
+ .dark {
131
+ background-color: rgb(68, 68, 68);
132
+ }
133
+
134
+ .cell.highlight {
135
+ background-image: repeating-linear-gradient(-45deg, rgba(var(--active-background-color), 0.1), rgba(var(--active-background-color), 0.1) 1rem, rgba(var(--active-background-color), 0.4) 1rem, rgba(var(--active-background-color), 0.4) 2rem);
136
+ background-size: 200% 200%;
137
+ animation: barberpole 10s linear infinite;
138
+ }
139
+
140
+ @keyframes barberpole {
141
+ 100% {
142
+ background-position: 100% 100%;
143
+ }
144
+ }
145
+
146
+ .piece {
147
+ width: 80%;
148
+ height: 80%;
149
+ border-radius: 50%;
150
+ margin: 0;
151
+ position: relative;
152
+ top: 50%;
153
+ left: 50%;
154
+ transform: translate(-50%, -50%);
155
+ background-color: rgba(var(--player-color), 1);
156
+ /* border:0.35rem solid rgb(var(--player-color)); */
157
+ box-shadow: 0.2rem 0.2rem 0px 0px rgba(0, 0, 0, 0.2), 0px 0px 0 0.2rem inset rgba(0, 0, 0, 0.2);
158
+ /* filter: drop-shadow(0px 0px red);*/
159
+ }
160
+
161
+ .cell.selected .piece {
162
+ filter: brightness(0.6);
163
+ /* animation-name: pulse;
164
+ animation-duration: 1.4s;
165
+ animation-timing-function: linear;
166
+ animation-iteration-count: infinite; */
167
+ }
168
+ .piece.must-capture {
169
+ /* filter: brightness(0.6); */
170
+ animation-name: pulse;
171
+ animation-duration: 1.4s;
172
+ animation-timing-function: linear;
173
+ animation-iteration-count: infinite;
174
+ }
175
+
176
+ /* .piece::after {
177
+ position: absolute;
178
+ content: "";
179
+ width: 100%;
180
+ height: 100%;
181
+ border-radius: 50%;
182
+ margin: 0;
183
+ top: 50%;
184
+ left: 50%;
185
+ transform: translate(-50%, -50%) rotate(0deg);
186
+ /* border:0.35rem var(--border-style) var(--border-color); * /
187
+ animation-duration: 6s;
188
+ animation-timing-function: linear;
189
+ animation-iteration-count: infinite;
190
+ }
191
+
192
+ .piece.spin-ani::after {
193
+ transform: translate(-50%, -50%) rotate(0deg);
194
+ border: 0.35rem var(--border-style) var(--border-color);
195
+ animation-name: spin;
196
+ } */
197
+
198
+ .piece.king {
199
+ background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'><path fill='rgba(68,68,68,0.5)' d='M309 106c11.4-7 19-19.7 19-34c0-22.1-17.9-40-40-40s-40 17.9-40 40c0 14.4 7.6 27 19 34L209.7 220.6c-9.1 18.2-32.7 23.4-48.6 10.7L72 160c5-6.7 8-15 8-24c0-22.1-17.9-40-40-40S0 113.9 0 136s17.9 40 40 40c.2 0 .5 0 .7 0L86.4 427.4c5.5 30.4 32 52.6 63 52.6l277.2 0c30.9 0 57.4-22.1 63-52.6L535.3 176c.2 0 .5 0 .7 0c22.1 0 40-17.9 40-40s-17.9-40-40-40s-40 17.9-40 40c0 9 3 17.3 8 24l-89.1 71.3c-15.9 12.7-39.5 7.5-48.6-10.7L309 106z'/></svg>");
200
+ background-size: 50%;
201
+ background-repeat: no-repeat;
202
+ background-position: center;
203
+ }
204
+
205
+ #winMessage {
206
+ position: absolute;
207
+ top: 50%;
208
+ left: 50%;
209
+ transform: translate(-50%, -50%);
210
+ background-color: #222;
211
+ padding: 20px 30px;
212
+ border: 8px solid rgb(68, 68, 68);
213
+ color: rgb(68, 68, 68);
214
+ border-radius: 8px;
215
+ font-size: 24px;
216
+ display: none;
217
+ z-index: 10;
218
+ cursor: pointer;
219
+ }
220
+
221
+ #setPlayerNamesWrapper {
222
+ position: absolute;
223
+ top: 50%;
224
+ left: 50%;
225
+ width: 40%;
226
+ aspect-ratio: 16 / 9;
227
+ transform: translate(-50%, -50%);
228
+ border-radius: 8px;
229
+ padding: 20px 30px;
230
+ display: flex;
231
+ flex-direction: column;
232
+ justify-content: center;
233
+ align-items: center;
234
+ gap: 0;
235
+ background-image: url(http://62.68.75.171/themes/prismify-bootstrap-starter-kit/assets/images/dame_header_image.png);
236
+ background-repeat: no-repeat;
237
+ background-size: contain;
238
+ background-position: center;
239
+ #setPlayerNamesInputs {
240
+ position: relative;
241
+ display: flex;
242
+ flex-direction: column;
243
+ align-items: center;
244
+ input,
245
+ label {
246
+ font-family: "Caveat Brush", serif;
247
+ font-size: 2rem;
248
+ font-weight: 600;
249
+ border-radius: 4px;
250
+ border-width: 8px;
251
+ border-style: solid;
252
+ border-color: transparent;
253
+ background-color: transparent;
254
+ }
255
+
256
+ #inputPlayerName1 {
257
+ padding: 10px 20px;
258
+ background-color: rgb(var(--player1-color));
259
+ border-color: rgb(var(--player1-color));
260
+ color: color-mix(in srgb, rgba(var(--player1-color), 1) 20%, rgb(14, 14, 64));
261
+ transform: rotate(0.2deg);
262
+ margin-left: 4px;
263
+ margin-right: -4px;
264
+ }
265
+
266
+ #modeSelect {
267
+ padding: 10px 20px;
268
+ background-color: rgb(var(--player2-color));
269
+ border-color: rgb(var(--player2-color));
270
+ transform: rotate(-0.2deg);
271
+ border-radius: 4px;
272
+ border-width: 8px;
273
+ margin-top: -8px;
274
+ max-width: 60%;
275
+ margin-left: 60px;
276
+ #inputPlayerName2 {
277
+ color: color-mix(in srgb, rgba(var(--player2-color), 1) 20%, rgb(38, 7, 7));
278
+ text-align: right;
279
+ max-width: calc(100% - 60px);
280
+ }
281
+
282
+ #cpuToggle {
283
+ display: none;
284
+ }
285
+
286
+ label {
287
+ padding: 10px 20px;
288
+ background-color: rgb(var(--player2-color));
289
+ border: 8px solid rgb(var(--player2-color));
290
+ color: #555;
291
+ font-size: 16px;
292
+ cursor: pointer;
293
+ transition: all 0.3s ease-in-out;
294
+ background-repeat: no-repeat;
295
+ background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'><path fill='rgba(81,40,42,1)' d='M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z'/></svg>");
296
+ }
297
+
298
+ label:has(#cpuToggle:checked) {
299
+ background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'><path fill='rgba(81,40,42,1)' d='M320 0c17.7 0 32 14.3 32 32l0 64 120 0c39.8 0 72 32.2 72 72l0 272c0 39.8-32.2 72-72 72l-304 0c-39.8 0-72-32.2-72-72l0-272c0-39.8 32.2-72 72-72l120 0 0-64c0-17.7 14.3-32 32-32zM208 384c-8.8 0-16 7.2-16 16s7.2 16 16 16l32 0c8.8 0 16-7.2 16-16s-7.2-16-16-16l-32 0zm96 0c-8.8 0-16 7.2-16 16s7.2 16 16 16l32 0c8.8 0 16-7.2 16-16s-7.2-16-16-16l-32 0zm96 0c-8.8 0-16 7.2-16 16s7.2 16 16 16l32 0c8.8 0 16-7.2 16-16s-7.2-16-16-16l-32 0zM264 256a40 40 0 1 0 -80 0 40 40 0 1 0 80 0zm152 40a40 40 0 1 0 0-80 40 40 0 1 0 0 80zM48 224l16 0 0 192-16 0c-26.5 0-48-21.5-48-48l0-96c0-26.5 21.5-48 48-48zm544 0c26.5 0 48 21.5 48 48l0 96c0 26.5-21.5 48-48 48l-16 0 0-192 16 0z'/></svg>");
300
+ }
301
+ }
302
+
303
+ input:focus {
304
+ outline: none;
305
+ }
306
+
307
+ span#vs {
308
+ position: absolute;
309
+ top: 50%;
310
+ margin-top: -10px;
311
+ font-family: "Caveat Brush", serif;
312
+ font-size: 2rem;
313
+ font-weight: 600;
314
+ left: 50%;
315
+ transform: translate(-50%, -50%);
316
+ color: rgba(255, 255, 255, 1);
317
+ text-shadow: #444 2px 2px 0px, #444 2px -2px 0px, #444 -2px 2px 0px, #444 -2px -2px 0px, #444 2px 0px 0px, #444 0px 2px 0px, #444 -2px 0px 0px, #444 0px -2px 0px;
318
+ }
319
+ }
320
+
321
+ #savePlayerNames {
322
+ padding: 10px 20px;
323
+ background-color: #555;
324
+ border: none;
325
+ color: #fff;
326
+ font-size: 16px;
327
+ border-radius: 4px;
328
+ cursor: pointer;
329
+ margin-top: 12px;
330
+ }
331
+ }
332
+
333
+ #setPlayerNamesWrapperBackdrop {
334
+ position: absolute;
335
+ content: "";
336
+ width: 100vw;
337
+ height: 100vh;
338
+ top: 0px;
339
+ left: 0;
340
+ backdrop-filter: blur(10px);
341
+ }
342
+
343
+ @keyframes pulse {
344
+ 0% {
345
+ filter: brightness(1);
346
+ }
347
+
348
+ 50% {
349
+ filter: brightness(0.4);
350
+ }
351
+
352
+ 100% {
353
+ filter: brightness(1);
354
+ }
355
+ }
356
+
357
+ @keyframes spin {
358
+ from {
359
+ transform: translate(-50%, -50%) rotate(0deg);
360
+ }
361
+
362
+ to {
363
+ transform: translate(-50%, -50%) rotate(360deg);
364
+ }
365
+ }
366
+ </style>
367
+
368
+ <div id="game-container">
369
+ <div id="status">Spieler 1 am Zug</div>
370
+ <div id="board"></div>
371
+ <div class="buttons">
372
+ <button id="new-game">Neues Spiel</button>
373
+ </div>
374
  </div>
375
+ <div id="winMessage"></div>
376
+ <div id="setPlayerNamesWrapperBackdrop">
377
+ <div id="setPlayerNamesWrapper">
378
+ <div id="setPlayerNamesInputs">
379
+ <input type="text" id="inputPlayerName1" autocomplete="off" />
380
+ <div id="modeSelect">
381
+ <input type="text" id="inputPlayerName2" autocomplete="off" /><label> <input type="checkbox" id="cpuToggle" /></label>
382
+ </div>
383
+
384
+ <span id="vs">gegen</span>
385
+ </div>
386
+ <button id="savePlayerNames">Los</button>
387
+ </div>
388
+ </div>
389
+ <script>
390
+ const boardSize = 8
391
+ let board = [],
392
+ currentPlayer = 1,
393
+ selectedPiece = null,
394
+ validMoves = [],
395
+ gameRunning = false,
396
+ vsCPU = false
397
+
398
+ const playerColors = {
399
+ 1: "168, 208, 230",
400
+ 2: "246, 171, 182",
401
+ }
402
+
403
+ let players = {
404
+ 1: { name: "Spieler 1", color: "168, 208, 230" },
405
+ 2: { name: "Spieler 2", color: "246, 171, 182" },
406
+ }
407
+
408
+ const captureHighlightColors = {
409
+ 1: "128, 168, 190",
410
+ 2: "206, 131, 142",
411
+ }
412
+
413
+ const pieceColors = {
414
+ 1: "77, 129, 199",
415
+ 2: "214, 106, 139",
416
+ }
417
+
418
+ const body = document.body
419
+ body.style.setProperty("--player1-color", players[1].color)
420
+ body.style.setProperty("--player2-color", players[2].color)
421
+
422
+ const inputPlayerName1 = document.getElementById("inputPlayerName1")
423
+ inputPlayerName1.value = players[1].name
424
+
425
+ const inputPlayerName2 = document.getElementById("inputPlayerName2")
426
+ inputPlayerName2.value = players[2].name
427
+
428
+ const savePlayerNamesButton = document.getElementById("savePlayerNames")
429
+ const boardElement = document.getElementById("board")
430
+ const statusElement = document.getElementById("status")
431
+ const newGameButton = document.getElementById("new-game")
432
+ const winMessageElement = document.getElementById("winMessage")
433
+ const cpuToggle = document.getElementById("cpuToggle")
434
+
435
+ function inBounds(row, col) {
436
+ return row >= 0 && row < boardSize && col >= 0 && col < boardSize
437
+ }
438
+
439
+ function isEmpty(row, col) {
440
+ return board[row][col] === 0
441
+ }
442
+
443
+ function isOpponent(piece, player) {
444
+ return piece !== 0 && (player === 1 ? piece === 2 || piece === 4 : piece === 1 || piece === 3)
445
+ }
446
+
447
+ function isPlayerPiece(piece, player) {
448
+ return player === 1 ? piece === 1 || piece === 3 : player === 2 && (piece === 2 || piece === 4)
449
+ }
450
+
451
+ function isKing(piece) {
452
+ return piece === 3 || piece === 4
453
+ }
454
+
455
+ function initGame() {
456
+ board = Array.from({ length: boardSize }, () => Array(boardSize).fill(0))
457
+
458
+ for (let row = 0; row < 3; row++) {
459
+ for (let col = 0; col < boardSize; col++) {
460
+ if ((row + col) % 2 === 1) board[row][col] = 1
461
+ }
462
+ }
463
+
464
+ for (let row = boardSize - 3; row < boardSize; row++) {
465
+ for (let col = 0; col < boardSize; col++) {
466
+ if ((row + col) % 2 === 1) board[row][col] = 2
467
+ }
468
+ }
469
+
470
+ currentPlayer = 1
471
+ selectedPiece = null
472
+ validMoves = []
473
+ gameRunning = true
474
+ winMessageElement.style.display = "none"
475
+ newGameButton.style.display = "inline-block"
476
+ vsCPU = cpuToggle.checked
477
+ cpuToggle.disabled = false
478
+ updateStatus()
479
+ updateBackground()
480
+ renderBoard()
481
+
482
+ if (vsCPU && currentPlayer === 2) {
483
+ setTimeout(cpuMove, 500)
484
+ }
485
+ }
486
+
487
+ function updateStatus() {
488
+ statusElement.textContent = `${players[currentPlayer].name} ist am Zug`
489
+ }
490
+
491
+ function updateBackground() {
492
+ body.style.setProperty("--active-background-color", players[currentPlayer].color)
493
+ }
494
+
495
+ function getValidMoves(row, col) {
496
+ const moves = []
497
+ const piece = board[row][col]
498
+
499
+ if (!isPlayerPiece(piece, currentPlayer)) return moves
500
+
501
+ const directions = isKing(piece)
502
+ ? [
503
+ [1, 1],
504
+ [1, -1],
505
+ [-1, 1],
506
+ [-1, -1],
507
+ ]
508
+ : currentPlayer === 1
509
+ ? [
510
+ [1, -1],
511
+ [1, 1],
512
+ ]
513
+ : [
514
+ [-1, -1],
515
+ [-1, 1],
516
+ ]
517
+
518
+ directions.forEach(([dr, dc]) => {
519
+ const newRow = row + dr,
520
+ newCol = col + dc
521
+ if (inBounds(newRow, newCol) && isEmpty(newRow, newCol)) {
522
+ moves.push({ row: newRow, col: newCol, capture: false })
523
+ }
524
+
525
+ const captureRow = row + 2 * dr,
526
+ captureCol = col + 2 * dc
527
+ if (inBounds(newRow, newCol) && inBounds(captureRow, captureCol) && isOpponent(board[newRow][newCol], currentPlayer) && isEmpty(captureRow, captureCol)) {
528
+ moves.push({
529
+ row: captureRow,
530
+ col: captureCol,
531
+ capture: true,
532
+ captured: { row: newRow, col: newCol },
533
+ })
534
+ }
535
+ })
536
+
537
+ return moves
538
+ }
539
+
540
+ function getValidMovesForPlayer(row, col, player) {
541
+ const moves = []
542
+ const piece = board[row][col]
543
+
544
+ if (!isPlayerPiece(piece, player)) return moves
545
+
546
+ const directions = isKing(piece)
547
+ ? [
548
+ [1, 1],
549
+ [1, -1],
550
+ [-1, 1],
551
+ [-1, -1],
552
+ ]
553
+ : player === 1
554
+ ? [
555
+ [1, -1],
556
+ [1, 1],
557
+ ]
558
+ : [
559
+ [-1, -1],
560
+ [-1, 1],
561
+ ]
562
+
563
+ directions.forEach(([dr, dc]) => {
564
+ const newRow = row + dr,
565
+ newCol = col + dc
566
+ if (inBounds(newRow, newCol) && isEmpty(newRow, newCol)) {
567
+ moves.push({ row: newRow, col: newCol, capture: false })
568
+ }
569
+
570
+ const captureRow = row + 2 * dr,
571
+ captureCol = col + 2 * dc
572
+ if (inBounds(newRow, newCol) && inBounds(captureRow, captureCol) && isOpponent(board[newRow][newCol], player) && isEmpty(captureRow, captureCol)) {
573
+ moves.push({
574
+ row: captureRow,
575
+ col: captureCol,
576
+ capture: true,
577
+ captured: { row: newRow, col: newCol },
578
+ })
579
+ }
580
+ })
581
+
582
+ return moves
583
+ }
584
+
585
+ function hasAnyMoves(player) {
586
+ for (let row = 0; row < boardSize; row++) {
587
+ for (let col = 0; col < boardSize; col++) {
588
+ if (isPlayerPiece(board[row][col], player) && getValidMovesForPlayer(row, col, player).length > 0) {
589
+ return true
590
+ }
591
+ }
592
+ }
593
+ return false
594
+ }
595
+
596
+ function hasAnyCapture() {
597
+ for (let row = 0; row < boardSize; row++) {
598
+ for (let col = 0; col < boardSize; col++) {
599
+ if (isPlayerPiece(board[row][col], currentPlayer) && getValidMoves(row, col).some((move) => move.capture)) {
600
+ return true
601
+ }
602
+ }
603
+ }
604
+ return false
605
+ }
606
+
607
+ function makeMove(fromRow, fromCol, move) {
608
+ board[move.row][move.col] = board[fromRow][fromCol]
609
+ board[fromRow][fromCol] = 0
610
+
611
+ if (move.capture) {
612
+ const captured = move.captured
613
+ board[captured.row][captured.col] = 0
614
+ }
615
+
616
+ if (currentPlayer === 1 && move.row === boardSize - 1 && board[move.row][move.col] === 1) {
617
+ board[move.row][move.col] = 3
618
+ } else if (currentPlayer === 2 && move.row === 0 && board[move.row][move.col] === 2) {
619
+ board[move.row][move.col] = 4
620
+ }
621
+ }
622
+
623
+ function switchPlayer() {
624
+ currentPlayer = currentPlayer === 1 ? 2 : 1
625
+ selectedPiece = null
626
+ renderBoard()
627
+ validMoves = []
628
+ updateStatus()
629
+ updateBackground()
630
+
631
+ if (hasAnyMoves(currentPlayer)) {
632
+ if (vsCPU && currentPlayer === 2) {
633
+ setTimeout(cpuMove, 500)
634
+ }
635
+ } else {
636
+ endGame(currentPlayer === 1 ? 2 : 1)
637
+ }
638
+ }
639
+
640
+ function cpuMove() {
641
+ let possibleMoves = []
642
+ const mustCapture = hasAnyCapture()
643
+
644
+ for (let row = 0; row < boardSize; row++) {
645
+ for (let col = 0; col < boardSize; col++) {
646
+ if (isPlayerPiece(board[row][col], currentPlayer)) {
647
+ let moves = getValidMoves(row, col)
648
+ if (mustCapture) {
649
+ moves = moves.filter((move) => move.capture)
650
+ }
651
+ if (moves.length > 0) {
652
+ possibleMoves.push({ row, col, moves })
653
+ }
654
+ }
655
+ }
656
+ }
657
+
658
+ if (possibleMoves.length === 0) {
659
+ endGame(currentPlayer === 1 ? 2 : 1)
660
+ return
661
+ }
662
+
663
+ const { row, col, moves } = possibleMoves[Math.floor(Math.random() * possibleMoves.length)]
664
+ const move = moves[Math.floor(Math.random() * moves.length)]
665
+
666
+ setTimeout(() => {
667
+ makeMove(row, col, move)
668
+ renderBoard()
669
+ if (move.capture) {
670
+ cpuCaptureChain(move.row, move.col)
671
+ } else {
672
+ checkWin() || switchPlayer()
673
+ }
674
+ }, 500)
675
+ }
676
+
677
+ function cpuCaptureChain(row, col) {
678
+ let captureMoves = getValidMoves(row, col).filter((move) => move.capture)
679
+ if (captureMoves.length > 0) {
680
+ const move = captureMoves[Math.floor(Math.random() * captureMoves.length)]
681
+ setTimeout(() => {
682
+ makeMove(row, col, move)
683
+ renderBoard()
684
+ cpuCaptureChain(move.row, move.col)
685
+ }, 500)
686
+ } else {
687
+ checkWin() || switchPlayer()
688
+ }
689
+ }
690
+
691
+ function checkWin() {
692
+ let player1Pieces = 0,
693
+ player2Pieces = 0
694
+
695
+ for (let row = 0; row < boardSize; row++) {
696
+ for (let col = 0; col < boardSize; col++) {
697
+ if (board[row][col] === 1 || board[row][col] === 3) {
698
+ player1Pieces++
699
+ } else if (board[row][col] === 2 || board[row][col] === 4) {
700
+ player2Pieces++
701
+ }
702
+ }
703
+ }
704
+
705
+ if (player1Pieces === 0) {
706
+ endGame(2)
707
+ return true
708
+ } else if (player2Pieces === 0) {
709
+ endGame(1)
710
+ return true
711
+ } else if (!hasAnyMoves(currentPlayer === 1 ? 2 : 1)) {
712
+ endGame(currentPlayer)
713
+ return true
714
+ }
715
+
716
+ return false
717
+ }
718
+
719
+ function endGame(winner) {
720
+ gameRunning = false
721
+ newGameButton.style.display = "none"
722
+ winMessageElement.textContent = `Spieler ${winner} hat gewonnen! (Zum Neustart klicken)`
723
+ winMessageElement.style.display = "block"
724
+ winMessageElement.style.backgroundColor = `rgba(${players[winner].color}, 1.0)`
725
+ cpuToggle.disabled = false
726
+ winMessageElement.addEventListener("click", initGame, { once: true })
727
+ }
728
+
729
+ function renderBoard() {
730
+ boardElement.innerHTML = ""
731
+
732
+ for (let row = 0; row < boardSize; row++) {
733
+ for (let col = 0; col < boardSize; col++) {
734
+ const cell = document.createElement("div")
735
+ cell.classList.add("cell")
736
+ cell.classList.add((row + col) % 2 === 0 ? "light" : "dark")
737
+ cell.dataset.row = row
738
+ cell.dataset.col = col
739
+
740
+ if (validMoves.some((move) => move.row === row && move.col === col)) {
741
+ cell.classList.add("highlight")
742
+ }
743
+
744
+ if (selectedPiece && selectedPiece.row === row && selectedPiece.col === col) {
745
+ cell.classList.add("selected")
746
+ }
747
+
748
+ const piece = board[row][col]
749
+ if (piece !== 0) {
750
+ const pieceElement = document.createElement("div")
751
+ pieceElement.classList.add("piece")
752
+ pieceElement.style.setProperty("--player-color", players[piece % 2 === 0 ? 2 : 1].color)
753
+
754
+ if (isKing(piece)) {
755
+ pieceElement.classList.add("king")
756
+ }
757
+
758
+ if (getValidMoves(row, col).some((move) => move.capture)) {
759
+ pieceElement.classList.add("must-capture")
760
+ } else {
761
+ pieceElement.classList.remove("must-capture")
762
+ }
763
+
764
+ cell.appendChild(pieceElement)
765
+ }
766
+
767
+ cell.addEventListener("click", handleCellClick)
768
+ boardElement.appendChild(cell)
769
+ }
770
+ }
771
+ }
772
+
773
+ function handleCellClick(event) {
774
+ if (!gameRunning || (vsCPU && currentPlayer === 2)) return
775
+
776
+ const row = parseInt(event.currentTarget.dataset.row)
777
+ const col = parseInt(event.currentTarget.dataset.col)
778
+
779
+ if (selectedPiece) {
780
+ const move = validMoves.find((move) => move.row === row && move.col === col)
781
+ if (move) {
782
+ makeMove(selectedPiece.row, selectedPiece.col, move)
783
+ renderBoard()
784
+ if (move.capture) {
785
+ const captureMoves = getValidMoves(move.row, move.col).filter((move) => move.capture)
786
+ if (captureMoves.length > 0) {
787
+ selectedPiece = { row: move.row, col: move.col }
788
+ validMoves = captureMoves
789
+ return
790
+ }
791
+ }
792
+ selectedPiece = null
793
+ validMoves = []
794
+ checkWin() || switchPlayer()
795
+ return
796
+ }
797
+ }
798
+
799
+ if (isPlayerPiece(board[row][col], currentPlayer)) {
800
+ if (hasAnyCapture()) {
801
+ const captureMoves = getValidMoves(row, col).filter((move) => move.capture)
802
+ if (captureMoves.length === 0) return
803
+ selectedPiece = { row, col }
804
+ validMoves = captureMoves
805
+ } else {
806
+ selectedPiece = { row, col }
807
+ validMoves = getValidMoves(row, col)
808
+ }
809
+ renderBoard()
810
+ }
811
+ }
812
+
813
+ function openSavePlayerNamesDialog() {
814
+ if (!cpuToggle.checked) {
815
+ inputPlayerName2.value = inputPlayerName2.value === "CPU" ? "Spieler 2" : inputPlayerName2.value
816
+ } else {
817
+ inputPlayerName2.value = "CPU"
818
+ }
819
+ inputPlayerName2.disabled = cpuToggle.checked
820
+ document.getElementById("setPlayerNamesWrapperBackdrop").style.display = "block"
821
+ }
822
+
823
+ savePlayerNamesButton.addEventListener("click", () => {
824
+ players[1].name = inputPlayerName1.value.length > 0 ? inputPlayerName1.value : "Spieler 1"
825
+ players[2].name = inputPlayerName2.value.length > 0 ? inputPlayerName2.value : "Spieler 2"
826
+ document.getElementById("setPlayerNamesWrapperBackdrop").style.display = "none"
827
+ cpuToggle.disabled = false
828
+ initGame()
829
+ })
830
+
831
+ newGameButton.addEventListener("click", openSavePlayerNamesDialog)
832
+ cpuToggle.addEventListener("click", openSavePlayerNamesDialog)
833
+
834
+ initGame()
835
+ </script>
836
  </body>
837
  </html>