石头,石头,剪刀,蜥蜴,史诗般的斯波克比赛


98

最新排行榜@ 2014-08-02 12:00

| Pos # | Author               | Name                    | Language   | Score | Win   | Draw  | Loss  | Avg. Dec. Time |
+-------+----------------------+-------------------------+------------+-------+-------+-------+-------+----------------+
| 1st   | Emil                 | Pony                    | Python2    | 064   | 064   | 000   | 005   | 0026.87 ms     |
| 2nd   | Roy van Rijn         | Gazzr                   | Java       | 062   | 062   | 001   | 006   | 0067.30 ms     |
| 2nd   | Emil                 | Dienstag                | Python2    | 062   | 062   | 001   | 006   | 0022.19 ms     |
| 4th   | ovenror              | TobiasFuenke            | Python2    | 061   | 061   | 001   | 007   | 0026.89 ms     |
| 5th   | PhiNotPi             | BayesianBot             | Perl       | 060   | 060   | 000   | 009   | 0009.27 ms     |
| 6th   | Claudiu              | SuperMarkov             | Python2    | 058   | 058   | 001   | 010   | 0026.77 ms     |
| 7th   | histocrat            | Alternator              | Ruby       | 057   | 057   | 001   | 011   | 0038.53 ms     |
| 8th   | histocrat            | LeonardShelby           | Ruby       | 053   | 053   | 000   | 016   | 0038.55 ms     |
| 9th   | Stretch Maniac       | SmarterBot              | Java       | 051   | 051   | 002   | 016   | 0070.02 ms     |
| 9th   | Martin Büttner       | Markov                  | Ruby       | 051   | 051   | 003   | 015   | 0038.45 ms     |
| 11th  | histocrat            | BartBot                 | Ruby       | 049   | 049   | 001   | 019   | 0038.54 ms     |
| 11th  | kaine                | ExcitingishBot          | Java       | 049   | 049   | 001   | 019   | 0065.87 ms     |
| 13th  | Thaylon              | UniformBot              | Ruby       | 047   | 047   | 001   | 021   | 0038.61 ms     |
| 14th  | Carlos Martinez      | EasyGame                | Java       | 046   | 046   | 002   | 021   | 0066.44 ms     |
| 15th  | Stretch Maniac       | SmartBot                | Java       | 045   | 045   | 001   | 023   | 0068.65 ms     |
| 16th  | Docopoper            | RoboticOboeBotOboeTuner | Python2    | 044   | 044   | 000   | 025   | 0156.55 ms     |
| 17th  | Qwix                 | Analyst                 | Java       | 043   | 043   | 001   | 025   | 0069.06 ms     |
| 18th  | histocrat            | Analogizer              | Ruby       | 042   | 042   | 000   | 027   | 0038.58 ms     |
| 18th  | Thaylon              | Naan                    | Ruby       | 042   | 042   | 004   | 023   | 0038.48 ms     |
| 20th  | Thaylon              | NitPicker               | Ruby       | 041   | 041   | 000   | 028   | 0046.21 ms     |
| 20th  | bitpwner             | AlgorithmBot            | Python2    | 041   | 041   | 001   | 027   | 0025.34 ms     |
| 22nd  | histocrat            | WereVulcan              | Ruby       | 040   | 040   | 003   | 026   | 0038.41 ms     |
| 22nd  | Ourous               | QQ                      | Cobra      | 040   | 040   | 003   | 026   | 0089.33 ms     |
| 24th  | Stranjyr             | RelaxedBot              | Python2    | 039   | 039   | 001   | 029   | 0025.40 ms     |
| 25th  | JoshDM               | SelfLoathingBot         | Java       | 038   | 038   | 001   | 030   | 0068.75 ms     |
| 25th  | Ourous               | Q                       | Cobra      | 038   | 038   | 001   | 030   | 0094.04 ms     |
| 25th  | Ourous               | DejaQ                   | Cobra      | 038   | 038   | 001   | 030   | 0078.31 ms     |
| 28th  | Luis Mars            | Botzinga                | Java       | 037   | 037   | 002   | 030   | 0066.36 ms     |
| 29th  | kaine                | BoringBot               | Java       | 035   | 035   | 000   | 034   | 0066.16 ms     |
| 29th  | Docopoper            | OboeBeater              | Python2    | 035   | 035   | 002   | 032   | 0021.92 ms     |
| 29th  | Thaylon              | NaanViolence            | Ruby       | 035   | 035   | 003   | 031   | 0038.46 ms     |
| 32nd  | Martin Büttner       | SlowLizard              | Ruby       | 034   | 034   | 004   | 031   | 0038.32 ms     |
| 33rd  | Kyle Kanos           | ViolentBot              | Python3    | 033   | 033   | 001   | 035   | 0032.42 ms     |
| 34th  | HuddleWolf           | HuddleWolfTheConqueror  | .NET       | 032   | 032   | 001   | 036   | 0029.86 ms     |
| 34th  | Milo                 | DogeBotv2               | Java       | 032   | 032   | 000   | 037   | 0066.74 ms     |
| 34th  | Timmy                | DynamicBot              | Python3    | 032   | 032   | 001   | 036   | 0036.81 ms     |
| 34th  | mccannf              | YAARBot                 | JS         | 032   | 032   | 002   | 035   | 0100.12 ms     |
| 38th  | Stranjyr             | ToddlerProof            | Java       | 031   | 031   | 010   | 028   | 0066.10 ms     |
| 38th  | NonFunctional User2..| IHaveNoIdeaWhatImDoing  | Lisp       | 031   | 031   | 002   | 036   | 0036.26 ms     |
| 38th  | john smith           | RAMBOBot                | PHP        | 031   | 031   | 002   | 036   | 0014.53 ms     |
| 41st  | EoinC                | SimpleRandomBot         | .NET       | 030   | 030   | 005   | 034   | 0015.68 ms     |
| 41st  | Martin Büttner       | FairBot                 | Ruby       | 030   | 030   | 006   | 033   | 0038.23 ms     |
| 41st  | Docopoper            | OboeOboeBeater          | Python2    | 030   | 030   | 006   | 033   | 0021.93 ms     |
| 44th  | undergroundmonorail  | TheGamblersBrother      | Python2    | 029   | 029   | 000   | 040   | 0025.55 ms     |
| 45th  | DrJPepper            | MonadBot                | Haskel     | 028   | 028   | 002   | 039   | 0008.23 ms     |
| 46th  | Josef E.             | OneBehind               | Java       | 027   | 027   | 007   | 035   | 0065.87 ms     |
| 47th  | Ourous               | GitGudBot               | Cobra      | 025   | 025   | 001   | 043   | 0053.35 ms     |
| 48th  | ProgramFOX           | Echo                    | .NET       | 024   | 024   | 004   | 041   | 0014.81 ms     |
| 48th  | JoshDM               | SelfHatingBot           | Java       | 024   | 024   | 005   | 040   | 0068.88 ms     |
| 48th  | Trimsty              | Herpetologist           | Python3    | 024   | 024   | 002   | 043   | 0036.93 ms     |
| 51st  | Milo                 | DogeBot                 | Java       | 022   | 022   | 001   | 046   | 0067.86 ms     |
| 51st  | William Barbosa      | StarWarsFan             | Ruby       | 022   | 022   | 002   | 045   | 0038.48 ms     |
| 51st  | Martin Büttner       | ConservativeBot         | Ruby       | 022   | 022   | 001   | 046   | 0038.25 ms     |
| 51st  | killmous             | MAWBRBot                | Perl       | 022   | 022   | 000   | 047   | 0016.30 ms     |
| 55th  | Mikey Mouse          | LizardsRule             | .NET       | 020   | 020   | 007   | 042   | 0015.10 ms     |
| 55th  | ja72                 | BlindForesight          | .NET       | 020   | 020   | 001   | 048   | 0024.05 ms     |
| 57th  | robotik              | Evolver                 | Lua        | 019   | 019   | 001   | 049   | 0008.19 ms     |
| 58th  | Kyle Kanos           | LexicographicBot        | Python3    | 018   | 018   | 003   | 048   | 0036.93 ms     |
| 58th  | William Barbosa      | BarneyStinson           | Lua        | 018   | 018   | 005   | 046   | 0005.11 ms     |
| 60th  | Dr R Dizzle          | BartSimpson             | Ruby       | 017   | 017   | 001   | 051   | 0038.22 ms     |
| 60th  | jmite                | IocainePowder           | Ruby       | 017   | 017   | 003   | 049   | 0038.50 ms     |
| 60th  | ArcticanAudio        | SpockOrRock             | PHP        | 017   | 017   | 001   | 051   | 0014.19 ms     |
| 60th  | Dr R Dizzle          | BetterLisaSimpson       | Ruby       | 017   | 017   | 000   | 052   | 0038.23 ms     |
| 64th  | Dr R Dizzle          | LisaSimpson             | Ruby       | 016   | 016   | 002   | 051   | 0038.29 ms     |
| 65th  | Martin Büttner       | Vulcan                  | Ruby       | 015   | 015   | 001   | 053   | 0038.26 ms     |
| 65th  | Dr R Dizzle          | Khaleesi                | Ruby       | 015   | 015   | 005   | 049   | 0038.29 ms     |
| 67th  | Dr R Dizzle          | EdwardScissorHands      | Ruby       | 014   | 014   | 002   | 053   | 0038.21 ms     |
| 67th  | undergroundmonorail  | TheGambler              | Python2    | 014   | 014   | 002   | 053   | 0025.47 ms     |
| 69th  | cipher               | LemmingBot              | Python2    | 011   | 011   | 002   | 056   | 0025.29 ms     |
| 70th  | Docopoper            | ConcessionBot           | Python2    | 007   | 007   | 000   | 062   | 0141.31 ms     |
+-------+----------------------+-------------------------+------------+-------+-------+-------+-------+----------------+
Total Players: 70
Total Matches Completed: 2415
Total Tourney Time: 06:00:51.6877573

比赛笔记

排除的机器人

  • BashRocksBot-使用.net执行cygwin bash脚本仍然不高兴
  • CounterPreferenceBot-等待错误修复
  • RandomlyWeighted-等待错误修复
  • CasinoShakespeare-排除在外,因为它需要有效的互联网连接

原始发布的问题

您已转入您的朋友屋,进行史上最史诗般的对决,包括摇滚,纸艺,剪刀,蜥蜴,史波克。按照真正的BigBang书呆子风格,没有人玩自己的游戏,而是创建了控制台机器人来代表他们玩。您拔出USB密钥并将其移交给征服者Sheldor,以包括在对决中。竹enny发呆。也许霍华德发呆了。我们不在伦纳德的公寓里判断。

规则

适用标准岩石,纸张,剪刀,蜥蜴,Spock规则。

  • 剪刀剪纸
  • 纸盖岩石
  • 岩石粉碎蜥蜴
  • 蜥蜴毒害了斯波克
  • Spock粉碎剪刀
  • 剪刀斩首蜥蜴
  • 蜥蜴吃纸
  • 纸反驳Spock
  • Spock使岩石蒸发
  • 岩石压碎剪刀

RPSLV规则

每个玩家的机器人将在比赛中与彼此的机器人进行一场比赛。

每场比赛将包括RPSLV游戏的100次迭代。

每场比赛后,获胜者是赢得了100场游戏/手最多的玩家。

如果您赢了一场比赛,您将在联赛表中获得1分。在平局的情况下,任何玩家都不会获得积分。

机器人要求

您的漫游器必须可从命令行运行。

Sheldor的* nix盒坏了,所以我们要从他的Windows 8游戏笔记本电脑上运行它,因此请确保您提供的解决方案可以在Windows上运行。Sheldor主动提供了安装任何必需的运行时(在合理的范围内)的能力,以便能够运行您的解决方案。(.NET,Java,Php,Python,Ruby,Powershell ...)

输入项

在每场比赛的第一个游戏中,没有参数提供给您的机器人。在每场比赛的随后各场比赛中:-Arg1将包含您在这场比赛中的机器人手/决定的历史记录。-Arg2将包含这场比赛中对手的手牌/决定的历史记录。

历史记录将由一系列大写字母表示,表示您可以玩的手。

 | R | Rock     |
 | P | Paper    |
 | S | Scissors |
 | L | Lizard   |
 | V | Spock    |

例如

  • 游戏1:MyBot.exe
  • 游戏2:MyBot.exe SV
  • 游戏3:MyBot.exe SS VL
  • 游戏4:MyBot.exe SSR VLS

输出量

您的机器人必须为每个游戏编写一个代表其“手”的单个角色响应。结果应写入STDOUT,然后机器人应退出。有效的大写字母如下。

 | R | Rock     |
 | P | Paper    |
 | S | Scissors |
 | L | Lizard   |
 | V | Spock    |

如果您的漫游器没有返回有效的手牌(即上述5个大写字母中的1个大写字母),那么您将自动没收该手牌,比赛将继续进行。

如果两个机器人都没有交出有效的一手牌,则该游戏被视为平局,比赛继续进行。

匹配格式

每个提交的机器人将在锦标赛中与其他机器人进行一场比赛。

每场比赛将持续100场比赛。

比赛将以匿名方式进行,您不会对正在使用的特定机器人有深入的了解,但是您可以在当前比赛的历史中使用您可以从他的决策中获得的所有信息来改变针对您的策略对手。您还可以跟踪以前的游戏历史,以建立模式/试探法等...(请参阅以下规则)

在一个游戏中,编排引擎将使您的漫游器和您的对手漫游器相距100毫秒,然后比较结果,以避免在同一语言/运行时发生任何PRNG冲突。(这实际上是在测试期间发生的)。

判断与约束

以征服者谢尔多(Sheldor)为名的谢尔登·库珀(Sheldon Cooper)博士谨提议监督比赛的进行。征服者谢尔登(Sheldor the Conqueror)是一名公正的监督者(主要是)。Sheldor的所有决定均为最终决定。

游戏将以公平适当的方式进行:

  • 您的机器人脚本/程序将存储在业务流程引擎的子文件夹下 Players\[YourBotName]\
  • 您可以使用子文件夹Players\[YourBotName]\data记录当前锦标赛进行中的任何数据或游戏历史。每次锦标赛开始时都会清除数据目录。
  • 您可能无法访问锦标赛中其他玩家的玩家目录
  • 您的漫游器不能具有针对其他特定漫游器行为的特定代码
  • 每个玩家可以提交一个以上的机器人来玩,只要他们不互动或不互相帮助。

编辑-其他约束

  • 关于财产,将不予支持。您的机器人必须使用5个有效手牌之一。我将使用一些随机数据测试锦标赛之外的每个机器人,以确保它们的行为。抛出错误(例如,遗失错误)的所有漫游器都将被排除在锦标赛之外,直到修复了错误为止。
  • 机器人可以是派生的,只要它们的行为精简不同即可。与现有漫游器行为完全相同的漫游器(包括其他语言)将被取消比赛资格
  • 以下已经存在垃圾邮件机器人,因此请不要重新提交
    • 摇滚-巴特·辛普森
    • 纸-LisaSimpson
    • 剪刀-EdwardScissorhands
    • Spock-火神
    • 蜥蜴-Khaleesi
    • 伪随机-SimpleRandomBot和FairBot
    • 伪随机RPS-ConservativeBot
    • 伪随机LV-Barney Stinson
  • 漫游器可能不会呼唤第三方服务或网络资源(或其他任何会大大降低比赛速度/决策时间的东西)。CasinoShakespeare是唯一的例外,因为该机器人是在添加此约束之前提交的。

随着提交的机器人越来越多,Sheldor会尽可能利用锦标赛结果更新此问题。

编排/控制程序

编排程序以及每个bot的源代码都可以在github上找到。

https://github.com/eoincampbell/big-bang-game

提交内容

您的提交应包括

  • 机器人的名字
  • 您的密码
  • 一个命令
    • 从外壳执行您的机器人,例如
    • 红宝石myBot.rb
    • python3 myBot.py
    • 要么
    • 首先编译两者,然后执行它。例如
    • csc.exe MyBot.cs
    • MyBot.exe

样品提交

BotName: SimpleRandomBot
Compile: "C:\Program Files (x86)\MSBuild\12.0\Bin\csc.exe" SimpleRandomBot.cs
Run:     SimpleRandomBot [Arg1] [Arg2]

码:

using System;
public class SimpleRandomBot
{
    public static void Main(string[] args)
    {
        var s = new[] { "R", "P", "S", "L", "V" };
        if (args.Length == 0)
        {
            Console.WriteLine("V"); //always start with spock
            return;
        }
        char[] myPreviousPlays = args[0].ToCharArray();
        char[] oppPreviousPlays = args[1].ToCharArray();
        Random r = new Random();
        int next = r.Next(0, 5);
        Console.WriteLine(s[next]);
    }
}

澄清度

如有任何疑问,请在下面的评论中提问。


7
玩家没收牌局时,历史记录如何?
histocrat

1
我本来打算用一种分析方法全力以赴,但是这里的大多数机器人都很愚蠢,足以击败智能AI。
蓬松的

1
只是因为我从来没有在领先的是任何 KOTH挑战,我参加了,我已经采取了屏幕截图,以作纪念。
Kyle Kanos 2014年

3
我今晚将运行另一个Tourney,并将完整的比赛结果发布在pastebin上...下一批将有450场比赛,但运行起来应该更快一些,因为我已经在控制程序中实现了一些并行化功能
Eoin Campbell

3
如果我没记错的话,编排脚本中似乎存在一个严重的错误:玩家1和2的历史记录总是分别作为第一个和第二个参数传递给机器人,而根据规则,机器人应始终获取它们的规则。首先是自己的历史。现在玩家2正在有效地击败自己。(我有点怀疑,因为我的机器人在每场比赛中都赢得了玩家1的胜利,却输掉了其他比赛的一半。)
Emil

Answers:


26

小马(Python 2)

这是基于我前段时间写的一个剪刀石头布机器人,该机器人是在Udacity在线课程结束时进行编程挑战的。我将其更改为包括Spock和蜥蜴,并进行了一些改进。

该程序有11种不同的简单策略,每种策略有5种变体。它根据它们在上一轮比赛中的表现来从中进行选择。

我删除了一个后备策略,该策略只是随机地与更强的对手对抗。我想这样更有趣。

import sys

# just play Spock for the first two rounds
if len(sys.argv)<2 or len(sys.argv[1])<2: print 'V'; sys.exit()

# initialize and translate moves to numbers for better handling:
my_moves, opp_moves = sys.argv[1], sys.argv[2]
moves = ('R', 'P', 'S', 'V', 'L')   
history = zip([moves.index(i) for i in my_moves],
              [moves.index(i) for i in opp_moves])

# predict possible next moves based on history
def prediction(hist):
    N = len(hist)    

    # find longest match of the preceding moves in the earlier history
    cand_m = cand_o = cand_b = range(N-1)
    for l in xrange(1,min(N, 20)):
        ref = hist[N-l]
        cand_m = ([c for c in cand_m if c>=l and hist[c-l+1][0]==ref[0]]
                  or cand_m[-1:])
        cand_o = ([c for c in cand_o if c>=l and hist[c-l+1][1]==ref[1]]
                  or cand_o[-1:])
        cand_b = ([c for c in cand_b if c>=l and hist[c-l+1]==ref]
                  or cand_b[-1:])

    # analyze which moves were used how often
    freq_m, freq_o = [0]*5, [0]*5
    for m in hist:
        freq_m[m[0]] += 1
        freq_o[m[1]] += 1

    # return predictions
    return ([hist[-i][p] for i in 1,2 for p in 0,1]+   # repeat last moves
            [hist[cand_m[-1]+1][0],     # history matching of my own moves
             hist[cand_o[-1]+1][1],     # history matching of opponent's moves
             hist[cand_b[-1]+1][0],     # history matching of both
             hist[cand_b[-1]+1][1],
             freq_m.index(max(freq_m)), # my most frequent move
             freq_o.index(max(freq_o)), # opponent's most frequent move
             0])                        # good old rock (and friends)


# what would have been predicted in the last rounds?
pred_hist = [prediction(history[:i]) for i in xrange(2,len(history)+1)]

# how would the different predictions have scored?
n_pred = len(pred_hist[0])
scores = [[0]*5 for i in xrange(n_pred)]
for pred, real in zip(pred_hist[:-1], history[2:]):
    for i in xrange(n_pred):
        scores[i][(real[1]-pred[i]+1)%5] += 1
        scores[i][(real[1]-pred[i]+3)%5] += 1
        scores[i][(real[1]-pred[i]+2)%5] -= 1
        scores[i][(real[1]-pred[i]+4)%5] -= 1

# return best counter move
best_scores = [list(max(enumerate(s), key=lambda x: x[1])) for s in scores]
best_scores[-1][1] *= 1.001   # bias towards the simplest strategy    
if best_scores[-1][1]<0.4*len(history): best_scores[-1][1] *= 1.4
strat, (shift, score) = max(enumerate(best_scores), key=lambda x: x[1][1])
print moves[(pred_hist[-1][strat]+shift)%5]

运行方式:

python Pony.py

编辑:在不确定的情况下,我偏向于最简单的策略(即始终采取相同的举动),因此做了微小的更改。这有助于避免尝试在没有任何模式的情况下找到过于复杂的模式,例如在诸如ConservativeBot之类的机器人中。

注意:我试图解释该机器人在我的其他机器人Dienstag中使用的基本历史记录匹配策略。


3
96%的获胜率非常出色。
AndoDaan 2014年

非常好。如果您还没有看到Iocaine Powder,可能会喜欢。
wchargin 2014年

@WChargin,当然。:)当我编写原始代码时,几年前我已经读过有关Iocaine Powder的文章,并且隐约记得了总体思路。因此,Pony的确受到了启发,即使不是很直接。事实证明,它们非常相似。我认为我的策略范围更广,而“碘卡因粉”具有我未包括的聪明水平的元元推理。
艾米尔(Emil)2014年

20

红宝石马尔科夫

查看对手的最后两个动作,并确定可能的(最可能的)跟进动作。如果以前没有选择过组合,他只会使用对手的所有动作(到目前为止)。然后,他收集了所有可能的响应,并选择了一个随机响应。

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0 || (history = ARGV[1]).length < 3
    choices = ['R','P','S','L','V']
else
    markov = Hash.new []
    history.chars.each_cons(3) { |chars| markov[chars[0..1].join] += [chars[2]] }

    choices = []
    likely_moves = markov.key?(history[-2,2]) ? markov[history[-2,2]] : history.chars
    likely_moves.each { |move| choices += responses[move] }
end

puts choices.sample

运行像

markov.rb

然后,我使用此程序来确定下一步将要执行的最可能的动作,然后找出您将要做的事情,最后找到一种方法来击败您将要做的事情,并一次又一次地无限循环地执行整个操作。
杰米2014年

@Jamie你的意思是喜欢这个人吗?codegolf.stackexchange.com/a/35295/8478
马丁·恩德

你猜对了。(评论的时间不够长,无法发布)
Jamie


13

星球大战迷-红宝石

拧你,Spock

puts ['R','P','L','S'].sample

像这样运行:

ruby starwarsfan.rb

已添加至财务总监
伊恩·坎贝尔

您可以通过答案编辑进行回滚-添加它们后,我将在此处发表评论。
伊恩·坎贝尔2014年

为什么选择R和S?:P
cjfaure

@mardavi它是“星球大战”粉丝,因为它不使用Spock。
威廉·巴博萨

啊,你是对的(当然)。我读得太快了,我的错(但幸运的是没有后果)
mardavi 2014年

13

Barney Stinson-卢阿

我只有一条规则:新总是更好。拧旧的Jo Ken Po或任何您称呼的东西。

math.randomseed(os.time())
print(math.random() > 0.5 and "V" or "L")

像这样运行:

lua legenwaitforitdary.lua

8

无聊的机器人(Java)

他假设每个人总是扮演相同的角色,并据此计划。他通常会打领带,尽管其他人都对吗?

public class BoringBot
{
    public static void main(String[] args)
    {
        int Rock=0;
        int Paper=0;
        int Scissors=0;
        int Lizard=0;
        int Spock=0;

        if (args.length == 0)
        {
            System.out.print("P");
            return;
        }

        char[] oppPreviousPlays = args[1].toCharArray();

        for (int j=0; j<oppPreviousPlays.length; j++) {
            switch(oppPreviousPlays[j]){
                case 'R': Rock++; break;
                case 'P': Paper++; break;
                case 'S': Scissors++; break;
                case 'L': Lizard++; break;
                case 'V': Spock++;
            }
        }

        int Best = Math.max(Math.max(Lizard+Scissors-Spock-Paper,
                                     Rock+Spock-Lizard-Scissors),
                            Math.max(Math.max(Paper+Lizard-Spock-Rock,
                                              Paper+Spock-Rock-Scissors),
                                     Rock+Scissors-Paper-Lizard));

        if (Best== Lizard+Scissors-Spock-Paper){
            System.out.print("R"); return;
        } else if (Best== Rock+Spock-Lizard-Scissors){
            System.out.print("P"); return;
        } else if (Best== Paper+Lizard-Spock-Rock){
            System.out.print("S"); return;
        } else if(Best== Paper+Spock-Rock-Scissors){
            System.out.print("L"); return;
        } else {
            System.out.print("V"); return;
        }
    }
}

