forked from ilikecats/papercats
First generation of bots!
This commit is contained in:
parent
efd5f58b9e
commit
d83ec69553
@ -5,20 +5,158 @@ if (process.argv.length < 3) {
|
||||
|
||||
var core = require("../game-core");
|
||||
var client = require("../client");
|
||||
var user;
|
||||
|
||||
var GRID_SIZE = core.GRID_SIZE;
|
||||
var CELL_WIDTH = core.CELL_WIDTH;
|
||||
var MOVES = [[-1, 0], [0, 1], [1, 0], [0, -1]]
|
||||
|
||||
var AGGRESSIVE = Math.random();
|
||||
var THRESHOLD = 10;
|
||||
|
||||
var startFrame = -1;
|
||||
var endFrame = -1;
|
||||
var coeffs = [1,3,1,1,3];
|
||||
var grid, others, user;
|
||||
var DIST_TYPES = {
|
||||
land: {
|
||||
check: function(loc) { return grid.get(loc.row, loc.col) === user; },
|
||||
coeff: function() {return coeffs[0];}
|
||||
}, tail: {
|
||||
check: function(loc) {return tail(user, loc)},
|
||||
coeff: function() {return -coeffs[1];}
|
||||
}, oTail: {
|
||||
check: foundProto(tail),
|
||||
coeff: function() {return AGGRESSIVE * coeffs[2];}
|
||||
}, other: {
|
||||
check: foundProto(function(other, loc) { return other.row === this.row && other.col === this.col; }),
|
||||
coeff: function() {return -(1 - AGGRESSIVE) * coeffs[3];}
|
||||
}, edge: {
|
||||
check: function(loc) {return loc.row <= 1 || loc.col <= 1 || loc.row >= GRID_SIZE - 1 || loc.col >= GRID_SIZE - 1},
|
||||
coeff: function() {return -coeffs[4];}
|
||||
}
|
||||
};
|
||||
|
||||
function foundProto(func) {
|
||||
return function(loc) {
|
||||
return others.some(function(other) {
|
||||
return func(other, loc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function connect() {
|
||||
client.connectGame(process.argv[2], process.argv[3] || '[BOT]', function(success, msg) {
|
||||
});
|
||||
}
|
||||
|
||||
function Loc(row, col, step) {
|
||||
if (this.constructor != Loc) {
|
||||
return new Loc(row, col, step);
|
||||
}
|
||||
|
||||
this.row = row;
|
||||
this.col = col;
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
//Projects vector b onto vector a
|
||||
function project(a, b) {
|
||||
var factor = (b[0] * a[0] + b[1] * a[1]) / (a[0] * a[0] + a[1] * a[1]);
|
||||
return [factor * a[0], factor * a[1]];
|
||||
}
|
||||
|
||||
function tail(player, loc) {
|
||||
return player.tail.hitsTail(loc);
|
||||
}
|
||||
|
||||
function traverseGrid(dir) {
|
||||
steps = new Array(GRID_SIZE * GRID_SIZE);
|
||||
for (var i in steps) {
|
||||
steps[i] = -1;
|
||||
}
|
||||
|
||||
distWeights = {};
|
||||
for (var type in DIST_TYPES) {
|
||||
distWeights[type] = 0;
|
||||
}
|
||||
|
||||
var row = user.row, col = user.col;
|
||||
var minRow = Math.max(0, row - 10), maxRow = Math.min(GRID_SIZE, row + 10);
|
||||
var minCol = Math.max(0, col - 10), maxCol = Math.min(GRID_SIZE, col + 10);
|
||||
|
||||
var proj = 0;
|
||||
for (var i = 1; i >= -1; i-=2) {
|
||||
proj = (1 + THRESHOLD) * i;
|
||||
while (proj != 0) {
|
||||
proj -= i;
|
||||
var normRange = Math.abs(proj);
|
||||
for (var norm = -normRange; norm <= normRange; norm++) {
|
||||
for (var distType in distWeights) {
|
||||
var move = MOVES[dir];
|
||||
var delta = THRESHOLD - Math.abs(proj);
|
||||
var dist = Math.sign(proj) * delta * delta / (Math.abs(norm) + 1)
|
||||
var loc = {row: proj * move[0] + norm * move[1], col: proj * move[1] + norm * move[0]};
|
||||
|
||||
loc.row += user.row;
|
||||
loc.col += user.col;
|
||||
|
||||
if (loc.row < 0 || loc.row >= GRID_SIZE || loc.col < 0 || loc.col >= GRID_SIZE) {
|
||||
continue;
|
||||
}
|
||||
if (DIST_TYPES[distType].check(loc)) {
|
||||
distWeights[distType] += dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distWeights;
|
||||
}
|
||||
|
||||
function printGrid() {
|
||||
var chars = new core.Grid(GRID_SIZE);
|
||||
for (var r = 0; r < GRID_SIZE; r++) {
|
||||
for (var c = 0; c < GRID_SIZE; c++) {
|
||||
if (tail(user, {row: r, col: c})) {
|
||||
chars.set(r, c, 't');
|
||||
} else {
|
||||
var owner = grid.get(r, c);
|
||||
chars.set(r, c, owner ? '' + owner.num % 10 : '.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var p of others) {
|
||||
chars.set(p.row, p.col, 'x');
|
||||
}
|
||||
chars.set(user.row, user.col, '^>V<'[user.currentHeading]);
|
||||
|
||||
var str = '';
|
||||
for (var r = 0; r < GRID_SIZE; r++) {
|
||||
str += '\n';
|
||||
for (var c = 0; c < GRID_SIZE; c++) {
|
||||
str += chars.get(r, c);
|
||||
}
|
||||
}
|
||||
console.log(str);
|
||||
}
|
||||
|
||||
client.allowAnimation = false;
|
||||
client.renderer = {
|
||||
disconnect: function() {
|
||||
console.log("I died...");
|
||||
var dt = (endFrame - startFrame);
|
||||
startFrame = -1;
|
||||
|
||||
console.log("I died... (survived for " + dt + " frames.)");
|
||||
console.log("I killed " + client.kills + " player(s).");
|
||||
console.log("Coefficients: " + coeffs)
|
||||
|
||||
var mutation = Math.min(10, Math.pow(2, -dt / 150));
|
||||
for (var i = 0; i < coeffs.length; i++) {
|
||||
coeffs[i] += Math.random() * mutation * 2 - mutation;
|
||||
}
|
||||
|
||||
connect();
|
||||
},
|
||||
|
||||
@ -27,10 +165,61 @@ client.renderer = {
|
||||
},
|
||||
|
||||
update: function(frame) {
|
||||
if (frame % 6 == 1)
|
||||
{
|
||||
//TODO: decide move.
|
||||
client.changeHeading(Math.floor(Math.random() * 4));
|
||||
if (startFrame == -1) {
|
||||
startFrame = frame;
|
||||
}
|
||||
endFrame = frame;
|
||||
|
||||
if (frame % 6 == 1) {
|
||||
grid = client.grid;
|
||||
others = client.getOthers();
|
||||
|
||||
//printGrid();
|
||||
|
||||
var weights = [0, 0, 0, 0];
|
||||
for (var d of [3, 0, 1]) {
|
||||
var weight = 0;
|
||||
|
||||
d = (d + user.currentHeading) % 4;
|
||||
distWeights = traverseGrid(d);
|
||||
|
||||
var str = d + ": "
|
||||
for (var distType in DIST_TYPES) {
|
||||
var point = distWeights[distType] * DIST_TYPES[distType].coeff();
|
||||
weight += point;
|
||||
str += distType + ": " + point + ", ";
|
||||
}
|
||||
//console.log(str);
|
||||
weights[d] = weight;
|
||||
}
|
||||
|
||||
var low = Math.min(0, Math.min.apply(this, weights));
|
||||
var total = 0;
|
||||
|
||||
weights[(user.currentHeading + 2) % 4] = low;
|
||||
for (var i = 0; i < weights.length; i++) {
|
||||
weights[i] -= low * (1 + Math.random());
|
||||
total += weights[i];
|
||||
}
|
||||
|
||||
if (total == 0) {
|
||||
for (var d of [-1, 0, 1]) {
|
||||
d = (d + user.currentHeading) % 4;
|
||||
while (d < 0) d += 4;
|
||||
weights[d] = 1;
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
//console.log(weights)
|
||||
|
||||
//Choose a random direction from the weighted list
|
||||
var choice = Math.random() * total;
|
||||
var d = 0;
|
||||
while (choice > weights[d]) {
|
||||
choice -= weights[d++];
|
||||
}
|
||||
client.changeHeading(d);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
16
client.js
16
client.js
@ -178,6 +178,20 @@ function changeHeading(newHeading) {
|
||||
}
|
||||
}
|
||||
|
||||
function getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
function getOthers() {
|
||||
var ret = [];
|
||||
for (var p of players) {
|
||||
if (p !== user) {
|
||||
ret.push(p);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getPlayers() {
|
||||
return players.slice();
|
||||
}
|
||||
@ -345,7 +359,7 @@ function update() {
|
||||
}
|
||||
|
||||
//Export stuff
|
||||
var funcs = [connectGame, changeHeading, getPlayers];
|
||||
var funcs = [connectGame, changeHeading, getOthers, getPlayers, getUser];
|
||||
funcs.forEach(function (f) {
|
||||
exports[f.name] = f;
|
||||
});
|
||||
|
@ -661,6 +661,20 @@ function changeHeading(newHeading) {
|
||||
}
|
||||
}
|
||||
|
||||
function getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
function getOthers() {
|
||||
var ret = [];
|
||||
for (var p of players) {
|
||||
if (p !== user) {
|
||||
ret.push(p);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getPlayers() {
|
||||
return players.slice();
|
||||
}
|
||||
@ -828,7 +842,7 @@ function update() {
|
||||
}
|
||||
|
||||
//Export stuff
|
||||
var funcs = [connectGame, changeHeading, getPlayers];
|
||||
var funcs = [connectGame, changeHeading, getOthers, getPlayers, getUser];
|
||||
funcs.forEach(function (f) {
|
||||
exports[f.name] = f;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user