四人对峙


54

四人对峙

描述

您已经以某种方式陷入四重僵局。手中装有枪支,手榴弹挂在皮带上。

目标是在对峙结束时拥有最大的健康。当最多一个人的健康状况良好时,对峙已经结束。

每个玩家都有5健康,并且在其健康值下降到/低于时死亡0。玩家死亡的回合是该玩家可以承受的最后回合。

如果在对峙结束时有一名现场玩家,则该玩家获胜。否则,负面健康程度最低的玩家获胜。

动作

  • 射击:对某人射击。

    • 2 射击活着的敌人会造成伤害
    • 0 射击死敌会造成伤害
    • health_at_start_of_turn+2射击自己会造成伤害。(请注意,这会使您处于最-2健康状态。)
    • 如果一个敌人在射击自己的同一回合向您射击,您将以-4的生命值结束对峙(您在杀死自己的回合中仍然受到其他玩家的伤害)。
    • 您在接下来的回合中的操作将被忽略(并假设为Nothing)。
  • 躲闪:尝试躲避单个对手的投篮。

  • 准备:解开您的手榴弹,并准备扔它。

    • 在被炸毁之前,您只有三回合将其扔掉(6对自己3造成伤害,对所有活着的敌人造成伤害)
    • 用未投掷的手榴弹杀死就等于不投掷手榴弹三圈。
  • 投掷:将手榴弹扔向某人,并希望获得最好的结果。

    • 8如果目标还活着,则会受到伤害
    • 其他每个人(包括您自己)都可能受到3伤害
  • 什么都没有无所事事地转弯,看着每个人都死了。

输入项

您的程序将获得以下信息:

  • 每个球员的健康
  • 自对峙开始以来该玩家采取的行动的清单以下是每个玩家传递的信息的格式:

    [Health],[Action 1],[Action 2],[Action 3],...
    

动作将以“ 输出”部分中指定的格式给出。

您将收到4个这样的字符串,它们之间用空格隔开,并作为单个参数传递。这些字符串的顺序为:

[Player Info] [Opponent 1 Info] [Opponent 2 Info] [Opponent 3 Info]

字符串作为第二个参数传递。第一个参数包含一个整数,该整数唯一地标识正在执行的对峙。保证同一组玩家之间的僵持不会同时发生。但是,同时发生多个对峙。

例如:

$./Player.bash 5 "3,S2,N 5,P,N 3,S0,N -2,S3,N"

当前,玩家和第二个对手的生命值为3,第一个对手的生命值为5,第三个对手的生命值为-2并且已经死亡。

在第一回合:

  • 玩家1击中敌人2
  • 敌人1准备了手榴弹
  • 敌人2投手
  • 敌人3开枪自杀

在第二个回合中:

  • 所有球员什么都没做。(玩家和敌人2不能做任何事情,因为他们在前一回合射击。敌人3已死:他将Nothing在剩下的对峙中继续努力。)

僵局开始时的第二个参数是:5 5 5 5

输出量

应该以下面列出的格式输出命令。无效的输出被解释为“无”。要求目标的命令后应跟一个整数(0-30代表玩家,并1-3代表敌人1-3)。

  • S[target]:拍摄[目标]。
  • D[target]:尝试躲闪[目标]。
  • P:准备一枚手榴弹。
  • T[target]:向[目标]投掷手榴弹。
  • N: 没做什么。

需要目标的命令,但是在目标之间03不是目标之间或完全没有目标的命令将假定为目标0(玩家)。

计分

在每个对峙结束时,玩家将获得一个由以下公式计算得出的分数:

35 + health at end of standoff 

如果玩家的对局健康受到不利影响,他们获得低于35分的分数。以下几点也可以作为奖励:

  • 最健康:+4点
  • 第二健康:+2分
  • 第三健康:+1点。

如果是平局,则给予较低的奖励(如果两个人的健康状况最高,则两个人都被授予+2;如果三个人的健康状况最高,则被授予+1,如果每个人均等,则+0)。

通过计算所有单个分数的平均值来确定最终分数。

规则/细节

  • 转弯内的事件顺序如下:
    • 所有玩家都在行动。
    • 生命值等于或小于0的玩家死亡。
    • 需要爆炸的未投掷手榴弹将爆炸(刚刚死亡的玩家仍然受到伤害,因为这仍然是他们死亡的转折点)。
  • 条目之间没有协作。
  • 每组4名玩家之间将发生三场对峙。(玩家的顺序可能会因每次僵持而有所不同)。
  • 占用过多磁盘空间内存的条目将被取消资格。
  • 读取或修改除条目以外的文件将使您的条目失去资格。
  • 50th如果转弯结束时对峙尚未结束,则由醉汉驾驶的卡车将在转弯后驶过所有在场球员50th
    • 这辆卡车会对所有在场玩家造成20点伤害。
  • 僵局很快发生。1秒后程序将被切断。
  • 即使您已经去世,您的程序也会被调用。
  • 您只能在目录中读取或写入文件(如果您的条目名为JohnDoe,则可以将文件保存在目录player / JohnDoe /中);但是,当您的脚本运行时,这将不是当前目录。
  • 僵局将在运行Arch Linux的计算机上进行(发布2014.08.01)。

该控制器在GitHub可用

请在您的帖子中包括以下内容:

  • 机器人的名字
  • 运行bot java Doe.java输入(例如)的shell命令将作为单个参数(java Doe.java 5 "-2,S0 -2,S1 -2,S2 5,N")通过命令行传递
  • 您的机器人代码
  • Bot应该如何编译(如果适用)
  • 语言(以及适用的版本,尤其是python)

*控制器占用的时间太长,无法容纳六个。

计分板

                      Observer 43.280570409982
                   MuhammadAli 43.134861217214
                         Osama 43.031983702572
                    LateBoomer 42.560275019099
                 SimpleShooter 42.412885154062
             LessSimpleShooter 42.3772
                           Neo 42.3738
                        Scared 42.3678
                     Richochet 42.3263
                   Equivocator 42.2833
  TwentyFourthsAndAHalfCentury 42.2640
                        Darwin 42.1584
                       HanSolo 42.1025
                        Coward 42.0458
           ManipulativeBastard 41.8948
                        Sadist 41.7232
                     Aggressor 41.7058
                 CourageTheDog 41.5629
                     Grenadier 40.9889
                     Bomberman 40.8840
                         Spock 40.8713
                        Sniper 40.6346
                 DONTNUKEMEBRO 39.8151
               PriorityTargets 39.6126
                     Hippolyta 39.2480
                     EmoCowboy 39.2069
                      Zaenille 39.1971
                 AntiGrenadier 39.1919
      PoliticallyCorrectGunman 39.1689
                 InputAnalyzer 39.1517
                      Rule0Bot 39.1000
                     BiasedOne 39.0664
                      Pacifist 39.0481
               StraightShooter 39.0292
                         Ninja 38.7801
                           MAD 38.2543
                        Monkey 37.7089
                   Label1Goto1 36.2131
Generated: 2014/08/22 03:56:13.470264860 UTC

日志:在GitHub上


1
您只有一枚手榴弹,还是很多?一次可以准备多个手榴弹吗?
isaacg 2014年

2
@Bob很确定EmoWolf已添加到不再有趣的“标准漏洞”中。尽管自杀条目实际上可能并不那么可怕。
es1024 2014年

3
给大家的教训:不要酒后驾车。
Mark Gabriel

8
@ es1024如果自杀实际上是一种可行的策略,则应真正允许使用EmoWolf类型的提交。特别是当可用动作明确包括自杀!现在不是“漏洞”,不是吗?这并不是真正的不公平优势,其中大多数漏洞确实存在。但那只是我的个人意见。
鲍勃

3
基于几次运行控制器,这似乎很嘈杂。如果比赛结束,则您可能应该增加跑步次数以使其平息一些。
戴维斯·吉田

Answers:


7

观察者

这个家伙分析了他的敌人。目标是生存直到只剩下一个“积极的”对手,然后在史诗般的对峙中杀死那个对手。

编译:javac Observer.java运行:java Observer arg0 arg1

import java.util.List;
import java.util.ArrayList;
import java.util.Random;

class Observer {
    private static List<Integer> aggressiveEnemies = new ArrayList<>();
    private static List<Integer> enemyGrenadiers = new ArrayList<>();
    private static List<Integer> aliveEnemies = new ArrayList<>();

    public static void main(String[] args) {
        if (args[1].length() <= 7) { //first round
            Random rand = new Random();
            printResult("D" + (rand.nextInt(3) + 1));
        }
        String players[] = args[1].split(" ");

        if (truckIsOnWay(players[0])) {
            printResult("P");
        }       

        calcEnemyInfo(players);

        // end this standoff now
        if (truckWillHit(players[0])) {
            if (isGrenadier(players[0]))
                printResult("T" + aliveEnemies.get(0));
            else
                printResult("S0");
        }

        // shoot enemy who is not aggressive
        if (aggressiveEnemies.size() == 0) {
            printResult("S" + aliveEnemies.get(0));
        }

        // only one enemy to handle
        if (aggressiveEnemies.size() == 1) {
            String player = players[aggressiveEnemies.get(0)];
            if (isGrenadier(player)) {
                printResult("S" + aggressiveEnemies.get(0));
            } else if (shotLastTurn(player, aggressiveEnemies.get(0))) {
                //safe to shoot him without receiving damage
                printResult("S" + aggressiveEnemies.get(0));
            } else {
                printResult("D" + aggressiveEnemies.get(0));
            }
        }

        // multiple aggressive enemies
        if (enemyGrenadiers.size() > 0) {
            printResult("S" + enemyGrenadiers.get(0));
        } else {
            int id = aggressiveEnemies.get(0);
            for (int playerId : aggressiveEnemies) {
                if (!shotLastTurn(players[playerId], playerId)) {
                    id = playerId;
                }
            }
            printResult("D" + id);
        }
    }

