Gold Battle KoTH

43

To wyzwanie się skończyło. Aby zobaczyć ostateczne wyniki zawodników, kliknij tutaj

W tym wyzwaniu każde zgłoszenie jest jednym botem. Każdy bot powinien być funkcją Javascript. Boty będą walczyć o najwyższą łączną wartość złota. Złoto można hodować lub zdobywać za zabijanie innych botów i służy ono do ulepszania leczenia, ataku, ochrony i rolnictwa.

Cel:

W ciągu kilku rund zawierających do 1000 tur (kończy się, gdy pozostanie tylko jeden bot), bot o najwyższej wartości całkowitej (suma uzyskanego złota) jest zwycięzcą.

Okazuje:

W każdej turze każdy żywy bot (> 0 HP) zostanie uruchomiony raz. Może zwrócić ruch, który może być jednym z następujących:

  • Leczenie: odzyskuje HP
  • Atak: Usuwa HP z innego bota
  • Tarcza: Chroni przed późniejszymi atakami
  • Ogłuszenie: Pomija następną turę innego bota
  • Farma: Zarabia złoto kosztem HP
  • Ulepszenie: popraw niektóre ruchy

Wszystkie boty zwrócą swój ruch, zanim zostaną wykonane, więc ogłuszenie, leczenie, atak, tarcza itp. Nie wpłynie na żadne roboty poruszające się później w tej turze. Na przykład, jeśli Bot A ogłusza Bot B, a Bot B podąża za Bot A w kolejności tury, Bot B będzie się poruszał później w tej samej turze, a ogłuszenie nastąpi w następnej turze.

Walka, hodowla i ulepszanie:

Każdy bot ma maksymalną HP 100 i przypisany identyfikator UID od 0 do 99. Ten identyfikator UID zmienia się po każdej rundzie i jest to sposób, w jaki boty śledzą się nawzajem.

Leczenie jest jednym z najprostszych ruchów, dodając ilość HP zależną od jego poziomu (zaczyna się od 5 HP). Bot nie może wyleczyć powyżej 100 HP.

Atakowanie bota za pomocą UID to kolejny możliwy ruch, którego podstawowe obrażenia wynoszą 5 HP na poziomie 0. Boty można również ogłuszyć, pomijając kolejną turę, która również używa UID.

Boty mają dodatkową liczbę PW tarczy, która nie ma limitu. Tarcza HP będzie absorbować obrażenia od bezpośrednich ataków innych botów i jest dodawana przez tarczę. Na poziomie 0 ekranowanie dodaje 5 punktów życia tarczy.

Farma zarobi 5 sztuk złota na poziomie 0, kosztem 2 HP. Tych 2 HP nie można osłonić. Jedynym zastosowaniem złota (oprócz wygrywania) jest ulepszanie ruchów. Leczenie, atakowanie i tarcza mają wartość podstawową 5 HP, a farma zaczyna się od 5 złota. Każdy z tych ruchów ma indywidualne poziomy, które zaczynają się od 0. Te formuły określą wartość HP lub złota ruchu, gdzie L jest poziomem:

  • Gojenie: L + 5
  • Napadający: 1.25L + 5
  • Zastawianie: 1.5L + 5
  • Rolnictwo: 2L + 5

Koszt ulepszenia dowolnego ruchu jest taki sam dla określonego poziomu i jest określony przez 2.5L² + 2.5L + 10, gdzie L jest poziomem bieżącym. Bot może użyć tej funkcji cost(currentLevel)jako skrótu, aby to ustalić.

Boty zaczynają się od 25 sztuk złota, co pozwala im szybko ulepszyć dwa ruchy na poziom 1 lub jeden ruch na poziom 2. To początkowe złoto nie liczy się do całkowitej wartości botów. Zabicie bota daje połowę jego całkowitej wartości w złocie, w zaokrągleniu w górę, a jeśli dwa boty zabijają drugiego w tej samej turze, oboje otrzymują nagrodę.

Wejście wyjście:

