Goldschlacht KoTH


43

Diese Herausforderung ist beendet. Klicken Sie hier, um die Endergebnisse der Wettbewerber anzuzeigen

Bei dieser Herausforderung ist jeder Beitrag ein Bot. Jeder Bot sollte eine Javascript-Funktion sein. Bots kämpfen um den höchsten Goldwert. Gold kann gezüchtet oder durch das Töten anderer Bots verdient werden und wird verwendet, um Heilung, Angriffe, Abschirmung und Landwirtschaft zu verbessern.

Zielsetzung:

Bei einer Anzahl von Runden mit bis zu 1000 Runden (endet, wenn nur noch ein Bot übrig ist) gewinnt der Bot mit dem höchsten Gesamtwert (die Summe aller erhaltenen Goldstücke).

Wendet sich:

In jedem Zug wird jeder Bot, der lebt (> 0 HP), einmal ausgeführt. Es kann eine Bewegung zurückgeben, die eine der folgenden sein kann:

  • Heilen: Gewinnt HP zurück
  • Angriff: Entfernt HP von einem anderen Bot
  • Schild: Verteidigt sich gegen spätere Angriffe
  • Betäuben: Überspringt den nächsten Zug eines anderen Bots
  • Farm: Verdient Gold auf Kosten von HP
  • Upgrade: Machen Sie bestimmte Züge besser

Alle Bots geben ihren Zug zurück, bevor einer ausgeführt wird. Betäubung, Heilung, Angriff, Schild usw. wirken sich nicht auf Bots aus, die sich später in diesem Zug bewegen. Wenn zum Beispiel Bot A Bot B betäubt und Bot B in der Reihenfolge nach Bot A ist, bewegt sich Bot B immer noch später in derselben Runde und die Betäubung erfolgt in der nächsten Runde.

Kampf, Landwirtschaft und Aufwertung:

Jeder Bot hat eine maximale HP von 100 und eine zugewiesene UID zwischen 0 und 99. Diese UID ändert sich nach jeder Runde und zeigt an, wie Bots sich gegenseitig überwachen.

Heilung ist einer der einfachsten Schritte, bei dem eine HP-Menge hinzugefügt wird, die von der Stufe abhängt (ab 5 HP). Ein Bot kann nicht mehr als 100 HP heilen.

Das Angreifen eines Bots mit seiner UID ist ein weiterer möglicher Zug mit einem Grundschaden von 5 HP auf Stufe 0. Bots können auch betäubt werden, indem sie ihren nächsten Zug überspringen, der ebenfalls UIDs verwendet.

Bots haben zusätzliche Schild-HP, die keine Begrenzung haben. Dieser Schild HP absorbiert Schaden durch direkte Angriffe anderer Bots und wird durch Abschirmung hinzugefügt. Bei Stufe 0 erhöht die Abschirmung die HP um 5 Schilde.

Die Landwirtschaft erhält 5 Goldpunkte auf Stufe 0 zu einem Preis von 2 HP. Diese 2 HP können nicht abgeschirmt werden. Die einzige Verwendung für Gold (über das Gewinnen hinaus) ist das Aktualisieren von Zügen. Heilung, Angriff und Abschirmung haben einen Grundwert von 5 HP, und die Landwirtschaft beginnt bei 5 Gold. Jede dieser Bewegungen hat individuelle Stufen, die bei 0 beginnen. Diese Formeln bestimmen den Wert in HP oder Gold einer Bewegung, wobei L die Stufe ist:

  • Heilung: L + 5
  • Angreifen: 1.25L + 5
  • Abschirmung: 1.5L + 5
  • Landwirtschaft: 2L + 5

Die Kosten für ein Upgrade eines Zuges sind für eine bestimmte Stufe gleich und werden dadurch bestimmt 2.5L² + 2.5L + 10, wobei L die aktuelle Stufe ist. Ein Bot kann die Funktion cost(currentLevel)als Abkürzung verwenden, um dies zu bestimmen.

