In dieser Herausforderung spielst du das Dilemma des lauten iterierten Gefangenen.
Das Gefangenendilemma ist ein Szenario in der Spieltheorie, in dem es zwei Spieler gibt, die jeweils zwei Optionen haben: Kooperation oder Defekt. Jeder Spieler macht es besser für sich, wenn er defekt ist, als wenn er kooperiert, aber beide Spieler würden das Ergebnis, bei dem beide Spieler kooperieren, dem vorziehen, bei dem beide Spieler defekt sind.
Das iterierte Gefangenendilemma ist dasselbe Spiel, außer dass Sie wiederholt gegen denselben Gegner spielen und wissen, was Ihr Gegner in der Vergangenheit gespielt hat. Ihr Ziel ist es immer, die höchste Punktzahl für sich selbst zu erzielen, unabhängig davon, wie Ihr Gegner vorgeht.
Das laute Dilemma der iterierten Gefangenen bringt ein wenig Lärm in die Kommunikation. Wenn du weißt, was dein Gegner in der Vergangenheit gespielt hat, werden Geräusche eingeführt. Sie werden auch wissen, welche Bewegungen Sie in der Vergangenheit gemacht haben. Die Geräuschrate ist während einer Runde gegen denselben Gegner konstant, aber zwischen verschiedenen Runden unterschiedlich.
Herausforderung
In dieser Herausforderung werden Sie ein Python 3-Programm schreiben, um das Dilemma eines lauten iterierten Gefangenen zu spielen.
Ihr Programm erhält drei Eingaben:
Deine eigenen Züge, ohne zufällige Flips.
Die Züge deines Gegners mit zufälligen Flips.
Eine Statusvariable, die in jeder Runde als leere Liste beginnt und die Sie bei Bedarf ändern können. Sie können dies ignorieren, wenn Sie es nicht verwenden möchten.
Ihr Programm sollte ausgegeben werden, 'c'
um zusammenzuarbeiten oder 'd'
zu defekten.
Hier ist zum Beispiel ein Programm, das kooperiert, wenn der Gegner in der Vergangenheit mindestens 60% der Zeit kooperiert hat, nachdem zufällige Flips angewendet wurden, und für die ersten 10 Flips:
def threshold(my_plays, their_flipped_plays, state):
if len(their_flipped_plays) < 10:
return 'c'
opp_c_freq = their_flipped_plays.count('c')/len(their_flipped_plays)
if opp_c_freq > 0.6:
return 'c'
else:
return 'd'
Wenn Sie Python nicht kennen, schreiben Sie Ihren Beitrag in Pseudocode, und jemand (ich oder ein anderes Mitglied der Site) kann das entsprechende Python-Programm erstellen.
Gameplay
Der Turnierläufer ist hier zu finden: noisy-game . Laufen noisy-game.py
, um das Turnier zu starten. Ich werde dieses Repository mit neuen Einreichungen auf dem Laufenden halten. Beispielprogramme finden Sie in basic.py
.
Die Gesamtpunktzahl eines Programms ergibt sich aus der Gesamtpunktzahl von über 100 Spielen des Spiels.
Ein Spiel besteht aus Round-Robin-Matches jedes Spielers gegen jeden Spieler, einschließlich sich selbst. Ein Matchup besteht aus 100 Runden. Eine Runde besteht aus 300 Zügen, bei denen jeweils 'c'
oder ausgegeben werden 'd'
.
Ihre Einsendung wird gegen jede Einsendung, einschließlich Ihrer eigenen, ein Matchup spielen. Jedes Matchup besteht aus 100 Runden. Während jeder Runde wird eine Schlagwahrscheinlichkeit einheitlich zufällig aus gewählt [0, 0.5]
.
Jede Runde besteht aus 300 Zügen. Bei jedem Zug erhalten beide Programme alle vorherigen Spiele, die sie versucht haben, und alle vorherigen Spiele, die das andere Programm nach dem Anwenden von Flips gemacht hat, sowie eine Statusvariable, eine veränderbare Liste, die das Programm ändern kann, wenn es möchte. Die Programme geben ihre Züge aus.
Züge werden wie folgt gewertet: Wenn ein Programm a spielt 'c'
, erhält das gegnerische Programm 2 Punkte. Wenn ein Programm einen 'd'
abspielt, erhält dieses Programm 1 Punkt.
Dann wird jeder Zug unabhängig mit einer Wahrscheinlichkeit gespiegelt, die gleich der Spiegelwahrscheinlichkeit ist, und zum Zeigen für den Gegner gespeichert.
Nachdem alle Runden gespielt wurden, addieren wir die Anzahl der Punkte, die jeder Spieler in jedem Matchup erhalten hat. Anschließend verwenden wir das folgende Bewertungssystem, um die Punktzahl jedes Spielers für das Spiel zu berechnen. Diese Wertung wird durchgeführt, nachdem alle Matchups abgeschlossen sind.
Wertung
Wir werden die Evolutionsbewertung verwenden. Jedes Programm beginnt mit gleichem Gewicht. Anschließend werden die Gewichte für 100 Iterationen unter Verwendung der Punktsummen aus dem Spiel wie folgt aktualisiert:
Das neue Gewicht jedes Programms ist proportional zum Produkt seines vorherigen Gewichts und seiner durchschnittlichen Punktzahl, gewichtet mit den Gewichten seiner Gegner.
100 solcher Aktualisierungen werden angewendet, und die endgültigen Gewichte sind die Punktzahlen der einzelnen Programme für diesen Lauf des Spiels.
Die Gesamtpunktzahl ergibt sich aus der Summe der über 100 Durchläufe des Spiels.
Die Spieler werden alle gültige Antworten auf diese Herausforderung sein, plus sechs Basisprogramme , um uns zum Start zu bringen.
Vorbehalte
Verändern Sie die Eingänge nicht. Versuchen Sie nicht, die Ausführung eines anderen Programms zu beeinträchtigen, außer durch Zusammenarbeit oder Fehler. Machen Sie keine Opfergabe, bei der versucht wird, eine andere Aufgabe zu erkennen, und nutzen Sie diesen Gegner auf eigene Kosten. Standardlücken sind verboten.
BEARBEITEN: Einreichungen dürfen keines der Basisprogramme oder frühere Einreichungen exakt duplizieren .
Wenn Sie Fragen haben, können Sie diese gerne stellen.
Aktuelle Ergebnisse
nicht_genug: 40.6311
stealer: 37.1416
enough: 14.4443
wait_for_50: 6.947
threshold: 0.406784
buckets: 0.202875
change_of_heart: 0.0996783
exploit_threshold: 0.0670485
kickback: 0.0313357
tit_for_stat: 0.0141368
decaying_memory: 0.00907645
tit_for_whoops: 0.00211803
slider: 0.00167053
trickster: 0.000654875
sounder: 0.000427348
tit_for_tat: 9.12471e-05
stubborn_stumbler: 6.92879e-05
tit_for_time: 2.82541e-05
jedi2sith: 2.0768e-05
cooperate: 1.86291e-05
everyThree: 1.04843e-05
somewhat_naive: 4.46701e-06
just_noise: 1.41564e-06
growing_distrust: 5.32521e-08
goldfish: 4.28982e-09
vengeful: 2.74267e-09
defect: 3.71295e-10
alternate: 2.09372e-20
random_player: 6.74361e-21
Ergebnisse mit nur Antworten auf diese Frage und Basisprogrammen, die das Spiel des Gegners ignorieren:
nicht_genug: 39.3907
stealer: 33.7864
enough: 20.9032
wait_for_50: 5.60007
buckets: 0.174457
kickback: 0.0686975
change_of_heart: 0.027396
tit_for_stat: 0.024522
decaying_memory: 0.0193272
tit_for_whoops: 0.00284842
slider: 0.00153227
sounder: 0.000472289
trickster: 0.000297515
stubborn_stumbler: 3.76073e-05
cooperate: 3.46865e-05
tit_for_time: 2.42263e-05
everyThree: 2.06095e-05
jedi2sith: 1.62591e-05
somewhat_naive: 4.20785e-06
just_noise: 1.18372e-06
growing_distrust: 6.17619e-08
vengeful: 3.61213e-09
goldfish: 3.5746e-09
defect: 4.92581e-10
alternate: 6.96497e-20
random_player: 1.49879e-20
Gewinnen
Der Wettbewerb bleibt auf unbestimmte Zeit geöffnet, da neue Beiträge veröffentlicht werden. Ich erkläre jedoch einen Monat nach dem Absenden dieser Frage einen Gewinner (akzeptiere eine Antwort) auf der Grundlage der Ergebnisse.
quelle
exploit_threshold()
mehrmals versucht, alsexploit_threshold1()
usw. zu kopieren und sie zurplayers
Liste hinzugefügt . Warum erhalte ich bei identischen Strategien sehr unterschiedliche Ergebnisse?Antworten:
Genug ist nicht genug
(könnte auch
enough2
oder genannt werdenstealback
)Ich erfuhr, dass die ursprüngliche Meise für zwei Tattoos auf zwei aufeinanderfolgende Tattoos gewartet
tit_for_whoops
hat, und in der Tat scheint es, dass wir frühere einzelne Tattoos vergeben und vergessen sollten ( na ja, fast ...). Und viele Spieler haben in den letzten Runden Fehler gemacht. Ich bin immer noch lieber nett, wenn bisher alles in Ordnung war, aber die Toleranzgrenze des Bots wird immer niedriger.quelle
Tit-For-Whoops
Inspiriert von einer Strategie von ncase.me/trust
Fehler nur, wenn der andere Spieler zweimal hintereinander fehlerhaft war, um Missverständnisse zu vermeiden.
quelle
Sinneswandel
Hat eine Veränderung des Herzens auf halbem Weg durch. Macht sich überraschend gut.
quelle
Strategie-Stealer
Inspiriert von genug, change_of_heart und tit-for-whoops. Sollte etwas verzeihender sein. Ich habe versucht, die Zahlen zu optimieren, um die besten Ergebnisse zu erzielen, aber sie wollten nicht viel ändern.
quelle
Tit-For-Time
Wenn du die meiste Zeit damit verbracht hast, mich zu verletzen, werde ich dich nur zurück verletzen. Wahrscheinlich.
quelle
Wachsendes Misstrauen
Je mehr der Gegner mich verrät, desto weniger kann ich darauf vertrauen, dass es nur Lärm war.
quelle
state
Argument, dass standardmäßig eine Liste ist? Listen können geändert werden, sodass der Status leicht geändert werden kann.Jedi2Sith
Beginnt alles schön und selbstlos, aber mit der Zeit nimmt der Einfluss der dunklen Seite stetig zu, bis der Punkt ohne Wiederkehr. Diesen Einfluss kann man nicht aufhalten, aber all die schlechten Dinge, die passieren, tragen einfach zur Macht der dunklen Seite bei ...
Probieren Sie es online!
quelle
Schieberegler
Beginnt mit 'c' und gleitet nach und nach von 'd' weg.
quelle
Hartnäckiger Stolper
Basierend auf Ihrer Exploit-Threshold-Strategie wurde nur bei konsistenten Spielen der Wechsel zwischen fehlerhaft und meistens kooperativ verfolgt
UPDATE: Verfolgt sowohl zwei als auch drei aufeinanderfolgende Spiele, bestraft nur unter härteren Bedingungen und fügt eine zufällige Auswahl hinzu, wenn Sie nicht sicher sind
UPDATE 2: Zustand entfernt und Verteilungsfunktion hinzugefügt
quelle
Noise Bot
Ich bin auf jeden Fall Bot zusammenarbeiten. Das ist nur Lärm.
quelle
Genug ist genug
Beginnt als Meise für zwei Tats, wobei die beiden Tats nicht aufeinander folgen müssen (im Gegensatz zu
tit_for_whoops
). Wenn esd
zu oft spielen muss, geht esd
-total.quelle
Goldfisch-Bot
Ein Goldfisch vergibt nie, vergisst aber schnell.
quelle
quelle
Verfallendes Gedächtnis
Wiegt die jüngste Geschichte mehr. Vergisst langsam die Vergangenheit.
quelle
Rückschlag
Einige vage Ideen ...
quelle
Bekommt nicht wirklich die ganze "Noise" Sache
Vergibt niemals einen Verräter.
quelle
Schallgeber:
edit: Vergeltung in wahrscheinlich geräuscharmen Szenarien hinzugefügt
Im Grunde genommen bedeutet dies, dass wir weniger Lärm als gewöhnlich erwarten sollten, wenn alle 4 ersten Züge zusammenarbeiten. hin und wieder ein bisschen defekt, um die weniger Punkte auszugleichen, die wir durch nie defektes Material bekommen würden, und um es auf Lärm zurückführen zu können. wir rächen uns auch, wenn sie gegen uns defekt sind
Wenn unser Gegner in diesen Spielzügen (2 oder mehr) viele Defekte ausführt, gehen wir einfach auf sie zurück. Wenn es nur Lärm wäre, würde der Lärm unsere Bewegungen sowieso beeinträchtigen.
andernfalls, wenn nur 1 Zug fehlerhaft war, machen wir für den Rest des Spiels nur eine einfache Meise.
quelle
Wechseln
Picks zufällig in der ersten Runde, dann wechselt. Immer Mängel in den letzten 10 Runden.
quelle
Warte auf 50
Nach 50 Fehlern, lass es sie haben!
quelle
Irgendwie naiv
Ich gehe einfach davon aus, dass wenn Sie in den letzten n Runden weniger als die Flip-Wahrscheinlichkeit (ungefähr) verloren haben , es ein Rauschen war und nicht, dass Sie gemein sind!
Habe nicht herausgefunden, was das beste n ist , könnte das genauer untersuchen.
quelle
Alle drei
Defekte alle drei Umdrehungen unabhängig. Defekte auch die letzten 50 Umdrehungen. Auch defekt, wenn sein Gegner 4 von 5 der letzten Runden defekt ist.
quelle
Eimer
Spielt sich schön anzufangen. Betrachtet die letzten 20, wenn <25% d c zurückgibt,> 75% d, d zurückgibt und dazwischen zufällig entlang einer linearen Wahrscheinlichkeitsfunktion wählt. Letzte 50, Mängel. Hatte dies zuletzt 10 aber sah viele der letzten 50 Mängel.
Lassen Sie mich hier zum ersten Mal wissen, ob etwas repariert werden muss (oder wie ich dies testen kann).
quelle
players
für schnelle Iterationen entfernen .Tit-For-Stat
Mängel, wenn der Gegner mehr als die Hälfte der Zeit gescheitert ist.
quelle