Das Rock, Paper, Scissors, Lizard, Spock-Turnier der Epicness

98

Neueste Bestenliste @ 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

Turnier Notes

Ausgeschlossene Bots

  • BashRocksBot - immer noch keine Freude, wenn .net Cygwin-Bash-Skripte ausführt
  • CounterPreferenceBot - Warten auf Fehlerbehebung
  • RandomlyWeighted - Warten auf Fehlerbehebung
  • CasinoShakespeare - ausgeschlossen, da eine aktive Internetverbindung erforderlich ist

Original gepostete Frage

Du bist zu deinem Freund nach Hause geschwungen, um die epischste Showdown-Schlacht aller Zeiten zwischen Rock, Paper, Scissors, Lizard, Spock zu bestreiten. Im echten BigBang-Nerd-Stil spielt keiner der Spieler selbst, sondern hat Konsolen-Bots erstellt, um in ihrem Namen zu spielen. Sie ziehen Ihren USB-Stick heraus und übergeben ihn an Sheldor the Conqueror, um ihn in den Showdown einzubeziehen . Penny ohnmächtig. Oder vielleicht fällt Howard in Ohnmacht. Wir richten hier bei Leonard nicht.

Regeln

Es gelten die Standardregeln für Steine, Papier, Schere, Echse und Spock.

  • Schere schneiden Papier
  • Papier bedeckt Rock
  • Rock zerquetscht Lizard
  • Eidechse vergiftet Spock
  • Spock zerschmettert die Schere
  • Schere enthauptet Eidechse
  • Eidechse isst Papier
  • Papier widerlegt Spock
  • Spock verdampft Rock
  • Rock zerquetscht die Schere

RPSLV-Regeln

Der Bot eines jeden Spielers spielt im Turnier ein Match gegen einen anderen Bot.

Jedes Match besteht aus 100 Iterationen eines RPSLV-Spiels.

Nach jedem Spiel gewinnt der Spieler, der die meisten Spiele / Hände von 100 gewonnen hat.

Wenn Sie ein Spiel gewinnen, erhalten Sie 1 Punkt in der Rangliste. Bei einem Unentschieden erhält keiner der Spieler einen Punkt.

Bot-Anforderungen

Ihr Bot muss über die Befehlszeile ausgeführt werden können.

Sheldors * nix-Box ist gestorben, daher wird sie von seinem Windows 8-Gaming-Laptop ausgeführt. Stellen Sie also sicher, dass Ihre bereitgestellte Lösung unter Windows ausgeführt werden kann. Sheldor hat freundlicherweise angeboten, alle erforderlichen Laufzeiten (innerhalb eines angemessenen Rahmens) zu installieren, um Ihre Lösung ausführen zu können. (.NET, Java, PHP, Python, Ruby, Powershell ...)

Eingänge

Im ersten Spiel eines jeden Matches werden Ihrem Bot keine Argumente geliefert. In jedem folgenden Spiel jedes Spiels: - Arg1 enthält die Historie Ihrer Bots Hände / Entscheidungen in diesem Spiel. - Arg2 enthält die Historie der Hände / Entscheidungen Ihres Gegners in diesem Spiel.

Der Verlauf wird durch eine Folge von Großbuchstaben dargestellt, die die möglichen Hände darstellen, die Sie spielen können.

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

Z.B

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

Ausgabe

Ihr Bot muss für jedes Spiel eine Antwort schreiben, die seine "Hand" darstellt. Das Ergebnis sollte nach STDOUT geschrieben werden und der Bot sollte dann beendet werden. Gültige einfache Großbuchstaben finden Sie weiter unten.

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

In dem Fall, dass Ihr Bot keine gültige Hand zurückgibt (dh 1 der obigen 5 Großbuchstaben), verlieren Sie diese Hand automatisch und das Match wird fortgesetzt.

Wenn beide Bots keine gültige Hand zurückgeben, wird das Spiel als unentschieden gewertet und das Spiel fortgesetzt.

Übereinstimmungsformat

Jeder eingereichte Bot spielt im Turnier ein Match gegen einen anderen Bot.

Jedes Match wird genau 100 Spiele dauern.

Die Spiele werden anonym gespielt. Sie verfügen nicht über fortgeschrittene Kenntnisse des spezifischen Bots, gegen den Sie spielen. Sie können jedoch alle Informationen, die Sie aus seiner Entscheidungsfindung im Verlauf des aktuellen Spiels erhalten, verwenden, um Ihre Strategie gegen Ihren zu ändern Gegner. Sie können auch den Verlauf Ihrer vorherigen Spiele verfolgen, um Muster / Heuristiken usw. aufzubauen. (Siehe Regeln unten)

Während eines einzelnen Spiels führt die Orchestrierungs-Engine Ihren Bot und den des Gegners im Abstand von 100 Millisekunden aus und vergleicht dann die Ergebnisse, um PRNG-Kollisionen in derselben Sprache / Laufzeit zu vermeiden. (Das ist mir tatsächlich beim Testen passiert).

Urteilen & Einschränkungen