Aby komunikować się ze sterownikiem, zwracana wartość funkcji służy do wysyłania informacji o ruchu. Jeden z nich powinien zostać zwrócony:

  • Uzdrowić: heal()
  • Atak: attack(uid)
  • Tarcza: shield()
  • Oszołomić: stun(uid)
  • Gospodarstwo rolne: farm()
  • Aktualizacja: upgrade("heal" / "attack" / "shield" / "farm")

Aby pominąć turę (nic nie rób), nic nie zwracaj lub zwróć wartość fałszowania.

Aby uzyskać bieżący numer tury (zaczyna się od 1), użyj turn().

Argumenty twojej funkcji będą zawierać informacje o twoim bocie, UID innych botów i przechowywanie między kolejnymi. Pierwszy parametr jest obiekt o następujących właściwościach: uid, hp, goldi shield. Są to kopie bieżących informacji Twojego bota. Istnieje również zagnieżdżonego obiektu levels, z numerami szczebla heal, attack, shieldi farm.

Drugi argument jest tasuje tablicę wszystkich żywych robotom niż ty, podany jako przedmiot zawierający właściwości uid, hp(wraz z osłoną) worthi attack(poziom ataku). Trzeci argument to pusty obiekt, którego można użyć do przechowywania między kolejnymi.

Przykładowe boty:

Ten bot będzie farmował, dopóki nie może ulepszyć swojego ataku do poziomu 5, a następnie za każdym razem atakuje losowego bota, dopóki nie umrze (lub nie wygra). Niezbyt skuteczny z powodu braku leczenia / osłony.

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

Ten bot ma dwa tryby: ofensywny i defensywny. W trybie obronnym ogłusza losowego bota lub leczy, aw trybie ofensywnym atakuje lub osłania. W miarę możliwości będzie próbował ulepszyć swoje ataki.

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

Zasady:

  • Standardowe luki zabronione
  • Boty nie mogą odczytywać, modyfikować ani dodawać żadnych zmiennych poza swoim zakresem, nie mogą próbować oszukiwać i nie mogą wywoływać żadnych funkcji zdefiniowanych przez kontroler lub DOM
  • Zwracana wartość musi być fałszem lub jednym z powyższych wyjść funkcji
  • Boty nie powinny być zaprojektowane do celowania w konkretnego bota, ale mogą być zaprojektowane tak, aby wykorzystywać wspólne strategie
  • Boty nie mogą się atakować (wykryte z powodu komentarza @Ness)
  • Boty muszą się wystarczająco różnić od innych botów, aby można je było rozsądnie uznać za osobne wpisy
  • Zespolenie nie jest teraz dozwolone
  • Kontroler można znaleźć tutaj
  • Pokój rozmów

Debugowanie nowego kontrolera:

Korzystając z pliku gold-battle-log.js, możesz ustawić wartość debugwłaściwości bota botDatana 0 (bez rejestrowania), 1 (log ruchów) lub 2 (log ruchów, hp, złoto, poziomy itp.)

Wyzwanie kończy się o godzinie 17.00 UTC w piątek, 9 sierpnia

Programy Redwolf
źródło
4
Utworzono istotę ze wszystkimi botami. gist.github.com/Draco18s/2efbf95edcf98d6b1f264e26bbb669d1 Postaram się go aktualizować (ale jeśli nie, to przyzwoity początek).
Draco18s
4
Automatycznie aktualizowany kontroler z botami w zestawie: redwolfprograms.com/koth
Programy Redwolf
4
Głosuję za zamknięciem tego pytania, ponieważ jest już de facto zamknięte na nowe odpowiedzi („To wyzwanie się zakończyło. Aby zobaczyć ostateczne wyniki ...”)
pppery
3
@pppery Nie możesz? Byłbym w porządku z niekonkurencyjnymi odpowiedziami, a [closed]na końcu prawdopodobnie sprawi, że zwykli widzowie pominą czytanie mojego wyzwania, ponieważ; zakładają, że jest niskiej jakości lub nie na temat.
Programy Redwolf
5
@pppery Nigdy nie słyszałem o zamkniętym wyzwaniu za ukończenie do dzisiaj, i twierdzę, że ograniczenia społeczne, które chcesz egzekwować, nawet nie istnieją. Nie trzeba go zamykać i nie chcę go zamykać. Wydaje mi się, że to zamknięcie ze względu na zamknięcie, a nie dla dobra strony. Jeśli ktoś chce opublikować odpowiedź na stare pytanie, powinien. Po regule poważnego rywala nie ma żadnej wzmianki o tym, że musi być poważnym rywalem, gdy jest publikowana; odpowiedź może nadal stanowić poważny pretendent do wyzwania, nawet jeśli nie jest pretendentem do zwycięstwa
Redwolf Programs

Odpowiedzi:

16

Nie do zabicia

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

Biorąc pod uwagę wykładnicze koszty ulepszeń, równie dobrze możemy ulepszyć rolnictwo, jeśli nie możemy ulepszyć leczenia, umożliwiając botowi bardziej efektywne zbieranie złota.

Draco18s
źródło
Absolutnie miażdżąc konkurencję w moich testach
Programy Redwolf
1
Wydaje mi się, że ten bot może być trochę silniejszy, gdyby ifużył tego pierwszego stwierdzenia <=- obecnie nigdy się nie zagoi.
Scoots
@ Scoots Nie wiem, ile to będzie miało znaczenie, ale zmienię to.
Draco18s
2
@ Draco18s Jestem pewien, że to ma bardzo małe znaczenie - ale czy ta strona nie dotyczy praktycznie niewielkich ulepszeń? :)
Scoots
@ Scoots Leczenie do maksymalnego zdrowia nie ma większego znaczenia w tym wyzwaniu, ponieważ nie ma prawdziwych zagrożeń atakujących. Jedynym naprawdę ofensywnym botem jest bullybot i tak naprawdę nie można nic z nim zrobić. To może faktycznie obniżyć wydajność, aby zachować pełne zdrowie.
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();
            }
        }
    }
}

Jest za dużo botów, za mało złota, żeby się obejść. Ten bot proponuje rozwiązanie.

Ludobójstwo, tak, ale losowe, beznamiętne, sprawiedliwe wobec bogatych i biednych.

Nazywali go szaleńcem.

ThanosBot chce tego, co najlepsze dla społeczności botów i jest gotów przejść całą drogę. Na początku ulepszy swój atak, uprawę roli i leczenie, aby skuteczniej zbierać zasoby i wygrywać bitwy. Prograsycznie zacznie atakować ludzi losowo, wciąż zbierając zasoby, na nadchodzące bitwy. Będzie ulepszał swoją armię, swoją broń i siebie.

Gdy 50% populacji zostanie wyeliminowane, urodzone boty będą wiedziały tylko pełne brzuchy i czyste niebo, przejdą na emeryturę i będą oglądać życie wschodzące na wdzięcznym wszechświecie. Stanie się całkowicie pacyfistą, lecząc się wyłącznie zupami warzywnymi i hodowlą.

Dziecko kaito
źródło
6
Kusi mnie, by zmienić nazwę „atak” na „przyciąganie”
Redwolf Programs
11

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

Teraz nie tylko kradnie zabójstwa, ale także kradnie zabójstwa!

Ten bot nie robi wiele poza farmą, a gdy zauważy taką możliwość, dołącza do ostatecznego ciosu w umierającego wroga i jakoś udaje mu się być bardzo dobrym.

dzaima
źródło
Działa, ponieważ wszystkie boty biorące udział w zabójczym ciosie otrzymują pełną nagrodę.
Draco18s
@ Draco18s Rozumiem, dlaczego to może być dobre, po prostu nie spodziewałem się, że tak prosty pomysł, aby uzyskać średnio 2x wynik następnego najlepszego bota (w momencie jego tworzenia).
dzaima
Hehe, to sprawiedliwe. Będę musiał pobrać wszystkie boty, kiedy będę mógł, i zobaczę, czy mogę znaleźć inne rozwiązanie.
Draco18s,
9