    private static void printResult(String result) {
        System.out.print(result);
        System.exit(0);
    }

    private static boolean isAlive(String player) {
        return !(player.charAt(0) == '-' || player.charAt(0) == '0');
    }

    private static void calcEnemyInfo(String[] players) {
        for (int i = 1; i < players.length; i++) {
            if (isAlive(players[i])) {
                aliveEnemies.add(i);
                if (isAggressive(players[i], i)) {
                    aggressiveEnemies.add(i);
                }
                if (isGrenadier(players[i])) {
                    enemyGrenadiers.add(i);
                }
            }
        }
    }

    private static boolean truckIsOnWay(String player) {
        return player.length() - player.replace(",", "").length() == 48;
    }

    private static boolean truckWillHit(String player) {
        return player.length() - player.replace(",", "").length() == 49;
    }

    private static boolean isAggressive(String player, int id) {
        return (player.contains("S") || player.contains("P")) && !player.contains("S" + id);
    }

    private static boolean isGrenadier(String player) {
        return player.contains("P");
    }

    private static boolean shotLastTurn(String player, int id) {
        return player.charAt(player.length() - 2) == 'S' && !player.contains("S" + id);
    }
}

!player.contains("S" + id)这是“ isAggressive”功能的必要条件吗?无论如何,一名自杀的玩家会死亡
Cruncher '18年

22

掷弹兵

枪支被高估了。一个真正的苏格兰人的僵局是这样的:

  • 准备
  • 以最健康的方式向敌人投掷
  • 重复(如果有奇迹,你还活着)

尽管这看起来微不足道,但这可能不是一个可怕的策略。由于枪支和手榴弹都有两转周期,这是迄今为止更有效的1分造成伤害的方式。

当然,如果所有三个对手都在第一轮将我射杀,那是不好的。但也不会有太多其他事情。

public class Grenadier {
    public static void main(String[] args) {
        if(args.length < 2)
            return;
        String[] list = args[1].split(" ");
        if(list.length < 4)
            return;

        if(list[0].charAt(list[0].length()-1) != 'P'){
            System.out.print("P");
            return;
        }

        int target = 1;
        for(int i=2;i<4;i++)
            if(list[i].charAt(0)>list[target].charAt(0))
                target = i;

        System.out.print("T"+target);
    }
}

以标准Java方式编译/运行:

> javac Grenadier.java
> java Grenadier arg0 arg1

1个毫无意义的脚注


41
哈哈哈脚注
骄傲的haskeller 2014年

我认为投掷手榴弹,然后射击更有效。使用此策略,您幸存4个回合的机会很少。但是3也许(是的,两个人都拿2,但是第二轮射击是在行动之后,而不是之前)
Cruncher

@Cruncher你可能是对的。埃里克在聊天中说了同样的话。我告诉他,我的家伙不相信枪支,太固执了,无法使用这种逻辑,因此他发布了该策略。但是,如果我们严格地讲造成的损害,我仍然相信这样做会更有效率。这并不意味着在赢得比赛方面会更有效。即使我在第三回合死亡,我的第二枚手榴弹仍然会熄灭。因此,如果我活到那时,那将保证每个人遭受6点以上的伤害,游戏结束。
Geobits,2014年

我现在考虑@@ Geobits,这可能会更好。最重要的是您与对手之间的差异。当手榴弹炸毁时,投掷者可获得+3德尔塔,其余则获得+0。净+3。射击。与您拍摄的人一起获得+2的差值。+0,其余。我认为问题是您-3与已经死亡的人在一起。如果有人死亡,您应该开枪:)
Cruncher 2014年

2
@codebreaker没玩过。这是现实生活中的参考。
Geobits,2014年

16

阿西莫夫的规则编号0 Bot-Python

机器人可能不会伤害人类,也可能无所作为而使人类受到伤害。

很直截了当,他将攻击他见到的第一个手持手榴弹的玩家,以保护大多数人。如果没有人对大多数人构成威胁,他将无所作为。

import sys

def total_humans_alive(humans):
  return sum([is_alive(human) for human in humans])

def is_alive(x):
  return int(x.split(",")[0]) > 0  

def is_threat_to_humanity(lastAction):
  return lastAction == "P"

action = "N"
threat_id = 1
humans = sys.argv[2].split()[1:];

if total_humans_alive(humans) == 3:
  for human in humans:
    if is_threat_to_humanity(human[-1]):
      action = "S" + str(threat_id)
      break
    threat_id= threat_id+ 1

print action

像这样运行:

python rule0bot.py

2
您的机器人不合逻辑。如果持有手榴弹的玩家投掷,人类会受到8 + 3 + 3 + 3 = 17的伤害。如果用射门杀死他,人类将受到2 + 6 + 3 + 3 + 3 = 17的伤害。在这两种情况下,炸毁手榴弹的人将花费8,而其他所有人将3(除非他们以前已经死亡)。整个人类不受影响。不过我还是喜欢。+1:D
Geobits,2014年

4
实际上,人类的最佳方案是希望将手榴弹扔向机器人;)
Geobits 2014年

1
@Geobits不试图阻止面临威胁的人是机器人的本性。它将试图阻止有人手持手榴弹,以防止大多数(另外两个)受到伤害。机器人,你读过我吗?这种逻辑得到了Little Lost Robot和The Evitable Conflict的支持。
威廉·巴博萨

我读过它,但我的意思是,射击他们并不能阻止它。如果他拿着手榴弹死了,它仍然会爆炸。不仅如此,对人类造成的总损害也保持不变。您是对人类的直接伤害,却对人类没有好处。
Geobits 2014年

2
+1我不同意Kyle Kanos的投票,并希望废除该票。同样,认为地球位对人类没有任何帮助是错误的。当然,在最坏的情况下,人性可能不会更好,但是如果其他两个玩家射击挥舞着手榴弹的手榴弹,那么他们都会更好。
FreeAsInBeer 2014年

14

Han Solo-Python

汉先出手。在这种情况下,他将首先通过选择最接近的活着目标来射击。

import sys

def is_alive(player):
  return int(player.split(",")[0]) > 0

closest_living_target = 1;

for player in sys.argv[2].split()[1:]:
  if is_alive(player):
    action = "S" + str(closest_living_target)
    break

  closest_living_target = closest_living_target + 1

print action

像这样运行:

python hansolo.py

注意:这是我用Python编写的第一件事,因此,如果您发现任何特定于python的不良做法,请告诉我。


1
pep8风格建议您使用的方法应该是is_alive
Daenyth

4
@WilliamBarbosa看看pep8,它是每个人都使用的python样式指南。legacy.python.org/dev/peps/pep-0008
Daenyth,2014年

2
祝贺您在8/11回合中成为唯一一个平均健康状况大于0的漫游器。
isaacg 2014年

6
IMO,“样式指南”用于理发师,而不是程序员。
凯尔·坎诺斯

2
@KyleKanos保持一致性很高兴。我的意思是,如果一个项目使用骆驼,另一半类型的这样的半开发商,其结果将是“blergh”
威廉·巴博萨

12

情绪牛仔

为什么要死呢?现在就自杀吧。希望其余的傻瓜将彼此炸毁至小于-2。

分数通常为-2。如果人们决定将我射杀,有时为-4。远远不止于此,这意味着它应该胜过当前的一些提交。

蟒蛇

print('S0')

python EmoCowboy.py

编辑:这不是在开玩笑,这就是为什么这些emo提交被皱眉的原因。这是合法的策略。活着是致命的!


11

和平主义者

他是一个真正的好人,只是被错误的人群所吸引。

main = putStr "N"

运行为runghc pacifist.hs,但是如果效率存在问题,则可能需要使用-O3进行编译。


1
请重命名路易吉(Luigi),看看他是否会赢得任何胜利!
威廉·巴博萨

1
@WilliamBarbosa Luigi?你是说路易吉吗?
2014年

7
大声笑好像-O3在发狂。
tomsmeding

@tomsmeding侧面很慢runghc。实际上,在我的Linux机器上,它要慢10倍。

5
这意味着存在暴力,这是我们的和平主义者不准备应对的暗示
致命的2014年

9

猴子 -Python(首次进入!)

有样学样。将完全重复随机玩家所采取的最后一个动作。

import sys, random
targetData = sys.argv[2].split()[random.randint(0,3)]
print(targetData.split(',')[len(targetData.split(','))-1])

可以这样运行:“ python monkey.py args”不需要额外的步骤。


2
我希望他们不会对你开枪!Python支持负数组索引,因此您无需计算长度并减去1。只需-1直接使用。
2014年

@comperendinous说我在他们的名单上是S3。如果我执行S3,就不会开枪打我。另外,-1索引将返回最后一个元素?如果是这样,那就酷!我一定会添加它。
埃里亚斯·本尼维德斯