Bots beginnen mit 25 Goldpunkten, sodass sie entweder zwei Züge auf Stufe 1 oder einen auf Stufe 2 aufrüsten können. Dieses anfängliche Gold zählt nicht für den Gesamtwert eines Bots. Wenn du einen Bot tötest, erhältst du die Hälfte seines Gesamtwerts an Gold, aufgerundet. Wenn zwei Bots in derselben Runde einen anderen töten, erhalten beide die Belohnung.

Input-Output:

Um mit der Steuerung zu kommunizieren, wird der Rückgabewert der Funktion zum Senden von Bewegungsinformationen verwendet. Eine davon sollte zurückgegeben werden:

  • Heilen: heal()
  • Attacke: attack(uid)
  • Schild: shield()
  • Betäuben: stun(uid)
  • Bauernhof: farm()
  • Aktualisierung: upgrade("heal" / "attack" / "shield" / "farm")

Um eine Runde zu überspringen (nichts zu tun), nichts zurückzugeben oder einen falschen Wert zurückzugeben.

Verwenden Sie, um die aktuelle Zugnummer (beginnt bei 1) abzurufen turn().

Zu den Argumenten Ihrer Funktion gehören Informationen zu Ihrem Bot, UIDs anderer Bots und Speicher zwischen den Runden. Das erste Argument ist ein Objekt mit den folgenden Eigenschaften: uid, hp, gold, und shield. Dies sind Kopien der aktuellen Informationen Ihres Bots. Es gibt auch ein verschachteltes Objekt levels, mit den Pegelzahlen heal, attack, shield, und farm.

Das zweite Argument ist ein Shuffled Array aller alive Bots außer dein, als Objekt formatiert Eigenschaften enthält uid, hp(plus shield), worthund attack(Attack - Ebene). Das dritte Argument ist ein leeres Objekt, das für die Speicherung zwischen den Runden verwendet werden kann.

Beispiel Bots:

Dieser Bot wird so lange gezüchtet, bis er seinen Angriff auf Stufe 5 verbessern kann. Anschließend wird in jeder Runde ein zufälliger Bot angegriffen, bis er stirbt (oder gewinnt). Nicht sehr effektiv wegen mangelnder Heilung / Abschirmung.

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

Dieser Bot hat zwei Modi: Offensiv und Defensiv. Es wird entweder einen zufälligen Bot betäuben oder heilen, wenn es sich im defensiven Modus befindet, und es wird entweder angreifen oder beschützen, wenn es sich im offensiven Modus befindet. Es wird versuchen, seine Angriffe nach Möglichkeit zu aktualisieren.

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

Regeln:

  • Standardschlupflöcher verboten
  • Bots dürfen keine Variablen außerhalb ihres Gültigkeitsbereichs lesen, ändern oder hinzufügen, dürfen nicht versuchen zu schummeln und dürfen keine vom Controller definierten oder DOM-Funktionen aufrufen
  • Der Rückgabewert muss falsch sein oder einer der obigen Funktionsausgänge
  • Bots sollten nicht so konzipiert sein, dass sie auf einen bestimmten Bot abzielen, sondern können so konzipiert sein, dass sie gemeinsame Strategien nutzen
  • Bots dürfen sich nicht selbst angreifen (entdeckt aufgrund eines Kommentars von @Ness)
  • Bots müssen sich ausreichend von anderen Bots unterscheiden, damit sie als separate Einträge angesehen werden können
  • Teaming ist jetzt nicht erlaubt
  • Controller finden Sie hier
  • Chatroom

Neues Controller-Debugging:

Mithilfe der Datei gold-battle-log.jskönnen Sie den Wert der debugEigenschaft eines Bots botDataauf 0 (keine Protokollierung), 1 (Protokollbewegungen) oder 2 (Protokollbewegungen, HP, Gold, Ebenen usw.) setzen.

Die Challenge endet am Freitag, den 9. August um 17:00 Uhr UTC


4
Erstellt einen Kern mit allen Bots. Ich werde mich bemühen, es auf dem neuesten Stand zu halten (aber wenn nicht, ist es ein anständiger Start).
Draco18s


