/* Welcome to your Code your snake bot! This is a minimal example showing spawning, the snake's position, and where the closest apple is. It won't work right away because you need to authenticate yourself. Read /learn/welcome.md. */ const LEFT = 0 const RIGHT = 1 const UP = 2 const DOWN = 3 const FOOD = 3 const GOLDEN_FOOD = 4 const BLACK_HOLE = 5 const newSnake = require('./wrapper.js') const dotenv = require('dotenv'); dotenv.config(); const fs = require('fs'); let snake = newSnake(process.env.auth) // Login with the auth cookie in the secrets tab var vals = fs.readFileSync("data", 'utf8').split("\n") /*File Format: `${LAST_DEATH} ${BEST_LENGTH} ${TOTAL_ATTEMPTS} ${TOTAL_LENGTH} ${BEST_SEEN} ${BEST_SEEN_WHO} ` */ horz_dir = LEFT vert_dir = UP LAST_DEATH = vals[0] BEST_LENGTH = Number(vals[1]) TOTAL_ATTEMPTS = Number(vals[2]) TOTAL_LENGTH = Number(vals[3]) LAST_LENGTH = 0 BEST_SEEN = Number(vals[4]) BEST_SEEN_WHO = vals[5] TEST_REGIONS = [] APPLES_LIST=[] targetApp={} snake.onSpawn = function(x, y) { // When the snake spawns console.log(`Spawned at X ${x}, Y ${y}`) TOTAL_ATTEMPTS++ } snake.onDeath = function(reason) { // When the snake dies LAST_DEATH = reason TOTAL_LENGTH += LAST_LENGTH LAST_LENGTH = 0 fs.writeFileSync("data", `${LAST_DEATH} ${BEST_LENGTH} ${TOTAL_ATTEMPTS} ${TOTAL_LENGTH} ${BEST_SEEN} ${BEST_SEEN_WHO} `) snake.spawn() // Respawn } snake.onTick = function(obj) { // When the game updates if (snake.spawned) { // If the snake is alive let closestApple = snake.closestApple() // Get the closest apple let bestApp = bestApple() if (snake.me()) { if (snake.me()?.body.length > BEST_LENGTH) { BEST_LENGTH = snake.me().body.length } LAST_LENGTH = snake.me().body.length for (var player in obj.players) { if (obj.players[player].body.length > BEST_SEEN) { BEST_SEEN = obj.players[player].body.length BEST_SEEN_WHO = player } } } // Clear the console and log the snake's position and the closest apple's position console.clear() console.log(`I am at X ${snake.x}, Y ${snake.y}`) console.log(`The closest apple is at X ${closestApple.x}, Y ${closestApple.y}`) console.log(`The best apple is at X ${bestApp.x}, Y ${bestApp.y}`) console.log(`Last Death reason was: ${LAST_DEATH}`) console.log(`\nBest Length:${BEST_LENGTH}\nAverage Length:${Math.floor((TOTAL_LENGTH + snake.me()?.body.length) / TOTAL_ATTEMPTS)}\nCurrent Length:${snake.me()?.body.length}\nTotal Spawns:${TOTAL_ATTEMPTS}\n\nBest Seen:${BEST_SEEN_WHO} - ${BEST_SEEN}`) //console.log(JSON.stringify(obj)); function bestApple() { //Returns the best apple that will not result in greedy collisions. var testApple = snake.closestApple() var allowed = true; var adjacentBodies=0; for (var player in obj.players) { if (player !== "sigonasr2") { for (var i of obj.players[player].body) { adjacentBodies+=(Math.abs(i[0] - testApple.x)===0)&&(Math.abs(i[1] - testApple.y)===1)||(Math.abs(i[0] - testApple.x)===1)&&(Math.abs(i[1] - testApple.y)===0)?1:0 if (Math.abs(i[0] - testApple.x) < 3 && Math.abs(i[1] - testApple.y) < 3) { allowed = false; break; } if (Math.abs(obj.players[player].head[0] - testApple.x) < 2 && Math.abs(obj.players[player].head[1] - testApple.y) < 2) { allowed = false; break; } } } else { adjacentBodies+=(Math.abs(obj.players[player].body[0] - testApple.x)===0)&&(1,Math.abs(obj.players[player].body[1] - testApple.y)===1)||(Math.abs(obj.players[player].body[0] - testApple.x)===1)&&(1,Math.abs(obj.players[player].body[1] - testApple.y)===0)?1:0 } } for (var i of snake.blackHoles()) { adjacentBodies+=(Math.abs(i[0] - testApple.x)===0)&&(Math.abs(i[1] - testApple.y)===1)||(Math.abs(i[0] - testApple.x)===1)&&(Math.abs(i[1] - testApple.y)===0)?1:0 } adjacentBodies+=((testApple.x===0)?1:0)+((testApple.y===0)?1:0)+((testApple.x===149)?1:0)+((testApple.y===149)?1:0) //Boundary checks count as walls too. if (adjacentBodies>=2) { allowed=false //We can't allow picking up an apple with only one way out. } if (allowed) { return testApple; } for (var apple of snake.apples()) { var testApple = apple var allowed = true; var adjacentBodies=0; for (var player in obj.players) { if (player !== "sigonasr2") { for (var i of obj.players[player].body) { adjacentBodies+=((Math.abs(i[0] - testApple[0])===0)&&(Math.abs(i[1] - testApple[1])===1)||(Math.abs(i[0] - testApple[0])===1)&&(Math.abs(i[1] - testApple[1])===0))?1:0 if (Math.abs(i[0] - testApple[0]) < 3 && Math.abs(i[1] - testApple[1]) < 3) { allowed = false; break; } } if (Math.abs(obj.players[player].head[0] - testApple[0]) < 2 && Math.abs(obj.players[player].head[1] - testApple[1]) < 2) { allowed = false break; } } else { adjacentBodies+=(Math.abs(obj.players[player].body[0] - testApple[0])===0)&&(Math.abs(obj.players[player].body[1] - testApple[1])===1)||(Math.abs(obj.players[player].body[0] - testApple[0])===1)&&(Math.abs(obj.players[player].body[1] - testApple[1])===0)?1:0 } } for (var i of snake.blackHoles()) { adjacentBodies+=(Math.abs(i[0] - testApple[0])===0)&&(Math.abs(i[1] - testApple[1])===1)||(Math.abs(i[0] - testApple[0])===1)&&(Math.abs(i[1] - testApple[1])===0)?1:0 } adjacentBodies+=((testApple[0]===0)?1:0)+((testApple[1]===0)?1:0)+((testApple[0]===149)?1:0)+((testApple[1]===149)?1:0) //Boundary checks count as walls too. if (adjacentBodies>=2) { console.log(adjacentBodies+" found for "+testApple) allowed=false //We can't allow picking up an apple with only one way out. } if (allowed) { return { x: testApple[0], y: testApple[1] }; } } console.log("No viable apple found...") return { x: 0, y: 0 } } function spotIsFree(dir, x, y) { newCoords = [x, y] for (var i of TEST_REGIONS) { if (i[0] === newCoords[0] && i[1] === newCoords[1]) { return false; } } for (var i of snake.me()?.body) { if (i[0] === newCoords[0] && i[1] === newCoords[1]) { return false; } } for (var i of snake.blackHoles()) { if (i[0] === newCoords[0] && i[1] === newCoords[1]) { return false; } } for (var i of snake.bodyPositions()) { if (i[0] === newCoords[0] && i[1] === newCoords[1]) { return false; } } for (var i of snake.headPositions()) { if (i[0] === newCoords[0] && i[1] === newCoords[1]) { return false; } } for (var player in obj.players) { if (player !== "sigonasr2") { var head = obj.players[player].head var dir = obj.players[player].direction if (head[0]+(dir===LEFT?1:dir===RIGHT?-1:0)===newCoords[0]&&head[1]+(dir===DOWN?1:dir===UP?-1:0)===newCoords[1]) { return false } } } if (newCoords[0] < 0 || newCoords[0] > 149 || newCoords[1] < 0 || newCoords[1] > 149) { return false; } return true; } function findPath(dir, x, y,appleDepth=5) { if (spotIsFree(dir, x, y)) { TEST_REGIONS = [[x, y], ...TEST_REGIONS] diff_x = x - targetApp.x diff_y = y - targetApp.y if (diff_x === 0 && diff_y === 0) { if (--appleDepth===0) { return true; } else { var myRegions = [...TEST_REGIONS] while (APPLES_LIST.length>0) { var newApple = APPLES_LIST.shift() TEST_REGIONS=[...myRegions] targetApp={x:newApple[0],y:newApple[1]} diff_x = x - targetApp.x diff_y = y - targetApp.y if (Math.abs(diff_x) > Math.abs(diff_y)) { if (diff_x > 0) { if (dir !== RIGHT && findPath(LEFT, x - 1, y,appleDepth)) { return true; } //Preferred direction found. } else { if (dir !== LEFT && findPath(RIGHT, x + 1, y,appleDepth)) { return true; } } } else { if (diff_y > 0) { if (dir !== DOWN && findPath(UP, x, y - 1,appleDepth)) { return true; } //Preferred direction found. } else { if (dir !== UP && findPath(DOWN, x, y + 1,appleDepth)) { return true; } } } } } } if (Math.abs(diff_x) > Math.abs(diff_y)) { if (diff_x > 0) { if (dir !== RIGHT && findPath(LEFT, x - 1, y,appleDepth)) { return true; } //Preferred direction found. } else { if (dir !== LEFT && findPath(RIGHT, x + 1, y,appleDepth)) { return true; } } } else { if (diff_y > 0) { if (dir !== DOWN && findPath(UP, x, y - 1,appleDepth)) { return true; } //Preferred direction found. } else { if (dir !== UP && findPath(DOWN, x, y + 1,appleDepth)) { return true; } } } } return false; } function findSafePath(dir, x, y, targetX, targetY,emergency=false) { if (spotIsFree(dir, x, y)) { TEST_REGIONS = [[x, y], ...TEST_REGIONS] diff_x = x - targetX diff_y = y - targetY if (diff_x === 0 && diff_y === 0) { return true; } if (Math.abs(diff_x) > Math.abs(diff_y)) { if (diff_x > 0) { if (dir !== RIGHT && findSafePath(LEFT, x - 1, y, targetX, targetY)) { return true; } //Preferred direction found. } else { if (dir !== LEFT && findSafePath(RIGHT, x + 1, y, targetX, targetY)) { return true; } } } else { if (diff_y > 0) { if (dir !== DOWN && findSafePath(UP, x, y - 1, targetX, targetY)) { return true; } //Preferred direction found. } else { if (dir !== UP && findSafePath(DOWN, x, y + 1, targetX, targetY)) { return true; } } } } return false; } //Make a path towards the closest apple. Always play it safe. diff_x = snake.x - bestApp.x diff_y = snake.y - bestApp.y TEST_REGIONS = [] EXTRA_MOVEMENT=false APPLES_LIST= snake.apples() .filter((a)=>a[0]!==bestApp.x&&a[1]!==bestApp.y) .sort((a,b)=>Math.sqrt(Math.pow(snake.x-a[0],2)+Math.pow(snake.y-a[1],2))-Math.sqrt(Math.pow(snake.x-b[0],2)+Math.pow(snake.y-b[1],2))) targetApp=bestApp if (Math.abs(diff_x) > Math.abs(diff_y)) { if (diff_x > 0) { if (snake.me()?.direction !== RIGHT && findPath(LEFT, snake.x - 1, snake.y)) { snake.setDirection(LEFT); return; } //Preferred direction found. } else { if (snake.me()?.direction !== LEFT && findPath(RIGHT, snake.x + 1, snake.y)) { snake.setDirection(RIGHT); return; } } } else { if (diff_y > 0) { if (snake.me()?.direction !== DOWN && findPath(UP, snake.x, snake.y - 1)) { snake.setDirection(UP); return; } //Preferred direction found. } else { if (snake.me()?.direction !== UP && findPath(DOWN, snake.x, snake.y + 1)) { snake.setDirection(DOWN); return; } } } //TODO Try different apples here before trying to "just survive". There may be a better path. console.log("Okay maybe this apple wasn't such a good idea... Try another one.") APPLES_LIST= snake.apples() .filter((a)=>a[0]!==bestApp.x&&a[1]!==bestApp.y) //I want apples furthest away to be checked first. These are probably the safest calculations to make. .sort((a,b)=>Math.sqrt(Math.pow(snake.x-b[0],2)+Math.pow(snake.y-b[1],2))-Math.sqrt(Math.pow(snake.x-a[0],2)+Math.pow(snake.y-a[1],2))) for (var apple of APPLES_LIST) { TEST_REGIONS = [] EXTRA_MOVEMENT=false var adjacentBodies=0; for (var player in obj.players) { if (player !== "sigonasr2") { for (var i of obj.players[player].body) { adjacentBodies+=((Math.abs(i[0] - apple[0])===0)&&(Math.abs(i[1] - apple[1])===1)||(Math.abs(i[0] - apple[0])===1)&&(Math.abs(i[1] - apple[1])===0))?1:0 } } else { adjacentBodies+=((Math.abs(obj.players[player].body[0] - apple[0])===0)&&(Math.abs(obj.players[player].body[1] - apple[1])===1)||(Math.abs(obj.players[player].body[0] - apple[0])===1)&&(Math.abs(obj.players[player].body[1] - apple[1])===0))?1:0 } } for (var i of snake.blackHoles()) { adjacentBodies+=((Math.abs(i[0] - apple[0])===0)&&(Math.abs(i[1] - apple[1])===1)||(Math.abs(i[0] - apple[0])===1)&&(Math.abs(i[1] - apple[1])===0))?1:0 } adjacentBodies+=((apple[0]===0)?1:0)+((apple[1]===0)?1:0)+((apple[0]===149)?1:0)+((apple[1]===149)?1:0) //Boundary checks count as walls too. if (adjacentBodies>=2) { continue; //Skip this apple. It's dangerous. } if (snake.x !== 0 && snake.y !== 0) { if (snake.me()?.direction !== DOWN && findSafePath(UP, snake.x, snake.y - 1, apple[0], apple[1])) { snake.setDirection(UP); return; } if (snake.me()?.direction !== RIGHT && findSafePath(LEFT, snake.x - 1, snake.y, apple[0], apple[1])) { snake.setDirection(LEFT); return; } if (snake.me()?.direction !== LEFT && findSafePath(RIGHT, snake.x + 1, snake.y, apple[0], apple[1])) { snake.setDirection(RIGHT); return; } if (snake.me()?.direction !== UP && findSafePath(DOWN, snake.x, snake.y + 1, apple[0], apple[1])) { snake.setDirection(DOWN); return; } } } console.log("No viable path, just survive for now...") TEST_REGIONS = [] EXTRA_MOVEMENT=false if (snake.x !== 0 && snake.y !== 0) { if (snake.me()?.direction !== DOWN && findSafePath(UP, snake.x, snake.y - 1, 0, 0)) { snake.setDirection(UP); return; } if (snake.me()?.direction !== RIGHT && findSafePath(LEFT, snake.x - 1, snake.y, 0, 0)) { snake.setDirection(LEFT); return; } if (snake.me()?.direction !== LEFT && findSafePath(RIGHT, snake.x + 1, snake.y, 0, 0)) { snake.setDirection(RIGHT); return; } if (snake.me()?.direction !== UP && findSafePath(DOWN, snake.x, snake.y + 1, 0, 0)) { snake.setDirection(DOWN); return; } } TEST_REGIONS = [] EXTRA_MOVEMENT=false console.log("Last resort...") if (snake.me()?.direction !== DOWN && findSafePath(UP, snake.x, snake.y - 1, 149, 149)) { snake.setDirection(UP); return; } if (snake.me()?.direction !== RIGHT && findSafePath(LEFT, snake.x - 1, snake.y, 149, 149)) { snake.setDirection(LEFT); return; } if (snake.me()?.direction !== LEFT && findSafePath(RIGHT, snake.x + 1, snake.y, 149, 149)) { snake.setDirection(RIGHT); return; } if (snake.me()?.direction !== UP && findSafePath(DOWN, snake.x, snake.y + 1, 149, 149)) { snake.setDirection(DOWN); return; } TEST_REGIONS = [] EXTRA_MOVEMENT=false if (spotIsFree(snake.me().direction, x + (snake.me().direction === RIGHT ? 1 : snake.me().direction === LEFT ? -1 : 0), y + (snake.me().direction === DOWN ? 1 : snake.me().direction === UP ? -1 : 0))) { return; } else if (snake.me()?.direction !== UP && spotIsFree(DOWN, x, y + 1)) { snake.setDirection(DOWN) return } else if (snake.me()?.direction !== RIGHT && spotIsFree(LEFT, x - 1, y)) { snake.setDirection(LEFT) return } else if (snake.me()?.direction !== LEFT && spotIsFree(RIGHT, x + 1, y)) { snake.setDirection(RIGHT) return } else if (snake.me()?.direction !== DOWN && spotIsFree(UP, x, y - 1)) { snake.setDirection(UP) return } console.log("Dedge.") } } snake.onLogin = function(username) { // When logged in console.log(`Connected as ${username}!`) snake.spawn() // Spawn the snake } /* Sample: //Field is 150x150. We'll assume zero-based. {"players":{"Bot 3263":{"body":[[66,95],[66,96],[66,97],[66,98],[66,99],[66,100],[66,101],[66,102],[66,103],[67,103],[68,103],[69,103],[69,104],[70,104],[70,105],[70,106],[70,107],[71,107],[71,108],[71,109],[71,110],[71,111],[71,112],[72,112],[72,113],[72,114],[72,115],[73,115],[74,115],[75,115],[76,115],[76,116],[76,117],[76,118],[76,119],[76,120],[76,121],[77,121],[77,122],[77,123],[77,124],[77,125],[78,125],[79,125],[80,125],[80,126],[80,127],[80,128],[80,129],[80,130],[80,131],[80,132],[80,133],[80,134],[81,134],[82,134],[82,135],[82,136],[82,137],[82,138],[82,139],[82,140],[83,140],[83,141],[84,141],[85,141],[86,141],[87,141],[88,141],[89,141],[90,141],[91,141],[92,141],[93,141],[94,141],[95,141],[96,141],[97,141],[98,141],[99,141],[100,141],[101,141],[101,142],[100,142],[100,143],[99,143],[98,143],[97,143],[96,143],[95,143],[94,143],[93,143],[92,143],[91,143],[90,143],[89,143],[88,143],[87,143],[86,143],[85,143],[84,143],[83,143],[82,143],[82,144],[82,145],[81,145],[80,145],[79,145],[78,145],[77,145],[76,145],[75,145],[74,145],[73,145],[72,145],[71,145],[70,145],[69,145],[69,146],[68,146],[67,146],[66,146],[65,146],[64,146],[63,146],[62,146],[62,145],[62,144],[62,143],[62,142],[62,141],[62,140],[61,140],[60,140],[60,139],[59,139],[59,138],[59,137],[59,136],[59,135],[59,134],[59,133],[59,132],[59,131],[59,130],[59,129],[59,128],[59,127],[59,126],[59,125],[59,124],[58,124],[58,125],[58,126],[58,127],[58,128],[58,129],[58,130],[58,131],[58,132],[58,133],[58,134],[58,135],[58,136],[58,137],[58,138],[58,139],[57,139],[56,139],[55,139],[54,139],[53,139],[52,139],[51,139],[51,140],[50,140],[49,140],[48,140],[47,140],[47,141],[46,141],[45,141],[44,141],[43,141],[42,141],[42,142],[41,142],[41,143],[40,143],[39,143],[38,143],[38,142],[38,141],[38,140],[38,139],[38,138],[38,137],[38,136],[38,135],[38,134],[38,133],[38,132],[38,131],[38,130],[37,130],[36,130],[36,129],[36,128],[36,127],[35,127],[35,126],[36,126],[37,126],[38,126],[39,126],[39,127],[39,128],[39,129],[39,130],[40,130],[40,129],[40,128],[40,127],[40,126],[40,125],[39,125],[38,125],[37,125],[36,125],[35,125],[34,125],[33,125],[32,125],[32,126],[32,127],[31,127],[30,127],[29,127],[28,127],[27,127],[26,127],[25,127],[24,127],[23,127],[22,127],[21,127],[20,127],[19,127],[18,127],[17,127],[16,127],[15,127],[15,126],[14,126],[14,127],[14,128],[14,129],[14,130],[14,131],[14,132],[13,132],[12,132],[12,133],[11,133],[10,133],[9,133],[9,134],[10,134],[11,134],[12,134],[12,135],[12,136],[12,137],[12,138],[12,139],[12,140],[12,141],[12,142],[12,143],[12,144],[12,145],[12,146],[12,147],[12,148],[13,148],[14,148],[14,149],[13,149],[12,149],[11,149],[11,148],[11,147],[11,146],[11,145],[11,144],[11,143],[11,142],[11,141],[11,140],[11,139],[11,138],[11,137],[11,136],[10,136],[9,136],[9,135],[8,135],[8,134],[8,133],[8,132],[8,131],[8,130],[8,129],[8,128],[8,127],[8,126],[8,125],[8,124],[8,123],[8,122],[8,121],[8,120],[8,119],[8,118],[8,117],[8,116],[8,115],[8,114],[8,113],[8,112],[9,112],[9,111],[9,110],[9,109],[10,109],[11,109],[11,108],[10,108],[9,108],[8,108],[7,108],[7,109],[6,109],[6,110],[5,110],[4,110],[3,110],[3,109],[3,108],[4,108],[4,107],[4,106],[5,106],[5,105],[5,104],[5,103],[6,103],[6,102],[6,101],[7,101]],"head":[7,100],"direction":2,"grow":0,"bc":{"r":57,"g":166,"b":110}},"Bot 2494":{"body":[[58,83],[57,83],[57,82],[56,82],[56,81],[55,81],[54,81],[53,81],[52,81],[51,81],[51,80],[50,80],[50,81],[50,82],[50,83],[50,84],[49,84],[48,84],[48,85],[47,85],[46,85],[45,85],[45,84],[45,83],[45,82],[45,81],[45,80],[45,79],[45,78],[45,77],[45,76],[45,75],[46,75],[46,74],[46,73],[47,73],[47,72],[47,71],[47,70],[47,69],[48,69],[49,69],[49,68],[49,67],[49,66],[49,65],[49,64],[48,64],[47,64],[46,64],[46,63],[45,63],[44,63],[44,62],[43,62],[43,63],[43,64],[43,65],[43,66],[43,67],[43,68],[42,68],[41,68],[40,68],[40,69],[40,70],[40,71],[40,72],[40,73],[40,74],[40,75],[39,75],[38,75],[38,76],[38,77],[38,78],[37,78],[36,78],[35,78],[34,78],[33,78],[32,78],[32,79],[31,79],[31,80],[30,80],[29,80],[28,80],[28,79],[28,78],[28,77],[28,76],[28,75],[28,74],[28,73],[27,73],[26,73],[26,72],[25,72],[25,71],[24,71],[23,71],[22,71],[21,71],[20,71],[19,71],[19,70],[18,70],[18,69],[18,68],[17,68],[17,67],[16,67],[15,67],[14,67],[13,67],[13,66],[12,66],[12,65],[12,64],[12,63],[11,63],[11,62],[10,62],[9,62],[8,62],[7,62],[7,61],[6,61],[6,60],[6,59],[6,58],[6,57],[6,56],[6,55],[6,54],[6,53],[6,52],[7,52],[7,51],[7,50],[7,49],[7,48],[8,48],[9,48],[10,48],[11,48],[12,48],[13,48],[14,48],[15,48],[16,48],[17,48],[18,48],[18,49],[18,50],[18,51],[18,52],[19,52],[19,53],[19,54],[20,54],[21,54],[22,54],[22,55],[23,55],[23,54],[23,53],[23,52],[24,52],[24,51],[24,50],[24,49],[25,49],[25,48]],"head":[25,47],"direction":2,"grow":0,"bc":{"r":31,"g":195,"b":75}},"Bot 6255":{"body":[[146,60],[146,59],[146,58],[146,57],[146,56],[146,55],[146,54],[146,53],[147,53],[147,52],[147,51],[147,50],[147,49],[147,48],[148,48],[149,48],[149,47],[149,46],[149,45],[149,44],[149,43],[149,42],[149,41],[149,40],[149,39],[149,38],[149,37],[149,36],[149,35],[149,34],[149,33],[149,32],[149,31],[149,30],[149,29],[149,28],[149,27],[149,26],[149,25],[149,24],[149,23],[149,22],[149,21],[149,20],[149,19],[149,18],[149,17],[149,16],[149,15],[149,14],[149,13],[148,13],[148,12],[148,11],[147,11],[146,11],[145,11],[144,11],[143,11],[143,10],[144,10],[145,10],[145,9],[144,9],[143,9],[142,9],[142,10],[142,11],[142,12]],"head":[142,13],"direction":3,"grow":0,"bc":{"r":91,"g":186,"b":78}},"Bot 9777":{"body":[[145,26],[145,25],[145,24],[145,23],[145,22],[145,21],[145,20],[145,19],[145,18],[145,17],[145,16],[145,15],[145,14],[145,13],[146,13],[146,12],[145,12],[144,12],[144,13],[144,14],[144,15],[144,16],[144,17],[144,18],[143,18],[143,17],[143,16],[142,16],[142,17],[142,18],[142,19],[142,20],[142,21],[142,22]],"head":[142,23],"direction":3,"grow":0,"bc":{"r":21,"g":208,"b":83}},"Bot 4387":{"body":[[86,115],[86,116],[86,117],[87,117],[87,116],[87,115],[87,114],[87,113],[87,112],[87,111],[87,110],[87,109],[87,108],[87,107]],"head":[87,106],"direction":2,"grow":0,"bc":{"r":81,"g":141,"b":99}},"sigonasr2":{"body":[],"head":[14,2],"direction":0,"grow":0,"bc":{"r":134,"g":160,"b":22}}},"other":[{"pos":[79,129],"type":5},{"pos":[93,145],"type":5},{"pos":[10,12],"type":5},{"pos":[57,113],"type":5},{"pos":[102,28],"type":5},{"pos":[61,73],"type":5},{"pos":[24,7],"type":5},{"pos":[9,114],"type":5},{"pos":[35,64],"type":5},{"pos":[55,3],"type":5},{"pos":[2,98],"type":5},{"pos":[40,47],"type":5},{"pos":[104,127],"type":5},{"pos":[53,119],"type":5},{"pos":[125,26],"type":5},{"pos":[101,67],"type":5},{"pos":[104,37],"type":5},{"pos":[46,18],"type":5},{"pos":[133,4],"type":5},{"pos":[68,129],"type":5},{"pos":[84,87],"type":5},{"pos":[16,129],"type":5},{"pos":[103,31],"type":5},{"pos":[91,8],"type":5},{"pos":[120,131],"type":5},{"pos":[5,4],"type":3},{"pos":[23,12],"type":3},{"pos":[7,11],"type":4},{"pos":[7,21],"type":3},{"pos":[2,7],"type":3},{"pos":[4,26],"type":3},{"pos":[8,31],"type":3},{"pos":[28,16],"type":3},{"pos":[48,34],"type":4},{"pos":[4,0],"type":4},{"pos":[1,35],"type":3},{"pos":[26,25],"type":4},{"pos":[4,14],"type":3},{"pos":[40,45],"type":3},{"pos":[95,121],"type":5},{"pos":[18,27],"type":3},{"pos":[16,24],"type":3},{"pos":[38,31],"type":4},{"pos":[19,0],"type":3},{"pos":[7,3],"type":4},{"pos":[22,31],"type":4},{"pos":[31,44],"type":4},{"pos":[21,30],"type":4},{"pos":[57,11],"type":4},{"pos":[6,34],"type":3},{"pos":[10,13],"type":3},{"pos":[78,1],"type":4},{"pos":[70,55],"type":4},{"pos":[20,17],"type":3},{"pos":[62,69],"type":4},{"pos":[22,100],"type":3},{"pos":[73,44],"type":4},{"pos":[20,29],"type":3},{"pos":[56,43],"type":3},{"pos":[14,98],"type":4},{"pos":[33,111],"type":3},{"pos":[66,26],"type":3},{"pos":[42,35],"type":3},{"pos":[36,37],"type":3},{"pos":[32,29],"type":4},{"pos":[57,47],"type":3},{"pos":[60,64],"type":3},{"pos":[105,141],"type":4},{"pos":[47,40],"type":4},{"pos":[60,102],"type":3},{"pos":[9,9],"type":3},{"pos":[116,134],"type":4},{"pos":[29,26],"type":3},{"pos":[38,105],"type":3},{"pos":[3,28],"type":4},{"pos":[81,148],"type":4},{"pos":[41,113],"type":4},{"pos":[51,27],"type":4},{"pos":[124,29],"type":3},{"pos":[68,132],"type":3},{"pos":[54,9],"type":3},{"pos":[139,148],"type":3},{"pos":[1,76],"type":3},{"pos":[40,35],"type":4},{"pos":[53,149],"type":4},{"pos":[137,127],"type":4},{"pos":[124,66],"type":4},{"pos":[45,34],"type":4},{"pos":[25,33],"type":3},{"pos":[9,67],"type":4},{"pos":[139,61],"type":4},{"pos":[102,67],"type":4},{"pos":[67,57],"type":4},{"pos":[85,105],"type":3},{"pos":[61,34],"type":3}]} */