Korektor

Ten bot stara się przywrócić spokój w społeczności botów. Nieustannie atakuje boty najwyższym atakiem, poddając się tylko wtedy, gdy uzdrowienie bota jest lepsze niż jego własny atak. Gdy nie pozostaną żadne boty o uzdrowieniu gorszym niż jego atak, przejdzie na emeryturę, prowadząc spokojne rolnictwo.

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();
}
B0RDERS
źródło
8

Optymista

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

Zakłada, że ​​będzie mógł spędzić 80% swojego czasu na spokojnym uprawianiu ziemi, więc zaczyna od maksymalizacji rolnictwa, a dopiero potem zaczyna zwracać uwagę na swoje umiejętności bojowe. Na pewno nic nie pójdzie źle!

histocrat
źródło
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();
}

Po co zwiększać wartość ataku, skoro możesz zadawać obrażenia i nadal uzyskać pełny kredyt?

Jeszcze raz wróć do piggybacking off Kill Stealer. Byłem w stanie uprościć kilka bloków kodu, w których stwierdzenia były zawsze prawdziwe i majstrowały przy niektórych liczbach, co spowodowało ogromne zyski w stosunku do oryginału.

Muszę przekazać to @dzaimie za uświadomienie sobie, że ogłuszenie bogatego przeciwnika, który prawdopodobnie będzie zaangażowany w asysty na turę przed zabiciem, jest dość sprytny. Jeden z (bardzo) kilku razy Stun()ma pozytywny wynik sumy. Po raz kolejny udało mi się ulepszyć ten pomysł, ponieważ wiedząc, że Kill Stealer będzie działał w podobny sposób, Kill Assist szuka „drugiego najlepszego” celu (z pewną dyskrecją) i ogłusza go.

Drobna aktualizacja, aby zapobiec ogłuszaniu bota o śmierci i zapobiec ogłuszaniu bota, który najprawdopodobniej zabije.

Przykładowe wyniki (okrojone 5 najlepszych po 1000 gier)

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
Draco18s
źródło
Zaraz, w jakim świecie Kapitan Farmer otrzymuje 14 000 sztuk złota?
Programy Redwolf
Ten:runGame(1) results: [...] captFarmer: 13768
Draco18s
To dość nieoczekiwanie wysoka ... w moich testach
zwykle wynosi
* śmiech * Nie mam pojęcia. Zrobię automatyczną aktualizację, aby upewnić się, że wszystko jest czyste.
Draco18s,
Mój ulubiony bot przed upływem terminu.
Noc2,
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()
            }
        }        
    }   
}

Luis Felipe De Jesus Munoz
źródło
Nie przejmuj się mną ... Pożyczę to.
Draco18s
6

PatientStrategistBot

Próbowałem napisać bota, który zaczyna kadrowanie i obronę w razie potrzeby, a następnie przełącza się na zabijanie innych botów o wysokiej wartości w dalszej części gry.

Obecnie nie wydaje się to działać poprawnie, ponieważ albo został zabity przez gang botów-morderców na początku gry, albo utknął gdzieś w trybie ofensywnym.

Nadal jestem bardzo zadowolony z tego, że to mój pierwszy kod JS, więc ... (Kradnąłem fragmenty kodu stąd i tam było to szybsze niż przeglądanie całej podstawowej składni 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();

}
Nicolai
źródło
6

Szwajcaria

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

Jak sama nazwa wskazuje, ten bot jest neutralny, w większości neutralny (teraz pomaga zabijać boty, które umrą), a jedynie farmy i leczy, powoli gromadząc złoto ( tak jak Szwajcaria )

SuperStormer
źródło
6

Bot, który hoduje, atakuje, osłania, a nawet leczy, ale nigdy nie ogłusza

