Gold Battle KoTH


44

Questa sfida è finita. Per vedere i punteggi finali dei concorrenti, clicca qui

In questa sfida, ogni invio è un bot. Ogni bot dovrebbe essere una funzione Javascript. I robot combatteranno per ottenere il massimo valore totale in oro. L'oro può essere coltivato o guadagnato uccidendo altri robot e viene utilizzato per migliorare la cura, l'attacco, la protezione e l'agricoltura.

Obbiettivo:

In un numero di round che contiene fino a 1000 turni (termina quando rimane solo un bot), il bot con il valore totale più alto (la somma di tutto l'oro ottenuto) è il vincitore.

Giri:

Ad ogni turno, ogni bot che è vivo (> 0 HP) verrà eseguito una volta. Può restituire una mossa, che può essere una delle seguenti:

  • Guarigione: riacquista HP
  • Attacco: rimuove HP da un altro bot
  • Scudo: difende dagli attacchi successivi
  • Stordimento: salta il turno successivo di un altro robot
  • Fattoria: guadagna oro al costo di HP
  • Aggiornamento: migliora alcune mosse

Tutti i robot restituiranno la loro mossa prima che qualcuno venga eseguito, quindi uno stordimento, una cura, un attacco, uno scudo, ecc. Non influenzeranno alcun robot che si muove successivamente in quel turno. Ad esempio, se il Bot A stordisce il Bot B e il Bot B è dopo il Bot A nell'ordine del turno, il Bot B si sposterà più tardi nello stesso turno e lo stordimento si verificherà nel turno successivo.

Combattimento, allevamento e potenziamento:

Ogni bot ha un massimo di 100 HP e un UID assegnato tra 0 e 99. Questo UID cambia dopo ogni round ed è il modo in cui i robot si tengono reciprocamente traccia.

La guarigione è una delle mosse più semplici, aggiungendo una quantità di HP determinata dal suo livello (inizia da 5 HP). Un bot non può curare oltre 100 HP.

Attaccare un bot con il suo UID è un'altra mossa possibile, con un danno base di 5 HP al livello 0. I robot possono anche essere storditi, saltando il loro turno successivo, che utilizza anche gli UID.

I robot hanno HP scudo aggiuntivo, che non ha limiti. Questo scudo HP assorbirà i danni dagli attacchi diretti di altri robot e viene aggiunto dalla schermatura. Al livello 0, la schermatura aggiunge 5 HP scudo.

L'agricoltura guadagnerà 5 monete d'oro al livello 0, al costo di 2 HP. Questo 2 HP non può essere schermato. L'unico uso dell'oro (oltre alla vincita) è migliorare le mosse. La cura, l'attacco e la protezione hanno un valore base di 5 HP e l'agricoltura inizia con 5 monete d'oro. Ognuna di quelle mosse ha livelli individuali, che iniziano da 0. Queste formule determineranno il valore in HP o oro di una mossa, dove L è il livello:

  • Guarigione: L + 5
  • attaccare: 1.25L + 5
  • Schermatura: 1.5L + 5
  • agricoltura: 2L + 5

Il costo per aggiornare qualsiasi mossa è lo stesso per un certo livello, ed è determinato da 2.5L² + 2.5L + 10dove L è il livello attuale. Un bot può usare la funzione cost(currentLevel)come scorciatoia per determinarlo.

I robot iniziano con 25 monete d'oro, consentendo loro di aggiornare rapidamente due mosse al livello 1 o una mossa al livello 2. Questo oro iniziale non conta per un valore totale dei robot. Uccidere un robot ti dà metà del suo valore totale in oro, arrotondato per eccesso, e se due robot ne uccidono un altro nello stesso turno, entrambi ottengono la ricompensa.

Input Output:

Per comunicare con il controller, il valore di ritorno della funzione viene utilizzato per inviare informazioni di spostamento. Uno di questi dovrebbe essere restituito:

  • Guarire: heal()
  • Attacco: attack(uid)
  • Scudo: shield()
  • Stordire: stun(uid)
  • Azienda agricola: farm()
  • Aggiornamento: upgrade("heal" / "attack" / "shield" / "farm")

Per saltare un turno (non fare nulla), non restituire nulla o restituire un valore errato.

Per ottenere il numero di svolta corrente (inizia da 1), utilizzare turn().

Gli argomenti della tua funzione includeranno informazioni sul tuo bot, UID di altri bot e archiviazione tra turni. Il primo argomento è un oggetto con le seguenti proprietà: uid, hp, gold, e shield. Queste sono copie delle informazioni correnti del tuo bot. V'è anche un oggetto annidato levels, con i numeri di livello heal, attack, shield, e farm.

Il secondo argomento è una matrice già mescolato di tutti i bot vivi diversa dalla propria, formattato come un oggetto contenente proprietà uid, hp(più schermo), worthe attack(livello di attacco). Il terzo argomento è un oggetto vuoto che può essere utilizzato per l'archiviazione tra turni.

Robot di esempio:

Questo bot verrà coltivato fino a quando non può aggiornare il suo attacco al livello 5, quindi attaccherà un bot casuale ogni turno fino a quando non muore (o vince). Non molto efficace a causa della mancanza di guarigione / protezione.

function freeTestBotA(me, others, storage) {
    if (me.levels.attack < 5) {
        if (me.gold < cost(me.levels.attack))
            return farm();
        return upgrade("attack");
    }
    return attack(others[0].uid);
}

Questo bot ha due modalità: offensiva e difensiva. Stordirà un robot a caso o curerà quando è in modalità difensiva e attaccherà o proteggerà quando sarà in modalità offensiva. Tenterà di aggiornare i suoi attacchi quando possibile.

function freeTestBotB(me, others, storage) {
    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();
}

Regole:

  • Scappatoie standard vietate
  • I robot non possono leggere, modificare o aggiungere variabili al di fuori del loro ambito di applicazione, non possono tentare di imbrogliare e non possono chiamare alcuna funzione definita dal controller o DOM
  • Il valore di ritorno deve essere errato o una delle uscite della funzione sopra
  • I robot non devono essere progettati per targetizzare un bot specifico, ma possono essere progettati per trarre vantaggio da strategie comuni
  • I robot non possono attaccarsi (scoperti a causa di un commento di @Ness)
  • I robot devono essere sufficientemente diversi da qualsiasi altro robot da poter essere ragionevolmente considerati voci separate
  • Il teaming non è ora consentito
  • Il controller può essere trovato qui
  • chatroom

Nuovo debug del controller:

Utilizzando il file gold-battle-log.js, è possibile impostare il valore della debugproprietà di un bot botDatasu 0 (nessuna registrazione), 1 (spostamento del registro) o 2 (spostamento del registro, hp, gold, livelli, ecc.)

La sfida termina alle 1700 UTC di venerdì 9 agosto


4
Creato un riassunto con tutti i robot. gist.github.com/Draco18s/2efbf95edcf98d6b1f264e26bbb669d1 Farò il possibile per mantenerlo aggiornato (ma se non è un inizio decente).
Draco18s

4
Controller ad aggiornamento automatico con robot inclusi: redwolfprograms.com/koth
Programmi Redwolf

4
Sto votando per chiudere questa domanda perché è già di fatto chiusa a nuove risposte ("Questa sfida è finita. Per vedere i punteggi finali ...")
pppery

3
@pppery Non potresti? Starei bene con risposte non competitive, e [closed]alla fine è probabile che gli spettatori casuali saltino oltre la lettura della mia sfida poiché presumono che sia di bassa qualità o fuori tema.
Programmi Redwolf il

5
@pppery Non ho mai sentito parlare di una sfida chiusa per essere finita fino ad oggi, e direi che la restrizione sociale che vuoi imporre non esiste nemmeno. Non è necessario chiuderlo e non lo voglio chiuso. Per me, questo sembra chiudere per motivi di chiusura, piuttosto che per il bene del sito. Se qualcuno vuole pubblicare una risposta a una vecchia domanda, dovrebbe essere in grado di farlo. Non ci sono note dopo la seria regola del contendente che dice che deve essere un serio contendente quando viene pubblicato; una risposta può ancora essere un serio contendente per la sfida anche se non è un contendente per vincere
Redwolf Programmi

Risposte:


16

unkillable

biforcuta da Undyable .

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()
        }
    }
}