并且不要忘记第一个(整数)参数。您需要argv[2]获取玩家历史记录。
2014年

只是希望您不要与Emo Cowboy相提并论。
密码破解者2014年

6

简单射手-Perl (已修复的错误)

该机器人会以最健康的方式射击对手。这是一个非常简单的策略,但我认为它有很好的机会切实发挥作用。

@history = map([split(",",$_)],split(" ",$ARGV[1]));
$target = 1;
for(2..3){
 if($history[$_][0] >= $history[$target][0]){$target = $_}
}
print "S$target"

这是使用一些示例输入运行它的方法:

perl simpleshooter.plx 7 "3,S2,N 5,P,N 3,S0,N -2,S3,N"

哇。简单而智能。
Soham Chowdhury 2014年

6

Spock,在Python 3.x中

这段代码更像是一个实验(因此以Spock命名,因为...他是个火神,他们在这类事情上非常擅长),但是构建它还是很有趣的。如果给出游戏规则,所有这些代码背后的主要理由是假设像Spock一样,一个好的逻辑人物会做的:


该游戏的目的是使得分最大化,这要由每个站着不动的人来完成,这是不可能的,因为有卡车。

  • Spock必须遵循的指令之一是防止卡车出现,并确保在卡车出现之前,除了一个人外,其他所有人都已经死亡。

Spock在游戏其余部分中的演奏方式可以用他的名言来概括:“ 许多人的需求大于少数人的需求 ”。换句话说,Spock必须通过杀死造成伤害的人来确保遭受最少的伤害。他是如何做到的:

  • 如果没有任何玩家准备投掷手榴弹,请针对仍在玩耍的健康状况最差的玩家。
  • 如果有准备投掷手榴弹的玩家,那么这些人的目标是最不健康的人。

原因是,通过瞄准最弱的参与者,我们正在终止损害的根源。手榴弹背后的原因是它们无论如何都可以起飞,如果不扔出去,它们所造成的伤害更少。


因此,该机器人可以工作。我尚未针对输入失败进行过广泛的测试(因此,如果出现问题,请警告我),但我有信心解决了大多数问题。我基于HanSolo机器人的一小部分代码,但大部分情况下都是一团糟的代码。请享用。

def IsAlive(player):
  return int(player[1].split(",")[0]) > 0
def IsTarget(player, target_health):
  return int(player[1].split(",")[0]) < target_health
def HasGrenade(player):
  max_range = max(-4,-current_turn)
  for foo in range(-1,max_range,-1):
    if "P" in player[1].split(",")[foo]:
      for bar in range(-1,foo-1,-1):
        if player[1].split(",")[bar] not in ["T0", "T1", "T2", "T3"]:
          return True
  return False

import sys
info_list = sys.argv[2].split()
current_turn = len(info_list[0].split(","))
action = "N"

def Startgame():
  global action

  target = 1
  target_health = 5
  grenade_list=[]

  for player in zip(range(1,4),info_list[1:]):
    if HasGrenade(player):
      grenade_list.append(player)

  if not grenade_list:
    foo_list = []
    for player in zip(range(1,4),info_list[1:]):
      foo_list.append(player)
    target_list = foo_list
  else:
    target_list = grenade_list

  # Choose the least healthy player
  for player in target_list:
    if IsAlive(player) and IsTarget(player, target_health):
      target = player[0]
      target_health = int(player[1][0])

  action = "S" + str(target)

def Endgame(turn):
  global action

  if turn in [47, 49]:
    # Check if in 2 moves he can do enough damage
    rem_health = 0
    for player in zip(range(1,4),info_list[1:]):
      if IsAlive(player): rem_health += player[0]

    if rem_health < 5:
      Startgame() # It's lazy, but it should work
      return
    else:
      action = "P"
      return

  if turn in [48, 50]:
    # If Spock shot someone before, it needs to shoot again
    if info_list[0].split(",")[-1] in ["S0", "S1", "S2", "S3"]:
      Startgame()
      return
    else:
    # There's no rule against throwing grenades to dead bodies, so if
    # possible it will be thrown there.    
      target = 1
      target_health = 5

      foo_list = []
      for player in zip(range(1,4),info_list[1:]):
        foo_list.append(player)
      target_list = foo_list

      for player in target_list:
        if IsTarget(player, target_health):
          target = player[0]
          target_health = int(player[1][1])

      action = "T" + str(target)
      return

if current_turn > 46:
  Endgame(current_turn)
else:
  Startgame()

print(action)

像这样运行:

python spock.py

2014-08-12-关于手榴弹检测的
小错误修正2014-08-14-关于残局的小错误修正,感谢isaacg之前指出了这一点


您每两轮射击不得超过一次。阅读拍摄说明。
isaacg 2014年

@isaacg感谢您的提醒(确实可以解释行为),但是似乎存在一些潜在的错误。例如,在 Spock中,应该射击了InputAnalyser,因为他有一个手榴弹(即使Solo会有2点生命)。
Doktoro Reichard 2014年

Traceback (most recent call last): File "./players/Spock/Spock.py", line 87, in <module>: Endgame(current_turn) File "./players/Spock/Spock.py", line 79, in Endgame: if IsTarget(player, target_health): File "./players/Spock/Spock.py", line 4, in IsTarget: return int(player[1].split(",")[0]) < target_health TypeError: unorderable types: int() < str()
es1024

player[1][1]应该是int(player[1][1])
isaacg 2014年

再次@isaacg,谢谢您的帮助。我本来会早做的,但是我被很多东西淹没了。Spock最终建立在一个关于如何发挥作用的误导概念上,因此他获得了相对较低的分数。我确实对新机器人有一些想法,但是现在有很多我必须确保主要想法是原始的。
Doktoro Reichard 2014年

5

政治上正确的枪手

从政治上讲是正确的,因为它不会歧视任何事物。因此,它不是很聪明。

import random

array = ["P", "N", "S0", "S1", "S2", "S3", "D1", "D2", "D3", "T1", "T2", "T3"]

print(array[random.randrange(0,11)])

……什么参数传递给它的方式并不重要。 python politicallycorrectgunman.py


我认为方括号不应该成为输出的一部分。也许@ es1024可以确认这一点。而且您知道random.choice吗?这些选择非常好。
2014年

输出中的动作和目标之前没有任何内容,尽管之后的任何内容都被忽略了
es1024 2014年

@ es1024看起来更好吗?
2014年

@Undo是,现在可以正常使用
es1024 2014年

7
你不能只用random.choice(array)吗?
user2357112 2014年

5

直射手

他是骑兵中训练有素的一部分,并使用多种语言进行交谈。但是,眨眼间,“直射手”只能看到面前的一个敌人。作为一匹马,他不明白你必须在两次射击之间等待。

print('S2')

Perl,Python 2/3,Ruby:这匹马确实是一个polygot条目。

反正我赢了。我不能输。你可以射击我,但不能杀了我。埃德先生对我没事!

要获得更多思考(和一些功能范例)的答案,请参阅《二十四和半个世纪》


5

反手榴弹兵

手榴弹是坏的。很坏。因此,如果有人正在准备,最好的办法就是射击他们。否则,我们就出去玩。

-- Antigrenadier
local args = {...}  -- command line arguments

match = args[2]     -- store the set of matches

-- why this isn't standard in Lua....
function string:split( inSplitPattern, outResults )
  if not outResults then
    outResults = { }
  end
  local theStart = 1
  local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
  while theSplitStart do
    table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
    theStart = theSplitEnd + 1
    theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
  end
  table.insert( outResults, string.sub( self, theStart ) )
  return outResults
end

-- set up the players
players = match:split(" ")

-- search other players for someone who pulled a grenade
for i=2,#players do
   moves = players[i]
   -- test if person is alive
   if moves:sub(1,1) ~= "-" then
      -- cycle through all elements of the string
      for j=#moves,2,-1 do
         -- if found, shoot!
         if moves:sub(j,j) == "P" then
            print("S"..i-1)
            os.exit()
         end
      end
   end
end

-- otherwise we just relax
print("N")

4

Ricochet-Perl

简单的策略似乎可以很好地应对这一挑战,因此这是另一个。它射击一个随机的在世玩家。它具有在最后自杀以避免卡车的附加功能。

@history = map([split(",",$_)],split(" ",$ARGV[1]));
$health = $history[0][0];
@options = ();
for(1..3){
 if($history[$_][0] > 0){
  push(@options,$_);
 }
}
$target = @options[int(rand(~~@options))];
if(~~@{$history[0]} == 50){
 $target = 0;
}
print"S$target";

像这样运行:

perl ricochet.plx 5 "-2,S0 -2,S1 -2,S2 5,N" 

4

侵略者

绕开第一轮,在第二轮向最高健康对手投掷,然后向最高健康对手射击。

#include <cstdio>
#include <cstring>

int main(int argc, char** argv){
   char* t;
   t = strtok(argv[2]," ");
   int len = strlen(t);
   int max = -50, maxP;
   for(int i=1;i<4;i++){
      int cur;
      t = strtok(NULL," ");
      if(t[0]=='-'){cur = -1*(t[1]-'0');}
      else{cur = t[0]-'0';}
      if(cur>max){
         max = cur;
         maxP = i;
      }
   }
   if(len == 1){printf("P\n"); return 0;}
   if(len == 3){printf("T%d\n",maxP); return 0;}
   printf("S%d\n",maxP);
   return 0;
}