4
Ich stimme dafür, diese Frage zu schließen, da sie bereits de facto für neue Antworten geschlossen ist ("Diese Herausforderung ist beendet. Um die Endergebnisse zu sehen ...")
pppery

3
@pppery Könntest du nicht? Ich würde mit nicht konkurrierenden Antworten zurechtkommen, und [closed]am Ende wird es wahrscheinlich dazu führen, dass Gelegenheitszuschauer meine Herausforderung überspringen, da sie davon ausgehen, dass sie von geringer Qualität ist oder nicht zum Thema gehört.
Redwolf-Programme

5
@pppery Ich habe bis heute noch nie von einer Herausforderung gehört, die für beendet erklärt wurde, und ich würde argumentieren, dass die soziale Einschränkung, die Sie durchsetzen möchten, nicht einmal existiert. Es ist nicht nötig, es zu schließen, und ich möchte nicht, dass es geschlossen wird. Für mich scheint dies eher eine Schließung zum Zweck der Schließung als zum Wohle der Website zu sein. Wenn jemand eine Antwort auf eine alte Frage posten möchte, sollte er dazu in der Lage sein. Nach der Regel für ernsthafte Konkurrenten gibt es keinen Hinweis darauf, dass es sich bei der Veröffentlichung um einen ernsthaften Konkurrenten handeln muss. Eine Antwort kann immer noch ein ernstzunehmender Anwärter auf die Herausforderung sein, auch wenn es kein Anwärter auf den Sieg ist
Redwolf Programs

Antworten:


16

Nicht zu töten

aus Undyable gegabelt .

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

Angesichts der exponentiellen Kosten von Upgrades kann auch die Landwirtschaft verbessert werden, wenn die Heilung nicht verbessert werden kann, sodass der Bot Gold effizienter sammeln kann.


Absolut die Konkurrenz in meinen Tests zu vernichten
Redwolf Programs

1
Ich denke, dieser Bot könnte ein bisschen stärker sein, wenn die erste ifAnweisung verwendet wird <=- derzeit wird er nie vollständig verheilen.
Scoots

@Scoots Ich bin mir nicht sicher, wie wichtig es ist, aber das werde ich ändern.
Draco18s

2
@ Draco18s Ich bin sicher, es ist sehr, sehr wenig wichtig - aber dreht sich auf dieser Website nicht alles um winzige, praktisch unbedeutende Verbesserungen? :)
Scoots

@Scoots Die Heilung zu maximaler Gesundheit spielt bei dieser Herausforderung keine große Rolle, da es keine wirklichen Angriffsbedrohungen gibt. Der einzige wirklich beleidigende Bot ist der Bullybot, und man kann nichts gegen ihn unternehmen. Es könnte die Leistung tatsächlich verringern, um bei voller Gesundheit zu bleiben.
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();
            }
        }
    }
}

Es gibt zu viele Bots, nicht genug Gold, um herumzulaufen. Dieser Bot schlägt eine Lösung vor.

Genozid, ja, aber zufällig, leidenschaftslos, fair zu Arm und Reich.

Sie nannten ihn einen Verrückten.

ThanosBot möchte das Beste für die Bot-Community und ist bereit, den ganzen Weg zu gehen. Zu Beginn wird er seinen Angriff, seine Landwirtschaft und seine Heilung verbessern, um Ressourcen effizienter zu sammeln und Schlachten zu gewinnen. Prograssiv greift er zufällig Leute an und sammelt gleichzeitig Ressourcen für bevorstehende Kämpfe. Er wird seine Armee, seine Waffen und sich selbst weiter verbessern.

Sobald 50% der Bevölkerung eliminiert sind, werden die geborenen Bots nur noch vollen Bauch und klaren Himmel kennen, er wird sich in die Landwirtschaft zurückziehen und den Sonnenaufgang auf einem dankbaren Universum beobachten. Er wird völlig pazifistisch und heilt sich nur mit Gemüsesuppen und Landwirtschaft.


6
Ich bin versucht, "attack" in "snap"
umzubenennen

11

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

Jetzt stiehlt nicht nur Kills, sondern auch Kills!