Dati i costi esponenziali degli aggiornamenti, potremmo anche migliorare l'agricoltura se non riusciamo ad aggiornare la cura, consentendo al bot di raccogliere l'oro in modo più efficiente.


Schiacciando assolutamente la concorrenza nei miei test
Redwolf Program

1
Sento che questo bot potrebbe essere un po 'più forte se fosse ifusata quella prima affermazione <=- attualmente non guarirà mai del tutto.
Scoots il

@Scoots Non sono sicuro di quanto importi, ma lo cambierò.
Draco18s

2
@ Draco18s Sono sicuro che conta davvero pochissimo - ma questo sito non è tutto basato su piccoli miglioramenti praticamente insignificanti? :)
Scoots

@Scoots Guarire al massimo della salute non ha molta importanza in questa sfida perché non ci sono minacce di attacco reali. L'unico bot veramente offensivo è il bullybot e non puoi davvero fare nulla per lui. Potrebbe effettivamente ridurre le prestazioni per rimanere in piena salute.
B0RDERS

13

ThanosBot

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();
            }
        }
    }
}

Ci sono troppi robot, non abbastanza oro per andare in giro. Questo bot propone una soluzione.

Genocidio, sì, ma casuale, spassionato, da discreto a ricco e povero.

Lo chiamavano un pazzo.

ThanosBot vuole il meglio per la comunità dei bot ed è disposto a fare tutto il possibile. All'inizio, potenzierà il suo attacco, l'agricoltura e la guarigione, per raccogliere risorse in modo più efficiente e vincere battaglie. In modo progressivo, inizierà ad attaccare le persone in modo casuale mentre continua a raccogliere risorse, per le battaglie imminenti. Continuerà a migliorare il suo esercito, le sue armi e se stesso.

Una volta eliminato il 50% della popolazione, i robot nati conosceranno solo pance piene e cieli sereni, si ritirerà in una vita di allevamento e guarderà il sole sorgere su un universo riconoscente. Diventerà completamente pacifista, guarendo solo se stesso con zuppe di verdure e agricoltura.


6
Sono tentato di rinominare "attacco" in "scatto"
Redwolf Programmi il

11

Uccidi Stealer

function killStealer({hp, gold, attack:atck, shield:shld, levels:{heal:lHeal, shield:lShld, farm:lFarm, attack:lAtck}}, es, S) {
  let saneReduce = (a, f, n) => a.length? a.reduce(f) : n;
  let t = turn();
  if (t===1) {
    S.worth = 0;
    S.pHP = 100;
    S.pGold = 0;
    S.stat = {};
    S.pT = 0;
    for (let e of es) S.stat[e.uid] = {kills:0, seen:0};
  }

  let pT = S.pT;
  S.pT = t;

  let shp = shld+hp;

  let healP = lHeal      + 5;
  let shldP = lShld*1.5  + 5;
  let farmP = lFarm*2    + 5;
  let atckP = lAtck*1.25 + 5;
  let pheal = () => hp<5  ||  Math.min(100, hp+healP)-hp > shldP? heal() : shield();

  let attacked = S.pHP-hp-shld > 2;
  S.pHP = hp+shld;

  if (gold>S.pGold  &&  t!=1) S.worth+= gold-S.pGold;
  S.pGold = gold;

  let pes = S.pEs;
  let ces = {};
  for (let e of es) ces[e.uid] = {uid:e.uid, hp:e.hp, worth:e.worth};
  S.pEs = ces;

  if (t === 1) return shield(); // to not break things depending on previous frame

  if (t == pT+1) {
    for (let uidE in pes) {
      let e = pes[uidE];
      if (!ces[uidE]) { // dead
        if (e.worth < 30) continue; // don't bother, because others probably won't
        for (let a of es) {
          let pa = pes[a.uid];
          if (a.worth >= pa.worth + e.worth/2 - 2) {
            S.stat[a.uid].kills++;
          }
          if (a.worth != pa.worth || a.hp > pa.hp) S.stat[a.uid].seen++;
        }
      }
    }
  }


  let attackers = es.filter(c => {
    let k = S.stat[c.uid].kills;
    let s = S.stat[c.uid].seen;
    return k > 1  &&  k > s*.7;
  });
  let maxDmg = es.map(c=>c.attack).reduce((a, b) => Math.max(a, b), 0)*1.25 + 5;
  for (let e of es) {
    if (e.worth < farmP) continue;
    let p = pes[e.uid];
    let dmg = p.hp-e.hp;
    if (e.hp <= atckP) {
      return attack(e.uid);
    }
    if (e.hp-dmg-atckP <= 0) {
      return attack(e.uid);
    }
    if (e.hp-maxDmg-atckP <= 0) {
      return attack(e.uid);
    }
    if (e.hp-maxDmg-dmg <= 0) {
      return attack(e.uid);
    }
  }
  if (attackers.length>0 && t>50) {
    for (let e of es) {
      if (e.hp - maxDmg*2 - atckP <= 0  &&  e.worth > 200) {
        let worst = saneReduce(attackers.filter(c => c.hp > 80), (a, b)=>a.worth>b.worth? a : b, null);
        if (worst) return stun(worst.uid);
      }
    }
  }



  if (t < 60  &&  t%5 == 1) return shield();
  if (t === 2) return upgrade("heal");
  if (t === 3) return upgrade("farm");
  if (t%10 == 1) return shield();

  if (gold>=cost(lShld) && lFarm>-2) return upgrade("shield");
  if (gold>=cost(lFarm) && !attacked) return upgrade("farm");

  if (es.length > 2) {
    let notDead = es.filter(c => c.hp > 20);
    if (notDead.length !== 0) {
      notDead.sort((a, b) => a.hp-b.hp);
      if (notDead[Math.min(2, notDead.length-1)].hp > shp) {
        return pheal();
      }
    }
  }


  if (gold>=cost(lHeal)  &&  lHeal+5 < lFarm) return upgrade("heal");
  if (gold>=cost(lAtck)  &&  lAtck+5 < lFarm  &&  es.every(c=>c.attack<=lAtck+2)) return upgrade("attack");

  if (lShld>5  &&  shp < 205+healP+t  &&  shp < 600+t*5) return pheal();
  if (es.every(c => c.worth < S.worth+farmP) && es.length>2 && t<100 && lShld<6) return pheal();
  if (shp<=120  ||  hp<5) return pheal();
  return farm();
}

Ora non solo ruba uccisioni, ma ruba anche rubando uccisioni!

Questo robot non fa molto tranne la fattoria, e quando nota la possibilità, si unisce al colpo finale a un nemico morente e in qualche modo riesce ad essere molto buono.


Funziona perché tutti i robot coinvolti in un colpo mortale ottengono la ricompensa completa.
Draco18s

@ Draco18s Capisco perché potrebbe essere buono, non mi aspettavo un'idea così semplice per ottenere in media il doppio del punteggio del prossimo miglior bot (al momento della sua realizzazione).
dzaima,

Hehe, è giusto. Dovrò scaricare tutti i robot quando posso e vedere se riesco a trovare un'altra soluzione.
Draco18s

9

L'equalizzatore

Questo bot cerca di ristabilire la pace nella comunità dei bot. Si rivolge incessantemente ai robot con l'attacco più alto, rinunciando solo se la cura del robot è migliore del suo stesso attacco. Una volta che non sono rimasti robot con cure peggiori del suo attacco, si ritirerà in una vita di agricoltura pacifica.

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();
}

8

Ottimista

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();
}

Suppone che sarà in grado di trascorrere l'80% del suo tempo in maniera pacifica, quindi inizia a sfruttare al massimo l'agricoltura e solo allora inizia a prestare attenzione alle sue abilità di combattimento. Sicuramente nulla andrà storto!


8

Kill Assist

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();
}

Perché aggiornare il valore di attacco quando puoi fare danni da plink e ottenere ancora credito?

Ancora una volta torniamo a cavalcare Kill Stealer. Sono stato in grado di semplificare diversi blocchi di codice in cui le dichiarazioni erano sempre vere e giocherellare con alcuni numeri che hanno portato a enormi guadagni rispetto all'originale.

Devo consegnarlo a @dzaima per rendermi conto che stordire un ricco avversario che probabilmente sarà coinvolto in un assist nel turno prima che avvenga un'uccisione è abbastanza intelligente. Una delle (molto) poche volte Stun()ha un esito positivo della somma. Ancora una volta sono stato in grado di migliorare l'idea, poiché sapendo che Kill Stealer eseguirà una logica simile, Kill Assist cerca un "secondo miglior" obiettivo (con una certa discrezione) e invece li stordisce.

Aggiornamento minore per prevenire lo stordimento del robot che sta per morire e prevenire lo stordimento del robot che ha più probabilità di uccidere.

Risultati di esempio (troncati primi 5 dopo 1000 partite)

VM2406:1629 Kill Assist: 39495.679
VM2406:1629 The Accountant: 29990.267
VM2406:1629 Kill Stealer: 23530.153
VM2406:1629 Unkillable: 12722.604
VM2406:1629 captFarmer: 12232.466

Aspetta, in quale mondo il Capitano Farmer ottiene oro 14k?
Programmi di Redwolf il

Questo:runGame(1) results: [...] captFarmer: 13768
Draco18s

È piuttosto inaspettatamente alto ... di solito ottiene circa 10k nei miei test
Programmi Redwolf il

* shrugh * Nessuna idea. Farò un aggiornamento automatico per assicurarmi che tutto sia pulito.
Draco18s

Il mio bot preferito entro la scadenza.
Night2

7

Undyable Bot (v3)

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()
            }
        }        
    }   
}


Non preoccuparti di me ... Prenderò in prestito questo.
Draco18s

6

PatientStrategistBot

Ho provato a scrivere un bot che inizia a inquadrare e difendersi secondo necessità e poi passa a uccidere altri robot di alto valore più avanti nel gioco.

Attualmente questo non sembra funzionare correttamente poiché è stato ucciso da una banda di robot assassini all'inizio del gioco o rimane bloccato da qualche parte nella sua modalità offensiva.

Sono ancora abbastanza contento che questo sia il mio primo codice JS, quindi ... (Ho rubato frammenti di codice da qui e lì perché era più veloce che cercare su Google tutta la sintassi di base di JS)

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();

}

6

Svizzera

function switzerland(self,others,storage){
    let turnsLeft=999-turn()
    let lowestHpBots=others.sort((a,b)=>a.hp-b.hp)
    if(!storage.worth){
        storage.worth=0
        storage.prevGold=25
    }else if(self.gold>storage.prevGold){
        storage.worth+=self.gold-storage.prevGold
    }
    if(others.length===1&&storage.worth>others[0].worth){
        //stun lock the other bot if there are only 2 left and I can win
        return stun(others[0].uid)
    }else 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){
        //kill assist
        return attack(lowestHpBots[0].uid)
    } else if(self.shield<=50||self.shield<=5500/others.length&&self.shield<=1200&&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()
    }
}

Come suggerisce il nome, questo bot è neutro per lo più neutro (ora aiuta a uccidere i robot che stanno per morire) e solo fattorie e cure, costruendo lentamente il suo oro ( proprio come la Svizzera )


6

Il robot che coltiva, attacca, protegge e perfino guarisce ma non stordisce mai

(Il nome breve è TBTFASAEHBNS , da non confondere con TBTPTGCBCBA )

function TBTFASAEHBNS(me, others, storage) {
    this.getLevel = function (type) {
        return (typeof me.levels[type] === 'undefined' ? 0 : me.levels[type]);
    };

    this.getPower = function (type, level) {
        if (typeof level === 'undefined') level = this.getLevel(type);
        if (type === 'heal') return level + 5;
        if (type === 'attack') return (level * 1.25) + 5;
        if (type === 'shield') return (level * 1.5) + 5;
        if (type === 'farm') return (level * 2) + 5;
    };

    this.canUpgrade = function (type) {
        return myGold >= cost(this.getLevel(type));
    };

    this.farmOrUpgradeFarm = function () {
        if (this.canUpgrade('farm')) return upgrade('farm');
        if (myHp < 3) return heal();
        return farm();
    };

    let currentTurn = turn(),
        myGold = me.gold,
        myHp = me.hp,
        myShield = me.shield,
        myTotalHp = myHp + myShield,
        myHealPower = this.getPower('heal'),
        myShieldPower = this.getPower('shield'),
        myAttackPower = this.getPower('attack'),
        myFarmPower = this.getPower('farm'),
        topAttackPower = 0,
        attackOptions1 = [],
        attackOptions3 = [],
        attackOptions2 = [],
        finalTurns = 980;

    if (currentTurn === 1) {
        storage.othersInfo = {};
    }

    others.sort((a, b) => b.attack - a.attack);
    for (let i = 0; i < others.length; i++) {
        let other = others[i];

        if (i < 3) topAttackPower += this.getPower('attack', other.attack);

        if (other.worth > myFarmPower) {
            if (other.hp <= myAttackPower) {
                attackOptions1.push(other);
            } else {
                if (typeof storage.othersInfo[other.uid] !== 'undefined') {
                    let otherHpChange = storage.othersInfo[other.uid].hp - other.hp;

                    if (other.hp - otherHpChange <= 0) {
                        attackOptions2.push(other);
                    } else if (other.hp - (otherHpChange * 3) <= 0) {
                        attackOptions3.push(other);
                    }
                }
            }
        }

        storage.othersInfo[other.uid] = {hp: other.hp};
    }

    if (myTotalHp < (topAttackPower * 7) + 5) return shield();
    if (currentTurn <= 10) return this.farmOrUpgradeFarm();

    if (attackOptions1.length > 0) {
        attackOptions1.sort((a, b) => b.worth - a.worth);
        return attack(attackOptions1[0].uid);
    } else if (attackOptions2.length > 0) {
        attackOptions2.sort((a, b) => b.worth - a.worth);
        return attack(attackOptions2[0].uid);
    } else if (attackOptions3.length > 0) {
        attackOptions3.sort((a, b) => b.worth - a.worth);
        return attack(attackOptions3[0].uid);
    }

    if (currentTurn <= 20) return this.farmOrUpgradeFarm();
    if (currentTurn < finalTurns && myShieldPower < topAttackPower / 2 && Math.random() * 15 < 1 && this.canUpgrade('shield')) return upgrade('shield');
    if (currentTurn < finalTurns && this.canUpgrade('farm')) return upgrade('farm');
    if (currentTurn < finalTurns && myHealPower < 10 && this.canUpgrade('heal')) return upgrade('heal');
    if (myHp < 3) return heal();
    return farm();
}

Questo bot fondamentalmente:

  • Si basa sull'agricoltura all'inizio
  • Si difende quando necessario
  • Attacca quando può uccidere o quando pensa che ci sia la possibilità di uccidere qualcuno
  • Aggiornamenti qui e poi
  • Coltiva il resto del tempo
  • Non stordire mai

Modifica 1: risolto un problema e migliorato alcune piccole cose nel bot in base ai test con molti giochi.

Modifica 2: aggiornamenti dello scudo ridotti.


2
Appena ho visto il nome ho capito che sarebbe stato il tuo bot (:
Programmi Redwolf il

Mi dispiace per i nomi lunghi, ma ne sono dipendente!
Night2

1
Forse è un segno di un buon robot ... i miei test mostrano che è al 5 ° posto
Programmi Redwolf il

5

SniperBot

Questo bot sarà efficace solo se qualcuno inizia ad aggiungere robot che effettivamente attaccano su base regolare. SmartFarmer è la mia attuale soluzione ottimizzata

  1. guarisce se può ottenere un colpo solo
  2. guarisce se sotto i 30 anni
  3. attacca il bot se riesce a toglierlo e guadagnare più denaro dell'agricoltura
  4. potenzia l'agricoltura se può permettersi
  5. potenzia la cura se ha meno di 80 anni di salute e se lo può permettere
  6. aziende agricole

gli avvoltoi non hanno bisogno di un attacco

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();
}

Identificatore imprevisto ( int) alla riga 2. Errore di riferimento: integrità non definita.
Draco18s

Dovrebbe essere me.hp?
mbomb007

spiacente. nuovo su JavaScript. grazie per l'aiuto
B0RDERS

Potresti if(me.hp <30 && ...)essere semplificato solo alla prima clausola a causa della necessità di un livello di guarigione assurdo per la sua importanza (Liv 65)
Veskah

@Veskah Grazie per averlo sottolineato. Quello era un residuo di quando il CV minimo era più alto
B0RDERS il

5

BullyDozerBot

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);
}

Mashup di BullyBot e alcuni altri bit. L'ottimista aveva un piccolo e doloroso pezzo di attacco opportunistico che ho pensato (anche se altri robot fanno calcoli simili).

Invece di opprimere il bersaglio stordendolo, li uccide per il loro dolce e dolce bottino. Si rivolge anche al più debole della mandria per bullismo, ma si arrenderà e andrà a coltivare solo se i PS del bersaglio più debole sono troppo alti.


ti stai coltivando a morte. Accetta la mia modifica :)
B0RDERS il

1
@AndrewBorders Ah, non ci ho nemmeno pensato. Grazie.
Draco18s

Questo robot è stato fantastico fino a quando non sono arrivati ​​i robot protettori.
B0RDERS

@ B0RDERS Shield è molto potente, anche se fa perdere tempo.
Draco18s

5

FizzBuzz

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);
}

Bot principalmente offensivo. Estremamente sconvolto dal fatto che non può veramente FizzBuzz, quindi invece ronza rabbiosamente. Quando non è Fizzing o Buzzing, si ritira in un altro bot per 30 turni e si arrende e sceglie un altro bot da bersagliare se non sta facendo progressi.

Esegue straordinariamente incoerentemente. Poco male, aggiornato il controller, ora sembra essere sempre nella metà del pacchetto.


Mi piace questo concetto. Indipendentemente dalla situazione attuale, continua a ridacchiare al suo ritmo.
Ness,

5

bullyBot

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);
}

Provalo online!

Non può vincere, ma farà sicuramente del suo meglio per assicurarsi che il suo obiettivo non lo sia neanche. bullyBot coltiva anche al primo turno in modo che se non c'è influenza esterna, batterà il suo bersaglio 5-0 o legherà 5-5.


5

JustFarm

Ho pensato di iniziare semplice.

function justFarm(me, others){
    return farm();
}

13
Questo robot si suiciderà a causa del costo agricolo di 2HP.
Draco18s

@ Draco18s Anche se il round potrebbe finire prima, a seconda del numero di bot
Programmi Redwolf

1
Sebbene tecnicamente vero, un timer da 50 round è molto molto breve quando l'ora di fine predefinita è 1000.
Draco18s

Ha battuto i due robot di esempio, ma ora ci sono alcune altre osservazioni che potrei provare a trovare qualcosa di meglio.
Anonimo

@Anonimo Forse includendo potenziamenti per la cura e l'agricoltura saranno sufficienti. Poiché ottenere più oro è l'obiettivo finale, mantenerlo come lavoro principale del bot potrebbe funzionare. Finora non ci sono stati robot che hanno "modalità" come la modalità cura e la modalità fattoria, potrebbe essere un approccio interessante
Programmi Redwolf

4

ScavengerBot (V2)

Ho realizzato che prima non era un granché. La nuova strategia è aspettare fino a quando non può uccidere un altro bot. Se nessuno può essere ucciso, si siede e costruisce uno scudo.

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();
}

1
me.levels.attacl?
Draco18s

Buona cattura, risolto
reffu

4

lunatico

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);   
}

La strategia di default di Moody's è migliorare l'agricoltura e la cura per un po ', quindi eliminare gli altri robot in ordine decrescente di valore. Tuttavia, se viene attaccato, si spaventerà e si concentrerà nuovamente sulla guarigione per un po '. Se attacca e "fallisce", perché la vittima stava curando o proteggendo in modo più efficace dell'attacco, si arrabbierà e andrà a potenziare le sue abilità di attacco.


4

Bandito

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;
}

Primo tentativo di bot di apprendimento per rinforzo. Puramente difensivo per ora per restringere lo spazio di ricerca. Una specie di spin-off più intelligente di FizzBuzz: ripete ripetutamente una serie specifica di cinque azioni; le cinque azioni sono quelle che sono state scelte da RL.

Ma per ora si basa principalmente sull'enumerazione: ho appena generato tutte le 3 ^ 5 = 243 permutazioni di serie di cinque azioni difensive che si sono ripetute più volte e memorizzato i loro punteggi medi (divisi per 200, per ottenere il guadagno medio sopra cinque turni) oltre 100 iterazioni storage.priornell'array. Quindi, durante il gioco, implementa un approccio avido di epsilon per aggiornare quelle liste di punteggi, quindi è più a prova di futuro. (Anche perché l'uso di epsilon = 0.3 è andato molto meglio di epsilon = 0.1, quindi l'ho tenuto.)

Va bene, posizionandosi costantemente tra scavengerBot e Optimist. Attualmente sto facendo un po 'più di allenamento su giochi reali e sto cercando modi migliori per inquadrare la strategia, per vedere se posso migliorarla.


4

The Opportunist

Questo prende in prestito un po 'da pochi altri (in particolare ScavengerBot (V2) e Unkillable) poiché avevano le stesse idee che avevo in mente, ma in genere mi piacciono gli stili di arrotondamento e jack-of-all-trade più che concentrarmi solo su una o due cose. Questo probabilmente significherà che non vincerò, ma dovrebbe essere nel mezzo da qualche parte (cosa che mi succede la maggior parte delle volte in molte cose).

Quindi ruba succose uccisioni; guarisce se necessario; potenzia la fattoria, attacca e cura in quell'ordine; e fattorie altrimenti.

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();
    }
}

1
Il secondo argomento dovrebbe essereothers
SuperStormer il

4

ScaredBot

  1. Trova altri robot:
    • con l'attacco più alto
    • con più ricchezza e HP inferiori al proprio attacco
  2. Se il suo scudo HP + è inferiore a quello trovato highest attack * (25% of bots), o si avvicina all'estremità inferiore di HP + shield, allora protegge
  3. Se trova un bot con uno scudo inferiore rispetto al suo stesso attacco, lo attacca.
  4. Se la sua salute lo è < 50, guarisce.
  5. Se può potenziare uno qualsiasi degli scudi, curare e coltivare, aggiorna quello con il livello più basso
  6. Si coltiva
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();
    }
}

L'idea è di rimanere in vita il più a lungo possibile e altrimenti provare a ottenere l'oro in un modo sicuro ed economico per poter aggiornare.

Le priorità di aggiornamento dovrebbero probabilmente essere modificate, così come le condizioni per determinare se proteggere.


3

SmartFarmer

Aziende agricole, potenzia l'agricoltura, guarisce se in bassa salute. L'agricoltura sembrava sopraffatta fino all'arrivo dei robot veramente offensivi. Ora il mio bot viene ucciso :-(

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();
}

1
Stavo testando (manualmente) essenzialmente la stessa strategia per vedere qual è il valore massimo ottenibile e i numeri migliori che ho potuto ottenere, ritardando leggermente quando la cura è stata aggiornata (ho usato l'oro> = costo * 2) e salendo al livello 10 .
Nicolai,

Quel moltiplicatore di prezzo è una buona idea. Ho aggiunto qualcosa di simile. Sarei interessato a vedere quali numeri hai
B0RDERS

3

Mort

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];
}

Ad ogni turno, confronta il profitto ammortizzato dell'uccisione di ogni robot con quello dell'agricoltura e della guarigione e sceglie l'opzione migliore. Dovrebbe davvero usare lo stato per capire quanto tempo ci vorrà per uccidere un robot, ma per ora presuppone che ogni robot guarisca o protegga una media di 5 punti al turno al netto del danno che altri robot fanno.


3

Bot amichevole

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();
}

others[0].hpè hp + shieldinvece di hp...


4
Qualcuno può aiutarmi a tradurre il nome della funzione in inglese? ^ _ ^
tsh

4
Secondo Google Translate, "闷声 发大财" significa "Muffled". Abbastanza sicuro che non è quello che vuoi ed è in effetti un altro fallimento epico di Google Translate ... Ho cercato ulteriormente e tutti i risultati sembrano menzionare che non esiste una sola parola inglese che può essere utilizzata qui, quindi potrebbe essere meglio tenerlo come è, in realtà, come sembra essere una preposizione cinese che generalmente significa che si dovrebbe lavorare in silenzio e lasciare che i risultati parlino da soli e raggiungano una filosofia tradizionale. Sfortunatamente, non conosco affatto il cinese per tradurlo direttamente. : D
Erik the Outgolfer

1
come madrelingua cinese, significa qualcosa come "fare silenziosamente una grande fortuna": v conn connota anche intenzionalmente essere silenzioso, letteralmente "nascondendo il suono"
la trasformata di Rin di Fourier il

1
Subdolo? Sotto il radar? DontMindMe? AttentionDeflector?
Peter Taylor,

3

Il ragioniere

