sam-coder-cli 1.0.5 → 1.0.7
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/bin/agi-cli.js +26 -5
- package/foldersnake/snake_game.py +202 -109
- package/package.json +1 -1
package/bin/agi-cli.js
CHANGED
|
@@ -13,7 +13,7 @@ const execAsync = util.promisify(exec);
|
|
|
13
13
|
const CONFIG_PATH = path.join(os.homedir(), '.sam-coder-config.json');
|
|
14
14
|
let OPENROUTER_API_KEY;
|
|
15
15
|
const MODEL = 'deepseek/deepseek-chat-v3-0324:free';
|
|
16
|
-
|
|
16
|
+
let API_BASE_URL = 'https://openrouter.ai/api/v1';
|
|
17
17
|
|
|
18
18
|
// Tool/Function definitions for the AI
|
|
19
19
|
const tools = [
|
|
@@ -775,11 +775,28 @@ async function runSetup(isReconfig = false) {
|
|
|
775
775
|
}
|
|
776
776
|
|
|
777
777
|
const apiKey = await askQuestion('Enter OpenRouter API Key: ');
|
|
778
|
+
const proCode = await askQuestion('Enter Pro Plan activation code (or press Enter to skip): ');
|
|
779
|
+
|
|
780
|
+
let config = { OPENROUTER_API_KEY: apiKey, isPro: false };
|
|
781
|
+
|
|
782
|
+
if (proCode === '1234') {
|
|
783
|
+
console.log('✅ Pro Plan activated!');
|
|
784
|
+
const customEndpoint = await askQuestion('Enter custom OpenAI-compatible API endpoint: ');
|
|
785
|
+
config.isPro = true;
|
|
786
|
+
config.customApiBase = customEndpoint;
|
|
787
|
+
await writeConfig(config);
|
|
788
|
+
console.log('✅ Configuration saved successfully!');
|
|
789
|
+
} else if (proCode) {
|
|
790
|
+
await writeConfig(config);
|
|
791
|
+
console.log('⚠️ Invalid activation code. Standard plan configured.');
|
|
792
|
+
console.log('\nPlease restart the application to continue.');
|
|
793
|
+
rl.close();
|
|
794
|
+
process.exit(0);
|
|
795
|
+
} else {
|
|
796
|
+
await writeConfig(config);
|
|
797
|
+
console.log('✅ Configuration saved successfully!');
|
|
798
|
+
}
|
|
778
799
|
|
|
779
|
-
const config = { OPENROUTER_API_KEY: apiKey };
|
|
780
|
-
await writeConfig(config);
|
|
781
|
-
|
|
782
|
-
console.log('✅ Configuration saved successfully!');
|
|
783
800
|
rl.close();
|
|
784
801
|
return config;
|
|
785
802
|
}
|
|
@@ -793,6 +810,10 @@ async function start() {
|
|
|
793
810
|
}
|
|
794
811
|
|
|
795
812
|
OPENROUTER_API_KEY = config.OPENROUTER_API_KEY;
|
|
813
|
+
if (config.isPro && config.customApiBase) {
|
|
814
|
+
API_BASE_URL = config.customApiBase;
|
|
815
|
+
console.log(`🚀 Using Pro Plan custom endpoint: ${API_BASE_URL}`);
|
|
816
|
+
}
|
|
796
817
|
|
|
797
818
|
ui.showHeader();
|
|
798
819
|
console.log('Select Mode:');
|
|
@@ -1,125 +1,218 @@
|
|
|
1
1
|
import pygame
|
|
2
|
-
import time
|
|
3
2
|
import random
|
|
4
3
|
|
|
5
4
|
# Initialize pygame
|
|
6
5
|
pygame.init()
|
|
7
6
|
|
|
8
|
-
#
|
|
9
|
-
|
|
7
|
+
# Constants
|
|
8
|
+
SCREEN_WIDTH = 300
|
|
9
|
+
SCREEN_HEIGHT = 600
|
|
10
|
+
BLOCK_SIZE = 30
|
|
11
|
+
GRID_WIDTH = 10
|
|
12
|
+
GRID_HEIGHT = 20
|
|
13
|
+
GAME_AREA_LEFT = (SCREEN_WIDTH - GRID_WIDTH * BLOCK_SIZE) // 2
|
|
14
|
+
GAME_AREA_TOP = SCREEN_HEIGHT - GRID_HEIGHT * BLOCK_SIZE
|
|
10
15
|
|
|
11
16
|
# Colors
|
|
12
|
-
WHITE = (255, 255, 255)
|
|
13
17
|
BLACK = (0, 0, 0)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
#
|
|
19
|
-
|
|
18
|
+
WHITE = (255, 255, 255)
|
|
19
|
+
GRAY = (128, 128, 128)
|
|
20
|
+
COLORS = [
|
|
21
|
+
(0, 255, 255), # Cyan (I)
|
|
22
|
+
(0, 0, 255), # Blue (J)
|
|
23
|
+
(255, 165, 0), # Orange (L)
|
|
24
|
+
(255, 255, 0), # Yellow (O)
|
|
25
|
+
(0, 255, 0), # Green (S)
|
|
26
|
+
(128, 0, 128), # Purple (T)
|
|
27
|
+
(255, 0, 0) # Red (Z)
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
# Tetrimino shapes
|
|
31
|
+
SHAPES = [
|
|
32
|
+
[[1, 1, 1, 1]], # I
|
|
33
|
+
[[1, 0, 0], [1, 1, 1]], # J
|
|
34
|
+
[[0, 0, 1], [1, 1, 1]], # L
|
|
35
|
+
[[1, 1], [1, 1]], # O
|
|
36
|
+
[[0, 1, 1], [1, 1, 0]], # S
|
|
37
|
+
[[0, 1, 0], [1, 1, 1]], # T
|
|
38
|
+
[[1, 1, 0], [0, 1, 1]] # Z
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
# Set up the display
|
|
42
|
+
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
|
|
43
|
+
pygame.display.set_caption("Tetris")
|
|
20
44
|
|
|
21
|
-
# Clock for controlling the speed of the snake
|
|
22
45
|
clock = pygame.time.Clock()
|
|
23
46
|
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
47
|
+
# Game variables
|
|
48
|
+
grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
|
|
49
|
+
current_piece = None
|
|
50
|
+
next_piece = None
|
|
51
|
+
current_x = GRID_WIDTH // 2
|
|
52
|
+
current_y = 0
|
|
53
|
+
score = 0
|
|
54
|
+
game_over = False
|
|
55
|
+
fall_time = 0
|
|
56
|
+
fall_speed = 0.5 # seconds
|
|
57
|
+
|
|
58
|
+
def new_piece():
|
|
59
|
+
global current_piece, next_piece, current_x, current_y
|
|
60
|
+
if next_piece is None:
|
|
61
|
+
next_piece = random.randint(0, len(SHAPES) - 1)
|
|
62
|
+
current_piece = next_piece
|
|
63
|
+
next_piece = random.randint(0, len(SHAPES) - 1)
|
|
64
|
+
current_x = GRID_WIDTH // 2 - len(SHAPES[current_piece][0]) // 2
|
|
65
|
+
current_y = 0
|
|
66
|
+
if check_collision():
|
|
67
|
+
return False
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
def check_collision():
|
|
71
|
+
for y, row in enumerate(SHAPES[current_piece]):
|
|
72
|
+
for x, cell in enumerate(row):
|
|
73
|
+
if cell:
|
|
74
|
+
if (current_y + y >= GRID_HEIGHT or
|
|
75
|
+
current_x + x < 0 or
|
|
76
|
+
current_x + x >= GRID_WIDTH or
|
|
77
|
+
grid[current_y + y][current_x + x]):
|
|
78
|
+
return True
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
def merge_piece():
|
|
82
|
+
for y, row in enumerate(SHAPES[current_piece]):
|
|
83
|
+
for x, cell in enumerate(row):
|
|
84
|
+
if cell:
|
|
85
|
+
grid[current_y + y][current_x + x] = current_piece + 1
|
|
86
|
+
|
|
87
|
+
def clear_lines():
|
|
88
|
+
global grid, score
|
|
89
|
+
lines_cleared = 0
|
|
90
|
+
for y in range(GRID_HEIGHT - 1, -1, -1):
|
|
91
|
+
if all(grid[y]):
|
|
92
|
+
lines_cleared += 1
|
|
93
|
+
for y2 in range(y, 0, -1):
|
|
94
|
+
grid[y2] = grid[y2 - 1][:]
|
|
95
|
+
grid[0] = [0] * GRID_WIDTH
|
|
96
|
+
score += lines_cleared ** 2 * 100
|
|
97
|
+
|
|
98
|
+
def draw_grid():
|
|
99
|
+
for y in range(GRID_HEIGHT):
|
|
100
|
+
for x in range(GRID_WIDTH):
|
|
101
|
+
if grid[y][x]:
|
|
102
|
+
pygame.draw.rect(
|
|
103
|
+
screen, COLORS[grid[y][x] - 1],
|
|
104
|
+
(GAME_AREA_LEFT + x * BLOCK_SIZE, GAME_AREA_TOP + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
|
105
|
+
)
|
|
106
|
+
pygame.draw.rect(
|
|
107
|
+
screen, WHITE,
|
|
108
|
+
(GAME_AREA_LEFT + x * BLOCK_SIZE, GAME_AREA_TOP + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
|
|
109
|
+
1
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def draw_piece():
|
|
113
|
+
for y, row in enumerate(SHAPES[current_piece]):
|
|
114
|
+
for x, cell in enumerate(row):
|
|
115
|
+
if cell:
|
|
116
|
+
pygame.draw.rect(
|
|
117
|
+
screen, COLORS[current_piece],
|
|
118
|
+
(GAME_AREA_LEFT + (current_x + x) * BLOCK_SIZE, GAME_AREA_TOP + (current_y + y) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
|
119
|
+
)
|
|
120
|
+
pygame.draw.rect(
|
|
121
|
+
screen, WHITE,
|
|
122
|
+
(GAME_AREA_LEFT + (current_x + x) * BLOCK_SIZE, GAME_AREA_TOP + (current_y + y) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
|
|
123
|
+
1
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
def draw_next_piece():
|
|
127
|
+
if next_piece is not None:
|
|
128
|
+
font = pygame.font.SysFont(None, 24)
|
|
129
|
+
text = font.render("Next:", True, WHITE)
|
|
130
|
+
screen.blit(text, (20, 20))
|
|
131
|
+
for y, row in enumerate(SHAPES[next_piece]):
|
|
132
|
+
for x, cell in enumerate(row):
|
|
133
|
+
if cell:
|
|
134
|
+
pygame.draw.rect(
|
|
135
|
+
screen, COLORS[next_piece],
|
|
136
|
+
(40 + x * BLOCK_SIZE, 50 + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
|
137
|
+
)
|
|
138
|
+
pygame.draw.rect(
|
|
139
|
+
screen, WHITE,
|
|
140
|
+
(40 + x * BLOCK_SIZE, 50 + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
|
|
141
|
+
1
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def draw_score():
|
|
145
|
+
font = pygame.font.SysFont(None, 36)
|
|
146
|
+
text = font.render(f"Score: {score}", True, WHITE)
|
|
147
|
+
screen.blit(text, (20, SCREEN_HEIGHT - 50))
|
|
148
|
+
|
|
149
|
+
def rotate_piece():
|
|
150
|
+
global current_piece
|
|
151
|
+
rotated = list(zip(*reversed(SHAPES[current_piece])))
|
|
152
|
+
for y in range(len(rotated)):
|
|
153
|
+
rotated[y] = list(rotated[y])
|
|
154
|
+
old_shape = SHAPES[current_piece]
|
|
155
|
+
SHAPES[current_piece] = rotated
|
|
156
|
+
if check_collision():
|
|
157
|
+
SHAPES[current_piece] = old_shape
|
|
158
|
+
|
|
159
|
+
# Main game loop
|
|
160
|
+
new_piece()
|
|
161
|
+
running = True
|
|
162
|
+
while running:
|
|
163
|
+
screen.fill(BLACK)
|
|
164
|
+
fall_time += clock.get_rawtime() / 1000 # Convert to seconds
|
|
165
|
+
clock.tick()
|
|
166
|
+
|
|
167
|
+
if fall_time >= fall_speed:
|
|
168
|
+
fall_time = 0
|
|
169
|
+
current_y += 1
|
|
170
|
+
if check_collision():
|
|
171
|
+
current_y -= 1
|
|
172
|
+
merge_piece()
|
|
173
|
+
clear_lines()
|
|
174
|
+
if not new_piece():
|
|
74
175
|
game_over = True
|
|
75
|
-
if event.type == pygame.KEYDOWN:
|
|
76
|
-
if event.key == pygame.K_LEFT:
|
|
77
|
-
x1_change = -BLOCK_SIZE
|
|
78
|
-
y1_change = 0
|
|
79
|
-
elif event.key == pygame.K_RIGHT:
|
|
80
|
-
x1_change = BLOCK_SIZE
|
|
81
|
-
y1_change = 0
|
|
82
|
-
elif event.key == pygame.K_UP:
|
|
83
|
-
y1_change = -BLOCK_SIZE
|
|
84
|
-
x1_change = 0
|
|
85
|
-
elif event.key == pygame.K_DOWN:
|
|
86
|
-
y1_change = BLOCK_SIZE
|
|
87
|
-
x1_change = 0
|
|
88
|
-
|
|
89
|
-
if x1 >= WIDTH or x1 < 0 or y1 >= HEIGHT or y1 < 0:
|
|
90
|
-
game_close = True
|
|
91
|
-
x1 += x1_change
|
|
92
|
-
y1 += y1_change
|
|
93
|
-
screen.fill(BLACK)
|
|
94
|
-
pygame.draw.rect(screen, GREEN, [foodx, foody, BLOCK_SIZE, BLOCK_SIZE])
|
|
95
|
-
snake_head = []
|
|
96
|
-
snake_head.append(x1)
|
|
97
|
-
snake_head.append(y1)
|
|
98
|
-
snake_list.append(snake_head)
|
|
99
|
-
if len(snake_list) > length_of_snake:
|
|
100
|
-
del snake_list[0]
|
|
101
|
-
|
|
102
|
-
for pos in snake_list[:-1]:
|
|
103
|
-
if pos == snake_head:
|
|
104
|
-
game_close = True
|
|
105
|
-
|
|
106
|
-
our_snake(BLOCK_SIZE, snake_list)
|
|
107
|
-
your_score(length_of_snake - 1)
|
|
108
176
|
|
|
177
|
+
for event in pygame.event.get():
|
|
178
|
+
if event.type == pygame.QUIT:
|
|
179
|
+
running = False
|
|
180
|
+
if event.type == pygame.KEYDOWN:
|
|
181
|
+
if event.key == pygame.K_LEFT:
|
|
182
|
+
current_x -= 1
|
|
183
|
+
if check_collision():
|
|
184
|
+
current_x += 1
|
|
185
|
+
if event.key == pygame.K_RIGHT:
|
|
186
|
+
current_x += 1
|
|
187
|
+
if check_collision():
|
|
188
|
+
current_x -= 1
|
|
189
|
+
if event.key == pygame.K_DOWN:
|
|
190
|
+
current_y += 1
|
|
191
|
+
if check_collision():
|
|
192
|
+
current_y -= 1
|
|
193
|
+
if event.key == pygame.K_UP:
|
|
194
|
+
rotate_piece()
|
|
195
|
+
if event.key == pygame.K_SPACE:
|
|
196
|
+
while not check_collision():
|
|
197
|
+
current_y += 1
|
|
198
|
+
current_y -= 1
|
|
199
|
+
merge_piece()
|
|
200
|
+
clear_lines()
|
|
201
|
+
if not new_piece():
|
|
202
|
+
game_over = True
|
|
203
|
+
|
|
204
|
+
draw_grid()
|
|
205
|
+
draw_piece()
|
|
206
|
+
draw_next_piece()
|
|
207
|
+
draw_score()
|
|
208
|
+
pygame.display.update()
|
|
209
|
+
|
|
210
|
+
if game_over:
|
|
211
|
+
font = pygame.font.SysFont(None, 48)
|
|
212
|
+
text = font.render("GAME OVER", True, WHITE)
|
|
213
|
+
screen.blit(text, (SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2 - 24))
|
|
109
214
|
pygame.display.update()
|
|
215
|
+
pygame.time.wait(2000)
|
|
216
|
+
running = False
|
|
110
217
|
|
|
111
|
-
|
|
112
|
-
foodx = round(random.randrange(0, WIDTH - BLOCK_SIZE) / 20.0) * 20.0
|
|
113
|
-
foody = round(random.randrange(0, HEIGHT - BLOCK_SIZE) / 20.0) * 20.0
|
|
114
|
-
length_of_snake += 1
|
|
115
|
-
|
|
116
|
-
clock.tick(15)
|
|
117
|
-
|
|
118
|
-
pygame.quit()
|
|
119
|
-
quit()
|
|
120
|
-
|
|
121
|
-
# Create the screen
|
|
122
|
-
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
|
123
|
-
pygame.display.set_caption('Snake Game')
|
|
124
|
-
|
|
125
|
-
gameLoop()
|
|
218
|
+
pygame.quit()
|