Dieser Bot macht nicht viel außer Farm, und wenn er die Möglichkeit bemerkt, schlägt er einen sterbenden Feind und schafft es irgendwie, sehr gut zu sein.


Es funktioniert, weil alle Bots, die an einem tödlichen Schlag beteiligt sind, die volle Belohnung erhalten.
Draco18s

@Draco18s Ich verstehe, warum es gut sein kann, ich habe einfach nicht damit gerechnet, dass eine so einfache Idee im Durchschnitt das 2-fache der Punktzahl des nächstbesten Bots (zum Zeitpunkt des Bildens) erreicht.
Dzaima

Hehe, das ist fair. Ich muss alle Bots herunterladen, wenn ich kann, und nachsehen, ob ich eine andere Lösung finde.
Draco18s

9

Der Ausgleicher

Dieser Bot versucht, den Frieden in der Bot-Community wiederherzustellen. Er zielt unerbittlich auf die Bots mit dem höchsten Angriff ab und gibt nur auf, wenn die Heilung des Bots besser ist als sein eigener Angriff. Sobald keine Bots übrig sind, deren Heilung schlimmer ist als der Angriff, zieht er sich in ein Leben in friedlicher Landwirtschaft zurück.

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

Optimist

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

Vorausgesetzt, es wird 80% seiner Zeit friedlich bewirtschaften können, so beginnt es mit der Maximierung der Bewirtschaftung und fängt erst dann an, auf seine Kampffertigkeiten zu achten. Es wird bestimmt nichts schief gehen!


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

Warum den Angriffswert erhöhen, wenn Sie Plinkschaden verursachen und trotzdem die volle Punktzahl erhalten können?

Noch einmal zurück zum Huckepack Kill Stealer. Ich konnte mehrere Codeblöcke vereinfachen, in denen Aussagen immer wahr waren und mit Zahlen spielten, was zu massiven Gewinnen gegenüber dem Original führte.

Ich muss es @dzaima geben, um zu erkennen, dass es ziemlich klug ist, einen reichen Gegner zu betäuben, der wahrscheinlich an einer Assistenz beteiligt ist, bevor ein Kill stattfindet. Eines der (sehr) wenigen Male Stun()hat ein positives Gesamtergebnis. Wieder einmal konnte ich die Idee verbessern, da Kill Assist in dem Wissen, dass Kill Stealer eine ähnliche Logik ausführen wird, nach einem "zweitbesten" Ziel sucht (mit etwas Diskretion) und diese stattdessen betäubt.

Geringfügiges Update, um das Betäuben des Bot, der kurz vor dem Tod steht, und das Betäuben des Bot, der mit größter Wahrscheinlichkeit den Tod herbeiführt, zu verhindern.

Beispielergebnisse (abgeschnittene Top 5 nach 1000 Spielen)

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

Warten Sie, in welcher Welt bekommt Captain Farmer 14.000 Gold?
Redwolf-Programme

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

Das ist ziemlich unerwartet hoch ... in meinen Tests wird es normalerweise um die
10.000

* achselzuck * Keine Ahnung. Ich werde ein automatisiertes Update durchführen, um sicherzustellen, dass alles sauber ist.
Draco18s

Mein Lieblingsbot am Ende der Frist.
Night2

7

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


Kümmere dich nicht um mich ... Ich werde mir das ausleihen.
Draco18s

6

PatientStrategistBot

Ich habe versucht, einen Bot zu schreiben, der nach Bedarf mit dem Framing und der Verteidigung beginnt und später im Spiel andere Bots mit hohem Wert tötet.

Derzeit scheint dies nicht richtig zu funktionieren, da es entweder zu Beginn des Spiels von einer Bande von Mord-Bots getötet wurde oder irgendwo in seinem offensiven Modus hängen bleibt.

Immer noch ziemlich zufrieden damit, dass dies mein erster JS-Code ist, also ... (Ich habe Code-Schnipsel von hier und da gestohlen, weil das schneller war, als die gesamte JS-Basissyntax zu googeln.)

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

Schweiz

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

