In this challenge, bots must survive as long as possible. In each turn, the bot with the most HP is eliminated.
This challenge is inspired by the Smallest unique number KoTH.
Results
After 100,000 rounds:
Jack: 63390
The Follower: 4942
The Algorithm: 2452
The Randomiser: 140
Toe Tipping: 0
EZ: 0
The Average: 0
LowProfile2: 0
Lower Profile: 0
The Bandwagon: 0
Fair Share: 0
Low Profile: 0
Game Details
- In each game, all bots start with 100 HP
- In each turn:
- All bots select an amount of HP to lose (minimum 1, inclusive)
- Each bot loses the amount of HP they returned
- All bots with 0 HP or less are eliminated
- The bot with the highest HP is eliminated
- If there is a tie for highest HP, all bots that tied are eliminated
- The last bot alive wins 1 point
- If all remaining bots are eliminated in the same turn, no points are awarded
- After a number of games (default is 1000), the winner is the bot with the most points
Bot Format
Each bot should be a JavaScript function, which is run once per turn. This function will be provided three arguments:
- The bot's HP
- The HP of all other bots as of the last turn, or 0 if dead
- Formatted as an array, will be randomly shuffled for each game
- An object which can be used for storage between turns
The return value of this function should be a number (minimum 1, inclusive), representing the amount of HP to take. If the return value is not a number or is less than 1, it defaults to 1.
Example Bot
Example Bot tries to keep its HP 2 below the previous turn's average.
function(hp, others, storage) {
var alive = others.filter(bot => bot > 0);
var avg = alive.reduce((a, b) => a + b, 0) / alive.length;
return hp - (avg - 2);
}
Controller
//Bots go in this object:
const bots = {
"Example Bot": function(hp, others, storage) {
var alive = others.filter(bot => bot > 0);
var avg = alive.reduce((a, b) => a + b, 0) / alive.length;
return hp - (avg - 2);
}
};
//games: Number of games to run
//log: An array of bot names to log info about, or empty array for game overviews
function runGames(games = 1000, log = null) {
let p = performance.now();
let botData = [];
for (let bot in bots)
botData.push({
name: bot,
run: bots[bot],
uid: 0,
hp: 0,
points: 0,
storage: {},
});
for (let g = 0; g < games; g++) {
let uids = new Array(botData.length).fill(0).map((a, b) => b);
let turn = 0;
if (log)
console.log("[0] Starting game " + (g + 1));
for (let j, i = uids.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
[uids[i], uids[j]] = [uids[j], uids[i]];
}
for (let i = 0; i < botData.length; i++) {
botData[i].uid = uids[i];
botData[i].hp = 100;
botData[i].storage = {};
}
do {
let hps = [];
let max, alive;
turn++;
for (let hp, b, i = 0; i < botData.length; i++) {
b = botData[i];
if (!b.hp)
continue;
try {
hp = Number(b.run(
b.hp,
botData.map(a => [a.uid, a.hp]).sort((a, b) => a[0] - b[0]).filter(a => a[0] != b.uid).map(a => a[1]),
b.storage
));
if (log && log.includes(b.name))
console.log("[" + turn + "] " + b.name + " (" + b.hp + "): " + hp);
} catch(e) {
hp = 100;
if (log && log.includes(b.name))
console.warn(b.name + " (" + JSON.stringify(b.storage) + "):\n" + (e.stack || e.message));
}
hps[i] = Number.isNaN(hp) ? 1 : Math.max(1, hp);
}
for (let i = 0; i < botData.length; i++) {
if (hps[i]) {
botData[i].hp = Math.max(0, botData[i].hp - hps[i]);
if (!botData[i].hp && log)
console.log("[" + turn + "] Eliminated: " + botData[i].name + " (0)");
}
}
alive = botData.filter(a => a.hp);
if (alive.length == 1)
alive[0].points += 1;
if (alive.length <= 1)
break;
max = Math.max(...botData.map(a => a.hp));
for (let i = 0; i < botData.length; i++) {
if (botData[i].hp == max) {
if (log)
console.log("[" + turn + "] Eliminated: " + botData[i].name + " (" + botData[i].hp + ")");
botData[i].hp = 0;
}
}
alive = botData.filter(a => a.hp);
if (alive.length == 1)
alive[0].points += 1;
if (alive.length <= 1)
break;
} while (1);
}
console.log(games + " game(s) completed (" + ((performance.now() - p) / 1000).toFixed(3) + "s):\n" + botData.map(a => [a.name, a.points]).sort((a, b) => b[1] - a[1]).map(a => a[0] + ": " + a[1]).join("\n"));
}
Rules
- Accessing the controller or other bots is not allowed
- There's no time limit, but keep within reason
- Any bots that error are eliminated
- Clarification: Fractional HP is allowed
- Deadline:
Wednesday, March 25, 12:00 UTC (8:00 EDT)Closed to submissions!