(Skrócona nazwa to TBTFASAEHBNS , nie należy mylić jej z 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();
}

Ten bot w zasadzie:

  • Na początku gromadzi się w rolnictwie
  • Broni się w razie potrzeby
  • Atakuje, kiedy może zabić lub gdy myśli, że jest szansa na zabicie kogoś
  • Aktualizacje tu i wtedy
  • Przez resztę czasu uprawia ziemię
  • Nigdy nie ogłusza

Edycja 1: Naprawiono problem i poprawiono kilka drobnych rzeczy w bocie na podstawie testów z dużą ilością gier.

Edycja 2: Zmniejszone ulepszenia tarczy.

Noc 2
źródło
2
Gdy tylko zobaczyłem nazwę, wiedziałem, że to będzie twój bot (:
Redwolf Programs
Przykro mi z powodu długich nazwisk, ale jestem od tego uzależniony!
Noc2
1
Może to oznaka dobrego bota ... moje testy pokazują, że jest na 5. miejscu
Redwolf Programs
5

SniperBot

Ten bot będzie skuteczny tylko wtedy, gdy ktoś zacznie dodawać boty, które faktycznie atakują regularnie. SmartFarmer to moje obecne zoptymalizowane rozwiązanie

  1. leczy, jeśli można dostać jeden strzał
  2. leczy, jeśli poniżej 30
  3. atakuje bota, jeśli go zdoła i zarobi więcej pieniędzy niż rolnictwo
  4. ulepsza rolnictwo, jeśli może sobie na to pozwolić
  5. ulepsza leczenie, jeśli ma mniej niż 80 zdrowia i może sobie pozwolić
  6. farmy

sępy nie potrzebują ataku

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();
}
B0RDERS
źródło
Nieoczekiwany identyfikator ( int) w linii 2. ReferenceError: zdrowie nie jest zdefiniowane.
Draco18s
Powinno być me.hp?
mbomb007
Przepraszam. nowy w javascript. dzięki za pomoc
B0RDERS
Twój if(me.hp <30 && ...)może być uproszczone do zaledwie pierwszym punkcie z powodu konieczności absurdalny poziom leczyć za to do materii (lvl 65)
Veskah
@Veskah Dzięki za zwrócenie na to uwagi. Była to pozostałość z czasów, gdy min.
Hp
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 of BullyBot i kilka innych bitów. Optymista miał krótki i słodki kawałek oportunistycznego ataku, który wymyśliłem (chociaż inne boty wykonują podobne obliczenia).

Zamiast zastraszać cel ogłuszając go, morduje go za ich słodkie, słodkie łupy. Atakuje także najsłabszych w stadzie pod kątem zastraszania, ale zrezygnuje i po prostu pójdzie na rolnictwo, jeśli HP najsłabszego celu jest zbyt wysoki.

Draco18s
źródło
hodujesz się na śmierć. Zaakceptuj moją edycję :)
B0RDERS
1
@AndrewBorders Ha, nawet o tym nie myślałem. Dzięki.
Draco18s
Ten bot był świetny, dopóki nie pojawiły się te boty opiekuńcze.
B0RDERS
@ B0RDERS Tarcza jest bardzo silna, nawet jeśli marnuje czas.
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);
}

Przeważnie ofensywny bot. Niezwykle zdenerwowany faktem, że nie może tak naprawdę FizzBuzz, więc zamiast tego brzęczy ze złością. Kiedy nie jest to Fizzing ani Buzzing, odłupuje innego bota na 30 tur i poddaje się i wybiera innego bota, którego celem jest cel, jeśli nie robi postępów.

Wykonuje wyjątkowo niekonsekwentnie. Nieważne, zaktualizowałem kontroler, teraz wydaje się, że zawsze znajduje się w połowie pakietu.

Transformacja Fouriera Rina
źródło
Podoba mi się ta koncepcja. Bez względu na obecną sytuację wciąż się rozwija w swoim własnym tempie.
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);
}

Wypróbuj online!

