<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<p id="gen"></p>
<canvas id="canvas"></canvas>
</body>
</html>
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.canvas.width = window.innerWidth - 75;
ctx.canvas.height = window.innerHeight - 75;
var startingX = 50;
var startingY = 250;
var playerPositions;
var movesThisGeneration;
var bestPathFound = [];
var plantX = ctx.canvas.width/2;
var plantY = 0;
var generations = -1;
function drawPlayer1(){
ctx.fillStyle = "white";
ctx.fillRect(playerPositions.player1.x - 5, playerPositions.player1.y - 5, 20, 20);
ctx.fillStyle = "red";
ctx.fillRect(playerPositions.player1.x, playerPositions.player1.y, 5, 5);
}
function drawPlayer2(){
ctx.fillStyle = "white";
ctx.fillRect(playerPositions.player2.x - 5, playerPositions.player2.y - 5, 20, 20);
ctx.fillStyle = "blue";
ctx.fillRect(playerPositions.player2.x, playerPositions.player2.y, 5, 5);
}
function drawPlant(){
ctx.fillStyle = "orange";
ctx.fillRect(plantX, plantY, 10000, 1000000);
}
drawPlant();
nextGeneration();
var currentTick = 0;
function tick() {
drawPlayer2();
drawPlayer1();
movePlayers();
evaluateVictory();
currentTick++;
checkForFailure();
}
function checkForFailure() {
if (bestPathFound.length && currentTick > bestPathFound.length) {
nextGeneration()
}
}
function movePlayers() {
movePlayer('player1');
movePlayer('player2');
}
function pickDirection() {
var directionToMove;
// 90% chance to follow existing path. 10% chance for deviation
if(bestPathFound.length >= currentTick && Math.random < 0.9) {
return bestPathFound[currentTick]
}
if(!directionToMove) {
switch(Math.floor(Math.random() * 4) + 1) { // Random number between ranges
case 1:
return 'left';
case 2:
return 'right';
case 3:
return 'up';
case 4:
return 'down';
}
}
}
function movePlayer(playerName) {
var directionToMove = pickDirection();
movesThisGeneration[playerName].push(directionToMove);
switch(directionToMove) {
case 'up':
playerPositions[playerName] = {
x: playerPositions[playerName].x,
y: playerPositions[playerName].y + 5,
}
break;
case 'down':
playerPositions[playerName] = {
x: playerPositions[playerName].x,
y: playerPositions[playerName].y - 5,
}
break;
case 'left':
playerPositions[playerName] = {
x: playerPositions[playerName].x - 5,
y: playerPositions[playerName].y,
}
break;
case 'right':
playerPositions[playerName] = {
x: playerPositions[playerName].x + 5,
y: playerPositions[playerName].y,
}
break;
}
correctPlayerPosition(playerName);
}
function correctPlayerPosition(playerName) {
if( playerPositions[playerName].x < 0 ) {
playerPositions[playerName].x = 0;
}
if( playerPositions[playerName].x > ctx.canvas.width) {
playerPositions[playerName].x = ctx.canvas.width;
}
if( playerPositions[playerName].y < 0 ) {
playerPositions[playerName].y = 0;
}
if( playerPositions[playerName].y > ctx.canvas.height ) {
playerPositions[playerName].y = ctx.canvas.height;
}
}
function evaluateVictory() {
if(playerPositions.player1.x >= plantX) {
declareVictor('player1');
} else if (playerPositions.player2.x >= plantX) {
declareVictor('player2');
}
}
function declareVictor(playerName) {
if(
!bestPathFound.length ||
bestPathFound.length > movesThisGeneration[playerName].length
) {
bestPathFound = movesThisGeneration[playerName]
}
nextGeneration();
}
function nextGeneration() {
currentTick = 0;
playerPositions = {
player1: {x: startingX, y: startingY},
player2: {x: startingX, y: startingY}
};
movesThisGeneration = {
player1: [],
player2: []
};
generations++;
document.getElementById("gen").innerHTML ="Number of generations so far: " + generations + " Moves to Plant: " + bestPathFound.length;
}
setInterval(tick, 1);
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |