Last active
August 14, 2018 13:35
-
-
Save Radvylf/82b38cea41495c4cc686f3d78e23fa3f to your computer and use it in GitHub Desktop.
Gold Collectors KoTH controller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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