像./agg ID“ 5 5 5 5”这样运行。


4

忍者

只是躲避试图避免被击中。

math.randomseed(os.time())
print("D"..tostring(math.random(4)-1))

运行为

lua ninja.lua

Arg是不必要的,但可以添加而不会出现问题。


2
@KyleKanos忍者会躲闪自己的镜头吗?
skeggse 2014年

2
@distilledchaos:是的,他会的。
凯尔·坎诺斯

4

名称:PriorityTargets

Shell命令:ruby PriorityTargets.rb 5 [game_state]

语言:Ruby V2.1.2

描述:PriorityTargets尝试查找常见的游戏风格。然后,根据这些游戏风格,决定要攻击谁以及使用哪种武器。

注意:首次提交Code Golf!比其他提交的内容大很多,因为我有点疯狂。

#!/usr/bin/env ruby

class PriorityTargets
  class PlayerAction
    SHOOT = 'S'
    DODGE = 'D'
    PREPARE_GRENADE = 'P'
    THROW_GRENADE = 'T'
    NOTHING = 'N'
    attr_accessor :action, :target

    def initialize(action_string)
        @action = action_string[0, 1]
        @target = self.has_target? ? action_string[1, 1].to_i : false
    end

    def to_s
      string = @action
      string << @target.to_s if self.has_target?
      string
    end

    def has_cooldown?
      [SHOOT].include? @action
    end

    def is_aggressive?
      [SHOOT, PREPARE_GRENADE, THROW_GRENADE].include? @action
    end

    def has_target?
      [SHOOT, DODGE, THROW_GRENADE].include? @action
    end
  end


  class Player
    attr_reader :identifier, :health, :history
    attr_accessor :playstyles

    def initialize(player_identifier, player_string)
      @identifier = player_identifier
      @playstyles = []

      player_info = player_string.split(',')
      @health = player_info.shift.to_i
      @history = parse_history(player_info)
    end


    def has_attacked?(player, round = nil)
      round ||= self.history.length - 1
      player.history[0, round].each do |turn|
        did_attack = true and break if turn.is_aggressive? && turn.has_target? && turn.target == player.identifier
      end
      did_attack ||= false
    end

    def is_holding_grenade?(round = nil)
      round ||= self.history.length
      turn_history = self.history[0, round]
      is_holding = false

      turn_history.each_with_index do |turn, curr_round|
        if turn.action == PlayerAction::PREPARE_GRENADE && curr_round >= round - 3
          is_holding = true if turn_history.drop(curr_round).select{|turn| turn.action == PlayerAction::THROW_GRENADE }.length == 0
        end
      end

      is_holding
    end

    def is_dead?; self.health <= 0; end
    def is_on_cooldown?
      return false if self.history.length == 0
      self.history.last.has_cooldown?
    end

    def turn_at_round(round); self.history[round-1]; end

    private

      def parse_history(history_array)
        parsed = []
        history_array.each {|action_string| parsed << PlayerAction.new(action_string) }
        parsed
      end
  end

  class PlayerList
    include Enumerable

    def initialize(player_list = [], filter_list = false)
      @list = player_list
      @filter = filter_list if filter_list
    end

    #Enumerable Methods
    def each
      list = @list.select{|player| @filter.include?(player.identifier) } if @filter
      list = @list unless @filter
      list.each {|player| yield(player) }
    end

    def <<(player); @list << player; end
    def [](key)
      player = @list.select{|player| @filter.include?(player.identifier) }[key] if @filter
      player = @list[key] unless @filter
      player
    end

    def length
      list = @list.select{|player| @filter.include?(player.identifier) } if @filter
      list = @list unless @filter
      list.length
    end

    def empty?; self.length == 0; end
    def not_empty?; self.length > 0; end

    def create_filtered_list(player_ids)
      new_player_list = PlayerList.new(@list, player_ids)
      new_player_list
    end

    #PlayerList Methods
    def includes_playstyle?(playstyle)
      (self.with_playstyle(playstyle).length > 0)
    end

    def have_executed_action?(action)
      action_found = false
      self.each {|player| action_found = true and break if player.history.select {|turn| turn.action == action}.length > 0 }
      action_found
    end

    def direct_damages(round = nil)
      round ||= self.first.history.length

      damage_list = {}
      @list.each {|player| damage_list[player.identifier] = 0 }

      if round >= 1
        @list.each do |player|
          player.history[0, round].each_with_index do |turn, curr_round|

            if turn.has_target?
              target_player = @list.select{|curr_player| curr_player.identifier == turn.target }.first
              target_turn = target_player.turn_at_round(curr_round)

              damage_list[turn.target] += 8 if turn.action == PlayerAction::THROW_GRENADE

              if turn.action == PlayerAction::SHOOT
                damage_list[turn.target] += 2 unless target_turn.action == PlayerAction::DODGE && target_turn.target == player.identifier
              end
            end
          end
        end
      end

      damage_list.select! {|key| @filter.include? key } if @filter
      damage_list
    end


    def filtered_with_condition(&condition_block)
      player_ids = []
      self.each {|player| player_ids << player.identifier if condition_block.call(player) }
      create_filtered_list(player_ids)
    end

    def on_cooldown; filtered_with_condition {|player| player.is_on_cooldown?} end
    def not_on_cooldown; filtered_with_condition {|player| !player.is_on_cooldown?} end

    def dead; filtered_with_condition {|player| player.is_dead?} end
    def not_dead; filtered_with_condition {|player| !player.is_dead?} end

    def with_playstyle(playstyle); filtered_with_condition {|player| player.playstyles.include?(playstyle)} end
    def not_with_playstyle(playstyle); filtered_with_condition {|player| !player.playstyles.include?(playstyle)} end

    def with_max_health(round = nil)
      round ||= self.first.history.length
      player_damages = direct_damages(round)
      filtered_with_condition {|player| player_damages[player.identifier] == player_damages.values.min }
    end

    def with_identifier(identifier)
      matches = self.with_identifiers([ identifier ])
      return nil if matches.empty?
      matches.first
    end

    def with_identifiers(identifiers)
      create_filtered_list(identifiers)
    end
  end

  class PlayerTypes
    GRENADIER = :GRENADIER
    COWBOY = :COWBOY
    SKIDDISH = :SKIDDISH
    AGGRESSOR = :AGGRESSOR
    DEFENSIVE = :DEFENSIVE
    ANTI_GRENADIER = :ANTI_GRENADIER
    PLAYSTYLE_ORDER = [GRENADIER, COWBOY, SKIDDISH, AGGRESSOR, DEFENSIVE, ANTI_GRENADIER]

    def initialize(player_list)
      @players = player_list
    end

    def analyze_playstyles
      return if @players.first.history.length == 0

      PLAYSTYLE_ORDER.each do |playstyle|
        check_fnc = "is_"+playstyle.to_s+'?'
        @players.each {|player| player.playstyles << playstyle if self.send(check_fnc, player) }
      end
    end

    def is_GRENADIER?(player)
      #Grenade on first turn
      #Used more than one grenade
      #Never used gun, only grenade
      shoot_count = player.history.count {|turn| turn.action == PlayerAction::SHOOT }
      grenade_count = player.history.count {|turn| turn.action == PlayerAction::PREPARE_GRENADE }

      profiled ||= true if player.history.first.action == PlayerAction::PREPARE_GRENADE
      profiled ||= true if grenade_count > 1
      profiled ||= true if shoot_count == 0 && grenade_count > 0
      profiled ||= false
    end

    def is_COWBOY?(player)
      #Never used grenade, only gun
      shoot_count = player.history.count {|turn| turn.action == PlayerAction::SHOOT }
      grenade_count = player.history.count {|turn| turn.action == PlayerAction::PREPARE_GRENADE }

      profiled ||= true if grenade_count == 0 && shoot_count > 0
      profiled ||= false
    end

    def is_SKIDDISH?(player)
      #Dodged more than once
      #Never hurts anybody
      dodge_count = player.history.count {|turn| turn.action == PlayerAction::DODGE }
      attack_count = player.history.count {|turn| turn.is_aggressive? }

      profiled ||= true if dodge_count > 1
      profiled ||= true if attack_count == 0 && player.history.length > 1
      profiled ||= false
    end

    def is_AGGRESSOR?(player)
      #Only shoots person >= most health
      profiled = false
      player.history.each {|turn| profiled = true if turn.is_aggressive? && turn.has_target? }

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          profiled = false if !@players.with_max_health(round).include? @players.with_identifier(turn.target)
        end
      end
      profiled
    end

    def is_DEFENSIVE?(player)
      #Only hurts people who hurt them first
      player.history.each {|turn| profiled = true if turn.is_aggressive? && turn.has_target? }

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          target_player = @players.with_identifier(turn.target)
          profiled = false unless target_player.has_attacked?(player, round)
        end
      end
      profiled ||= false
    end

    def is_ANTI_GRENADIER?(player)
      #After a Grenadier has been shown, only shoots grenadier
      shots_fired = 0
      shots_fired_while_holding = 0

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          target_player = @players.with_identifier(turn.target)
          shots_fired += 1
          shots_fired_while_holding += 1 if target_player.is_holding_grenade?(round)
        end
      end

      (shots_fired > 0 && shots_fired/2.0 <= shots_fired_while_holding)
    end
  end




  def initialize(game_state)
    players_info = game_state.split(' ')
    @player = Player.new(0, players_info.shift)
    @players = PlayerList.new
    @players << @player
    enemy_identifiers = []

    players_info.each_with_index {|info, index| @players << Player.new(index+1, info); enemy_identifiers << index+1; }

    @enemies = @players.with_identifiers(enemy_identifiers  )
  end

  def analyze_playstyles
    types = PlayerTypes.new(@players)
    types.analyze_playstyles
  end

  def find_dodge_target
    armed_aggressors = @enemies.with_playstyle(PlayerTypes::AGGRESSOR).not_on_cooldown().not_dead()

    if armed_aggressors.not_empty?
      return armed_aggressors.with_max_health().first if @players.with_max_health().include?(@player) && @players.with_max_health().length == 1
    end

    return @enemies[Random.rand(3)] if @player.history.length == 0
    nil
  end

  def find_target
    unarmed_aggressors = @enemies.with_playstyle(PlayerTypes::AGGRESSOR).on_cooldown().not_dead()
    anti_grenadiers = @enemies.with_playstyle(PlayerTypes::ANTI_GRENADIER).not_dead()
    grenadiers = @enemies.with_playstyle(PlayerTypes::GRENADIER).not_dead()
    cowboys = @enemies.with_playstyle(PlayerTypes::COWBOY).not_dead()
    skiddish = @enemies.with_playstyle(PlayerTypes::SKIDDISH).not_dead()
    defensive = @enemies.with_playstyle(PlayerTypes::DEFENSIVE).not_dead()

    if unarmed_aggressors.not_empty?
      return unarmed_aggressors.with_max_health().first if @players.with_max_health().include?(@player) && @players.with_max_health().length == 1
    end

    return anti_grenadiers.with_max_health().first if anti_grenadiers.not_empty?
    return grenadiers.with_max_health().first if grenadiers.not_empty?
    return cowboys.with_max_health().first if cowboys.not_empty?
    return skiddish.with_max_health().first if skiddish.not_empty?
    return defensive.with_max_health().first if defensive.not_empty?
    return @enemies.with_max_health().not_dead().first if @enemies.with_max_health().not_dead().length > 0
    nil
  end

  def find_weapon
    return PlayerAction::THROW_GRENADE if @player.is_holding_grenade?

    anti_grenadiers = @enemies.with_playstyle(PlayerTypes::ANTI_GRENADIER).not_dead()

    return PlayerAction::PREPARE_GRENADE if anti_grenadiers.empty? && @enemies.have_executed_action?(PlayerAction::PREPARE_GRENADE)
    PlayerAction::SHOOT
  end

  def make_decision
    dodge_target = self.find_dodge_target
    target = self.find_target
    weapon = self.find_weapon

    decision ||= PlayerAction.new(PlayerAction::NOTHING) if @player.is_on_cooldown? || @enemies.with_max_health().not_dead().length == 0
    decision ||= PlayerAction.new(PlayerAction::DODGE + dodge_target.identifier.to_s) if dodge_target
    decision ||= PlayerAction.new(weapon + target.identifier.to_s)
    STDOUT.write decision.to_s
  end
