10
10
.canvas-container { display : flex; justify-content : center; }
11
11
canvas { border : 1px solid # 999 ; background-color : # fff ; margin : 10px ; }
12
12
.info { text-align : center; }
13
+ .info p { margin : 5px 0 ; }
13
14
</ style >
14
15
</ head >
15
16
< body >
@@ -20,29 +21,39 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
20
21
</ div >
21
22
< div class ="info ">
22
23
< 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 >
23
29
</ div >
24
30
</ div >
25
31
26
32
< script src ="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest "> </ script >
27
33
< 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 ;
32
38
const RESOURCE_TYPES = [ 'food' , 'water' ] ;
33
39
const THREAT_TYPES = [ 'predator' , 'hazard' ] ;
34
40
const ACTIONS = [ 'up' , 'down' , 'left' , 'right' ] ;
35
41
36
42
const worldCanvas = document . getElementById ( 'world-canvas' ) ;
37
43
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' ) ;
39
50
40
51
class Environment {
41
52
constructor ( gridSize ) {
42
53
this . gridSize = gridSize ;
43
54
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 ) ;
46
57
}
47
58
48
59
createState ( gridSize ) {
@@ -58,37 +69,31 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
58
69
}
59
70
60
71
createResources ( gridSize ) {
61
- let resources = [ ] ;
62
72
const resourceCount = Math . floor ( gridSize * gridSize * 0.05 ) ;
63
73
for ( let i = 0 ; i < resourceCount ; i ++ ) {
64
74
let type = RESOURCE_TYPES [ Math . floor ( Math . random ( ) * RESOURCE_TYPES . length ) ] ;
65
75
let x = Math . floor ( Math . random ( ) * gridSize ) ;
66
76
let y = Math . floor ( Math . random ( ) * gridSize ) ;
67
- resources . push ( { x, y, type } ) ;
68
77
this . state [ y ] [ x ] = { type : 'resource' , resourceType : type } ;
69
78
}
70
- return resources ;
71
79
}
72
80
73
81
createThreats ( gridSize ) {
74
- let threats = [ ] ;
75
82
const threatCount = Math . floor ( gridSize * gridSize * 0.03 ) ;
76
83
for ( let i = 0 ; i < threatCount ; i ++ ) {
77
84
let type = THREAT_TYPES [ Math . floor ( Math . random ( ) * THREAT_TYPES . length ) ] ;
78
85
let x = Math . floor ( Math . random ( ) * gridSize ) ;
79
86
let y = Math . floor ( Math . random ( ) * gridSize ) ;
80
- threats . push ( { x, y, type } ) ;
81
87
this . state [ y ] [ x ] = { type : 'threat' , threatType : type } ;
82
88
}
83
- return threats ;
84
89
}
85
90
}
86
91
87
92
class Agent {
88
93
constructor ( env , id ) {
89
94
this . env = env ;
90
95
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 ) ] ;
92
97
this . energy = MAX_ENERGY ;
93
98
this . alive = true ;
94
99
this . qTable = { } ;
@@ -105,24 +110,32 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
105
110
move ( ) {
106
111
if ( ! this . alive ) return ;
107
112
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 ) ;
116
116
117
117
this . updatePosition ( dx , dy ) ;
118
- this . interactWithEnvironment ( ) ;
118
+ const reward = this . interactWithEnvironment ( ) ;
119
119
this . energy -= 1 ; // Decrease energy on each move
120
120
121
+ const newState = this . getState ( ) ;
122
+ this . learn ( currentState , action , reward , newState ) ;
123
+
121
124
if ( this . energy <= 0 ) {
122
125
this . alive = false ;
123
126
}
124
127
}
125
128
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
+
126
139
updatePosition ( dx , dy ) {
127
140
const newX = Math . min ( Math . max ( this . position [ 0 ] + dx , 0 ) , GRID_SIZE - 1 ) ;
128
141
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>
132
145
interactWithEnvironment ( ) {
133
146
const [ x , y ] = this . position ;
134
147
const cell = this . env . state [ y ] [ x ] ;
148
+ let reward = - 0.1 ; // Small penalty to encourage efficient movement
135
149
136
150
if ( cell && cell . type === 'resource' ) {
137
151
this . energy = Math . min ( this . energy + 20 , MAX_ENERGY ) ; // Gain energy
152
+ reward = 10 ; // Positive reward for collecting resource
138
153
this . env . state [ y ] [ x ] = null ; // Remove resource after collection
139
154
} else if ( cell && cell . type === 'threat' ) {
140
155
this . energy -= 30 ; // Lose energy
156
+ reward = - 20 ; // Negative reward for encountering threat
141
157
}
158
+
159
+ return reward ;
142
160
}
143
161
144
- chooseAction ( ) {
145
- const state = this . getState ( ) ;
162
+ chooseAction ( state ) {
146
163
if ( Math . random ( ) < this . epsilon || ! this . qTable [ state ] ) {
147
164
// Explore random action
148
165
return ACTIONS [ Math . floor ( Math . random ( ) * ACTIONS . length ) ] ;
@@ -154,16 +171,36 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
154
171
155
172
getBestAction ( state ) {
156
173
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 = [ ] ;
159
177
for ( let action of ACTIONS ) {
160
- const qValue = this . qTable [ state ] [ action ] || 0 ;
178
+ const qValue = qValues [ action ] || 0 ;
161
179
if ( qValue > maxQ ) {
162
180
maxQ = qValue ;
163
- bestAction = action ;
181
+ bestActions = [ action ] ;
182
+ } else if ( qValue === maxQ ) {
183
+ bestActions . push ( action ) ;
164
184
}
165
185
}
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 ) ;
167
204
}
168
205
}
169
206
@@ -186,7 +223,12 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
186
223
run ( ) {
187
224
setInterval ( ( ) => {
188
225
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
+
190
232
this . update ( ) ;
191
233
this . draw ( ) ;
192
234
} , 100 ) ;
@@ -196,6 +238,11 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
196
238
for ( let agent of this . agents ) {
197
239
agent . move ( ) ;
198
240
}
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 ;
199
246
}
200
247
201
248
draw ( ) {
@@ -219,7 +266,10 @@ <h1>DIAMOND Simulation with Resource Interaction and Learning</h1>
219
266
// Draw agents
220
267
for ( let agent of this . agents ) {
221
268
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 } )` ;
223
273
worldCtx . fillRect ( agent . position [ 0 ] * CELL_SIZE , agent . position [ 1 ] * CELL_SIZE , CELL_SIZE , CELL_SIZE ) ;
224
274
}
225
275
}
0 commit comments