Dr. Sheldon Cooper in der Gestalt von Sheldor the Conqueror hat freundlicherweise angeboten, die Durchführung des Turniers zu überwachen. Sheldor the Conqueror ist ein fairer und gerechter Aufseher (meistens). Alle Entscheidungen von Sheldor sind endgültig.

Das Spielen wird auf faire und angemessene Weise durchgeführt:

  • Ihr Bot-Skript / Programm wird in der Orchestrierungs-Engine unter einem Unterordner gespeichert Players\[YourBotName]\
  • Sie können den Unterordner verwenden Players\[YourBotName]\data, um die Daten oder den Spielverlauf des aktuellen Turniers zu protokollieren. Datenverzeichnisse werden zu Beginn jedes Turnierlaufs gelöscht.
  • Sie dürfen nicht auf das Spielerverzeichnis eines anderen Spielers im Turnier zugreifen
  • Ihr Bot kann keinen bestimmten Code haben, der auf ein anderes bestimmtes Bots-Verhalten abzielt
  • Jeder Spieler kann mehr als einen Bot zum Spielen einreichen, solange er nicht interagiert oder sich gegenseitig unterstützt.

Bearbeiten - Zusätzliche Einschränkungen

  • Verfallserklärungen werden nicht unterstützt. Ihr Bot muss eine der 5 gültigen Hände spielen. Ich werde jeden Bot außerhalb des Turniers mit zufälligen Daten testen, um sicherzustellen, dass er sich verhält. Alle Bots, die Fehler werfen (dh Fehler verwirken), werden vom Turnier ausgeschlossen, bis sie einen Fehler behoben haben.
  • Bots können abgeleitet sein, solange sie sich in ihrem Verhalten prägnant unterscheiden. Bots (auch in anderen Sprachen), die genau dasselbe Verhalten wie ein vorhandener Bot aufweisen, werden disqualifiziert
  • Es gibt bereits Spam-Bots für die folgenden E-Mails. Bitte senden Sie sie nicht erneut
    • Rock - BartSimpson
    • Papier - LisaSimpson
    • Scissor - EdwardScissorhands
    • Spock - Vulcan
    • Eidechse - Khaleesi
    • Pseudo-Zufall - SimpleRandomBot & FairBot
    • Pseudo-Zufalls-RPS - ConservativeBot
    • Psuedo Random LV - Barney Stinson
  • Bots dürfen keine Dienste oder Webressourcen von Drittanbietern anrufen (oder irgendetwas anderes, das die Geschwindigkeit / Entscheidungszeit der Spiele erheblich verlangsamt). CasinoShakespeareDies ist die einzige Ausnahme, da dieser Bot gesendet wurde, bevor diese Einschränkung hinzugefügt wurde.

Sheldor wird diese Frage so oft wie möglich mit Turnierergebnissen aktualisieren, da mehr Bots eingereicht werden.

Orchestrierungs- / Steuerungsprogramm

Das Orchestrierungsprogramm sowie der Quellcode für jeden Bot sind auf github verfügbar.

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

Einreichungsdetails

Ihre Einreichung sollte enthalten

  • Der Name Ihres Bots
  • Dein Code
  • Ein Befehl an
    • Führen Sie Ihren Bot aus der Shell aus, z
    • ruby myBot.rb
    • python3 myBot.py
    • ODER
    • Kompilieren Sie zuerst Ihre beiden und führen Sie sie dann aus. z.B
    • csc.exe MyBot.cs
    • MyBot.exe

Beispielhafte Einreichung

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

Code:

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

Klärung

Fragen, stellen Sie in den Kommentaren unten.

Eoin Campbell
quelle
7
Wie sieht die Geschichte aus, wenn ein Spieler eine Hand verloren hat?
Histokrat
1
Ich wollte alles mit einem analytischen Ansatz machen, aber die meisten Bots hier sind dumm genug, um die intelligente KI zu besiegen.
flauschiger
1
Nur weil ich nie in Führung bin jede KotH Herausforderung , die ich konkurrierte habe in, habe ich einen Screenshot als Erinnerung genommen.
Kyle Kanos
3
Ich werde heute Abend ein weiteres Turnier veranstalten und die vollständigen Spielergebnisse im Pastebin veröffentlichen. Die nächste Partie wird ungefähr 450 Spiele haben, sollte aber etwas schneller laufen, da ich einige Parallelisierungs-Funktionen im Steuerungsprogramm implementiert habe
Eoin Campbell,
3
Wenn ich mich nicht irre, scheint es einen schwerwiegenden Fehler im Orchestrierungsskript zu geben: Die Historien von Spieler 1 und 2 werden immer als erstes und zweites Argument an die Bots übergeben, während die Bots gemäß den Regeln immer ihre bekommen sollten eigene Geschichte zuerst. Jetzt versucht Spieler 2 effektiv, sich selbst zu schlagen. (Ich wurde etwas misstrauisch, weil mein Bot jedes einzelne Spiel gewann, in dem er Spieler 1 war, während er die Hälfte der anderen Spiele verlor.)
Emil

Antworten:

26

Pony (Python 2)

Dies basiert auf einem Rock-Paper-Scissors-Bot, den ich vor einiger Zeit für eine Programmieraufgabe am Ende eines Udacity-Online-Kurses geschrieben habe . Ich habe es geändert, um Spock und Eidechse einzuschließen, und einige Verbesserungen vorgenommen.

Das Programm hat 11 verschiedene einfache Strategien mit jeweils 5 Varianten. Die Auswahl richtet sich danach, wie gut sie in den letzten Runden abgeschnitten hätten.

Ich habe eine Fallback-Strategie entfernt, die zufällig gegen stärkere Gegner gespielt hat. Ich denke, es macht mehr Spaß.

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]

Rennen wie:

python Pony.py

Bearbeiten : Ich habe eine kleine Änderung vorgenommen, indem ich mich in unsicheren Fällen auf die einfachste Strategie konzentriert habe (dh immer den gleichen Zug gespielt habe). Dies hilft ein wenig, um nicht zu versuchen, übermäßig komplizierte Muster zu finden, in denen es keine gibt, z. B. in Bots wie ConservativeBot.

Hinweis : Ich habe versucht, die grundlegende Strategie für den Verlaufsabgleich zu erläutern, die dieser Bot im Beitrag für meinen anderen Bot Dienstag verwendet .

Emil
quelle
3
Eine Gewinnquote von 96 Prozent ist hervorragend.
AndoDaan
Sehr schön. Sie mögen vielleicht Iocaine Powder , wenn Sie es noch nicht gesehen haben.
Wchargin
@WChargin natürlich. :) Als ich meinen Originalcode schrieb, hatte ich vor einigen Jahren etwas über Iocaine Powder gelesen und erinnerte mich vage an die allgemeine Idee. Pony ist in der Tat davon inspiriert, wenn auch nicht direkt. Wie sich herausstellt, sind sie sich sehr ähnlich. Ich denke, mein Repertoire an Strategien ist breiter, während Iocaine Powder eine clevere Ebene an Meta-Meta-Argumenten hat, die ich nicht mit einbezogen habe.
Emil
20

Markov, Rubin

Betrachtet die letzten beiden Züge des Gegners und bestimmt die möglichen (und wahrscheinlichsten) Folgemaßnahmen. Wenn die Kombination noch nicht ausgewählt wurde, verwendet er stattdessen (bisher) alle Züge des Gegners. Dann sammelt er alle möglichen Antworten für diese und wählt eine zufällige.

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

Laufen wie

markov.rb
Martin Ender
quelle
Und dann benutze ich dieses Programm, um die bestmögliche Bewegung zu bestimmen, die ich als nächstes machen werde, um dann herauszufinden, was Sie tun werden, und um schließlich einen Weg zu finden, um zu schlagen, was Sie tun werden, und um die ganze Sache immer wieder in einer Endlosschleife zu wiederholen.
Jamie
@ Jamie Du meinst, wie dieser Typ? codegolf.stackexchange.com/a/35295/8478
Martin Ender
Du errätst es. (Der Kommentar war nicht lang genug, um veröffentlicht zu werden)
Jamie
19

ConservativeBot, Ruby

Neue Dinge sind schlechte Dinge.

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

Laufen wie

ruby conservative.rb
Martin Ender
quelle
OG-Version ist die beste Version.
Maxywb
13

Star Wars Fan - Rubin

Fick dich, Spock

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

Führen Sie es wie folgt aus:

ruby starwarsfan.rb
William Barbosa
quelle
Hinzugefügt zu Controller
Eoin Campbell
Sie können einen Rollback durchführen, indem Sie die Antwort bearbeiten. Ich werde hier nur einen Kommentar abgeben, wenn ich sie hinzugefügt habe.
Eoin Campbell
Warum R und S? : P
cjfaure
@mardavi Es ist ein Star Wars-Fan, weil es Spock nicht verwendet.
William Barbosa
ah, du hast recht (natürlich) Ich habe es zu schnell gelesen, mein Fehler (aber zum Glück ohne Konsequenzen)
mardavi
13

Barney Stinson - Lua

Ich habe nur eine Regel: Neu ist immer besser. Scheiß auf den alten Jo Ken Po oder wie du es nennst.

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

Führen Sie es wie folgt aus:

lua legenwaitforitdary.lua
William Barbosa
quelle
8

Langweiliger Bot (Java)

Er geht davon aus, dass jeder immer das Gleiche spielt und entsprechend plant. Normalerweise zieht er Steine ​​in einer Krawatte, weil alle anderen das auch tun, oder?

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
quelle
Beachten Sie, dass wenn dies eine Strategie ist, die bereits jemand anderes verwendet, lassen Sie es mich wissen und ich werde sie löschen. Es fühlt sich einfach wie die offensichtliche an, die ich noch nicht gesehen habe.
Kaine
ist das C #. Sie sind .length Eigenschaften sind falsch. und es gibt keine Methodemax
Eoin Campbell
@EoinCampbell Es ist Java, ich habe mit beiden gespielt und anscheinend vergessen, welche Befehle zu welchen gehören.
Kaine
Achso cool. Lass es bei mir und ich werde es inklusive bekommen.
Eoin Campbell
immer noch kaputt. Ausführen von jre8 - java BoringBot.java - Fehler: Hauptklasse D: \ My Software Dev \ Big-Bang-Spiel \ BigBang.Orchestrator \ bin \ Debug \ Players \ BoringBot \ BoringBot.java konnte nicht gefunden oder geladen werden -
Eoin Campbell
8

IocainPowder, Ruby

Bildbeschreibung hier eingeben

Basierend auf der RPS-Strategie (die hier schamlos gestohlen wurde) . Der Bot wählt eine Vermutung, die mit dem Markov-Bot identisch ist, nimmt jedoch an, dass der Gegner erraten hat, was er auswählen wird, und wählt einen Zug, um diesen entsprechend zu schlagen.

Beachten Sie, dass ich gerade die Grundidee der verknüpften Strategie angepasst habe und sie nicht im Detail befolgt habe.

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

Laufen wie

iocaine.rb
jmite
quelle
5
Du benutzt dieses Wort weiter. Ich denke nicht, dass es bedeutet, was Sie denken, dass es bedeutet.
JoshDM
2
Die wirkliche Kraft von Iocain-Pulver bestand darin, zwischen Markov und Beating-Markov zu wechseln. Es beginnt als Smart Markov, springt jedoch in den Beating-Markov-Modus, sobald es den Verlust bemerkt (beginnt). Sollte leicht hinzuzufügen sein.
Roy van Rijn
Ahh, schlau! Ich werde nicht lügen, ich hatte nur Iocaine gehört, der mir beschrieben wurde, und ich habe es mir nicht genau angesehen. Sie können gerne meinen Code ändern, wenn Sie möchten, oder Ihren eigenen Code einreichen und die Gutschrift erhalten!
jmite
8

HuddleWolfTheConqueror - C #

HuddleWolf ist zurück und besser als je zuvor. Er wird Sheldor den Eroberer in seinem eigenen albernen Spiel besiegen. HuddleWolf ist intelligent genug, um Spammerbots zu identifizieren und ihnen entgegenzuwirken. Für intelligentere Gegner nutzt HuddleWolf sein Wissen über grundlegende Statistiken der 5. Klasse und verwendet einen gewichteten Würfelwurf, der auf der Spielgeschichte der Gegner basiert.

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];
    }
}
HuddleWolf
quelle
8

Kleinkindersicher

Dieser ziemlich dumme Bot geht davon aus, dass er ein Kleinkind spielt, das seine Züge "verfolgt" und immer versucht, das zu besiegen, was zuletzt geworfen wurde. Wenn der Bot mehrmals hintereinander geschlagen wird, springt er zu einem neuen Punkt im Muster. Es basiert auf meiner Strategie, meinen viel jüngeren Bruder immer zu schlagen . :)

BEARBEITEN :: Die Länge einer Verlustserie wurde geändert, die erforderlich ist, um in zufällige Würfe zu springen. Außerdem wurde ein größerer Fehler mit dem Zufallssprung behoben.

Speichern unter ToddlerProof.java, kompilieren und ausführen mitjava 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;
    }
}
Stranjyr
quelle
1
Sollten wir print oder println verwenden? ... Ich war mir nicht sicher.
Kaine
Hmmm. Ich würde mir vorstellen, dass beide funktionieren würden, aber ich könnte sehen, dass println durcheinander kommt, wenn das Steuerprogramm die neue Zeile anstelle des Zeichens greift. Vielen Dank für den Hinweis, ich werde meinen Code für alle Fälle bearbeiten
Stranjyr
@ Stranjyr Es gab einige Fehler in Ihrem letzten Lauf. Das Kontrollprogramm wurde nicht bombardiert, aber wenn Sie den Verlauf nach "ToddlerProof plays n" durchsuchen, scheint es, dass Ihr Bot für bestimmte Hände Null zurückgibt und die Hand dann automatisch öffnet. Ein Beispielspiel ist "Echo & ToddlerProof", in dem Echo "LVSPRLV" gespielt hat, bevor Ihr Bot anfing zu scheißen.
Eoin Campbell
@Eion Campbell Danke, dass du es erwähnt hast. Ich habe das früher gesehen, als du die Logs vom gescheiterten Turnier gepostet hast, und ich glaube, ich habe es behoben. Es kam zu einem Fehler, bei dem mehr als 5 aufeinanderfolgende Karten verloren gingen und statt zu einem zufälligen Spiel zu springen, nur ein ungültiger Wert geworfen wurde. Und dann, weil das es verlieren ließ, warf es einen anderen ungültigen Wert. Ein Teufelskreis.
Stranjyr
Cool. Habe es jetzt im Kontrollprogramm aktualisiert.
Eoin Campbell
8

Bart Simpson

"Guter alter Rock! Nichts geht über Rock!"

puts 'R'

Rennen wie

