Skip to content

Commit 18e297b

Browse files
authored
Update lite-diamon-sim.html
1 parent 20ad6f2 commit 18e297b

File tree

1 file changed

+82
-32
lines changed

1 file changed

+82
-32
lines changed

lite-diamon-sim.html

Lines changed: 82 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
.canvas-container { display: flex; justify-content: center; }
1111
canvas { border: 1px solid #999; background-color: #fff; margin: 10px; }
1212
.info { text-align: center; }
13+
.info p { margin: 5px 0; }
1314
</style>
1415
</head>
1516
<body>
@@ -20,29 +21,39 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
2021
</div>
2122
<div class="info">
2223
<p>Total Steps: <span id="total-steps">0</span></p>
24+
<p>Population Size: <span id="population-size">10</span></p>
25+
<p>Average Energy Level: <span id="average-energy">0</span></p>
26+
<p>Exploration Rate (epsilon): <span id="exploration-rate">0.2</span></p>
27+
<p>Learning Rate (alpha): <span id="learning-rate">0.1</span></p>
28+
<p>Discount Factor (gamma): <span id="gamma">0.9</span></p>
2329
</div>
2430
</div>
2531

2632
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script>
2733
<script>
28-
let GRID_SIZE = 60;
29-
let CELL_SIZE = 10;
30-
let MAX_ENERGY = 100;
31-
let POPULATION_SIZE = 10;
34+
const GRID_SIZE = 60;
35+
const CELL_SIZE = 10;
36+
const MAX_ENERGY = 100;
37+
const POPULATION_SIZE = 10;
3238
const RESOURCE_TYPES = ['food', 'water'];
3339
const THREAT_TYPES = ['predator', 'hazard'];
3440
const ACTIONS = ['up', 'down', 'left', 'right'];
3541

3642
const worldCanvas = document.getElementById('world-canvas');
3743
const worldCtx = worldCanvas.getContext('2d');
38-
const stepsCounter = document.getElementById('total-steps');
44+
const totalStepsCounter = document.getElementById('total-steps');
45+
const averageEnergyCounter = document.getElementById('average-energy');
46+
const populationSizeCounter = document.getElementById('population-size');
47+
const explorationRateCounter = document.getElementById('exploration-rate');
48+
const learningRateCounter = document.getElementById('learning-rate');
49+
const gammaCounter = document.getElementById('gamma');
3950

4051
class Environment {
4152
constructor(gridSize) {
4253
this.gridSize = gridSize;
4354
this.state = this.createState(gridSize);
44-
this.resources = this.createResources(gridSize);
45-
this.threats = this.createThreats(gridSize);
55+
this.createResources(gridSize);
56+
this.createThreats(gridSize);
4657
}
4758

4859
createState(gridSize) {
@@ -58,37 +69,31 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
5869
}
5970

6071
createResources(gridSize) {
61-
let resources = [];
6272
const resourceCount = Math.floor(gridSize * gridSize * 0.05);
6373
for (let i = 0; i < resourceCount; i++) {
6474
let type = RESOURCE_TYPES[Math.floor(Math.random() * RESOURCE_TYPES.length)];
6575
let x = Math.floor(Math.random() * gridSize);
6676
let y = Math.floor(Math.random() * gridSize);
67-
resources.push({ x, y, type });
6877
this.state[y][x] = { type: 'resource', resourceType: type };
6978
}
70-
return resources;
7179
}
7280

7381
createThreats(gridSize) {
74-
let threats = [];
7582
const threatCount = Math.floor(gridSize * gridSize * 0.03);
7683
for (let i = 0; i < threatCount; i++) {
7784
let type = THREAT_TYPES[Math.floor(Math.random() * THREAT_TYPES.length)];
7885
let x = Math.floor(Math.random() * gridSize);
7986
let y = Math.floor(Math.random() * gridSize);
80-
threats.push({ x, y, type });
8187
this.state[y][x] = { type: 'threat', threatType: type };
8288
}
83-
return threats;
8489
}
8590
}
8691

8792
class Agent {
8893
constructor(env, id) {
8994
this.env = env;
9095
this.id = id;
91-
this.position = [Math.floor(GRID_SIZE / 2), Math.floor(GRID_SIZE / 2)];
96+
this.position = [Math.floor(Math.random() * GRID_SIZE), Math.floor(Math.random() * GRID_SIZE)];
9297
this.energy = MAX_ENERGY;
9398
this.alive = true;
9499
this.qTable = {};
@@ -105,24 +110,32 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
105110
move() {
106111
if (!this.alive) return;
107112

108-
const action = this.chooseAction();
109-
let [dx, dy] = [0, 0];
110-
switch (action) {
111-
case 'up': dy = -1; break;
112-
case 'down': dy = 1; break;
113-
case 'left': dx = -1; break;
114-
case 'right': dx = 1; break;
115-
}
113+
const currentState = this.getState();
114+
const action = this.chooseAction(currentState);
115+
const [dx, dy] = this.getActionDelta(action);
116116

117117
this.updatePosition(dx, dy);
118-
this.interactWithEnvironment();
118+
const reward = this.interactWithEnvironment();
119119
this.energy -= 1; // Decrease energy on each move
120120

121+
const newState = this.getState();
122+
this.learn(currentState, action, reward, newState);
123+
121124
if (this.energy <= 0) {
122125
this.alive = false;
123126
}
124127
}
125128

129+
getActionDelta(action) {
130+
switch (action) {
131+
case 'up': return [0, -1];
132+
case 'down': return [0, 1];
133+
case 'left': return [-1, 0];
134+
case 'right': return [1, 0];
135+
default: return [0, 0];
136+
}
137+
}
138+
126139
updatePosition(dx, dy) {
127140
const newX = Math.min(Math.max(this.position[0] + dx, 0), GRID_SIZE - 1);
128141
const newY = Math.min(Math.max(this.position[1] + dy, 0), GRID_SIZE - 1);
@@ -132,17 +145,21 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
132145
interactWithEnvironment() {
133146
const [x, y] = this.position;
134147
const cell = this.env.state[y][x];
148+
let reward = -0.1; // Small penalty to encourage efficient movement
135149

136150
if (cell && cell.type === 'resource') {
137151
this.energy = Math.min(this.energy + 20, MAX_ENERGY); // Gain energy
152+
reward = 10; // Positive reward for collecting resource
138153
this.env.state[y][x] = null; // Remove resource after collection
139154
} else if (cell && cell.type === 'threat') {
140155
this.energy -= 30; // Lose energy
156+
reward = -20; // Negative reward for encountering threat
141157
}
158+
159+
return reward;
142160
}
143161

144-
chooseAction() {
145-
const state = this.getState();
162+
chooseAction(state) {
146163
if (Math.random() < this.epsilon || !this.qTable[state]) {
147164
// Explore random action
148165
return ACTIONS[Math.floor(Math.random() * ACTIONS.length)];
@@ -154,16 +171,36 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
154171

155172
getBestAction(state) {
156173
if (!this.qTable[state]) return ACTIONS[Math.floor(Math.random() * ACTIONS.length)];
157-
let bestAction = ACTIONS[0];
158-
let maxQ = this.qTable[state][bestAction] || 0;
174+
const qValues = this.qTable[state];
175+
let maxQ = -Infinity;
176+
let bestActions = [];
159177
for (let action of ACTIONS) {
160-
const qValue = this.qTable[state][action] || 0;
178+
const qValue = qValues[action] || 0;
161179
if (qValue > maxQ) {
162180
maxQ = qValue;
163-
bestAction = action;
181+
bestActions = [action];
182+
} else if (qValue === maxQ) {
183+
bestActions.push(action);
164184
}
165185
}
166-
return bestAction;
186+
// Randomly select among best actions to break ties
187+
return bestActions[Math.floor(Math.random() * bestActions.length)];
188+
}
189+
190+
learn(state, action, reward, nextState) {
191+
if (!this.qTable[state]) {
192+
this.qTable[state] = {};
193+
}
194+
if (!this.qTable[nextState]) {
195+
this.qTable[nextState] = {};
196+
}
197+
198+
const qPredict = this.qTable[state][action] || 0;
199+
const qNextMax = Math.max(...ACTIONS.map(a => this.qTable[nextState][a] || 0));
200+
const qTarget = reward + this.gamma * qNextMax;
201+
202+
// Update Q-value
203+
this.qTable[state][action] = qPredict + this.alpha * (qTarget - qPredict);
167204
}
168205
}
169206

@@ -186,7 +223,12 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
186223
run() {
187224
setInterval(() => {
188225
this.totalSteps++;
189-
stepsCounter.textContent = this.totalSteps;
226+
totalStepsCounter.textContent = this.totalSteps;
227+
populationSizeCounter.textContent = POPULATION_SIZE;
228+
explorationRateCounter.textContent = this.agents[0].epsilon.toFixed(2);
229+
learningRateCounter.textContent = this.agents[0].alpha.toFixed(2);
230+
gammaCounter.textContent = this.agents[0].gamma.toFixed(2);
231+
190232
this.update();
191233
this.draw();
192234
}, 100);
@@ -196,6 +238,11 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
196238
for (let agent of this.agents) {
197239
agent.move();
198240
}
241+
242+
// Update average energy level
243+
const totalEnergy = this.agents.reduce((sum, agent) => sum + agent.energy, 0);
244+
const averageEnergy = (totalEnergy / POPULATION_SIZE).toFixed(2);
245+
averageEnergyCounter.textContent = averageEnergy;
199246
}
200247

201248
draw() {
@@ -219,7 +266,10 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
219266
// Draw agents
220267
for (let agent of this.agents) {
221268
if (agent.alive) {
222-
worldCtx.fillStyle = 'purple';
269+
// Agent color based on energy level
270+
const energyRatio = agent.energy / MAX_ENERGY;
271+
const colorIntensity = Math.floor(energyRatio * 255);
272+
worldCtx.fillStyle = `rgb(${255 - colorIntensity}, 0, ${colorIntensity})`;
223273
worldCtx.fillRect(agent.position[0] * CELL_SIZE, agent.position[1] * CELL_SIZE, CELL_SIZE, CELL_SIZE);
224274
}
225275
}

0 commit comments

Comments
 (0)