黄金之战


43

这一挑战已经结束。要查看竞争对手的最终成绩,请单击此处

在此挑战中,每个提交都是一个机器人。每个漫游器都应该是一个Javascript函数。机器人将争取获得最高的黄金总价值。可以耕种黄金,也可以通过杀死其他机器人赚取黄金,黄金可以用来提高治疗,攻击,屏蔽和耕种的能力。

目的:

在多达1000轮的回合中(仅剩一个机器人时结束),总价值最高(获得的所有金币的总和)的机器人就是赢家。

转弯:

在每个回合中,每个存活(> 0 HP)的机器人都将运行一次。它可以返回移动,可以是以下之一:

  • 治疗:恢复HP
  • 攻击:从另一个机器人移除HP
  • 盾牌:防御以后的攻击
  • 晕眩:跳过另一个机器人的下一站
  • 农场:以HP为代价赚钱
  • 升级:改善某些动作

所有漫游器都将在执行任何动作之前返回它们的移动,因此眩晕,治疗,攻击,护盾等不会影响此后稍后移动的任何漫游器。例如,如果Bot A使Bot B昏迷,并且Bot B在回合顺序中紧随Bot A,则Bot B仍将在同一回合中稍后移动,并且在下一回合发生眩晕。

战斗,耕种和升级:

每个漫游器的最大HP为100,并且分配的UID在0到99之间。此UID在每轮之后都会更改,这是漫游器相互跟踪的方式。

修复是最简单的举动之一,增加的HP量取决于其等级(从5 HP开始)。机器人无法治愈100 HP以上的生命。

通过其UID攻击机器人是另一种可能的举动,在0级时造成5 HP的基本伤害。也可以使Bot昏迷,跳过下一回合,后者也使用UID。

机器人具有额外的防护罩HP,没有限制。此防护罩HP会吸收其他僵尸程序的直接攻击造成的损害,并通过防护罩添加。在0级时,屏蔽会增加5点屏蔽HP。

养殖将在0级获得5金,花费2 HP。这2 HP无法屏蔽。黄金的唯一用途(超越获胜)是升级动作。治疗,攻击和屏蔽的基础价值为5 HP,耕种开始于5金币。这些移动中的每一个都有各自的级别,从0开始。这些公式将确定移动的HP或黄金值,其中L是级别:

  • 修复: L + 5
  • 进攻: 1.25L + 5
  • 屏蔽: 1.5L + 5
  • 农业: 2L + 5

在某个级别上,升级任何移动的成本是相同的,并且由决定2.5L² + 2.5L + 10,其中L是当前级别。机器人可以使用该功能cost(currentLevel)用作确定此事件的快捷方式。

机器人以25金开始,使他们能够快速升级到1级或两次升级到2级。这一开始的金不计入机器人的总价值。杀死一个机器人将使您获得其总价值的一半黄金,并将其四舍五入,如果两个机器人在同一回合中杀死另一个机器人,它们都将获得奖励。

输入输出:

为了与控制器通信,该函数的返回值用于发送移动信息。其中之一应返回:

  • 愈合: heal()
  • 攻击: attack(uid)
  • 屏蔽: shield()
  • 晕眩 stun(uid)
  • 农场: farm()
  • 升级: upgrade("heal" / "attack" / "shield" / "farm")

要跳过转弯(不执行任何操作),不返回任何内容或返回虚假的值。

要获取当前的转数(从1开始),请使用 turn()

函数的参数将包括有关您的机器人,其他机器人的UID以及匝间存储的信息。第一个参数是具有以下属性的对象:uidhpgold,和shield。这些是您的漫游器当前信息的副本。此外,还有一个嵌套的对象levels,具有电平数字healattackshield,和farm

第二个参数是除您之外的所有活动中的漫游器的重组数组,其格式设置为包含属性uidhp(加屏蔽)worth,和attack(攻击级别)的对象。第三个参数是一个空对象,可用于转弯间存储。

示例机器人:

该机器人将一直耕作,直到可以将其攻击升级到5级,然后每回合攻击一个随机机器人,直到死亡(或获胜)。由于缺乏愈合/屏蔽作用,效果不是很好。

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

该机器人具有两种模式:进攻和防御。处于防御模式时,它会眩晕一个随机机器人或使其恢复生命;处于防御模式时,它将被攻击或屏蔽。它将尽可能尝试升级其攻击。

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

规则:

  • 标准漏洞禁止
  • Bot可能不会读取,修改或添加超出其范围的任何变量,可能不会试图作弊,并且可能不会调用任何控制器定义的或DOM函数
  • 返回值必须是虚假的,或者上述函数输出之一
  • 机器人不应设计为针对特定机器人,而应设计为利用常见策略
  • 机器人可能不会自我攻击(由于@Ness的评论而被发现)
  • 漫游器必须与其他任何漫游器都足够不同,以使其可以合理地视为单独的条目
  • 现在不允许分组
  • 控制器可以在这里找到
  • 聊天室

新的控制器调试:

使用该文件gold-battle-log.js,您可以将debug机器人的属性值设置botData为0(不记录),1(对数移动)或2(对数移动,hp,黄金,等级等)。

挑战赛将于8月9日星期五1700 UTC结束


4
与所有机器人一起创建了要点。gist.github.com/Draco18s/2efbf95edcf98d6b1f264e26bbb669d1我将努力保持其更新(但如果不是这样的话,这是一个不错的开始)。
Draco18s

4
带有机器人的自动更新控制器包括:redwolfprograms.com/koth
Redwolf Programs

4
我投票结束这个问题,因为它实际上已经对新的答案关闭了(“这个挑战已经结束。要看最终的分数……”)
pppery

3
@pppery可以吗?我可以提供非竞争性的答案,并且[closed]最终可能会使休闲的观众跳过阅读我的挑战,因为他们认为这是低质量或偏离主题的。
Redwolf节目

5
@pppery我从来没有听说过要完成一项挑战,直到今天才结束,我认为您要实施的社会限制甚至不存在。无需关闭它,我也不想关闭它。对我而言,这似乎是为了关闭而不是为了网站的利益而关闭。如果有人想发布旧问题的答案,他们应该可以。严格的竞争者规则说它必须在发布时必须是认真的竞争者之后没有任何提示。即使不是赢家的竞争者,答案仍然可能是挑战的真正竞争者
Redwolf Programs

Answers:


16

不可杀的

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

考虑到升级的成倍成本,如果我们无法升级治疗效果,则最好升级养殖场,从而使机器人能够更有效地收集黄金。


在我的测试中绝对压制竞争
Redwolf Programs

1
我觉得如果if使用第一个语句,该机器人可能会更强大<=-目前,它将永远无法恢复。
酷航

@Scoots不确定这有多重要,但我会更改它。
Draco18s

2
@ Draco18s我敢肯定,它的作用很小-但是这个网站不是所有关于微小改进的微不足道的内容吗?:)
酷航

@Scoots在此挑战中恢复健康状况并不重要,因为没有真正的攻击威胁。唯一真正令人反感的机器人是Bullybot,您无法真正对他做任何事情。它可能实际上会降低性能以保持完全健康。
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();
            }
        }
    }
}

有太多的机器人,没有足够的黄金。该机器人提出了一个解决方案。

种族灭绝,是的,但随机,冷漠,对富人和穷人都公平。

他们称他为疯子。

ThanosBot希望机器人社区拥有最好的,并愿意一路走下去。首先,他将提升自己的进攻,耕种和治疗能力,以更有效地收集资源并赢得战斗。令人高兴的是,他将开始随机攻击人们,同时仍在收集资源,准备进行战斗。他将继续改善自己的军队,武器和自己。

一旦消灭了50%的人口,出生的机器人将只知道饱腹和晴朗的天空,他将退休以耕种为生,并在感恩的宇宙上观看太阳升起。他将成为完全的和平主义者,只会通过蔬菜汤和耕种来治愈自己。


6
我很想将“攻击”重命名为“快照”
Redwolf Programs

11

杀死偷窃者

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

现在,不仅可以窃取杀人,而且也可以窃取杀人!

这个机器人除了农场之外没有做太多事情,当它发现这种可能性时,就对垂死的敌人进行最后一击,并且在某种程度上设法变得很好。


之所以行之有效,是因为参与致命一击的所有机器人均会获得全部奖励。
Draco18s

@ Draco18s我理解为什么它会很好,我只是没想到这么简单的想法会平均获得次优机器人的2倍(在制造时)。
dzaima

呵呵,很公平。我将在可能的情况下必须下载所有漫游器,并查看是否可以找到其他解决方案。
Draco18s

9

均衡器

该机器人旨在恢复机器人社区的和平。他无情地以攻击力最高的机器人为目标,只有在机器人的康复能力优于自己的攻击时才放弃。一旦没有比攻击更严重的机器人了,他将退休,过上和平的农业生活。

function equalizer(me, others, storage){
  if(storage.agroKilled == null)storage.agroKilled = false;
  if(!storage.agroKilled){
    if(storage.blacklist == null)storage.blacklist = [];
    if(storage.lastAttack == null)storage.lastAttack = -1;
    var maxAtk = 0;
    var maxAtkUid = -1;
    var maxAtkHealth = 0;
    for(var i = 0; i < others.length; i++)if(others[i].uid == storage.lastAttack){
      maxAtk = others[i].attack*1.25+5;
      maxAtkUid = storage.lastAttack;
      maxAtkHealth = others[i].hp;
    }
    for(var i = 0; i < others.length; i++){
      if(storage.lastAttack == others[i].uid && others[i].hp >= storage.lastHealth){
        maxAtk = 0;
        maxAtkUid = -1;
        maxAtkHealth = 0;
        storage.blacklist.push(others[i].uid);
      }
    }
    storage.lastAttack = -1;
    var willHeal;
    for(var i = 0; i < others.length; i++)if(others[i].attack*1.25+5 > maxAtk){
      willHeal = false
      for(var j = 0; j < storage.blacklist.length; j++)if(others[i].uid==storage.blacklist[j])willHeal = true;
      if(!willHeal){
        maxAtk = others[i].attack*1.25+5;
        maxAtkUid = others[i].uid;
        maxAtkHealth = others[i].hp;
      }
    }
    if(me.hp < maxAtk) return heal();
    if(me.hp <= 100 - me.levels.heal - 5) return heal();
    var target = -1;
    var targetWorth = me.levels.farm * 2 + 5;
    for(var i = 0; i < others.length; i++) {
      if (others[i].hp <= maxAtk && others[i].worth / 2 > targetWorth) {
        target= others[i].uid;
          targetWorth = others[i].worth / 2;
      }
    }
    if(target!=-1) return attack(target);
    if(me.gold >= cost(me.levels.attack)) return upgrade("attack");
    if(me.levels.heal + 7 < me.levels.attack && me.levels.heal < 9 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
    if(maxAtkUid!=-1){
      storage.lastAttack = maxAtkUid;
      storage.lastHealth = maxAtkHealth;
      return attack(maxAtkUid);
    }
    storage.agroKilled = true;
  }
  if(me.hp < 30) return heal();
  if(me.gold > cost(me.levels.farm)) return upgrade("farm");
  return farm();
}

8

乐天派

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

假定它将能够花费80%的时间和平地耕种,因此首先要最大限度地耕种,然后才开始对其战斗技能给予任何关注。当然,不会有任何问题!


8

杀人辅助

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

当您可以造成伤害并仍然获得全额信用时,为什么要提升攻击价值呢?

再一次背负Kill Stealer。我能够简化几个代码块,其中的语句始终是真实的,并且摆弄一些数字,从而使结果比原始代码大得多。

我必须把它交给@dzaima,以意识到在杀人发生之前击杀一个有可能参与转牌助攻的富裕对手非常聪明。(非常)几次Stun()都具有正和结果。我再一次改进了这个想法,因为知道Kill Stealer将运行类似的逻辑,所以Kill Assist会(出于某种判断)寻找“次优”目标,并将其击晕。

进行较小的更新,以防止使即将死去的机器人震惊,并防止使最有可能使机器人丧命的机器人。

示例结果(在1000场比赛后排名前5位被截断)

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

等等,在什么世界上,农夫船长获得14k金?
Redwolf Programs

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

这真是出乎意料的高...在我的测试中,通常可以达到1万左右
Redwolf Programs

*耸肩*不知道。我将进行自动要点更新,以确保一切都干净。
Draco18s

在截止日期结束前我最喜欢的机器人。
2

7

顽强的机器人(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()
            }
        }        
    }   
}


别介意 ...我要借用这个。
Draco18s

6

病人策略专家

我试图编写一个机器人,该机器人可以根据需要开始进行构架和防御,然后在游戏后期切换到杀死其他高价值机器人。

目前,这种方法似乎无法正常运行,因为它要么在游戏开始时就被一伙谋杀机器人杀死,要么被卡在进攻模式中。

仍然很高兴这是我的第一个JS代码,所以...(我确实从这里和那里窃取了代码片段,因为这比谷歌搜索所有JS基本语法要快)

function PatientStratgistBot(me, others, storage) {

    //set up some stuff in first turn
    if (turn() == 1) {
    storage.selfWorth = 0;
    storage.attackMode = false;
    storage.expectHP = 100;
    storage.expectShield = 0;
    storage.shieldTarget = 0;
    storage.targetUid = "None";
    storage.attackRounds = 0;
    storage.targetStartHP = 100;

        return upgrade("farm");
    }

    let farmPower = me.levels.farm * 2 + 5;

    //defensive Actions

    var maxAtk = Math.max(...others.map(o => o.attack));

    storage.shieldTarget = Math.ceil(maxAtk * 1.25 / 1.5) + 1;

    if (me.levels.shield < storage.shieldTarget && me.gold >= cost(me.levels.shield) && me.levels.shield < me.levels.farm)
        return upgrade("shield");

    if (turn() >= 7 && me.shield < 10 && me.levels.shield * 1.5 >= me.levels.heal) return shield();

    if (turn() >= 15 && me.shield < 15 && me.levels.shield * 1.5 >= me.levels.heal) return shield();

    if (turn() >= 30 && me.shield < 20 && me.levels.shield * 1.5 >= me.levels.heal) return shield();

    //attack mode
    // check if there any targets worth to go for

    function findTarget(potentialTargets, baseR){
    var targetUID = "None";
    var best = 0;
    for( var i = 0; i < potentialTargets.length; i++) {
        //We upgrade to attack lvl12, so 20 dmg; assume an enemy can heal/shield up to 15 per round
        var killRounds = Math.ceil(potentialTargets[i].hp / 5)
        var gain = potentialTargets[i].worth / ( 2 * ( killRounds + baseR) )
        //console.log(me, turn(), potentialTargets[i], killRounds, baseR, gain, farmPower)
        if (gain > farmPower * ( killRounds + baseR ) && gain > best)
            targetUID = potentialTargets[i].uid;
            storage.targetStartHP =  potentialTargets[i].hp;
    }
    return targetUID;
    }


    if (turn() >= 600) {


    //check if a current target is dead
    const uids = others.map(x=>x.uid);
        if(storage.targetUid != "None" && !uids.includes(storage.targetUid)) {
        storage.targetUid = "None";
        storage.attackMode = false;
        storage.attackRounds = 0;
    }


    // check if we are doing enough damage to current target
    if (storage.targetUid != "None" && storage.attackRounds >= 3) {

        var deltaHP = storage.targetStartHP - others[storage.targetUid].hp

        if (deltaHP / storage.attackRounds < 5) {
            storage.targetUid = "None";
            storage.attackMode = false;
            storage.attackRounds = 0;

        }

    }

    var investCost = 0
    for( var i = me.levels.attack; i < 12; i++) investCost += cost(i);

    if (storage.attackMode == true && me.gold >= investCost && me.levels.attack < 12) return upgrade("attack");

    if (storage.attackMode == false) {
        baseRounds = investCost / farmPower * 1.2; //overestimation with the heal level we should have at this point

        if (findTarget(others, baseRounds) != "None")
            storage.attackMode = true;

        var betterThanMe = others.filter(o => o.worth >= storage.selfWorth);

        if (betterThanMe.length > 0)
            storage.attackMode = true;

        //storage.attackMode = true;


    }

    }

    if (storage.attackMode == true && me.levels.attack == 12) {

    if (storage.targetUid == "None") {

        var target = findTarget(others, 0)
        storage.targetUid = target;
        storage.attackRounds = 0;
        return attack(target);

    }

    return attack(storage.targetUid)

    }



    //otherwise farm

    if (me.hp < 50) {
    storage.expectHP += 5 + me.levels.heal;
        return heal();
    }

    if (me.gold >= cost(me.levels.farm) && storage.attackMode == false)
        return upgrade("farm");

    //upgrade heal, so we can farm more, but increase farm ability faster
    if (me.levels.farm > 5 && me.levels.heal < 10 && me.gold >= 2*cost(me.levels.heal))
        return upgrade("heal");


   //be opportunistic - check if killing someone is more profitable than farming
    killable = others.filter(o => o.hp < me.levels.attack * 1.25 + 5 && o.worth / 2 > farmPower);
    if (killable.length > 0){
    //ideally check for the most worth target here
        return attack(killable[0].uid);
    }

    storage.expectHP -= 2;
    storage.selfWorth += farmPower;
    return farm();

}

6

瑞士

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

顾名思义,该机器人是中立的,大多是中立的(现在它可以杀死即将死亡的机器人),而农场却可以治愈,慢慢地积累其黄金(就像瑞士一样


6

能够耕种,攻击,盾牌甚至治愈但绝不会晕眩的机器人

(简称为TBTFASAEHBNS,不要误解为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();
}

该机器人基本上是:

  • 一开始就以耕作为基础
  • 在需要时捍卫自己
  • 当它可以杀死某人或认为有机会杀死某人时发动攻击
  • 在此升级,然后
  • 其余时间耕种
  • 永不眩晕

编辑1:根据对许多游戏的测试,解决了一个问题并改进了机器人中的一些小问题。

编辑2:减少盾牌升级。


2
一看到名字,我就知道它将是您的机器人(:
Redwolf Programs

我对长名感到抱歉,但是我沉迷于此!
2

1
也许这是一个很好的机器人的迹象......我的测试表明它在第5位
Redwolf计划

5

狙击手

仅当有人开始添加定期进行攻击的自动程序时,该自动程序才有效。SmartFarmer是我当前优化的解决方案

  1. 如果能can愈就愈
  2. 30岁以下即可愈
  3. 攻击机器人,如果能摘下它并赚取比耕种更多的钱
  4. 负担得起的话就升级农业
  5. 如果您的健康状况低于80岁,并且可以负担得起,则可以提高治疗效果
  6. 农场

秃鹰不需要攻击

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

int第2行出现意外的标识符()。ReferenceError:运行状况未定义。
Draco18s

应该是me.hp
mbomb007

抱歉。JavaScript新手。感谢您的帮助
B0RDERS

由于您if(me.hp <30 && ...)需要对它进行荒谬的治疗,因此您可以简化为第一条款(lvl 65)
Veskah

@Veskah感谢您指出这一点。那是从最小hp较高时开始的残余
B0RDERS

5

恶霸推土机

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

BullyBot和其他一些位的混搭。我对Optimist的攻击机会短而甜蜜(尽管其他bot进行了类似的计算)。

它没有通过使目标昏迷来欺负目标,而是以甜美甜蜜的战利品谋杀了他们。它还将目标最弱的人群作为欺凌对象,但如果最弱的目标的HP太高,它将放弃并开始耕种。


你正在耕种自己直到死亡。接受我的编辑:)
B0RDERS

1
@AndrewBorders哈,甚至都没想过。谢谢。
Draco18s

在这些保护程序机器人出现之前,该机器人非常棒。
B0RDERS

@ B0RDERS盾非常坚固,即使它浪费时间。
Draco18s

5

嘶嘶声

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

主要是攻击性机器人。由于它无法真正实现FizzBu​​zz,因此非常生气,因此只能生气地嗡嗡作响。当它不是嘶嘶声或嗡嗡声时,它会在另一个机器人上削掉30圈,然后放弃并选择另一个机器人作为目标,如果它没有取得进展。

执行异常不一致。没关系,更新了控制器,现在似乎总是在包的中间。


我喜欢这个概念。无论当前情况如何,它都在按自己的步调前进。
尼斯

5

恶霸

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

在线尝试!

可能不会赢,但一定会尽他最大的努力来确保他的目标也不会。BullyBot也在第一回合进行耕种,因此,如果没有外界影响,他将以5-0击败目标或将他们5-5并列。


5

正义农场

我以为我会从简单开始。

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

13
由于2HP的耕作成本,该机器人将自杀。
Draco18s

@ Draco18s尽管回合可能在此之前结束,但具体取决于机器人的数量
Redwolf Programs

1
虽然技术上真实的,50轮计时器是非常非常短的时候默认的结束时间为1000
Draco18s

它击败了两个示例机器人,但是现在我可能会尝试提交一些更好的东西。
匿名

@Anonymous也许包括治疗和耕种升级就足够了。因为获得最大的金钱是最终目标,所以将其作为机器人的主要工作是可行的。到目前为止,还没有任何机器人具有“治愈”模式和“农场”模式等“模式”,这可能是一种有趣的方法
Redwolf Programs

4

ScavengerBot(V2)

意识到以前并没有太多的清道夫。新策略是等到可以杀死另一个机器人。如果没有人可以被杀死,它会坐下来并建立盾牌。

function scavengerBot(me, others) {
    if (me.shield < (me.levels.shield * 1.5 + 5)) {
        return shield();
    }
    var currentAttack = 1.25 * me.levels.attack + 5;
    var hasVictim = false;
    var victimUid = 0;
    var maxWorth = 0;
    for (var i = 0; i < others.length; i++) {
        var hp = others[i].hp;
        var worth = others[i].worth;
        if (hp <= currentAttack && worth > maxWorth) {
            hasVictim = true;
            victimUid = others[i].uid;
            maxWorth = worth;
        }
    }

    if (hasVictim) {
        return attack(victimUid);
    }

    if (me.gold >= cost(me.levels.attack)) {
        return upgrade("attack");
    }

    if (me.gold >= cost(me.levels.shield)) {
        return upgrade("shield");
    }
    return shield();
}

1
me.levels.attacl
Draco18s

固定好捕获
reffu

4

穆迪

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

穆迪(Moody)的默认策略是升级耕种和恢复一段时间,然后按价值降序淘汰其他机器人。但是,如果受到攻击,它将感到恐惧并重新专注于治疗。如果它攻击并“失败”,因为受害者比攻击更有效地进行了治愈或屏蔽,它将生气并离开以提高其攻击能力。


4

土匪

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

第一次尝试强化学习机器人。现在纯粹是为了缩小搜索范围。FizzBu​​zz的一种更聪明的衍生产品-反复重复一系列特定的五个动作;这五个动作是RL选择的。

但这目前主要基于枚举-我刚刚生成了五个防御动作系列的所有3 ^ 5 = 243个排列,这些动作一遍又一遍地重复,并存储了它们的平均得分(除以200,得出的平均得分超过五圈)在storage.prior数组中进行100次迭代。然后,在游戏过程中,它实现了epsilon-greedy方法来更新这些得分列表,因此更具前瞻性。(另外,因为使用epsilon = 0.3的效果要好于epsilon = 0.1,所以我保留了它。)

没关系,始终放置在scavengerBot和Optimist之间。我目前正在对真实游戏进行更多培训,并寻找更好的方法来制定该策略,以查看是否可以改进它。


4

机会主义者

这是从其他一些人那里借来的(特别是ScavengerBot(V2)和Unkillable),因为他们的想法与我相同,但我通常更喜欢全面和万能的风格,而不是只关注于一两件事。这很可能意味着我不会赢,但是应该在某个地方的中间(这在很多情况下通常发生在我身上)。

因此,它可以偷走多汁的杀戮;必要时als愈;按此顺序升级农场,攻击和治疗;和农场,否则。

function Opportunist(me, others, storage) {

    // Initializing and keeping track of selfWorth
    if (turn() == 1) {
        storage.selfWorth = 0;
    }
    else if (storage.previousGold < me.gold) {
        storage.selfWorth += (me.gold - storage.previousGold);
    }
    storage.previousGold = me.gold;

    // Me stats
    var me_attack = 1.25 * me.levels.attack + 5;
    var me_heal = me.levels.heal + 5;

    // Look for the juiciest hunk of loot
    // If there are multiple of the highest worth, the last is chosen
    var choice = others[0].uid;
    var mostWorthy = -1;
    for (var i = 0; i < others.length; i++) {
        worth = others[i].worth
        if (others[i].hp <= me_attack && worth >= mostWorthy) {
            choice = others[i].uid;
            mostWorthy = worth;
        }
    }

    // Actions in order of priority
    // The juicy targets must be worth the action
    if (mostWorthy > (storage.selfWorth * 0.25) ) {
        return attack(choice);
    }
    else if (me.hp <= 100 - me_heal) {
        return heal()
    }
    else if (me.gold >= cost(me.levels.farm)) {
        return upgrade("farm");
    }
    else if (me.gold >= cost(me.levels.attack)) {
        return upgrade("attack");
    }
    else if (me.gold >= cost(me.levels.heal)) {
        return upgrade("heal");
    }
    else {
        return farm();
    }
}

1
第二个参数应该是others
SuperStormer

4

ScaredBot

  1. 它会发现其他机器人:
    • 攻击力最高
    • 拥有最多的财富和生命值低于自身攻击力
  2. 如果它的HP +盾牌低于找到的值highest attack * (25% of bots),或者它接近的下端HP + shield,则它盾牌
  3. 如果发现具有比自己的攻击更低的防护的机器人,就会对其进行攻击。
  4. 如果健康< 50,它将he愈。
  5. 如果可以升级任何盾牌,治疗和农场,则会升级最低等级的盾牌
  6. 农场
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();
    }
}

这个想法是要尽可能长寿,否则尝试以安全,便宜的方式获得黄金以进行升级。

升级优先级以及确定是否屏蔽的条件可能应该进行调整。


3

聪明的农民

农场,改善农业状况,如果健康状况不佳,可以自愈。在真正令人反感的机器人到来之前,耕种似乎无能为力。现在我的机器人被杀死了:-(

function smartFarmer(me, others){
    if(me.hp < 13) return heal();
    for(var i = 0; i < others.length; i++)if(others[i].attack * 1.25 + 5 > me.hp)return heal();
    if(me.gold >= cost(me.levels.farm)) return upgrade("farm");
    if(me.levels.heal < 9 && me.levels.farm > me.levels.heal + 7 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
    return farm();
}

1
我(手动)测试了基本相同的策略,以查看获得的最大价值和获得的最佳数字是通过稍微延迟治疗升级时的时间(我使用黄金> =成本* 2)并提高至lvl10治疗。
Nicolai

这个价格乘数是一个好主意。我添加了类似的内容。我想知道您得到了什么数字
B0RDERS

3

莫特

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

每回合,将杀死每个机器人的摊销收益与耕种和修复的收益进行比较,并选择最佳选择。确实,它应该使用状态来确定杀死一个机器人将花费多长时间,但是现在它只是假设每个机器人平均每回合能治愈或屏蔽其他机器人造成的伤害5点。


3

友好的机器人

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].hphp + shield代替hp...


4
有人可以帮我将函数名称翻译成英文吗?^ _ ^
tsh

4
根据Google翻译的说法,“闷声发大财”的意思是“闷闷不乐”。可以肯定的是,这不是您想要的,实际上是又一次Google Translate史诗失败了……我进行了进一步搜索,所有结果似乎都提到这里没有可使用的单个英语单词,因此最好将其保留为实际上,这似乎是一个汉语介词,通常意味着一个人应该默默工作,让结果自己说话,并达到传统的哲学。不幸的是,我根本不懂中文直接翻译它。:D
暴民埃里克

1
作为母语为中文的人,它的意思是“默默地发大财”:v闷声也暗示着有意安静,从字面上“掩盖了声音”
in的傅立叶变换法

1
鬼??低调神秘?DontMindMe?注意偏转器?
彼得·泰勒

3

会计师

这个实用的bot计算出最经济的举动,但他喜欢保持较低的攻击水平,以避免所有警惕的bot遇到麻烦。他不会试图为无防御能力的人提供帮助,也不会为他们提供猎物。相反,他会尽最大努力。

function accountant(me, others, storage) {
    if (turn() == 1) {
        storage.lastHP = me.hp + me.shield;
        storage.hisAttack = 5;
        storage.timesAttacked = 0;
        storage.lastAttack = -1;
        storage.healths = [], storage.uids = [], storage.heals = [];
        for (var i = 0; i < others.length; i++) {
            storage.healths.push(others[i].hp);
            storage.uids.push(others[i].uid);
            storage.heals.push(5);
        }
    }
    storage.timesAttacked++;
    if (storage.lastHP == me.hp + me.shield) storage.timesAttacked = 0;
    else storage.hisAttack = storage.lastHP - me.hp - me.shield;
    storage.lastHP = me.hp + me.shield;
    var attacks = [];
    for (var i = 0; i < others.length; i++) if (others[i].uid != me.uid) attacks[i] = 1.25 * others[i].attack + 5;
    attacks.sort();
    for (var i = 0; i < others.length; i++) {
        storageIndex = storage.uids.indexOf(others[i].uid);
        if (storage.heals[storageIndex] < others[i].hp - storage.healths[storageIndex] + (others[i].uid == storage.lastAttack ? 1.25 * me.levels.attack + 5 : 0)) others[i].hp - storage.healths[storageIndex] + (others[i].uid == storage.lastAttack ? 1.25 * me.levels.attack + 5 : 0);
    }
    var maxProfitTurn = 2 * me.levels.farm + 5, victimID = -1, tempProfit;
    for (var i = 0; i < others.length; i++) {
        storageIndex = storage.uids.indexOf(others[i].uid);
        tempProfit = others[i].worth / 2 * (1.25 * me.levels.attack + 5 - storage.heals[storageIndex]) / others[i].hp;
        if (tempProfit > maxProfitTurn) {
            victimID = others[i].uid;
            maxProfitTurn = tempProfit;
        }
    }
    maxUrgentProfit = 0;
    for (var i = 0; i < others.length; i++) if (maxUrgentProfit < others[i].worth / 2 && others[i].hp <= attacks.slice(0, 4).reduce((a, b) => a + b) + 1.25 * me.levels.attack + 5) {
        maxUrgentProfit = others[i].worth / 2;
        victimID = others[i].uid;
    }
    if (maxUrgentProfit > 0) {
        storage.lastAttack = victimID;
        return attack(victimID);
    }
    storage.lastAttack = -1;
    if (storage.timesAttacked == 0) {
        if (me.levels.shield < 20 && me.gold >= cost(me.levels.shield)) return upgrade("shield");
        if (me.levels.heal < 5 && me.levels.shield >= me.levels.heal + 5 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
        if (Math.random() < Math.pow((me.hp + me.shield) / 100, -2)) {
            storage.lastHP += 1.5 * me.levels.shield + 5;
            return shield();
        }
    }
    else {
        if (Math.random() < .5 || me.hp + me.shield - storage.hisAttack - attacks[0] <= 10) {
            storage.lastHP += 1.5 * me.levels.shield + 5;
            return shield();
        }
        if (me.levels.shield < 20 && me.gold >= cost(me.levels.shield)) return upgrade("shield");
        if (me.hp <= 2) {
            storage.lastHP += me.levels.shield + 5;
            return heal();
        }
        storage.lastHP -= 2;
        return farm();
    }
    if (me.gold >= cost(me.levels.farm)) return upgrade("farm");
    storage.lastAttack = victimID;
    if (victimID != -1) return attack(victimID);
    if (me.hp <= 2) {
        storage.lastHP += me.levels.shield + 5;
        return heal();
    }
    storage.lastHP -= 2;
    return farm();
}

3

真正的龟

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

就是这个 那里真的很危险。耕种可以增加您的价值,使您成为目标。因此,在您建立起巨大的防护罩并且所有暴力行为都消失之前,种地真的不安全。然后,您可以将头戳开,然后开始耕种。或杀人辅助。付得起的东西。


2

监护人

我可以提交多个提交,对不对?

CampBot的叉子。不屏蔽,而是专注于攻击。显示偏好攻击性更高的玩家,而不是像CampBot那样随机攻击。专注于升级其农业而不是治愈。

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

我的机器人没有随机攻击...
SuperStormer

您可以根据需要发布任意多次,我想的越多越好
Redwolf Programs

@SuperStormer我意识到您的并不完全是随机的,而是:let victim=potentialVictims[Math.floor(Math.random()*potentialVictims.length)]
匿名

但它首先过滤掉了不值得攻击的内容
SuperStormer

当您发布此消息时,我正在开发一个名为均衡器的类似机器人。我仍然在进行微调,但我喜欢您的一些想法。
B0RDERS

2

兰多

这个愚蠢的家伙会根据均匀的随机性和一些偏见来选择动作。如果随机选择的操作不起作用,则将其下拉至下一个选择。

因此,平均而言,他应该有近2/9的进攻时间和有3/9的出场时间。如果他能够升级,或者如果值得治疗/屏蔽,则剩下的几率约为1/9。

他的表现可能不太好,但是至少他极有可能成为最高统治者。这就是Rando的全部目的。他只需要相信自己!所有的选择都摆在他的面前。他只需要选择任何给定情况所需的内容即可。

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

(我知道“默认”是不必要的,但我认为对于健壮的代码而言,这是一种很好的编码做法。)


2
“他只需要相信自己” ...我现在正在笑很多
Redwolf Programs

2

杀死机器人

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

一个简单的机器人Kill Bot只是想杀死它的敌人。由于防护远比治疗有效(尤其是在被夷为平地时),因此杀戮机器人只要在受到攻击时就通过防护自身总是试图成为一个无吸引力的目标。Kill Bot在附近的弱势和平主义者中表现不错(您可以为他们感到轻蔑)。


3
请注意,这o.attack是攻击级别,而不是其伤害
Redwolf Programs

2

农场愈合机器人

由@Anonymous'JustFarm bot分叉

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

2

坚不可摧

使用盾牌对Draco18机器人的修改(对其他机器人更有效)

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();
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.