end

priority_targets = PriorityTargets.new(ARGV[1])
priority_targets.analyze_playstyles
priority_targets.make_decision

1
我喜欢您的方法,期待看到它将如何做。
演员

可悲的是,它似乎有一个制造榴弹兵的错误。好吧,下次还会做的更好:)
fingerco 2014年

3

胆小鬼-Perl

表现得很co弱。当他感觉健康时,他会选择一个感觉不佳的敌人并开枪射击他。那些在最后一回合射击的敌人的加分(因为众所周知,他们正在Nothing此回合,因此绝对没有防御能力)。当他感觉不太舒服时,他会跑去掩护以躲藏起来,偶尔开枪射击某人。

#!/usr/bin/perl

@allinfo = map { [split/,/] } split / /, $ARGV[1];
@life = map { $_->[0] } @allinfo;
@action = map { @$_>1 ? $_->[-1] : () } @allinfo;

if($life[0] < 3 && rand() < .5 )
{
    printf "D%d", +(sort { ($life[$a]>0)*($action[$a] eq "N") <=> ($life[$b]>0)*($action[$b] eq "N") } 1..3)[2]
}
else
{
    @score = map { $life[$_]>0 ? (5/$life[$_] + 2*($action[$_] =~ /S./)) : 0 } 1..3;
    printf "S%d", +(sort { $score[$a] <=> $score[$b] } 1..3);
}

漂亮的标准Perl代码;将其保存在某个文件中,然后运行perl file argument argument [...]。我已经检查了语法,而且还可以,所以我希望对此没有问题。

E:消除了除以0的可能性。


3

炸弹人

用R编写的Bot,命令行应该是:Rscript Bomberman.R arg0 arg1
开始编写此Bot之后,我意识到Geobits已经制造了一个掷弹兵,但我认为我的枪弹有很大不同,因为它在准备投掷手榴弹之前会检查其生命值是否高于3,然后将其扔到最后一个射手,然后是最健康的射手,如果生命值低于3,它将躲避危险的玩家(在最后一轮既不死也没有射手)或射击其余玩家之一。

input <- commandArgs(TRUE)
history <- do.call(rbind,strsplit(scan(textConnection(input[2]),"",quiet=TRUE),","))
health <- as.integer(history[,1])
last_shooter <- which(grepl("S",history[-1,ncol(history)]))
last_prepare <- which(history[1,]=="P")
if(!length(last_prepare)) last_prepare <- -1
last_throw <- which(grepl("T",history[1,]))
if(!length(last_throw)) last_throw <- 0
most_healthy <- which.max(health[-1])
dead <- which(health[-1]<=0)
inoffensive <- c(last_shooter,dead)
danger <- which(!(1:3)%in%inoffensive)
alive <- which(!(1:3)%in%dead)
if(health[1]>3 & last_throw > last_prepare) out <- "P"
if(last_throw < last_prepare) out <- ifelse(length(last_shooter),paste("T",last_shooter[1],sep=""),paste("T",most_healthy[1],sep=""))
if(health[1]<=3 & last_throw > last_prepare){
    if(length(danger)){
        out <- paste("D",sample(danger,1),sep="")
    }else{
        out <- paste("S",sample(alive,1),sep="")
    }
}
cat(out)

编辑

由于我查看的所有日志都显示我的机器人仅输出,因此该机器人与您的控制器之间似乎存在通信问题N。因此,这里是同一机器人,但是用Python重写,希望如果该机器人也遇到通信问题,那么有人会看到它。
被称为python Bomberman.py arg0 arg1

import sys,re,random

history = sys.argv[2]
history = [k.split(",") for k in history.split()]
health = [k[0] for k in history]
last_turn = [k[-1] for k in history]
last_shooter = [i for i,x in enumerate(last_turn) if re.search(r'S[0-3]',x)]
last_prepare = [i for i,x in enumerate(history[0]) if x=='P']
if not len(last_prepare):
    last_prepare = [-1]

last_throw = [i for i,x in enumerate(history[0]) if re.search(r'T[0-3]',x)]
if not len(last_throw):
    last_throw = [0]

most_healthy = [i for i,x in enumerate(health) if x==max(health)]
dead = [i for i,x in enumerate(health) if x<=0]
inoffensive = last_shooter+dead
danger = [k for k in range(1,4) if k not in inoffensive]
alive = [k for k in range(1,4) if k not in dead]
if health[0]>3 and last_throw[-1] > last_prepare[-1]:
    out = 'P'

if last_throw[-1] < last_prepare[-1]:
    if len(last_shooter):
        out = 'T'+random.choice(last_shooter)
    else:
        out = 'T'+random.choice(most_healthy)

if health[0]<=3 and last_throw[-1] > last_prepare[-1]:
    if len(danger):
        out = 'D'+random.choice(danger)
    else:
        out = 'S'+random.choice(alive)

print(out)

机器人的名称相对较弱,但我
想不通

GymnastBomber !!
Cruncher 2014年

3

躲避上轮未射击的在世球员。如果每个人都在最后一轮还活着射击,那就随机射击一个活着的球员。看到大灯后自杀。

import java.util.Random;
public class Neo {
    public static void main(String[] args) {
        if(args.length < 2)
            return;
        String[] list = args[1].split(" ");
        if(list.length < 4)
            return;
        Random rand = new Random();
        int turn = list[0].split(",").length;
        if(turn == 49){
            System.out.print("S0");
            return;
        }
        int target=0;
        for(int i=1;i<4;i++)
            if(list[i].length()<2 || (list[i].charAt(0)!='-' && list[i].charAt(list[i].length()-2)!='S'))
                target=i;
        if(target>0){
            System.out.print("D"+target);
            return;
        }
        while(target<1){
            int i=rand.nextInt(3)+1;
            if(list[i].charAt(0)!='-')
                target=i;
        }
        System.out.print("S"+target);
    }
}

对于这个手榴弹攻击者,我并不抱有太大期望,但是对于射手来说,这可能效果很好。我们拭目以待。


我在回答中使用了一些样板代码。我希望可以。
overactor 2014年

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1 at java.lang.String.charAt(String.java:658) at Neo.main(Neo.java:17)
es1024

@ es1024现在应该走了,而且在每一个第一回合都不会做任何事情。
Geobits,2014年

2

二十四世纪半

