Skip to content

Instantly share code, notes, and snippets.

@Radvylf
Last active August 14, 2018 13:35
Show Gist options
  • Save Radvylf/82b38cea41495c4cc686f3d78e23fa3f to your computer and use it in GitHub Desktop.
Save Radvylf/82b38cea41495c4cc686f3d78e23fa3f to your computer and use it in GitHub Desktop.
Gold Collectors KoTH controller
//ATTENTION:
//Paste this code into the Developer Console on about:blank, and press enter. To activate, type activateCanvas(fps, turns)
var botData =
[
{
name: "Bot Name",
run: function() {
//function
}
}, {
name: "Enemy Bot",
run: function() {
//2nd function
}
}
];
var coinLocations = [];
var botCount = botData.length;
var arenaSize = botCount + 4;
var botPos = [];
var eventLog = [];
var botNotes = {
storeData: function(key, value) {
var bot = botData[botNotes.storeData.caller.index];
bot.kvpData[key] = value;
},
getData: function(key) {
var bot = botData[botNotes.getData.caller.index];
return bot.kvpData[key] || null;
}
};
function typeDecorate(value) {
var type = ({}).toString.call(value).match(/\s([a-zA-Z]+)/)[1];
if (type == "String") {
return "\"" + value + "\"";
} else if (type == "Array") {
return "[" + value.join(", ") + "]";
} else if (type == "Object") {
return JSON.stringify(value);
} else if (type == "Number") {
if (Math.floor(value) == value) {
return value + ".0";
} else if (value.toString().split(".")[1].length > 3) {
return Math.floor(value) + "...";
} else {
return value;
}
} else {
return value;
}
}
function logEvent(txt) {
eventLog.push("[" + turnCanvas.inc + "] " + txt);
}
function randInt(min, max) {
return Math.floor(Math.random() * ((max - min) + 1)) + min;
}
function botSetup() {
var n, close;
for (var b, r, i = 0; i < botCount; i++) {
b = botData[i];
b.coins = 0;
b.loc = [];
b.kvpData = {};
b.alive = true;
b.run.index = i;
r = getValidPosition();
logEvent("Set position of bot " + b.name + " to " + typeDecorate(r));
b.loc = r;
botPos[i] = r;
}
for (i = 0; i < 5; i++) {
r = getValidPosition();
logEvent("Set position of coin " + i + " to " + typeDecorate(r));
coinLocations[i] = r;
}
}
function runBots() {
var ind, s, l, n, names, c, coins, botSet = [];
var botsAlive = botPos.filter(function(a){return !(arrayEqual(a, [-2,-2]))});
botsAlive.forEach(function(arr){
for (n = 0; n < botCount; n++) {
if (botPos[n] == arr) {
coins = botData[n].coins;
}
}
botSet.push([arr[0], arr[1], coins]);
});
for (var m, b, i = 0; i < botCount; i++) {
b = botData[i];
if (b.alive) {
m = b.run({locationX: b.loc[0], locationY: b.loc[1], coins: b.coins, arenaLength: arenaSize}, JSON.parse(JSON.stringify(botSet.filter((a)=>(a[0]!=b.loc[0] || a[1]!=b.loc[1])))), JSON.parse(JSON.stringify(coinLocations)));
if (m === "north") {
b.loc[1] -= 1;
} else if (m === "east") {
b.loc[0] += 1;
} else if (m === "south") {
b.loc[1] += 1;
} else if (m === "west") {
b.loc[0] -= 1;
} else {
//Bot was lazy/indecisive/made a typo
}
}
}
var pos = [];
var pbot = [];
var col = [];
var dat = [];
for (i = 0; i < botCount; i++) {
b = botData[i];
if (b.alive) {
if (arrayIndex(pos, b.loc) != -1) { //if two bots in same space
if (arrayIndex(col, b.loc) != -1) { //if three+ bots in same space
for (n = 0; n < dat.length; n++) {
l = dat[n];
if (l.loc == b.loc) {
l.count += 1;
l.indexes.push(n);
}
}
} else {
col.push(b.loc);
dat.push({loc:b.loc,count:1,indexes:[i,pbot[arrayIndex(pos, b.loc)]]});
}
} else {
pos.push(b.loc);
pbot.push(i);
}
}
}
names = [];
for (i = 0; i < dat.length; i++) {
l = dat[i];
s = l.indexes;
s.sort((a,b)=>(botData[b].coins - botData[a].coins)).forEach((a)=>{names.push(botData[a].name)});
c = botData[s[0]];
if (c.coins == botData[s[1]].coins) {
logEvent("Bots " + c.name + " and " + botData[s[1]].name + " both had " + c.coins + " coins, so " + names.slice(0,-1).join(', ') + " and " + names.slice(-1) + " died.");
for (n = 0; n < s.length; n++) {
b = botData[s[n]];
b.alive = false;
}
} else {
for (n = 1; n < s.length; n++) {
b = botData[s[n]];
c.coins += Math.ceil(b.coins * 0.85);
logEvent("Bot " + c.name + " ate " + b.name + " and gained " + Math.ceil(b.coins * 0.85) + " coins");
b.alive = false;
}
while (arrayIndex(coinLocations, c.loc) !== -1) {
ind = arrayIndex(coinLocations, c.loc);
if (ind === 0) {
logEvent("Bot " + c.name + " ate a gold coin after engaging in combat and winning")
c.coins += 5;
} else {
logEvent("Bot " + c.name + " won a fight over a silver coin");
c.coins += 2;
}
coinMove(ind);
}
}
}
for (i = 0; i < botCount; i++) {
b = botData[i];
while (b.alive && arrayIndex(coinLocations, b.loc) !== -1) {
ind = arrayIndex(coinLocations, b.loc);
if (ind === 0) {
//logEvent("Bot " + b.name + " discovered a gold coin");
b.coins += 5;
} else {
//logEvent("Bot " + b.name + " found a silver coin");
b.coins += 2;
}
coinMove(ind);
}
botPos[i] = b.loc;
if (!(b.alive)) {
botPos[i] = [-2,-2];
}
if ((b.loc[0] < 0 || b.loc[1] < 0 || b.loc[0] >= arenaSize || b.loc[1] >= arenaSize) && b.alive) {
b.alive = false;
logEvent("Bot " + b.name + " tired of this world, and jumped off its edge")
botPos[i] = [-2,-2];
}
}
}
function coinMove(ind) {
var r, x, y, n, close;
do {
r = [randInt(0, arenaSize - 1), randInt(0, arenaSize - 1)];
for (n = 0; n < botPos.length; n++) {
x = botPos[n][0];
y = botPos[n][1];
if (Math.abs(x - r[0]) <= 1 && Math.abs(y - r[1]) <= 1) {
close = true;
} else {
close = false;
}
}
} while (close);
coinLocations[ind] = r;
}
function arrayIndex(arr, inc) {
for (var i = 0; i < arr.length; i++) {
if (inc instanceof Array) {
if (arr[i] instanceof Array && arr[i].length == inc.length) {
for (var c = 0, n = 0; n < inc.length; n++) {
if (arr[i][n] === inc[n]) {
c++;
}
}
if (c == inc.length) {
return i;
}
}
} else if (arr[i] === inc) {
return i;
}
}
return -1;
}
function arrayEqual(arr, equ) {
if (arr.length !== equ.length) {
return false;
}
for (var i = 0; i < arr.length; i++) {
if (arr[i] !== equ[i]) {
return false;
}
}
return true;
}
//Positioning Program, made by N.P. and tested by Sundar
function getValidPosition() {
let pos = 0;
while (pos === 0) {
let x = randInt(0, arenaSize-1);
let y = randInt(0, arenaSize-1);
let allowed = true;
for (let i = 0; i < botPos.length; i++) {
let thisX = botPos[i][0];
let thisY = botPos[i][1];
if (Math.abs(thisX-x) <= 1 && Math.abs(thisY-y) <= 1) {
allowed = false;
}
}
if (allowed) {
pos = [x, y];
}
}
return pos;
}
//Auto-run function, created by RedwolfPrograms
function activateCanvas(fps, turns) {
turnCanvas.turns = turns;
logEvent("Began " + turns + " turn round at " + fps + " FPS");
turnCanvas.clear = setInterval(runMoves, 1000 / fps);
botSetup();
createLeaderboard();
}
function runMoves() {
if (turnCanvas.inc >= turnCanvas.turns) {
var survivorList = [];
for (var i = 0; i < botData.length; i++) {
if (botData[i].alive) {
survivorList.push(botData[i].name);
}
}
logEvent("Finished " + turnCanvas.turns + " turn round with " + survivorList.length + " bot(s) remaining: " + survivorList.join("; "));
clearInterval(turnCanvas.clear);
console.groupCollapsed("Event Log (" + eventLog.length + ")");
for (var n = 0; n < eventLog.length; n++) {
console.log(eventLog[n]);
}
console.groupEnd();
}
document.getElementById("Title").innerText = "Turn " + turnCanvas.inc++;
runBots();
updateCanvas();
updateLeaderboard();
}
//Append HTML and CSS for display
document.write("<style>body{background:#000;margin-left:5px}canvas{border:16px solid grey;background-color:#fff}h1{color:#fff}td,th{border:1px solid #000;padding-left:4px;padding-right:4px;background-color:#f8f8ff;text-align:left}</style><h1 id='Title'>Display</h1><canvas id='Canvas'></canvas><table id='leaderboard'><tr><th>Name<th>X<th>Y<th>Score</table>");
//Display program by N. P., who is awesome beyond belief
var squareSize = 16
var canvas = document.getElementById('Canvas')
canvas.width = arenaSize*squareSize
canvas.height = arenaSize*squareSize
var context = canvas.getContext('2d');
var turnCanvas = {turns: 0, inc: 0, clear: null};
function drawCircle(x, y, color) {
var trueX = x * squareSize + squareSize/2
var trueY = y * squareSize + squareSize/2
var radius = squareSize/8*3
context.beginPath();
context.arc(trueX, trueY, radius, 0, 2 * Math.PI, false);
context.fillStyle = color;
context.fill();
context.lineWidth = '1';
context.strokeStyle = '#000000';
context.stroke();
}
function drawBot(x, y, color) {
var lowX = x * squareSize
var lowY = y * squareSize
context.lineWidth = 1
context.strokeStyle = '#000000';
context.rect(lowX+.5, lowY+.5, squareSize-1, squareSize-1);
context.stroke()
context.fillStyle = color;
context.fillRect(lowX+1, lowY+1, squareSize-2, squareSize-2);
}
function updateCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height)
for (var i = 1; i < coinLocations.length; i++) {
drawCircle(coinLocations[i][0], coinLocations[i][1], '#b4b4b4')
}
drawCircle(coinLocations[0][0], coinLocations[0][1], '#ffd700')
for (var i = 0; i < botPos.length; i++) {
if (botPos[i][0] > -2) {
drawBot(botPos[i][0], botPos[i][1], botData[i].botColor)
}
}
}
function createLeaderboard() {
var table = document.getElementById('leaderboard')
for (var i = 0; i < botData.length; i++) {
var newRow = document.createElement('tr')
var newName = document.createElement('td')
var newX = document.createElement('td')
var newY = document.createElement('td')
var newScore = document.createElement('td')
newRow.id = botData[i].name + 'Row'
newName.id = botData[i].name + 'Name'
newX.id = botData[i].name + 'X'
newY.id = botData[i].name + 'Y'
newScore.id = botData[i].name + 'Score'
newName.innerHTML = botData[i]['name']
newRow.appendChild(newName)
newRow.appendChild(newX)
newRow.appendChild(newY)
newRow.appendChild(newScore)
table.appendChild(newRow)
}
}
function updateLeaderboard() {
for (var i = 0; i < botData.length; i++) {
var nameDisplay = document.getElementById(botData[i].name + 'Name')
var xDisplay = document.getElementById(botData[i].name + 'X')
var yDisplay = document.getElementById(botData[i].name + 'Y')
var scoreDisplay = document.getElementById(botData[i].name + 'Score')
if (!botData[i]['alive']) {
xDisplay.innerHTML = ''
yDisplay.innerHTML = ''
nameDisplay.style.color = 'grey'
scoreDisplay.style.color = 'grey'
scoreDisplay.innerHTML = botData[i]['coins']
} else {
xDisplay.innerHTML = botData[i]['loc'][0]
yDisplay.innerHTML = botData[i]['loc'][1]
scoreDisplay.innerHTML = botData[i]['coins']
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment