Bestenliste
154 Calculator
144 Taxman
138 Statistician
137 Solver
137 RandoAggroLawyer
136 Gambler
134 Turncoat
119 Lawyer
119 BloodyMurder
113 Bandit
79 Challenger
74 Mask
64 Random
Der Taschenrechner von Brilliand ist der Gewinner!Seine Antwort wird akzeptiert, aber das heißt nicht, dass die Herausforderung vorbei ist. Sie können gerne neue Einträge einreichen oder Ihre aktuellen bearbeiten und versuchen, ihn vom Thron zu stoßen. Ich werde dem Anführer Ende des Monats ein Kopfgeld gewähren.
Spielregeln
Coup ist ein Kartenspiel für 2-6 Spieler, das wir zu zweit spielen werden. Es besteht aus einer Münzschatzkammer (für unsere Zwecke unendlich) und einem Kartenspiel mit 15 Karten, die jeweils 3 der folgenden Typen enthalten: Botschafter, Attentäter, Kapitän, Contessa, Herzog. Zu Beginn des Spiels erhält jeder Spieler eine Münze und teilt zwei Karten nach dem Zufallsprinzip aus, die er so lange geheim hält, bis sie benötigt werden. Das Ziel ist, der letzte Spieler zu sein, der Karten auf der Hand hat.
In ihrem Zug kann ein Spieler unabhängig von seinen Karten eine der folgenden Aktionen ausführen:
- Einkommen: Nimm 1 Münze aus der Schatzkammer. Unblockierbar und unbestreitbar.
- Auslandshilfe: Nimm 2 Münzen aus der Schatzkammer. Kann von einem Spieler mit einem Herzog geblockt werden. Unanfechtbar.
- Coup: Entfernen Sie eine Karte eines Gegners Ihrer Wahl aus dem Spiel. Kostet 7 Münzen. Das Opfer kann wählen, welche Karte abgelegt werden soll. Wenn ein Spieler zu Beginn seines Zuges 10 oder mehr Münzen hat, muss er einen Coup durchführen. Unblockierbar und unbestreitbar.
Abhängig von ihren Karten können die Spieler auch eine der folgenden Aktionen ausführen:
- Tausch: Ein Spieler mit einem Botschafter darf zwei Karten vom Stapel nehmen. Dann können sie aus ihrer Hand und den gezogenen Karten so viele Karten auswählen, wie sie ursprünglich hatten. (Das heißt, wenn sie nur eine Karte hatten, können sie diese gegen eine der gezogenen Karten tauschen oder behalten, und wenn sie zwei Karten hatten, können sie zwei der vier Karten wählen.) Die beiden unerwünschten Karten werden auf den Stapel zurückgelegt . Unblockierbar, aber herausfordernd.
- Attentäter: Ein Spieler mit einem Attentäter kann 3 Münzen ausgeben, um die Karte eines Gegners aus dem Spiel zu entfernen. Das Opfer kann wählen, welche Karte abgelegt werden soll. Kann von einem Spieler mit einer Contessa geblockt werden. In diesem Fall werden die Münzen nicht zurückgegeben. Challenge, in welchem Fall die Münzen werden zurückgegeben.
- Stehlen: Ein Spieler mit einem Kapitän darf seinem Gegner zwei Münzen abnehmen. Hat der Gegner eine Münze, nimmt er diese eine Münze. Hat der Gegner keine Münzen, darf er nicht stehlen. Kann von einem Spieler mit einem Botschafter oder einem Kapitän geblockt werden. Herausfordernd.
- Steuer: Ein Spieler mit einem Herzog kann 3 Münzen aus der Schatzkammer nehmen. Unblockierbar, aber herausfordernd.
Der schwierige Teil des Coups ist, dass die Spieler darüber lügen dürfen, welche Karten sie haben! Man muss keine Karte haben, um zu versuchen, die damit verbundene Aktion oder den damit verbundenen Block auszuführen.
Wenn ein Spieler die Aktion einer Karte ausführt, kann jeder Gegner (auch einer, der durch diese Aktion nicht geschädigt wird) den Schauspieler herausfordern und sagen, er glaube nicht, dass er die Karte für diese Aktion hat. Wenn der Herausforderer korrekt ist, wird die Aktion abgebrochen und der Darsteller muss eine Karte seiner Wahl ablegen (wobei er gegebenenfalls ausgegebene Münzen zurückerhält). Wenn nicht, wird die Aktion ausgeführt, der Schauspieler legt die Karte, über die er herausgefordert wurde, auf das Deck zurück und zieht eine neue Karte, und der Herausforderer muss eine seiner Karten ablegen. Die Spieler müssen ehrlich sein, welche Karten sie haben, wenn sie herausgefordert werden.
Karten, die mit Assassinate, Coup und verlorenen Herausforderungen aus dem Spiel entfernt wurden, werden nicht in den Stapel zurückgelegt, aber Karten, die als Teil einer gewonnenen Herausforderung aufgedeckt wurden, werden in den Stapel zurückgelegt.
Blöcke können wie Aktionen herausgefordert werden. Wenn zum Beispiel Spieler A fremde Hilfe beansprucht und Spieler B sagt "Ich habe einen Herzog und ich blockiere deine fremde Hilfe", kann A sagen "Ich glaube nicht, dass du einen Herzog hast." Wenn diese Behauptung korrekt ist, verliert B eine Karte, weil er in einer Lüge gefangen ist, und A nimmt 2 Münzen. Ist dies nicht der Fall, verliert A eine Karte und erhält keine Münzen, und B muss seinen Herzog wieder auf den Stapel legen und eine neue Karte ziehen.
Die Art und Weise, wie Blockaden und Herausforderungen mit Assassinate funktionieren, muss konkretisiert werden. Angenommen, Spieler A sagt "Ich habe einen Attentäter, und ich ermorden Spieler B". Wenn B nicht versucht, A herauszufordern oder zu blockieren, wird das Attentat ausgeführt: B verliert eine Karte und A zahlt 3 Münzen.
Alternativ kann B herausfordern, indem er sagt "Ich glaube nicht, dass Sie einen Assassinen haben". Wenn dies zutrifft, wirft A eine Karte ab und die Münzen werden zurückgegeben, während B nicht betroffen ist und A an der Reihe ist. Wenn der Glaube von B falsch ist und A einen Attentäter hält, verliert B beide Karten und versagt, eine für die falsche Herausforderung und eine für das Attentat.
Anstatt herauszufordern, könnte B sagen "Ich habe eine Contessa und ich blockiere den Attentäter". Wenn A an B glaubt, ist A an der Reihe und seine Münzen werden nicht zurückgegeben. Aber A kann den Block herausfordern und sagen "Ich glaube nicht, dass Sie eine Contessa haben." Wenn B tatsächlich eine Contessa hat, verliert A eine Karte für die falsche Herausforderung. Aber wenn B dies nicht tut, verliert B eine Karte, weil er in einer Lüge gefangen ist, und eine weitere, die er durch das Attentat erhalten hat.
Eine ähnliche Logik wie bei der obigen Erklärung gilt für die Fähigkeit "Diebstahl des Kapitäns", bei der entweder die Aktion oder der Block herausgefordert werden kann.
Es ist möglich, dass Sie beide Karten verlieren und in einem Zug eliminiert werden, wenn Sie einen Attentäter erfolglos herausfordern oder wenn Sie erwischt werden, weil Sie fälschlicherweise behaupten, eine Contessa zu haben, die ein Attentat blockiert. Sie verlieren eine Karte aus der Herausforderung und eine Karte aus dem Attentat.
Herausforderung
Ihre Aufgabe ist es, ein Programm zu schreiben, das Coup spielt. Es wird als Befehlszeilenargument angegeben:
- Der Name einer Datei, die die Liste der bisherigen Aktionen ihrer und ihrer Gegner enthält.
- Eine Ganzzahl von 0 bis 12, die die Münzzahl des Gegners angibt.
- Eine Ganzzahl von 0 bis 12, die die Anzahl der Münzen angibt.
- Eine Zeichenfolge mit ein bis vier Zeichen, die die Karten angibt. Normalerweise sind dies einfach die eine oder die zwei Karten, die Ihr Programm hat. Wenn Ihr Programm jedoch gerade an einem Exchange erfolgreich war, ist es n + 2 Zeichen lang, wobei n die Anzahl der verbleibenden Karten ist. Ihr Programm muss dann das n ausgeben Karten, die es behalten möchte, an STDOUT ausgeben. (Programme dürfen STDOUT nur zu diesem Zweck lesen oder darauf zugreifen. Wenn Sie eine Debug-Ausgabe erstellen möchten, schreiben Sie bitte an STDERR.)
- Ein oder mehrere Argumente, die auf rechtliche Schritte hinweisen.
(Beispielaufruf: yourprogram file.txt 1 7 '~!' a c p q
"Ihr Gegner hat 1 Münze. Sie haben 7 Münzen, einen Botschafter und eine Contessa. In file.txt können Sie unter Berücksichtigung des Spielverlaufs und des aktuellen Spielzustands a, c, p oder q auswählen. ")
Ihr Programm muss ein oder (in zwei bestimmten Situationen) zwei Zeichen an die angegebene Datei anhängen, um deren Aktion anzuzeigen. Ansonsten darf der vorhandene Inhalt der Datei nicht verändert werden. Es kann beliebige neue Dateien erstellen, jedoch nur in dem Verzeichnis, in dem es ausgeführt wird. Bitte geben Sie alle notwendigen Befehle an, um Ihr Programm zu kompilieren und auszuführen.
Ich habe unten zwei Beispielkonkurrenten angegeben, die in Go geschrieben sind.
Das Ausgabeformat ist:
I\n
: Einkommen. Rechtliche Antworten: jede Aktion am Zug (vorausgesetzt, man hat die Münzen für Attentat / Coup).F
: Entwicklungshilfe. Rechtliche Antworten:d
(Block als Herzog),p
(lassen Sie es passieren).C
: Coup. Rechtliche Maßnahmen: je nachdem , was der_
,'
,<
,=
,0
in der Hand.E
: Austausch. Rechtliche Maßnahmen:q
(Herausforderung, die Spieler nicht zu glauben , hat einen Botschafter)p
.T
: MwSt. Rechtliche Antworten:q
(Anfechtung, nicht glaubend, dass der Spieler einen Herzog hat)p
,.A
: Ermordung. Rechtliche Maßnahmen:s
(Block als Contessa),q
(challenge), und von welch auch immer_
,'
,<
,=
,0
ist in der Hand.S
: Stehlen. Rechtliche Maßnahmen:a
(Block als Botschafterin),c
(Block als Kapitän),q
(Herausforderung, den Spieler nicht glauben , einen Kapitän hat)p
.d
: Block Foreign Aid als Herzog. Rechtliche Antworten:\n
(Akzeptiere den Block),q
(Fordere heraus, nicht zu glauben, dass der Spieler einen Herzog hat).a
: Blockiere einen Diebstahl als Botschafter. Rechtliche Antworten:\n
(Akzeptieren Sie den Block),q
(Fordern Sie den Spieler heraus und glauben Sie nicht, dass er einen Botschafter hat).c
: Blockiere einen Steal als Captain.\n
(Akzeptiere den Block),q
(Fordere heraus, ohne zu glauben, dass der Spieler einen Kapitän hat).s
: Blockiere einen Attentäter als Contessa. Rechtliche Antworten:\n
(Akzeptiere den Block),q
(Fordere heraus, ohne zu glauben, dass der Spieler eine Contessa hat).p
: Bestehen Sie eine Herausforderung, wenn Sie nicht an der Reihe sind. Nicht verwendet mitA
; ablehnen, um ein Attentat herauszufordern_'<=0
. Legale Antwort:\n
(beende deinen Zug) und schreibe die Karten, die du behalten möchtest, vom vierten Befehlszeilenargument an STDOUT, wenn du gerade erfolgreich an einer Börse warst.q
: Fordere die letzte Aktion oder Blockierung heraus. Rechtliche Reaktion: Wenn Sie die Karte für die angefochtene Aktion haben, welche~^*!$
davon auch immer. Wenn nicht, dann was auch immer_'<=0
von Ihrer Hand, die Sie aufgeben möchten, gefolgt von einem Zeilenumbruch, wenn Sie an der Reihe sind.~
,^
,*
,!
,$
: Zeigen , dass Sie die Wahrheit über halten, wurden jeweils zu sagen, ein Botschafter, ein Assassine, ein Hauptmann, ein Contessa und ein Duke (auch repräsentieren diese Karten in Befehlszeilenargumente verwendet, und STDOUT Ausgabe in einem Exchange ). Rechtliche Maßnahmen: je nachdem , was der_
,'
,<
,=
,0
Sie in der Hand haben._
,'
,<
,=
,0
: Geben als Strafe jeweils einen Botschafter, und Attentäter, ein Kapitän, ein Contessa, und einen Herzog , weil Sie eine Herausforderung verloren oder wurden / couped Assassinated. Legal Antwort:\n
.\n
: Beende deinen Zug und lehne es ab, einen Block herauszufordern, falls zutreffend. Rechtliche Antworten: Jede Aktion in Großbuchstaben (vorausgesetzt, man hat die Münzen für Assassinate / Coup und der Gegner hat die Münzen für Steal).
Das Format hat die folgenden nützlichen Eigenschaften:
- Spielzüge beginnen mit einem Großbuchstaben.
- Linien folgen dem Muster: Großbuchstaben, Kleinbuchstaben, optional Satzzeichen oder 0 für aufgedeckte Karten, Zeilenvorschub.
- Eine Datei, die mit einer neuen Zeile endet, oder eine leere Datei, zeigt an, dass dies der Beginn des Programmzugs ist und dass eine Großbuchstabenaktion ausgewählt werden muss.
- Die rechtlichen Schritte, die Sie bei einem Aufruf ausführen dürfen, werden in der Regel eindeutig durch das letzte Zeichen in der Datei bestimmt. Die Ausnahme ist
q
, dass eine gewisse Logik damit verbunden sein wird. Sehen Sie sich die Funktionget_legal_actions
im Arbiter an, um dies zu verstehen. Oder Sie können einfach die rechtlichen Schritte verwenden, die Sie in der Befehlszeile angegeben haben. - Eine gerade Anzahl von Zeichen in einer Zeile zeigt an, dass Sie an der Reihe sind und Ihr Programm aufgefordert wird, eine Aktion auszuwählen, einen Block herauszufordern oder die Reihe zu beenden.
- Eine ungerade Anzahl von Zeichen in einer Zeile weist darauf hin, dass Sie an der Reihe sind und Ihr Programm aufgefordert wird, eine Karte zu blockieren, herauszufordern oder aufzudecken / abzugeben.
Ich werde für jede Aktion ein Beispiel geben.
I\n
ist am einfachsten zu verstehen. Ein Programm nimmt eine Münze des Einkommens und beendet dann seinen Zug. Dies ist einer der beiden Fälle, in denen Programme zwei Zeichen drucken müssen, da Einkommen die einzige Aktion ist, bei der der Gegner nicht betroffen ist und weder blocken noch herausfordern kann.
Fp\n
Bedeutet, dass ein Programm Foreign Aid genommen hat und sein Gegner abgelehnt hat, zu blockieren ( p
). Bei seinem nächsten Aufruf stellte das erste Programm fest, dass es nach dem letzten Kleinbuchstaben p
und / oder der geraden Anzahl von Zeichen in dieser Zeile diesen noch nicht beendeten Zug gemacht hat, sodass es weiß, dass es seinen aktuellen Zug beendet, indem es eine neue Zeile druckt.
C=\n
bedeutet, dass ein Programm einen Coup gestartet hat. Sein Gegner, der wusste, dass er wegen der ungeraden Anzahl von Buchstaben in der Leitung gerufen wurde, gab eine Contessa auf. Wieder wusste das erste Programm, dass dies der unvollständige Zug bei seinem nächsten Aufruf durch die gerade Anzahl von Zeichen in der Zeile war, also schrieb es eine neue Zeile, um seinen Zug zu beenden.
Eq~<\n
würde bedeuten, dass ein Programm versucht hat, einen Austausch ( E
) und sein Gegner herauszufordern ( q
). Das Austauschprogramm ergab, dass es wahrheitsgemäß einen Botschafter hatte ( ~
) und der Herausforderer einen Kapitän zur Bestrafung aufgab ( <
). Nach dem Beenden des Herausforderers wird das Austauschprogramm erneut mit einer vierstelligen Zeichenfolge als viertem Befehlszeilenargument aufgerufen (oder mit drei Zeichen, wenn es nur eine Karte enthält). Es schreibt die Zeichen, die die Karten darstellen, die es behalten möchte, an STDOUT und eine neue Zeile in die Datei.
Tq'\n
Das bedeutet, dass ein Programm versucht hat, eine unwahre Steuer zu erheben, herausgefordert wurde und einen Attentäter aufgab. Es zeigt den anderen Fall, in dem zwei Zeichen geschrieben werden: Wenn Sie an der Reihe sind und gezwungen sind, eine Karte aufzugeben - entweder aufgrund der richtigen Herausforderung eines Gegners (wie hier) oder aufgrund Ihrer falschen Herausforderung eines Blocks -, müssen Sie beide schreiben die Karte, die du aufgibst, und ein Zeilenvorschub, um deinen Zug zu beenden.
Asq!'\n
Das würde bedeuten, dass Spieler B versucht hat, Spieler A ( A
) zu ermorden , aber A behauptet, eine Contessa zu haben, um ihn zu blockieren ( s
). B glaubte A nicht und forderte heraus ( q
). A enthüllte, dass sie tatsächlich eine Contessa hatten ( !
). B gab einen Assassinen als Strafe auf, verlor seine Münzen und beendete seinen Zug ( '\n
), indem er wie in diesem speziellen Fall zwei Zeichen schrieb. (Wenn A entschieden hätte, nicht zu blocken oder herauszufordern, hätte es schreiben können =
, und dann hätte sein Gegner gesehen, dass die Runde vorbei war, und eine neue Zeile geschrieben. Die Zeile hätte dann gelesen A=\n
, wie im Coup-Beispiel.)
Sq*0\n
bedeutet, dass ein Programm versucht, etwas zu stehlen; der Gegner fordert heraus, nicht zu glauben, dass der Dieb einen Kapitän hat; und das ursprüngliche Programm enthüllt einen Kapitän, so dass die Herausforderung nicht erfolgreich ist und der Herausforderer einen Herzog als Strafe aufgibt. (Eine weitere Möglichkeit für den Gegner wäre, den Diebstahl durch Schreiben anzunehmen p
. Der Gegner erkennt dann das Ende seines Zuges und schreibt \n
, was zu einer Zeile mit Sp\n
. Führt .)
Der Schiedsrichter
Programme werden von diesem Python-Skript aufgerufen. Es werden zehn Runden durchgeführt, in denen sich jeder Wettbewerber mit jedem anderen Wettbewerber auseinandersetzt, während er als Erster und Zweiter antritt. Es verfolgt Karten- und Münzzählungen und bestimmt den Verlierer, indem das erste Programm eine Zeile mit einem Satzzeichen zweimal beendet. Programme, die mit einem Nicht-Null-Status beendet werden, die Datei ändern, einen illegalen Vorgang in die Datei schreiben oder versuchen, einen illegalen Austausch durchzuführen, verfallen automatisch. Wenn jeder Spieler mehr als 100 Aktionen einschließlich Blöcken und Herausforderungen ausführt, ohne einen Gewinner zu haben, verlieren beide Programme. Ein Gewinner erhält einen Punkt. Der Spieler, dessen Programm die meisten Punkte erzielt, gewinnt.
Ich schlage vor, Sie lesen den Quellcode des Schiedsrichters, insbesondere die get_legal_actions
Funktion. Es kann Ihnen helfen, die Spezifikation zu verstehen und Ihre eigenen Programme zu schreiben.
import itertools
import os
import random
import subprocess
class Player:
def __init__(self, name, command):
self.name = name
self.command = command
self.score = 0
self.coins = 1
self.cards = ""
actions_dict = {
'E': '_', 'T': '0', 'A': "'", 'S': '<',
'd': '0', 'a': '_', 'c': '<', 's': '='
}
punishment_to_reveal = {'_': '~', "'": '^', '<': '*', '=': '!', '0': '$'}
reveal_to_punishment = {
punishment_to_reveal[k]: k for k in punishment_to_reveal
}
def get_legal_actions(history, player, opponent):
c = history[-1]
result = ""
# Our turn begins; choose an action.
if c == '\n':
if player.coins >= 10:
return ["C"]
ret = ['I\n'] + list("FET")
if player.coins >= 3:
ret.append("A")
if player.coins >= 7:
ret.append('C')
if opponent.coins > 0:
ret.append("S")
return ret
# Opponent attempted foreign aid; can pass or claim Duke to block.
elif c == 'F':
return list('dp')
# We have been Couped; must surrender a card.
elif c == 'C':
return player.cards
# We failed a challenge; must surrender a card and print a newline
# if it is our turn.
elif c in '~^*!$':
if history[-3] in 'acds':
return [card + '\n' for card in player.cards]
return player.cards
# Opponent attempted Exchange or Tax; can pass or challenge.
elif c == 'E' or c == 'T':
return list('pq')
# Opponent attempted an Assassination; can block, challenge, or give in.
elif c == 'A':
return list('sq') + player.cards
# Opponent attempted to Steal; can pass, block as Ambassador/Captain,
# or challenge.
elif c == 'S':
return list('acpq')
# Opponent blocked; can challenge or withdraw.
elif c in 'acds':
return list('q\n')
# Opponent passed on blocking Foreign Aid/Tax/Exchange or they gave up a
# card as punishment, must end turn.
elif c in "p_'<=0":
return ['\n']
# Opponent challenged us.
elif c == 'q':
challenged_action = history[-2]
# If we have the card they challenged us over, must reveal it.
necessary_card = actions_dict[challenged_action]
if necessary_card in player.cards:
return [punishment_to_reveal[necessary_card]]
# Otherwise, we can give up either of our cards, writing a newline
# if it is our turn.
if challenged_action in 'acds':
return list(player.cards)
else:
return [card + '\n' for card in player.cards]
else:
return None
deck = ['_', "'", '<', '=', '0'] * 3
random.shuffle(deck)
def determine_turn_effects(line, output, cards, current_player, opponent):
last_action = line[-2]
# Only operate if the opponent declined to challenge (p) or the
# program successfully challenged their block
if last_action in "p_'<=0":
primary_action = line[0]
# Foreign Aid
if primary_action == 'F':
print current_player.name, "received 2 coins of Foreign Aid"
current_player.coins += 2
# Tax
elif primary_action == 'T':
print current_player.name, "received 3 coins of Tax"
current_player.coins += 3
# Steal
elif primary_action == 'S':
stolen_coins = 1 if opponent.coins == 1 else 2
print current_player.name,\
"stole %d coins from %s" % (stolen_coins, opponent.name)
current_player.coins += stolen_coins
opponent.coins -= stolen_coins
# Exchange, store desired cards and replace undesired ones
elif primary_action == 'E':
print current_player.name, "tried to take %r" % output, "from", cards
legal_outputs = [''.join(p) for p in itertools.permutations(
cards, len(current_player.cards))]
if output not in legal_outputs:
print current_player.name, "forfeits by illegal exchange"
return opponent
current_player.cards = [
reveal_to_punishment[c] for c in output
]
undesired_cards = list(cards)
for c in output:
undesired_cards.remove(c)
for card in undesired_cards:
deck.append(reveal_to_punishment[card])
random.shuffle(deck)
# Coins are not returned from a successful Contessa block
elif last_action == 's':
print current_player.name, "lost 3 coins from a Contessa block"
current_player.coins -= 3
return None
def play_game(player1, player2, round_number, game_number):
outfilename = os.path.abspath(__file__)[:-len(__file__)] + '_'.join([
player1.name, player2.name, str(round_number), str(game_number)
]) + '.txt'
print outfilename
f = open(outfilename, 'w')
f.close()
players_list = [player1, player2]
player1.cards = [deck.pop(), deck.pop()]
player2.cards = [deck.pop(), deck.pop()]
current_player_index = 0
for i in range(200):
current_player = players_list[current_player_index]
opponent = players_list[(current_player_index+1) % 2]
legal_actions = []
original_contents = []
original_contents_joined = ""
with open(outfilename, 'r') as outfile:
original_contents = outfile.readlines()
original_contents_joined = ''.join(original_contents)
if len(original_contents) == 0:
legal_actions = ['I\n'] + list("FEST")
else:
legal_actions = get_legal_actions(
original_contents[-1], current_player, opponent)
if not legal_actions:
print "Error: file ended in invalid character"
return current_player
# Has the player completed an Exchange? Pass them new cards if so.
exchange_cards = ""
old_last_line = original_contents[-1] if len(original_contents) > 0 else '\n'
if old_last_line[-1] != '\n' and old_last_line[0] == 'E' and \
len(old_last_line) % 2 == 0 and old_last_line[-1] in "p_'<=0":
exchange_cards = punishment_to_reveal[deck.pop()] + \
punishment_to_reveal[deck.pop()]
cards = exchange_cards + ''.join(
punishment_to_reveal[card] for card in current_player.cards)
args = current_player.command + [
outfilename,
str(opponent.coins),
str(current_player.coins),
cards
] + legal_actions
print ' '.join(args)
output = ""
os.chdir(current_player.name)
try:
output = subprocess.check_output(args)
# Competitors that fail to execute must forfeit
except subprocess.CalledProcessError:
print current_player.name, "forfeits by non-zero exit status"
return opponent
finally:
os.chdir('..')
new_contents = []
new_contents_joined = ""
with open(outfilename, 'r') as outfile:
new_contents = outfile.readlines()
new_contents_joined = ''.join(new_contents)
if original_contents_joined != new_contents_joined[:-2] and \
original_contents_joined != new_contents_joined[:-1]:
print current_player.name, "forfeits by modifying the file"
print "old:", original_contents
print "new:", new_contents
return opponent
new_last_line = new_contents[-1]
the_move_made = ""
for action in legal_actions:
if new_last_line.endswith(action):
the_move_made = action
break
# Competitors that make an illegal move must forfeit
if not the_move_made:
print current_player.name, "forfeits with an illegal move,",\
"last line: %r" % new_last_line
print opponent.name, "wins!"
return opponent
print current_player.name, "played %r" % the_move_made
# Side effects of moves.
#
# Income, give the current player a coin.
if the_move_made == "I\n":
print current_player.name, "received 1 coin of income"
current_player.coins += 1
# The program surrendered a card on its turn; take it away.
elif len(the_move_made) == 2:
print current_player.name, "lost a card from being challenged"
current_player.cards.remove(the_move_made[0])
# Coins are not returned from a successful Contessa block
if new_last_line[-3] == '!':
print current_player.name, "lost 3 coins from a Contessa block"
current_player.coins -= 3
# The program surrendered a card when it was not its turn.
elif the_move_made in "_'<=0":
print current_player.name, "gave up a", the_move_made
current_player.cards.remove(the_move_made)
if new_last_line[0] == 'C':
opponent.coins -= 7
elif new_last_line[0] == 'A':
opponent.coins -= 3
# Did the program unsuccessfully challenge an Assassination
# (e.g. Aq^0\n)
# or get caught falsely blocking with a Contessa
# (e.g. Asq0\n)?
# If yes, it loses right away.
if new_last_line[0] == 'A' and new_last_line[1] in 'qs' and \
len(new_last_line) == 4:
print current_player.name, "lost both cards in the same turn."
print opponent.name, "wins!"
return opponent
elif the_move_made == 'S':
print current_player.name, "attempted Steal"
elif the_move_made == 'T':
print current_player.name, "attempted Tax"
elif the_move_made == 'A':
print current_player.name, "attempted Assassinate"
elif the_move_made == 'C':
print current_player.name, "launched a Coup"
elif the_move_made == 'F':
print current_player.name, "attempted Foreign Aid"
elif the_move_made == 'E':
print current_player.name, "attempted Exchange"
elif the_move_made == 'q':
print current_player.name, "challenged"
elif the_move_made == 'p':
print current_player.name, "passed"
elif the_move_made == 'a':
print current_player.name, "blocked with an Ambassador"
elif the_move_made == 'c':
print current_player.name, "blocked with a Captain"
elif the_move_made == 's':
print current_player.name, "blocked with a Contessa"
elif the_move_made == 'd':
print current_player.name, "blocked with a Duke"
# The program revealed a card from an opponent's unsuccessful challenge.
# Give it a new card.
# Special case: a program whose Exchange is unsuccessfully challenged
# may keep the Ambassador it revealed in the Exchange, so give a new
# card for a revealed Ambassador only if it was used to block a Steal.
elif the_move_made in '^*!$' or (the_move_made == '~' and
new_last_line[0] == 'S'):
p = reveal_to_punishment[the_move_made]
current_player.cards.remove(p)
current_player.cards.append(deck.pop())
deck.append(p)
random.shuffle(deck)
print current_player.name, "did have a", the_move_made
# The program ended its turn. We must examine the rest of the line to
# determine the side effects.
elif the_move_made == '\n':
potential_winner = determine_turn_effects(
new_last_line, output.strip(), cards, current_player,
opponent)
if potential_winner:
print potential_winner.name,\
"wins because their opponent made an illegal exchange!"
return potential_winner
# One player has lost all their cards. Victory for the opponent!
if current_player.cards == []:
print opponent.name, "wins by eliminating both opponent cards!"
return opponent
current_player_index += 1
current_player_index %= 2
return None
competitors = []
competitors.append(Player("Challenger", ["./challenger"]))
competitors.append(Player("Random", ["./random"]))
# ...More competitors here
for i in range(10):
print "-- Round", i
j = 0
for pairing in itertools.permutations(competitors, 2):
player1, player2 = pairing
print '--- Game', j, ':', player1.name, 'vs.', player2.name
winner = play_game(player1, player2, i, j)
if not winner:
j += 1
continue
winner.score += 1
player1.coins = 1
player1.cards = ""
player2.coins = 1
player2.cards = ""
deck = ['_', "'", '<', '=', '0'] * 3
random.shuffle(deck)
j += 1
competitors.sort(reverse=True, key=lambda player: player.score)
for player in competitors:
print '%5d %s' % (player.score, player.name)
Sonstiges
Ein Programm kann keinen Code haben, der für ein anderes Programm spezifisch ist, und Programme können sich nicht gegenseitig helfen. (Möglicherweise haben Sie mehrere Programme, die jedoch in keiner Weise miteinander interagieren können.)
Wenn Ihr Programm beide Karten im selben Zug verliert, muss es nur eine schreiben. Der Schiedsrichter wird feststellen, dass es beseitigt wurde.
Es ist möglich und empfohlen, aber nicht erforderlich, dass Programme den Verlauf des Spiels in der Datei überprüfen. Auf diese Weise können sie feststellen, welche Karten ihr Gegner angeblich hat, und sie in einer Lüge fangen.
Im echten Coup-Spiel können Sie eine Aktion herausfordern und dann versuchen, sie in derselben Runde zu blockieren. Ich könnte die Spezifikation nicht zum Laufen bringen, wenn ich das zulasse, also könnten Sie entweder eine bestimmte Aktion anfechten oder blockieren, aber nicht beide.
Ich entschuldige mich bei @PeterTaylor, der mir beim letzten Posten dieses Dokuments vorgeschlagen hat, es in der Sandbox zu veröffentlichen und das Protokoll zu überarbeiten, um die Ausgabe in STDOUT / STDIN hin und her zu leiten. Ich habe mich so sehr bemüht, das zum Laufen zu bringen, und einen ganzen Tag damit verbracht (als ich bereits einen ganzen Tag damit verbracht hatte, die ursprüngliche Herausforderung zu schreiben). Die Implementierung von Exchanges erwies sich jedoch als sehr kompliziert. Außerdem hätte dies die Komplexität der Einreichungen erhöht, da sie ihre eigene Münzzählung nachverfolgen mussten. Also habe ich die Herausforderung mehr oder weniger so gepostet, wie sie ursprünglich war.
S
, Programm B blockiert durch Schreiben c
, A lehnt es ab, durch Schreiben herauszufordern \n
. Eine erfolgreiche Herausforderung eines Diebstahls würde lauten: A schreibt S
, B fordert schriftlich heraus q
, A räumt die Herausforderung schriftlich ein, z. B. _\n
Sie dürfen pro Spielzug nur eine Aktion ausführen, einschließlich Tausch. Die rechtlichen Antworten auf Exchange lauten "Bestanden" und "Anfechtung".