请注意,如果这是其他人已经在使用的策略,请告诉我,我将删除。感觉就像我还没有看到的显而易见的那种。
kaine 2014年

这是C#吗?你是.length属性是错误的。没有办法max
Eoin Campbell 2014年

@EoinCampbell这是java,我一直在玩这两个程序,显然忘记了哪个命令属于哪个命令。
kaine 2014年

真酷。把它留给我,我会把它包括在内。
伊恩·坎贝尔

还是坏了。运行jre8 - java的BoringBot.java -错误:无法找到或加载主类d:\我的软件开发\大爆炸式的游戏\ BigBang.Orchestrator \ BIN \调试\玩家\ BoringBot \ BoringBot.java -
约恩·坎贝尔

8

IocainePowder,Ruby

在此处输入图片说明

基于此处的RPS策略(从中进行无耻窃取)。该机器人看上去选择了与Markov机器人相同的猜测,但随后假设对手已经猜到它将要选择的内容,并选择了相应的动作来击败该机器人。

请注意,我只是调整了链接策略的基本概念,而没有对其进行详细介绍。

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0 || (history = ARGV[1]).length < 3
    choices = ['R','P','S','L','V']
else
    markov = Hash.new []
    history.chars.each_cons(3) { |chars| markov[chars[0..1].join] += [chars[2]] }

    choices = []
    likely_moves = markov.key?(history[-2,2]) ? markov[history[-2,2]] : history.chars
    likely_moves.each { |move| choices += responses[move] }
end

myChoice = choices.sample 
theirChoice = responses[myChoice].sample
actualChoice = responses[theirChoice].sample
puts actualChoice

运行像

iocaine.rb

5
你一直在用那个词。我认为这并不意味着您认为的意思。
2014年

2
碘卡因粉末的真正力量在于在使用马尔可夫和跳动马尔可夫之间进行切换。它以聪明的马尔可夫开始,但一旦感觉到(开始丢失),便跳入跳动-马尔可夫模式。应该很容易添加。
Roy van Rijn 2014年

啊,聪明!不会撒谎,我只听过Iocaine向我描述的内容,实际上并没有详细地看过它。如果您愿意或提交自己的代码,请随意修改我的代码!
jmite 2014年

8

HuddleWolfTheConqueror-C#

HuddleWolf回来了,比以往任何时候都更好。他将在自己的愚蠢游戏中击败征服者谢尔多。HuddleWolf足够聪明,可以识别和打击垃圾邮件制造者。对于更聪明的对手,HuddleWolf利用他的五年级基本统计知识,并根据对手的比赛历史使用加权掷骰子。

using System;
using System.Collections.Generic;
using System.Linq;

public class HuddleWolfTheConqueror
{

    public static readonly char[] s = new[] { 'R', 'P', 'S', 'L', 'V' };

    public static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine(pickRandom());
            return;
        }

        char[] myPlays = args[0].ToCharArray();
        char[] oppPlays = args[1].ToCharArray();

        char tryPredict = canPredictCounter(oppPlays);
        if (tryPredict != '^')
        {
            Console.WriteLine(tryPredict);
        }
        else
        {
            Console.WriteLine(pickRandom());
        }
        return;
    }


    public static char canPredictCounter(char[] history)
    {
        // don't predict if insufficient data
        if (history.Length < 5)
        {
            return '^';
        }

        // calculate probability of win for each choice
        Dictionary<char, double> dic = getBestProabability(history);

        // get item with highest probability of win
        List<char> maxVals = new List<char>();
        char maxVal = '^';
        double mostFreq = 0;
        foreach (var kvp in dic)
        {
            if (kvp.Value > mostFreq)
            {
                mostFreq = kvp.Value;
            }
        }
        foreach (var kvp in dic)
        {
            if (kvp.Value == mostFreq)
            {
                maxVals.Add(kvp.Key);
            }
        }

        // return error
        if (maxVals.Count == 0)
        {
            return maxVal;
        }

        // if distribution is not uniform, play best play
        if (maxVals.Count <= 3)
        {
            Random r = new Random(Environment.TickCount);
            return maxVals[r.Next(0, maxVals.Count)];
        }

        // if probability is close to uniform, use weighted dice roll
        if (maxVals.Count == 4)
        {
            return weightedRandom(dic);
        }

        // if probability is uniform, use random dice roll
        if (maxVals.Count >= 5)
        {
            return pickRandom();
        }

        // return error
        return '^';
    }

    public static Dictionary<char, double> getBestProabability(char[] history)
    {
        Dictionary<char, double> dic = new Dictionary<char, double>();
        foreach (char c in s)
        {
            dic.Add(c, 0);
        }
        foreach (char c in history)
        {
            if (dic.ContainsKey(c))
            {
                switch(c)
                {
                    case 'R' : 
                        dic['P'] += (1.0/(double)history.Length);
                        dic['V'] += (1.0/(double)history.Length);
                        break;
                    case 'P' : 
                        dic['S'] += (1.0/(double)history.Length);
                        dic['L'] += (1.0/(double)history.Length);
                        break;
                    case 'S' : 
                        dic['V'] += (1.0/(double)history.Length);
                        dic['R'] += (1.0/(double)history.Length);
                        break;
                    case 'L' : 
                        dic['R'] += (1.0/(double)history.Length);
                        dic['S'] += (1.0/(double)history.Length);
                        break;
                    case 'V' : 
                        dic['L'] += (1.0/(double)history.Length);
                        dic['P'] += (1.0/(double)history.Length);
                        break;
                    default : 
                        break;

                }
            }
        }
        return dic;
    }

    public static char weightedRandom(Dictionary<char, double> dic)
    {
        Random r = new Random(Environment.TickCount);
        int next = r.Next(0, 100);
        int curVal = 0;
        foreach (var kvp in dic)
        {
            curVal += (int)(kvp.Value*100);
            if (curVal > next)
            {
                return kvp.Key;
            }
        }
        return '^';
    }

    public static char pickRandom()
    {
        Random r = new Random(Environment.TickCount);
        int next = r.Next(0, 5);
        return s[next];
    }
}

8

幼儿证明

这个相当愚蠢的机器人假定它正在扮演一个会“追逐”其动作的蹒跚学步的孩子,总是试图击败最后抛出的东西。如果该机器人连续数次遭到殴打,它将跳至模式中的新点。它是基于我的策略总是打我的很多弟弟。:)

编辑::更改了跳入随机投掷所需的连胜损失的长度。还修复了随机跳转的主要错误。

另存为ToddlerProof.java,编译,然后运行java ToddlerProof [me] [them]

import java.util.HashMap;
public class ToddlerProof
{
    char[] moves = new char[]{'R', 'P', 'S', 'L', 'V'};
    public static void main(String[] args)
    {
        if(args.length<1) //first Round
        {
            System.out.print('V');//Spock is best
            return;
        }
        else
        {
            String them = args[1];
            String me = args[0];
            int streak = 0;

            HashMap<Character, Character> nextMove = new HashMap<Character, Character>();
            //Next move beats things that beat my last move
            nextMove.put('L', 'V');
            nextMove.put('V', 'S');
            nextMove.put('S', 'P');
            nextMove.put('P', 'R');
            nextMove.put('R', 'L');
            //Check if last round was a tie or the opponent beat me
            int lastResult = winner(me.charAt(me.length()-1), them.charAt(them.length()-1));
            if(lastResult == 0)
            {
                //tie, so they will chase my last throw
                System.out.print(nextMove.get(me.charAt(me.length()-1)));

                return;
            }
            else if(lastResult == 1)
            {
                //I won, so they will chase my last throw
                System.out.print(nextMove.get(me.charAt(me.length()-1)));


                return;
            }

            else{
                //I lost
                //find streak
                for(int i = 0; i<me.length(); i++)
                {
                    int a = winner(me.charAt(i), them.charAt(i));
                    if(a >= 0) streak = 0;
                    else streak++;
                }
                //check lossStreak
                //If the streak is 2, then a rotation will make it even.
                //if it is >2, something bad has happened and I need to adjust.
                if(streak>2)
                {
                    //if they are on to me, do something random-ish
                    int r = (((them.length()+me.length()-1)*13)/7)%4;
                    System.out.print(move[r]);
                    return;
                }
                //otherwise, go on with the plan
                System.out.print(nextMove.get(me.charAt(me.length()-1)));
                return;
            }
        }
    }
    public static int winner(char me, char them)
    {
        //check for tie
        if(me == them) return 0;
        //check if they won
        if(me=='V' && (them == 'L' || them == 'P')) return -1;
        if(me=='S' && (them == 'V' || them == 'R')) return -1;
        if(me=='P' && (them == 'S' || them == 'L')) return -1;
        if(me=='R' && (them == 'P' || them == 'V')) return -1;
        if(me=='L' && (them == 'R' || them == 'S')) return -1;
        //otherwise, I won
        return 1;
    }
}