Wie der Name schon sagt, ist dieser Bot neutral, meistens neutral (jetzt hilft er, Bots zu töten, die sterben werden) und nur Farmen und Heilungen, wobei er langsam sein Gold aufbaut ( genau wie die Schweiz ).


6

Der Bot, der bewirtschaftet, angreift, schützt und sogar heilt, aber niemals betäubt

( Kurzname ist TBTFASAEHBNS , nicht mit TBTPTGCBCBA zu verwechseln )

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

Dieser Bot im Grunde:

  • Baut zu Beginn auf der Landwirtschaft auf
  • Verteidigt sich bei Bedarf
  • Angriffe, wenn es töten kann oder wenn es glaubt, dass die Chance besteht, jemanden zu töten
  • Upgrades hier und dann
  • Bewirtschaftet den Rest der Zeit
  • Betäubt niemals

Edit 1: Ein Problem wurde behoben und einige kleine Dinge im Bot wurden verbessert, basierend auf Tests mit vielen Spielen.

Edit 2: Schild-Upgrades wurden reduziert.


2
Sobald ich den Namen sah, wusste ich, dass es Ihr Bot sein würde (:
Redwolf Programs

Es tut mir leid wegen der langen Namen, aber ich bin süchtig danach!
Night2

1
Vielleicht ist es ein Zeichen für einen guten Bot ... meine Tests zeigen, dass es auf dem 5. Platz ist
Redwolf Programs

5

SniperBot

Dieser Bot ist nur dann wirksam, wenn jemand beginnt, Bots hinzuzufügen, die tatsächlich regelmäßig angreifen. SmartFarmer ist meine derzeit optimierte Lösung

  1. heilt, wenn man einen Schuss bekommt
  2. heilt wenn unter 30
  3. greift bot an, wenn es sich lohnt und mehr Geld verdient als die Landwirtschaft
  4. verbessert die Landwirtschaft, wenn sie es sich leisten kann
  5. Verbessert die Heilung, wenn die Gesundheit unter 80 ist und sich dies leisten kann
  6. Bauernhöfe

Geier brauchen keinen Angriff

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

Unerwarteter Bezeichner ( int) in Zeile 2. ReferenceError: Zustand ist nicht definiert.
Draco18s

Sollte sein me.hp?
mbomb007

Es tut uns leid. neu in Javascript. danke für die
hilfe

Man if(me.hp <30 && ...)könnte es auf die erste Klausel vereinfachen, weil man ein absurdes Maß an Heilung braucht, damit es eine Rolle spielt (Stufe 65)
Veskah,

@Veskah Danke für den Hinweis. Das war ein Überbleibsel aus der Zeit, als die min-PS höher waren
B0RDERS

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 von BullyBot und einigen anderen Teilen. Der Optimist hatte ein kurzes und süßes Stück mit opportunistischen Angriffen, das ich angesprochen habe (obwohl andere Bots ähnliche Berechnungen anstellten).

Anstatt das Ziel zu schikanieren, indem man es betäubt, werden sie wegen ihrer süßen, süßen Beute ermordet . Es zielt auch auf die Schwächsten in der Herde ab, um sie zu schikanieren, aber es gibt auf und geht in die Landwirtschaft, wenn die HP des schwächsten Ziels zu hoch sind.


Sie bewirtschaften sich zu Tode. Akzeptiere meine
Änderung

1
@AndrewBorders Ha, ich habe nicht einmal darüber nachgedacht. Vielen Dank.
Draco18s

Dieser Bot war großartig, bis diese Beschützer-Bots kamen.
B0RDERS

@ B0RDERS Schild ist sehr stark, auch wenn es Zeit verschwendet.
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);
}

Meistens anstößiger Bot. Sehr verärgert über die Tatsache, dass es nicht wirklich FizzBuzz kann und stattdessen nur wütend summt. Wenn es nicht zischend oder summend ist, zersplittert es einen anderen Bot für 30 Runden und gibt auf und wählt einen anderen Bot als Ziel aus, wenn es keine Fortschritte macht.

Leistung außerordentlich uneinheitlich. Egal, der Controller wurde aktualisiert und scheint nun immer in der Mitte des Pakets zu sein.


Ich mag dieses Konzept. Unabhängig von der aktuellen Situation tuckert es weiter in seinem eigenen Tempo.
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);
}

Probieren Sie es online!

Kann nicht gewinnen, wird aber mit Sicherheit sein Bestes geben, um sicherzustellen, dass sein Ziel es auch nicht tut. bullyBot bewirtschaftet auch in der ersten Runde, sodass er sein Ziel mit 5: 0 besiegt oder mit 5: 5 bindet, wenn es keinen Einfluss von außen gibt.


5

JustFarm

Ich dachte, ich würde einfach anfangen.

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

13
Dieser Bot wird aufgrund der 2HP-Kosten der Landwirtschaft Selbstmord erleiden.
Draco18s

@ Draco18s Obwohl die Runde davor enden kann, abhängig von der Anzahl der Bots
Redwolf-Programme

1
Obwohl technisch gesehen , ist ein 50-Runden-Timer sehr, sehr kurz, wenn die Standardendzeit 1000 ist.
Draco18s

Es hat die beiden Beispiel-Bots übertroffen, aber jetzt gibt es ein paar weitere Einreichungen, bei denen ich versuchen könnte, etwas Besseres zu finden.
Anonym

@Anonymous Vielleicht reichen Heilung und Upgrades der Landwirtschaft aus. Da es das ultimative Ziel ist, das meiste Gold zu erhalten, sollte dies so bleiben, wie es die Hauptaufgabe des Bots sein könnte. Bisher hat es noch keine Bots gegeben, die "Modi" wie den Heilungsmodus und den
Farmmodus haben. Dies

4

ScavengerBot (V2)

Es wurde mir klar, dass es vorher kein wirklicher Aasfresser war. Neue Strategie ist warten, bis es einen anderen Bot töten kann. Wenn niemand getötet werden kann, sitzt es und baut Schild auf.

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

Guter Fang, behoben
reffu

4

Launisch

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

Moody's Standardstrategie besteht darin, die Landwirtschaft und die Heilung für eine Weile zu verbessern und dann die anderen Bots in absteigender Reihenfolge ihres Werts auszuschalten. Wenn es jedoch angegriffen wird, wird es ängstlich und konzentriert sich für eine Weile wieder auf die Heilung. Wenn es angreift und "scheitert", weil das Opfer wirksamer geheilt oder abgeschirmt hat als der Angriff, wird es wütend und verbessert seine Angriffsfähigkeiten.


4

Bandit

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

Erster Versuch eines Verstärkungslernbots. Vorerst rein defensiv, um den Suchraum einzugrenzen. Eine Art intelligenter Nebeneffekt von FizzBuzz - es wiederholt eine bestimmte Reihe von fünf Aktionen immer wieder. Die fünf Aktionen werden von RL ausgewählt.

Aber es basiert im Moment hauptsächlich auf Aufzählungen - ich habe gerade alle 3 ^ 5 = 243 Permutationen von Serien von fünf Verteidigungsaktionen generiert, die sich immer wieder wiederholten, und ihre Durchschnittswerte (geteilt durch 200) gespeichert, um den Durchschnittsgewinn zu erhalten fünf Umdrehungen) über 100 Iterationen im storage.priorArray. Während des Spiels wird dann ein Epsilon-gieriger Ansatz implementiert, um diese Punktelisten zu aktualisieren, damit sie zukunftssicherer sind. (Auch weil die Verwendung von epsilon = 0.3 viel besser war als epsilon = 0.1, habe ich es einfach beibehalten.)

Es ist in Ordnung, konsequent zwischen ScavengerBot und Optimist zu platzieren. Momentan mache ich ein bisschen mehr Training für echte Spiele und suche nach besseren Möglichkeiten, die Strategie zu gestalten, um zu sehen, ob ich sie verbessern kann.


4

Der Opportunist

