ClementRomac's picture
ClementRomac HF staff
Added interactive demo with some policies
09a6f7f
/**
* @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();
}
}