该Python条目会躲避并躲避,直到仅剩下被动玩家或一个攻击性玩家,然后开始射击。它希望一个过世的火星人照顾手榴弹兵和醉酒的卡车司机。

除非我做错了什么,否则这是功能性的Python。当然,它看起来不像我在Haskell和朋友找到我之前写的那种Python,而且我认为我没有对任何东西进行突变。但是,如果您了解得更多,请告诉我。

#!/usr/bin/env python
import sys
import random

## ==== Move Types ================================================== ##
def move_type (move):
    if "" == move:
        return "N"
    return move[0]

def is_passive_move (move):
    if "N" == move:
        return True
    if "D" == move_type (move):
        return True
    return False

def is_aggressive_move (move):
    return not is_passive_move (move)

def passive_moves (moves):
    return [m for m in moves if is_passive_move (m)]

def aggressive_moves (moves):
    return [m for m in moves if is_aggressive_move (m)]
## ================================================== Move Types ==== ##

## ==== Player Model ================================================ ##
class Player:
    def __init__ (self, number, health, moves):
        self.number = number
        self.health = health
        self.moves  = moves

    def last_move (self):
        if 0 == len (self.moves):
            return ""
        return self.moves[-1]

def player_from (number, player_string):
    x = player_string.split (",")
    health = int (x[0].strip ())
    moves = [move.strip () for move in x[1:]]

    return Player (number, health, moves)

def players_from (game_state):
    return [player_from (n, p) for (n, p) in
                                   zip (range(4), game_state.split ())]

def is_alive (player):
    return 0 < player.health

def i_am_dead (me):
    return not is_alive (me)

def can_shoot (player):
    return "S" != move_type (player.last_move ())

def is_passive (player):
    passive_move_count = len (passive_moves (player.moves))
    aggressive_move_count = len (aggressive_moves (player.moves))

    return passive_move_count > (aggressive_move_count + 1)

def players_who_can_breathe (players):
    return [p for p in players if is_alive (p)]

def players_who_can_shoot (players):
    return [p for p in players if can_shoot (p)]

def players_who_stand_around (players):
    return [p for p in players if is_passive (p)]
## ================================================ Player Model ==== ##

## ==== Actions ===================================================== ##
def shoot_randomly_at (possible_targets):
    chosen_target = random.choice (possible_targets)
    return "S{0}".format (chosen_target.number)

def dodge_one_of_the (potential_shooters):
    chosen_shooter = random.choice (potential_shooters)
    return "D{0}".format (chosen_shooter.number)

def do_nothing ():
    return "N"

def pick_move (game_state):

    players = players_from (game_state)
    me = players[0]
    enemies = players[1:]

    if i_am_dead (me):
        return do_nothing ()

    living_enemies = players_who_can_breathe (enemies)
    if 1 == len (living_enemies):
        return shoot_randomly_at (living_enemies)

    passive_enemies = players_who_stand_around (living_enemies)
    if len (living_enemies) == len (passive_enemies):
        return shoot_randomly_at (passive_enemies)

    potential_shooters = players_who_can_shoot (living_enemies)
    if 0 < len (potential_shooters):
        return dodge_one_of_the (potential_shooters)

    return do_nothing ()
## ===================================================== Actions ==== ##

if "__main__" == __name__:

    game_state = sys.argv[2]
    print (pick_move (game_state))

运行方式:

python twenty-fourth-and-a-halfth-century.py 0 "5 5 5 5"

2

害怕

此提交令所有人感到恐惧。但这尤其使某些人感到害怕。因此,它找出谁是最危险的人并开枪射击。如果多个敌人看上去是最危险的,它将随机射击。

import sys
import random


def is_alive(player):
    return int(player.split(",")[0]) > 0


# Anyone with a live grenade who is alive is dangerous
def is_dangerous(player):
    return player.count("P") > player.count("T") and \
        int(player.split(",")[0]) > 0


def health(player):
    return int(player.split(",")[0])


# Failing that, healthy people are dangerous
def danger_rating(player):
    return 6 if is_dangerous(player) else health(player)

enemies = sys.argv[2].split()[1:]

highest_danger = max(danger_rating(enemy) for enemy in enemies)
most_dangerous_enemy = random.choice(
    [enemy_num+1 for enemy_num in range(len(enemies))
     if danger_rating(enemies[enemy_num]) == highest_danger])

print("S"+str(most_dangerous_enemy))

这是python(2或3,两者的结果相同。)另存为scared.py,运行python3 scared.py


2

操纵混蛋– Python

准备并投掷手榴弹。如果他认为没有时间或敌人太少,就会开枪射击。如果他一个人,他会试图超越另一个人。

import sys

def health(p):
    return int(p[0])

def is_alive(p):
    return health(p) > 0

def can_act(p):
    return is_alive(p) and p[-1][0] != 'S'

def can_throw(p):
    return is_alive(p) and p[-1][0] == 'P'

def shot_first(p):
    if len(p) == 1:
        return False
    return p[1][0] == 'S'

def act(a):
    print a
    sys.exit(0)

player = sys.argv[2].split()[0].split(',')
enemies = [e.split(',') for e in sys.argv[2].split()[1:]]
healthiest = sorted(enumerate(enemies, 1), key=lambda e:health(e[1]))[-1]
alive = sum(is_alive(e) for e in enemies)

if alive == 1:
    i, e = healthiest
    if health(e) <= 2 and not can_act(e):
        act('S%d' % i)
    if can_throw(player):
        act('T%d' % i)
    if can_throw(e):
        act('S%d' % i)
    if can_act(e) and shot_first(e) and len(player) < 40:
        act('D%d' % i)
    if len(player) > 45:
        act('P')
    act('S%d' % i)

if can_throw(player):
    i, e = healthiest
    act('T%d' % i)

if len(player) > 45:
    act('P')

if health(player) <= 2 or any(can_throw(e) for e in enemies) or alive == 2:
    i, e = healthiest
    act('S%d' % i)

act('P')

2

大s

我已经尝试了一天左右,现在是时候发布帖子了,看看与此同时其他人的发展情况。

module Main where

import Data.List
import Data.Ord
import System.Environment

