Skip to content

Instantly share code, notes, and snippets.

@Draco18s
Last active August 7, 2019 16:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Draco18s/2efbf95edcf98d6b1f264e26bbb669d1 to your computer and use it in GitHub Desktop.
Save Draco18s/2efbf95edcf98d6b1f264e26bbb669d1 to your computer and use it in GitHub Desktop.
//Copy and paste bot functions here:
function justFarm(me, others){
return farm();
}
function undyableBot(me, others, storage){
if(me.hp < 100 - (me.levels.heal + 5)*2){
return heal()
}else{
if(me.levels.heal < 10 && cost(me.levels.heal) / 2 < cost(me.levels.farm)){
if(me.gold >= cost(me.levels.heal)){
return upgrade("heal")
}else{
return farm()
}
}else{
if(me.gold >= cost(me.levels.farm)){
return upgrade("farm")
}else{
return farm()
}
}
}
}
function UnkillableBot(me){
if(me.hp <= 100 - (me.levels.heal + 5)){
return heal()
}else if(turn() % 10 == 0 && me.shield < 800) {
return shield()
}else{
if(me.gold >= cost(me.levels.shield) && me.levels.shield <= 9){
return upgrade("shield")
}else if(me.gold >= cost(me.levels.farm)){
return upgrade("farm")
}else{
if(me.shield < 500 && me.levels.shield > 4) {
return shield()
}
return farm()
}
}
}
function scavengerBot(me, others) {
if (me.shield < (me.levels.shield * 1.5 + 5)) {
return shield();
}
var currentAttack = 1.25 * me.levels.attack + 5;
var hasVictim = false;
var victimUid = 0;
var maxWorth = 0;
for (var i = 0; i < others.length; i++) {
var hp = others[i].hp;
var worth = others[i].worth;
if (hp <= currentAttack && worth > maxWorth) {
hasVictim = true;
victimUid = others[i].uid;
maxWorth = worth;
}
}
if (hasVictim) {
return attack(victimUid);
}
if (me.gold >= cost(me.levels.attack)) {
return upgrade("attack");
}
if (me.gold >= cost(me.levels.shield)) {
return upgrade("shield");
}
return shield();
}
function bullyBot(me, others, storage){
if(turn()==1){return farm();}
if(storage.bullyTarget==null){storage.bullyTarget=others[0].uid;}
var targetlives = false;
for(var i = 0; i < others.length; i++) {
if (others[i].uid == storage.bullyTarget) {
targetlives = true;
break;
}
}
if(!targetlives){storage.bullyTarget = others[0].uid;}
return stun(storage.bullyTarget);
}
function indestructible(me){
if (me.hp < 100) {
return heal();
} else if (me.shield < 15) {
return shield();
} else {
if (me.gold >= cost(me.levels.shield)) {
return upgrade("shield");
} else if (me.gold >= cost(me.levels.farm)) {
return upgrade("farm");
} else {
return farm();
}
}
}
function sniperBot(me, others){
if(me.hp < 30) return heal();
for(var i = 0; i < others.length; i++)if(others[i].attack > me.hp)return heal();
var target = -1;
var targetWorth = me.levels.farm * 2 + 5;
for(var i = 0; i < others.length; i++) {
if (others[i].hp <= 1.25 * me.levels.attack + 5 && others[i].worth / 2 > targetWorth) {
target= others[i].uid;
targetWorth = others[i].worth / 2;
}
}
if(target!=-1) return attack(target);
if(me.gold >= cost(me.levels.farm)) return upgrade("farm");
if(me.hp < 50 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
return farm();
}
function Optimist(me, others, storage) {
if (me.hp < 10)
return heal();
if ( (me.hp + me.shield) < 50 )
return shield();
if (me.gold >= cost(me.levels.farm) && cost(me.levels.farm) < 0.8 * (1000 - turn()))
return upgrade("farm");
rich_bots = others.sort( (x,y) => y.worth - x.worth );
potential_victim = rich_bots.find( bot => bot.hp <= me.levels.attack * 1.25 + 5 );
if (potential_victim)
return attack(potential_victim.uid);
if (me.gold < rich_bots[0].worth + cost(me.levels.farm) + 25)
return farm();
if (me.levels.heal < me.levels.farm)
return upgrade("heal");
if (me.levels.shield < me.levels.heal)
return upgrade("shield");
if (me.levels.attack < me.levels.shield)
return upgrade("attack");
return shield();
}
function BullyDozerBot(me, others, storage){
if(me.gold >= cost(me.levels.attack) && (storage.bullyTarget && storage.bullyTarget.hp < 500)) {
return upgrade("attack");
}
if(storage.bullyTarget==null){
storage.bullyTarget=others.sort((a,b) => a.hp - b.hp)[0];
}
potential_victim = others.find( bot => bot.hp <= me.levels.attack * 1.25 + 5 );
if (potential_victim) {
return attack(potential_victim.uid);
}
var targetlives = false;
for(var i = 0; i < others.length; i++) {
if (others[i] == storage.bullyTarget) {
targetlives = true;
break;
}
}
if(!targetlives){
storage.bullyTarget=others.sort((a,b) => a.hp - b.hp)[0];
}
if(storage.bullyTarget.hp >= 500) {
if(me.gold >= cost(me.levels.farm)) {
return upgrade("farm");
}
for(var i = 0; i < others.length; i++){
if(others[i].attack*1.25+10 > me.hp){
return heal();
}
}
return farm();
}
return attack(storage.bullyTarget.uid);
}
function menShengFaDaCai(me, others) {
// heal if needed
const maxAttack = Math.max(...others.map(bot => bot.attack));
const maxAttackCost = maxAttack * maxAttack + 5;
const othersHp = others.map(bot => bot.hp).sort();
const targetHp = othersHp[Math.ceil(othersHp.length / 2)];
if (me.hp < 95 && me.hp < Math.max(maxAttackCost * 2, targetHp, 50)) return heal();
// upgrade heal and farm if possible
const { heal: healLevel, farm: farmLevel } = me.levels;
const gain = (heal, farm) => ((5 + heal) / 2) * (2 * farm + 5) / ((5 + heal) / 2 + 1);
const gain0 = gain(healLevel, farmLevel);
const gainUpgradeHeal = gain(healLevel + 1, farmLevel);
const gainUpgradeFarm = gain(healLevel, farmLevel + 1);
const gainUpgradeHealPerGold = (gainUpgradeHeal - gain0) / cost(healLevel);
const gainUpgradeFarmPerGold = (gainUpgradeFarm - gain0) / cost(farmLevel);
const preferUpgradeHeal = gainUpgradeHealPerGold > gainUpgradeFarmPerGold;
const mayOffer = type => me.gold >= cost(me.levels[type]);
if (preferUpgradeHeal && mayOffer('heal')) return upgrade('heal');
if (!preferUpgradeHeal && mayOffer('farm')) return upgrade('farm');
// keep farming
return farm();
}
function smartFarmer(me, others){
if(me.hp < 13) return heal();
for(var i = 0; i < others.length; i++)if(others[i].attack * 1.25 + 5 > me.hp)return heal();
if(me.gold >= cost(me.levels.farm)) return upgrade("farm");
if(me.levels.heal < 9 && me.levels.farm > me.levels.heal + 7 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
return farm();
}
function pacifistWinnerBot(me, others, storage) {
if(!storage.start){
storage.start=true;
storage.others = others;
}
others.map(bot =>
storage.others.map(
bot2 => {if(bot2.uid==bot.uid)bot=bot2}//update worth, hp, attack level
)
);
const maxAtk = 5+1.25*Math.max(storage.others.map(bot => bot.attack));
if(storage.win || ((me.gold > Math.max(storage.others.map(bot => bot.worth))+25) && storage.others.reduce((bot,x) => x+(bot.hp<=0),0)==1)){
storage.win=true;
return stun(storage.others.filter(bot => bot.hp>0)[0].uid);
}
if(me.hp < 2+maxAtk) return heal();
if(me.hp < 2+maxAtk*2) return shield();
if(me.levels.healing<1 && me.gold>cost(me.levels.healing)) return upgrade("heal");
if((me.gold > cost(me.levels.shield)) && (1.5*me.levels.shield+5 < 2*maxAtk)) return upgrade("shield");
if(me.gold > 50+cost(me.levels.farm)) return upgrade("farm");
return farm();
}
function FizzBuzz(me, others, storage) {
if (!storage.target) storage.target = others[0].uid;
const uids = others.map(x=>x.uid);
if(!uids.includes(storage.target) || (turn() % 30 === 0
&& others[uids.indexOf(storage.target)].hp>30))
storage.target = others[0].uid;
if (cost(me.levels.farm) < me.gold) return upgrade("farm");
if (turn() % 15 === 0) return heal();
if (turn() % 3 === 0) return farm();
if (turn() % 5 === 0) return heal();
if (cost(me.levels.attack) < me.gold) return upgrade("attack");
return attack(storage.target);
}
function campBot(self,others,storage){
if(!storage.victimBlacklist){
storage.victimBlacklist=[]
}
let turnsLeft=999-turn()
function findVictim(){
let potentialVictims=others.filter(bot=>bot.worth>70&&((bot.attack>1&&bot.hp<200)||bot.hp<80)&&!storage.victimBlacklist.includes(bot.uid))
if(potentialVictims.length>0){
let victim=potentialVictims[Math.floor(Math.random()*potentialVictims.length)]
storage.victimUid=victim.uid
storage.victimPrevHp=victim.hp
storage.prevMove="attack"
return attack(victim.uid)
}else{
storage.prevMove="farm"
return farm()
}
}
if(self.hp<=(95-self.levels.heal)){
storage.prevMove="heal"
return heal()
} else if(self.shield<=50){
return shield()
} else if(self.gold>=cost(self.levels.attack)&&turnsLeft>100&&self.levels.attack<=3){
storage.prevMove="upgrade"
return upgrade("attack")
} else if(self.gold>=cost(self.levels.farm)&&cost(self.levels.farm)<turnsLeft*(2*(self.levels.farm+1)+5)){
storage.prevMove="upgrade"
return upgrade("farm")
}else if(self.gold>=cost(self.levels.heal)&&cost(self.levels.heal)<turnsLeft/(self.levels.heal+6)*(2*self.levels.farm+5)&&self.levels.heal<=2){
storage.prevMove="upgrade"
return upgrade("heal")
}else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=3){
return upgrade("shield")
}else if(!storage.victimUid){
return findVictim()
}else if(Object.values(others).map(bot=>bot.uid).includes(storage.victimUid)){
let victimCurrHp=Object.values(others).filter(bot=>bot.uid==storage.victimUid)[0].hp
if(storage.victimPrevHp<victimCurrHp&&storage.prevMove==="attack"){
storage.victimBlacklist.push(storage.victimUid)
storage.victimUid=undefined
return findVictim()
}else{
storage.victimPrevHp=victimCurrHp
storage.prevMove="attack"
return attack(storage.victimUid)
}
}else{
storage.victimUid=undefined
return findVictim()
}
}
function switzerland(self,others,storage){
let turnsLeft=999-turn()
let lowestHpBots=others.sort((a,b)=>a.hp-b.hp)
if(self.hp<=(95-self.levels.heal)){
return heal()
}else if(lowestHpBots[0]&&lowestHpBots[0].hp<20&&lowestHpBots[0].worth/2>2*self.levels.farm+5&&self.hp+self.shield>=110){
return attack(lowestHpBots[0].uid)
} else if(self.shield<=50||self.shield<=4500/others.length&&self.shield<=500&&turn()>=20||lowestHpBots[1]&&lowestHpBots[1].hp>self.hp+self.shield){
return shield()
}else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=8){
return upgrade("shield")
} else if(self.gold>=cost(self.levels.farm)&&(turnsLeft+1)*(2*(self.levels.farm)+5)<turnsLeft*(2*(self.levels.farm+1)+5)){
return upgrade("farm")
} else if(self.gold>=cost(self.levels.heal)&&(turnsLeft+1)/(self.levels.heal+5)*(2*self.levels.farm+5)<turnsLeft/(self.levels.heal+6)*(2*self.levels.farm+5)&&self.levels.heal<=2){
return upgrade("heal")
}else{
return farm()
}
}
function guardian(self,others,storage){
if(!storage.victimBlacklist){
storage.victimBlacklist=[]
}
let turnsLeft=999-turn()
function findVictim(){
let potentialVictims=others.filter(bot=>!storage.victimBlacklist.includes(bot.uid))
if(potentialVictims.length>0){
let victim=potentialVictims.reduce((el, em) => el.attack > em.attack ? el : em);
storage.victimUid=victim.uid
storage.victimPrevHp=victim.hp
storage.prevMove="attack"
return attack(victim.uid)
}else{
storage.prevMove="farm"
return farm()
}
}
if(self.hp<=(95-self.levels.heal)){
storage.prevMove="heal"
return heal()
} else if(self.gold>=cost(self.levels.attack)){
storage.prevMove="upgrade"
return upgrade("attack")
} else if(self.gold>=cost(self.levels.farm)&&turnsLeft>100&&self.levels.heal<=1){
storage.prevMove="upgrade"
return upgrade("farm")
} else if(!storage.victimUid){
return findVictim()
}else if(Object.values(others).map(bot=>bot.uid).includes(storage.victimUid)){
let victimCurrHp=Object.values(others).filter(bot=>bot.uid==storage.victimUid)[0].hp
if(storage.victimPrevHp<victimCurrHp&&storage.prevMove==="attack"){
storage.victimBlacklist.push(storage.victimUid)
storage.victimUid=undefined
return findVictim()
}else{
storage.victimPrevHp=victimCurrHp
storage.prevMove="attack"
return attack(storage.victimUid)
}
}else{
storage.victimUid=undefined
return findVictim()
}
}
function equalizer(me, others, storage){
if(storage.agroKilled == null)storage.agroKilled = false;
if(!storage.agroKilled){
if(storage.blacklist == null)storage.blacklist = [];
if(storage.lastAttack == null)storage.lastAttack = -1;
var maxAtk = 0;
var maxAtkUid = -1;
var maxAtkHealth = 0;
for(var i = 0; i < others.length; i++)if(others[i].uid == storage.lastAttack){
maxAtk = others[i].attack*1.25+5;
maxAtkUid = storage.lastAttack;
maxAtkHealth = others[i].hp;
}
for(var i = 0; i < others.length; i++){
if(storage.lastAttack == others[i].uid && others[i].hp >= storage.lastHealth){
maxAtk = 0;
maxAtkUid = -1;
maxAtkHealth = 0;
storage.blacklist.push(others[i].uid);
}
}
storage.lastAttack = -1;
var willHeal;
for(var i = 0; i < others.length; i++)if(others[i].attack*1.25+5 > maxAtk){
willHeal = false
for(var j = 0; j < storage.blacklist.length; j++)if(others[i].uid==storage.blacklist[j])willHeal = true;
if(!willHeal){
maxAtk = others[i].attack*1.25+5;
maxAtkUid = others[i].uid;
maxAtkHealth = others[i].hp;
}
}
if(me.hp < maxAtk) return heal();
if(me.hp <= 100 - me.levels.heal - 5) return heal();
var target = -1;
var targetWorth = me.levels.farm * 2 + 5;
for(var i = 0; i < others.length; i++) {
if (others[i].hp <= maxAtk && others[i].worth / 2 > targetWorth) {
target= others[i].uid;
targetWorth = others[i].worth / 2;
}
}
if(target!=-1) return attack(target);
if(me.gold >= cost(me.levels.attack)) return upgrade("attack");
if(me.levels.heal + 7 < me.levels.attack && me.levels.heal < 9 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
if(maxAtkUid!=-1){
storage.lastAttack = maxAtkUid;
storage.lastHealth = maxAtkHealth;
return attack(maxAtkUid);
}
storage.agroKilled = true;
}
if(me.hp < 30) return heal();
if(me.gold > cost(me.levels.farm)) return upgrade("farm");
return farm();
}
function Moody(me, others, storage) {
health = me.hp + me.shield;
damage = storage.previous_health - health;
storage.previous_health = health;
if( damage > 2 ) {
storage.fear = 2;
}
if( storage.fear ) {
storage.fear -= 1;
if( me.gold >= cost(me.levels.heal) )
return upgrade("heal");
return heal();
}
if ( me.hp <= 50 ) {
return heal();
}
if (cost(me.levels.farm) < 0.15 * (1000 - turn())) {
if( me.gold >= cost(me.levels.farm) )
return upgrade("farm");
if( me.gold >= cost(me.levels.heal) )
return upgrade("heal");
return farm();
}
rich_bots = others.sort( (x,y) => y.worth - x.worth );
richest_enemy = rich_bots[0];
if (richest_enemy.hp >= storage.target_hp) {
storage.anger = true;
}
storage.target_hp = NaN;
if (storage.anger) {
if( me.gold >= cost(me.levels.attack) ) {
storage.anger = 0;
return upgrade("attack");
}
return farm();
}
storage.target_hp = richest_enemy.hp;
return attack(richest_enemy.uid);
}
function Opportunist(me, others, storage) {
// Initializing and keeping track of selfWorth
if (turn() == 1) {
storage.selfWorth = 0;
}
else if (storage.previousGold < me.gold) {
storage.selfWorth += (me.gold - storage.previousGold);
}
storage.previousGold = me.gold;
// Me stats
var me_attack = 1.25 * me.levels.attack + 5;
var me_heal = me.levels.heal + 5;
// Look for the juiciest hunk of loot
// If there are multiple of the highest worth, the last is chosen
var choice = others[0].uid;
var mostWorthy = -1;
for (var i = 0; i < others.length; i++) {
worth = others[i].worth
if (others[i].hp <= me_attack && worth >= mostWorthy) {
choice = others[i].uid;
mostWorthy = worth;
}
}
// Actions in order of priority
// The juicy targets must be worth the action
if (mostWorthy > (storage.selfWorth * 0.25) ) {
return attack(choice);
}
else if (me.hp <= 100 - me_heal) {
return heal()
}
else if (me.gold >= cost(me.levels.farm)) {
return upgrade("farm");
}
else if (me.gold >= cost(me.levels.attack)) {
return upgrade("attack");
}
else if (me.gold >= cost(me.levels.heal)) {
return upgrade("heal");
}
else {
return farm();
}
}
function killBot(me, others, storage) {
// If I lost health since my last check, shield.
if (me.hp < storage.hp){
storage.hp = me.hp;
return shield();
}
storage.hp = me.hp;
health = Math.min(...others.map(o => o.hp));
// If I have the least health or can be one-shot, shield.
if (others.some(o => o.attack * 1.25 + 5 >= me.hp + me.shield) || (health > me.hp + me.shield && health < 500)) return shield();
// If I can kill someone, kill them!
targets = others.filter(o => o.hp < me.attack);
if (targets.length > 0){
wealth = Math.max(...targets.map(o => o.worth));
targets = targets.filter(o => o.worth == wealth);
target = targets[Math.floor(Math.random()*targets.length)];
return attack(targets[0].uid);
}
// If I have the money, upgrade shielding or attack
if (me.levels.shield <= me.levels.attack){
if (cost(me.levels.shield) < me.gold) return upgrade("shield");
} else {
if (cost(me.levels.attack) < me.gold) return upgrade("attack");
}
// Otherwise, attack the weakest!
targets = others.filter(o => o.hp == health);
// And if there's a tie, attack the wealthiest.
wealth = Math.max(...targets.map(o => o.worth));
targets = targets.filter(o => o.worth == wealth);
target = targets[Math.floor(Math.random()*targets.length)];
return attack(targets[0].uid);
}
function Bandit(me, others, storage) {
// stuff we need
const epsilon = 0.3; // really high epsilon
function argmax(xs) {
var max = 0;
var argmax = 0;
for (var i=0; i<xs.length; i++) {
if (xs[i]>max) {
max = xs[i];
argmax = i;
}
}
return argmax;
}
function base3ToActionSeries(strategy) {
const actions = [shield(), farm(), heal()];
var idxs = []
var strategy_cut = strategy;
for (var i = 81; i >= 1; i /= 3) {
if (strategy_cut >= 2 * i) {idxs.push(2); strategy_cut -= 2*i}
else if (strategy_cut >= i) {idxs.push(1); strategy_cut -= i}
else idxs.push(0);
}
return idxs.map(idx => actions[idx]);
}
// actual logic starts here
// current strategy and info to calculate reward
if (!storage.prior)
storage.prior = [0,0.03325,0,0.0361,0.0361,0.2372,0,0.2372,0,0.00035,0.0361,0.23555,0.01305,0.0361,0.5798,0.23555,0.62065,0.23555,0,0.2372,0,0.20965,0.5841,0.2372,0,0.21905,0,0.0361,0.0361,0.2081,0.0361,0.0361,0.01455,0.000350,0.62065,0.205,0.000350,0.0361,0.3708,0.0361,0.0323,1.018050,0.5798,0.04495,0.5798,0.23555,0.62065,0.23555,0.62065,1.06395,0.62065,0.23555,0.62065,0.23555,0,0.2372,0,0.2372,0.5841,0.2372,0,0.2372,0,0.23555,0.62065,0.13775,0.5798,1.0257,0.5798,0.23555,0.62065,0.23555,0,0.2339,0,0.2372,0.5841,0.2339,0,0.2372,0,0.0342,0.0361,0.2372,0.03515,0.03325,0.6228,0.2372,0.5841,0.2372,0.0361,0.0130599,0.62065,0.03515,0.0361,1.0665,0.62065,0.24050,0.62065,0.23555,0.51465,0.2372,0.6228,1.0257,0.6228,0.2372,0.5841,0.2372,0.0361,0.0361,0.58195,0.0361,0.0313596,1.0614,0.58195,1.02315,0.58195,0.0342,0.0361,1.0206,0.02255,0.0183,0.02595,1.0206,1.5526,1.0206,0.58195,1.02315,0.58195,0.02765,0.0251,1.0614,0.0007,0.02085,0.3088,0.2372,0.5841,0.2273,0.6185,0.02255,0.6228,0.2372,0.5841,0.2372,0.62065,1.06395,0.62065,1.0665,0.0917,1.0665,0.62065,0,0.62065,0.2372,0.5841,0.2372,0.6228,1.0257,0.6228,0.2372,0.5841,0.2372,0,0.2372,0,0.23225,0.5841,0.2372,0,0.2372,0,0.23555,0.62065,0.23555,0.5798,1.0257,0.5798,0.23555,0.6142,0.23555,0,0.22235,0,0.2372,0.5841,0.2372,0,0.2372,0,0.23555,0,0.21905,0.62065,0.02255,0.62065,0.23555,0.61205,0.23555,0.5798,1.05885,0.5798,1.018050,0.03895,1.018050,0.5798,1.05885,0.5798,0.23555,0.62065,0.23555,0.62065,0.0361,0.62065,0.23555,0.62065,0.23555,0,0.2372,0,0.2372,0.3745,0.2372,0,0.2372,0,0.23555,0.62065,0.23555,0.5798,0.9452,0.5798,0.23555,0.5626,0.23555,0,0.2372,0,0.18175,0.5841,0.0138,0,0.2372,0]
if (storage.lastScore == null)
storage.lastScore = 0;
if (storage.bestStrategy == null)
storage.bestStrategy = argmax(storage.prior);
if (cost(me.levels.heal) < me.gold) return upgrade("heal");
if (cost(me.levels.farm) < me.gold) return upgrade("farm");
// This barely explores and mostly exploits.
if (turn() % 5 === 0) {
// update
const reward = me.gold/2 - storage.lastScore;
// biased a bit towards later learned rewards
storage.prior[storage.bestStrategy] += reward*0.01
storage.prior[storage.bestStrategy] *= 100/101
// explore
if (Math.random() < epsilon) {
storage.bestStrategy = Math.floor(Math.random()*243);
}
else { // exploit
storage.bestStrategy = argmax(storage.prior);
}
storage.lastScore = me.gold/2;
}
var action = base3ToActionSeries(storage.bestStrategy)[turn() % 5];
return action;
}
function serialKiller(self,others,storage){
let turnsLeft=999-turn()
if(self.shield<50){
return shield()
} else if(self.gold>=cost(self.levels.attack)&&turnsLeft>20){
return upgrade("attack")
}else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=4&&turnsLeft>20){
return upgrade("shield")
}else{
return attack(others.sort((a,b)=>a.hp-b.hp)[0].uid)
}
}
function Rando(me, others, storage) {
var rnum = Math.floor(Math.random() * 9);
switch (rnum) {
case 0:
if (me.gold >= cost(me.levels.shield)) {
return upgrade("shield");
}
case 1:
if (me.hp >= 100 - (me.levels.heal + 5) && me.levels.shield >= me.levels.heal) {
return shield();
}
case 2:
if (me.hp < 100 - (me.levels.heal + 5)) {
return heal();
}
case 3:
if (me.gold >= cost(me.levels.farm)) {
return upgrade("farm");
}
case 4:
if (me.gold >= cost(me.levels.heal)) {
return upgrade("heal");
}
case 5:
if (me.hp > 2) {
return farm();
}
case 6:
// Beat down the leader!
var currentLeader = others[0].uid;
var leaderWorth = -1;
for (var i = 0; i < others.length; i++) {
worth = others[i].worth;
if (worth > leaderWorth) {
currentLeader = others[i].uid;
leaderWorth = worth;
}
}
return stun(currentLeader);
case 7:
if (me.gold >= cost(me.levels.attack)) {
return upgrade("attack");
}
case 8:
// Find the juiciest kill (if any), or attack the strongest
var choice = others[0].uid;
var choiceWorth = -1;
var currentLeader = others[0].uid;
var leaderWorth = -1;
for (var i = 0; i < others.length; i++) {
worth = others[i].worth
if (worth > leaderWorth) {
currentLeader = others[i].uid;
leaderWorth = worth;
}
if (others[i].hp <= (1.25 * me.levels.attack + 5) && worth >= choiceWorth) {
choice = others[i].uid;
choiceWorth = worth;
}
}
if (choice > -1) {
return attack(choice);
}
else {
return attack(currentLeader);
}
default:
return false
}
}
function Mort(me, others, storage) {
if (me.hp <= 100 - (me.levels.heal + 5))
return heal();
actions = ["farm", "heal", "attack"].filter(action => cost(me.levels[action]) <= me.gold).map( action => [upgrade(action), 1000 - turn() - cost(me.levels[action]) ] )
my_damage = me.levels.attack * 1.25 + 5;
actions = actions.concat(others.map( bot => [ attack(bot.uid), (bot.worth/2)/Math.max(bot.hp/(my_damage-(bot.hp > my_damage ? 5 : 0)),1) ] ));
actions.push( [farm(), (2 * me.levels.farm + 5)*(1-2/(me.levels.heal+5))] );
return actions.sort( (x,y) => y[1] - x[1] )[0][0];
}
function farmhealBot(me, others, storage) {
if (me.hp <= 95)
return heal();
else return farm();
}
function killStealer(me, others, storage) {
let t = turn();
if (t===1) {
storage.worth = 0;
storage.pHP = 100;
storage.pGold = 0;
storage.bad = {};
for (let o of others) storage.bad[o.uid] = 0;
}
let hp = me.hp;
let gold = me.gold;
let shld = me.shield;
let lHeal = me.levels.heal;
let lFarm = me.levels.farm;
let lShld = me.levels.shield;
let lAtck = me.levels.attack;
let healPower = lHeal + 5;
let shldPower = lShld*1.5 + 5;
let farmPower = lFarm*2 + 5;
let atckPower = lAtck*1.25 + 5;
let attacked = storage.pHP-hp > 2;
storage.pHP = hp;
if (gold > storage.pGold) storage.worth+= gold-storage.pGold;
if (gold-storage.pGold > farmPower+5) storage.lastAtck = -10;
let pOthers = storage.pOthers;
storage.pOthers = {};
for (let o of others) {
storage.pOthers[o.uid] = {hp: o.hp, uid: o.uid, worth: o.worth};
}
if (storage.dead !== undefined) {
if (!others.some(c=>c.uid == storage.dead)) {
for (let o of others) {
if (o.worth >= pOthers[o.uid]+storage.deadWorth) storage.bad[o.uid]++;
}
}
// else console.log("I MISJUDGED");
storage.dead = undefined;
}
let maxdmg = others.map(c=>c.attack).reduce((a, b) => Math.max(a, b))*1.25 + 5;
if (t > 2) {
for (let o of others) {
if (o.hp < atckPower && o.worth > farmPower) {
storage.dead = o.uid;
storage.deadWorth = o.worth;
return attack(o.uid);
}
let pO = pOthers[o.uid];
let dmg = pO.hp - o.hp;
if (o.hp - dmg - atckPower <= 0 && o.worth > farmPower) {
storage.dead = o.uid;
storage.deadWorth = o.worth;
return attack(o.uid);
}
if (o.hp - maxdmg - atckPower <= 0 && o.worth > farmPower) {
storage.deadWorth = o.worth;
return attack(o.uid);
}
if (o.hp < 70 && o.hp - maxdmg*2 - atckPower <= 0) {
let maxBad = others.map(c => storage.bad[c.uid]).reduce((a, b) => Math.max(a, b));
let bad = others.filter(c => storage.bad[c.uid] >= maxBad/2).reduce((a, b) => a.worth>b.worth? a : b);
return stun(bad.uid);
}
}
}
if (others.length == 1 && others[0].worth < storage.worth && attacked) return stun(others[0].uid); // stun-lock hehe
if (t === 1) return upgrade("shield");
if (t === 2) return shield();
if (t%10 == 9 && lShld>4) return shield(); // slowly build up shield just in case
if (shld+hp < 100) return shldPower>healPower || hp >= 100-healPower? shield() : heal();
if (gold>=cost(lFarm) && lShld+2 > lFarm) return upgrade("farm"); // farm first, but make sure it doesn't get too far ahead
if (gold>=cost(lShld) && t>20 && (lShld<10 || lShld+5 < lFarm)) return upgrade("shield");
if (gold>=cost(lFarm)) return upgrade("farm"); // try upgrading farming again, because shield upgrading can be picky
if (gold>=cost(lHeal) && (lHeal+2 < lFarm && lHeal<10 || lHeal<3)) return upgrade("heal"); // healing isn't that important
if (shld<200 && attacked || shld<500 && t>20 && others.filter(c=>c.hp>=100).every(o=>o.hp+10 > hp+shld)) return shldPower>healPower || hp >= 100-healPower? shield() : heal();
if (lShld>1 && shld<lShld*50) return shield(); // we want to look impressive & terrifying
if (hp<=100-healPower) return heal();
if (gold >= cost(lAtck) && (lAtck+5 < lFarm)) return upgrade("attack"); // upgrade attack when it's cheap at the start, we wouldn't be able to do much anyways
return farm();
}
function ScaredBot(me, others) {
const my_attack = me.levels.attack * 1.25 + 5;
const my_defense = me.hp + me.shield;
var max_attack_val = 0;
var min_hp_worth = 0;
var min_hp_id = null;
var hp_under_me = 0;
for (var i=0; i<others.length; i++){
if (others[i].hp < my_attack && others[i].worth > min_hp_worth){
min_hp_id = others[i].uid;
min_hp_worth = others[i].worth;
}
if (others[i].attack*1.25+5 > max_attack_val){
max_attack_val = others[i].attack*1.25+5;
}
if (others[i].hp < my_defense && others[i].hp > 0){
hp_under_me++;
}
}
if (max_attack_val*0.25*others.length > my_defense || hp_under_me < 0.25*others.length){
return shield();
}
else if (min_hp_id != null){
return attack(min_hp_id);
}
else if (me.hp < 50){
return heal();
}
else {
var min_lvl = NaN;
var min_name = null;
const vals = [me.levels.heal, me.levels.shield, me.levels.farm];
const names = ["heal", "shield", "farm"];
for (var i=0; i<vals.length; i++){
if (!(min_lvl < vals[i])){
min_lvl = vals[i];
min_name = names[i];
}
}
if (me.gold > cost(min_lvl)){
return upgrade(min_name);
}
return farm();
}
}
function PatientStratgistBot(me, others, storage) {
//set up some stuff in first turn
if (turn() == 1) {
storage.selfWorth = 0;
storage.attackMode = false;
storage.expectHP = 100;
storage.expectShield = 0;
storage.shieldTarget = 0;
storage.targetUid = "None";
storage.attackRounds = 0;
storage.targetStartHP = 100;
return upgrade("farm");
}
let farmPower = me.levels.farm * 2 + 5;
//defensive Actions
var maxAtk = Math.max(...others.map(o => o.attack));
storage.shieldTarget = Math.ceil(maxAtk * 1.25 / 1.5) + 1;
if (me.levels.shield < storage.shieldTarget && me.gold >= cost(me.levels.shield) && me.levels.shield < me.levels.farm)
return upgrade("shield");
if (turn() >= 7 && me.shield < 10 && me.levels.shield * 1.5 >= me.levels.heal) return shield();
if (turn() >= 15 && me.shield < 15 && me.levels.shield * 1.5 >= me.levels.heal) return shield();
if (turn() >= 30 && me.shield < 20 && me.levels.shield * 1.5 >= me.levels.heal) return shield();
//attack mode
// check if there any targets worth to go for
function findTarget(potentialTargets, baseR){
var targetUID = "None";
var best = 0;
for( var i = 0; i < potentialTargets.length; i++) {
//We upgrade to attack lvl12, so 20 dmg; assume an enemy can heal/shield up to 15 per round
var killRounds = Math.ceil(potentialTargets[i].hp / 5)
var gain = potentialTargets[i].worth / ( 2 * ( killRounds + baseR) )
//console.log(me, turn(), potentialTargets[i], killRounds, baseR, gain, farmPower)
if (gain > farmPower * ( killRounds + baseR ) && gain > best)
targetUID = potentialTargets[i].uid;
storage.targetStartHP = potentialTargets[i].hp;
}
return targetUID;
}
if (turn() >= 600) {
//check if a current target is dead
const uids = others.map(x=>x.uid);
if(storage.targetUid != "None" && !uids.includes(storage.targetUid)) {
storage.targetUid = "None";
storage.attackMode = false;
storage.attackRounds = 0;
}
// check if we are doing enough damage to current target
if (storage.targetUid != "None" && storage.attackRounds >= 3) {
var deltaHP = storage.targetStartHP - others[storage.targetUid].hp
if (deltaHP / storage.attackRounds < 5) {
storage.targetUid = "None";
storage.attackMode = false;
storage.attackRounds = 0;
}
}
var investCost = 0
for( var i = me.levels.attack; i < 12; i++) investCost += cost(i);
if (storage.attackMode == true && me.gold >= investCost && me.levels.attack < 12) return upgrade("attack");
if (storage.attackMode == false) {
baseRounds = investCost / farmPower * 1.2; //overestimation with the heal level we should have at this point
if (findTarget(others, baseRounds) != "None")
storage.attackMode = true;
var betterThanMe = others.filter(o => o.worth >= storage.selfWorth);
if (betterThanMe.length > 0)
storage.attackMode = true;
//storage.attackMode = true;
}
}
if (storage.attackMode == true && me.levels.attack == 12) {
if (storage.targetUid == "None") {
var target = findTarget(others, 0)
storage.targetUid = target;
storage.attackRounds = 0;
return attack(target);
}
return attack(storage.targetUid)
}
//otherwise farm
if (me.hp < 50) {
storage.expectHP += 5 + me.levels.heal;
return heal();
}
if (me.gold >= cost(me.levels.farm) && storage.attackMode == false)
return upgrade("farm");
//upgrade heal, so we can farm more, but increase farm ability faster
if (me.levels.farm > 5 && me.levels.heal < 10 && me.gold >= 2*cost(me.levels.heal))
return upgrade("heal");
//be opportunistic - check if killing someone is more profitable than farming
killable = others.filter(o => o.hp < me.levels.attack * 1.25 + 5 && o.worth / 2 > farmPower);
if (killable.length > 0){
//ideally check for the most worth target here
return attack(killable[0].uid);
}
storage.expectHP -= 2;
storage.selfWorth += farmPower;
return farm();
}
function KillAssist(me, others, storage) {
let t = turn();
if (t===1) {
storage.worth = 0;
storage.pHP = 100;
storage.pGold = 0;
}
let hp = me.hp;
let gold = me.gold;
let shld = me.shield;
let lHeal = me.levels.heal+0.25;
let lFarm = me.levels.farm;
let lShld = me.levels.shield;
let lAtck = me.levels.attack;
let healPower = lHeal + 4.75;
let shldPower = lShld*1.5 + 5;
let farmPower = lFarm*2 + 5;
let atckPower = lAtck*1.25 + 5;
let dmgTaken = storage.pHP-(hp+shld);
let attacked = dmgTaken > 2;
storage.pHP = (hp+shld);
if (gold > storage.pGold) storage.worth+= gold-storage.pGold;
if (gold-storage.pGold > farmPower+5) storage.lastAtck = -10;
storage.pGold = gold;
let pOthers = storage.pOthers;
storage.pOthers = {};
for (let o of others) {
storage.pOthers[o.uid] = {hp: o.hp, uid: o.uid, worth: o.worth};
}
if (t === 1 || t === 2) return upgrade("shield");
if (t === 3) return shield();
let maxdmg = others.map(c=>c.attack).reduce((a, b) => Math.max(a, b))*1.25 + 5;
let lowhp = others.map(c=>c.hp).reduce((a, b) => Math.min(a, b));
let lowhpid = others.find(c=>c.hp == lowhp).uid;
let maxAttacker = others.find(o => o.attack*1.25 + 5 == maxdmg).uid;
for (let o of others) {
if (o.hp < atckPower && o.worth > farmPower) {
storage.dead = o.uid;
storage.deadWorth = o.worth;
return attack(o.uid);
}
let pO = pOthers[o.uid];
let dmg = pO.hp - o.hp;
if (o.hp - dmg - atckPower <= atckPower && o.worth >= farmPower) {
storage.dead = o.uid;
storage.deadWorth = o.worth;
return attack(o.uid);
}
if (o.hp - maxdmg - atckPower <= atckPower && o.worth >= farmPower) {
storage.deadWorth = o.worth;
return attack(o.uid);
}
}
let lowhpdiff = Math.max(pOthers[lowhpid].hp - others.find(o => o.uid == lowhpid).hp,0);
if (others.some(o => o.hp > maxdmg && o.hp < lowhpdiff*2+atckPower+maxdmg && o.worth > farmPower)) {
let bad = others.reduce((a, b) => a.worth>b.worth? a : b);
let bad2 = others.reduce((a, b) => bad.uid == b.uid ? a : (bad.uid == a.uid ? b : (a.worth>b.worth ? a : b)));
if(bad.worth < bad2.worth*3 && bad.hp >= (maxdmg+atckPower)*2 && bad.uid != maxAttacker && bad.uid != lowhpid) {
return stun(bad.uid);
}
if(bad2.hp >= (maxdmg+atckPower)*2 && bad2.uid != maxAttacker && bad.uid != lowhpid) {
return stun(bad2.uid);
}
}
if (t%10 == 9 && lShld>4) return shield(); // slowly build up shield just in case
if (shld+hp < 100) return shldPower>healPower || hp >= 100-healPower? shield() : heal();
var bon = shldPower-maxdmg < 3 && t < 700 ? lShld/2 : 0;
var bon2 = t/100;
if (gold>=cost(lFarm) && lShld+2 > lFarm && bon == 0 && !attacked) return upgrade("farm"); // farm first, but make sure it doesn't get too far ahead
if (gold>=cost(lShld) && t>20 && (lShld<10+bon || lShld+5+bon2 < lFarm+bon) && t < 900) return upgrade("shield");
if (gold>=cost(lFarm)) return upgrade("farm"); // try upgrading farming again, because shield upgrading can be picky
if (gold>=cost(lHeal) && (lHeal<3)) return upgrade("heal"); // healing isn't that important
if (shld<200 && attacked || shld<500 && t>20 && others.filter(c=>c.hp>=100).every(o=>o.hp+10 > hp+shld)) return shldPower>healPower || hp >= 100-healPower? shield() : heal();
let hpdelta = attacked ? dmgTaken+shldPower : maxdmg
if (shld<lShld*60 && (1000-t)*(hpdelta) > shld+hp) return shield(); // we want to look impressive & terrifying
if (hp<=100-healPower) return heal();
return farm();
}
function ThanosBot(me, others, storage){
if(turn()==1){
storage.origPopulation = others.length;
return upgrade("attack");
}
if (others.length < storage.origPopulation / 2)
{
if(me.hp <= 100 - (me.levels.heal + 5)){
return heal();
}
else {
return farm();
}
}
if(me.hp <= 100 - (me.levels.heal + 5)){
return heal()
}else{
if(me.gold >= cost(me.levels.attack)){
return upgrade("attack")
}else if(me.gold >= cost(me.levels.heal)){
return upgrade("heal")
}else if(me.gold >= cost(me.levels.farm)){
return upgrade("farm")
}else{
if(Math.random() < 0.5){
return attack(others[0].uid);
}
else{
return farm();
}
}
}
}
function accountant(me, others, storage) {
if (turn() == 1) {
storage.lastHP = me.hp + me.shield;
storage.hisAttack = 5;
storage.timesAttacked = 0;
storage.lastAttack = -1;
storage.healths = [], storage.uids = [], storage.heals = [];
for (var i = 0; i < others.length; i++) {
storage.healths.push(others[i].hp);
storage.uids.push(others[i].uid);
storage.heals.push(5);
}
}
storage.timesAttacked++;
if (storage.lastHP == me.hp + me.shield) storage.timesAttacked = 0;
else storage.hisAttack = storage.lastHP - me.hp - me.shield;
storage.lastHP = me.hp + me.shield;
var maxAttack = 0;
for (var i = 0; i < others.length; i++) if (1.25 * others[i].attack + 5 > maxAttack) maxAttack = 1.25 * others[i].attack + 5;
var storageIndex;
for (var i = 0; i < others.length; i++) {
storageIndex = storage.uids.indexOf(others[i].uid);
if (storage.heals[storageIndex] < others[i].hp - storage.healths[storageIndex] + (others[i].uid == storage.lastAttack ? 1.25 * me.levels.attack + 5 : 0)) others[i].hp - storage.healths[storageIndex] + (others[i].uid == storage.lastAttack ? 1.25 * me.levels.attack + 5 : 0);
}
var maxProfitTurn = 2 * me.levels.farm + 5, victimID = -1, tempProfit;
for (var i = 0; i < others.length; i++) {
storageIndex = storage.uids.indexOf(others[i].uid);
tempProfit = others[i].worth / 2 * (1.25 * me.levels.attack + 5 - storage.heals[storageIndex]) / others[i].hp;
if (tempProfit > maxProfitTurn) {
victimID = others[i].uid;
maxProfitTurn = tempProfit;
}
}
var isUrgent = false;
for (var i = 0; i < others.length; i++) if (others[i].hp <= maxAttack) {
isUrgent = true;
maxProfitTurn = others[i].worth / 2;
victimID = others[i].uid;
}
if (maxProfitTurn > (2 * me.levels.farm + 5) && (maxProfitTurn > me.gold || isUrgent)) {
storage.lastAttack = victimID;
return attack(victimID);
}
storage.lastAttack = -1;
if (storage.timesAttacked == 0) {
if (me.levels.shield < 20 && me.gold >= cost(me.levels.shield)) return upgrade("shield");
if (me.levels.heal < 5 && me.levels.shield >= me.levels.heal + 5 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
if (Math.random() < 100 / (me.hp + me.shield)) {
storage.lastHP += 1.5 * me.levels.shield + 5;
return shield();
}
}
else {
if (Math.random() < .5 || me.hp + me.shield - storage.hisAttack - maxAttack <= 10) {
storage.lastHP += 1.5 * me.levels.shield + 5;
return shield();
}
if (me.levels.shield < 20 && me.gold >= cost(me.levels.shield)) return upgrade("shield");
if (me.hp <= 2) {
storage.lastHP += me.levels.shield + 5;
return heal();
}
storage.lastHP -= 2;
return farm();
}
if (me.gold >= cost(me.levels.farm)) return upgrade("farm");
storage.lastAttack = victimID;
if (victimID != -1) return attack(victimID);
if (me.hp <= 2) {
storage.lastHP += me.levels.shield + 5;
return heal();
}
storage.lastHP -= 2;
return farm();
}
function captFarmer(me, others, storage) {
if (!storage.mode)
storage.mode = "prep";
var weak = others.find(el => el.hp < me.levels.attack * 1.25 + Math.max(...others.map(el => el.attack)) * 1.75 + 10 && Math.ceil(el.worth / 2) > me.levels.farm * 2 + 5);
if (weak && storage.weak >= 0) {
storage.weak += 1;
return attack(weak.uid);
}
if (storage.weak < 0)
storage.weak += 1;
else if (storage.weak > 3)
storage.weak = -3;
else if (!storage.weak)
storage.weak = 0;
if (me.hp + me.shield < 90)
storage.mode = "lowhp";
if (storage.mode == "prep") {
if (turn() < 5)
return shield();
if (turn() == 5)
return upgrade("attack");
if (turn() == 6)
return upgrade("attack");
storage.modeTimer = 0;
storage.mode = "farm";
} else if (storage.mode == "lowhp") {
let last = storage.lastHp;
let hp = me.hp + me.shield;
storage.lastHp = hp;
if (!last)
return shield();
if (me.hp == 100) {
if (me.shield >= 25) {
storage.mode = "farm";
storage.modeTimer = 0;
}
return shield();
}
if (last > hp) {
if (last - hp + me.levels.heal + 5 <= me.levels.shield * 1.5 + 5)
return shield();
else
return farm();
} else {
return shield();
}
} else if (storage.mode == "farm") {
if (me.gold >= cost(me.levels.shield))
return upgrade("shield");
if (me.gold >= cost(me.levels.farm))
return upgrade("farm");
if (me.gold >= cost(me.levels.attack))
return upgrade("attack");
if (me.hp > 80 && !storage.healMode)
return farm();
storage.healMode = true;
if (me.hp < 97)
return heal();
storage.healMode = false;
return shield();
}
return shield();
}
function barbarianMan(me, others, storage) {
if (!storage.mode) {
storage.mode = "prep";
storage.prep = 0;
}
if (me.hp + me.shield < 100)
storage.mode = "lowhp";
var weak = others.find(el => el.hp < me.levels.attack * 1.25 + Math.max(...others.map(el => el.attack)) * 2.5 + 10 && Math.ceil(el.worth / 2) >= 5);
if (weak && storage.weak >= 0) {
storage.weak += 1;
return attack(weak.uid);
}
if (storage.weak < 0)
storage.weak += 1;
else if (storage.weak > 3)
storage.weak = -3;
else if (!storage.weak)
storage.weak = 0;
if (storage.mode == "prep") {
storage.prep += 1;
if (storage.prep < 3)
return upgrade("shield");
if (storage.prep < 7)
return shield();
if (storage.prep < 10)
return farm();
if (storage.prep < 11)
return heal();
if (storage.prep < 13)
return farm();
if (storage.prep < 14)
return heal();
if (storage.prep < 16)
return upgrade("attack");
storage.mode = "kill";
} else if (storage.mode == "lowhp") {
if ((me.hp + me.shield) > 150) {
if (me.hp >= 95)
storage.mode = "kill";
return heal();
}
return shield();
} else if (storage.mode == "kill") {
if (!storage.badTargs) {
storage.badTargs = [];
storage.testHp = [];
}
storage.lastHp = null;
if (me.gold >= cost(me.levels.attack) && me.levels.attack < 5)
return upgrade("attack");
if (me.gold >= cost(me.levels.shield))
return upgrade("shield");
if (me.gold >= cost(me.levels.farm))
return upgrade("farm");
if (storage.gTarg && attack(storage.gTarg)[0])
return attack(storage.gTarg);
if (storage.test == "attack1" && attack(storage.tTarg)[0]) {
storage.test = "attack2";
storage.testHp[0] = others.find(el => el.uid == storage.tTarg).hp;
return attack(storage.tTarg);
}
if (storage.test == "attack2" && attack(storage.tTarg)[0]) {
storage.test = "exam";
storage.testHp[1] = others.find(el => el.uid == storage.tTarg).hp;
return attack(storage.tTarg);
}
if (storage.test == "exam" && attack(storage.tTarg)[0]) {
if (storage.testHp[1] - storage.testHp[0] > 3) {
storage.gTarg = storage.tTarg;
storage.test = null;
} else {
storage.badTargs.push(storage.tTarg);
storage.test = null;
}
return heal();
}
let targs = [];
let scores = [];
for (let o, i = 0; i < others.length; i++) {
o = others[i];
if (storage.badTargs.includes(o.uid))
continue;
targs.push(o.uid);
scores.push((-(o.worth ** 2) / 5000 + 4 * (o.worth) / 15) / o.hp);
}
if (!targs.length)
storage.mode = "farm";
storage.tTarg = targs[scores.indexOf(Math.max(...scores))];
storage.test = "attack1";
return heal();
} else if (storage.mode == "farm") {
if (me.gold >= cost(me.levels.shield))
return upgrade("shield");
if (me.gold >= cost(me.levels.farm))
return upgrade("farm");
if (me.hp > 80 && !storage.healMode)
return farm();
storage.healMode = true;
if (me.hp < 97)
return heal();
storage.healMode = false;
return shield();
}
return shield();
}
function TheHalfHalf(me, others, storage){
if (turn() == 0) {
return upgrade("heal");
}
if(turn() % 2 == 0) {
if(me.hp <= 50 - (me.levels.heal + 5)){
return heal()
} else {
if(me.gold >= cost(me.levels.farm)){
return upgrade("farm")
} else {
return farm();
}
}
} else {
if(me.hp <= 50){
return shield();
} else {
return attack(others[Math.floor(Math.random() * Math.floor(others.length))].uid);
}
}
}
function TeacherBot(self, others, storage){//10979.913
var maxAtk = others.map(c=>c.attack).reduce((a, b) => Math.max(a, b));
var maxDmg = maxAtk * 1.25 + 5;
var myDmg = self.levels.attack * 1.25 + 5;
var potential_victim = others.find( bot => bot.hp <= Math.max(maxDmg, myDmg) );
if (potential_victim) {
return attack(potential_victim.uid);
}
let turnsLeft=999-turn()
if(self.shield<50 && turn() > 5){
return shield()
}else if(self.gold>=cost(self.levels.attack)&&turnsLeft>20){
return upgrade("attack")
}else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=4&&turnsLeft>50){
return upgrade("shield")
}else{
return attack(others.sort((a,b)=>b.attack-a.attack)[0].uid)
}
}
var botData = [
{
name: "justFarm",
debug: 0,
run: justFarm
},
{
name: "undyableBot",
debug: 0,
run: undyableBot
},
{
name: "Unkillable",
debug: 0,
run: UnkillableBot
},
{
name: "scavengerBot",
debug: 0,
run: scavengerBot
},
{
name: "bullyBot",
debug: 0,
run: bullyBot
},
{
name: "indestructible",
debug: 0,
run: indestructible
},
{
name: "SniperBot",
debug: 0,
run: sniperBot
},
{
name: "Optimist",
debug: 0,
run: Optimist
},
{
name: "BullyDozerBot",
debug: 0,
run: BullyDozerBot
},
{
name: "Friendly bot",
debug: 0,
run: menShengFaDaCai
},
{
name: "SmartFarmer",
debug: 0,
run: smartFarmer
},
{
name: "PacifistBot",
debug: 0,
run: pacifistWinnerBot
},
{
name: "FizzBuzz",
debug: 0,
run: FizzBuzz
},
{
name: "CampBot",
debug: 0,
run: campBot
},
{
name: "Switzerland",
debug: 0,
run: switzerland
},
{
name: "Guardian",
debug: 0,
run: guardian
},
{
name: "The Equalizer",
debug: 0,
run: equalizer
},
{
name: "Moody",
debug: 0,
run: Moody
},
{
name: "The Opportunist",
debug: 0,
run: Opportunist
},
{
name: "Kill Bot",
debug: 0,
run: killBot
},
{
name: "Bandit",
debug: 0,
run: Bandit
},
{
name: "Serial Killer",
debug: 0,
run: serialKiller
},
{
name: "Rando",
debug: 0,
run: Rando
},
{
name: "Mort",
debug: 0,
run: Mort
},
{
name: "FarmHeal Bot",
debug: 0,
run: farmhealBot
},
{
name: "Kill Stealer",
debug: 0,
run: killStealer
},
{
name: "ScaredBot",
debug: 0,
run: ScaredBot
},
{
name: "PatientStrategistBot",
debug: 0,
run: PatientStratgistBot
},
{
name: "Kill Assist",
debug: 0,
run: KillAssist
},
{
name: "ThanosBot",
debug: 0,
run: ThanosBot
},
{
name: "The Accountant",
debug: 0,
run: accountant
},
{
name: "captFarmer",
debug: 0,
run: captFarmer
},
{
name: "barbarianMan",
debug: 0,
run: barbarianMan
},
{
name: "TheHalfHalf",
debug: 0,
run: TheHalfHalf
},
{
name: "TeacherBot",
debug: 0,
run: TeacherBot
}
];
function freeTestBotA(me, others) {
if (me.levels.attack < 5) {
if (me.gold < cost(me.levels.attack))
return farm();
return upgrade("attack");
}
return attack(others[0].uid);
}
function freeTestBotB(me, others) {
if (me.gold >= cost(me.levels.attack))
return upgrade("attack");
if (me.hp < 50)
if (Math.random() < 0.5)
return stun(others[0].uid);
else
return heal();
else
if (Math.random() < 0.5)
return attack(others[0].uid);
else
return shield();
}
//Put bot names and functions below. Set debug to 1 or 2 for event log.
//Just call this function to test. Errors will not stop the game. Max turns: 1000. Event logger included, set log to false to disable
function runGame(rounds = 1, log = true) {
records = [];
for (let i = 0; i < rounds; i++)
runRound(log);
var ids = [];
for (let i = 0; i < records.length; i++)
ids[i] = i;
ids = ids.sort((a, b) => records[b] - records[a]);
var results = "Results: ";
for (let b, i = 0; i < ids.length; i++) {
b = ids[i];
results += "\n " + (i < 9 ? " " : "") + (i + 1) + ". " + botData[b].name + ": " + (records[b] / rounds);
}
console.log(results);
}
//Ignore everything under this, it's internal stuff
var records = [];
var bots = [];
var turns = 0;
var heal = () => ["heal"];
var attack = bot => {
var index = bots.findIndex(el => el.uid == bot && el.hp > 0);
if (index == -1)
return [null, "attack", bot];
return ["attack", index];
};
var shield = () => ["shield"];
var stun = bot => {
var index = bots.findIndex(el => el.uid == bot && el.hp > 0);
if (index == -1)
return [null];
return ["stun", index];
};
var farm = () => ["farm"];
var upgrade = item => {
if (["heal", "attack", "shield", "farm"].includes(item))
return ["upgrade", item];
return [null, "upgrade", item];
};
var cost = lvl => 2.5 * (lvl ** 2) + 2.5 * lvl + 10;
var turn = () => turns;
var move = code => {
if (!Array.isArray(code))
return "Invalid [" + code + "]";
else if (code[0] == "heal")
return "Healed";
else if (code[0] == "attack")
return "Attacked " + botData[code[1]].name;
else if (code[0] == "shield")
return "Shielded";
else if (code[0] == "stun")
return "Stunned " + botData[code[1]].name;
else if (code[0] == "farm")
return "Farmed";
else if (code[0] == "upgrade")
return "Upgraded " + code[1];
else if (!code[0] && !code[1])
return "Skipped";
else if (!code[0] && code[1] == "attack")
return "Attacked unknown UID [" + code[2] + "]";
else if (!code[0] && code[1] == "upgrade")
return "Upgraded unknown move [" + code[2] + "]";
else
return "Unknown [" + code[0] + "]";
};
function runRound(log) {
var uids = [];
for (let i = 0; i < 100; i++)
uids[i] = i;
for (let j, i = 99; 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++) {
bots[i] = {
uid: uids[i],
hp: 100,
gold: 25,
shield: 0,
stun: false,
worth: 0,
lvl: {
heal: 0,
attack: 0,
shield: 0,
farm: 0
},
storage: {}
};
records[i] = records[i] || 0;
}
turns = 0;
while (bots.filter(el => el.hp > 0).length > 1 && turns < 1000) {
turns += 1;
runTurn(log);
}
}
function runTurn(log) {
var moves = [];
var uids = bots.filter(el => el.hp > 0).map(el => ({
uid: el.uid,
hp: el.hp + el.shield,
worth: el.worth,
attack: el.lvl.attack
}));
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 ls, u, m, r, b, i = 0; i < bots.length; i++) {
b = bots[i];
b.attackers = [];
if (log && botData[i].debug == 1)
ls = JSON.stringify(b.storage);
if (b.hp > 0 && !b.stun) {
try {
r = botData[i].run(m = {
uid: b.uid,
hp: b.hp,
gold: b.gold,
shield: b.shield,
levels: {
heal: b.lvl.heal,
attack: b.lvl.attack,
shield: b.lvl.shield,
farm: b.lvl.farm
}
}, u = uids.filter(el => el.uid != b.uid), b.storage) || [null];
} catch (e) {
console.error("Error in " + botData[i].name + ":\n" + e.stack);
r = [null];
}
} else {
b.stun = false;
r = [null];
}
if (log && botData[i].debug == 1 && b.hp > 0 && !b.stun) {
console.log("[" + turns + "] " + botData[i].name + ":\n Self: " + JSON.stringify(m) + "\n Others: " + JSON.stringify(u) + "\n Storage: " + ls + "\n Move: " + move(r));
}
if (r[0] == "heal")
b.hp = Math.min(100, b.hp + b.lvl.heal + 5);
moves[i] = r;
}
for (let m, b, n, i = 0; i < moves.length; i++) {
m = moves[i];
b = bots[i];
n = botData[i].name;
if (log && botData[i].debug == 2 && b.hp > 0) {
if (b.stun)
console.log("[" + turns + "] " + n + ": Stunned by " + b.stun);
else
console.log("[" + turns + "] " + n + ":\n HP/SHP: " + b.hp + "/" + (b.hp + b.shield) + "\n Gold/Worth: " + b.gold + "/" + b.worth + "\n Levels: " + b.lvl.heal + "/" + b.lvl.attack + "/" + b.lvl.shield + "/" + b.lvl.farm + "\n Move: " + move(moves[i]));
}
if (!m)
continue;
if (m[0] == "attack") {
bots[m[1]].hp = bots[m[1]].hp - Math.max(0, b.lvl.attack * 1.25 + 5 - bots[m[1]].shield);
bots[m[1]].shield = Math.max(0, bots[m[1]].shield - b.lvl.attack * 1.25 - 5);
bots[m[1]].attackers.push(i);
} else if (m[0] == "stun") {
if (bots[m[1]].stun)
bots[m[1]].stun += ", " + n;
else
bots[m[1]].stun = n;
} else if (m[0] == "farm") {
b.gold += b.lvl.farm * 2 + 5;
b.worth += b.lvl.farm * 2 + 5;
records[i] += b.lvl.farm * 2 + 5;
b.hp -= 2;
if (log && b.hp < 0)
console.log("%c[" + turns + "] " + n + " died of overfarming", "font-weight: bold");
} else if (m[0] == "upgrade" && b.gold >= cost(b.lvl[m[1]])) {
b.lvl[m[1]] += 1;
b.gold -= cost(b.lvl[m[1]] - 1);
}
}
for (let m, b, n, i = 0; i < moves.length; i++) {
m = moves[i];
b = bots[i];
n = botData[i].name;
if (m[0] == "shield") {
b.shield += b.lvl.shield * 1.5 + 5;
}
if (b.hp < 0) {
for (let a, j = 0; j < b.attackers.length; j++) {
a = bots[b.attackers[j]];
a.gold += Math.ceil(b.worth / 2);
a.worth += Math.ceil(b.worth / 2);
records[b.attackers[j]] += Math.ceil(b.worth / 2);
if (log)
console.log("%c[" + turns + "] " + botData[b.attackers[j]].name + " killed " + n, "font-weight: bold");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment