바위, 종이, 가위, 도마뱀, 스팍 토너먼트


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-cygwin bash 스크립트를 실행하는 .net에는 여전히 기쁨이 없습니다.
  • CounterPreferenceBot-버그 수정 대기 중
  • RandomlyWeighted-버그 수정을 기다리는 중
  • CasinoShakespeare-인터넷 연결이 필요하므로 제외

원래 게시 된 질문

당신은 바위, 종이, 가위, 도마뱀, 스팍의 가장 서사시 대결 전투를 위해 친구 집으로 돌아 왔습니다. 진정한 BigBang 괴상한 스타일에서는 어떤 선수도 스스로 경기를하지 않지만 대신 콘솔 봇을 만들어 냈습니다. USB 키를 꺼내서 정복자 에게 넘겨 대결에 포함시킵니다. 페니 스 oon. 또는 하워드가 기절했을 수도 있습니다. 우리는 여기 레너드의 아파트에서 판단하지 않습니다.

규칙

표준 바위, 종이, 가위, 도마뱀, 스팍 규칙이 적용됩니다.

  • 가위 잘라 종이
  • 종이 커버 락
  • 바위는 도마뱀을 분쇄
  • 도마뱀 독
  • 스팍스 ​​가위
  • 가위는 도마뱀을 해독합니다
  • 도마뱀은 종이를 먹는다
  • 스팍은 종이를 반증한다
  • 스팍은 바위를 기화시킨다
  • 가위 분쇄기

RPSLV 규칙

각 플레이어의 봇은 토너먼트에서 서로 다른 봇과 하나의 경기 를합니다.

각 경기는 100 회 반복 된 RPSLV 게임으로 구성됩니다.

각 경기가 끝나면 100 점 만점에 가장 많은 게임 / 핸드를 얻은 선수가 승자가됩니다.

경기에서 이기면 리그 테이블에서 1 점을받습니다. 드로우 매치의 결과로 어느 플레이어도 점수를 얻지 못합니다.

봇 요구 사항

봇은 명령 줄에서 실행할 수 있어야합니다.

Sheldor의 * nix 박스가 죽었으므로 Windows 8 Gaming Laptop에서 실행하므로 제공된 솔루션이 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 개의 단일 대문자 중 하나), 해당 핸드를 자동으로 몰아 내고 경기는 계속됩니다.

두 봇이 모두 유효한 핸드를 반환하지 않으면 게임은 무승부로 간주되며 경기는 계속됩니다.

경기 형식

제출 된 각 봇은 토너먼트에서 서로 다른 봇과 하나의 경기를합니다.

각 경기는 정확히 100 게임 지속됩니다.

시합은 익명으로 진행되며, 상대하는 특정 봇에 대한 고급 지식은 없지만 현재 시합 기록에서 자신의 의사 결정에서 얻을 수있는 모든 정보를 사용하여 상대. 패턴 / 휴리스틱 등을 구축하기 위해 이전 게임의 기록을 추적 할 수도 있습니다 (아래 규칙 참조).

단일 게임 동안 오케스트레이션 엔진은 봇과 상대 봇을 100 밀리 초 간격으로 실행 한 다음 동일한 언어 / 런타임에서 PRNG 충돌을 피하기 위해 결과를 비교합니다. (이것은 실제로 테스트 중에 나에게 발생했습니다).

심사 및 제약

정복자 Sheldor의 모습으로 Sheldon Cooper 박사는 토너먼트 운영을 감독하기 위해 친절하게 제안했습니다. 정복자 쉘더는 공정하고 감독자입니다 (주로). Sheldor의 모든 결정은 최종 결정입니다.

게임은 공정하고 적절한 방식으로 수행됩니다.

  • 봇 스크립트 / 프로그램은 하위 폴더 아래 오케스트레이션 엔진에 저장됩니다. Players\[YourBotName]\
  • 하위 폴더 Players\[YourBotName]\data를 사용하여 진행중인 현재 토너먼트의 데이터 또는 게임 기록을 기록 할 수 있습니다 . 데이터 디렉토리는 토너먼트가 시작될 때마다 제거됩니다.
  • 토너먼트에서 다른 플레이어의 플레이어 디렉토리에 액세스 할 수 없습니다
  • 봇은 다른 특정 봇 동작을 대상으로하는 특정 코드를 가질 수 없습니다
  • 각 플레이어는 서로 상호 작용하거나 도와주지 않는 한 둘 이상의 봇을 제출하여 플레이 할 수 있습니다.

편집-추가 제약

  • 상실에 대해서는 지원되지 않습니다. 봇은 5 개의 유효한 핸드 중 하나를 플레이해야합니다. 토너먼트 외부의 각 봇을 무작위 데이터로 테스트하여 동작하는지 확인합니다. 오류 (예 : 오류를 잃어버린)를 던지는 봇은 버그가 수정 될 때까지 토너먼트에서 제외됩니다.
  • 봇은 행동이 간결하게 다른 한 파생적 일 수 있습니다. 기존 봇과 정확히 동일한 동작을 수행하는 봇 (다른 언어 포함)은 실격 처리됩니다.
  • 다음에 대한 스팸 봇이 이미 있으므로 다시 제출하지 마십시오.
    • 락-바트 심슨
    • 종이-LisaSimpson
    • 가위-EdwardScissoror
    • 스팍-벌컨
    • 도마뱀-칼리시
    • 의사 랜덤-SimpleRandomBot 및 FairBot
    • 슈도 랜덤 RPS-보수적 인 봇
    • 슈도 랜덤 LV-바니 스틴 슨
  • 봇은 타사 서비스 또는 웹 리소스 (또는 경기의 속도 / 의사 결정 시간을 크게 느리게하는 기타)를 불러 낼 수 없습니다. CasinoShakespeare이 제약 조건이 추가되기 전에 봇이 제출 된 유일한 예외입니다.

더 많은 봇이 제출됨에 따라, Sheldor는 토너먼트 결과를 최대한 자주 업데이트합니다.

오케스트레이션 / 제어 프로그램

각 봇에 대한 소스 코드와 함께 오케스트레이션 프로그램은 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

3
오늘 밤에 또 다른 토너먼트를 운영하고 pastebin에 전체 경기 결과를 게시 할 것입니다 ... 다음 배치에는 약 450 게임이 있지만 제어 프로그램에서 병렬화 항목을 구현함에 따라 실행 속도가 더 빨라야합니다
Eoin Campbell

3
내가 실수하지 않으면 오케스트레이션 스크립트에 심각한 버그가있는 것 같습니다. 플레이어 1과 2의 기록은 항상 첫 번째와 두 번째 인수로 봇에 전달되지만 규칙에 따라 봇은 항상 자신의 역사를 먼저. 이제 플레이어 2는 효과적으로 이길려고합니다. (내 봇은 다른 경기의 절반을 잃으면 서 플레이어 1 인 모든 싱글 경기에서 이겼 기 때문에 조금 수상했습니다.)
Emil

답변:


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

아주 좋아요 아직 보지 않았다면 요 카인 파우더를 좋아할 것입니다.
wchargin

물론 @WChargin. :) 원래 코드를 작성할 때 몇 년 전에 Iocaine Powder에 대해 읽었고 일반적인 아이디어를 모호하게 기억했습니다. 포니는 직접적으로는 아니더라도 실제로 영감을 받았습니다. 결과적으로 매우 유사합니다. Iocaine Powder에는 내가 포함하지 않은 영리한 메타 메타 추론 수준이 있지만 내 전략에는 더 넓은 레퍼토리가 있다고 생각합니다.
Emil

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

그런 다음이 프로그램을 사용하여 다음에 수행 할 가장 가능한 움직임을 결정한 다음 수행 할 작업을 찾은 다음, 수행 할 작업을 이길 수있는 방법을 찾아서 모든 일을 반복해서 반복합니다.
Jamie

@Jamie이 사람을 좋아합니까? codegolf.stackexchange.com/a/35295/8478
Martin Ender

당신은 그것을 추측합니다. (의견이 게시되기에 충분히 길지 않았습니다)
Jamie

19

보수적 인 봇, 루비

새로운 것은 나쁜 것입니다.

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

다음과 같이 실행

ruby conservative.rb

OG 버전이 가장 좋은 버전입니다.
maxywb

13

스타 워즈 팬-루비

스크류, 스팍

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

다음과 같이 실행하십시오.

ruby starwarsfan.rb

컨트롤러에 추가
Eoin Campbell

당신은 답변 편집으로 롤백 할 수 있습니다-나는 그들을 추가했을 때 여기에 주석을 달 것입니다.
Eoin Campbell

왜 R과 S인가? : P
cjfaure

@mardavi Spock을 사용하지 않기 때문에 Star Wars 팬입니다.
William Barbosa

아, 그렇습니다 (물론). 나는 그것을 너무 빨리, 내 실수로 읽었다 (그러나 운 좋게도 결과없이)
mardavi

13

바니 스틴 슨-루아

나는 단 하나의 규칙을 가지고 있습니다 : 새로운 것이 항상 좋습니다. 오래된 조 켄 포 또는 당신이 부르는 것을 조이십시오.

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

다음과 같이 실행하십시오.

lua legenwaitforitdary.lua

8

보링 봇 (자바)

그는 모든 사람이 항상 같은 것을하고 그에 따라 계획한다고 가정합니다. 그는 일반적으로 관계에서 바위를 골라냅니다.

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

이 C #입니다. .length 속성이 잘못되었습니다. 방법은 없습니다max
Eoin Campbell

@EoinCampbell 그것은 자바이며, 나는 둘 다 놀고 있었고 분명히 어떤 명령이 어느 명령에 속하는지 잊어 버렸습니다.
kaine

아 멋지다. 나에게 맡기면 포함시킬 것이다.
Eoin Campbell

여전히 고장났다. jre8 실행-java BoringBot.java-오류 : 메인 클래스 D : \ My Software Dev \ big-bang-game \ BigBang.Orchestrator \ bin \ Debug \ Players \ BoringBot \ BoringBot.java를 찾거나로드 할 수 없음
Eoin Campbell

8

IocainePowder, 루비

여기에 이미지 설명을 입력하십시오

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
당신은 그 단어를 계속 사용합니다. 나는 그것이 당신이 생각하는 것을 의미한다고 생각하지 않습니다.
JoshDM

2
Iocaine Powder의 진정한 힘은 마르코프 사용과 베팅 마르코프 사용 간의 전환이라는 것입니다. 그것은 스마트 마르코프로 시작하지만 일단 감지되면 (잃어 버리기 시작) 뛰는 마르코프 모드로 넘어갑니다. 추가하기 쉬워야합니다.
Roy van Rijn

아, 영리하다! 거짓말하지 않을 것입니다. 나는 요오 케인이 나에게 묘사 한 것을 들었을뿐 실제로 그것을 자세히 보지 않았습니다. 직접 작성하거나 제출하여 크레딧을 얻으려면 내 코드를 자유롭게 수정하십시오!
jmite

8

허들 울프 정복자-C #

허들 울프가 돌아 왔습니다. 그는 자신의 바보 같은 게임에서 정복자 Sheldor를 이길 것입니다. HuddleWolf는 스패머 봇을 식별하고 대응할 수있을 정도로 똑똑합니다. 더 지능적인 상대의 경우, 허들 울프는 기본 5 학년 통계에 대한 지식을 사용하고 야당의 플레이 역사에 따라 가중 주사위 롤을 사용합니다.

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

흠. 둘 다 작동한다고 생각하지만 제어 프로그램이 문자 대신 줄 바꿈을 잡으면 println이 엉망이되는 것을 볼 수 있습니다. 지적 해 주셔서 감사합니다. 만일을 대비하여 코드를 편집하겠습니다
Stranjyr

@ Stranjyr 마지막 ​​실행에 몇 가지 버그가있었습니다. 그것은 제어 프로그램을 폭격하지 않았지만 "ToddlerProof plays n"에 대한 기록을 검색하면 봇이 특정 손에 대해 null을 반환 한 다음 손을 autolosing하는 것처럼 보입니다. 예를 들어 게임은 "Echo & ToddlerProof"이며, Ebot은 봇이 멈출 때까지 "LVSPRLV"를 플레이했습니다.
Eoin Campbell

@Eion Campbell 언급 해 주셔서 감사합니다. 나는 당신이 실패한 투어에서 로그를 게시했을 때 그것을 보았고, 나는 그것을 고쳤다 고 생각합니다. 무작위 플레이로 점프하는 대신 5 번 이상 연속으로 잃으면 유효하지 않은 값을 던지는 오류가 발생했습니다. 그리고, 그것이 잃어 버렸기 때문에, 그것은 또 다른 잘못된 가치를 던졌습니다 . 악순환
Stranjyr

시원한. 제어 프로그램에서 지금 업데이트하십시오.
Eoin Campbell

8

바트 심슨

"좋은 오래된 바위! 아무것도 바위를 이길!"

puts 'R'

다음으로 실행

ruby DoTheBartman.rb

리사 심슨

"가난하고 예측 가능한 바트. 항상 바위를 선택합니다."

puts 'P'

다음으로 실행

ruby LisaSimpson.rb

더 나은 리사 심슨

나는 Lisa를 매우 바보로 만드는 것에 대해 기분이 나빠서, 그녀가 바위를 이길 두 손 중 하나를 무작위로 선택할 수있었습니다. 여전히 멍청하지만 그녀는 결국 심슨입니다. 아마도 크레용이 그녀의 뇌에 갇혀 있을까요?

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

다음으로 실행

ruby BetterLisaSimpson.rb


@ MartinBüttner 젠장, 그 사실을 몰랐습니다. 프로그램은 여전히 ​​다른 일을하는 것처럼 보입니다. 적어도 여기서 Lisa는 두 가지 버전의 동생을 때림으로써 더 우월하다고 느낄 수 있습니다.
R Dizzle 박사

1
Shelor는 동의합니다 ... BartBot과 BartSimpson이있을 것입니다 :)
Eoin Campbell

3
우리는 BortBot 만 있습니다.
JoshDM

1
이것들은 markov에 의해 학살 될 것입니다 :)
Cruncher

7

에코

C #으로 작성되었습니다. 로 컴파일하십시오 csc Echo.cs. 처럼 실행하십시오 Echo.exe ARG1 ARG2.

첫 번째로 에코는 무작위 옵션을 사용합니다. 첫 번째 실행 후 매번 에코는 단순히 상대방의 최신 동작을 반복합니다.

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

(이것은 배경 설정에 대한 유일한 문자 내 전략이라고 생각합니다.)


누군가가 갈래 혀로 태어 났는지 확인하려면 에피소드를 되돌아 봐야합니다. LizardMan FTW !!!
Eoin Campbell

3
그러나 이것이 빅뱅의 모든 사람들이 어쨌든 연주하는 방법이 아닙니까?
kaine

2
@anotherguest 이것이 바로 "이것은 유일한 캐릭터 내 전략"입니다.
마틴 엔더

6

Tyrannosaurus, Godzilla, Barney ... 도마뱀 규칙. 때때로 그들은 곤경에 빠지고 Spock에 전화하거나 Rocks를 던질 필요가 있습니다.

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 가지 예측 모델을 만드는 것입니다. 각 모델은 "마지막 턴에서 록을 쳤고 상대방이 2 턴 전에 가위를 쳤다는 것을 의미합니다. 이것은 상대방의 다음 움직임에 대한 확률 분포입니다." 각 확률 분포는 다차원 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

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제대로 작동합니다 (공개 클래스와 동일하게 파일 이름을 지정하십시오)
Justin

감사! 비교적 새로운 프로그래머로서 나는 이것을 알지 못했습니다.
Stretch Maniac

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

느린 도마뱀, 루비

도마뱀으로 시작한 후에는 항상 상대의 이전 동작을 능가하는 임의의 동작을 선택합니다.

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

LexicographicBot

이 봇은 편지를 주문하는 것을 좋아하므로 상대방이 벌칸을 선택하지 않는 한 이전 라운드에서 한 상대보다 1 높은 응답을 선택합니다. 그러면 무작위로 응답을 선택합니다.

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

인수없이 첫 실행시 중단됩니다. 역 추적 (최근의 마지막 호출) : <module>의 10 행 "파일"LexicographicBot \ LexicographicBot.py ""상대 = sys.argv [2] IndexError : 목록 색인이 범위를 벗어남
Eoin Campbell

@EoinCampbell : 첫 번째 실행에서 종료 절을 잊어 버렸습니다. 추가되었으며 이제 제대로 작동합니다.
Kyle Kanos

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

상대 봇이 항상 이전의 움직임에 반응하고, 이길 수있는 것, 잃을 것 같은 것을 선택하거나, 가능한 움직임의 제한된 세트에서 동일한 움직임을 선택한다고 가정합니다. 그런 다음 해당 가정을 고려하여 최선의 움직임을 선택합니다.

처음 10 개의 동작이 하드 코딩 된 것을 제외하고 : 먼저 나는 도마뱀 만 알고있는 척하며, 상대방은 항상 적절한 분석을위한 충분한 데이터가있을 때까지 마지막으로 던진 것을 이길 것으로 가정합니다.


4

자바-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에서,이 프로그램은 상대방이 지금까지 가장 자주 던진 두 동작 중 하나를 던질 것이라고 가정한다는 점을 제외하고는 같은 방식으로 작동합니다.

예,이 두 프로그램은 한 문자 만 떨어져 있습니다. :)


도박꾼은 어떤 조건에서 모드를 변경합니까?
R Dizzle 박사

@DrRDizzle 그렇지 않습니다. 이것은 하나에 두 개의 봇을 제출 한 것처럼 보입니다.
Paŭlo Ebermann

2
연속해서 일정 시간 이상 잃어버린 경우 MODE가 전환되면이 프로그램이 더 효과적이지 않습니까?
R Dizzle 박사

4