1
我们应该使用print还是println?...我不确定。
kaine 2014年

嗯 我想两者都可以,但是如果控制程序抓住换行符而不是字符,我会发现println混乱了。感谢您指出这一点,我将编辑代码,以防万一
Stranjyr 2014年

@Stranjyr在您的上一次运行中存在一些错误。它没有轰炸控制程序,但是如果您在历史记录中搜索“ ToddlerProof播放n”,则看起来您的机器人在某些手牌上返回了null,然后自动将其丢掉。示例游戏为“ Echo&ToddlerProof”,在您的机器人开始崩溃之前,Echo玩了“ LVSPRLV”。
伊恩·坎贝尔

@Eion Campbell感谢您提及它。当您从失败的比赛中发布日志时,我已经看到了,我想我已经解决了。它遇到了一个错误,即如果它连续输掉5个以上,而不是跳到随机播放,它只会抛出一个无效值。然后,由于丢失了它,因此它又抛出了另一个无效值。恶性循环。
Stranjyr

凉。现在在控制程序中进行更新。
·坎贝尔

8

巴特·辛普森

“好老的石头!没有其他东西能打败石头!”

puts 'R'

运行为

ruby DoTheBartman.rb

丽莎·辛普森

“可怜的,可预测的巴特。总是选择摇滚。”

puts 'P'

运行为

ruby LisaSimpson.rb

更好的丽莎·辛普森

我对让丽莎变得如此愚蠢感到很沮丧,所以我允许她随机选择两只会击败岩石的手。仍然很愚蠢,但她毕竟是辛普森一家。也许蜡笔卡在了她的大脑里?

puts ['P','V'].sample

运行为

ruby BetterLisaSimpson.rb


@MartinBüttner该死,没注意到。尽管这些程序似乎仍在做不同的事情-至少在这里,Lisa可以通过击败她哥哥的两个不同版本而感到更加优越。
R Dizzle博士2014年

1
Sheldor同意...应该有BartBot和BartSimpson :)
Eoin Campbell

3
我们只有BortBot。
2014年

1
这些将被markov屠杀:)
Cruncher

7

回声

用C#编写。用编译csc Echo.cs。运行像Echo.exe ARG1 ARG2

第一次运行时,Echo采用随机选项。在第一次响后的每次奔跑中,Echo都会重复对手的最新动作。

using System;

namespace Echo
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Random r = new Random();
                string[] options = new string[] { "R", "P", "S", "L", "V" };
                Console.WriteLine(options[r.Next(0, options.Length)]);
            }
            else if (args.Length == 2)
            {
                string opponentHistory = args[1];
                Console.WriteLine(opponentHistory[opponentHistory.Length - 1]);
            }
        }
    }
}

7

火神,红宝石

我的手指粘在一起。

puts 'V'

运行像

ruby vulcan.rb

(我认为这是您背景设置的唯一角色内策略。)


需要回头看这些情节,看看是否有人生来有分叉的舌头。蜥蜴人FTW !!!
伊恩·坎贝尔2014年

3
但这不是大爆炸中的每个人都怎么玩吗?
kaine

2
@anotherguest这就是我的意思,“这是唯一的角色内策略”。
Martin Ender 2014年

6

霸王龙,哥斯拉,巴尼...蜥蜴规则。有时他们遇到麻烦,需要打电话给Spock或扔石头

using System;
public class LizardsRule
{
    public static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine("L");
            return;
        }
        char[] oppPreviousPlays = args[1].ToCharArray();
        var oppLen = oppPreviousPlays.Length;
        if (oppPreviousPlays.Length > 2
            && oppPreviousPlays[oppLen - 1] == 'R'
            && oppPreviousPlays[oppLen - 2] == 'R'
            && oppPreviousPlays[oppLen - 3] == 'R')
        {
            //It's an avalance, someone call Spock
            Console.WriteLine("V");
            return;
        }

        if (oppPreviousPlays.Length > 2
                && oppPreviousPlays[oppLen - 1] == 'S'
                && oppPreviousPlays[oppLen - 2] == 'S'
                && oppPreviousPlays[oppLen - 3] == 'S')
        {
            //Scissors, Drop your tail and pick up a rock
            Console.WriteLine("R");
            return;
        }

        //Unleash the Fury Godzilla
        Console.WriteLine("L");     
    }
}

6

BayesianBot,Perl(现在是v2!)

最重要的是,这是一个独特的程序。在其中,您将看到统计信息和可怕的编程形式的完美融合。此外,该机器人可能违反了贝叶斯统计的许多规则,但名称听起来更酷。

该机器人的核心要素是创建250种不同的预测模型。每个模型的形式为“鉴于我上一回合打了石头,对手两回合打了剪刀,这是我的对手下一动的概率分布。” 每个概率分布都采用多维Dirichlet分布的形式。

每回合,所有适用模型(通常为10个)的预测都将相乘以形成总体预测,然后将其用于确定哪些移动具有最高预期收益。

编辑1:在此版本中,我更改了先前的发行版本,并使该程序丢失时更加随机化。

有些事情可能会有所改进,例如模型的数量(250个仅是3位数字),选择先验分布(当前为Dir(3,3,3,3,3)),以及融合预测的方法。另外,我从来没有费心将任何概率分布归一化,这是可以的,因为我正在将它们相乘。

我没有很高的期望,但是我希望这个机器人能够做得很好。

my ($phist, $ohist) = @ARGV;

my %text2num = ('R',0,'V',1,'P',2,'L',3,'S',4);  #the RVPLS ordering is superior
my @num2text = ('R','V','P','L','S');

