Bataille d'or KoTH

44

Ce défi est terminé. Pour voir les résultats finaux des concurrents, cliquez ici

Dans ce défi, chaque soumission correspond à un bot. Chaque bot devrait être une fonction Javascript. Les bots vont se battre pour obtenir la plus haute valeur totale en or. L’or peut être cultivé ou gagné en tuant d’autres bots et est utilisé pour améliorer la guérison, les attaques, le blindage et l’agriculture.

Objectif:

Sur un nombre de tours contenant jusqu'à 1000 tours (se termine lorsqu'il ne reste qu'un seul bot), c'est le bot qui a la valeur totale la plus élevée (la somme de tout l'or obtenu) est le gagnant.

Se tourne:

A chaque tour, chaque bot en vie (> 0 HP) sera exécuté une fois. Il peut retourner un mouvement, qui peut être l'un des suivants:

  • Heal: Regagne HP
  • Attaque: supprime HP d'un autre bot
  • Bouclier: se défend contre les attaques ultérieures
  • Stun: Saute le prochain tour d'un autre bot
  • Ferme: Gagne de l'or au prix de HP
  • Mise à niveau: améliorer certains mouvements

Tous les robots renverront leur mouvement avant que tous ne soient exécutés. Par conséquent, un étourdissement, des soins, une attaque, un bouclier, etc., n'affecteront pas les robots se déplaçant plus tard dans ce tour. Par exemple, si le bot A étouffe le bot B, et que le bot B est après le bot A dans l'ordre du tour, le bot B continuera à se déplacer plus tard dans le même tour et l'étourdissement se produira au tour suivant.

Combat, agriculture et valorisation:

Chaque bot a un maximum de 100 HP et un UID attribué compris entre 0 et 99. Cet UID change après chaque tour et constitue le moyen utilisé par les bots pour se suivre.

La guérison est l'un des mouvements les plus simples, en ajoutant une quantité de HP déterminée par son niveau (à partir de 5 HP). Un bot ne peut pas guérir après 100 CV.

Attaquer un bot par son UID est un autre mouvement possible, avec des dégâts de base de 5 PV au niveau 0. Les bots peuvent également être assommés en sautant leur prochain tour, qui utilise également des UID.

Les robots ont un bouclier supplémentaire HP, qui n'a pas de limite. Ce bouclier HP absorbe les dégâts des attaques directes d’autres bots et s’ajoute au blindage. Au niveau 0, le blindage ajoute 5 boucliers HP.

L'agriculture gagnera 5 or au niveau 0, au prix de 2 HP. Ce 2 HP ne peut pas être blindé. La seule utilisation de l'or (au-delà de la victoire) est d'améliorer les mouvements. Les soins, les attaques et les blindages ont une valeur de base de 5 PV et l'agriculture commence à 5 or. Chacun de ces mouvements a des niveaux individuels, qui commencent à 0. Ces formules détermineront la valeur en HP ou en or d'un mouvement, où L est le niveau:

  • Guérison: L + 5
  • Attaquant: 1.25L + 5
  • Blindage: 1.5L + 5
  • Agriculture: 2L + 5

Le coût de la mise à niveau d'un déplacement est le même pour un certain niveau et est déterminé par 2.5L² + 2.5L + 10, où L est le niveau actuel. Un bot peut utiliser cette fonction cost(currentLevel)comme raccourci pour le déterminer.

Les bots commencent avec 25 pièces d'or, ce qui leur permet d'améliorer rapidement soit deux mouvements au niveau 1, soit un mouvement au niveau 2. Cet or de départ ne compte pas dans la valeur totale des bots. Tuer un bot vous donne la moitié de sa valeur totale en or, arrondi, et si deux bots en tuent un au même tour, ils reçoivent tous les deux la récompense.

Entrée sortie:

Pour communiquer avec le contrôleur, la valeur de retour de la fonction est utilisée pour envoyer des informations de déplacement. L'un d'eux doit être retourné:

  • Guérir: heal()
  • Attaque: attack(uid)
  • Bouclier: shield()
  • Étourdir: stun(uid)
  • Ferme: farm()
  • Améliorer: upgrade("heal" / "attack" / "shield" / "farm")

Pour sauter un tour (ne rien faire), ne rien retourner ou une valeur de fausseté.

Pour obtenir le numéro de tour actuel (commence à 1), utilisez turn().

Les arguments de votre fonction incluront des informations sur votre bot, les UID d'autres bots et le stockage entre les tours. Le premier argument est un objet avec les propriétés suivantes: uid, hp, gold, et shield. Ce sont des copies des informations actuelles de votre bot. Il y a aussi un objet imbriqué levels, avec les numéros de niveau de heal, attack, shieldet farm.

Le deuxième argument est un tableau mélangé de tous les robots vivants autres que le vôtre, formatés en tant qu'objet contenant des propriétés uid, hp(plus un bouclier) worth, et attack(niveau d'attaque). Le troisième argument est un objet vide qui peut être utilisé pour le stockage entre les tours.

Exemple de robots:

Ce bot agraiera jusqu'à ce qu'il puisse augmenter son attaque au niveau 5, puis attaquera un bot aléatoire à chaque tour jusqu'à ce qu'il meure (ou gagne). Pas très efficace en raison du manque de guérison / blindage.

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

Ce bot a deux modes: offensif et défensif. Il assommera un bot aléatoire ou guérira en mode défensif et il attaquera ou se protégera en mode offensif. Il tentera d'améliorer ses attaques chaque fois que possible.

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

Règles:

  • Les échappatoires standard sont interdites
  • Les robots ne peuvent pas lire, modifier ou ajouter de variables en dehors de leur portée, ne peuvent pas tenter de tricher et ne peuvent appeler aucune fonction définie par le contrôleur ou DOM
  • La valeur de retour doit être falsy ou l'une des sorties de fonction ci-dessus
  • Les bots ne doivent pas être conçus pour cibler un bot spécifique, mais peuvent tirer parti des stratégies communes
  • Les robots ne peuvent pas s'attaquer eux-mêmes (découverte suite à un commentaire de @Ness)
  • Les robots doivent être suffisamment différents des autres robots pour pouvoir être considérés comme des entrées séparées.
  • Faire équipe est maintenant interdit
  • Le contrôleur peut être trouvé ici
  • Tchat

Nouveau débogage de contrôleur:

À l'aide du fichier gold-battle-log.js, vous pouvez définir la valeur de la debugpropriété d'un bot botDatasur 0 (pas de journalisation), 1 (journal se déplace) ou 2 (journal se déplace, hp, or, niveaux, etc.).

Le défi se termine à 17h00 UTC le vendredi 9 août

Programmes Redwolf
la source
4
Créé un noyau avec tous les robots. gist.github.com/Draco18s/2efbf95edcf98d6b1f264e26bbb669d1 Je vais essayer de le tenir à jour (mais si ce n'est pas un bon début).
Draco18s
4
Mise à
Programmes Redwolf
4
Je vote pour clore cette question car elle est déjà de facto fermée à de nouvelles réponses ("Ce défi est terminé. Pour voir les scores finaux ...")
pppery le
3
@ppery Ne pourrais-tu pas? Je serais bien avec des réponses non compétitives, et [closed]à la fin, il est probable que les téléspectateurs occasionnels passeront au-dessus de ma lecture du défi car ils supposeraient que cela est de faible qualité ou hors sujet.
Programmes Redwolf
5
@ppery Je n'ai jamais entendu parler d'un défi fermé pour être terminé jusqu'à aujourd'hui, et je dirais que la restriction sociale que vous souhaitez appliquer n'existe même pas. Il n'est pas nécessaire de le fermer et je ne veux pas le fermer. Pour moi, cela semble fermer pour des raisons de fermeture plutôt que pour le bien du site. Si quelqu'un veut poster une réponse à une vieille question, il devrait pouvoir le faire. Il n'y a aucune note après la règle de concurrent sérieux disant qu'il doit être un concurrent sérieux quand il est posté; une réponse peut toujours être un sérieux prétendant au défi même si ce n'est pas un prétendant à la victoire
Redwolf Programs

Réponses:

16

Incassable

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

Etant donné les coûts exponentiels des mises à niveau, nous pouvons également mettre à niveau l'agriculture si nous ne pouvons pas améliorer la guérison, ce qui permettra au bot de collecter l'or plus efficacement.

Draco18s
la source
Absolument écrasant la concurrence dans mes tests
Programmes Redwolf
1
Je pense que ce bot pourrait être un peu plus fort si cette première ifdéclaration avait été utilisée <=- actuellement, il ne guérira jamais complètement.
Scoots
@Scoots Je ne sais pas à quel point cela va compter, mais je vais changer cela.
Draco18s
2
@ Draco18s Je suis sûr que cela compte très peu, mais ce site ne traite-t-il pas de petites améliorations insignifiantes? :)
Scoots
@Scoots Améliorer au maximum la santé n'a pas beaucoup d'importance dans ce défi car il n'y a pas de réelle menace d'attaque. Le seul bot réellement offensant est bullybot, et vous ne pouvez rien y faire. Cela pourrait en fait diminuer les performances si vous voulez rester en pleine santé.
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();
            }
        }
    }
}

Il y a trop de robots, pas assez d'or pour faire le tour. Ce bot propose une solution.

Génocide, oui, mais aléatoire, impartial, équitable pour les riches comme pour les pauvres.

Ils l'ont appelé un fou.

ThanosBot veut le meilleur pour la communauté de robots et est prêt à aller jusqu'au bout. Au début, il améliorera son attaque, son agriculture et sa guérison, afin de collecter plus efficacement des ressources et de gagner des batailles. Progressivement, il commencera à attaquer des gens au hasard tout en rassemblant des ressources pour les batailles à venir. Il continuera à améliorer son armée, ses armes et lui-même.

Une fois que 50% de la population aura été éliminée, les bots nés ne connaîtront plus que le ventre et le ciel dégagés, il se retirera dans une vie agricole et verra le soleil se lever sur un univers reconnaissant. Il deviendra complètement pacifiste, ne guérissant que par les soupes de légumes et l'agriculture.

Kaito Kid
la source
6
Je suis tenté de renommer "attack" en "snap"
Redwolf Programmes
11

Tuer le voleur

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

Maintenant, non seulement vole tue, mais vole vole tue aussi!

Ce bot ne fait pas grand chose à part Farm, et quand il s'en aperçoit, s'associe pour porter le coup de grâce à un ennemi mourant et parvient à être très bon.

dzaima
la source
Cela fonctionne parce que tous les robots impliqués dans un coup fatal reçoivent la pleine récompense.
Draco18s
@ Draco18s Je comprends pourquoi cela pourrait être bon, je ne m'attendais pas à une idée aussi simple d'obtenir en moyenne 2 fois le score du meilleur meilleur bot (au moment de le créer).
dzaima
Hehe, c'est juste. Je vais devoir télécharger tous les robots quand je peux et voir si je peux trouver une autre solution.
Draco18s
9

L'égaliseur

Ce bot cherche à rétablir la paix dans la communauté de bot. Il cible sans relâche les robots avec la plus haute attaque, n'abandonnant que si la guérison du bot est meilleure que sa propre attaque. Une fois qu'il ne restera plus que des robots avec un potentiel de guérison pire que son attaque, il se retirera dans une vie d'agriculture pacifique.

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();
}
COMMANDES
la source
8

Optimiste

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

Supposons qu’il sera en mesure de passer 80% de son temps à cultiver de manière pacifique. C’est pourquoi il commence tout d'abord par maximiser son activité, puis commence à prêter une attention particulière à ses aptitudes au combat. Sûrement rien ne va mal tourner!

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

Pourquoi augmenter la valeur d'attaque quand vous pouvez faire des dégâts de plink tout en obtenant tout le crédit?

Une fois de plus, retrouvez Tiger Stealer. J'ai été en mesure de simplifier plusieurs blocs de code où les déclarations étaient toujours vraies et faussées avec des nombres qui ont entraîné des gains énormes par rapport à l'original.

Je dois le donner à @dzaima pour lui avoir rendu compte qu'il était assez malin d'assommer un riche adversaire susceptible d'être impliqué dans une passe décisive. L'une des (très) rares fois Stun()donne un résultat positif. Une fois encore, j'ai pu améliorer l'idée, sachant que Kill Stealer fonctionnerait selon une logique similaire, Kill Assist recherche une "deuxième meilleure" cible (avec une certaine discrétion) et l'étourdit à la place.

Mise à jour mineure pour empêcher l'étourdissement du bot sur le point de mourir et l'empêchement de l'étourdissement du bot le plus susceptible de le faire tuer.

Exemples de résultats (top 5 tronqués après 1000 matchs)

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
la source
Attendez, dans quel monde Captain Farmer obtient-il 14k gold?
Programmes Redwolf
Celui-ci:runGame(1) results: [...] captFarmer: 13768
Draco18s
C'est assez inopinément élevé… il passe généralement autour de 10k dans mes tests
Programmes Redwolf
* shrugh * Aucune idée. Je vais faire une mise à jour automatique de base pour s'assurer que tout est propre.
Draco18s
Mon bot préféré avant la fin du délai.
Night2
7

Undyable Bot (v3)

function undyableBot(me, others, storage){    

    if(me.hp < 100 - (me.levels.heal + 5)*2){
        return heal()
    }else{
        if(me.levels.heal < 10 && cost(me.levels.heal) / 2 < cost(me.levels.farm)){
            if(me.gold >= cost(me.levels.heal)){
                return upgrade("heal")
            }else{
                return farm()
            }
        }else{
            if(me.gold >= cost(me.levels.farm)){
                return upgrade("farm")
            }else{
                return farm()
            }
        }        
    }   
}

Luis Felipe De Jesus Munoz
la source
Ne fais pas attention à moi ... je vais emprunter ça.
Draco18s
6

PatientStratègeBot

J'ai essayé d'écrire un robot qui commence par définir et défendre en fonction de ses besoins, puis de passer à la mort d'autres robots de grande valeur plus tard dans le jeu.

Actuellement, cela ne semble pas fonctionner correctement, car il a été tué par une bande de robots meurtriers au début du jeu ou est bloqué quelque part dans son mode offensif.

Je suis toujours content que ce soit mon premier code JS, alors ... (j'ai volé des extraits de code ici et là, car c'était plus rapide que de chercher dans la syntaxe de base 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();

}
Nicolaï
la source
6

Suisse

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

Comme son nom l'indique, ce bot est neutre pour la plupart (il aide maintenant à tuer les bots qui vont mourir) et se contente de fermes et de soins, accumulant lentement son or ( comme en Suisse )

SuperStormer
la source
6

Le bot qui ferme, attaque, protège et même soigne mais ne s'étouffe jamais

(Nom abrégé: TBTFASAEHBNS , à ne pas confondre avec 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();
}

Ce bot essentiellement:

  • S'appuie sur l'agriculture au début
  • Se défend en cas de besoin
  • Attaque lorsqu'il peut tuer ou lorsqu'il pense qu'il y a une chance de tuer quelqu'un
  • Mises à niveau ici et ensuite
  • Fermes le reste du temps
  • Ne jamais étourdir

Éditer 1: Correction d'un problème et amélioration de petites choses dans le bot basées sur des tests avec beaucoup de jeux.

Edit 2: Mises à jour réduites du bouclier.

Nuit2
la source
2
Dès que j'ai vu le nom, j'ai su qu'il s'agirait de votre bot (:
Programmes Redwolf
Je suis désolé pour les noms longs, mais je suis accro à ça!
Night2
1
Peut-être que c'est un signe d'un bon bot ... mes tests montrent qu'il est à la 5ème place
Programmes Redwolf
5

SniperBot

Ce bot ne sera efficace que si quelqu'un commence à ajouter des robots qui attaquent régulièrement. SmartFarmer est ma solution optimisée actuelle

  1. guérit si peut être one-shot
  2. guérit si moins de 30 ans
  3. attaque bot si peut enlever et gagner plus d'argent que l'agriculture
  4. modernise l'agriculture si peut se permettre
  5. améliore la guérison si elle a moins de 80 ans de santé et peut se permettre
  6. fermes

les vautours n'ont pas besoin d'attaque

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();
}
COMMANDES
la source
Identifiant inattendu ( int) sur la ligne 2. ReferenceError: l'intégrité n'est pas définie.
Draco18s
Devrait être me.hp?
mbomb007
Désolé. nouveau sur javascript. merci pour l'aide
B0RDERS
Vous if(me.hp <30 && ...)pourriez être simplifié à la première clause en raison du besoin d’un niveau de guérison absurde pour qu’elle compte (Niv. 65)
Veskah
@Veskah Merci de l'avoir signalé. C'était un reste de quand le hp min était plus élevé
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 of BullyBot et quelques autres bits. Optimist avait un petit morceau d’attaque opportuniste que j'ai remarqué (bien que d’autres bots fassent des calculs similaires).

Au lieu d’intimider la cible en l’étourdissant, il les assassine pour leur butin sucré. Il cible également les plus faibles de la harde contre le harcèlement, mais il abandonnera et ira simplement à l'agriculture si le nombre de PV de la cible la plus faible est trop élevé.

Draco18s
la source
vous vous cultivez jusqu'à la mort. Accepter mon édition :)
B0RDERS
1
@ AndrewBorders Ha, n'y a même pas pensé. Merci.
Draco18s
Ce bot était génial jusqu'à ce que ces robots protecteurs se manifestent.
B0RDERS
@ B0RDERS Shield est très fort, même s'il fait perdre du temps.
Draco18s
5

FizzBuzz

function FizzBuzz(me, others, storage) {
    if (!storage.target) storage.target = others[0].uid;
    const uids = others.map(x=>x.uid);
    if(!uids.includes(storage.target) || (turn() % 30 === 0 
        && others[uids.indexOf(storage.target)].hp>30))
        storage.target = others[0].uid;

    if (cost(me.levels.farm) < me.gold) return upgrade("farm");
    if (turn() % 15 === 0) return heal();
    if (turn() % 3 === 0) return farm();
    if (turn() % 5 === 0) return heal();

    if (cost(me.levels.attack) < me.gold) return upgrade("attack");
    return attack(storage.target);
}

Bot principalement offensant. Extrêmement contrarié par le fait qu’il ne peut pas vraiment fonctionner par FizzBuzz, il bourdonne alors avec colère. Quand ce n'est pas Fizzing ou Buzzing, il écrase un autre bot pendant 30 tours, puis abandonne et choisit un autre bot à cibler s'il ne progresse pas.

Effectue extraordinairement incohérent. Qu'à cela ne tienne, met à jour le contrôleur, semble maintenant se situer toujours au milieu du paquet.

Transformée de Fourier de Rin
la source
J'aime ce concept. Indépendamment de la situation actuelle, il continue à avancer à son rythme.
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);
}

Essayez-le en ligne!

Peut ne pas gagner, mais tentera certainement ses damndest pour s'assurer que sa cible ne soit pas non plus. bullyBot exploite également le premier tour, de sorte que s'il n'y a pas d'influence extérieure, il battra son objectif 5-0 ou égalerait 5-5.

Veska
la source
5

JustFarm

Je pensais que je commencerais simple.

function justFarm(me, others){
    return farm();
}
Anonyme
la source
13
Ce bot va se suicider à cause du coût de l'agriculture de 2 CV.
Draco18s
@ Draco18s Bien que la ronde puisse se terminer avant cela, en fonction du nombre de bots
Programmes Redwolf
1
Bien que techniquement vrai, un chronomètre 50 tours est très très court lorsque l'heure de fin par défaut est 1000.
Draco18s
Il bat les deux exemples de robots, mais maintenant il y a quelques autres soumissions, je pourrais essayer de proposer quelque chose de mieux.
Anonyme
@Anonymous Peut-être y compris la guérison et les améliorations agricoles suffiront. L'objectif ultime étant d'obtenir le plus d'or possible, le garder comme travail principal du bot pourrait fonctionner. Il n’ya pas eu jusqu’à présent de robots qui aient des "modes" comme le mode guérison et le mode ferme, cela pourrait être une approche intéressante
Programmes Redwolf
4

ScavengerBot (V2)

J'ai réalisé que ce n'était pas vraiment un charognard avant. La nouvelle stratégie consiste à attendre jusqu'à ce qu'il puisse tuer un autre bot. Si personne ne peut être tué, il s'assied et construit un bouclier.

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
la source
1
me.levels.attacl?
Draco18s
Bonne prise, fixe
reffu
4

de mauvaise humeur

function Moody(me, others, storage) {
    health = me.hp + me.shield;
    damage = storage.previous_health - health;
    storage.previous_health = health;
    if( damage > 2 ) {
        storage.fear = 2;
    }
    if( storage.fear ) {
        storage.fear -= 1;
        if( me.gold >= cost(me.levels.heal) )
            return upgrade("heal");
        return heal();
    }
    if ( me.hp <= 50 ) {
        return heal();
    }
    if (cost(me.levels.farm) < 0.15 * (1000 - turn())) {
        if( me.gold >= cost(me.levels.farm) )
            return upgrade("farm");
        if( me.gold >= cost(me.levels.heal) )
            return upgrade("heal");
        return farm();
    }
    rich_bots = others.sort( (x,y) => y.worth - x.worth );
    richest_enemy = rich_bots[0];
    if (richest_enemy.hp >= storage.target_hp) {
        storage.anger = true;
    }
    storage.target_hp = NaN;
    if (storage.anger) {
        if( me.gold >= cost(me.levels.attack) ) {
            storage.anger = 0;
            return upgrade("attack");
        }
        return farm();
    }
    storage.target_hp = richest_enemy.hp;   
    return attack(richest_enemy.uid);   
}

La stratégie par défaut de Moody's est de moderniser l'agriculture et la guérison pendant un certain temps, puis d'éliminer les autres robots par ordre décroissant de valeur. Cependant, si c'est attaqué, il va avoir peur et se recentrer sur la guérison pour un peu. S'il attaque et "échoue", parce que la victime guérit ou se protège plus efficacement que l'attaque, elle se mettra en colère et partira pour améliorer ses capacités d'attaque.

histocrate
la source
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;
}

Première tentative d'un bot d'apprentissage du renforcement. Pour l’instant, purement défensif pour limiter l’espace de recherche. Une sorte de spin-off plus intelligent de FizzBuzz - il répète une série spécifique de cinq actions à plusieurs reprises; les cinq actions sont ce que choisit RL.

Pour l’instant, elle est principalement basée sur le dénombrement - je viens de générer les 3 ^ 5 = 243 permutations de séries de cinq actions défensives qui se répètent encore et encore, et stocke leurs scores moyens (divisés par 200, pour obtenir le gain moyen cinq tours) sur 100 itérations dans le storage.priortableau. Ensuite, pendant le jeu, il met en œuvre une approche epsilon-gourmande pour mettre à jour ces listes de partitions afin d’être plus à l’avenir. (Et aussi parce que l'utilisation d'epsilon = 0.3 a été bien meilleure que d'epsilon = 0.1, je l'ai donc conservée.)

Ça va, en plaçant systématiquement entre scavengerBot et Optimist. Je suis actuellement en train de m'entraîner davantage sur de vrais jeux et de rechercher de meilleurs moyens de cadrer la stratégie pour voir si je peux l'améliorer.

Transformée de Fourier de Rin
la source
4

L'opportuniste

Celui-ci emprunte un peu à quelques autres (notamment ScavengerBot (V2) et Unkillable) car ils avaient les mêmes idées que moi, mais j'aime généralement les styles bien arrondis et touche-à-tout que de me concentrer uniquement sur une ou deux choses. Cela signifiera probablement que je ne gagnerai pas, mais cela devrait se situer quelque part au milieu (ce qui m’arrive le plus souvent dans beaucoup de choses).

Donc, il vole des tueries juteuses; guérit si nécessaire; améliore la ferme, attaque et soigne dans cet ordre; et les fermes autrement.

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
la source
1
2ème argument devrait êtreothers
SuperStormer
4

ScaredBot

  1. Il trouve d'autres robots:
    • avec la plus haute attaque
    • avec la plupart des richesses et HP inférieure à sa propre attaque
  2. Si son bouclier HP + est inférieur à celui trouvé highest attack * (25% of bots), ou s’approche de la limite inférieure de HP + shield, alors il protège
  3. S'il trouve un bot avec un bouclier inférieur à sa propre attaque, il l'attaque.
  4. Si sa santé est < 50, il guérit.
  5. S'il peut améliorer un des boucliers, des soins et une ferme, il met à niveau celui avec le niveau le plus bas
  6. Il ferme
function ScaredBot(me, others) {
    const my_attack = me.levels.attack * 1.25 + 5;
    const my_defense = me.hp + me.shield;

    var max_attack_val = 0;
    var min_hp_worth = 0;
    var min_hp_id = null;
    var hp_under_me = 0;
    for (var i=0; i<others.length; i++){
        if (others[i].hp < my_attack && others[i].worth > min_hp_worth){
            min_hp_id = others[i].uid;
            min_hp_worth = others[i].worth;
        }
        if (others[i].attack*1.25+5 > max_attack_val){
            max_attack_val = others[i].attack*1.25+5;
        }
        if (others[i].hp < my_defense && others[i].hp > 0){
            hp_under_me++;
        }
    }
    if (max_attack_val*0.25*others.length > my_defense || hp_under_me < 0.25*others.length){
        return shield();
    }
    else if (min_hp_id != null){
        return attack(min_hp_id);
    }
    else if (me.hp < 50){
        return heal();
    }
    else {
        var min_lvl = NaN;
        var min_name = null;
        const vals = [me.levels.heal, me.levels.shield, me.levels.farm];
        const names = ["heal", "shield", "farm"];
        for (var i=0; i<vals.length; i++){
            if (!(min_lvl < vals[i])){
                min_lvl = vals[i];
                min_name = names[i];
            }
        }
        if (me.gold > cost(min_lvl)){
            return upgrade(min_name);
        }
        return farm();
    }
}

L'idée est de rester en vie le plus longtemps possible et sinon, tentez d'obtenir de l'or de manière sûre et peu coûteuse pour pouvoir vous mettre à niveau.

Les priorités de mise à niveau devraient probablement être modifiées, ainsi que la condition pour déterminer s'il faut protéger.

utilisateur24343
la source
3

SmartFarmer

Les fermes, améliore l'agriculture, guérit si la santé est faible. L'agriculture semblait maîtrisée jusqu'à l'arrivée des robots réellement offensifs. Maintenant mon bot est tué :-(

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();
}
COMMANDES
la source
1
J'essayais (manuellement) essentiellement la même stratégie pour voir quelle était la valeur maximale possible et les meilleurs chiffres que je pouvais obtenir, consistaient à retarder légèrement la guérison (j'ai utilisé or> = coût * 2) et à atteindre le niveau de soin 10. .
Nicolai
Ce multiplicateur de prix est une bonne idée. J'ai ajouté quelque chose de similaire. Je serais intéressé de voir quels chiffres vous avez obtenus
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];
}

Chaque tour, compare le bénéfice amorti de la destruction de chaque bot à celui de l'agriculture et de la guérison et choisit la meilleure option. Vraiment, il devrait utiliser l’état pour déterminer le temps qu’il faudra pour tuer un bot, mais pour l’instant, il suppose simplement que chaque bot guérit ou protège avec une moyenne de 5 points par tour, net des dégâts que les autres robots font.

histocrate
la source
3

Bot sympathique

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].hpest hp + shieldau lieu de hp...

tsh
la source
4
Quelqu'un peut-il m'aider à traduire le nom de la fonction en anglais? ^ _ ^
tsh
4
Selon Google Translate, "发大财" signifie "étouffé". C’est sûr que ce n’est pas ce que vous voulez et qu’il s’agit en fait d’un autre échec de Google Translate ... J'ai cherché plus loin et tous les résultats semblent indiquer qu’il n’ya pas un mot anglais qui puisse être utilisé ici, il serait donc peut-être préférable de le conserver En fait, comme cela semble être une préposition chinoise, cela signifie généralement que l'on doit travailler en silence et laisser les résultats parler d'eux-mêmes et aboutir à une philosophie traditionnelle. Malheureusement, je ne connais pas du tout le chinois pour le traduire directement. : D
Erik the Outgolfer
1
en tant que langue maternelle chinoise, cela signifie "faire une grande fortune en silence": v 闷声 signifie aussi être volontairement silencieux, littéralement "couvrir le son"
Rin's Fourier transformer
1
Sournois? Sous le radar? DontMindMe? AttentionDéflecteur?
Peter Taylor
3

Le comptable

Ce bot pratique calcule le coup le plus avantageux sur le plan économique, mais il aime garder son profil d'attaque faible pour éviter les ennuis de la part de tous les robots vigilants. Il n'essaye pas d'aider les sans défense ni de s'en prendre à eux. Il fait plutôt ce qui l’aide le plus.

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();
}
COMMANDES
la source
3

vraimentCommittedTurtle

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

Voici la chose. C'est devenu vraiment dangereux là-bas. L'agriculture augmente votre valeur et fait de vous une cible. Il n’est donc vraiment pas prudent de cultiver tant que vous n’avez pas construit un immense bouclier et que la violence n’est plus en place. Ensuite, vous pouvez sortir la tête de votre coquille et commencer à cultiver. Ou tuer-aider. Tout ce qui paie mieux.

histocrate
la source
2

Gardien

Je peux avoir plus d'une soumission, non?

Une fourchette de CampBot. Ne protège pas, se concentre plutôt sur l'attaque. Montre une préférence pour attaquer les joueurs avec des statistiques d'attaque plus élevées, plutôt que de frapper au hasard, comme CampBot. Met l'accent sur la modernisation de l'agriculture plutôt que sur la guérison.

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()
    }
}
Anonyme
la source
Mon bot ne
m'attaque
Vous pouvez poster autant de fois que vous le souhaitez, plus vous êtes fous
Des programmes Redwolf
@SuperStormer Je réalise que le vôtre n'est pas entièrement aléatoire, mais:let victim=potentialVictims[Math.floor(Math.random()*potentialVictims.length)]
Anonyme
mais il filtre d’abord ceux qui ne valent pas la peine d’être attaqués
SuperStormer
Je travaillais sur un bot similaire nommé l'égaliseur lorsque vous avez posté ceci. Je suis encore en train de la peaufiner, mais j'aime certaines de vos idées.
B0RDERS
2

Rando

Ce gars stupide va choisir des actions basées sur un caractère aléatoire uniforme avec quelques préjugés. Si une action choisie au hasard ne fonctionne pas, elle passe au choix suivant.

Donc, en moyenne, il devrait attaquer presque 2/9 du temps et cultiver près de 3/9 du temps. Les autres ont environ 1/9 de chance s’il est capable de s’améliorer, ou si la guérison / protection en vaut la peine, etc.

Il ne sera probablement pas performant, mais au moins, il y a une petite chance qu'il règne en maître. Et c'est tout le but de Rando. Il a juste besoin de croire en lui! Toutes les options sont devant lui. Il lui suffit de choisir ce qui est nécessaire pour une situation donnée.

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

(Je sais que "default" n'est pas nécessaire, mais je pense que c'est une bonne pratique de codage pour un code robuste.)

Ness
la source
2
"Il a juste besoin de croire en lui-même" ... Je ris tellement maintenant
Programmes Redwolf
2

Tuer Bot

function killBot(me, others, storage) {
    // If I lost health since my last check, shield.
    if (me.hp < storage.hp){
        storage.hp = me.hp;
        return shield();
    }

    storage.hp = me.hp;

    health = Math.min(...others.map(o => o.hp));
    // If I have the least health or can be one-shot, shield.
    if (others.some(o => o.attack * 1.25 + 5 >= me.hp + me.shield) || (health > me.hp + me.shield && health < 500)) return shield();

    // If I can kill someone, kill them!
    targets = others.filter(o => o.hp < me.attack);
    if (targets.length > 0){
        wealth = Math.max(...targets.map(o => o.worth));
        targets = targets.filter(o => o.worth == wealth);
        target = targets[Math.floor(Math.random()*targets.length)];
        return attack(targets[0].uid);
    }

    // If I have the money, upgrade shielding or attack
    if (me.levels.shield <= me.levels.attack){
        if (cost(me.levels.shield) < me.gold) return upgrade("shield");
    } else {
        if (cost(me.levels.attack) < me.gold) return upgrade("attack");
    }

    // Otherwise, attack the weakest!
    targets = others.filter(o => o.hp == health);
    // And if there's a tie, attack the wealthiest.
    wealth = Math.max(...targets.map(o => o.worth));
    targets = targets.filter(o => o.worth == wealth);
    target = targets[Math.floor(Math.random()*targets.length)];
    return attack(targets[0].uid);
}

Un bot simple, Kill Bot veut juste tuer ses ennemis. Puisque le bouclier est beaucoup plus efficace que la guérison (surtout lorsqu'il est nivelé), Kill Bot essaie juste de toujours être une cible peu attrayante en se protégeant chaque fois qu'il est attaqué. Kill Bot fait assez bien parmi les bots pacifistes faibles ici (vous pouvez sentir son mépris pour eux).

Spitemaster
la source
3
Notez que o.attackc'est le niveau d'attaque, pas ses dégâts
Programmes Redwolf
2

FarmHeal Bot

Source du bot JustFarm de @Anonymous

function farmhealBot(me, others, storage) {
  if (me.hp <= 95)
    return heal();
  else return farm();
}
ordinateur de poche
la source
2

Indestructible

Une modification du bot de Draco18, utilisant des boucliers (plus efficace contre les autres robots)

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();
        }
    }
}
Programmes Redwolf
la source