Może nie wygra, ale na pewno dołoży wszelkich starań, aby jego cel też nie. bullyBot farmuje również w pierwszej turze, więc jeśli nie będzie żadnych zewnętrznych wpływów, pokona swój cel 5-0 lub zwiąże je 5-5.

Veskah
źródło
5

JustFarm

Myślałem, że zacznę proste.

function justFarm(me, others){
    return farm();
}
Anonimowy
źródło
13
Ten bot popełni samobójstwo z powodu kosztu uprawy 2HP.
Draco18s
@ Draco18s Chociaż runda może się wcześniej zakończyć, w zależności od liczby botów
Redwolf Programs
1
Chociaż technicznie jest to prawda, 50
minutowy
Pokonał dwa przykładowe boty, ale teraz jest jeszcze kilka zgłoszeń, które mogę spróbować wymyślić coś lepszego.
Anonimowy
@Anonimowy Może wystarczy ulepszenia leczenia i hodowli. Ponieważ zdobycie jak największej ilości złota jest ostatecznym celem, utrzymanie go, ponieważ główna praca bota może działać. Do tej pory nie było żadnych botów, które mają „tryby” takie jak tryb leczenia i tryb farmy, może być ciekawym podejściem
Programy Redwolf
4

ScavengerBot (V2)

Uświadomiłem sobie, że wcześniej nie był to śmieciarz. Nową strategią jest czekanie, aż zabije innego bota. Jeśli nikogo nie można zabić, siedzi i buduje tarczę.

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();
}
reffu
źródło
1
me.levels.attacl?
Draco18s
Dobry połów, naprawiony
reffu
4

Nastrojowy

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

Domyślną strategią Moody's jest ulepszenie rolnictwa i leczenia, a następnie wyeliminowanie innych botów w malejącej kolejności wartości. Jednak jeśli zostanie zaatakowany, przestraszy się i ponownie skoncentruje na leczeniu. Jeśli zaatakuje i „zawiedzie”, ponieważ ofiara leczyła się lub osłaniała skuteczniej niż atak, rozzłości się i pójdzie ulepszyć swoje umiejętności ataku.

histocrat
źródło
4

Bandyta

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

Pierwsza próba bota uczącego się wzmacniającego. Na razie czysto defensywny, aby zawęzić obszar poszukiwań. Coś w rodzaju mądrzejszego podziału FizzBuzz - powtarza określoną serię pięciu akcji w kółko; pięć akcji wybiera RL.

Ale na razie opiera się on głównie na wyliczaniu - właśnie wygenerowałem wszystkie 3 ^ 5 = 243 permutacje serii pięciu działań obronnych, które powtarzały się w kółko i zapisywałem ich średnie wyniki (podzielone przez 200, aby uzyskać średni zysk ponad pięć obrotów) ponad 100 iteracji w storage.priortablicy. Następnie, w trakcie gry, wprowadza epsilon-chciwe podejście do aktualizacji tych list wyników, aby było bardziej przyszłościowe. (Również dlatego, że użycie epsilon = 0.3 działało o wiele lepiej niż epsilon = 0.1, więc po prostu go zachowałem).

Jest w porządku, konsekwentnie umieszczając pomiędzy scavengerBot i Optimist. Obecnie ćwiczę trochę więcej na temat prawdziwych gier i szukam lepszych sposobów na opracowanie strategii, aby sprawdzić, czy mogę ją ulepszyć.

Transformacja Fouriera Rina
źródło
4

Opportunista

Ten pożyczył trochę od kilku innych (zwłaszcza ScavengerBot (V2) i Unkillable), ponieważ mieli te same pomysły, które miałem na myśli, ale ogólnie lubię dobrze zaokrąglone style i walory typu all-of-trade, zamiast skupiać się tylko na jedna lub dwie rzeczy. To prawdopodobnie będzie oznaczać, że nie wygram, ale powinno to być gdzieś pośrodku (co zdarza mi się przez większość czasu w wielu sprawach).