words' "" = []
words' s = s' : words' (tail' s'')
  where
    (s', s'') = break (==',') s
    tail' (',':r) = r
    tail' r = r

nRound = length . words'

lastAction = last . words'

health :: String -> Int
health = read . head . words'

alive = (>0) . health

grenadeAge :: String -> Int
grenadeAge p | not (alive p) = 0
             | otherwise = g 0 $ tail $ words' p
  where
    g n (a:b:r) | head a == 'S' = g (if n>0 then n+2 else 0) r
    g 0 ("P":r) = g 1 r
    g n (('T':_):r) | n>0 = g 0 r
    g n (_:r) | n>0 = g (n+1) r
    g n (_:r) = g n r
    g n [] = n

prepared :: String -> Bool
prepared p = alive p && head (lastAction p) /= 'S'

nShotMe = length . filter (=="S0") . words'

getPlayer = (!!)

action players@(me:them) | not (prepared me) = "S2" -- bogus
                         | nRound me >= 49 = "S0"
                         | grenadeAge me >= 1 = 'T':(show $ maximumBy (comparing (nShotMe . getPlayer players)) l)
                         | any prepared them && nRound me > 0 = 'D':(show $ maximumBy (comparing (nShotMe . getPlayer players)) l)
                         | otherwise = 'S':(show $ maximumBy (comparing (health . getPlayer players)) l)
  where l = filter (alive . (getPlayer players)) [1..3]



main = do
  players <- fmap (words . head . tail) getArgs
  putStrLn $ action players

进行编译ghc -O2 osama.hs,然后使用运行./players/Osama/osama


2

狙击手-Lua

在第一个回合中,它会射击一个随机的人,然后射击它会杀死的任何玩家(2点或1点生命)。如果这些方法均无效,它将尝试射击最后射击的玩家,否则它将射击随机的玩家。与运行lua Sniper.lua

turns = arg[2]
health = string.sub(turns, 1, 1)
--make random numbers random
math.randomseed(io.popen("date +%s%N"):read("*all"))
math.random(); math.random(); math.random()
function Split(str, delim, maxNb)
    -- Eliminate bad cases...
    if string.find(str, delim) == nil then
        return { str }
    end
    if maxNb == nil or maxNb < 1 then
        maxNb = 0    -- No limit
    end
    local result = {}
    local pat = "(.-)" .. delim .. "()"
    local nb = 0
    local lastPos
    for part, pos in string.gmatch(str, pat) do
        nb = nb + 1
        result[nb] = part
        lastPos = pos
        if nb == maxNb then break end
    end
    -- Handle the last field
    if nb ~= maxNb then
        result[nb + 1] = string.sub(str, lastPos)
    end
    return result
end
enemies = Split(turns, " ")
--first turn
if #enemies[1] == 1 then
  print(string.format("S%i",math.random(1,3)))
  os.exit()
end
--kills if possible
for enemy=1,3 do
  if (tonumber(string.sub(enemies[enemy + 1],1,1)) or 0) < 3 and string.sub(enemies[enemy + 1],1,1) ~= "-" then
    print(string.format("S%i",enemy))
    os.exit()
  end
end
--shoots the last person that shot at it
for enemy=1,3 do
  if string.sub(enemies[enemy + 1],#enemies[enemy + 1]-1) == "S0" and tonumber(string.sub(enemies[enemy + 1],1,1)) > 0 then
    print(string.format("S%i",enemy))
    os.exit()
  end
end
--otherwise shoot a random alive person
local aliveEnemies = {}
for enemy=1,3 do
  if string.sub(enemies[enemy + 1],1,1) ~= "-" then
    aliveEnemies[#aliveEnemies+1]=enemy
  end
end
print(string.format("S%i",math.random(1,#aliveEnemies)))

实际上,它将首先带有一个额外的参数来运行;例如lua Sniper.lua 3 "5,S1 3,D3 5,N 5,P"。您可能需要检查arg索引。
2014年

@comperendinous,谢谢,现在解决
waylon531

嗨,@ waylon531,有关Lua的问题:随机种子math.randoms“ math.randomseed(os.time())math.random(); math.random(); math.random()”不足以将脚本?
AndoDaan 2014年

1
AndoDaan,根据lua-users.org/wiki/MathLibraryTutorial,某些操作系统在第一次调用math.random()时总是返回相同的数字。
waylon531 2014年

lua: ./players/Sniper/Sniper.lua:38: attempt to compare nil with number堆栈回溯:./players/Sniper/Sniper.lua:38: in main chunk [C]: in ?
es1024

2

达尔文

适者生存意味着最不健康的人必须死。

基本原理

从星期二(12日)开始的结果来看,似乎有三个不同的分组:幸存者;有效自杀;比没有用还糟。幸存者分享基于射击的简单策略。虽然其他几个机器人(SpockCoward)将针对健康状况最差的敌人,但他们还将其策略与其他行动复杂化。这不是。像Simple Shooter一样,它具有清晰的目标定义,并坚持不懈地坚持下去。看看它适合结果的位置会很有趣。

#!/usr/bin/env python

import sys
import random

## ==== Player Model ================================================ ##
class Player:
    def __init__ (self, number, health):
        self.number = number
        self.health = health

def player_from (number, player_string):
    x = player_string.split (",")
    health = int (x[0].strip ())

    return Player (number, health)

def players_from (game_state):
    return [player_from (n, p) for (n, p) in
                                   zip (range(4), game_state.split ())]

def is_alive (player):
    return 0 < player.health

def i_am_dead (me):
    return not is_alive (me)

def players_who_can_breathe (players):
    return [p for p in players if is_alive (p)]

def players_by_health (players):
    return sorted (players, key=lambda p: p.health)

def least_healthy_players (players):
    sorted_living_players = \
        players_by_health (players_who_can_breathe (players))
    lowest_living_health = sorted_living_players[0].health
    return [p for p in players if lowest_living_health == p.health]
## ================================================ Player Model ==== ##

## ==== Actions ===================================================== ##
def shoot_randomly_at (possible_targets):
    chosen_target = random.choice (possible_targets)
    return "S{0}".format (chosen_target.number)

def do_nothing ():
    return "N"

def pick_move (game_state):
    players = players_from (game_state)
    me = players[0]
    enemies = players[1:]

    if i_am_dead (me):
        return do_nothing ()

    least_healthy_enemies = least_healthy_players (enemies)
    return shoot_randomly_at (least_healthy_enemies)
## ===================================================== Actions ==== ##

if "__main__" == __name__:

    game_state = sys.argv[2]
    print (pick_move (game_state))

这是我较早的二十四和半世纪的简化版本,并进行了一些修改:

python darwin.py 3 "5 5 5 5"

2

Zaenille-C

优先事项:

  1. 如果左1对1则进行拍摄
  2. 射击掷弹兵
  3. 躲闪
  4. 没什么(只是让一些人困惑)

用编译gcc <filename.c>

用运行./a.out <parameters>

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
    char* input = argv[2];
    int enemyCount=1;
    int aliveCount=0;
    int aliveEnemy=0;

    //default
    char action = 'N';
    int target = NULL;

    const char delim[1] = " ";
    char *token;

    //first turn
    if(strcmp(input,"5 5 5 5")==0){
        printf("D1");
        return 0;
    }

    token = strtok(input, delim);
    token = strtok(NULL, delim); //skip to the first enemy

    while(token != NULL){
        //if someone is alive :
        if(strstr(token,"-")==NULL && token[0]!='0'){
            aliveCount++;
            aliveEnemy=enemyCount;
            //if that person did nothing this turn, take it as a tip that he will shoot next turn, and dodge
            if(strstr(token, "N")!=NULL){
                action = 'D';
                target=enemyCount;
            }

            //if that person prepared a grenade, shoot him down
            if(strstr(token, "P")!=NULL){
                action = 'S';
                target=enemyCount;
            }
        }

        token = strtok(NULL, delim);
        enemyCount++;
    }

    //if there is 1 enemy left, shoot him down
    if(aliveCount==1){
        action='S';
        target=aliveEnemy;
    }

    printf(action=='N'?"N":"%c%d",action,target);

    return 0;
}

1
如果问题中给出的示例不符合要求,则第一个(整数)参数不表示舍入计数。你不会想搬起石头砸自己的第一圈就因为你会被分配到防区数82
comperendinous

真?D:谢谢@comperendinous。将编辑代码。
2014年

2

输入分析仪

诸如此类游戏的关键是分析所有对手的比赛方式并做出相应的反应。我的机器人将使用复杂的算法来做到这一点,这将导致使用我的对手变成我的优势,从而获得决定性的胜利!

编辑:我现在

  1. 闪避任何有实弹的玩家
  2. 不会再尝试推翻/投掷/躲闪自己。

import System.Environment   
import Data.Char (ord)
import Data.List.Split

main = do 
    args <- getArgs
    let secondArg = (last args)
    let opt = (argCount secondArg 0)
    let list = (splitOn " " secondArg)
    let enemysToCheck = [1,2,3]
    let target = (avoidShootingSelf (findTarget (last args) 0 0 0 0))
    putStrLn (decide list enemysToCheck opt target)

argCount :: String -> Int -> Int
argCount (s:str) i
    |(length str) == 0 = i `mod` 4
    | otherwise = (argCount str (i + (ord s)))

--myPseudo takes number 0-3, and a possible target and translates it to a command 
myPseudo :: Int -> Int -> String
myPseudo 0 b = "S" ++ (show b)
myPseudo 1 b = "D" ++ (show b)
myPseudo 2 b = "P"
myPseudo 3 b = "T" ++ (show b)

decide :: [String] -> [Int] -> Int -> Int -> String
decide [] [] a b = (myPseudo a b)
decide (x:xs) [] a b = (myPseudo a b)
decide xs (y:ys) a b
    | (liveGrenade z 0) == True = "D" ++ (show y)
    | otherwise = (decide xs ys a b)
    where z = xs!!y

--checks if a player has a live grenade
liveGrenade :: String -> Int -> Bool
liveGrenade [] a = a > 0
liveGrenade (s:str) a
    | s == 'T' = (liveGrenade str (a - 1))
    | s == 'P' = (liveGrenade str (a + 1))
    | otherwise = (liveGrenade str a)

--findTarget picks a target by doing some irrelevant string processing on the 2nd argument
findTarget :: String -> Int -> Int -> Int -> Int -> Int
findTarget [] a b c d = ((maximum [a,b,c,d]) `mod` 4)
findTarget (s:str) a b c d
    | s == 'S' = (findTarget str (a + 1) b c d)
    | s == 'D' = (findTarget str a (b + 1) c d)
    | s == 'P' = (findTarget str a b (c + 1) d)
    | s == 'T' = (findTarget str a b c (d + 1))
    | s == 'N' = (findTarget str a b c (d + 1))
    | otherwise = (findTarget str a b c d)

--Makes sure I do target myself takes int 0-3
avoidShootingSelf :: Int -> Int
avoidShootingSelf 0 = 1
avoidShootingSelf a = a

使用以下命令编译bot(需要ghc)

ghc --make InputAnalyzer.hs

要运行的Shell命令应为以下内容

./InputAnalyzer

注意:我已经在Windows上进行了测试,因此,如果您在编译/运行方面遇到任何麻烦,请在注释中说出这一点,我将尽最大努力找出正确的命令。


1
好吧,我想这是在Haskell中获得加权伪随机数生成器的一种方法。
2014年

2

狗叫勇气

第一件事-射杀坏人。然后随机闪躲,直到有人准备手榴弹。然后,当所有人向他开枪时,准备我自己的手榴弹,然后将其扔给任何人。但是分心的人。

编辑:现在实现了我认为应该的。之前的分数是:35.9

更新:有时射击而不是躲闪

勇气狗

import sys
from collections import defaultdict as ddict
from random import choice
args = sys.argv
info = " ".join(args[2:]).strip('"').split(" ")
players = ddict(dict)
for i,s in enumerate(info):
    parts = s.split(",")
    players[i]["health"]=int(parts[0])
    players[i]["last"]=parts[-1]
    players[i]["history"]=parts[1:]
    players[i]["turn"]=len(parts)
me=0
others=[1,2,3]
turn=players[me]["turn"]
alive = filter(lambda p:players[p]["health"]>0,others)
def act():
    if turn is 1:
        return "S%d" % choice(alive)
    if "P" == players[me]["history"][-1]:
        targets = set(alive)
        for i in alive:
            if "P" == players[i]["history"][-2]:
                targets.remove(i)
        return "T%d" % choice(list(targets))
    for i in others:
        if players[i]["history"][-1] is "P":
            return "P"
    if choice([True,False,False]):
        return "S%d" % choice(alive)
    return "D%d" % choice(alive)
print act()

运行为

python couragethedog.py

2

MAD-Java

MAD机器人相信通过相互保证破坏的威吓力量。每当他没有准备好的手榴弹时,他都会准备一个。然后他躲开可能的枪手,直到有人试图对他造成伤害或他的手榴弹即将爆炸。从他受到攻击的那一刻起,他就向在这场比赛中试图对他造成更多伤害的人投掷手榴弹。如果他的手榴弹即将爆炸,他会炸弹领先的玩家。当没有东西躲闪或直接向手榴弹扔去并且他的手榴弹至少还可以转一圈时,MAD不反对对某人开枪。

    import java.util.ArrayList;
import java.util.Random;

public class MAD 
{
    public static void main(String[] args) 
    {
        if(args.length < 2)
        {
            return; // nothing to do here
        }
        String[] players = args[1].split(" ");
        if(players.length < 4 || !isAlive(players[0]))
        {
            return; // nothing to do here
        }
        Random rand = new Random();

        int grenadeExplodes = grenadeExplodes(players[0]);        
        if(grenadeExplodes==-1)
        {
            System.out.print("P"); // I don't feel safe without a prepared grenade in my hand
            return;
        }

        int highestDamage = -1;
        int playerToShoot = -1;        
        for(int i=1; i<4; i++) // did anyone try to hit me?
        {
            int damage = damageAttempted(players[i], 0);
            if(isAlive(players[i]) && (damage>highestDamage || (damage==highestDamage && rand.nextDouble()>0.5)))
            {
                highestDamage = damage;
                playerToShoot = i;
            }           
        }

        if(highestDamage > 0)
        {
            System.out.print("T" + Integer.toString(playerToShoot)); // don't tell me I didn't warn you
            return;
        }

        int highestHealth = -1;
        int healthiestPlayer = -1;      
        for(int i=1; i<4; i++) // who is doing too well for their own good?
        {
            int health = getHealth(players[i]);
            if(health>highestHealth || (health==highestHealth && rand.nextDouble()>0.5))
            {
                highestHealth = health;
                healthiestPlayer = i;
            }
        }

        if(grenadeExplodes==0)
        {
            System.out.print("T" + Integer.toString(healthiestPlayer).charAt(0)); // get this hot head outta here!!
            return;
        }

        // I've got time to flaunt my grenade around

        ArrayList<Integer> playersToDodge = new ArrayList<Integer>();       
        for(int i=1; i<4; i++) // lets see who could shoot me
        {
            if(canMove(players[i]) && grenadeExplodes(players[i])!=0)
            {
                playersToDodge.add(i);
                if(grenadeExplodes(players[i])==-1) // players who have no grenade are more likely to shoot
                {
                    playersToDodge.add(i);
                }
            }
        }

        if(playersToDodge.size()>0)
        {
            System.out.print("D" + Integer.toString(playersToDodge.get(rand.nextInt(playersToDodge.size() - 1))).charAt(0)); // what do we say to would-be gunners?
            return;
        }

        if(grenadeExplodes!=1)
        {
            System.out.print("S" + Integer.toString(healthiestPlayer).charAt(0)); // seems like I can take a free shot at someone
        }
        else
        {
            System.out.print("N"); // wouldn't want to end up with an exploding grenade in my hand while being unable to throw it.
        }

    }

    public static boolean isAlive(String player) 
    {
        return player.charAt(0)!='-'; 
    }

    public static boolean canMove(String player)
    {
        return isAlive(player) && player.charAt(player.length()-2)!='S';
    }

    public static int grenadeExplodes(String player)
    {
        String[] actions = player.split(",");

        if(actions.length>3 && actions[actions.length - 3].charAt(0)=='P' 
            && actions[actions.length - 2].charAt(0)=='T' 
            && actions[actions.length - 1].charAt(0)=='P')
        {
            return 0;
        } 
        else if(actions.length>2 && actions[actions.length - 2].charAt(0)=='P' 
            && actions[actions.length - 1].charAt(0)=='T')
        {
            return 1;
        } 
        else if(actions.length>1 && actions[actions.length - 1].charAt(0)=='P')
        {
            return 2;
        }
        else
        {
            return -1;
        }
    }

    public static int damageAttempted(String player, int target)
    {
        String[] actions = player.split(",");
        int damage = 0;
        char targetChar = Integer.toString(target).charAt(0);
        for(int i=0; i<actions.length; i++)
        {
            if(actions[i].charAt(0)=='S' && actions[i].charAt(1)==targetChar)
            {
                damage += 2;
            } 
            else if (actions[i].charAt(0)=='T')
            {
                if(actions[i].charAt(1)==targetChar)
                {
                    damage += 8;
                }
                else
                {
                    damage += 3;
                }
            }
        }

        return damage;
    }

    public static int getHealth(String player)
    {
        return Integer.parseInt(player.split(",")[0]);
    }
}

这个机器人可能表现不佳,但是我还是很喜欢这个主意。如果使用更智能的机器人来记录其他机器人的行为,并且在4个机器人之间进行更多匹配,则MAD可能会在现场做得更好。


值得一提的是Geobits,我偷了他Neo入门的一些样板代码。
overactor 2014年

您并不需要花很多,也不需要学分:)
Geobits

呼叫java MAD 43 "5 5 5 5"似乎什么也不输出。
es1024

2

虐待狂

蟒蛇

他的首要任务是造成疼痛和手榴弹伤害。他拉第一弯。当你无法进攻时,他喜欢杀人。他通过躲避和拉扯以延长统治时间来与SSS(单个简单射手)玩耍。他甚至选择先攻击对任何人都无所作为的人。

因为他使用手榴弹,所以他(以及其他所有人)通常无法在第二轮或第三轮中幸存下来。如果他与另一个手榴弹配对,每个人都会死亡。这意味着我并不期望赢得胜利,但是我写这篇文章是为了学习python(以前从未使用过,我正试图介绍一堆新语言)。还有其他几个“拉第一”,所以如果您觉得它太过类似,请告诉我。然而,其他人似乎并不愿意拉然后躲避。

import sys    

def ident(thatguy):

    return int(thatguy.split(",")[0])

def health(thatguy):
    return int(thatguy.split(",")[1])

def shooter(thatguy):
    if(len(thatguy.split(","))<3):
        return 1==1
    else: return thatguy.split(",")[2][0]=="S"

def mosthealth(group):
    bigbad=group[0]
    for foe in group:
        if (health(foe)>health(bigbad)): bigbad=foe
    return bigbad

def igotanuke(mine):
    return mine.count("P")-mine.count("T")>0

def guytonuke(allguys,fighters):
    backup=allguys[:]
    for Aguy in backup:
        if(health(Aguy)<4):
            allguys.remove(Aguy)
            if (shooter(Aguy)): fighters.remove(Aguy)

    if(len(allguys)==0): return mosthealth(backup)
    if (len(allguys)==len(fighters)):
        return mosthealth(allguys)
    else:
        for fighter in fighters: allguys.remove(fighter)
        return mosthealth(allguys)

raw = sys.argv[2]
player = raw.split(" ")
thisisme=player.pop(0)
turn = len(player[0].split(","))-1

guys=[]
gunners=[]
c=1
for dude in player:
    dude=str(c)+","+dude
    c+=1
    if (health(dude)>0): 
        guys.append(dude)
        if (shooter(dude)):
            gunners.append(dude)

if (turn==0): print "P"
elif(turn==49): print"S0"
elif(igotanuke(thisisme))&( turn % 2 == 1): print "T"+str(ident(guytonuke(guys,gunners)))
elif(len(guys)<2)&(len(gunners)>0) & (turn % 2 == 1): print P
elif(turn % 2 == 0) & (len(gunners)>0): print "D"+str(ident(mosthealth(gunners)))
elif(turn % 2 == 1) & (len(gunners)>0): print "S"+str(ident(mosthealth(gunners)))
else: print "S"+str(ident(mosthealth(guys)))

我认为那不会raw_input起作用。sys.argv[2]似乎是Python条目的共识。您可能还会发现for的用途pop,这将使您凝结thisisme=player[0];player.remove(player[0])为简单的事物thisisme=player.pop(0)
2014年

@comperendinous我正在Ideone上测试代码,并且sys.argv根本不起作用(可能是由于导入sys)。这就是为什么我使用raw_input的原因。有什么区别会导致后者不起作用?如果是这样,我可能需要为python找到另一个在线编译器。感谢您对pop的建议!我没有意识到该命令允许指定索引。我将在以后的任何python代码中使用它。
kaine 2014年

1
raw_input从中拉出STDIN,但播放器历史记录作为命令行参数传递到您的程序,这就是您需要的原因sys.argv。为了进行测试,您可以使用手动进行设置sys.argv = ["sadist.py", "0", "5 5 5 5"]。然后,您应该可以致电player=sys.argv[2].split()。如果sys确实无法导入,那么为了进行测试,您甚至可以删除点并调用array sysargv。只要其他所有操作都可行,并且您可以返回sys.argv提交,就可以了。
2014年

@comperendinous确认,如果我调用sys.argv,它将以0形式返回程序名称,以1形式返回单个数字,以2形式返回实际部分?它们都是字符串。有了这些信息,我应该能够正确地对其进行编辑。非常感谢你!
kaine 2014年
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.