Dieser leiht sich ein bisschen von ein paar anderen (insbesondere ScavengerBot (V2) und Unkillable) aus, da sie die gleichen Ideen hatten, die ich mir vorgestellt hatte, aber ich mag im Allgemeinen Rundungen und Alleskönner-Stile mehr, als mich nur darauf zu konzentrieren ein oder zwei Dinge. Dies wird wahrscheinlich bedeuten, dass ich nicht gewinnen werde, aber es sollte irgendwo in der Mitte sein (was mir die meiste Zeit in vielen Dingen passiert).

So stiehlt es saftige Kills; heilt wenn nötig; Verbessert die Farm, greift an und heilt in dieser Reihenfolge. und Farmen sonst.

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
2. Argument sollte seinothers
SuperStormer

4

ScaredBot

  1. Es findet andere Bots:
    • mit dem höchsten Angriff
    • mit den meisten Reichtümern und HP niedriger als der eigene Angriff
  2. Wenn der HP + -Schild niedriger ist als der gefundene highest attack * (25% of bots)oder sich dem unteren Ende nähert HP + shield, wird er abgeschirmt
  3. Wenn er einen Bot gefunden hat, dessen Schild niedriger ist als sein eigener Angriff, greift er ihn an.
  4. Wenn es gesund ist < 50, heilt es.
  5. Wenn Schild, Heilung und Farm aufgerüstet werden können, wird die niedrigste Stufe aufgerüstet
  6. Es bewirtschaftet
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();
    }
}

Die Idee ist, so lange wie möglich am Leben zu bleiben und ansonsten Gold auf sichere und kostengünstige Weise zu beschaffen, um ein Upgrade durchführen zu können.

Die Upgrade-Prioritäten sollten wahrscheinlich angepasst werden, ebenso wie die Bedingungen, unter denen entschieden wird, ob ein Schild angebracht werden soll.


3

SmartFarmer

Farmen, Upgrades der Landwirtschaft, heilt bei geringer Gesundheit. Die Landwirtschaft schien überfordert zu sein, bis die wirklich offensiven Bots eintrafen. Jetzt wird mein Bot getötet :-(

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
Ich habe (manuell) im Wesentlichen die gleiche Strategie getestet, um herauszufinden, was der maximal erreichbare Wert und die besten Zahlen sind, die ich bekommen konnte, indem ich die Aktualisierung der Heilung leicht verzögert habe (ich habe Gold> = Kosten * 2 verwendet) und bis Stufe 10 geheilt habe .
Nicolai

Dieser Preismultiplikator ist eine gute Idee. Ich habe etwas Ähnliches hinzugefügt. Es würde mich interessieren, welche Zahlen Sie haben
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];
}

Jede Runde vergleicht den amortisierten Gewinn, den das Töten eines Bots mit dem der Landwirtschaft und Heilung erzielt, und wählt die beste Option aus. Eigentlich sollte der Status verwendet werden, um herauszufinden, wie lange es dauern wird, einen Bot zu töten, aber im Moment wird davon ausgegangen, dass jeder Bot durchschnittlich 5 Punkte pro Runde heilt oder abschirmt, abzüglich des Schadens, den andere Bots anrichten.


3

Freundlicher Bot

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].hpist hp + shieldstatt hp...


4
Kann mir jemand helfen, den Funktionsnamen ins Englische zu übersetzen? ^ _ ^
tsh

4
Laut Google Translate bedeutet "means 闷声" "gedämpft". Ich bin mir ziemlich sicher, dass das nicht das ist, was Sie wollen, und es ist in der Tat ein weiteres Google Translate-Epos Tatsächlich scheint es sich um eine chinesische Präposition zu handeln, die im Allgemeinen bedeutet, dass man leise arbeitet und die Ergebnisse für sich selbst sprechen lässt und zu einer traditionellen Philosophie gelangt. Leider kann ich überhaupt kein Chinesisch, um es direkt zu übersetzen. : D
Erik der Outgolfer

1
als chinesischer Muttersprachler bedeutet es so etwas wie "still ein großes Vermögen machen": v 闷声 bedeutet auch absichtlich leise sein, wörtlich "Ton vertuschen"
Rins Fourier-Transformation