@phist = map($text2num{$_},split(//,$phist));
@ohist = map($text2num{$_},split(//,$ohist));

$lowerlimit = 0;
for($lowerlimit..~~@phist-3){$curloc=$_;
 $result = $ohist[$curloc+2];
 @moveset = ($ohist[$curloc],$ohist[$curloc+1],$phist[$curloc],$phist[$curloc+1]);
 for(0..3){$a=$_;
  for(0..$a){$b=$_;
   $predict[$a][$b][$moveset[$a]][$moveset[$b]][$result]++;
  }
 }
}

@recentmoves = ($ohist[-2],$ohist[-1],$phist[-2],$phist[-1]);

@curpred = (1,1,1,1,1);

for(0..3){$a=$_;
 for(0..$a){$b=$_;
  for(0..4){$move=$_;
   $curpred[$move] *= $predict[$a][$b][$recentmoves[$a]][$recentmoves[$b]][$move]/3+1;
  }
 }
}

@bestmove = (0,0,0,0,0);
for(0..4){
 $bestmove[$_] = $curpred[$_]/2+$curpred[$_-1]+$curpred[$_-2];
}

$max = 0;
for(0..4){
 if($bestmove[$_]>$max){
  $max = $bestmove[$_];
 }
}
@options=();
$offset=0;
if(($ohist[-1] - $phist[-1])%5 < 2 && ($ohist[-2] - $phist[-2])%5 < 2 && ($ohist[-3] - $phist[-3])%5 < 2){  #frequentist alert!
 $offset=int(rand(3));
}
for(0..4){
 if($bestmove[$_] == $max){
  push(@options,$num2text[($_+$offset)%5]);
 }
}
$outputb = $options[int(rand(~~@options))];

print "$outputb";

我一直在像这样运行该程序:

perl BayesianBot.plx

5

动态机器人

动态漫游器几乎总是在变化。真的很讨厌重复

import sys, random
choices = ['L','V','S','P','R'] * 20
if len(sys.argv) > 1:
    my_history = sys.argv[1]
    [choices.remove(my_history[-1]) for i in range(15)]
print(choices[random.randrange(len(choices))])

语言:Python 3.4.1

命令:python dynamicbot.py <history>python3 dynamicbot.py <history>取决于您的系统


是的,想到了这一点。
seequ 2014年

5

SmartBot-Java

我在此网站上首次获得任何东西!

虽然不是一个非常有创意的名字...

SmartBot会找到对手和/或自身的动作与上次进行的动作相似的动作序列,并据此进行计划。

name = SmartBot

我想运行它,如果我错了,请纠正我。

java -jar SmartBot.jar

import java.util.ArrayList;
public class SmartBot {
    public static void main(String[] args) {
        if(args.length ==0){
            System.out.print("L");
            return;
        }
        if(args[0].length()<3){
            String[] randLetter = new String[]{"R","P","S","L","V"};
            System.out.print(randLetter[(int) Math.floor(Math.random()*5)]);
            return;
        }
        String myHistory = args[0];
        String otherHistory = args[1];

        double rScore,pScore,sScore,lScore,vScore;//score - highest = highest probability of next opponent move
        rScore = pScore = sScore = lScore = vScore = 0;
        lScore = .001;
        ArrayList<ArrayList<Integer>> moveHits = new ArrayList<ArrayList<Integer>>();
        for(int g = 0;g<2;g++){
            for(int i=1;i<(myHistory.length() / 2) + 1;i++){
                if(g==0){
                    moveHits.add(findAll(myHistory.substring(myHistory.length() - i),myHistory));
                }
                else{
                    moveHits.add(findAll(otherHistory.substring(otherHistory.length() - i),otherHistory));
                }
            }
            for(int i = 0; i < moveHits.size();i++){
                int matchingMoves = i+1;
                ArrayList<Integer> moveIndexes = moveHits.get(i);
                for(Integer index:moveIndexes){
                    if(index+matchingMoves +1<= otherHistory.length()){
                        char nextMove = otherHistory.charAt(index + matchingMoves-1);
                        if(nextMove=='R'){rScore = rScore + matchingMoves;}
                        if(nextMove=='P'){pScore = pScore + matchingMoves;}
                        if(nextMove=='S'){sScore = sScore + matchingMoves;}
                        if(nextMove=='L'){lScore = lScore + matchingMoves;}
                        if(nextMove=='V'){vScore = vScore + matchingMoves;}
                    }
                }
            }
        }
        if(rScore >= pScore && rScore >= sScore && rScore >= lScore && rScore >= vScore){
            System.out.print("V");
            return;
        }
        if(pScore >= rScore && pScore >= sScore && pScore >= lScore && pScore >= vScore){
            System.out.print("L");
            return;
        }
        if(sScore >= pScore && sScore >= rScore && sScore >= lScore && sScore >= vScore){
            System.out.print("R");
            return;
        }
        if(vScore >= pScore && vScore >= sScore && vScore >= lScore && vScore >= rScore){
            System.out.print("L");
            return;
        }
        if(lScore >= pScore && lScore >= sScore && lScore >= rScore && lScore >= vScore){
            System.out.print("S");
        }
        return;
    }
    public static ArrayList<Integer> findAll(String substring,String realString){
        ArrayList<Integer> ocurrences = new ArrayList<Integer>();
        Integer index = realString.indexOf(substring);
        if(index==-1){return ocurrences;}
        ocurrences.add(index+1);
        while(index!=-1){
            index = realString.indexOf(substring,index + 1);
            if(index!=-1){
                ocurrences.add(index+1);
            }
        }
        return ocurrences;
    }
}

它通过类似模式发生的次数为每个可能的下一步动作分配分数。

它稍微偏爱蜥蜴。


我相信,如果您先将其震击,那就可以运行它。如果您只是简单地对其进行编译,则java ABot应该可以工作(请记住,将文件命名为与公共类相同)
贾斯汀

谢谢!作为一个相对较新的程序员,我没有意识到这一点。
舒展疯子2014年

5

SpockOrRock-PHP

SpockOrRock

在现实世界中玩耍时,大多数人会本能地选择剪刀。该机器人选择Spock或Rock击败普通玩家。以前的回合不打扰。

php spockorrock.php

<?php

//Pick either Spock or Rock
if (rand(0,1) == 0)     echo("R\n");
else                    echo("V\n");


?>

4

SlowLizard,Ruby

从蜥蜴开始后,它总是会随机选择一个击败对手先前动作的动作。

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0
  puts 'L'
else
  puts responses[ARGV[1][-1]].sample
end

运行像

ruby slowlizard.rb

4

词典

该漫游器喜欢订购他的字母,因此他将选择比上一轮对手高1的响应-除非对手选择了Vulcan,然后他才随机选择一个响应。

import sys
import random

choices = ["L", "P", "R", "S", "V"]

total = len(sys.argv)
if total==1:
    print("L")
    sys.exit()

opponent = sys.argv[2]
opponent_last = opponent[-1]

if opponent_last == choices[-1]:
    print(random.choice(choices))
else:
    next = choices.index(opponent_last)+1
    print(choices[next])

这预计对手的手将被第二发:

                           me
                            v
python LexicographicBot.py SR RV
                              ^
                            opponent

@MartinBüttner:添加了命令!我一直在忙于工作,试图发表一些东西,因此消失了。
Kyle Kanos 2014年

第一次运行时中断,没有参数。追溯(最近一次通话最近):文件“ LexicographicBot \ LexicographicBot.py”,第10行,在<module>对手= sys.argv [2] IndexError:列表索引超出范围
Eoin Campbell

@EoinCampbell:我在第一次运行时忘记了退出子句,它已经添加并且现在应该可以正常工作。
凯尔·坎诺斯

4

Werevulcan-红宝石

运行为 ruby werevulcan.rb

@rules = {

  'L' => %w[V P],
  'P' => %w[V R],
  'R' => %w[L S],
  'S' => %w[P L],
  'V' => %w[R S]
}

@moves = @rules.keys

def defeats?(move1, move2)
  @rules[move1].include?(move2)
end

def score(move1, move2)
  if move1 == move2
    0
  elsif defeats?(move1, move2)
    1
  else
    -1
  end
end

def move
  player, opponent = ARGV

  # For the first 30 rounds, pick a random move that isn't Spock
  if player.to_s.size < 30
    %w[L P R S].sample
  elsif opponent.chars.to_a.uniq.size < 5
    exploit(opponent)
  else
    # Pick a random move that's biased toward Spock and against lizards
    %w[L P P R R S S V V V].sample
  end

end

def exploit(opponent)
  @moves.shuffle.max_by{ |m| opponent.chars.map{|o| score(m,o) }.reduce(:+) }
end

puts move

狼人在白天看起来很正常,但是当月亮升起时,耳朵变得尖尖,移动变得更加合乎逻辑。


4

类比器-红宝石

用运行ruby analogizer.rb。我已经对代码进行了逻辑修复,但是不知道为什么会有错误。

@rules = {

  'L' => %w[V P],
  'P' => %w[V R],
  'R' => %w[L S],
  'S' => %w[P L],
  'V' => %w[R S]
}

@moves = @rules.keys

def defeats?(move1, move2)
  @rules[move1].include?(move2)
end

def score(move1, move2)
  if move1 == move2
    0
  elsif defeats?(move1, move2)
    1
  else
    -1
  end
end

def move
  player, opponent = ARGV

  case player.to_s.size
  # Throw six lizards in the beginning to confuse opponent
  when 0..5
    'L'
  when 6
    'V'
  when 7
    'S'
  when 8
    'P'
  when 9
    'R'
  else
    analyze_history(player.chars.to_a, opponent.chars.to_a)
  end

end

def analyze_history(player, opponent)
  my_last_move = player.last
  predicted_moves = Hash.new {0}
  opponent_reactions = player.zip(opponent.drop(1))

  # Check whether opponent tended to make a move that would've beaten, lost, or tied my last move
  opponent_reactions.each do |my_move, reaction|
    score = score(reaction, my_move)
    analogous_moves = @moves.select { |move| score == score(move, my_last_move) }
    analogous_moves.each { |move| predicted_moves[move] += 1 }
  end

  # Assume if an opponent has never made a certain move, it never will
  @moves.each { |m| predicted_moves[m] = 0 unless opponent.include?(m) }

  # Pick the move with the best score against opponent's possible moves, weighted by their likelihood, picking randomly for ties
  @moves.shuffle.max_by{ |m| predicted_moves.map { |predicted, freq| score(m, predicted) * freq }.reduce(0,:+) }

end

puts move

假设对方机器人始终对我之前的举动做出反应,或者选择会击败它的东西,可能会失败的东西,或者相同的举动(可能是从一组有限的可能举动中)。然后,在该假设下选择最佳动作。

除了前十个动作是硬编码的:首先我假装自己只知道蜥蜴,然后我假设对手总是扔出一些东西来击败最后扔出的东西,直到我有足够的数据进行适当的分析为止。


4

Java-SelfLoathingBot

BotName: SelfLoathingBot
Compile: Save as 'SelfLoathingBot.java'; compile.
Run:     java SelfLoathingBot [me] [them]

机器人是随机开始的,然后〜33%随机进入,或〜33%的对手在前一场比赛中获胜,选择获胜策略的机会为50%。

import java.util.Random;

public class SelfLoathingBot {

    static final Random RANDOM = new Random();

    private static char randomPlay() {

        switch (RANDOM.nextInt(5)) {

            case 0 : return 'R';

            case 1 : return 'P';

            case 2 : return 'S';

            case 3 : return 'L';

            default : return 'V';
        }
    }

    private static char antiPlay(String priorPlayString) {

        char[] priorPlays = priorPlayString.toCharArray();

        int choice = RANDOM.nextInt(2);

        switch (priorPlays[priorPlays.length - 1]) {

            case 'R' : return choice == 0 ? 'P' : 'V'; 

            case 'P' : return choice == 0 ? 'S' : 'L';

            case 'S' : return choice == 0 ? 'V' : 'R';

            case 'L' : return choice == 0 ? 'R' : 'S';

            default : return choice == 0 ? 'L' : 'P'; // V        
        }
    }

    public static void main(String[] args) {

        int choice = args.length == 0 ? 0 : RANDOM.nextInt(3);

        char play;

        switch (choice) {

            case 1 :

                // 33.3% chance Play myself
                play = antiPlay(args[0]);
                break;

            case 2 :

                // 33.3% chance Play opponent just in case opponent is screwy like that
                play = antiPlay(args[1]);
                break;

            default :

                // 33.3% chance 100% Random
                play = randomPlay();
        }

        System.out.print(play);
        return;
    }
}

4

分析师

分析师会分析一些东西并做一些事情来击败您。

编译javac Analyst.java并运行为java Analyst

import java.util.Random;

public class Analyst{
    public static void main(String[] args){
        char action = 'S';

        try{
            char[] enemyMoves = null, myMoves = null;

            //first move is random
            if(args.length == 0){
                System.out.print(randomMove());
                System.exit(0);
            //moves 2-3 will beat their last move
            }else if(args[0].length() < 8){
                System.out.print(counterFor(args[1].charAt(args[1].length()-1)));
                System.exit(0);
            //following moves will execute some analyzation stuff
            }else{
                //get previous moves
                myMoves = args[0].toCharArray();
                enemyMoves = args[1].toCharArray();
            }

            //test if they're trying to beat our last move
            if(beats(enemyMoves[enemyMoves.length-1], myMoves[myMoves.length-2])){
                action = counterFor(counterFor(myMoves[myMoves.length-1]));
            }
            //test if they're copying our last move
            else if(enemyMoves[enemyMoves.length-1] == myMoves[myMoves.length-2]){
                action = counterFor(myMoves[myMoves.length-1]);
            }
            //else beat whatever they've done the most of
            else{
                action = counterFor(countMost(enemyMoves));
            }

            //if they've beaten us for the first 40 moves, do the opposite of what ive been doing
            if(theyreSmarter(myMoves, enemyMoves)){
                action = counterFor(action);
            }

        //if you break my program do something random
        }catch (Exception e){
            action = randomMove();
        }

        System.out.print(action);
    }

    private static char randomMove(){
        Random rand = new Random(System.currentTimeMillis());
        int randomMove = rand.nextInt(5);

        switch (randomMove){
            case 0: return 'R';
            case 1: return 'P';
            case 2: return 'S';
            case 3: return 'L';
            default: return 'V';
        }
    }

    private static char counterFor(char move){
        Random rand = new Random(System.currentTimeMillis());
        int moveSet = rand.nextInt(2);

        if(moveSet == 0){
            switch (move){
                case 'R': return 'P'; 
                case 'P': return 'S'; 
                case 'S': return 'R'; 
                case 'L': return 'R'; 
                default: return 'P';
            }
        }else{
            switch (move){
                case 'R': return 'V'; 
                case 'P': return 'L'; 
                case 'S': return 'V'; 
                case 'L': return 'S'; 
                default: return 'L';
            }
        }
    }

    private static boolean beats(char move1, char move2){
        if(move1 == 'R'){
            if((move2 == 'S') || (move2 == 'L')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'P'){
            if((move2 == 'R') || (move2 == 'V')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'S'){
            if((move2 == 'L') || (move2 == 'P')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'L'){
            if((move2 == 'P') || (move2 == 'V')){
                return true;
            }else{
                return false;
            }
        }else{
            if((move2 == 'R') || (move2 == 'S')){
                return true;
            }else{
                return false;
            }
        }
    }

    private static char countMost(char[] moves){
        int[] enemyMoveList = {0,0,0,0,0};

        for(int i=0; i<moves.length; i++){
            if(moves[i] == 'R'){
                enemyMoveList[0]++;
            }else if(moves[i] == 'P'){
                enemyMoveList[1]++;
            }else if(moves[i] == 'S'){
                enemyMoveList[2]++;
            }else if(moves[i] == 'L'){
                enemyMoveList[3]++;
            }else if(moves[i] == 'V'){
                enemyMoveList[4]++;
            }
        }

        int max = 0, maxIndex = 0;
        for(int i=0; i<5; i++){
            if(enemyMoveList[i] > max){
                max = enemyMoveList[i];
                maxIndex = i;
            }
        }

        switch (maxIndex){
            case 0: return 'R';
            case 1: return 'P';
            case 2: return 'S';
            case 3: return 'L';
            default: return 'V';
        }
    }

    private static boolean theyreSmarter(char[] myMoves, char[] enemyMoves){
        int loseCounter = 0;

        if(enemyMoves.length >= 40){
            for(int i=0; i<40; i++){
                if(beats(enemyMoves[i],myMoves[i])){
                    loseCounter++;
                }
            }
        }else{
            return false;
        }

        if(loseCounter > 20){
            return true;
        }else{
            return false;
        }
    }
}

4

赌徒-Python 2

import sys
import random

MODE = 1

moves = 'RSLPV'

def element_sums(a, b):
    return [a[i] + b[i] for i in xrange(len(a))]

def move_scores(p):
    def calc(to_beat):
        return ['LDW'.find('DLLWW'[moves.find(m)-moves.find(to_beat)]) for m in moves]

    return dict(zip(moves, element_sums(calc(p[0]), calc(p[1]))))

def move_chooser(my_history, opponent_history):
    predict = sorted(moves, key=opponent_history.count, reverse=MODE)[-2:]
    scores = move_scores(predict)
    return max(scores, key=lambda k:scores[k])

if __name__ == '__main__':
    if len(sys.argv) == 3:
        print move_chooser(*sys.argv[1:])
    elif len(sys.argv) == 1:
        print random.choice(moves)

与名称相反,此程序中唯一使用随机性的时间是在第一轮,没有任何信息。取而代之的是,它以赌徒的谬论来命名,因为人们相信,如果过去很少发生随机事件,那么将来很有可能发生。例如,如果您将公平硬币翻转20次,而前15个为正面,则赌徒的谬论指出,其余翻转为尾的几率会增加。当然,这是不正确的。无论之前的翻转如何,公平硬币出现尾巴的几率始终为50%。

该程序分析对手的历史,找到到目前为止使用最少的2个动作,并假设这次的对手的动作将是这两个动作之一。将2分配给一个获胜,1分配给一个平局,0分配给亏损,它会在这两个预测的移动中找到得分最高的移动并将其抛出。

赌徒兄弟-Python 2

import sys
import random

MODE = 0

moves = 'RSLPV'

def element_sums(a, b):
    return [a[i] + b[i] for i in xrange(len(a))]

def move_scores(p):
    def calc(to_beat):
        return ['LDW'.find('DLLWW'[moves.find(m)-moves.find(to_beat)]) for m in moves]

    return dict(zip(moves, element_sums(calc(p[0]), calc(p[1]))))

def move_chooser(my_history, opponent_history):
    predict = sorted(moves, key=opponent_history.count, reverse=MODE)[-2:]
    scores = move_scores(predict)
    return max(scores, key=lambda k:scores[k])

if __name__ == '__main__':
    if len(sys.argv) == 3:
        print move_chooser(*sys.argv[1:])
    elif len(sys.argv) == 1:
        print random.choice(moves)

通过将MODE变量切换为0,该程序将基于相关的谬误(有时也称为赌徒的谬误)进行操作。它指出,如果过去发生随机事件的频率更高,那么将来更可能发生。例如,如果您掷硬币20次而前15个为正面,则该谬误指出,由于当前存在条纹,其余的翻转更可能是正面。在模式0下,此程序以相同的方式操作,不同之处在于它假定对手将抛出到目前为止最常抛出的两个动作之一。

是的,这两个程序仅相隔一个字符。:)


TheGambler在什么情况下会更改MODE?
R Dizzle博士2014年

@DrRDizzle不是,看起来这是两个机器人合而为一的提交。
圣保罗Ebermann

2
如果您连续损失超过一定次数,如果切换MODE,此程序会不会更有效?
R Dizzle博士2014年

4

Dienstag(Python 2)

我的第一个条目Pony似乎在所有第二个猜测(三重猜想,...)和元推理中都表现不错。但这是否有必要?

因此,这里是小马的小朋友Dienstag,他只有55种策略之一:预测对手的下一步行动并将其击败。

从长远来看,Dienstag会与当前排行榜前十名中的每个Bot取得胜利或并列。除了小马以外。

import sys
if len(sys.argv)<2 or len(sys.argv[1])<2: print 'L'; sys.exit()
hist = [map('RPSVL'.index, p) for p in zip(sys.argv[1], sys.argv[2])]
N = len(hist)
cand = range(N-1)
for l in xrange(1,N):
    cand = ([c for c in cand if c>=l and hist[c-l+1]==hist[-l]] or cand[-1:])
print 'RPSVL'[(hist[cand[-1]+1][1]+(1,3)[N%2==0])%5]

运行方式:

python Dienstag.py

我承认代码有些混乱。如果有人想进一步了解它,我可能会添加一些解释。

编辑:这是一个简短的示例演练,以解释这个想法:

  • 该程序获取其自身的历史以及对手的动作:

    sys.arg[1] = 'LLVLLVL', sys.arg[2] = 'RPSPSSP'

  • 历史记录组合成对,并将移动转换为数字(R = 0,...):

    hist = [[4, 0], [4, 1], [3, 2], [4, 1], [4, 2], [3, 2], [4, 1]]

  • 到目前为止,已进行的回合数已确定:

    N = 7

  • 现在的基本思路是寻找历史较早的最后一步中最长的不间断链。该程序会跟踪此类链在列表中的结束位置cand(“候选”)。在开始时,未经检查,将考虑历史中除最后一个位置以外的所有位置:

    cand = [0, 1, 2, 3, 4, 5]

  • 现在,可能的链的长度逐步增加。对于链长,l = 1它将查找上一个移动对的先前出现的位置[4, 1]。可以在历史记录位置1和找到3。仅这些保留在cand列表中:

    cand = [1, 3]

  • 接下来,l = 2检查第二个倒数第二对在哪个可能的候选项之前[3, 2]。这只是位置的情况3

    cand = [3]

  • 对于l = 3多有一些长的没有以前的链和cand将是空的。在这种情况下,cand将保留的最后一个元素:

    cand = [3]

  • 机器人现在假定历史将重复。该隐最后一次[3, 2], [4, 1]发生,然后是[4, 2]。因此,对手打了2(剪刀),可以被(2+1)%5 = 3(Spock)或(2+3)%5 = 0(rock)打败。该机器人会根据第一个或第二个替代方案(取决于N是奇数还是偶数)引入答案。

  • 在这里3选择移动,然后将其翻译回去:

    print 'V'

注意: Dienstag具有时间复杂度O(N 2),用于在N轮之后返回下一步。小马的时间复杂度为O(N 3)。因此,在这方面,它们可能比大多数其他条目差很多。


请做。对我来说,这是一次很棒的学习经历。我通常生活在C#/ Java领域,所以lua,ruby,python,haskell的疯狂对我来说非常有趣。
伊恩·坎贝尔

我也很想在游戏中添加一个额外的Pony实例。这就像必须在第三次战斗中击败自己的镜子自我,才能达到致命的战斗水平;-)
伊恩·坎贝尔

@EoinCampbell :-)至少直接比赛Pony vs. Pony会是完美的选择。我的两个机器人都没有随机性。
埃米尔(Emil)2014年

3

重击岩石

cygwin作为运行时是否有太多要求?

bashrocks.sh:

#!/bin/bash
HAND=(R P S L V)
RAND=`od -A n -t d -N 1 /dev/urandom | xargs`
echo ${HAND[ $RAND  % 5 ]}

并像这样运行它:

sh bashrocks.sh

5
阅读标题后,我对您除之外的任何操作都感到非常失望R。;)
Martin Ender 2014年

@mccannf。对此有一些问题...我已经安装了cygwin,并使用od.exe,xargs.exe和echo.exe的C:\ Cygwin \ bin完全限定路径修改了脚本。仍然出现以下错误。C:/ Cygwin / bin / xargs:回显:无此类文件或目录%5“)语法错误:预期操作数(错误标记为“
Eoin Campbell

@EoinCampbell-在Windows中创建文件时,可以dos2unix在执行之前在cygwin中的文件上运行吗?
mccannf 2014年

当然。我会尝试的。
伊恩·坎贝尔

我认为问题可能出在/ dev / urandom语句
Eoin Campbell,

3

算法

为了拥有一个的算法。

因为做某事总是感觉更安全,越复杂越好。

尚未进行过认真的数学运算,因此该算法可能没有那么有效。

import random, sys

if __name__ == '__main__':

    # Graph in adjacency matrix here
    graph = {"S":"PL", "P":"VR", "R":"LS", "L":"VP", "V":"SR"}
    try:
        myHistory = sys.argv[1]
        opHistory = sys.argv[2]
        choices = ""

        # Insert some graph stuff here. Newer versions may include advanced Math.
        for v in graph:
            if opHistory[-1] == v:
                for u in graph:
                    if u in graph[v]:
                        choices += graph[u]

        print random.choice(choices + opHistory[-1])

    except:
        print random.choice("RPSLV")

Python 2程序: python algorithm.py


1
该算法的摘要:查看对手的最后玩法,然后随机玩两个对手之一,如果他们再玩一次,将会输给对手的最后一招。因此,对于连续两次不玩相同动作的机器人来说,效果更好。
罗里·奥肯

哈哈。我真的不知道我是否那样做。如果我没有记错的话,那实际上是一种随机选择5种动作中任何一种的复杂方法。;)
矢量化

3

FairBot,Ruby

让我们开始简单。

puts ['R','P','S','L','V'].sample

运行像

ruby fairbot.rb

最后一个“ V”参数的小错字。如果您想更新完整性,请将其修复在我的身边
Eoin Campbell

@EoinCampbell谢谢,固定!
Martin Ender 2014年

1
有趣的是,这与所有策略的获胜机率完全相同。
Cruncher 2014年

3

暴力机器人

该机器人会根据对手的先前选择来选择最暴力的选择:

import sys

choice_dict = {"L" : "S", "P" : "S", "R" : "V", "S" : "V", "V" : "L"}

total = len(sys.argv)
if total==1:
    print("L")
    sys.exit()

opponent = sys.argv[2]
opponent_last = opponent[-1]

print(choice_dict[opponent_last])

运行为

python ViolentBot.py (me) (opp)

无参数中断。追溯(最近一次通话最近):文件“ ViolentBot \ ViolentBot.py”,第9行,在<module>对手= sys.argv [2] IndexError:列表索引超出范围
Eoin Campbell

破坏了参数。追溯(最近一次通话):文件“ ViolentBot \ ViolentBot.py”,第12行,在<module>中打印(choice_dict [opponent_last])KeyError:“ S”
Eoin Campbell,

@EoinCampbell:我为第一次运行添加了exit子句,您现在应该可以运行它了。
凯尔·坎诺斯

3

Haskell-MonadBot

我不知道ghc是否被视为“在合理范围内”,但让我们假设它是。该机器人的策略是对抗其对手最受欢迎的举动。

Compile: ghc monadbot.hs
Run:     ./monadbot [Arg1] [Arg2]

码:

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

main :: IO ()
main = do
  args <- getArgs
  let moves = if not (null args) then args !! 1 else ""
      fave = if not (null moves) then head $ maximumBy (comparing length) (group $ sort moves) else 'V'
  putChar $ case fave of 'R' -> 'P'
                         'P' -> 'S'
                         'S' -> 'R'
                         'L' -> 'R'
                         'V' -> 'P'
                         _   -> 'V'
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.