A bot used for https://code-your-snake.codingmaster398.repl.co/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
467 lines
25 KiB
467 lines
25 KiB
/*
|
|
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=11) {
|
|
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}]}
|
|
*/
|
|
|