mirror of
https://github.com/wassname/rl_2d_walker.js.git
synced 2026-09-09 11:33:20 +08:00
Initial commit.
This commit is contained in:
+112
@@ -0,0 +1,112 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
font-size: 10px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
h4:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
select {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#main_holder {
|
||||
width: 800px;
|
||||
height: auto;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
#main_screen {
|
||||
border: 1px solid #888;
|
||||
}
|
||||
|
||||
#info {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info>div {
|
||||
vertical-align: top;
|
||||
margin-right: 15px;
|
||||
display: inline-block;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.name_list_table {
|
||||
border-collapse: collapse;
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.name_list_table td, .name_list_table th {
|
||||
border: 1px solid #888;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
.name_list_table .name {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.name_list_table .elite_name {
|
||||
color: #b40;
|
||||
}
|
||||
|
||||
.name_list_table .score {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.name_list_table .generation {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#hidden_ss {
|
||||
height: 0;
|
||||
width: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#generation_timer {
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
#generation_timer_bar {
|
||||
background-color: #bbf;
|
||||
height: 100%;
|
||||
width: 0;
|
||||
font-size: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML5 Genetic Algorithm Biped Walkers</title>
|
||||
<link rel="stylesheet" href="css/walkers.css" type="text/css" />
|
||||
<script src="js/jsbox2d.js"></script>
|
||||
<script src="js/walker.js"></script>
|
||||
<script src="js/game.js"></script>
|
||||
<script src="js/floor.js"></script>
|
||||
<script src="js/draw.js"></script>
|
||||
<script src="js/interface.js"></script>
|
||||
<script>
|
||||
|
||||
function init() {
|
||||
gameInit();
|
||||
}
|
||||
|
||||
window.addEventListener("load", init, false);
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="main_holder">
|
||||
<h1>Genetic Algorithm Walkers</h1>
|
||||
<h3 id="page_quote">"It's like watching other people QWOP"</h3>
|
||||
<canvas id="main_screen" width="800" height="350"></canvas>
|
||||
<div id="generation_timer"><div id="generation_timer_bar"> </div></div>
|
||||
|
||||
<div id="info">
|
||||
|
||||
<div>
|
||||
<h2>Current Generation (<span id="gen_number">0</span>)</h2>
|
||||
<table class="name_list_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Score</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="name_list">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Record History</h2>
|
||||
<table class="name_list_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Gen</th>
|
||||
<th>Name</th>
|
||||
<th>Score</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="champ_list">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="controls">
|
||||
<h2>Controls</h2>
|
||||
Gene mutation probability
|
||||
<select id="mutation_chance">
|
||||
<option value="0">0%</option>
|
||||
<option value="0.01">1%</option>
|
||||
<option value="0.05">5%</option>
|
||||
<option value="0.1">10%</option>
|
||||
<option value="0.25">25%</option>
|
||||
<option value="0.5">50%</option>
|
||||
<option value="0.75">75%</option>
|
||||
<option value="1">100%</option>
|
||||
</select><br />
|
||||
Gene mutation amount
|
||||
<select id="mutation_amount">
|
||||
<option value="0">0%</option>
|
||||
<option value="0.01">1%</option>
|
||||
<option value="0.05">5%</option>
|
||||
<option value="0.1">10%</option>
|
||||
<option value="0.25">25%</option>
|
||||
<option value="0.5">50%</option>
|
||||
<option value="0.75">75%</option>
|
||||
<option value="1">100%</option>
|
||||
</select><br />
|
||||
Champions to copy
|
||||
<select id="elite_clones"></select><br />
|
||||
Motor noise
|
||||
<select id="motor_noise">
|
||||
<option value="0">0%</option>
|
||||
<option value="0.01">1%</option>
|
||||
<option value="0.02">2%</option>
|
||||
<option value="0.03">3%</option>
|
||||
<option value="0.04">4%</option>
|
||||
<option value="0.05">5%</option>
|
||||
<option value="0.1">10%</option>
|
||||
</select><br />
|
||||
Round length
|
||||
<select id="round_length">
|
||||
<option value="300">Very short</option>
|
||||
<option value="600">Short</option>
|
||||
<option value="1200">Regular</option>
|
||||
<option value="1800">Long</option>
|
||||
<option value="2400">Looooong</option>
|
||||
</select><br />
|
||||
Animation quality
|
||||
<select id="draw_fps">
|
||||
<option value="0">none</option>
|
||||
<option value="10">10 fps</option>
|
||||
<option value="30">30 fps</option>
|
||||
<option value="60">60 fps</option>
|
||||
</select><br />
|
||||
Simulation speed
|
||||
<select id="simulation_fps">
|
||||
<option value="0">Pause</option>
|
||||
<option value="30">30</option>
|
||||
<option value="60">60</option>
|
||||
<option value="120">120</option>
|
||||
<option value="1000">1000</option>
|
||||
</select><br />
|
||||
<br />
|
||||
Lower the animation quality and simulation speed to save some CPU.<br /><br />
|
||||
Zero frames per second and high simulation speed will give you the fastest results, but processor usage will go up as well.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
drawInit = function() {
|
||||
globals.main_screen = document.getElementById("main_screen");
|
||||
globals.ctx = main_screen.getContext("2d");
|
||||
resetCamera();
|
||||
}
|
||||
|
||||
resetCamera = function() {
|
||||
globals.zoom = config.max_zoom_factor;
|
||||
globals.translate_x = 0;
|
||||
globals.translate_y = 280;
|
||||
}
|
||||
|
||||
setFps = function(fps) {
|
||||
config.draw_fps = fps;
|
||||
if(globals.draw_interval)
|
||||
clearInterval(globals.draw_interval);
|
||||
if(fps > 0 && config.simulation_fps > 0) {
|
||||
globals.draw_interval = setInterval(drawFrame, Math.round(1000/config.draw_fps));
|
||||
}
|
||||
}
|
||||
|
||||
drawFrame = function() {
|
||||
var minmax = getMinMaxDistance();
|
||||
globals.target_zoom = Math.min(config.max_zoom_factor, getZoom(minmax.min_x, minmax.max_x + 4, minmax.min_y + 2, minmax.max_y + 2.5));
|
||||
globals.zoom += 0.1*(globals.target_zoom - globals.zoom);
|
||||
globals.translate_x += 0.1*(1.5-minmax.min_x - globals.translate_x);
|
||||
globals.translate_y += 0.3*(minmax.min_y*globals.zoom + 280 - globals.translate_y);
|
||||
//globals.translate_y = minmax.max_y*globals.zoom + 150;
|
||||
globals.ctx.clearRect(0, 0, globals.main_screen.width, globals.main_screen.height);
|
||||
globals.ctx.save();
|
||||
globals.ctx.translate(globals.translate_x*globals.zoom, globals.translate_y);
|
||||
globals.ctx.scale(globals.zoom, -globals.zoom);
|
||||
drawFloor();
|
||||
for(var k = config.population_size - 1; k >= 0 ; k--) {
|
||||
if(globals.walkers[k].health > 0) {
|
||||
drawWalker(globals.walkers[k]);
|
||||
}
|
||||
}
|
||||
globals.ctx.restore();
|
||||
}
|
||||
|
||||
drawFloor = function() {
|
||||
globals.ctx.strokeStyle = "#444";
|
||||
globals.ctx.lineWidth = 1/globals.zoom;
|
||||
globals.ctx.beginPath();
|
||||
var floor_fixture = globals.floor.GetFixtureList();
|
||||
globals.ctx.moveTo(floor_fixture.m_shape.m_vertices[0].x, floor_fixture.m_shape.m_vertices[0].y);
|
||||
for(var k = 1; k < floor_fixture.m_shape.m_vertices.length; k++) {
|
||||
globals.ctx.lineTo(floor_fixture.m_shape.m_vertices[k].x, floor_fixture.m_shape.m_vertices[k].y);
|
||||
}
|
||||
globals.ctx.stroke();
|
||||
}
|
||||
|
||||
drawWalker = function(walker) {
|
||||
if(walker.is_elite) {
|
||||
//globals.ctx.strokeStyle = "hsl(22,"+100*walker.health/config.walker_health+"%,35%)";
|
||||
// globals.ctx.fillStyle = "hsl(20,"+45*walker.health/config.walker_health+"%,85%)";
|
||||
globals.ctx.strokeStyle = "hsl(22,100%,"+(90-55*walker.health/config.walker_health)+"%)";
|
||||
globals.ctx.fillStyle = "hsl(20,45%,"+(100-15*walker.health/config.walker_health)+"%)";
|
||||
} else {
|
||||
//globals.ctx.strokeStyle = "hsl(240,"+100*walker.health/config.walker_health+"%,41%)";
|
||||
// globals.ctx.fillStyle = "hsl(240,"+17*walker.health/config.walker_health+"%,85%)";
|
||||
globals.ctx.strokeStyle = "hsl(240,100%,"+(90-49*walker.health/config.walker_health)+"%)";
|
||||
globals.ctx.fillStyle = "hsl(240,45%,"+(100-15*walker.health/config.walker_health)+"%)";
|
||||
}
|
||||
globals.ctx.lineWidth = 1/globals.zoom;
|
||||
|
||||
// left legs and arms first
|
||||
drawRect(walker.left_arm.lower_arm);
|
||||
drawRect(walker.left_arm.upper_arm);
|
||||
drawRect(walker.left_leg.foot);
|
||||
drawRect(walker.left_leg.lower_leg);
|
||||
drawRect(walker.left_leg.upper_leg);
|
||||
|
||||
// head
|
||||
drawRect(walker.head.neck);
|
||||
drawRect(walker.head.head);
|
||||
|
||||
// torso
|
||||
drawRect(walker.torso.lower_torso);
|
||||
drawRect(walker.torso.upper_torso);
|
||||
|
||||
// right legs and arms
|
||||
drawRect(walker.right_leg.upper_leg);
|
||||
drawRect(walker.right_leg.lower_leg);
|
||||
drawRect(walker.right_leg.foot);
|
||||
drawRect(walker.right_arm.upper_arm);
|
||||
drawRect(walker.right_arm.lower_arm);
|
||||
}
|
||||
|
||||
drawRect = function(body) {
|
||||
// set strokestyle and fillstyle before call
|
||||
globals.ctx.beginPath();
|
||||
var fixture = body.GetFixtureList();
|
||||
var shape = fixture.GetShape();
|
||||
var p0 = body.GetWorldPoint(shape.m_vertices[0]);
|
||||
globals.ctx.moveTo(p0.x, p0.y);
|
||||
for(var k = 1; k < 4; k++) {
|
||||
var p = body.GetWorldPoint(shape.m_vertices[k]);
|
||||
globals.ctx.lineTo(p.x, p.y);
|
||||
}
|
||||
globals.ctx.lineTo(p0.x, p0.y);
|
||||
|
||||
globals.ctx.fill();
|
||||
globals.ctx.stroke();
|
||||
}
|
||||
|
||||
drawTest = function() {
|
||||
globals.ctx.strokeStyle = "#000";
|
||||
globals.ctx.fillStyle = "#666";
|
||||
globals.ctx.lineWidth = 1;
|
||||
globals.ctx.beginPath();
|
||||
globals.ctx.moveTo(0, 0);
|
||||
globals.ctx.lineTo(0, 2);
|
||||
globals.ctx.lineTo(2, 2);
|
||||
|
||||
globals.ctx.fill();
|
||||
globals.ctx.stroke();
|
||||
|
||||
}
|
||||
|
||||
getMinMaxDistance = function() {
|
||||
var min_x = 9999;
|
||||
var max_x = -1;
|
||||
var min_y = 9999;
|
||||
var max_y = -1;
|
||||
for(var k = 0; k < globals.walkers.length; k++) {
|
||||
if(globals.walkers[k].health > 0) {
|
||||
var dist = globals.walkers[k].torso.upper_torso.GetPosition();
|
||||
min_x = Math.min(min_x, dist.x);
|
||||
max_x = Math.max(max_x, dist.x);
|
||||
min_y = Math.min(min_y, globals.walkers[k].low_foot_height, globals.walkers[k].head_height);
|
||||
max_y = Math.max(max_y, dist.y);
|
||||
}
|
||||
}
|
||||
return {min_x:min_x, max_x:max_x, min_y:min_y, max_y:max_y};
|
||||
}
|
||||
|
||||
getZoom = function(min_x, max_x, min_y, max_y) {
|
||||
var delta_x = Math.abs(max_x - min_x);
|
||||
var delta_y = Math.abs(max_y - min_y);
|
||||
var zoom = Math.min(globals.main_screen.width/delta_x,globals.main_screen.height/delta_y);
|
||||
return zoom;
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
function createFloor() {
|
||||
var body_def = new b2.BodyDef();
|
||||
var body = globals.world.CreateBody(body_def);
|
||||
var fix_def = new b2.FixtureDef();
|
||||
fix_def.friction = 0.8;
|
||||
fix_def.shape = new b2.ChainShape();
|
||||
|
||||
// start with flat floor
|
||||
var edges = [
|
||||
new b2.Vec2(-3.5, -0.16),
|
||||
new b2.Vec2(2.5, -0.16)
|
||||
];
|
||||
|
||||
for(var k = 2; k < config.max_floor_tiles; k++) {
|
||||
var ratio = k/config.max_floor_tiles;
|
||||
edges.push(new b2.Vec2(edges[edges.length-1].x + (1 + ratio * Math.random() - ratio/2), edges[edges.length-1].y + (ratio * Math.random() - ratio/2 )));
|
||||
// edges.push(new b2.Vec2(edges[edges.length-1].x + 1,-0.16));
|
||||
}
|
||||
fix_def.shape.CreateChain(edges, edges.length);
|
||||
body.CreateFixture(fix_def);
|
||||
return body;
|
||||
}
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
config = {
|
||||
time_step: 60,
|
||||
simulation_fps: 60,
|
||||
draw_fps: 60,
|
||||
velocity_iterations: 8,
|
||||
position_iterations: 3,
|
||||
max_zoom_factor: 130,
|
||||
min_motor_speed: -2,
|
||||
max_motor_speed: 2,
|
||||
population_size: 20,
|
||||
mutation_chance: 0.1,
|
||||
mutation_amount: 0.5,
|
||||
walker_health: 300,
|
||||
fitness_criterium: 'score',
|
||||
check_health: true,
|
||||
elite_clones: 2,
|
||||
max_floor_tiles: 50,
|
||||
round_length: 1200,
|
||||
min_body_delta: 1.4,
|
||||
min_leg_delta: 0.4,
|
||||
instadeath_delta: 0.4
|
||||
};
|
||||
|
||||
globals = {};
|
||||
|
||||
gameInit = function() {
|
||||
interfaceSetup();
|
||||
|
||||
globals.world = new b2.World(new b2.Vec2(0, -10));
|
||||
globals.walkers = createPopulation();
|
||||
|
||||
globals.floor = createFloor();
|
||||
drawInit();
|
||||
|
||||
globals.step_counter = 0;
|
||||
globals.simulation_interval = setInterval(simulationStep, Math.round(1000/config.simulation_fps));
|
||||
globals.draw_interval = setInterval(drawFrame, Math.round(1000/config.draw_fps));
|
||||
}
|
||||
|
||||
simulationStep = function() {
|
||||
globals.world.Step(1/config.time_step, config.velocity_iterations, config.position_iterations);
|
||||
globals.world.ClearForces();
|
||||
populationSimulationStep();
|
||||
if(typeof globals.step_counter == 'undefined') {
|
||||
globals.step_counter = 0;
|
||||
} else {
|
||||
globals.step_counter++;
|
||||
}
|
||||
document.getElementById("generation_timer_bar").style.width = (100*globals.step_counter/config.round_length)+"%";
|
||||
if(globals.step_counter > config.round_length) {
|
||||
nextGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
setSimulationFps = function(fps) {
|
||||
config.simulation_fps = fps;
|
||||
clearInterval(globals.simulation_interval);
|
||||
if(fps > 0) {
|
||||
globals.simulation_interval = setInterval(simulationStep, Math.round(1000/config.simulation_fps));
|
||||
if(globals.paused) {
|
||||
globals.paused = false;
|
||||
if(config.draw_fps > 0) {
|
||||
globals.draw_interval = setInterval(drawFrame, Math.round(1000/config.draw_fps));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// pause the drawing as well
|
||||
clearInterval(globals.draw_interval);
|
||||
globals.paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
createPopulation = function(genomes) {
|
||||
setQuote();
|
||||
if(typeof globals.generation_count == 'undefined') {
|
||||
globals.generation_count = 0;
|
||||
} else {
|
||||
globals.generation_count++;
|
||||
}
|
||||
updateGeneration(globals.generation_count);
|
||||
var walkers = [];
|
||||
for(var k = 0; k < config.population_size; k++) {
|
||||
if(genomes && genomes[k]) {
|
||||
walkers.push(new Walker(globals.world, genomes[k]));
|
||||
} else {
|
||||
walkers.push(new Walker(globals.world));
|
||||
}
|
||||
if(globals.generation_count > 0 && k < config.elite_clones) {
|
||||
walkers[walkers.length - 1].is_elite = true;
|
||||
} else {
|
||||
walkers[walkers.length - 1].is_elite = false;
|
||||
}
|
||||
}
|
||||
return walkers;
|
||||
}
|
||||
|
||||
populationSimulationStep = function() {
|
||||
var dead_dudes = 0;
|
||||
for(var k = 0; k < config.population_size; k++) {
|
||||
if(globals.walkers[k].health > 0) {
|
||||
globals.walkers[k].simulationStep();
|
||||
} else {
|
||||
if(!globals.walkers[k].is_dead) {
|
||||
for(var l = 0; l < globals.walkers[k].bodies.length; l++) {
|
||||
if(globals.walkers[k].bodies[l]) {
|
||||
globals.world.DestroyBody(globals.walkers[k].bodies[l]);
|
||||
globals.walkers[k].bodies[l] = null;
|
||||
}
|
||||
}
|
||||
globals.walkers[k].is_dead = true;
|
||||
}
|
||||
dead_dudes++;
|
||||
}
|
||||
}
|
||||
printNames(globals.walkers);
|
||||
if(dead_dudes >= config.population_size) {
|
||||
nextGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
nextGeneration = function() {
|
||||
if(globals.simulation_interval)
|
||||
clearInterval(globals.simulation_interval);
|
||||
if(globals.draw_interval)
|
||||
clearInterval(globals.draw_interval);
|
||||
getInterfaceValues();
|
||||
var genomes = createNewGenerationGenomes();
|
||||
killGeneration();
|
||||
globals.walkers = createPopulation(genomes);
|
||||
resetCamera();
|
||||
globals.step_counter = 0;
|
||||
globals.simulation_interval = setInterval(simulationStep, Math.round(1000/config.simulation_fps));
|
||||
if(config.draw_fps > 0) {
|
||||
globals.draw_interval = setInterval(drawFrame, Math.round(1000/config.draw_fps));
|
||||
}
|
||||
}
|
||||
|
||||
killGeneration = function() {
|
||||
for(var k = 0; k < globals.walkers.length; k++) {
|
||||
for(var l = 0; l < globals.walkers[k].bodies.length; l++) {
|
||||
if(globals.walkers[k].bodies[l])
|
||||
globals.world.DestroyBody(globals.walkers[k].bodies[l]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createNewGenerationGenomes = function() {
|
||||
globals.walkers.sort(function(a,b) {
|
||||
return b[config.fitness_criterium] - a[config.fitness_criterium];
|
||||
});
|
||||
if(typeof globals.last_record == 'undefined') {
|
||||
globals.last_record = 0;
|
||||
}
|
||||
if(globals.walkers[0][config.fitness_criterium] > globals.last_record) {
|
||||
printChampion(globals.walkers[0]);
|
||||
globals.last_record = globals.walkers[0][config.fitness_criterium];
|
||||
}
|
||||
|
||||
var genomes = [];
|
||||
var parents = null;
|
||||
// clones
|
||||
for(var k = 0; k < config.elite_clones; k++) {
|
||||
genomes.push(globals.walkers[k].genome);
|
||||
}
|
||||
for(var k = config.elite_clones; k < config.population_size; k++) {
|
||||
if(parents = pickParents()) {
|
||||
genomes.push(copulate(globals.walkers[parents[0]], globals.walkers[parents[1]]));
|
||||
}
|
||||
}
|
||||
genomes = mutateClones(genomes);
|
||||
return genomes;
|
||||
}
|
||||
|
||||
pickParents = function() {
|
||||
var parents = [];
|
||||
for(var k = 0; k < config.population_size; k++) {
|
||||
if(Math.random() < (1/(k+2))) {
|
||||
parents.push(k);
|
||||
if(parents.length >= 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(typeof parents[0] == 'undefined' || typeof parents[1] == 'undefined') {
|
||||
return false;
|
||||
}
|
||||
return parents;
|
||||
}
|
||||
|
||||
copulate = function(walker_1, walker_2) {
|
||||
var new_genome = [];
|
||||
for(var k = 0; k < walker_1.genome.length; k++) {
|
||||
if(Math.random() < 0.5) {
|
||||
var parent = walker_1;
|
||||
} else {
|
||||
var parent = walker_2
|
||||
}
|
||||
var new_gene = JSON.parse(JSON.stringify(parent.genome[k]));
|
||||
for(var g in walker_1.genome[k]) {
|
||||
if(walker_1.genome[k].hasOwnProperty(g)) {
|
||||
if(Math.random() < config.mutation_chance) {
|
||||
if(g.indexOf('target') >= 0) {
|
||||
new_gene[g] = Math.floor(Math.random() * walker_1.bodies.length);
|
||||
} else {
|
||||
new_gene[g] = new_gene[g] * (1 + config.mutation_amount*(Math.random()*2 - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
new_genome[k] = new_gene;
|
||||
}
|
||||
return new_genome;
|
||||
}
|
||||
|
||||
mutateClones = function(genomes) {
|
||||
if(parseFloat(config.mutation_chance) == 0) {
|
||||
return genomes;
|
||||
}
|
||||
|
||||
for(var k = 0; k < genomes.length; k++) {
|
||||
var current = JSON.stringify(genomes[k]);
|
||||
for(var l = k + 1; l < genomes.length; l++) {
|
||||
if(current == JSON.stringify(genomes[l])) {
|
||||
var to_mutate = Math.floor(Math.random() * genomes[l].length);
|
||||
for(var g in genomes[l][to_mutate]) {
|
||||
if(genomes[l][to_mutate].hasOwnProperty(g)) {
|
||||
if(g.indexOf('target') < 0) {
|
||||
genomes[l][to_mutate][g] = genomes[l][to_mutate][g] * (1 + config.mutation_amount*(Math.random()*2 - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return genomes;
|
||||
}
|
||||
|
||||
getInterfaceValues = function() {
|
||||
config.elite_clones = document.getElementById("elite_clones").value;
|
||||
config.mutation_chance = document.getElementById("mutation_chance").value
|
||||
config.mutation_amount = document.getElementById("mutation_amount").value
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
quotes = [
|
||||
"The Ministry of Silly Walks on steroids",
|
||||
"It's like watching other people QWOP",
|
||||
"Keep tumbling",
|
||||
"As seen on a negative comment on Reddit",
|
||||
"The Walking Sad",
|
||||
"The Walking Fad",
|
||||
"Army of QWOP",
|
||||
"Nice me-and-my-friends-leaving-the-bar-at-2am simulator!"
|
||||
];
|
||||
|
||||
printNames = function(walkers) {
|
||||
var name_list = document.getElementById("name_list");
|
||||
name_list.innerHTML = "";
|
||||
for(var k = 0; k < walkers.length; k++) {
|
||||
var tr = document.createElement("TR");
|
||||
if(walkers[k].is_elite) {
|
||||
tr.className = "elite_name";
|
||||
}
|
||||
var td = document.createElement("TD");
|
||||
td.className = "name";
|
||||
td.appendChild(document.createTextNode(walkers[k].name));
|
||||
tr.appendChild(td);
|
||||
|
||||
td = document.createElement("TD");
|
||||
td.className = "score";
|
||||
td.appendChild(document.createTextNode(walkers[k][config.fitness_criterium].toFixed(2)));
|
||||
tr.appendChild(td);
|
||||
name_list.appendChild(tr);
|
||||
}
|
||||
}
|
||||
|
||||
printChampion = function(walker) {
|
||||
var champ_list = document.getElementById("champ_list");
|
||||
var tr = document.createElement("TR");
|
||||
|
||||
var cur_rows = champ_list.getElementsByTagName("TR");
|
||||
if(cur_rows.length >= config.population_size) {
|
||||
champ_list.removeChild(cur_rows[0]);
|
||||
}
|
||||
|
||||
var td = document.createElement("TD");
|
||||
td.className = "generation";
|
||||
td.appendChild(document.createTextNode(globals.generation_count));
|
||||
tr.appendChild(td);
|
||||
|
||||
td = document.createElement("TD");
|
||||
td.className = "name";
|
||||
td.appendChild(document.createTextNode(walker.name));
|
||||
tr.appendChild(td);
|
||||
|
||||
td = document.createElement("TD");
|
||||
td.className = "score";
|
||||
td.appendChild(document.createTextNode(walker[config.fitness_criterium].toFixed(2)));
|
||||
tr.appendChild(td);
|
||||
|
||||
champ_list.appendChild(tr);
|
||||
}
|
||||
|
||||
updateGeneration = function(number) {
|
||||
document.getElementById("gen_number").innerHTML = number;
|
||||
}
|
||||
|
||||
setQuote = function() {
|
||||
document.getElementById("page_quote").innerHTML = '"'+quotes[Math.floor(Math.random() * quotes.length)]+'"';
|
||||
}
|
||||
|
||||
interfaceSetup = function() {
|
||||
var mut_chance_sel = document.getElementById("mutation_chance");
|
||||
for(var k = 0; k < mut_chance_sel.options.length; k++) {
|
||||
if(mut_chance_sel.options[k].value == config.mutation_chance) {
|
||||
mut_chance_sel.options[k].selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var mut_amount_sel = document.getElementById("mutation_amount");
|
||||
for(var k = 0; k < mut_amount_sel.options.length; k++) {
|
||||
if(mut_amount_sel.options[k].value == config.mutation_amount) {
|
||||
mut_amount_sel.options[k].selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var elite_clones_sel = document.getElementById("elite_clones");
|
||||
for(var k = 0; k <= config.population_size; k++) {
|
||||
var option = document.createElement("OPTION");
|
||||
option.value = k;
|
||||
option.label = k;
|
||||
if(k == config.elite_clones) {
|
||||
option.selected = true;
|
||||
}
|
||||
elite_clones_sel.appendChild(option);
|
||||
}
|
||||
|
||||
var round_length_sel = document.getElementById("round_length");
|
||||
for(var k = 0; k <= round_length_sel.options.length; k++) {
|
||||
if(round_length_sel.options[k].value == config.round_length) {
|
||||
round_length_sel.options[k].selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
round_length_sel.onchange = function() {
|
||||
config.round_length = round_length_sel.value;
|
||||
}
|
||||
|
||||
var fps_sel = document.getElementById("draw_fps");
|
||||
for(var k = 0; k < fps_sel.options.length; k++) {
|
||||
if(fps_sel.options[k].value == config.draw_fps) {
|
||||
fps_sel.options[k].selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fps_sel.onchange = function() {
|
||||
setFps(fps_sel.value);
|
||||
}
|
||||
|
||||
var simulation_fps_sel = document.getElementById("simulation_fps");
|
||||
for(var k = 0; k < simulation_fps_sel.options.length; k++) {
|
||||
if(simulation_fps_sel.options[k].value == config.simulation_fps) {
|
||||
simulation_fps_sel.options[k].selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
simulation_fps_sel.onchange = function() {
|
||||
setSimulationFps(simulation_fps_sel.value);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
+423
@@ -0,0 +1,423 @@
|
||||
// walker has fixed shapes and structures
|
||||
// shape definitions are in the constructor
|
||||
|
||||
|
||||
var Walker = function() {
|
||||
this.__constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Walker.prototype.__constructor = function(world, genome) {
|
||||
|
||||
this.world = globals.world;
|
||||
|
||||
this.density = 106.2; // common for all fixtures, no reason to be too specific
|
||||
|
||||
this.max_distance = -5;
|
||||
this.health = config.walker_health;
|
||||
this.score = 0;
|
||||
this.low_foot_height = 0;
|
||||
this.head_height = 0;
|
||||
this.steps = 0;
|
||||
|
||||
this.bd = new b2.BodyDef();
|
||||
this.bd.type = b2.Body.b2_dynamicBody;
|
||||
this.bd.linearDamping = 0;
|
||||
this.bd.angularDamping = 0.01;
|
||||
this.bd.allowSleep = true;
|
||||
this.bd.awake = true;
|
||||
|
||||
this.fd = new b2.FixtureDef();
|
||||
this.fd.density = this.density;
|
||||
this.fd.restitution = 0.1;
|
||||
this.fd.shape = new b2.PolygonShape();
|
||||
this.fd.filter.groupIndex = -1;
|
||||
|
||||
this.torso_def = {
|
||||
upper_width: 0.25,
|
||||
upper_height: 0.45,
|
||||
lower_width: 0.25,
|
||||
lower_height: 0.2
|
||||
};
|
||||
|
||||
this.leg_def = {
|
||||
femur_width: 0.18,
|
||||
femur_length: 0.45,
|
||||
tibia_width: 0.13,
|
||||
tibia_length: 0.38,
|
||||
foot_height: 0.08,
|
||||
foot_length: 0.28
|
||||
};
|
||||
|
||||
this.arm_def = {
|
||||
arm_width: 0.12,
|
||||
arm_length: 0.37,
|
||||
forearm_width: 0.1,
|
||||
forearm_length: 0.42
|
||||
}
|
||||
|
||||
this.head_def = {
|
||||
head_width: 0.22,
|
||||
head_height: 0.22,
|
||||
neck_width: 0.1,
|
||||
neck_height: 0.08
|
||||
}
|
||||
|
||||
this.joints = [];
|
||||
|
||||
this.torso = this.createTorso();
|
||||
this.left_leg = this.createLeg();
|
||||
this.right_leg = this.createLeg();
|
||||
this.left_arm = this.createArm();
|
||||
this.right_arm = this.createArm();
|
||||
this.head = this.createHead();
|
||||
this.connectParts();
|
||||
|
||||
this.bodies = this.getBodies();
|
||||
|
||||
if(genome) {
|
||||
this.genome = JSON.parse(JSON.stringify(genome));
|
||||
} else {
|
||||
this.genome = this.createGenome(this.joints, this.bodies);
|
||||
}
|
||||
|
||||
this.name = this.makeName(this.genome);
|
||||
}
|
||||
|
||||
Walker.prototype.createTorso = function() {
|
||||
// upper torso
|
||||
this.bd.position.Set(0.5 - this.leg_def.foot_length/2 + this.leg_def.tibia_width/2, this.leg_def.foot_height/2 + this.leg_def.foot_height/2 + this.leg_def.tibia_length + this.leg_def.femur_length + this.torso_def.lower_height + this.torso_def.upper_height/2);
|
||||
var upper_torso = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.torso_def.upper_width/2, this.torso_def.upper_height/2);
|
||||
upper_torso.CreateFixture(this.fd);
|
||||
|
||||
// lower torso
|
||||
this.bd.position.Set(0.5 - this.leg_def.foot_length/2 + this.leg_def.tibia_width/2, this.leg_def.foot_height/2 + this.leg_def.foot_height/2 + this.leg_def.tibia_length + this.leg_def.femur_length + this.torso_def.lower_height/2);
|
||||
var lower_torso = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.torso_def.lower_width/2, this.torso_def.lower_height/2);
|
||||
lower_torso.CreateFixture(this.fd);
|
||||
|
||||
// torso joint
|
||||
var jd = new b2.RevoluteJointDef();
|
||||
var position = upper_torso.GetPosition().Clone();
|
||||
position.y -= this.torso_def.upper_height/2;
|
||||
position.x -= this.torso_def.lower_width/3;
|
||||
jd.Initialize(upper_torso, lower_torso, position);
|
||||
jd.lowerAngle = -Math.PI/18;
|
||||
jd.upperAngle = Math.PI/10;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 250;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
return {upper_torso: upper_torso, lower_torso: lower_torso};
|
||||
}
|
||||
|
||||
Walker.prototype.createLeg = function() {
|
||||
// upper leg
|
||||
this.bd.position.Set(0.5 - this.leg_def.foot_length/2 + this.leg_def.tibia_width/2, this.leg_def.foot_height/2 + this.leg_def.foot_height/2 + this.leg_def.tibia_length + this.leg_def.femur_length/2);
|
||||
var upper_leg = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.leg_def.femur_width/2, this.leg_def.femur_length/2);
|
||||
upper_leg.CreateFixture(this.fd);
|
||||
|
||||
// lower leg
|
||||
this.bd.position.Set(0.5 - this.leg_def.foot_length/2 + this.leg_def.tibia_width/2, this.leg_def.foot_height/2 + this.leg_def.foot_height/2 + this.leg_def.tibia_length/2);
|
||||
var lower_leg = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.leg_def.tibia_width/2, this.leg_def.tibia_length/2);
|
||||
lower_leg.CreateFixture(this.fd);
|
||||
|
||||
// foot
|
||||
this.bd.position.Set(0.5, this.leg_def.foot_height/2);
|
||||
var foot = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.leg_def.foot_length/2, this.leg_def.foot_height/2);
|
||||
foot.CreateFixture(this.fd);
|
||||
|
||||
// leg joints
|
||||
var jd = new b2.RevoluteJointDef();
|
||||
var position = upper_leg.GetPosition().Clone();
|
||||
position.y -= this.leg_def.femur_length/2;
|
||||
position.x += this.leg_def.femur_width/4;
|
||||
jd.Initialize(upper_leg, lower_leg, position);
|
||||
jd.lowerAngle = -1.4;
|
||||
jd.upperAngle = 0;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 160;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
// foot joint
|
||||
var position = lower_leg.GetPosition().Clone();
|
||||
position.y -= this.leg_def.tibia_length/2;
|
||||
jd.Initialize(lower_leg, foot, position);
|
||||
jd.lowerAngle = -Math.PI/5;
|
||||
jd.upperAngle = Math.PI/6;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 70;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
return {upper_leg: upper_leg, lower_leg: lower_leg, foot:foot};
|
||||
}
|
||||
|
||||
Walker.prototype.createArm = function() {
|
||||
// upper arm
|
||||
this.bd.position.Set(0.5 - this.leg_def.foot_length/2 + this.leg_def.tibia_width/2, this.leg_def.foot_height/2 + this.leg_def.foot_height/2 + this.leg_def.tibia_length + this.leg_def.femur_length + this.torso_def.lower_height + this.torso_def.upper_height - this.arm_def.arm_length/2);
|
||||
var upper_arm = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.arm_def.arm_width/2, this.arm_def.arm_length/2);
|
||||
upper_arm.CreateFixture(this.fd);
|
||||
|
||||
// lower arm
|
||||
this.bd.position.Set(0.5 - this.leg_def.foot_length/2 + this.leg_def.tibia_width/2, this.leg_def.foot_height/2 + this.leg_def.foot_height/2 + this.leg_def.tibia_length + this.leg_def.femur_length + this.torso_def.lower_height + this.torso_def.upper_height - this.arm_def.arm_length - this.arm_def.forearm_length/2);
|
||||
var lower_arm = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.arm_def.forearm_width/2, this.arm_def.forearm_length/2);
|
||||
lower_arm.CreateFixture(this.fd);
|
||||
|
||||
// arm joint
|
||||
var jd = new b2.RevoluteJointDef();
|
||||
var position = upper_arm.GetPosition().Clone();
|
||||
position.y -= this.arm_def.arm_length/2;
|
||||
jd.Initialize(upper_arm, lower_arm, position);
|
||||
jd.lowerAngle = 0;
|
||||
jd.upperAngle = 1.22;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 60;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
return {upper_arm: upper_arm, lower_arm: lower_arm};
|
||||
}
|
||||
|
||||
Walker.prototype.createHead = function() {
|
||||
// neck
|
||||
this.bd.position.Set(0.5 - this.leg_def.foot_length/2 + this.leg_def.tibia_width/2, this.leg_def.foot_height/2 + this.leg_def.foot_height/2 + this.leg_def.tibia_length + this.leg_def.femur_length + this.torso_def.lower_height + this.torso_def.upper_height + this.head_def.neck_height/2);
|
||||
var neck = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.head_def.neck_width/2, this.head_def.neck_height/2);
|
||||
neck.CreateFixture(this.fd);
|
||||
|
||||
// head
|
||||
this.bd.position.Set(0.5 - this.leg_def.foot_length/2 + this.leg_def.tibia_width/2, this.leg_def.foot_height/2 + this.leg_def.foot_height/2 + this.leg_def.tibia_length + this.leg_def.femur_length + this.torso_def.lower_height + this.torso_def.upper_height + this.head_def.neck_height + this.head_def.head_height/2);
|
||||
var head = this.world.CreateBody(this.bd);
|
||||
|
||||
this.fd.shape.SetAsBox(this.head_def.head_width/2, this.head_def.head_height/2);
|
||||
head.CreateFixture(this.fd);
|
||||
|
||||
// neck joint
|
||||
var jd = new b2.RevoluteJointDef();
|
||||
var position = neck.GetPosition().Clone();
|
||||
position.y += this.head_def.neck_height/2;
|
||||
jd.Initialize(head, neck, position);
|
||||
jd.lowerAngle = -0.1;
|
||||
jd.upperAngle = 0.1;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 2;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
return {head: head, neck: neck};
|
||||
}
|
||||
|
||||
Walker.prototype.connectParts = function() {
|
||||
// neck/torso
|
||||
// var jd = new b2.RevoluteJointDef();
|
||||
// var position = this.head.neck.GetPosition().Clone();
|
||||
// position.y -= this.head_def.neck_height/2;
|
||||
// jd.Initialize(this.head.neck, this.torso.upper_torso, position);
|
||||
// jd.lowerAngle = 0;
|
||||
// jd.upperAngle = 0.2;
|
||||
// jd.enableLimit = true;
|
||||
// jd.maxMotorTorque = 2;
|
||||
// jd.motorSpeed = 0;
|
||||
// jd.enableMotor = true;
|
||||
// this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
//neck/torso
|
||||
var jd = new b2.WeldJointDef();
|
||||
jd.bodyA = this.head.neck;
|
||||
jd.bodyB = this.torso.upper_torso;
|
||||
jd.localAnchorA = new b2.Vec2(0, -this.head_def.neck_height/2);
|
||||
jd.localAnchorB = new b2.Vec2(0, this.torso_def.upper_height/2);
|
||||
jd.referenceAngle = 0;
|
||||
this.world.CreateJoint(jd);
|
||||
|
||||
// torso/arms
|
||||
var jd = new b2.RevoluteJointDef();
|
||||
position = this.torso.upper_torso.GetPosition().Clone();
|
||||
position.y += this.torso_def.upper_height/2;
|
||||
jd.Initialize(this.torso.upper_torso, this.right_arm.upper_arm, position);
|
||||
jd.lowerAngle = -Math.PI/5;
|
||||
jd.upperAngle = Math.PI/4;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 120;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
var jd = new b2.RevoluteJointDef();
|
||||
jd.Initialize(this.torso.upper_torso, this.left_arm.upper_arm, position);
|
||||
jd.lowerAngle = -Math.PI/5;
|
||||
jd.upperAngle = Math.PI/4;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 120;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
// torso/legs
|
||||
var jd = new b2.RevoluteJointDef();
|
||||
position = this.torso.lower_torso.GetPosition().Clone();
|
||||
position.y -= this.torso_def.lower_height/2;
|
||||
jd.Initialize(this.torso.lower_torso, this.right_leg.upper_leg, position);
|
||||
jd.lowerAngle = -Math.PI/8;
|
||||
jd.upperAngle = Math.PI/7;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 250;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
|
||||
var jd = new b2.RevoluteJointDef();
|
||||
jd.Initialize(this.torso.lower_torso, this.left_leg.upper_leg, position);
|
||||
jd.lowerAngle = -Math.PI/8;
|
||||
jd.upperAngle = Math.PI/7;
|
||||
jd.enableLimit = true;
|
||||
jd.maxMotorTorque = 250;
|
||||
jd.motorSpeed = 0;
|
||||
jd.enableMotor = true;
|
||||
this.joints.push(this.world.CreateJoint(jd));
|
||||
}
|
||||
|
||||
Walker.prototype.getBodies = function() {
|
||||
|
||||
return [
|
||||
this.head.head,
|
||||
this.head.neck,
|
||||
this.torso.upper_torso,
|
||||
this.torso.lower_torso,
|
||||
this.left_arm.upper_arm,
|
||||
this.left_arm.lower_arm,
|
||||
this.right_arm.upper_arm,
|
||||
this.right_arm.lower_arm,
|
||||
this.left_leg.upper_leg,
|
||||
this.left_leg.lower_leg,
|
||||
this.left_leg.foot,
|
||||
this.right_leg.upper_leg,
|
||||
this.right_leg.lower_leg,
|
||||
this.right_leg.foot
|
||||
];
|
||||
}
|
||||
|
||||
Walker.prototype.createGenome = function(joints, bodies) {
|
||||
var genome = [];
|
||||
for(var k = 0; k < joints.length; k++) {
|
||||
var gene = new Object();
|
||||
/*
|
||||
gene.target_body1 = Math.floor(Math.random() * bodies.length);
|
||||
gene.target_body2 = Math.floor(Math.random() * bodies.length);
|
||||
gene.target_body3 = Math.floor(Math.random() * bodies.length);
|
||||
gene.body_cos_multiplier1 = 6*Math.random() - 3;
|
||||
gene.body_cos_multiplier2 = 6*Math.random() - 3;
|
||||
gene.body_cos_multiplier3 = 6*Math.random() - 3;
|
||||
|
||||
gene.torso_angle_multiplier = 4*Math.random() -2;
|
||||
*/
|
||||
gene.cos_factor = 6*Math.random() - 3;
|
||||
gene.time_factor = Math.random()/10;
|
||||
gene.time_shift = Math.random()*Math.PI/2
|
||||
genome.push(gene);
|
||||
}
|
||||
return genome;
|
||||
}
|
||||
|
||||
Walker.prototype.simulationStep = function() {
|
||||
for(var k = 0; k < this.joints.length; k++) {
|
||||
/*
|
||||
var target_body1 = this.bodies[this.genome[k].target_body1];
|
||||
var target_body2 = this.bodies[this.genome[k].target_body2];
|
||||
var target_body3 = this.bodies[this.genome[k].target_body3];
|
||||
|
||||
var sin1 = Math.sin(target_body1.GetAngle());
|
||||
var sin2 = Math.sin(target_body2.GetAngle());
|
||||
var sin3 = Math.sin(target_body3.GetAngle());
|
||||
|
||||
this.joints[k].SetMotorSpeed(
|
||||
this.genome[k].cos_factor * Math.sin(this.genome[k].torso_angle_multiplier*this.torso.upper_torso.GetAngle()) +
|
||||
this.genome[k].body_cos_multiplier1 * sin1 +
|
||||
this.genome[k].body_cos_multiplier2 * sin2 +
|
||||
this.genome[k].body_cos_multiplier3 * sin3
|
||||
);
|
||||
*/
|
||||
this.joints[k].SetMotorSpeed(this.genome[k].cos_factor*Math.cos(this.genome[k].time_shift+this.genome[k].time_factor*globals.step_counter));
|
||||
}
|
||||
var oldmax = this.max_distance;
|
||||
var distance = this.torso.upper_torso.GetPosition().x;
|
||||
this.max_distance = Math.max(this.max_distance, distance);
|
||||
|
||||
// score
|
||||
this.head_height = this.head.head.GetPosition().y;
|
||||
this.low_foot_height = Math.min(this.left_leg.foot.GetPosition().y, this.right_leg.foot.GetPosition().y);
|
||||
var body_delta = this.head_height-this.low_foot_height;
|
||||
var leg_delta = this.right_leg.foot.GetPosition().x - this.left_leg.foot.GetPosition().x;
|
||||
|
||||
if(body_delta > config.min_body_delta) {
|
||||
this.score += body_delta/50;
|
||||
if(this.max_distance > oldmax) {
|
||||
if(Math.abs(leg_delta) > config.min_leg_delta && this.head.head.m_linearVelocity.y > -2) {
|
||||
if(typeof this.leg_delta_sign == 'undefined') {
|
||||
this.leg_delta_sign = leg_delta/Math.abs(leg_delta);
|
||||
} else if(this.leg_delta_sign * leg_delta < 0) {
|
||||
this.leg_delta_sign = leg_delta/Math.abs(leg_delta);
|
||||
this.steps++;
|
||||
this.score += 100;
|
||||
this.score += this.max_distance;
|
||||
this.health = config.walker_health;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(config.check_health) {
|
||||
if(body_delta < config.instadeath_delta) {
|
||||
this.health = 0;
|
||||
} else {
|
||||
this.health--;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Walker.prototype.makeName = function(genome) {
|
||||
var name = '';
|
||||
var vowels = ['a','e','i','o','u'];
|
||||
var space_position = Math.floor(genome.length/2);
|
||||
for(var k = 0; k < genome.length; k++) {
|
||||
var sum = 0;
|
||||
for(var l in genome[k]) {
|
||||
if(genome[k].hasOwnProperty(l)) {
|
||||
sum += (genome[k][l]*10);
|
||||
}
|
||||
sum = Math.abs(Math.floor(sum));
|
||||
}
|
||||
if(k == space_position) {
|
||||
name += ' ';
|
||||
}
|
||||
if(k%2) {
|
||||
name += vowels[sum%5];
|
||||
} else {
|
||||
name += String.fromCharCode(97+sum%26);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
Reference in New Issue
Block a user