LULDev commited on
Commit
08dc4e3
·
verified ·
1 Parent(s): 6ac9ecb

undefined - Initial Deployment

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +606 -19
  3. prompts.txt +0 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Tictactoe
3
- emoji: 🔥
4
- colorFrom: gray
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: tictactoe
3
+ emoji: 🐳
4
+ colorFrom: purple
5
+ colorTo: green
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,606 @@
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>Multiplayer Tic-Tac-Toe</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
9
+ <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <script>
12
+ tailwind.config = {
13
+ theme: {
14
+ extend: {
15
+ colors: {
16
+ primary: '#6366f1',
17
+ secondary: '#818cf8',
18
+ accent: '#a5b4fc',
19
+ dark: '#1e293b',
20
+ light: '#f1f5f9',
21
+ 'board-bg': '#ede9fe'
22
+ },
23
+ fontFamily: {
24
+ sans: ['Nunito', 'sans-serif']
25
+ },
26
+ animation: {
27
+ 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
28
+ 'bounce-slow': 'bounce 2s infinite'
29
+ }
30
+ }
31
+ }
32
+ }
33
+ </script>
34
+ <style>
35
+ @keyframes fadeIn {
36
+ from { opacity: 0; transform: translateY(-10px); }
37
+ to { opacity: 1; transform: translateY(0); }
38
+ }
39
+
40
+ .fade-in {
41
+ animation: fadeIn 0.5s ease-out forwards;
42
+ }
43
+
44
+ .grid-cell:hover {
45
+ transform: scale(1.05);
46
+ transition: transform 0.3s ease;
47
+ }
48
+
49
+ .winning-cell {
50
+ animation: pulse 2s infinite, bounce 1s infinite;
51
+ }
52
+
53
+ #game-container {
54
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15), 0 15px 30px rgba(99, 102, 241, 0.1);
55
+ }
56
+
57
+ .chip-animation {
58
+ position: absolute;
59
+ background-color: rgba(255, 255, 255, 0.6);
60
+ border-radius: 50%;
61
+ animation: expand 1s forwards;
62
+ opacity: 0;
63
+ }
64
+
65
+ @keyframes expand {
66
+ 0% { transform: scale(0.1); opacity: 1; }
67
+ 100% { transform: scale(5); opacity: 0; }
68
+ }
69
+
70
+ .status-banner {
71
+ transition: all 0.3s ease;
72
+ }
73
+
74
+ .confetti {
75
+ position: absolute;
76
+ width: 10px;
77
+ height: 10px;
78
+ opacity: 0.7;
79
+ animation: fall 3s ease-in-out forwards;
80
+ }
81
+
82
+ @keyframes fall {
83
+ 0% { transform: translateY(-10vh) rotate(0deg); opacity: 1; }
84
+ 100% { transform: translateY(100vh) rotate(360deg); opacity: 0; }
85
+ }
86
+ </style>
87
+ </head>
88
+ <body class="bg-gradient-to-br from-indigo-50 to-purple-100 min-h-screen flex flex-col items-center justify-center p-4 font-sans">
89
+ <div id="game-container" class="w-full max-w-2xl bg-white rounded-2xl overflow-hidden fade-in">
90
+ <!-- Game Header -->
91
+ <div class="bg-gradient-to-r from-primary to-secondary text-white py-5 px-6 text-center">
92
+ <h1 class="text-3xl md:text-4xl font-bold flex items-center justify-center gap-2">
93
+ <i class="fas fa-gamepad"></i>
94
+ <span>Multiplayer Tic-Tac-Toe</span>
95
+ </h1>
96
+ <p class="mt-2 opacity-90">Play against friends in real-time!</p>
97
+ </div>
98
+
99
+ <!-- Lobby Section -->
100
+ <div id="lobby" class="p-6">
101
+ <div class="text-center mb-8">
102
+ <i class="fas fa-users text-6xl text-primary mb-4"></i>
103
+ <h2 class="text-2xl font-bold text-gray-800">Join or Create a Game</h2>
104
+ <p class="text-gray-600 mt-2">Share the Game ID with a friend to play together</p>
105
+ </div>
106
+
107
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
108
+ <!-- Create Game -->
109
+ <div class="bg-light rounded-xl p-6 border border-accent">
110
+ <div class="flex items-center gap-3 mb-4">
111
+ <div class="bg-primary rounded-lg p-3">
112
+ <i class="fas fa-plus-circle text-white text-xl"></i>
113
+ </div>
114
+ <h3 class="font-bold text-xl text-gray-800">Create New Game</h3>
115
+ </div>
116
+ <p class="text-gray-700 mb-4">Create a new game and invite a friend to play with you.</p>
117
+ <button id="create-game" class="w-full bg-primary hover:bg-primary/90 text-white py-3 rounded-lg font-semibold transition flex items-center justify-center gap-2">
118
+ <i class="fas fa-chess-board"></i> Create Game
119
+ </button>
120
+ </div>
121
+
122
+ <!-- Join Game -->
123
+ <div class="bg-light rounded-xl p-6 border border-accent">
124
+ <div class="flex items-center gap-3 mb-4">
125
+ <div class="bg-secondary rounded-lg p-3">
126
+ <i class="fas fa-user-plus text-white text-xl"></i>
127
+ </div>
128
+ <h3 class="font-bold text-xl text-gray-800">Join Existing Game</h3>
129
+ </div>
130
+ <div class="space-y-4">
131
+ <div>
132
+ <label class="block text-gray-700 font-medium mb-2" for="game-id">Enter Game ID</label>
133
+ <input type="text" id="game-id" placeholder="Game ID" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent">
134
+ </div>
135
+ <button id="join-game" class="w-full bg-secondary hover:bg-secondary/90 text-white py-3 rounded-lg font-semibold transition flex items-center justify-center gap-2">
136
+ <i class="fas fa-sign-in-alt"></i> Join Game
137
+ </button>
138
+ </div>
139
+ </div>
140
+ </div>
141
+
142
+ <!-- Game ID Display -->
143
+ <div id="game-id-display" class="hidden bg-light rounded-xl p-4 border border-accent">
144
+ <div class="flex flex-col items-center text-center">
145
+ <p class="font-bold text-lg text-gray-800 mb-2">Your Game ID:</p>
146
+ <div class="flex items-center gap-2">
147
+ <p id="game-code" class="font-mono text-2xl font-bold bg-white py-2 px-6 rounded-lg border border-primary text-primary"></p>
148
+ <button id="copy-id" class="bg-accent text-primary p-2 rounded-lg hover:bg-accent/80 transition">
149
+ <i class="fas fa-copy"></i>
150
+ </button>
151
+ </div>
152
+ <p class="text-gray-600 mt-3 flex items-center gap-2">
153
+ <i class="fas fa-info-circle text-primary"></i>
154
+ <span>Share this code with your friend to join the game</span>
155
+ </p>
156
+ </div>
157
+ </div>
158
+
159
+ <!-- Waiting Room -->
160
+ <div id="waiting-room" class="hidden mt-8 bg-board-bg rounded-xl p-8 text-center border border-accent">
161
+ <div class="flex flex-col items-center">
162
+ <div class="relative mb-6">
163
+ <div class="w-24 h-24 rounded-full bg-accent flex items-center justify-center">
164
+ <i class="fas fa-user-clock text-5xl text-primary"></i>
165
+ </div>
166
+ <div class="absolute -top-2 -right-2 w-10 h-10 rounded-full bg-primary text-white flex items-center justify-center animate-bounce-slow">
167
+ <span id="player-count">1</span>
168
+ </div>
169
+ </div>
170
+ <h3 class="text-xl font-bold text-gray-800 mb-3">Waiting for players...</h3>
171
+ <div class="w-full max-w-md bg-white rounded-lg p-4 mx-auto">
172
+ <div class="flex items-center justify-center gap-4 mb-4">
173
+ <div class="bg-primary/10 px-4 py-2 rounded-lg flex items-center gap-2">
174
+ <i class="fas fa-user text-primary"></i>
175
+ <span id="player-name" class="font-semibold">You</span>
176
+ </div>
177
+ <span class="font-bold text-gray-600">vs</span>
178
+ <div class="bg-gray-100 px-4 py-2 rounded-lg flex items-center gap-2">
179
+ <i class="fas fa-user-clock text-gray-500"></i>
180
+ <span class="text-gray-500">Waiting...</span>
181
+ </div>
182
+ </div>
183
+ <div class="w-full bg-gray-200 rounded-full h-2.5">
184
+ <div class="bg-primary h-2.5 rounded-full w-1/3 animate-pulse-slow"></div>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+
191
+ <!-- Game Section -->
192
+ <div id="game-section" class="hidden p-6">
193
+ <div id="game-status" class="status-banner bg-gradient-to-r from-purple-600 to-indigo-700 text-white py-3 px-6 rounded-lg flex items-center justify-between mb-6">
194
+ <div class="flex items-center gap-2">
195
+ <i class="fas fa-info-circle"></i>
196
+ <span id="status-text">Your turn! (X)</span>
197
+ </div>
198
+ <div id="players">
199
+ <span id="player-symbol" class="font-bold">X</span>
200
+ <span class="mx-1">|</span>
201
+ <span id="game-id-label"></span>
202
+ </div>
203
+ </div>
204
+
205
+ <!-- Game Board -->
206
+ <div class="relative bg-board-bg rounded-2xl p-4 overflow-hidden">
207
+ <div id="game-board" class="grid grid-cols-3 gap-4 max-w-lg mx-auto my-4">
208
+ <!-- Cells will be generated dynamically -->
209
+ </div>
210
+
211
+ <!-- Results Overlay -->
212
+ <div id="game-over" class="hidden absolute inset-0 bg-black/80 flex items-center justify-center rounded-2xl">
213
+ <div class="bg-white p-8 rounded-xl text-center">
214
+ <h3 id="result-text" class="text-2xl font-bold mb-4">X Wins!</h3>
215
+ <div class="flex flex-wrap gap-3 justify-center">
216
+ <button id="play-again" class="bg-primary hover:bg-primary/90 text-white py-3 px-6 rounded-lg font-semibold transition">
217
+ <i class="fas fa-redo mr-2"></i> Play Again
218
+ </button>
219
+ <button id="new-game" class="bg-secondary hover:bg-secondary/90 text-white py-3 px-6 rounded-lg font-semibold transition">
220
+ <i class="fas fa-plus mr-2"></i> New Game
221
+ </button>
222
+ </div>
223
+ </div>
224
+ </div>
225
+ </div>
226
+
227
+ <!-- Game Controls -->
228
+ <div class="flex flex-col sm:flex-row gap-4 mt-8">
229
+ <div class="flex gap-2">
230
+ <button id="copy-link" class="bg-light hover:bg-accent text-primary px-4 py-2 rounded-lg transition flex items-center gap-2">
231
+ <i class="fas fa-link"></i> Copy Invite Link
232
+ </button>
233
+ <button id="leave-game" class="bg-light hover:bg-rose-500/10 text-rose-500 px-4 py-2 rounded-lg transition flex items-center gap-2">
234
+ <i class="fas fa-sign-out-alt"></i> Leave Game
235
+ </button>
236
+ </div>
237
+ <div class="ml-auto flex gap-2">
238
+ <div id="player-one" class="bg-light px-4 py-2 rounded-lg flex items-center gap-2">
239
+ <i class="fas fa-user text-primary"></i>
240
+ <span>X: <span id="player-one-name">Player 1</span></span>
241
+ </div>
242
+ <div id="player-two" class="bg-light px-4 py-2 rounded-lg flex items-center gap-2">
243
+ <i class="fas fa-user text-secondary"></i>
244
+ <span>O: <span id="player-two-name">Player 2</span></span>
245
+ </div>
246
+ </div>
247
+ </div>
248
+ </div>
249
+ </div>
250
+
251
+ <!-- Footer -->
252
+ <footer class="mt-8 text-center text-gray-600">
253
+ <p>Created with <i class="fas fa-heart text-red-500"></i> & Socket.io</p>
254
+ </footer>
255
+
256
+ <script>
257
+ // DOM Elements
258
+ const lobbySection = document.getElementById('lobby');
259
+ const gameSection = document.getElementById('game-section');
260
+ const gameBoard = document.getElementById('game-board');
261
+ const waitingRoom = document.getElementById('waiting-room');
262
+ const gameIdDisplay = document.getElementById('game-id-display');
263
+ const gameIdInput = document.getElementById('game-id');
264
+ const gameIdLabel = document.getElementById('game-id-label');
265
+ const gameOver = document.getElementById('game-over');
266
+ const resultText = document.getElementById('result-text');
267
+ const statusText = document.getElementById('status-text');
268
+ const playerSymbol = document.getElementById('player-symbol');
269
+ const playerOneName = document.getElementById('player-one-name');
270
+ const playerTwoName = document.getElementById('player-two-name');
271
+ const playerCount = document.getElementById('player-count');
272
+
273
+ // Game state
274
+ let gameId = null;
275
+ let player = null;
276
+ let isCurrentTurn = false;
277
+ let gameBoardState = Array(9).fill(null);
278
+
279
+ // Initialize Socket.io connection
280
+ const socket = io("https://tic-tac-toe-socketio.adaptable.app/", { // Replace with your Socket.io server URL
281
+ transports: ['websocket']
282
+ });
283
+
284
+ // Event Listeners
285
+ document.getElementById('create-game').addEventListener('click', createGame);
286
+ document.getElementById('join-game').addEventListener('click', joinGame);
287
+ document.getElementById('copy-id').addEventListener('click', copyGameId);
288
+ document.getElementById('play-again').addEventListener('click', restartGame);
289
+ document.getElementById('new-game').addEventListener('click', resetGame);
290
+ document.getElementById('leave-game').addEventListener('click', leaveGame);
291
+ document.getElementById('copy-link').addEventListener('click', copyInviteLink);
292
+
293
+ // Socket.io Event Handlers
294
+ socket.on('connect', () => {
295
+ console.log('Connected to server with socket id:', socket.id);
296
+ });
297
+
298
+ socket.on('gameCreated', (id) => {
299
+ gameId = id;
300
+ document.getElementById('game-code').textContent = id;
301
+ gameIdDisplay.classList.remove('hidden');
302
+ waitingRoom.classList.remove('hidden');
303
+ });
304
+
305
+ socket.on('playerJoined', (players) => {
306
+ playerCount.textContent = players.length;
307
+ if (players.length === 2) {
308
+ // Transition to game screen after a short delay
309
+ setTimeout(() => {
310
+ lobbySection.classList.add('hidden');
311
+ gameSection.classList.remove('hidden');
312
+ waitingRoom.classList.add('hidden');
313
+ }, 1000);
314
+ }
315
+ });
316
+
317
+ socket.on('playerLeft', (players) => {
318
+ playerCount.textContent = players.length;
319
+ });
320
+
321
+ socket.on('gameJoined', (gameData) => {
322
+ gameId = gameData.id;
323
+ player = gameData.players.find(p => p.id === socket.id);
324
+
325
+ // Update player names
326
+ playerOneName.textContent = gameData.players[0].name;
327
+ playerTwoName.textContent = gameData.players[1]?.name || 'Waiting...';
328
+ playerCount.textContent = gameData.players.length;
329
+
330
+ // Set player symbols
331
+ if (player.id === gameData.players[0].id) {
332
+ playerSymbol.textContent = 'X';
333
+ playerSymbol.classList.add('text-primary');
334
+ } else if (player.id === gameData.players[1]?.id) {
335
+ playerSymbol.textContent = 'O';
336
+ playerSymbol.classList.add('text-secondary');
337
+ }
338
+
339
+ // If two players are present, start game
340
+ if (gameData.players.length === 2) {
341
+ lobbySection.classList.add('hidden');
342
+ gameSection.classList.remove('hidden');
343
+ waitingRoom.classList.add('hidden');
344
+ updateBoard(gameData.board);
345
+ updateGameState(gameData);
346
+ } else {
347
+ // Show waiting room
348
+ gameIdDisplay.classList.remove('hidden');
349
+ waitingRoom.classList.remove('hidden');
350
+ document.getElementById('game-code').textContent = gameId;
351
+ }
352
+
353
+ gameIdLabel.textContent = `Game ID: ${gameId}`;
354
+ });
355
+
356
+ socket.on('updateBoard', (board) => {
357
+ updateBoard(board);
358
+ gameBoardState = board;
359
+ });
360
+
361
+ socket.on('updateGameState', (gameData) => {
362
+ updateGameState(gameData);
363
+ });
364
+
365
+ socket.on('gameOver', (result) => {
366
+ showGameResult(result);
367
+ createConfetti();
368
+ });
369
+
370
+ socket.on('error', (message) => {
371
+ showNotification(message);
372
+ });
373
+
374
+ // Game Functions
375
+ function createGame() {
376
+ const playerName = `Player_${Math.floor(Math.random() * 1000)}`;
377
+ socket.emit('createGame', playerName);
378
+ }
379
+
380
+ function joinGame() {
381
+ const id = gameIdInput.value.trim();
382
+ if (!id) {
383
+ showNotification('Please enter a Game ID!');
384
+ return;
385
+ }
386
+
387
+ const playerName = `Player_${Math.floor(Math.random() * 1000)}`;
388
+ socket.emit('joinGame', { gameId: id, playerName });
389
+ }
390
+
391
+ function cellClick(index) {
392
+ if (isCurrentTurn && !gameBoardState[index]) {
393
+ const chipAnimation = document.createElement('div');
394
+ chipAnimation.className = 'chip-animation';
395
+ const cell = document.getElementById(`cell-${index}`);
396
+ cell.appendChild(chipAnimation);
397
+
398
+ setTimeout(() => {
399
+ socket.emit('makeMove', {
400
+ gameId,
401
+ index,
402
+ symbol: player.symbol
403
+ });
404
+ }, 300);
405
+ }
406
+ }
407
+
408
+ function updateBoard(board) {
409
+ gameBoardState = [...board];
410
+ gameBoard.innerHTML = '';
411
+
412
+ for (let i = 0; i < 9; i++) {
413
+ const cell = document.createElement('div');
414
+ cell.id = `cell-${i}`;
415
+ cell.className = 'grid-cell aspect-square bg-white rounded-xl border-2 border-accent shadow-md flex items-center justify-center cursor-pointer hover:shadow-lg transition-all';
416
+ cell.addEventListener('click', () => cellClick(i));
417
+
418
+ if (board[i]) {
419
+ const symbol = document.createElement('div');
420
+ symbol.className = 'text-4xl font-bold';
421
+
422
+ if (board[i] === 'X') {
423
+ symbol.textContent = 'X';
424
+ symbol.classList.add('text-primary');
425
+ } else {
426
+ symbol.textContent = 'O';
427
+ symbol.classList.add('text-secondary');
428
+ }
429
+
430
+ cell.appendChild(symbol);
431
+ }
432
+
433
+ gameBoard.appendChild(cell);
434
+ }
435
+ }
436
+
437
+ function updateGameState(gameData) {
438
+ isCurrentTurn = gameData.currentPlayerId === socket.id;
439
+ player = gameData.players.find(p => p.id === socket.id);
440
+
441
+ // Update status
442
+ if (gameData.winner) {
443
+ if (gameData.winner === 'draw') {
444
+ statusText.textContent = "It's a draw!";
445
+ } else if (gameData.winner === player.symbol) {
446
+ statusText.textContent = "You won!";
447
+ } else {
448
+ statusText.textContent = "You lost!";
449
+ }
450
+ } else {
451
+ if (isCurrentTurn) {
452
+ statusText.textContent = `Your turn! (${player.symbol})`;
453
+ document.getElementById('game-status').classList.remove('bg-gradient-to-r', 'from-purple-600', 'to-indigo-700');
454
+ document.getElementById('game-status').classList.add('bg-gradient-to-r', 'from-blue-600', 'to-indigo-700');
455
+ } else {
456
+ statusText.textContent = `Waiting for opponent...`;
457
+ document.getElementById('game-status').classList.remove('bg-gradient-to-r', 'from-blue-600', 'to-indigo-700');
458
+ document.getElementById('game-status').classList.add('bg-gradient-to-r', 'from-purple-600', 'to-indigo-700');
459
+ }
460
+ }
461
+
462
+ // Mark winning cells if any
463
+ if (gameData.winningCombo) {
464
+ gameData.winningCombo.forEach(index => {
465
+ const cell = document.getElementById(`cell-${index}`);
466
+ cell.classList.add('winning-cell');
467
+ });
468
+ }
469
+ }
470
+
471
+ function showGameResult(result) {
472
+ gameOver.classList.remove('hidden');
473
+
474
+ if (result.winner === 'draw') {
475
+ resultText.textContent = "Game ended in a draw!";
476
+ resultText.className = "text-2xl font-bold text-gray-800";
477
+ } else {
478
+ resultText.textContent = `${result.winner} wins the game!`;
479
+ resultText.className = `text-2xl font-bold ${result.winner === 'X' ? 'text-primary' : 'text-secondary'}`;
480
+ }
481
+ }
482
+
483
+ function restartGame() {
484
+ socket.emit('restartGame', gameId);
485
+ gameOver.classList.add('hidden');
486
+
487
+ // Remove winning cell classes
488
+ const cells = document.querySelectorAll('.grid-cell');
489
+ cells.forEach(cell => cell.classList.remove('winning-cell'));
490
+ }
491
+
492
+ function resetGame() {
493
+ // Reset UI
494
+ lobbySection.classList.remove('hidden');
495
+ gameSection.classList.add('hidden');
496
+ gameOver.classList.add('hidden');
497
+ gameIdDisplay.classList.add('hidden');
498
+ waitingRoom.classList.add('hidden');
499
+
500
+ // Reset game data
501
+ gameId = null;
502
+ player = null;
503
+ isCurrentTurn = false;
504
+ gameBoardState = Array(9).fill(null);
505
+
506
+ // Clean up
507
+ document.getElementById('game-id').value = '';
508
+ gameBoard.innerHTML = '';
509
+
510
+ // Leave current game
511
+ socket.emit('leaveGame', gameId);
512
+ }
513
+
514
+ function leaveGame() {
515
+ socket.emit('leaveGame', gameId);
516
+ resetGame();
517
+ }
518
+
519
+ function copyGameId() {
520
+ navigator.clipboard.writeText(gameId)
521
+ .then(() => showNotification('Game ID copied to clipboard!'))
522
+ .catch(err => showNotification('Failed to copy: ' + err));
523
+ }
524
+
525
+ function copyInviteLink() {
526
+ const link = `${window.location.origin}/?game=${gameId}`;
527
+ navigator.clipboard.writeText(link)
528
+ .then(() => showNotification('Invite link copied to clipboard!'))
529
+ .catch(err => showNotification('Failed to copy: ' + err));
530
+ }
531
+
532
+ function showNotification(message) {
533
+ // Create notification element
534
+ const notification = document.createElement('div');
535
+ notification.className = 'fixed bottom-5 right-5 bg-dark text-white px-4 py-3 rounded-lg shadow-lg transform transition-all duration-300';
536
+ notification.innerHTML = `
537
+ <div class="flex items-center gap-2">
538
+ <i class="fas fa-info-circle"></i>
539
+ <span>${message}</span>
540
+ </div>
541
+ `;
542
+
543
+ document.body.appendChild(notification);
544
+
545
+ // Remove after delay
546
+ setTimeout(() => {
547
+ notification.style.transform = 'translateX(100%)';
548
+ setTimeout(() => {
549
+ document.body.removeChild(notification);
550
+ }, 300);
551
+ }, 3000);
552
+ }
553
+
554
+ function createConfetti() {
555
+ const colors = ['#ef4444', '#f59e0b', '#10b981', '#3b82f6', '#8b5cf6', '#ec4899'];
556
+ const gameBoardRect = gameBoard.getBoundingClientRect();
557
+
558
+ for (let i = 0; i < 150; i++) {
559
+ const confetti = document.createElement('div');
560
+ const colorIndex = Math.floor(Math.random() * colors.length);
561
+
562
+ confetti.style.backgroundColor = colors[colorIndex];
563
+ confetti.className = 'confetti';
564
+ confetti.style.left = Math.random() * gameBoardRect.width + 'px';
565
+ confetti.style.top = Math.random() * gameBoardRect.height + 'px';
566
+ confetti.style.animationDuration = (Math.random() * 3 + 2) + 's';
567
+ confetti.style.opacity = Math.random();
568
+ confetti.style.width = Math.random() * 10 + 5 + 'px';
569
+ confetti.style.height = confetti.style.width;
570
+
571
+ gameBoard.appendChild(confetti);
572
+
573
+ setTimeout(() => {
574
+ confetti.remove();
575
+ }, 4000);
576
+ }
577
+ }
578
+
579
+ // Create board when page loads
580
+ function initializeBoard() {
581
+ for (let i = 0; i < 9; i++) {
582
+ const cell = document.createElement('div');
583
+ cell.id = `cell-${i}`;
584
+ cell.className = 'grid-cell aspect-square bg-white rounded-xl border-2 border-accent shadow-md flex items-center justify-center cursor-pointer hover:shadow-lg transition-all';
585
+ cell.addEventListener('click', () => cellClick(i));
586
+ gameBoard.appendChild(cell);
587
+ }
588
+ }
589
+
590
+ initializeBoard();
591
+
592
+ // Check for game ID in URL parameters
593
+ function checkUrlParams() {
594
+ const params = new URLSearchParams(window.location.search);
595
+ if (params.has('game')) {
596
+ const gameId = params.get('game');
597
+ gameIdInput.value = gameId;
598
+ // Auto-fill game ID field but don't join automatically
599
+ showNotification("Game ID detected! Click Join Game to continue.");
600
+ }
601
+ }
602
+
603
+ checkUrlParams();
604
+ </script>
605
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=LULDev/tictactoe" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
606
+ </html>
prompts.txt ADDED
File without changes