Więc kradnie soczyste zabójstwa; leczy, jeśli to konieczne; ulepsza farmę, atak i leczenie w tej kolejności; i farmy w inny sposób.

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();
    }
}
Ness
źródło
1
Drugi argument powinien brzmiećothers
SuperStormer
4

ScaredBot

  1. Znajduje inne boty:
    • z najwyższym atakiem
    • z największym bogactwem i HP niższym niż własny atak
  2. Jeśli jego HP + tarcza jest niższa niż znaleziona highest attack * (25% of bots)lub zbliża się do dolnego końca HP + shield, wtedy osłania
  3. Jeśli znalazł bota z niższą tarczą niż własny atak, atakuje go.
  4. Jeśli ma zdrowie < 50, leczy.
  5. Jeśli może ulepszyć dowolną tarczę, leczenie i farmę, ulepsza tę z najniższym poziomem
  6. To farmy
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();
    }
}

Chodzi o to, aby pozostać przy życiu jak najdłużej, a w przeciwnym razie spróbować zdobyć złoto w bezpieczny i tani sposób, aby móc ulepszyć.

Priorytety ulepszeń powinny zostać prawdopodobnie poprawione, a także warunek przy określaniu, czy należy chronić.

użytkownik24343
źródło
3

SmartFarmer

Farmy, ulepsza farmę, leczy, jeśli ma niskie zdrowie. Rolnictwo wydawało się obezwładnione, dopóki nie pojawiły się naprawdę ofensywne boty. Teraz mój bot został zabity :-(

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();
}
B0RDERS
źródło
1
(Ręcznie) testowałem zasadniczo tę samą strategię, aby zobaczyć, jaka jest maksymalna możliwa do uzyskania wartość i najlepsze liczby, jakie mogłem uzyskać, przez nieznaczne opóźnienie, kiedy leczenie jest ulepszone (użyłem złota> = koszt * 2) i przejście do leczenia na poziomie 10 .
Nicolai
Ten mnożnik cen to dobry pomysł. Dodałem coś podobnego. Byłbym zainteresowany, aby zobaczyć, jakie masz numery
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];
}

W każdej turze porównuje zamortyzowany zysk z zabicia każdego bota z zyskiem z hodowli i leczenia i wybiera najlepszą opcję. Naprawdę powinien użyć stanu, aby dowiedzieć się, ile czasu zajmie zabicie bota, ale na razie zakłada, że ​​każdy bot leczy lub osłania średnio 5 punktów za obrót bez obrażeń zadawanych przez inne boty.

histocrat
źródło
3

Przyjazny 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].hpjest hp + shieldzamiast hp...

tsh
źródło
4
Czy ktoś może mi pomóc w tłumaczeniu nazwy funkcji na angielski? ^ _ ^
tsh
4
Według Tłumacza Google „闷声 发大财” oznacza „Muffled”. Jestem pewien, że to nie jest to, czego chcesz i to w rzeczywistości kolejna epicka porażka Tłumacza Google ... Szukałem dalej i wszystkie wyniki wydają się wskazywać, że nie ma jednego angielskiego słowa, które można by tutaj użyć, więc lepiej byłoby zachować je jako jest tak naprawdę, ponieważ wydaje się być chińskim przyimkiem, co ogólnie oznacza, że ​​należy pracować w ciszy i pozwolić, aby wyniki mówiły same za siebie i osiągały tradycyjną filozofię. Niestety w ogóle nie znam chińskiego, aby tłumaczyć go bezpośrednio. : D
Erik the Outgolfer
1
jako rodzimy użytkownik języka chińskiego oznacza to coś w rodzaju „po cichu zarób wielką fortunę”: v 闷声 oznacza również celowo bycie cichym, dosłownie „zatuszowanie dźwięku”
transformacja Fouriera Rin
1
Podstępny? Pod radarem? DontMindMe? Uwaga Deflektor?
Peter Taylor
3

Księgowy

