UltraMarkoBR commited on
Commit
ca798e3
·
verified ·
1 Parent(s): 10575bc

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +792 -19
index.html CHANGED
@@ -1,19 +1,792 @@
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>Synapse | Adaptive Neural Simulation</title>
7
+
8
+ <!-- Fonts -->
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Inter:wght@300;400;600;800&display=swap" rel="stylesheet">
12
+
13
+ <!-- Icons -->
14
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
15
+
16
+ <style>
17
+ :root {
18
+ --bg-color: #050505;
19
+ --panel-bg: rgba(20, 20, 25, 0.6);
20
+ --text-main: #ffffff;
21
+ --text-muted: #888899;
22
+ --accent-primary: #00f3ff; /* Cyan */
23
+ --accent-secondary: #bc13fe; /* Magenta */
24
+ --accent-success: #00ff9d; /* Green */
25
+ --accent-danger: #ff0055;
26
+ --font-display: 'Inter', sans-serif;
27
+ --font-mono: 'JetBrains Mono', monospace;
28
+ --glass-border: 1px solid rgba(255, 255, 255, 0.1);
29
+ }
30
+
31
+ * {
32
+ box-sizing: border-box;
33
+ margin: 0;
34
+ padding: 0;
35
+ }
36
+
37
+ body {
38
+ background-color: var(--bg-color);
39
+ color: var(--text-main);
40
+ font-family: var(--font-display);
41
+ overflow: hidden; /* Prevent scroll, full app feel */
42
+ height: 100vh;
43
+ width: 100vw;
44
+ position: relative;
45
+ }
46
+
47
+ /* Canvas Layer */
48
+ #neural-canvas {
49
+ position: absolute;
50
+ top: 0;
51
+ left: 0;
52
+ width: 100%;
53
+ height: 100%;
54
+ z-index: 0;
55
+ }
56
+
57
+ /* UI Overlay Layer */
58
+ .ui-layer {
59
+ position: relative;
60
+ z-index: 10;
61
+ width: 100%;
62
+ height: 100%;
63
+ pointer-events: none; /* Let clicks pass through to canvas where needed */
64
+ display: grid;
65
+ grid-template-columns: 300px 1fr 300px;
66
+ grid-template-rows: 80px 1fr 60px;
67
+ padding: 20px;
68
+ gap: 20px;
69
+ }
70
+
71
+ /* Header */
72
+ header {
73
+ grid-column: 1 / -1;
74
+ display: flex;
75
+ justify-content: space-between;
76
+ align-items: center;
77
+ background: var(--panel-bg);
78
+ backdrop-filter: blur(12px);
79
+ -webkit-backdrop-filter: blur(12px);
80
+ border: var(--glass-border);
81
+ border-radius: 12px;
82
+ padding: 0 24px;
83
+ pointer-events: auto;
84
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
85
+ }
86
+
87
+ .brand {
88
+ display: flex;
89
+ align-items: center;
90
+ gap: 12px;
91
+ }
92
+
93
+ .brand i {
94
+ color: var(--accent-primary);
95
+ font-size: 1.5rem;
96
+ animation: pulse 2s infinite;
97
+ }
98
+
99
+ .brand h1 {
100
+ font-size: 1.2rem;
101
+ font-weight: 800;
102
+ letter-spacing: -0.5px;
103
+ text-transform: uppercase;
104
+ }
105
+
106
+ .brand span {
107
+ color: var(--accent-secondary);
108
+ font-size: 0.8rem;
109
+ background: rgba(188, 19, 254, 0.1);
110
+ padding: 2px 8px;
111
+ border-radius: 4px;
112
+ }
113
+
114
+ /* Stats Bar */
115
+ .stats-container {
116
+ display: flex;
117
+ gap: 30px;
118
+ }
119
+
120
+ .stat-item {
121
+ display: flex;
122
+ flex-direction: column;
123
+ align-items: flex-end;
124
+ }
125
+
126
+ .stat-label {
127
+ font-size: 0.7rem;
128
+ color: var(--text-muted);
129
+ font-family: var(--font-mono);
130
+ text-transform: uppercase;
131
+ }
132
+
133
+ .stat-value {
134
+ font-size: 1.2rem;
135
+ font-weight: 700;
136
+ font-family: var(--font-mono);
137
+ color: var(--accent-primary);
138
+ }
139
+
140
+ /* Sidebar Controls */
141
+ aside {
142
+ pointer-events: auto;
143
+ background: var(--panel-bg);
144
+ backdrop-filter: blur(12px);
145
+ border: var(--glass-border);
146
+ border-radius: 12px;
147
+ padding: 20px;
148
+ display: flex;
149
+ flex-direction: column;
150
+ gap: 20px;
151
+ transition: transform 0.3s ease;
152
+ }
153
+
154
+ .panel-title {
155
+ font-size: 0.9rem;
156
+ font-weight: 600;
157
+ color: var(--text-main);
158
+ border-bottom: 1px solid rgba(255,255,255,0.1);
159
+ padding-bottom: 10px;
160
+ margin-bottom: 5px;
161
+ }
162
+
163
+ .control-group {
164
+ display: flex;
165
+ flex-direction: column;
166
+ gap: 8px;
167
+ }
168
+
169
+ label {
170
+ font-size: 0.8rem;
171
+ color: var(--text-muted);
172
+ display: flex;
173
+ justify-content: space-between;
174
+ }
175
+
176
+ input[type="range"] {
177
+ -webkit-appearance: none;
178
+ width: 100%;
179
+ height: 4px;
180
+ background: rgba(255,255,255,0.1);
181
+ border-radius: 2px;
182
+ outline: none;
183
+ }
184
+
185
+ input[type="range"]::-webkit-slider-thumb {
186
+ -webkit-appearance: none;
187
+ width: 16px;
188
+ height: 16px;
189
+ background: var(--accent-primary);
190
+ border-radius: 50%;
191
+ cursor: pointer;
192
+ transition: transform 0.1s;
193
+ }
194
+
195
+ input[type="range"]::-webkit-slider-thumb:hover {
196
+ transform: scale(1.2);
197
+ }
198
+
199
+ .btn {
200
+ background: rgba(255,255,255,0.05);
201
+ border: 1px solid rgba(255,255,255,0.1);
202
+ color: white;
203
+ padding: 10px;
204
+ border-radius: 6px;
205
+ cursor: pointer;
206
+ font-family: var(--font-mono);
207
+ font-size: 0.8rem;
208
+ transition: all 0.2s;
209
+ text-align: center;
210
+ }
211
+
212
+ .btn:hover {
213
+ background: rgba(255,255,255,0.1);
214
+ border-color: var(--accent-primary);
215
+ }
216
+
217
+ .btn-primary {
218
+ background: var(--accent-primary);
219
+ color: #000;
220
+ border: none;
221
+ font-weight: 700;
222
+ }
223
+
224
+ .btn-primary:hover {
225
+ background: #fff;
226
+ box-shadow: 0 0 15px var(--accent-primary);
227
+ }
228
+
229
+ .btn-danger {
230
+ border-color: var(--accent-danger);
231
+ color: var(--accent-danger);
232
+ }
233
+
234
+ .btn-danger:hover {
235
+ background: var(--accent-danger);
236
+ color: white;
237
+ }
238
+
239
+ /* Log Panel */
240
+ #log-panel {
241
+ grid-column: 3;
242
+ grid-row: 2;
243
+ overflow: hidden;
244
+ display: flex;
245
+ flex-direction: column;
246
+ }
247
+
248
+ .log-content {
249
+ font-family: var(--font-mono);
250
+ font-size: 0.75rem;
251
+ color: var(--text-muted);
252
+ overflow-y: auto;
253
+ height: 100%;
254
+ display: flex;
255
+ flex-direction: column-reverse; /* Newest at bottom visually, but we prepend */
256
+ }
257
+
258
+ .log-entry {
259
+ margin-bottom: 6px;
260
+ padding-left: 10px;
261
+ border-left: 2px solid transparent;
262
+ animation: slideIn 0.3s ease-out;
263
+ }
264
+
265
+ .log-entry.info { border-color: var(--accent-primary); color: #ccc; }
266
+ .log-entry.success { border-color: var(--accent-success); color: var(--accent-success); }
267
+ .log-entry.warn { border-color: var(--accent-secondary); color: var(--accent-secondary); }
268
+
269
+ /* Footer */
270
+ footer {
271
+ grid-column: 1 / -1;
272
+ display: flex;
273
+ justify-content: center;
274
+ align-items: center;
275
+ pointer-events: auto;
276
+ }
277
+
278
+ .anycoder-link {
279
+ color: var(--text-muted);
280
+ text-decoration: none;
281
+ font-size: 0.8rem;
282
+ font-weight: 600;
283
+ display: flex;
284
+ align-items: center;
285
+ gap: 8px;
286
+ padding: 8px 16px;
287
+ background: rgba(0,0,0,0.5);
288
+ border-radius: 20px;
289
+ border: 1px solid rgba(255,255,255,0.05);
290
+ transition: all 0.3s;
291
+ }
292
+
293
+ .anycoder-link:hover {
294
+ color: var(--accent-primary);
295
+ border-color: var(--accent-primary);
296
+ background: rgba(0, 243, 255, 0.05);
297
+ }
298
+
299
+ /* Animations */
300
+ @keyframes pulse {
301
+ 0% { opacity: 0.6; text-shadow: 0 0 5px var(--accent-primary); }
302
+ 50% { opacity: 1; text-shadow: 0 0 20px var(--accent-primary); }
303
+ 100% { opacity: 0.6; text-shadow: 0 0 5px var(--accent-primary); }
304
+ }
305
+
306
+ @keyframes slideIn {
307
+ from { opacity: 0; transform: translateX(10px); }
308
+ to { opacity: 1; transform: translateX(0); }
309
+ }
310
+
311
+ /* Responsive */
312
+ @media (max-width: 1024px) {
313
+ .ui-layer {
314
+ grid-template-columns: 1fr;
315
+ grid-template-rows: auto auto 1fr auto;
316
+ gap: 10px;
317
+ padding: 10px;
318
+ }
319
+
320
+ header { grid-column: 1; }
321
+ aside {
322
+ grid-column: 1;
323
+ flex-direction: row;
324
+ flex-wrap: wrap;
325
+ height: auto;
326
+ padding: 10px;
327
+ }
328
+ #log-panel {
329
+ grid-column: 1;
330
+ grid-row: 3;
331
+ height: 150px;
332
+ }
333
+ footer { grid-column: 1; grid-row: 4; }
334
+
335
+ .stats-container { display: none; } /* Hide stats on small mobile to save space */
336
+ }
337
+ </style>
338
+ </head>
339
+ <body>
340
+
341
+ <canvas id="neural-canvas"></canvas>
342
+
343
+ <div class="ui-layer">
344
+ <header>
345
+ <div class="brand">
346
+ <i class="fa-solid fa-brain"></i>
347
+ <h1>Synapse <span>v2.4</span></h1>
348
+ </div>
349
+ <div class="stats-container">
350
+ <div class="stat-item">
351
+ <span class="stat-label">Population</span>
352
+ <span class="stat-value" id="stat-pop">0</span>
353
+ </div>
354
+ <div class="stat-item">
355
+ <span class="stat-label">Generation</span>
356
+ <span class="stat-value" id="stat-gen">1</span>
357
+ </div>
358
+ <div class="stat-item">
359
+ <span class="stat-label">Avg Fitness</span>
360
+ <span class="stat-value" id="stat-fit">0%</span>
361
+ </div>
362
+ </div>
363
+ <div class="brand" style="opacity: 0.5;">
364
+ <i class="fa-solid fa-microchip" style="animation: none; color: #fff;"></i>
365
+ <span style="background:transparent; padding:0;">SYSTEM ONLINE</span>
366
+ </div>
367
+ </header>
368
+
369
+ <aside>
370
+ <div class="control-group" style="flex: 1; min-width: 200px;">
371
+ <div class="panel-title">Simulation Parameters</div>
372
+
373
+ <div class="control-group">
374
+ <label>Mutation Rate <span id="val-mutation">5%</span></label>
375
+ <input type="range" id="inp-mutation" min="1" max="50" value="5">
376
+ </div>
377
+
378
+ <div class="control-group">
379
+ <label>Food Spawn Rate <span id="val-food">Normal</span></label>
380
+ <input type="range" id="inp-food" min="1" max="10" value="5">
381
+ </div>
382
+
383
+ <div class="control-group">
384
+ <label>Max Population <span id="val-maxpop">200</span></label>
385
+ <input type="range" id="inp-maxpop" min="50" max="1000" value="200">
386
+ </div>
387
+ </div>
388
+
389
+ <div class="control-group" style="justify-content: flex-end;">
390
+ <button class="btn btn-primary" id="btn-reset"><i class="fa-solid fa-rotate-right"></i> REBOOT SYSTEM</button>
391
+ <button class="btn btn-danger" id="btn-purge"><i class="fa-solid fa-trash"></i> PURGE WEAK</button>
392
+ </div>
393
+ </aside>
394
+
395
+ <aside id="log-panel">
396
+ <div class="panel-title">System Log</div>
397
+ <div class="log-content" id="log-container">
398
+ <!-- Logs go here -->
399
+ </div>
400
+ </aside>
401
+
402
+ <footer>
403
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
404
+ <i class="fa-solid fa-code"></i> Built with anycoder
405
+ </a>
406
+ </footer>
407
+ </div>
408
+
409
+ <script>
410
+ /**
411
+ * SYNAPSE ENGINE
412
+ * A self-adapting particle system simulation.
413
+ */
414
+
415
+ const canvas = document.getElementById('neural-canvas');
416
+ const ctx = canvas.getContext('2d');
417
+
418
+ // UI Elements
419
+ const ui = {
420
+ pop: document.getElementById('stat-pop'),
421
+ gen: document.getElementById('stat-gen'),
422
+ fit: document.getElementById('stat-fit'),
423
+ logs: document.getElementById('log-container'),
424
+ inputs: {
425
+ mutation: document.getElementById('inp-mutation'),
426
+ food: document.getElementById('inp-food'),
427
+ maxPop: document.getElementById('inp-maxpop')
428
+ },
429
+ labels: {
430
+ mutation: document.getElementById('val-mutation'),
431
+ food: document.getElementById('val-food'),
432
+ maxPop: document.getElementById('val-maxpop')
433
+ }
434
+ };
435
+
436
+ // State
437
+ let width, height;
438
+ let agents = [];
439
+ let foods = [];
440
+ let frame = 0;
441
+ let globalGeneration = 1;
442
+ let totalFitness = 0;
443
+
444
+ // Config
445
+ const config = {
446
+ mutationRate: 0.05,
447
+ foodSpawnRate: 5,
448
+ maxPopulation: 200,
449
+ baseSpeed: 2,
450
+ sensorRange: 100
451
+ };
452
+
453
+ // Resize Handler
454
+ function resize() {
455
+ width = canvas.width = window.innerWidth;
456
+ height = canvas.height = window.innerHeight;
457
+ }
458
+ window.addEventListener('resize', resize);
459
+ resize();
460
+
461
+ // Logger
462
+ function log(msg, type = 'info') {
463
+ const div = document.createElement('div');
464
+ div.className = `log-entry ${type}`;
465
+ div.innerHTML = `<span style="opacity:0.5">[${new Date().toLocaleTimeString().split(' ')[0]}]</span> ${msg}`;
466
+ ui.logs.prepend(div);
467
+ if (ui.logs.children.length > 20) ui.logs.lastChild.remove();
468
+ }
469
+
470
+ // Classes
471
+ class Vector {
472
+ constructor(x, y) { this.x = x; this.y = y; }
473
+ add(v) { this.x += v.x; this.y += v.y; }
474
+ mult(n) { this.x *= n; this.y *= n; }
475
+ limit(max) {
476
+ const magSq = this.x*this.x + this.y*this.y;
477
+ if (magSq > max*max) {
478
+ this.div(Math.sqrt(magSq));
479
+ this.mult(max);
480
+ }
481
+ }
482
+ div(n) { this.x /= n; this.y /= n; }
483
+ copy() { return new Vector(this.x, this.y); }
484
+ static sub(v1, v2) { return new Vector(v1.x - v2.x, v1.y - v2.y); }
485
+ static random2D() {
486
+ const angle = Math.random() * Math.PI * 2;
487
+ return new Vector(Math.cos(angle), Math.sin(angle));
488
+ }
489
+ }
490
+
491
+ class Food {
492
+ constructor(x, y) {
493
+ this.pos = new Vector(x || Math.random() * width, y || Math.random() * height);
494
+ this.size = 4;
495
+ this.color = '#00ff9d';
496
+ }
497
+ draw() {
498
+ ctx.beginPath();
499
+ ctx.arc(this.pos.x, this.pos.y, this.size, 0, Math.PI * 2);
500
+ ctx.fillStyle = this.color;
501
+ ctx.shadowBlur = 10;
502
+ ctx.shadowColor = this.color;
503
+ ctx.fill();
504
+ ctx.shadowBlur = 0;
505
+ }
506
+ }
507
+
508
+ class Agent {
509
+ constructor(x, y, dna) {
510
+ this.pos = new Vector(x || Math.random() * width, y || Math.random() * height);
511
+ this.vel = Vector.random2D();
512
+ this.acc = new Vector(0, 0);
513
+ this.r = 6;
514
+ this.maxSpeed = config.baseSpeed;
515
+ this.maxForce = 0.2;
516
+ this.health = 100;
517
+ this.dna = dna || { speed: 1, sense: 1, color: 'hsl(190, 100%, 50%)' };
518
+ this.generation = 1;
519
+ this.fitness = 0;
520
+
521
+ // Apply DNA
522
+ if(dna) {
523
+ this.maxSpeed = config.baseSpeed * dna.speed;
524
+ this.r = 6 * dna.sense;
525
+ }
526
+ }
527
+
528
+ update() {
529
+ this.health -= 0.2; // Metabolism
530
+ this.vel.add(this.acc);
531
+ this.vel.limit(this.maxSpeed);
532
+ this.pos.add(this.vel);
533
+ this.acc.mult(0);
534
+
535
+ // Wrap around screen
536
+ if (this.pos.x > width) this.pos.x = 0;
537
+ if (this.pos.x < 0) this.pos.x = width;
538
+ if (this.pos.y > height) this.pos.y = 0;
539
+ if (this.pos.y < 0) this.pos.y = height;
540
+ }
541
+
542
+ applyForce(force) {
543
+ this.acc.add(force);
544
+ }
545
+
546
+ seek(target) {
547
+ let desired = Vector.sub(target, this.pos);
548
+ desired.normalize();
549
+ desired.mult(this.maxSpeed);
550
+ let steer = Vector.sub(desired, this.vel);
551
+ steer.limit(this.maxForce);
552
+ this.applyForce(steer);
553
+ }
554
+
555
+ behave(foods) {
556
+ let closest = null;
557
+ let closestDist = Infinity;
558
+
559
+ // Find closest food
560
+ for (let food of foods) {
561
+ let d = Math.hypot(food.pos.x - this.pos.x, food.pos.y - this.pos.y);
562
+ if (d < closestDist && d < config.sensorRange * this.dna.sense) {
563
+ closestDist = d;
564
+ closest = food;
565
+ }
566
+ }
567
+
568
+ if (closest) {
569
+ this.seek(closest.pos);
570
+ this.fitness += 0.1; // Reward for seeking
571
+ } else {
572
+ // Wander if no food
573
+ this.vel.add(Vector.random2D().mult(0.5));
574
+ this.vel.limit(this.maxSpeed);
575
+ }
576
+ }
577
+
578
+ eat(foods) {
579
+ for (let i = foods.length - 1; i >= 0; i--) {
580
+ let d = Math.hypot(foods[i].pos.x - this.pos.x, foods[i].pos.y - this.pos.y);
581
+ if (d < this.r + foods[i].size) {
582
+ foods.splice(i, 1);
583
+ this.health += 40;
584
+ this.fitness += 10;
585
+ return true;
586
+ }
587
+ }
588
+ return false;
589
+ }
590
+
591
+ draw() {
592
+ ctx.beginPath();
593
+ ctx.arc(this.pos.x, this.pos.y, this.r, 0, Math.PI * 2);
594
+ ctx.fillStyle = this.dna.color;
595
+
596
+ // Visual indicator of health
597
+ ctx.globalAlpha = Math.max(0.2, this.health / 100);
598
+ ctx.fill();
599
+
600
+ // Draw direction indicator
601
+ ctx.beginPath();
602
+ ctx.moveTo(this.pos.x, this.pos.y);
603
+ ctx.lineTo(this.pos.x + this.vel.x * 10, this.pos.y + this.vel.y * 10);
604
+ ctx.strokeStyle = 'rgba(255,255,255,0.3)';
605
+ ctx.stroke();
606
+
607
+ ctx.globalAlpha = 1;
608
+ }
609
+
610
+ // Genetic Algorithm: Reproduce
611
+ reproduce(partner) {
612
+ if (this.health > 150 && agents.length < config.maxPopulation) {
613
+ // Mix DNA
614
+ const newSpeed = (this.dna.speed + partner.dna.speed) / 2;
615
+ const newSense = (this.dna.sense + partner.dna.sense) / 2;
616
+
617
+ // Mutate
618
+ const mutateSpeed = (Math.random() < config.mutationRate) ? (Math.random() * 0.4 + 0.8) : 1;
619
+ const mutateSense = (Math.random() < config.mutationRate) ? (Math.random() * 0.4 + 0.8) : 1;
620
+
621
+ const childDNA = {
622
+ speed: newSpeed * mutateSpeed,
623
+ sense: newSense * mutateSense,
624
+ color: this.dna.color // Simplify color inheritance for now
625
+ };
626
+
627
+ // Cap stats to prevent physics breaking
628
+ if(childDNA.speed > 3) childDNA.speed = 3;
629
+ if(childDNA.sense > 2) childDNA.sense = 2;
630
+
631
+ const child = new Agent(this.pos.x, this.pos.y, childDNA);
632
+ child.generation = Math.max(this.generation, partner.generation) + 1;
633
+ agents.push(child);
634
+
635
+ // Visual feedback
636
+ if(child.generation > globalGeneration) {
637
+ globalGeneration = child.generation;
638
+ log(`Evolution detected: Gen ${globalGeneration}`, 'success');
639
+ updateStats();
640
+ }
641
+
642
+ this.health -= 40;
643
+ partner.health -= 40;
644
+ }
645
+ }
646
+ }
647
+
648
+ // Initialization
649
+ function init() {
650
+ agents = [];
651
+ foods = [];
652
+ globalGeneration = 1;
653
+ totalFitness = 0;
654
+
655
+ for (let i = 0; i < 50; i++) {
656
+ agents.push(new Agent());
657
+ }
658
+ log("System initialized. 50 Agents spawned.");
659
+ updateStats();
660
+ }
661
+
662
+ // Main Loop
663
+ function animate() {
664
+ // Trail effect
665
+ ctx.fillStyle = 'rgba(5, 5, 5, 0.2)';
666
+ ctx.fillRect(0, 0, width, height);
667
+
668
+ // Spawn Food
669
+ if (frame % (11 - config.foodSpawnRate) === 0) {
670
+ foods.push(new Food());
671
+ }
672
+
673
+ // Draw Connections (Neural Network visual)
674
+ ctx.strokeStyle = 'rgba(0, 243, 255, 0.05)';
675
+ ctx.lineWidth = 1;
676
+ ctx.beginPath();
677
+ for (let i = 0; i < agents.length; i++) {
678
+ for (let j = i + 1; j < agents.length; j++) {
679
+ let d = Math.hypot(agents[i].pos.x - agents[j].pos.x, agents[i].pos.y - agents[j].pos.y);
680
+ if (d < 100) {
681
+ ctx.moveTo(agents[i].pos.x, agents[i].pos.y);
682
+ ctx.lineTo(agents[j].pos.x, agents[j].pos.y);
683
+ }
684
+ }
685
+ }
686
+ ctx.stroke();
687
+
688
+ // Update Agents
689
+ for (let i = agents.length - 1; i >= 0; i--) {
690
+ let agent = agents[i];
691
+ agent.behave(foods);
692
+ agent.update();
693
+ agent.eat(foods);
694
+ agent.draw();
695
+
696
+ // Reproduction logic (simplified: seek nearby healthy agent)
697
+ if (agent.health > 120) {
698
+ // Simple proximity check for mating
699
+ for (let j = 0; j < agents.length; j++) {
700
+ if (i !== j && agents[j].health > 120) {
701
+ let d = Math.hypot(agent.pos.x - agents[j].pos.x, agent.pos.y - agents[j].pos.y);
702
+ if (d < 50) {
703
+ agent.reproduce(agents[j]);
704
+ break;
705
+ }
706
+ }
707
+ }
708
+ }
709
+
710
+ // Death
711
+ if (agent.health <= 0) {
712
+ agents.splice(i, 1);
713
+ // Spawn a new random one to keep population going if it crashes
714
+ if(agents.length < 5) {
715
+ agents.push(new Agent());
716
+ log("Critical population low. Injecting new DNA.", "warn");
717
+ }
718
+ }
719
+ }
720
+
721
+ // Draw Food
722
+ for (let food of foods) {
723
+ food.draw();
724
+ }
725
+
726
+ // Stats Update (throttled)
727
+ if (frame % 60 === 0) {
728
+ updateStats();
729
+ }
730
+
731
+ frame++;
732
+ requestAnimationFrame(animate);
733
+ }
734
+
735
+ function updateStats() {
736
+ ui.pop.innerText = agents.length;
737
+ ui.gen.innerText = globalGeneration;
738
+
739
+ // Calculate avg fitness roughly
740
+ let totalFit = agents.reduce((acc, a) => acc + a.fitness, 0);
741
+ let avg = agents.length > 0 ? Math.floor(totalFit / agents.length) : 0;
742
+ ui.fit.innerText = avg + " pts";
743
+ }
744
+
745
+ // Interaction
746
+ canvas.addEventListener('mousedown', (e) => {
747
+ // Spawn a burst of food
748
+ for(let i=0; i<5; i++) {
749
+ foods.push(new Food(e.clientX + (Math.random()*40-20), e.clientY + (Math.random()*40-20)));
750
+ }
751
+ log("Energy injected at cursor location.");
752
+ });
753
+
754
+ // Controls
755
+ ui.inputs.mutation.addEventListener('input', (e) => {
756
+ config.mutationRate = e.target.value / 100;
757
+ ui.labels.mutation.innerText = e.target.value + "%";
758
+ });
759
+
760
+ ui.inputs.food.addEventListener('input', (e) => {
761
+ config.foodSpawnRate = parseInt(e.target.value);
762
+ const labels = ["Starving", "Low", "Normal", "High", "Abundant", "Overload"];
763
+ const idx = Math.min(Math.floor((e.target.value-1)/2), 5);
764
+ ui.labels.food.innerText = labels[idx] || "Normal";
765
+ });
766
+
767
+ ui.inputs.maxPop.addEventListener('input', (e) => {
768
+ config.maxPopulation = parseInt(e.target.value);
769
+ ui.labels.maxPop.innerText = config.maxPopulation;
770
+ });
771
+
772
+ document.getElementById('btn-reset').addEventListener('click', () => {
773
+ init();
774
+ log("System rebooted.", "info");
775
+ });
776
+
777
+ document.getElementById('btn-purge').addEventListener('click', () => {
778
+ // Kill bottom 50% fitness
779
+ agents.sort((a, b) => b.fitness - a.fitness);
780
+ const cut = Math.floor(agents.length / 2);
781
+ agents.splice(cut);
782
+ log(`Purged ${cut} weakest agents.`, "warn");
783
+ updateStats();
784
+ });
785
+
786
+ // Start
787
+ init();
788
+ animate();
789
+
790
+ </script>
791
+ </body>
792
+ </html>