2017-11-17 02:49:43 -05:00
|
|
|
if (process.argv.length < 3) {
|
2019-02-21 12:02:18 -05:00
|
|
|
console.log("Usage: node paper-io-bot.js <socket-url> [<name>]")
|
2019-01-15 10:42:15 -05:00
|
|
|
process.exit(1);
|
2017-11-17 02:49:43 -05:00
|
|
|
}
|
|
|
|
|
2022-11-12 07:13:41 -05:00
|
|
|
import io from "socket.io-client";
|
2022-11-12 04:28:24 -05:00
|
|
|
import * as client from "./src/game-client.js";
|
|
|
|
import { consts } from "./config.js";
|
2017-11-17 02:49:43 -05:00
|
|
|
|
2020-07-24 03:11:35 -04:00
|
|
|
const MOVES = [[-1, 0], [0, 1], [1, 0], [0, -1]];
|
2017-11-17 02:49:43 -05:00
|
|
|
|
2020-07-24 03:11:35 -04:00
|
|
|
let startFrame = -1;
|
|
|
|
let endFrame = -1;
|
|
|
|
let grid;
|
|
|
|
let others;
|
|
|
|
let user;
|
|
|
|
const playerPortion = {};
|
|
|
|
let claim = [];
|
2017-11-17 02:49:43 -05:00
|
|
|
|
|
|
|
function mod(x) {
|
2019-01-15 10:42:15 -05:00
|
|
|
x %= 4;
|
|
|
|
if (x < 0) x += 4;
|
|
|
|
return x;
|
2017-11-17 02:49:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function connect() {
|
2020-07-24 03:11:35 -04:00
|
|
|
const prefixes = consts.PREFIXES.split(" ");
|
|
|
|
const names = consts.NAMES.split(" ");
|
|
|
|
const name = process.argv[3] || [prefixes[Math.floor(Math.random() * prefixes.length)], names[Math.floor(Math.random() * names.length)]].join(" ");
|
2022-11-12 07:13:41 -05:00
|
|
|
client.connectGame(io, process.argv[2], "[BOT] " + name, function(success, msg) {
|
2019-02-22 00:22:21 -05:00
|
|
|
if (!success) {
|
|
|
|
console.error(msg);
|
|
|
|
setTimeout(connect, 1000);
|
|
|
|
}
|
2019-01-15 10:42:15 -05:00
|
|
|
});
|
2017-11-17 02:49:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function Loc(row, col) {
|
2019-01-15 10:42:15 -05:00
|
|
|
if (this.constructor != Loc) return new Loc(row, col);
|
2017-11-17 02:49:43 -05:00
|
|
|
|
2019-01-15 10:42:15 -05:00
|
|
|
this.row = row;
|
|
|
|
this.col = col;
|
2017-11-17 02:49:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function update(frame) {
|
2019-01-15 23:15:38 -05:00
|
|
|
if (startFrame == -1) startFrame = frame;
|
2019-01-15 10:42:15 -05:00
|
|
|
endFrame = frame;
|
|
|
|
|
|
|
|
if (frame % 6 == (startFrame + 1) % 6) {
|
2020-07-24 03:11:35 -04:00
|
|
|
grid = client.grid;
|
|
|
|
others = client.getOthers();
|
2019-01-15 10:42:15 -05:00
|
|
|
|
2020-07-24 03:11:35 -04:00
|
|
|
//Note: the code below isn't really my own code. This code is in fact the
|
|
|
|
//approximate algorithm used by the paper.io game. It has been modified from
|
|
|
|
//the original code (i.e. deobfuscating) and made more efficient in some
|
|
|
|
//areas (and some tweaks), otherwise, the original logic is about the same.
|
|
|
|
const row = user.row;
|
2019-01-15 10:42:15 -05:00
|
|
|
|
2020-07-24 03:11:35 -04:00
|
|
|
const col = user.col;
|
|
|
|
let dir = user.currentHeading;
|
|
|
|
const thres = (.05 + .1 * Math.random()) * consts.GRID_COUNT * consts.GRID_COUNT;
|
2019-01-15 10:42:15 -05:00
|
|
|
|
2020-07-24 03:11:35 -04:00
|
|
|
if (row < 0 || col < 0 || row >= consts.GRID_COUNT || col >= consts.GRID_COUNT) return;
|
|
|
|
|
|
|
|
if (grid.get(row, col) === user) {
|
2019-01-15 10:42:15 -05:00
|
|
|
//When we are inside our territory
|
|
|
|
claim = [];
|
2022-11-12 04:28:24 -05:00
|
|
|
const weights = [25, 25, 25, 25];
|
2019-01-15 10:42:15 -05:00
|
|
|
weights[dir] = 100;
|
|
|
|
weights[mod(dir + 2)] = -9999;
|
|
|
|
|
2020-07-24 03:22:41 -04:00
|
|
|
for (var nd = 0; nd < 4; nd++) {
|
|
|
|
for (var S = 1; S < 20; S++) {
|
2019-01-15 10:42:15 -05:00
|
|
|
var nr = MOVES[nd][0] * S + row;
|
|
|
|
var nc = MOVES[nd][1] * S + col;
|
|
|
|
|
2019-02-21 12:39:14 -05:00
|
|
|
if (nr < 0 || nc < 0 || nr >= consts.GRID_COUNT || nc >= consts.GRID_COUNT) {
|
2019-01-15 10:42:15 -05:00
|
|
|
if (S > 1) weights[nd]--;
|
|
|
|
else weights[nd] = -9999;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (grid.get(nr, nc) !== user) weights[nd]--;
|
|
|
|
|
|
|
|
var tailed = undefined;
|
2020-07-24 03:22:41 -04:00
|
|
|
for (var o of others) {
|
2019-01-15 10:42:15 -05:00
|
|
|
if (o.tail.hitsTail(new Loc(nr, nc))) {
|
|
|
|
tailed = o;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tailed) {
|
|
|
|
if (o.name.indexOf("PAPER") != -1) weights[nd] += 3 * (30 - S); //Don't really try to kill our own kind
|
|
|
|
else weights[nd] += 30 * (30 - S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//View a selection of choices based on the weights we computed
|
|
|
|
var choices = [];
|
2020-07-24 03:22:41 -04:00
|
|
|
for (var d = 0; d < 4; d++) {
|
|
|
|
for (var S = 1; S < weights[d]; S++) {
|
2019-01-15 10:42:15 -05:00
|
|
|
choices.push(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (choices.length === 0) choices.push(dir);
|
|
|
|
dir = choices[Math.floor(Math.random() * choices.length)];
|
|
|
|
}
|
|
|
|
else if (playerPortion[user.num] < thres) {
|
|
|
|
//Claim some land if we are relatively tiny and have little to risk.
|
|
|
|
if (claim.length === 0) {
|
2020-07-24 03:11:35 -04:00
|
|
|
const breadth = 4 * Math.random() + 2;
|
|
|
|
const length = 4 * Math.random() + 2;
|
|
|
|
const ccw = 2 * Math.floor(2 * Math.random()) - 1;
|
2019-01-15 10:42:15 -05:00
|
|
|
|
2022-11-12 04:28:24 -05:00
|
|
|
const turns = [dir, mod(dir + ccw), mod(dir + ccw * 2), mod(dir + ccw * 3)];
|
|
|
|
const lengths = [breadth, length, breadth + 2 * Math.random() + 1, length];
|
2019-01-15 10:42:15 -05:00
|
|
|
|
2020-07-24 03:11:35 -04:00
|
|
|
for (let i = 0; i < turns.length; i++) {
|
|
|
|
for (let j = 0; j < lengths[i]; j++) {
|
2019-01-15 10:42:15 -05:00
|
|
|
claim.push(turns[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (claim.length !== 0) dir = claim.shift();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
claim = [];
|
|
|
|
//We are playing a little bit more cautious when we are outside and have a
|
|
|
|
//lot of land
|
2022-11-12 04:28:24 -05:00
|
|
|
const weights = [5, 5, 5, 5];
|
2019-01-15 10:42:15 -05:00
|
|
|
weights[dir] = 50;
|
|
|
|
weights[mod(dir + 2)] = -9999;
|
|
|
|
|
2020-07-24 03:22:41 -04:00
|
|
|
for (var nd = 0; nd < 4; nd++) {
|
|
|
|
for (var S = 1; S < 20; S++) {
|
2019-01-15 10:42:15 -05:00
|
|
|
var nr = MOVES[nd][0] * S + row;
|
|
|
|
var nc = MOVES[nd][1] * S + col;
|
|
|
|
|
2019-02-21 12:39:14 -05:00
|
|
|
if (nr < 0 || nc < 0 || nr >= consts.GRID_COUNT || nc >= consts.GRID_COUNT) {
|
2019-01-15 10:42:15 -05:00
|
|
|
if (S > 1) weights[nd]--;
|
|
|
|
else weights[nd] = -9999;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (user.tail.hitsTail(new Loc(nr, nc))) {
|
|
|
|
if (S > 1) weights[nd] -= 50 - S;
|
|
|
|
else weights[nd] = -9999;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (grid.get(nr, nc) === user) weights[nd] += 10 + S;
|
|
|
|
|
|
|
|
var tailed = undefined;
|
2020-07-24 03:22:41 -04:00
|
|
|
for (var o of others) {
|
2019-01-15 10:42:15 -05:00
|
|
|
if (o.tail.hitsTail(new Loc(nr, nc))) {
|
|
|
|
tailed = o;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tailed) {
|
|
|
|
if (o.name.indexOf("PAPER") != -1) weights[nd] += 3 * (30 - S); //Don't really try to kill our own kind
|
|
|
|
else weights[nd] += 30 * (30 - S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//View a selection of choices based on the weights we computed
|
|
|
|
var choices = [];
|
2020-07-24 03:22:41 -04:00
|
|
|
for (var d = 0; d < 4; d++) {
|
|
|
|
for (var S = 1; S < weights[d]; S++) {
|
2019-01-15 10:42:15 -05:00
|
|
|
choices.push(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (choices.length === 0) choices.push(dir);
|
|
|
|
dir = choices[Math.floor(Math.random() * choices.length)];
|
|
|
|
}
|
2020-07-24 03:11:35 -04:00
|
|
|
client.changeHeading(dir);
|
|
|
|
}
|
2017-11-17 02:49:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function calcFavorability(params) {
|
2019-01-15 10:42:15 -05:00
|
|
|
return params.portion + params.kills * 50 + params.survival / 100;
|
2017-11-17 02:49:43 -05:00
|
|
|
}
|
|
|
|
|
2022-11-12 04:28:24 -05:00
|
|
|
client.setAllowAnimation(false);
|
|
|
|
client.setRenderer({
|
2019-01-15 10:42:15 -05:00
|
|
|
addPlayer: function(player) {
|
|
|
|
playerPortion[player.num] = 0;
|
|
|
|
},
|
|
|
|
disconnect: function() {
|
2020-07-24 03:11:35 -04:00
|
|
|
const dt = (endFrame - startFrame);
|
2019-01-15 10:42:15 -05:00
|
|
|
startFrame = -1;
|
|
|
|
|
2019-02-22 00:22:21 -05:00
|
|
|
console.log(`[${new Date()}] I died... (survived for ${dt} frames.)`);
|
2022-11-12 07:38:09 -05:00
|
|
|
console.log(`[${new Date()}] I killed ${client.getKills()} player(s).`);
|
2019-02-21 11:19:33 -05:00
|
|
|
setTimeout(connect, 5000);
|
2019-01-15 10:42:15 -05:00
|
|
|
},
|
|
|
|
removePlayer: function(player) {
|
|
|
|
delete playerPortion[player.num];
|
|
|
|
},
|
|
|
|
setUser: function(u) {
|
|
|
|
user = u;
|
|
|
|
},
|
2022-11-12 04:28:24 -05:00
|
|
|
update,
|
2019-01-15 10:42:15 -05:00
|
|
|
updateGrid: function(row, col, before, after) {
|
|
|
|
before && playerPortion[before.num]--;
|
|
|
|
after && playerPortion[after.num]++;
|
|
|
|
}
|
2022-11-12 04:28:24 -05:00
|
|
|
});
|
2017-11-17 02:49:43 -05:00
|
|
|
|
|
|
|
connect();
|