TeacherPuffy commited on
Commit
ea678b8
·
verified ·
1 Parent(s): 2b72810

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +141 -16
index.html CHANGED
@@ -2,6 +2,7 @@
2
  <html>
3
  <head>
4
  <title>Cancer Game Theory</title>
 
5
  <style>
6
  body {
7
  font-family: Arial, sans-serif;
@@ -33,6 +34,8 @@
33
  }
34
  .rules ul {
35
  line-height: 1.6;
 
 
36
  }
37
  canvas {
38
  border: 2px solid #1e3799;
@@ -71,28 +74,52 @@
71
  button:hover {
72
  background-color: #0c2461;
73
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  </style>
75
  </head>
76
  <body>
77
  <div class="header">
78
- <h1>Cancer Game Theory</h1>
79
  </div>
80
 
81
  <div class="rules">
82
  <h2>Simulation Rules</h2>
83
  <ul>
84
- <li>🦠 Cancer cells die when surrounded by 3+ cells within 40px</li>
85
- <li>🩺 Cancer cells convert isolated healthy cells (no nearby healthy)</li>
86
- <li>🧬 Cells reproduce based on type-specific rates</li>
87
- <li>⚡ Cancer cells move faster than healthy cells</li>
88
- <li>🧠 Neural networks control movement decisions</li>
89
- <li>🎮 Adjust parameters below to influence outcomes</li>
90
  </ul>
91
  </div>
92
 
93
  <div class="controls">
94
  <h2>Simulation Parameters</h2>
95
  <div class="param-group">
 
96
  <label>Initial Healthy: <input type="number" id="initialHealthy" value="15" min="1"></label>
97
  <label>Initial Cancer: <input type="number" id="initialCancer" value="8" min="1"></label>
98
  <label>Mutation Rate: <input type="number" id="mutationRate" value="0.1" step="0.01" min="0"></label>
@@ -107,6 +134,27 @@
107
  Healthy: <span id="healthyCount">0</span> |
108
  Cancer: <span id="cancerCount">0</span>
109
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  </div>
111
 
112
  <canvas id="simCanvas" width="800" height="500"></canvas>
@@ -124,6 +172,9 @@
124
  let generation = 1;
125
  let frameCount = 0;
126
  const cellRadius = 5;
 
 
 
127
 
128
  function getNormal(mean = 0, std = 1) {
129
  let u, v, s;
@@ -138,6 +189,9 @@
138
 
139
  class NeuralNetwork {
140
  constructor(parent = null) {
 
 
 
141
  if(parent) {
142
  this.weights1 = parent.weights1.map(row =>
143
  row.map(w => w + getNormal(0, parseFloat(document.getElementById('mutationRate').value)))
@@ -146,15 +200,15 @@
146
  row.map(w => w + getNormal(0, parseFloat(document.getElementById('mutationRate').value)))
147
  );
148
  } else {
149
- this.weights1 = Array.from({length: 8}, () =>
150
- Array.from({length: 4}, () => getNormal(0, 1)));
151
- this.weights2 = Array.from({length: 4}, () =>
152
- Array.from({length: 2}, () => getNormal(0, 1)));
153
  }
154
  }
155
 
156
  activate(x) {
157
- return x; // Linear activation for unlimited speed
158
  }
159
 
160
  predict(inputs) {
@@ -177,6 +231,7 @@
177
  this.y = parent ?
178
  parent.y + (Math.random() * 40 - 20) :
179
  Math.random() * canvas.height;
 
180
  }
181
 
182
  getNearbyCells() {
@@ -200,17 +255,16 @@
200
 
201
  const [vx, vy] = this.brain.predict(inputs);
202
 
203
- // Unlimited speed based on neural network output
204
  this.x += vx;
205
  this.y += vy;
 
206
 
207
- // Cancer cells get inherent speed boost
208
  if(this.type === 'cancer') {
209
- this.x += vx * 0.5; // Additional 50% speed boost
210
  this.y += vy * 0.5;
 
211
  }
212
 
213
- // Wrap around edges
214
  this.x = (this.x + canvas.width) % canvas.width;
215
  this.y = (this.y + canvas.height) % canvas.height;
216
  }
@@ -223,6 +277,72 @@
223
  }
224
  }
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  function checkCollisions() {
227
  cells.forEach((cell, i) => {
228
  if(cell.type === 'cancer') {
@@ -277,6 +397,7 @@
277
  generation++;
278
  reproduceCells();
279
  updateStatus();
 
280
  }
281
 
282
  cells.forEach(cell => cell.update());
@@ -296,6 +417,8 @@
296
  generation = 1;
297
  frameCount = 0;
298
  cells = [];
 
 
299
 
300
  const initialHealthy = parseInt(document.getElementById('initialHealthy').value);
301
  const initialCancer = parseInt(document.getElementById('initialCancer').value);
@@ -304,6 +427,8 @@
304
  for(let i = 0; i < initialCancer; i++) cells.push(new Cell('cancer'));
305
 
306
  updateStatus();
 
 
307
  ctx.clearRect(0, 0, canvas.width, canvas.height);
308
  cells.forEach(cell => cell.draw());
309
  });
 
2
  <html>
3
  <head>
4
  <title>Cancer Game Theory</title>
5
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
6
  <style>
7
  body {
8
  font-family: Arial, sans-serif;
 
34
  }
35
  .rules ul {
36
  line-height: 1.6;
37
+ list-style-type: none;
38
+ padding-left: 0;
39
  }
40
  canvas {
41
  border: 2px solid #1e3799;
 
74
  button:hover {
75
  background-color: #0c2461;
76
  }
77
+ .data-panel {
78
+ display: grid;
79
+ grid-template-columns: 1fr 1fr;
80
+ gap: 20px;
81
+ margin-top: 20px;
82
+ }
83
+ .generations-table {
84
+ max-height: 300px;
85
+ overflow-y: auto;
86
+ }
87
+ table {
88
+ width: 100%;
89
+ border-collapse: collapse;
90
+ }
91
+ th, td {
92
+ padding: 8px;
93
+ text-align: left;
94
+ border-bottom: 1px solid #ddd;
95
+ }
96
+ th {
97
+ background-color: #1e3799;
98
+ color: white;
99
+ }
100
  </style>
101
  </head>
102
  <body>
103
  <div class="header">
104
+ <h1>Cancer Game Theory Simulation</h1>
105
  </div>
106
 
107
  <div class="rules">
108
  <h2>Simulation Rules</h2>
109
  <ul>
110
+ <li>Cancer cells die when surrounded by 3+ cells within 40px</li>
111
+ <li>Cancer cells convert isolated healthy cells (no nearby healthy)</li>
112
+ <li>Cells reproduce based on type-specific rates</li>
113
+ <li>Cancer cells move faster than healthy cells</li>
114
+ <li>Neural networks control movement decisions</li>
115
+ <li>Adjust parameters below to influence outcomes</li>
116
  </ul>
117
  </div>
118
 
119
  <div class="controls">
120
  <h2>Simulation Parameters</h2>
121
  <div class="param-group">
122
+ <label>Hidden Dimension: <input type="number" id="hiddenDim" value="4" min="1"></label>
123
  <label>Initial Healthy: <input type="number" id="initialHealthy" value="15" min="1"></label>
124
  <label>Initial Cancer: <input type="number" id="initialCancer" value="8" min="1"></label>
125
  <label>Mutation Rate: <input type="number" id="mutationRate" value="0.1" step="0.01" min="0"></label>
 
134
  Healthy: <span id="healthyCount">0</span> |
135
  Cancer: <span id="cancerCount">0</span>
136
  </div>
137
+
138
+ <div class="data-panel">
139
+ <div class="generations-table">
140
+ <h3>Generation History (Every 10 gens)</h3>
141
+ <table id="generationTable">
142
+ <thead>
143
+ <tr>
144
+ <th>Generation</th>
145
+ <th>Healthy</th>
146
+ <th>Cancer</th>
147
+ <th>Avg Speed</th>
148
+ </tr>
149
+ </thead>
150
+ <tbody id="tableBody"></tbody>
151
+ </table>
152
+ </div>
153
+ <div>
154
+ <h3>Population Trends</h3>
155
+ <canvas id="populationChart"></canvas>
156
+ </div>
157
+ </div>
158
  </div>
159
 
160
  <canvas id="simCanvas" width="800" height="500"></canvas>
 
172
  let generation = 1;
173
  let frameCount = 0;
174
  const cellRadius = 5;
175
+ let populationChart = null;
176
+ let generationsData = [];
177
+ let currentHiddenDim = 4;
178
 
179
  function getNormal(mean = 0, std = 1) {
180
  let u, v, s;
 
189
 
190
  class NeuralNetwork {
191
  constructor(parent = null) {
192
+ const inputSize = 8;
193
+ const outputSize = 2;
194
+
195
  if(parent) {
196
  this.weights1 = parent.weights1.map(row =>
197
  row.map(w => w + getNormal(0, parseFloat(document.getElementById('mutationRate').value)))
 
200
  row.map(w => w + getNormal(0, parseFloat(document.getElementById('mutationRate').value)))
201
  );
202
  } else {
203
+ this.weights1 = Array.from({length: inputSize}, () =>
204
+ Array.from({length: currentHiddenDim}, () => getNormal(0, 1)));
205
+ this.weights2 = Array.from({length: currentHiddenDim}, () =>
206
+ Array.from({length: outputSize}, () => getNormal(0, 1)));
207
  }
208
  }
209
 
210
  activate(x) {
211
+ return x;
212
  }
213
 
214
  predict(inputs) {
 
231
  this.y = parent ?
232
  parent.y + (Math.random() * 40 - 20) :
233
  Math.random() * canvas.height;
234
+ this.speed = 0;
235
  }
236
 
237
  getNearbyCells() {
 
255
 
256
  const [vx, vy] = this.brain.predict(inputs);
257
 
 
258
  this.x += vx;
259
  this.y += vy;
260
+ this.speed = Math.hypot(vx, vy);
261
 
 
262
  if(this.type === 'cancer') {
263
+ this.x += vx * 0.5;
264
  this.y += vy * 0.5;
265
+ this.speed *= 1.5;
266
  }
267
 
 
268
  this.x = (this.x + canvas.width) % canvas.width;
269
  this.y = (this.y + canvas.height) % canvas.height;
270
  }
 
277
  }
278
  }
279
 
280
+ function updateChart() {
281
+ const ctx = document.getElementById('populationChart').getContext('2d');
282
+
283
+ if(populationChart) {
284
+ populationChart.destroy();
285
+ }
286
+
287
+ populationChart = new Chart(ctx, {
288
+ type: 'line',
289
+ data: {
290
+ labels: generationsData.map(d => d.generation),
291
+ datasets: [{
292
+ label: 'Healthy Cells',
293
+ data: generationsData.map(d => d.healthy),
294
+ borderColor: '#00ff00',
295
+ tension: 0.1
296
+ }, {
297
+ label: 'Cancer Cells',
298
+ data: generationsData.map(d => d.cancer),
299
+ borderColor: '#ff0000',
300
+ tension: 0.1
301
+ }]
302
+ },
303
+ options: {
304
+ responsive: true,
305
+ scales: {
306
+ y: {
307
+ beginAtZero: true
308
+ }
309
+ }
310
+ }
311
+ });
312
+ }
313
+
314
+ function updateTable() {
315
+ const tableBody = document.getElementById('tableBody');
316
+ tableBody.innerHTML = generationsData.map(d => `
317
+ <tr>
318
+ <td>${d.generation}</td>
319
+ <td>${d.healthy}</td>
320
+ <td>${d.cancer}</td>
321
+ <td>${d.avgSpeed.toFixed(2)}</td>
322
+ </tr>
323
+ `).join('');
324
+ }
325
+
326
+ function saveGenerationData() {
327
+ if(generation % 10 === 0) {
328
+ const healthy = cells.filter(c => c.type === 'healthy').length;
329
+ const cancer = cells.filter(c => c.type === 'cancer').length;
330
+ const speeds = cells.map(c => c.speed);
331
+ const avgSpeed = speeds.reduce((a,b) => a + b, 0) / speeds.length || 0;
332
+
333
+ generationsData.push({
334
+ generation,
335
+ healthy,
336
+ cancer,
337
+ avgSpeed
338
+ });
339
+
340
+ if(generationsData.length > 20) generationsData.shift();
341
+ updateChart();
342
+ updateTable();
343
+ }
344
+ }
345
+
346
  function checkCollisions() {
347
  cells.forEach((cell, i) => {
348
  if(cell.type === 'cancer') {
 
397
  generation++;
398
  reproduceCells();
399
  updateStatus();
400
+ saveGenerationData();
401
  }
402
 
403
  cells.forEach(cell => cell.update());
 
417
  generation = 1;
418
  frameCount = 0;
419
  cells = [];
420
+ generationsData = [];
421
+ currentHiddenDim = parseInt(document.getElementById('hiddenDim').value);
422
 
423
  const initialHealthy = parseInt(document.getElementById('initialHealthy').value);
424
  const initialCancer = parseInt(document.getElementById('initialCancer').value);
 
427
  for(let i = 0; i < initialCancer; i++) cells.push(new Cell('cancer'));
428
 
429
  updateStatus();
430
+ updateChart();
431
+ updateTable();
432
  ctx.clearRect(0, 0, canvas.width, canvas.height);
433
  cells.forEach(cell => cell.draw());
434
  });