npm-noxyai 1.0.10 → 1.0.12

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/index-noxyai.js CHANGED
@@ -9,18 +9,23 @@ const readline = require('readline');
9
9
  const BASE_URL = 'https://www.noxyai.com';
10
10
  const CONFIG_FILE = path.join(os.homedir(), '.noxyai.json');
11
11
 
12
- const GOOGLE_KEY = "AIzaSyAXoZgwIaEnXfO3JuKIvR8GzhydqRKPh20";
13
- const GOOGLE_CX = "33d4204810fae4852";
14
-
15
12
  const args = process.argv.slice(2);
16
13
  const command = args[0];
17
14
 
18
15
  // --- CONFIG MANAGEMENT ---
19
16
  function loadConfig() {
20
17
  if (fs.existsSync(CONFIG_FILE)) {
21
- try { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); } catch(e){}
18
+ try {
19
+ const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
20
+ if (config.agentMode === undefined) config.agentMode = true;
21
+ return config;
22
+ } catch(e) {}
22
23
  }
23
- return { token: null, model: 'auto' };
24
+ return {
25
+ token: null,
26
+ model: 'auto',
27
+ agentMode: true
28
+ };
24
29
  }
25
30
 
26
31
  function saveConfig(config) {
@@ -43,7 +48,7 @@ let spinnerInterval;
43
48
  function startSpinner(text) {
44
49
  const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
45
50
  let i = 0;
46
- process.stdout.write('\x1b[?25l'); // Hide cursor
51
+ process.stdout.write('\x1b[?25l');
47
52
  spinnerInterval = setInterval(() => {
48
53
  process.stdout.write(`\r\x1b[36m${frames[i]} ${text}\x1b[0m`);
49
54
  i = (i + 1) % frames.length;
@@ -52,7 +57,7 @@ function startSpinner(text) {
52
57
 
53
58
  function stopSpinner() {
54
59
  clearInterval(spinnerInterval);
55
- process.stdout.write('\r\x1b[K\x1b[?25h'); // Clear line, show cursor
60
+ process.stdout.write('\r\x1b[K\x1b[?25h');
56
61
  }
57
62
 
58
63
  function logout() {
@@ -70,6 +75,20 @@ function openBrowser(url) {
70
75
  else spawn('xdg-open', [url], { stdio: 'ignore' });
71
76
  }
72
77
 
78
+ // --- SEARCH FUNCTION ---
79
+ async function searchWeb(query) {
80
+ try {
81
+ const config = loadConfig();
82
+ const res = await fetch(`${BASE_URL}/api/io?action=search&q=${encodeURIComponent(query)}`, {
83
+ headers: { 'Authorization': 'Bearer ' + config.token }
84
+ });
85
+ const data = await res.json();
86
+ return data;
87
+ } catch (err) {
88
+ return { error: err.message };
89
+ }
90
+ }
91
+
73
92
  // --- CORE FUNCTIONS ---
74
93
  async function login() {
75
94
  printLogo();
@@ -132,7 +151,7 @@ function runTerminalCommand(cmd) {
132
151
  const child = spawn(cmd, { shell: true, stdio: 'inherit' });
133
152
 
134
153
  if (isServer) {
135
- console.log(`\x1b[36m[i] Server detected. Running in foreground. Press Ctrl+C to stop.\x1b[0m`);
154
+ console.log(`\n\x1b[36m[i] Server detected. Running in foreground. Press Ctrl+C to stop.\x1b[0m`);
136
155
  setTimeout(() => resolve(), 2500);
137
156
  }
138
157
 
@@ -166,38 +185,72 @@ async function chat(prompt, depth = 0) {
166
185
  const res = await fetch(BASE_URL + '/api/io', {
167
186
  method: 'POST',
168
187
  headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + config.token },
169
- body: JSON.stringify({ prompt: enhancedPrompt, model: config.model })
188
+ body: JSON.stringify({
189
+ prompt: enhancedPrompt,
190
+ model: config.model,
191
+ agentMode: config.agentMode
192
+ })
170
193
  });
171
194
 
172
195
  stopSpinner();
173
196
 
174
- if (!res.ok) return console.error('\n❌ API Error: ' + await res.text());
197
+ if (!res.ok) {
198
+ const errorText = await res.text();
199
+ if (res.status === 402) {
200
+ console.log('\n\x1b[31m' + errorText + '\x1b[0m');
201
+ return;
202
+ }
203
+ return console.error('\n❌ API Error: ' + errorText);
204
+ }
175
205
 
176
- console.log(`\n🤖 \x1b[36mNoxyAI (${config.model}):\x1b[0m\n`);
206
+ const modelDisplay = config.model === 'auto' ? 'Mamba-Codestral 7B' : config.model;
207
+ const agentStatus = config.agentMode ? '🤖 Agent' : '💬 Chat';
208
+ console.log(`\n${agentStatus} \x1b[36mNoxyAI (${modelDisplay}):\x1b[0m\n`);
177
209
 
178
210
  const reader = res.body.getReader();
179
211
  const decoder = new TextDecoder('utf-8');
180
212
  let fullResponse = "";
213
+ let usage = null;
214
+ let searchSources = [];
181
215
 
182
216
  while (true) {
183
217
  const { done, value } = await reader.read();
184
218
  if (done) break;
219
+
185
220
  const lines = decoder.decode(value, { stream: true }).split('\n');
186
221
  for (const line of lines) {
187
222
  if (line.startsWith('data: ')) {
188
223
  const data = line.slice(6).trim();
189
224
  if (data === '[DONE]') break;
225
+
190
226
  try {
191
227
  const parsed = JSON.parse(data);
228
+
229
+ // Reasoning in GREEN
230
+ if (parsed.reasoning) {
231
+ process.stdout.write('\x1b[32m' + parsed.reasoning + '\x1b[0m');
232
+ }
233
+
234
+ // Normal response
192
235
  if (parsed.text) {
193
236
  fullResponse += parsed.text;
194
237
  process.stdout.write(parsed.text);
195
238
  }
239
+
240
+ if (parsed.usage) {
241
+ usage = parsed.usage;
242
+ }
196
243
  } catch (e) {}
197
244
  }
198
245
  }
199
246
  }
200
247
 
248
+ // Only process agent actions if agent mode is ON
249
+ if (!config.agentMode) {
250
+ console.log('\n');
251
+ return;
252
+ }
253
+
201
254
  console.log('\n\n\x1b[32m[Agent] Processing actions...\x1b[0m');
202
255
  let agentFeedback = "";
203
256
 
@@ -216,16 +269,31 @@ async function chat(prompt, depth = 0) {
216
269
  }
217
270
  }
218
271
 
219
- // Tool: Search Web
272
+ // Tool: Search Web with sources
220
273
  const searchRegex = /<search>([\s\S]*?)<\/search>/g;
221
274
  while ((match = searchRegex.exec(fullResponse)) !== null) {
222
275
  const query = match[1].trim();
223
276
  console.log(`\x1b[35m🔍 Searching Web:\x1b[0m ${query}`);
224
277
  try {
225
- const searchRes = await fetch(`https://www.googleapis.com/customsearch/v1?key=${GOOGLE_KEY}&cx=${GOOGLE_CX}&q=${encodeURIComponent(query)}`);
226
- const searchData = await searchRes.json();
227
- const snippets = searchData.items ? searchData.items.map(i => `- ${i.title}: ${i.snippet}`).join('\n') : "No results.";
228
- agentFeedback += `\n[SEARCH RESULTS FOR "${query}"]\n${snippets}\n`;
278
+ const searchData = await searchWeb(query);
279
+ if (searchData.items) {
280
+ searchSources = searchData.items.slice(0, 5).map(i => ({
281
+ title: i.title,
282
+ link: i.link,
283
+ snippet: i.snippet
284
+ }));
285
+
286
+ console.log(`\x1b[35m📚 Sources found:\x1b[0m`);
287
+ searchSources.forEach((s, i) => {
288
+ console.log(` \x1b[36m${i+1}. ${s.title}\x1b[0m`);
289
+ console.log(` \x1b[90m${s.link}\x1b[0m`);
290
+ });
291
+
292
+ const snippets = searchData.items.map(i => `- ${i.title}: ${i.snippet}\n Source: ${i.link}`).join('\n');
293
+ agentFeedback += `\n[SEARCH RESULTS FOR "${query}"]\n${snippets}\n`;
294
+ } else {
295
+ agentFeedback += `\n[SEARCH RESULTS FOR "${query}"]\nNo results found.\n`;
296
+ }
229
297
  } catch (err) {
230
298
  agentFeedback += `\n[SEARCH FAILED: ${err.message}]\n`;
231
299
  }
@@ -256,7 +324,7 @@ async function chat(prompt, depth = 0) {
256
324
  }
257
325
 
258
326
  if (agentFeedback) {
259
- console.log(`\x1b[33m🔄 Sending data back to Agent...\x1b[0m`);
327
+ console.log(`\n\x1b[33m🔄 Sending data back to Agent...\x1b[0m`);
260
328
  await chat(`Here are the results of your actions:\n${agentFeedback}\nWhat is the next step? Output <file> or <execute> if ready, or <read>/<search> if you need more info.`, depth + 1);
261
329
  return;
262
330
  }
@@ -275,42 +343,66 @@ function startInteractiveMode() {
275
343
  const config = loadConfig();
276
344
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
277
345
  printLogo();
346
+
347
+ const agentStatus = config.agentMode ? '\x1b[32mON\x1b[0m' : '\x1b[31mOFF\x1b[0m';
348
+
278
349
  console.log(`\x1b[33mWelcome to NoxyAI Interactive Mode!\x1b[0m`);
279
350
  console.log(`Current Model: \x1b[32m${config.model}\x1b[0m`);
280
- console.log(`Commands: \x1b[36m/model\x1b[0m (Change Model), \x1b[36m/clear\x1b[0m, \x1b[36m/exit\x1b[0m\n`);
351
+ console.log(`Agent Mode: ${agentStatus}`);
352
+ console.log(`\nCommands:`);
353
+ console.log(` \x1b[36m/agent\x1b[0m - Toggle Agent Mode (3-model collaboration)`);
354
+ console.log(` \x1b[36m/model\x1b[0m - Change AI Model`);
355
+ console.log(` \x1b[36m/clear\x1b[0m - Clear screen`);
356
+ console.log(` \x1b[36m/exit\x1b[0m - Exit\n`);
281
357
 
282
358
  function ask() {
283
- rl.question('\x1b[36mNoxyAI > \x1b[0m', async (input) => {
359
+ const prompt = config.agentMode ? '\x1b[36mNoxyAI [Agent] > \x1b[0m' : '\x1b[36mNoxyAI [Chat] > \x1b[0m';
360
+ rl.question(prompt, async (input) => {
284
361
  const trimmed = input.trim();
285
362
  const lower = trimmed.toLowerCase();
286
363
 
287
364
  if (lower === 'exit' || lower === '/exit') {
365
+ console.log('\n\x1b[36mGoodbye! 👋\x1b[0m\n');
288
366
  process.exit(0);
289
367
  }
290
368
  else if (lower === '/clear') {
291
369
  console.clear();
292
370
  printLogo();
293
371
  ask();
294
- }
372
+ }
373
+ else if (lower === '/agent' || lower === '/agent on' || lower === '/agent off') {
374
+ config.agentMode = !config.agentMode;
375
+ saveConfig(config);
376
+ const status = config.agentMode ? '\x1b[32mON\x1b[0m' : '\x1b[31mOFF\x1b[0m';
377
+ console.log(`\n\x1b[33m🤖 Agent Mode: ${status}\x1b[0m`);
378
+ if (config.agentMode) {
379
+ console.log('\x1b[36mAgent mode uses 3 models working together:\x1b[0m');
380
+ console.log(' • Mamba-Codestral 7B (Fast Coding)');
381
+ console.log(' • Qwen3 80B (Deep Reasoning)');
382
+ console.log(' • GLM-4 9B (General Purpose)\n');
383
+ }
384
+ ask();
385
+ }
295
386
  else if (lower === '/model') {
296
387
  console.log('\n\x1b[33mSelect an AI Model:\x1b[0m');
297
- console.log(' \x1b[36m1)\x1b[0m Auto (Llama 3.3 70B - Fast/Coding)');
298
- console.log(' \x1b[36m2)\x1b[0m Qwen3 Next 80B Thinking (Deep Reasoning)');
299
- console.log(' \x1b[36m3)\x1b[0m GLM 4.7');
388
+ console.log(' \x1b[36m1)\x1b[0m Auto (Mamba-Codestral 7B - Fast/Coding)');
389
+ console.log(' \x1b[36m2)\x1b[0m Qwen3 Next 80B Thinking \x1b[32m[Reasoning in Green]\x1b[0m');
390
+ console.log(' \x1b[36m3)\x1b[0m Mistral Mamba-Codestral 7B');
391
+ console.log(' \x1b[36m4)\x1b[0m GLM-4 9B Chat');
300
392
 
301
- rl.question('\nEnter number (1-3): ', (choice) => {
393
+ rl.question('\nEnter number (1-4): ', (choice) => {
302
394
  let selected = 'auto';
303
395
  if (choice === '2') selected = 'Qwen3';
304
- if (choice === '3') selected = 'GLM';
396
+ if (choice === '3') selected = 'Mamba-Codestral';
397
+ if (choice === '4') selected = 'GLM-4';
305
398
 
306
- const currentConfig = loadConfig();
307
- currentConfig.model = selected;
308
- saveConfig(currentConfig);
399
+ config.model = selected;
400
+ saveConfig(config);
309
401
 
310
- console.log(`\n\x1b[32m✔ Model successfully changed to: ${selected}\x1b[0m\n`);
402
+ console.log(`\n\x1b[32m✔ Model changed to: ${selected}\x1b[0m\n`);
311
403
  ask();
312
404
  });
313
- return; // Pause the main loop while waiting for model choice
405
+ return;
314
406
  }
315
407
  else if (trimmed) {
316
408
  await chat(trimmed);
@@ -323,12 +415,22 @@ function startInteractiveMode() {
323
415
  ask();
324
416
  }
325
417
 
418
+ // Command handling
326
419
  if (command === 'login') login();
327
420
  else if (command === 'logout') logout();
328
421
  else if (command === 'help' || command === '--help') {
329
422
  printLogo();
330
- console.log(`\n \x1b[32mnoxyai\x1b[0m Start Interactive Mode\n \x1b[32mnoxyai chat "<prompt>"\x1b[0m Run single prompt\n`);
423
+ console.log(`\n \x1b[32mnoxyai\x1b[0m Start Interactive Mode`);
424
+ console.log(` \x1b[32mnoxyai chat "<prompt>"\x1b[0m Run single prompt`);
425
+ console.log(`\n Interactive Commands:`);
426
+ console.log(` \x1b[36m/agent\x1b[0m Toggle Agent Mode (3-model collaboration)`);
427
+ console.log(` \x1b[36m/model\x1b[0m Change AI Model\n`);
428
+ }
429
+ else if (command === 'chat') {
430
+ chat(args.slice(1).join(' ')).then(() => process.exit(0));
331
431
  }
332
- else if (command === 'chat') { chat(args.slice(1).join(' ')).then(() => process.exit(0)); }
333
432
  else if (!command) startInteractiveMode();
334
- else { console.error(`❌ Unknown command. Run "noxyai help"`); process.exit(1); }
433
+ else {
434
+ console.error(`❌ Unknown command. Run "noxyai help"`);
435
+ process.exit(1);
436
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "npm-noxyai",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "CLI for NoxyAI",
5
5
  "main": "index-noxyai.js",
6
6
  "bin": {
@@ -15,6 +15,7 @@
15
15
  "keywords": [],
16
16
  "type": "commonjs",
17
17
  "dependencies": {
18
- "express": "^5.2.1"
18
+ "express": "^5.2.1",
19
+ "http": "^0.0.1-security"
19
20
  }
20
21
  }
package/index.html DELETED
@@ -1,27 +0,0 @@
1
- <html>
2
- <head>
3
- <title>Tic Tac Toe</title>
4
- <link rel="stylesheet" href="style.css">
5
- </head>
6
- <body>
7
- <h1>Tic Tac Toe</h1>
8
- <div class="game-board">
9
- <div class="row">
10
- <div class="cell" id="cell-0"></div>
11
- <div class="cell" id="cell-1"></div>
12
- <div class="cell" id="cell-2"></div>
13
- </div>
14
- <div class="row">
15
- <div class="cell" id="cell-3"></div>
16
- <div class="cell" id="cell-4"></div>
17
- <div class="cell" id="cell-5"></div>
18
- </div>
19
- <div class="row">
20
- <div class="cell" id="cell-6"></div>
21
- <div class="cell" id="cell-7"></div>
22
- <div class="cell" id="cell-8"></div>
23
- </div>
24
- </div>
25
- <script src="script.js"></script>
26
- </body>
27
- </html>
package/reinstall_pip.py DELETED
@@ -1 +0,0 @@
1
- import pip; pip.uninstall('pip'); import os; os.system('python -m ensurepip')
package/script.js DELETED
@@ -1,38 +0,0 @@
1
- let currentPlayer = "X";
2
- let gameBoard = ["", "", "", "", "", "", "", "", ""];
3
-
4
- function clickCell(cellId) {
5
- if (gameBoard[cellId] === "") {
6
- gameBoard[cellId] = currentPlayer;
7
- document.getElementById(`cell-${cellId}`).innerText = currentPlayer;
8
- checkWin();
9
- currentPlayer = currentPlayer === "X" ? "O" : "X";
10
- }
11
- }
12
-
13
- function checkWin() {
14
- const winConditions = [
15
- [0, 1, 2],
16
- [3, 4, 5],
17
- [6, 7, 8],
18
- [0, 3, 6],
19
- [1, 4, 7],
20
- [2, 5, 8],
21
- [0, 4, 8],
22
- [2, 4, 6]
23
- ];
24
-
25
- for (let i = 0; i < winConditions.length; i++) {
26
- const [a, b, c] = winConditions[i];
27
- if (gameBoard[a] !== "" && gameBoard[a] === gameBoard[b] && gameBoard[b] === gameBoard[c]) {
28
- alert(`Player ${gameBoard[a]} wins!`);
29
- return;
30
- }
31
- }
32
- }
33
-
34
- document.addEventListener("DOMContentLoaded", () => {
35
- for (let i = 0; i < 9; i++) {
36
- document.getElementById(`cell-${i}`).addEventListener("click", () => clickCell(i));
37
- }
38
- });
package/server.js DELETED
@@ -1,11 +0,0 @@
1
- const express = require('express');
2
- const app = express();
3
- const port = 3000;
4
-
5
- app.get('/', (req, res) => {
6
- res.send('Hello World!');
7
- });
8
-
9
- app.listen(port, () => {
10
- console.log(`Server running on port ${port}`);
11
- });
package/snake_game.py DELETED
@@ -1,90 +0,0 @@
1
- import pygame
2
- import sys
3
- import time
4
- import random
5
-
6
- # Direction Constants
7
- UP = 1
8
- RIGHT = 2
9
- DOWN = 3
10
- LEFT = 4
11
-
12
- class SnakeGame:
13
- def __init__(self, width=800, height=600):
14
- self.width = width
15
- self.height = height
16
- self.snake = [(200, 200), (220, 200), (240, 200)]
17
- self.direction = RIGHT
18
- self.apple = self.set_new_apple()
19
- self.score = 0
20
- pygame.init()
21
- self.display = pygame.display.set_mode((width, height))
22
- self.font = pygame.font.Font(None, 36)
23
-
24
- def set_new_apple(self):
25
- while True:
26
- x = random.randint(0, self.width - 20) // 20 * 20
27
- y = random.randint(0, self.height - 20) // 20 * 20
28
- apple = (x, y)
29
- if apple not in self.snake:
30
- return apple
31
-
32
- def play(self):
33
- clock = pygame.time.Clock()
34
- while True:
35
- for event in pygame.event.get():
36
- if event.type == pygame.QUIT:
37
- pygame.quit()
38
- sys.exit()
39
- elif event.type == pygame.KEYDOWN:
40
- if event.key == pygame.K_UP and self.direction != DOWN:
41
- self.direction = UP
42
- elif event.key == pygame.K_DOWN and self.direction != UP:
43
- self.direction = DOWN
44
- elif event.key == pygame.K_LEFT and self.direction != RIGHT:
45
- self.direction = LEFT
46
- elif event.key == pygame.K_RIGHT and self.direction != LEFT:
47
- self.direction = RIGHT
48
-
49
- head = self.snake[-1]
50
- if self.direction == UP:
51
- new_head = (head[0], head[1] - 20)
52
- elif self.direction == DOWN:
53
- new_head = (head[0], head[1] + 20)
54
- elif self.direction == LEFT:
55
- new_head = (head[0] - 20, head[1])
56
- elif self.direction == RIGHT:
57
- new_head = (head[0] + 20, head[1])
58
-
59
- self.snake.append(new_head)
60
- if self.apple == new_head:
61
- self.apple = self.set_new_apple()
62
- self.score += 1
63
- else:
64
- self.snake.pop(0)
65
-
66
- if (new_head[0] < 0 or new_head[0] >= self.width or
67
- new_head[1] < 0 or new_head[1] >= self.height or
68
- new_head in self.snake[:-1]):
69
- break
70
-
71
- self.display.fill((0, 0, 0))
72
- for pos in self.snake:
73
- pygame.draw.rect(self.display, (0, 255, 0), (pos[0], pos[1], 20, 20))
74
- pygame.draw.rect(self.display, (255, 0, 0), (self.apple[0], self.apple[1], 20, 20))
75
- text = self.font.render(f'Score: {self.score}', True, (255, 255, 255))
76
- self.display.blit(text, (10, 10))
77
- pygame.display.flip()
78
- clock.tick(10)
79
-
80
- time.sleep(1)
81
- self.display.fill((0, 0, 0))
82
- text = self.font.render('Game Over', True, (255, 255, 255))
83
- self.display.blit(text, (self.width // 2 - 50, self.height // 2 - 18))
84
- pygame.display.flip()
85
- time.sleep(2)
86
- pygame.quit()
87
-
88
- if __name__ == '__main__':
89
- game = SnakeGame()
90
- game.play()
package/style.css DELETED
@@ -1,11 +0,0 @@
1
- body {
2
- display: flex;
3
- justify-content: center;
4
- align-items: center;
5
- height: 100vh;
6
- background-color: #f0f0f0;
7
- }
8
-
9
- #gameCanvas {
10
- border: 1px solid black;
11
- }
package/tic_tac_toe.py DELETED
@@ -1,111 +0,0 @@
1
- import random
2
-
3
- class TicTacToe:
4
- def __init__(self):
5
- self.board = [' ' for _ in range(9)]
6
-
7
- def print_board(self):
8
- row1 = '| {} | {} | {} |'.format(self.board[0], self.board[1], self.board[2])
9
- row2 = '| {} | {} | {} |'.format(self.board[3], self.board[4], self.board[5])
10
- row3 = '| {} | {} | {} |'.format(self.board[6], self.board[7], self.board[8])
11
-
12
- print()
13
- print(row1)
14
- print(row2)
15
- print(row3)
16
- print()
17
-
18
- def available_moves(self):
19
- return [i for i, spot in enumerate(self.board) if spot == ' ']
20
-
21
- def empty_cells(self):
22
- return ' ' in self.board
23
-
24
- def num_empty_cells(self):
25
- return self.board.count(' ')
26
-
27
- def make_move(self, letter, move):
28
- self.board[move] = letter
29
-
30
- def winner(self):
31
- winning_combos = [(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)]
32
- for combo in winning_combos:
33
- if self.board[combo[0]] == self.board[combo[1]] == self.board[combo[2]] != ' ':
34
- return self.board[combo[0]]
35
- if ' ' not in self.board:
36
- return 'Tie'
37
- return False
38
-
39
- def minimax(board, depth, is_maximizing):
40
- result = board.winner()
41
- if result:
42
- if result == 'X':
43
- return -10 + depth
44
- elif result == 'O':
45
- return 10 - depth
46
- elif result == 'Tie':
47
- return 0
48
-
49
- if is_maximizing:
50
- best_score = float('-inf')
51
- for move in board.available_moves():
52
- board.make_move('O', move)
53
- score = minimax(board, depth + 1, False)
54
- board.board[move] = ' '
55
- best_score = max(score, best_score)
56
- return best_score
57
- else:
58
- best_score = float('inf')
59
- for move in board.available_moves():
60
- board.make_move('X', move)
61
- score = minimax(board, depth + 1, True)
62
- board.board[move] = ' '
63
- best_score = min(score, best_score)
64
- return best_score
65
-
66
- def ai_move(board):
67
- best_score = float('-inf')
68
- best_move = 0
69
- for move in board.available_moves():
70
- board.make_move('O', move)
71
- score = minimax(board, 0, False)
72
- board.board[move] = ' '
73
- if score > best_score:
74
- best_score = score
75
- best_move = move
76
- return best_move
77
-
78
- def main():
79
- board = TicTacToe()
80
- while True:
81
- board.print_board()
82
- move = input("Enter your move (1-9): ")
83
- if board.board[int(move) - 1] != ' ':
84
- print("Invalid move, try again.")
85
- continue
86
- board.make_move('X', int(move) - 1)
87
- result = board.winner()
88
- if result:
89
- board.print_board()
90
- if result == 'X':
91
- print("You win!")
92
- elif result == 'O':
93
- print("AI wins!")
94
- else:
95
- print("It's a tie!")
96
- break
97
- move = ai_move(board)
98
- board.make_move('O', move)
99
- result = board.winner()
100
- if result:
101
- board.print_board()
102
- if result == 'X':
103
- print("You win!")
104
- elif result == 'O':
105
- print("AI wins!")
106
- else:
107
- print("It's a tie!")
108
- break
109
-
110
- if __name__ == '__main__':
111
- main()
@@ -1,46 +0,0 @@
1
- import tkinter as tk
2
- from tkinter import messagebox
3
-
4
- class TicTacToe:
5
- def __init__(self):
6
- self.window = tk.Tk()
7
- self.window.title("Tic Tac Toe")
8
- self.window.geometry("300x300")
9
- self.player_turn = "X"
10
-
11
- self.buttons = []
12
- for i in range(3):
13
- row = []
14
- for j in range(3):
15
- button = tk.Button(self.window, command=lambda row=i, column=j: self.click(row, column), height=3, width=6)
16
- button.grid(row=i, column=j)
17
- row.append(button)
18
- self.buttons.append(row)
19
-
20
- def click(self, row, column):
21
- if self.buttons[row][column]['text'] == "":
22
- self.buttons[row][column]['text'] = self.player_turn
23
- if self.check_win():
24
- messagebox.showinfo("Game Over", f"Player {self.player_turn} wins!")
25
- self.window.quit()
26
- self.player_turn = "O" if self.player_turn == "X" else "X"
27
-
28
- def check_win(self):
29
- for row in self.buttons:
30
- if row[0]['text'] == row[1]['text'] == row[2]['text'] != "":
31
- return True
32
- for column in range(3):
33
- if self.buttons[0][column]['text'] == self.buttons[1][column]['text'] == self.buttons[2][column]['text'] != "":
34
- return True
35
- if self.buttons[0][0]['text'] == self.buttons[1][1]['text'] == self.buttons[2][2]['text'] != "":
36
- return True
37
- if self.buttons[0][2]['text'] == self.buttons[1][1]['text'] == self.buttons[2][0]['text'] != "":
38
- return True
39
- return False
40
-
41
- def run(self):
42
- self.window.mainloop()
43
-
44
- if __name__ == "__main__":
45
- game = TicTacToe()
46
- game.run()