Dienstag (파이썬 2)

내 첫 번째 조랑말 은 두 번째 추측 (삼중 추측, ...)과 메타 추론과 잘 어울리는 것 같습니다. 하지만 그게 필요한가요?

포니의 작은 친구 인 Dienstag는 다음 55 가지 전략 중 하나입니다. 상대방의 다음 움직임을 예측하고 이길 수 있습니다.

장기적으로 Dienstag는 현재 순위표의 상위 10 위에있는 모든 봇과 승리 또는 관계를 맺습니다. 조랑말을 제외하고는

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에는 N 라운드 후 다음 이동을 반환하기위한 시간 복잡도 O ( N 2 )가 있습니다. 포니 시간 복잡도 O (갖는 N 3 ). 따라서이 측면에서 그들은 아마도 대부분의 다른 항목보다 훨씬 나쁩니다.


제발. 이것은 나에게 놀라운 학습 경험입니다. 나는 보통 C # / Java 땅에 살고 있으므로 모든 루아, 루비, 파이썬, 하스켈 광기 는 나에게 매우 흥미 롭습니다.
Eoin Campbell

또한 게임에 Pony의 추가 인스턴스를 추가하고 싶습니다. 마치 필멸의 전투 레벨 3에서 마지막으로 거울 자체와 싸워야 할 것입니다 ;-)
Eoin Campbell

@EoinCampbell :-) 적어도 직접 경기 Pony 대 Pony는 완벽한 추첨이 될 것입니다. 두 봇 모두에 임의의 요소가 없습니다.
Emil

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

@mccannf. 이 문제와 관련하여 문제가 있습니다 ... cygwin을 설치하고 od.exe, xargs.exe & echo.exe의 C : \ Cygwin \ bin에 대한 정규화 된 경로로 스크립트를 수정했습니다. 여전히 다음과 같은 오류가 발생합니다. C : / Cygwin / bin / xargs : echo : 해당 파일 또는 디렉토리가 없습니다 % 5 ") 구문 오류 : 피연산자가 예상됩니다 (오류 토큰은"
Eoin Campbell

@EoinCampbell-Windows에서 파일을 만들 때 dos2unixcygwin에서 파일을 실행하기 전에 실행할 수 있습니까?
mccannf

확실한. 시도해 볼게요.
Eoin Campbell

나는 문제가 / dev / urandom 문에 있다고 생각합니다
Eoin Campbell

3

연산

하나를위한 알고리즘.

Cuz '는 항상 무언가를하는 것이 더 안전하다고 느끼고 더 복잡할수록 좋습니다.

아직 심각한 수학을하지 않았으므로이 알고리즘은 그렇게 효과적이지 않을 수 있습니다.

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")

파이썬 2 프로그램 : python algorithm.py


1
이 알고리즘의 요약 : 상대방이 마지막으로 한 게임을 본 다음, 다시 한 번 상대의 마지막 움직임에 대해 잃을 두 움직임 중 하나를 무작위로 재생합니다. 따라서 동일한 움직임을 두 번 연속으로 수행하지 않는 봇에 비해 좋습니다.
Rory O'Kane

하하. 내가 그렇게했는지 정말 모르겠습니다. 내가 틀리지 않으면 실제로 5 개의 동작 중 하나를 무작위로 선택하는 복잡한 방법입니다. ;)
벡터화

3

페어 봇, 루비

간단하게 시작합시다.

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

다음과 같이 실행

ruby fairbot.rb

마지막 'V'매개 변수에 작은 오타가 있습니다. 완성도를 위해 업데이트를 원한다면 마이 사이드에 고쳤습니다
Eoin Campbell

@EoinCampbell 감사합니다!
마틴 엔더

1
흥미로운 점은 이것이 모든 전략에 대해 이길 확률이 정확히 같다는 것입니다.
Cruncher

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)

매개 변수없이 중단됩니다. 역 추적 (가장 최근 호출) : <모듈>의 9 행 "ViolentBot \ ViolentBot.py"파일 = relative = sys.argv [2] IndexError : 범위를 벗어난 목록 색인
Eoin Campbell

매개 변수와 함께 중단됩니다. 역 추적 (가장 최근의 호출 마지막) : 파일 "ViolentBot의 \의 ViolentBot.py", 라인 (12), <모듈> 인쇄 (choice_dict [opponent_last]) KeyError를에서 'S'
에오 인 캠벨

@EoinCampbell : 첫 번째 실행에 대한 종료 절을 추가했습니다. 이제 실행할 수 있습니다.
Kyle Kanos

3

하스켈-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'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.