1
Hinterhältig? Unter dem Radar? DontMindMe? AttentionDeflector?
Peter Taylor

3

Der Buchhalter

Dieser praktische Bot berechnet den wirtschaftlich günstigsten Zug, möchte aber sein Angriffsprofil niedrig halten, um Ärger durch alle vigilanten Bots zu vermeiden. Er versucht nicht, den Wehrlosen zu helfen oder sie zu jagen. Er tut vielmehr das, was ihm am meisten hilft.

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

Hier ist das Ding. Es ist wirklich gefährlich geworden da draußen. Die Landwirtschaft erhöht Ihren Wert und macht Sie zu einem Ziel. Es ist also wirklich nicht sicher zu farmen, bis du einen riesigen Schild aufgebaut hast und die Gewalt nachgelassen hat. Dann können Sie Ihren Kopf aus der Schale stecken und mit der Landwirtschaft beginnen. Oder tötungsunterstützend. Was sich auszahlt, ist besser.


2

Wächter

Ich kann mehr als eine Einreichung haben, oder?

Eine Gabelung von CampBot. Schildt nicht ab, sondern konzentriert sich auf Angriffe. Zeigt eine Präferenz für das Angreifen von Spielern mit höheren Angriffswerten, anstatt wie CampBot zufällig zu schlagen. Konzentriert sich eher auf die Verbesserung der Landwirtschaft als auf die Heilung.

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

Mein Bot greift nicht zufällig an ...
SuperStormer

Du kannst so oft posten, wie du willst, je mehr, nehme ich an
Redwolf Programs

@ SuperStormer Mir ist klar, dass Ihre nicht ganz zufällig sind, aber:let victim=potentialVictims[Math.floor(Math.random()*potentialVictims.length)]
Anonym

Aber zuerst werden diejenigen herausgefiltert, die es nicht wert sind, angegriffen zu werden
SuperStormer

Ich habe an einem ähnlichen Bot namens Equalizer gearbeitet, als Sie dies gepostet haben. Ich bin immer noch am Feinabstimmen, aber ich mag einige Ihrer Ideen.
2.

2

Rando

Dieser alberne Typ wählt Aktionen basierend auf einheitlicher Zufälligkeit mit einigen Vorurteilen. Wenn eine zufällig ausgewählte Aktion nicht funktioniert, wechselt sie zur nächsten Auswahl.

Im Durchschnitt sollte er also fast 2/9 der Zeit angreifen und fast 3/9 der Zeit bewirtschaften. Der Rest hat eine Chance von etwa 1/9, wenn er upgraden kann oder wenn die Heilung / Abschirmung es wert ist, usw.

Er wird wahrscheinlich nicht gut abschneiden, aber es gibt zumindest eine kleine Chance, dass er an der Spitze steht. Und das ist der ganze Zweck von Rando. Er muss nur an sich glauben! Alle Optionen sind vor ihm gelegt. Er braucht nur zu wählen, was für eine gegebene Situation benötigt wird.

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

(Ich weiß, dass "Standard" nicht erforderlich ist, aber ich denke, es ist eine gute Codierungspraxis für robusten Code.)


2
"Er muss nur an sich glauben" ... Ich lache gerade so viel
Redwolf Programs

2

Töte 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);
}

Als einfacher Bot will Kill Bot nur seine Feinde töten. Da das Abschirmen viel effizienter ist als das Heilen (besonders wenn es im Level ist), versucht Kill Bot immer ein unattraktives Ziel zu sein, indem er sich selbst abschirmt, wenn er angegriffen wird. Kill Bot macht sich unter den schwachen, pazifistischen Bots hier ziemlich gut (man kann seine Verachtung für sie spüren).


3
Beachten Sie, dass dies o.attackdie Angriffsstufe und nicht der Schaden ist
Redwolf Programs

2

FarmHeal Bot

Gegabelt von @Anonymous 'JustFarm bot

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

2

Unzerstörbar

Eine Modifikation des Draco18-Bots mit Schildern (effektiver gegen andere Bots)

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();
        }
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.