/** | |
* @classdesc Class that handles the simulation. | |
*/ | |
class Game { | |
/** | |
* @constructor | |
* @param agents {{morphologies: Array, policies: Array, positions: Array}} - Morphologies, policies and positions of the agents | |
* @param cppn_input_vector {Array} - 3-dimensional array that encodes the CPPN | |
* @param water_level {number} | |
* @param creepers_width {number} | |
* @param creepers_height {number} | |
* @param creepers_spacing {number} | |
* @param smoothing {number} | |
* @param creepers_type {boolean} | |
* @param ground {Array} - List of points {x, y} composing the ground | |
* @param ceiling {Array} - List of points {x, y} composing the ceiling | |
* @param align_terrain {Object} | |
*/ | |
constructor(agents, cppn_input_vector, water_level, creepers_width, creepers_height, | |
creepers_spacing, smoothing, creepers_type, ground, ceiling, align_terrain) { | |
this.run_fps = 60; | |
this.obs = []; | |
this.rewards = []; | |
this.initWorld(agents, cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, smoothing, | |
creepers_type, ground, ceiling, align_terrain); | |
this.running = false; | |
} | |
/** | |
* Initializes the environment. | |
* @param agents {{morphologies: Array, policies: Array, positions: Array}} - Morphologies, policies and positions of the agents | |
* @param cppn_input_vector {Array} - 3-dimensional array that encodes the CPPN | |
* @param water_level {number} | |
* @param creepers_width {number} | |
* @param creepers_height {number} | |
* @param creepers_spacing {number} | |
* @param smoothing {number} | |
* @param creepers_type {boolean} | |
* @param ground {Array} - List of points {x, y} composing the ground | |
* @param ceiling {Array} - List of points {x, y} composing the ceiling | |
* @param align_terrain {Object} | |
*/ | |
initWorld(agents, cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, | |
smoothing, creepers_type, ground, ceiling, align_terrain) { | |
this.env = new MultiAgentsContinuousParkour( | |
agents, | |
3, | |
smoothing, | |
200, | |
90, | |
20, | |
creepers_type, | |
ground, | |
ceiling, | |
align_terrain); | |
this.env.set_environment(cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, smoothing, creepers_type); | |
let step_rets = this.env.reset(); | |
this.obs.push([...step_rets.map(e => e[0])]); | |
this.rewards.push([...step_rets.map(e => e[1])]); | |
} | |
/** | |
* Pauses the simulation. | |
*/ | |
pause(){ | |
clearInterval(this.runtime); | |
this.running = false; | |
} | |
/** | |
* Runs the simulation. | |
* @returns {Promise<void>} | |
*/ | |
async run(){ | |
// Loads the policy for each agent before launching the simulation | |
for(let agent of window.game.env.agents){ | |
if(agent.policy.path != null){ | |
agent.model = await tf.loadGraphModel(agent.policy.path + '/model.json'); | |
} | |
else{ | |
agent.model = null; | |
} | |
} | |
// Creates a repeated interval over time | |
this.runtime = setInterval(() => { | |
this.play(); | |
}, 1000 / this.run_fps); | |
this.running = true; | |
} | |
/** | |
* | |
* @param agents {{morphologies: Array, policies: Array, positions: Array}} - Morphologies, policies and positions of the agents | |
* @param cppn_input_vector {Array} - 3-dimensional array that encodes the CPPN | |
* @param water_level {number} | |
* @param creepers_width {number} | |
* @param creepers_height {number} | |
* @param creepers_spacing {number} | |
* @param smoothing {number} | |
* @param creepers_type {boolean} | |
* @param ground {Array} - List of points {x, y} composing the ground | |
* @param ceiling {Array} - List of points {x, y} composing the ceiling | |
* @param align_terrain {Object} | |
*/ | |
reset(agents, cppn_input_vector, water_level, creepers_width, creepers_height, | |
creepers_spacing, smoothing, creepers_type, ground, ceiling, align_terrain){ | |
this.pause(); | |
let zoom = window.game.env.zoom; | |
let scroll = [...window.game.env.scroll]; | |
this.initWorld(agents, cppn_input_vector, water_level, creepers_width, creepers_height, creepers_spacing, smoothing, | |
creepers_type, ground, ceiling, align_terrain); | |
// Keeps the previous zoom and scroll | |
window.game.env.set_zoom(zoom); | |
window.game.env.set_scroll(null, scroll[0], scroll[1]); | |
this.env.render(); | |
} | |
/** | |
* Plays one simulation step. | |
*/ | |
play() { | |
// Gets the actions to execute for each agent | |
for(let agent of window.game.env.agents){ | |
let state = this.obs[this.obs.length - 1][agent.id]; | |
// Generates the actions thanks to the agent's policy model | |
if(agent.model != null){ | |
let envState = tf.tensor(state,[1, state.length]); | |
let inputs = { | |
"Placeholder_1:0": envState | |
}; | |
let output = 'main/mul:0' | |
agent.actions = agent.model.execute(inputs, output).arraySync()[0]; | |
} | |
// Generates random actions | |
else /*if(agent.policy.name == "random")*/{ | |
agent.actions = Array.from({length: agent.agent_body.get_action_size()}, () => Math.random() * 2 - 1); | |
} | |
// Generates motionless actions | |
/*else{ | |
agent.actions = Array.from({length: agent.agent_body.get_action_size()}, () => 0); | |
}*/ | |
} | |
// Runs one step and stores the resulted states for each agent | |
let step_rets = this.env.step(); | |
this.obs.push([...step_rets.map(e => e[0])]); | |
this.rewards.push([...step_rets.map(e => e[1])]); | |
this.env.render(); | |
} | |
} | |