Questo robot pratico calcola la mossa economicamente più vantaggiosa, ma gli piace mantenere basso il suo profilo di attacco per evitare problemi a tutti i robot di vigilanza. Non cerca di scegliere di aiutare gli indifesi o di depredarli. Piuttosto, fa ciò che lo aiuta di più.

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 attacks = [];
    for (var i = 0; i < others.length; i++) if (others[i].uid != me.uid) attacks[i] = 1.25 * others[i].attack + 5;
    attacks.sort();
    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;
        }
    }
    maxUrgentProfit = 0;
    for (var i = 0; i < others.length; i++) if (maxUrgentProfit < others[i].worth / 2 && others[i].hp <= attacks.slice(0, 4).reduce((a, b) => a + b) + 1.25 * me.levels.attack + 5) {
        maxUrgentProfit = others[i].worth / 2;
        victimID = others[i].uid;
    }
    if (maxUrgentProfit > 0) {
        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() < Math.pow((me.hp + me.shield) / 100, -2)) {
            storage.lastHP += 1.5 * me.levels.shield + 5;
            return shield();
        }
    }
    else {
        if (Math.random() < .5 || me.hp + me.shield - storage.hisAttack - attacks[0] <= 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();
}

3

reallyCommittedTurtle

function reallyCommittedTurtle(me, others, storage) {
    if( storage.previousHP ) {
        others.forEach ( o => {storage.deltaHP[o.uid] = o.hp - storage.previousHP[o.uid]; storage.previousHP[o.uid] = o.hp } );
    }
    else {
        storage.previousHP = {};
        storage.deltaHP = {};
        others.forEach ( o => storage.previousHP[o.uid] = o.hp );
    }
    if (turn() < 3)
        return upgrade("shield");
    if ( me.shield < 400 || others.find( o=> o.deltaHP < -2 ) )
        return shield();
    if (me.hp <= 95 - me.levels.heal) {
        if (me.gold >= cost(me.levels.heal))
            return upgrade("heal");
        return heal();
    }
    rich_bots = others.sort( (x,y) => y.worth - x.worth );
        potential_victim = rich_bots.find( bot => bot.hp + storage.deltaHP[bot.uid] <= me.levels.attack * 1.25 + 5 );
        if (potential_victim && potential_victim.worth/2 > me.levels.farm*2 + 5)
            return attack(potential_victim.uid);
    if (me.gold >= cost(me.levels.farm))
        return upgrade("farm");
    return farm();
}

Ecco la cosa. È diventato davvero pericoloso là fuori. L'agricoltura aumenta il tuo valore, rendendoti un bersaglio. Quindi non è davvero sicuro coltivare fino a quando non hai costruito un enorme scudo e tutta la violenza è morta. Quindi puoi estrarre la testa dal guscio e iniziare a coltivare. O uccidere assistendo. Qualunque cosa paghi meglio.


2

Custode

Posso avere più di un invio, giusto?

Un fork di CampBot. Non protegge, invece si concentra sugli attacchi. Mostra una preferenza per attaccare i giocatori con statistiche di attacco più alte, piuttosto che colpire a caso come CampBot. Si concentra sul miglioramento della sua agricoltura piuttosto che sulla guarigione.

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()
    }
}

il mio bot non attacca casualmente ...
SuperStormer

Puoi pubblicare tutte le volte che vuoi, più suppongo sia più
bello

@SuperStormer Mi rendo conto che il tuo non è del tutto casuale, ma:let victim=potentialVictims[Math.floor(Math.random()*potentialVictims.length)]
Anonimo il

ma prima filtra quelli che non vale la pena attaccare
SuperStormer il

Stavo lavorando su un bot simile chiamato equalizzatore quando hai pubblicato questo. Lo sto ancora perfezionando, ma mi piacciono alcune delle tue idee.
B0RDERS

2

Rando

Questo tipo sciocco sceglierà azioni basate sulla casualità uniforme con alcuni preconcetti. Se un'azione scelta casualmente non funziona, passa alla scelta successiva.

Quindi, in media, dovrebbe attaccare quasi i 2/9 delle volte e coltivare quasi i 3/9 delle volte. Il resto ha circa 1/9 di probabilità se è in grado di aggiornare, o se vale la pena curare / proteggere, ecc.

Probabilmente non si esibirà bene, ma almeno c'è una piccola possibilità che regni sovrano. E questo è l'intero scopo di Rando. Deve solo credere in se stesso! Tutte le opzioni sono poste davanti a lui. Deve solo scegliere ciò che è necessario per una determinata situazione.

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
    }
}

(So ​​che "default" non è necessario, ma penso che sia una buona pratica di codifica per codice robusto.)


2
"Ha solo bisogno di credere in se stesso" ... Sto ridendo così tanto in questo momento
Redwolf Programmi

2

Kill Bot

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);
}

Un semplice robot, Kill Bot vuole solo uccidere i suoi nemici. Poiché la schermatura è molto più efficiente della guarigione (specialmente se livellata), Kill Bot cerca solo di essere sempre un bersaglio poco attraente proteggendosi ogni volta che viene attaccato. Kill Bot fa abbastanza bene tra i robot deboli e pacifisti qui intorno (puoi sentirne il disprezzo per loro).


3
Nota che o.attackè il livello di attacco, non il suo danno
Programmi Redwolf il

2

FarmHeal Bot

Biforcuta dal bot JustFarm di @Anonym

function farmhealBot(me, others, storage) {
  if (me.hp <= 95)
    return heal();
  else return farm();
}

2

Indistruttibile

Una modifica del bot di Draco18, usando gli scudi (più efficace contro altri robot)

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();
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.