Ten praktyczny bot oblicza najbardziej korzystny ekonomicznie ruch, ale lubi utrzymywać niski profil ataku, aby uniknąć kłopotów ze strony wszystkich czujnych botów. Nie próbuje pomóc bezbronnym ani ich na nich polować. Raczej robi to, co najbardziej mu pomaga.

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();
}
B0RDERS
źródło
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();
}

To jest ta rzecz. Na zewnątrz jest naprawdę niebezpiecznie. Farming w ogóle zwiększa twoją wartość, czyniąc cię celem. Więc naprawdę nie jest bezpiecznie uprawiać ziemię, dopóki nie zbudujesz ogromnej tarczy, a cała przemoc ustanie. Następnie możesz wystawić głowę ze skorupy i rozpocząć uprawę. Lub pomoc w zabiciu. Cokolwiek się opłaca lepiej.

histocrat
źródło
2

Opiekun

Mogę mieć więcej niż jedno zgłoszenie, prawda?

Widelec CampBot. Nie osłania, zamiast tego skupia się na atakowaniu. Wykazuje preferencje dla atakujących graczy z wyższymi statystykami ataku, zamiast atakować losowo, jak CampBot. Koncentruje się na ulepszaniu rolnictwa, a nie na leczeniu.

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()
    }
}
Anonimowy
źródło
mój bot nie atakuje losowo ...
SuperStormer
Możesz publikować tyle razy, ile chcesz, im więcej, tym lepiej, jak sądzę
Redwolf Programs
@ SuperStormer Zdaję sobie sprawę, że twój nie jest całkowicie przypadkowy, ale:let victim=potentialVictims[Math.floor(Math.random()*potentialVictims.length)]
Anonimowy
ale najpierw odfiltrowuje te, które nie są warte ataku
SuperStormer
Pracowałem nad podobnym botem o nazwie korektor, kiedy to opublikowałeś. Nadal go dopracowuję, ale podoba mi się niektóre z twoich pomysłów.
B0RDERS
2

Rando

Ten głupi facet wybierze działania oparte na jednolitej losowości z pewnymi uprzedzeniami. Jeśli losowo wybrana akcja nie zadziała, spada do następnego wyboru.

Średnio więc powinien atakować prawie 2/9 czasu i farmować prawie 3/9 czasu. Reszta ma około 1/9 szansy, jeśli uda mu się ulepszyć lub jeśli warto skorzystać z leczenia / ochrony itp.

Prawdopodobnie nie osiągnie dobrych wyników, ale przynajmniej istnieje niewielka szansa, że ​​będzie panował najwyższy. I to jest cały cel Rando. Musi po prostu uwierzyć w siebie! Wszystkie opcje są przed nim. Musi tylko wybrać to, co jest potrzebne w danej sytuacji.

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

(Wiem, że „default” nie jest konieczne, ale myślę, że jest to dobra praktyka kodowania dla solidnego kodu).

Ness
źródło
2
„Musi po prostu uwierzyć w siebie” ... Tak bardzo się teraz
śmieję
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);
}

Prosty bot, Kill Bot chce po prostu zabić swoich wrogów. Ponieważ osłona jest znacznie bardziej wydajna niż leczenie (zwłaszcza gdy jest wyrównywana), Kill Bot stara się zawsze być nieatrakcyjnym celem, osłaniając się przy każdym ataku. Kill Bot radzi sobie całkiem nieźle wśród słabych, pacyfistycznych botów tutaj (możesz poczuć ich pogardę).

Mistrz Spitemaster
źródło
3
Pamiętaj, że o.attackto poziom ataku, a nie jego obrażenia
Redwolf Programs
2

FarmHeal Bot

Opracowano z bota @Anonymous „JustFarm

function farmhealBot(me, others, storage) {
  if (me.hp <= 95)
    return heal();
  else return farm();
}
na komputerze
źródło
2

niezniszczalna

Modyfikacja bota Draco18 przy użyciu tarcz (bardziej skuteczny przeciwko innym botom)

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();
        }
    }
}
Programy Redwolf
źródło