ruby DoTheBartman.rb

Lisa Simpson

"Armer, vorhersehbarer Bart. Wählt immer Rock."

puts 'P'

Rennen wie

ruby LisaSimpson.rb

Besser Lisa Simpson

Ich hatte ein schlechtes Gewissen, weil ich Lisa so dumm gemacht habe, also habe ich ihr erlaubt, nach dem Zufallsprinzip zwischen den Händen zu wählen, die den Rock schlagen. Immer noch dumm, aber sie ist doch eine Simpson. Vielleicht hat sich ein Wachsmalstift in ihrem Gehirn festgesetzt?

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

Rennen wie

ruby BetterLisaSimpson.rb
Dr. R Dizzle
quelle
2
Kleinere Namenskonflikte . +1 sowieso.
Martin Ender
@ MartinBüttner Verdammt, habe das nicht bemerkt. Die Programme scheinen jedoch immer noch verschiedene Dinge zu tun - und zumindest kann Lisa sich hier überlegener fühlen, wenn sie zwei verschiedene Versionen ihres Bruders besiegt.
Dr R Dizzle
1
Sheldor stimmt zu ... es wird einen BartBot und einen BartSimpson geben :)
Eoin Campbell
3
Wir haben nur BortBot.
JoshDM
1
Diese werden von Markov geschlachtet :)
Cruncher
7

Echo

Geschrieben in C #. Kompilieren mit csc Echo.cs. Laufen wie Echo.exe ARG1 ARG2.

Beim ersten Durchlauf wählt Echo eine zufällige Option. Bei jedem Lauf nach dem ersten wiederholt Echo einfach die letzte Aktion des Gegners.

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]);
            }
        }
    }
}
ProgramFOX
quelle
7

Vulkanier, Rubin

Meine Finger sind zusammengeklebt.

puts 'V'

Laufen wie

ruby vulcan.rb

(Ich denke, dies ist die einzige In-Character-Strategie für Ihre Hintergrundeinstellung.)

Martin Ender
quelle
Ich muss auf die Folgen zurückblicken, um festzustellen, ob jemand mit einer gespaltenen Zunge geboren wurde. LizardMan FTW !!!
Eoin Campbell
3
Aber spielt nicht jeder auf Urknall so?
Kaine
2
@anotherguest Das habe ich mit "Dies ist die einzige Strategie für Charaktere" gemeint.
Martin Ender
6

Tyrannosaurus, Godzilla, Barney ... Eidechsen-Regel. Gelegentlich geraten sie in Schwierigkeiten und müssen Spock anrufen oder Rocks werfen

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");     
    }
}
Mikey Mouse
quelle
6

BayesianBot, Perl (jetzt v2!)

Dies ist vor allem ein einzigartiges Programm. Darin werden Sie die brillante Verschmelzung von Statistik und schrecklicher Programmierform sehen. Auch dieser Bot bricht wahrscheinlich viele Regeln der Bayes'schen Statistik, aber der Name klingt cooler.

Das Kernstück dieses Bots ist die Erstellung von 250 verschiedenen Vorhersagemodellen. Jedes Modell hat die Form "Vorausgesetzt, ich habe in der letzten Runde Rock gespielt und mein Gegner hat vor zwei Runden Schere gespielt, ist dies die Wahrscheinlichkeitsverteilung für den nächsten Zug meines Gegners." Jede Wahrscheinlichkeitsverteilung hat die Form einer mehrdimensionalen Dirichlet-Verteilung.

In jeder Runde werden die Vorhersagen aller anwendbaren Modelle (in der Regel 10) zu einer Gesamtprognose multipliziert, anhand derer dann bestimmt wird, welche Züge die höchste erwartete Auszahlung haben.

Edit 1: In dieser Version habe ich die vorherige Distribution geändert und den Bot zufälliger gemacht, wenn er verliert.

Es gibt einige Dinge, die verbessert werden können, wie die Anzahl der Modelle (250 ist nur eine dreistellige Zahl), die Wahl der vorherigen Verteilung (derzeit Dir (3,3,3,3,3)) und die Methode zum Zusammenführen von Vorhersagen. Außerdem habe ich mich nie darum gekümmert, eine der Wahrscheinlichkeitsverteilungen zu normalisieren, was im Moment in Ordnung ist, weil ich sie multipliziere.

Ich habe keine besonders hohen Erwartungen, aber ich hoffe, dieser Bot wird es schaffen.

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

Ich habe dieses Programm so ausgeführt:

perl BayesianBot.plx
PhiNotPi
quelle
5

DynamicBot

Der dynamische Bot ändert sich fast immer. Es hasst es wirklich, sich zu wiederholen

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

Sprache: Python 3.4.1

Befehl: python dynamicbot.py <history>oder python3 dynamicbot.py <history>abhängig von Ihrem System

Tymric
quelle
Ja, darüber nachgedacht.
Siehe auch
5

SmartBot - Java

Mein allererster Eintrag für irgendetwas auf dieser Seite!

Obwohl kein sehr kreativer Name ...

SmartBot findet Abfolgen von Zügen, bei denen die Züge des Gegners und / oder sich selbst den zuletzt ausgeführten Zügen ähneln, und plant entsprechend.

name = SmartBot

Ich denke, es auszuführen, korrigiere mich, wenn ich falsch liege.

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

Für jeden möglichen nächsten Zug wird eine Punktzahl vergeben, die angibt, wie oft ähnliche Muster aufgetreten sind.

Es begünstigt leicht Eidechse.

Stretch Maniac
quelle
Ich glaube, dass du es so machst, wenn du es zuerst einsetzt. Wenn Sie es einfach erst kompilieren, java ABotsollte es funktionieren (denken Sie daran, die Datei genauso wie die öffentliche Klasse zu benennen)
Justin
Vielen Dank! Als relativ neuer Programmierer war mir das nicht bewusst.
Stretch Maniac
5

SpockOrRock - PHP

SpockOrRock

In der realen Welt spielen die meisten Leute instinktiv mit der Schere. Dieser Bot wählt entweder Spock oder Rock, um den durchschnittlichen Spieler zu schlagen. Es kümmert sich nicht um vorherige Runden.

renn mit php spockorrock.php

<?php

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


?>
ArcticanAudio
quelle
4

SlowLizard, Ruby

Nach dem Start mit Lizard wird immer ein zufälliger Zug ausgewählt, der den vorherigen Zug des Gegners schlägt.

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

Laufen wie

ruby slowlizard.rb
Martin Ender
quelle
4

LexicographicBot

Dieser Bot bestellt gerne seine Briefe, also wählt er eine Antwort, die 1 höher ist als die seines Gegners in der vorherigen Runde - es sei denn, der Gegner hat Vulcan gewählt, dann wählt er zufällig eine Antwort aus.

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

Dies erwartet, dass die gegnerische Hand an zweiter Stelle ausgeteilt wird:

                           me
                            v
python LexicographicBot.py SR RV
                              ^
                            opponent
Kyle Kanos
quelle
@ MartinBüttner: Befehl hinzugefügt! Ich war ziemlich beschäftigt bei der Arbeit, um etwas veröffentlichen zu lassen, daher das Verschwinden.
Kyle Kanos
bricht beim ersten Lauf ohne Argumente. Traceback (letzter Aufruf zuletzt): Datei "LexicographicBot \ LexicographicBot.py", Zeile 10, in <Modul> opponent = sys.argv [2] IndexError: Listenindex außerhalb des gültigen Bereichs
Eoin Campbell
@EoinCampbell: Ich habe die Exit-Klausel beim ersten Start vergessen, sie wurde hinzugefügt und sollte jetzt funktionieren.
Kyle Kanos
4

Werevulcan - Rubin

Rennen wie 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

Der Werevulkaner sieht tagsüber normal aus, aber wenn der Mond aufgeht, werden seine Ohren spitz und seine Bewegungen logischer.

Histokrat
quelle
4

Analogizer - Ruby

Laufen Sie mit ruby analogizer.rb. Ich habe eine logische Korrektur des Codes vorgenommen, aber keine Ahnung, warum es dabei Fehler gab.

@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

Angenommen, der gegnerische Bot reagiert immer auf meinen vorherigen Zug und wählt entweder etwas aus, das ihn schlagen würde, etwas, das ihn verlieren würde, oder denselben Zug, möglicherweise aus einer begrenzten Anzahl möglicher Züge. Unter dieser Annahme wird der beste Zug ausgewählt.

Abgesehen davon, dass die ersten zehn Züge fest codiert sind: Zuerst gebe ich vor, ich kenne nur die Echse, dann gehe ich davon aus, dass mein Gegner immer etwas wirft, um das letzte, was ich geworfen habe, zu schlagen, bis ich genug Daten für eine ordnungsgemäße Analyse habe.

Histokrat
quelle
4

Java - SelfLoathingBot

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

Der Bot startet nach dem Zufallsprinzip, dann ~ 33%, um zufällig zu spielen, oder ~ 33%, um eine Siegertaktik gegen eines der unmittelbar vorhergehenden Spiele zu spielen, wobei 50% der Siegertaktiken zur Auswahl stehen.

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;
    }
}
JoshDM
quelle
4

Der Analyst

Der Analyst analysiert einige Dinge und unternimmt einige, um Sie zu schlagen.

kompilieren javac Analyst.javaund ausführen alsjava 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;
        }
    }
}
Qwix
quelle
4

Der Spieler - 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)

Im Gegensatz zum Namen wird in diesem Programm nur in der ersten Runde Zufälligkeit verwendet, wenn keine Informationen vorliegen. Stattdessen ist es nach dem Irrtum des Spielers benannt, der Überzeugung, dass ein zufälliges Ereignis, das in der Vergangenheit seltener aufgetreten ist, mit größerer Wahrscheinlichkeit in der Zukunft eintreten wird. Wenn Sie zum Beispiel 20 Mal eine faire Münze werfen und die ersten 15 Köpfe sind, gibt der Irrtum des Spielers an, dass sich die Wahrscheinlichkeit erhöht, dass die verbleibenden Köpfe Schwänze sind. Das ist natürlich falsch. Unabhängig von den vorangegangenen Flips beträgt die Wahrscheinlichkeit, dass eine faire Münze auftaucht, immer 50%.

Dieses Programm analysiert die Geschichte des Gegners, findet die 2 Züge, die es bisher am wenigsten benutzt hat, und geht davon aus, dass der Zug des Gegners diesmal einer dieser beiden sein wird. Wenn Sie 2 für einen Sieg, 1 für ein Unentschieden und 0 für einen Verlust festlegen, wird der Zug mit der maximalen Punktzahl gegen diese beiden vorhergesagten Züge ermittelt und geworfen.

Der Bruder des Spielers - 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)

Durch Umschalten der MODEVariablen auf 0 wird dieses Programm auf der Grundlage eines verwandten Irrtums ausgeführt, der manchmal auch als der Irrtum des Spielers bezeichnet wird. Es besagt, dass ein zufälliges Ereignis, das in der Vergangenheit häufiger aufgetreten ist, mit größerer Wahrscheinlichkeit in der Zukunft eintreten wird. Wenn Sie beispielsweise 20-mal eine Münze werfen und die ersten 15 Köpfe sind, bedeutet dies, dass die verbleibenden Köpfe eher Köpfe sind, da derzeit ein Streifen vorliegt. Im Modus 0 arbeitet dieses Programm auf die gleiche Weise, mit der Ausnahme, dass der Gegner einen der beiden Züge ausführt, die er bisher am häufigsten ausgeführt hat.

Also ja, diese beiden Programme sind nur ein Zeichen voneinander entfernt. :)

untergrundbahn
quelle
Unter welchen Bedingungen wechselt TheGambler den MODUS?
Dr R Dizzle
@DrRDizzle Tut es nicht, es sieht so aus, als ob dies eine Einsendung von zwei Bots in einem ist.
Paŭlo Ebermann
2
Wäre dieses Programm nicht effektiver, wenn der Modus umgeschaltet würde, wenn Sie mehr als eine bestimmte Anzahl von Malen hintereinander verlieren?
Dr R Dizzle
4

Dienstag (Python 2)

Mein erster Eintrag Pony scheint mit all seinen zweiten Vermutungen (Dreifach-Vermutungen, ...) und Meta-Überlegungen ganz gut abzuschneiden. Aber ist das überhaupt nötig?

Hier ist also Dienstag, Ponys kleiner Freund, mit nur einer der 55 Strategien: Sagen Sie den nächsten Zug des Gegners voraus und schlagen Sie ihn.

Langfristig gewinnt oder bindet Dienstag jeden Bot in den Top Ten der aktuellen Bestenliste. Mit Ausnahme von Pony.

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]

Rennen wie:

python Dienstag.py

Ich gebe zu, dass der Code etwas verschleiert ist. Wenn jemand mehr darüber wissen möchte, kann ich Erklärungen hinzufügen.

Bearbeiten: Hier ist eine kurze exemplarische Vorgehensweise, um die Idee zu erklären:

  • Das Programm erhält die eigene Geschichte und die Züge des Gegners:

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

  • Die Historie wird zu einer Liste von Paaren zusammengefasst und die Züge in Zahlen übersetzt (R = 0, ...):

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

  • Die Anzahl der bisher gespielten Runden wird bestimmt:

    N = 7

  • Die Grundidee ist nun, nach der längsten ununterbrochenen Kette der letzten Züge in der früheren Geschichte zu suchen. Das Programm verfolgt, wo eine solche Kette in der Liste endet cand(für "Kandidaten"). Zu Beginn wird ohne Überprüfung jede Position in der Historie mit Ausnahme der letzten berücksichtigt:

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

  • Jetzt wird die Länge möglicher Ketten schrittweise erhöht. Bei der Kettenlänge l = 1wird nach früheren Vorkommen des letzten Zugpaars gesucht [4, 1]. Dies kann an der historischen Position 1und gefunden werden 3. Nur diese sind in der candListe enthalten:

    cand = [1, 3]

  • Anschließend wird l = 2geprüft, vor welchem ​​der möglichen Kandidaten sich das vorletzte Zugpaar befand [3, 2]. Dies ist nur für die Position der Fall 3:

    cand = [3]

  • Für l = 3und mehr gibt es keine vorherigen Ketten dieser Länge und candwäre leer. In diesem Fall candbleibt das letzte Element von :

    cand = [3]

  • Der Bot geht nun davon aus, dass sich die Geschichte wiederholen wird. Das letzte Mal, als das Kain [3, 2], [4, 1]auftrat, folgte es [4, 2]. Also hat der Gegner gespielt 2(Schere), was von (2+1)%5 = 3(Spock) oder (2+3)%5 = 0(Rock) geschlagen werden kann. Der Bot antwortet, wobei die erste oder zweite Alternative davon abhängt, ob sie Ngerade oder ungerade ist, um eine gewisse Varianz einzuführen.

  • Hier wird move 3gewählt, der dann zurück übersetzt wird:

    print 'V'

Hinweis: Dienstag hat die Zeitkomplexität O ( N 2 ), um den nächsten Zug nach N Runden zurückzugeben. Pony hat Zeitkomplexität O ( N 3 ). In dieser Hinsicht sind sie wahrscheinlich viel schlechter als die meisten anderen Einträge.

Emil
quelle
Bitte. Das ist eine großartige Lernerfahrung für mich. Ich lebe normalerweise in C # / Java-Land, so dass all der Lua-, Rubin-, Python- und Haskell- Wahnsinn für mich sehr interessant ist.
Eoin Campbell
Ich bin auch versucht, den Spielen eine zusätzliche Instanz von Pony hinzuzufügen. Es wird sein, als müsste man im 3. bis zum letzten Level von Mortal Combat gegen sein Spiegel-Ich kämpfen ;-)
Eoin Campbell,
@EoinCampbell :-) Zumindest das direkte Match Pony vs. Pony wäre ein perfektes Unentschieden. In beiden Bots gibt es kein Zufallselement.
Emil
3

Bash Rocks

Ist cygwin als Laufzeit zu viel verlangt?

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

und führe es so aus:

sh bashrocks.sh
mccannf
quelle
5
Nachdem ich den Titel gelesen habe, bin ich etwas enttäuscht, dass Sie alles andere als tun R. ;)
Martin Ender
@mccannf. Ich habe einige Probleme damit ... Ich habe cygwin installiert und Ihre Skripte mit vollständig qualifizierten Pfaden zu C: \ Cygwin \ bin für od.exe, xargs.exe & echo.exe geändert. erhalte immer noch den folgenden Fehler. C: / Cygwin / bin / xargs: echo: Keine solche Datei oder Verzeichnis% 5 ") Syntaxfehler: Operand erwartet (
Eoin Campbell
@EoinCampbell - Wenn Sie die Datei in Windows erstellen, können Sie sie dann dos2unixin Cygwin ausführen, bevor Sie sie ausführen?
McCannf
sicher. Ich werde es versuchen.
Eoin Campbell
Ich denke, das Problem könnte mit der / dev / urandom-Anweisung sein
Eoin Campbell
3

Algorithmus

Ein Algorithmus, um einen zu haben.

Denn es fühlt sich immer sicherer an, etwas zu tun. Je komplizierter, desto besser.

Ich habe noch keine ernsthaften Berechnungen angestellt, daher ist dieser Algorithmus möglicherweise nicht so effektiv.

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-Programm: python algorithm.py

Vektorisiert
quelle
1
Zusammenfassung dieses Algorithmus: Sehen Sie sich an, was der Gegner zuletzt gespielt hat, und spielen Sie dann zufällig einen der beiden Züge, die gegen den letzten Zug des Gegners verloren hätten, wenn er ihn erneut gespielt hätte. Es ist also besser gegen Bots, die nicht zweimal hintereinander den gleichen Zug spielen.
Rory O'Kane
Haha. Ich weiß nicht wirklich, ob ich es so gemacht habe. Wenn ich mich nicht irre, ist es eigentlich nur eine verschlungene Art, einen der 5 Züge zufällig auszuwählen. ;)
Vectorized
3

FairBot, Ruby

Fangen wir einfach an.

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

Laufen wie

ruby fairbot.rb
Martin Ender
quelle
kleiner Tippfehler auf dem letzten 'V'-Parameter. habe es auf dem Land behoben, wenn Sie der Vollständigkeit halber aktualisieren möchten
Eoin Campbell
@EoinCampbell danke, behoben!
Martin Ender
1
Das Interessante ist, dass dies genau die gleichen Gewinnchancen gegen ALLE Strategien hat.
Cruncher
3

ViolentBot

Dieser Bot wählt die gewalttätigste Option basierend auf der vorherigen Auswahl des Gegners:

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

Rennen wie

python ViolentBot.py (me) (opp)
Kyle Kanos
quelle
bricht ohne params. Traceback (letzter Aufruf zuletzt): Datei "ViolentBot \ ViolentBot.py", Zeile 9, in <Modul> opponent = sys.argv [2] IndexError: Index außerhalb des gültigen Bereichs auflisten
Eoin Campbell
bricht mit params. Rückverfolgung (letzter Aufruf zuletzt): Datei "ViolentBot \ ViolentBot.py", Zeile 12, in <Modul> print (choice_dict [opponent_last]) KeyError: 'S'
Eoin Campbell
@EoinCampbell: Ich habe eine Exit-Klausel für den ersten Lauf hinzugefügt. Du solltest sie jetzt ausführen können.
Kyle Kanos
3

Haskell - MonadBot

Ich weiß nicht, ob ghc als "im Rahmen der Vernunft" betrachtet wird, aber nehmen wir einfach an, dass es so ist. Die Strategie dieses Bots besteht darin, dem beliebtesten Zug seines Gegners entgegenzuwirken.

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

Code:

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'
DrJPepper
quelle