Classifica
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
È disponibile un archivio dell'ultima corrispondenza, incluso il registro e tutti i file di output.
Calculator, di Brilliand, è il vincitore! La sua risposta è accettata, ma ciò non significa che la sfida sia finita. Sentiti libero di inviare nuove voci o modificare quelle attuali e provare a farlo cadere dal suo trono. Alla fine del mese assegnerò un premio al leader.
Regole di gioco
Coup è un gioco di carte progettato per 2-6 giocatori, che giocheremo con due. Consiste in un tesoro di monete (infinito per i nostri scopi) e un mazzo di 15 carte, contenente 3 ciascuno dei seguenti tipi: Ambasciatore, Assassino, Capitano, Contessa, Duca. All'inizio del gioco, a ogni giocatore viene data una moneta e distribuite due carte a caso, che mantengono segrete fino al momento necessario. L'oggetto deve essere l'ultimo giocatore con le carte in mano.
Nel loro turno, un giocatore può effettuare una delle seguenti azioni indipendentemente dalle proprie carte:
- Entrate: prendi 1 moneta dal tesoro. Non bloccabile e insindacabile.
- Aiuti esteri: prendi 2 monete dal tesoro. Può essere bloccato da un giocatore con un Duca. Insindacabile.
- Coup: Rimuovi dal gioco una carta di un avversario a tua scelta. Costa 7 monete. La vittima può scegliere quale carta scartare. Se un giocatore ha 10 o più monete all'inizio del proprio turno, deve Coup. Non bloccabile e insindacabile.
A seconda delle loro carte, i giocatori possono anche effettuare una delle seguenti azioni come loro turno:
- Scambio: un giocatore con un Ambasciatore può prendere due carte dal mazzo. Quindi possono scegliere tra la loro mano e le carte pescate quante carte originariamente possedevano. (Cioè, se avessero una sola carta, potrebbero scambiarla con una delle carte pescate o tenerla, e se avessero due carte, potranno scegliere una qualsiasi delle quattro carte.) Le due carte indesiderate vengono rimesse nel mazzo . Non bloccabile, ma sfidabile.
- Assassinare: un giocatore con un Assassino può spendere 3 monete per rimuovere la carta di un avversario dal gioco. La vittima può scegliere quale carta scartare. Può essere bloccato da un giocatore con una Contessa, nel qual caso le monete non vengono restituite. Sfidabile, nel qual caso le monete vengono restituite.
- Ruba: un giocatore con un Capitano può prendere due monete dal proprio avversario. Se l'avversario ha una moneta, prenderà quella moneta. Se l'avversario ha zero monete, non può rubare. Può essere bloccato da un giocatore con un ambasciatore o un capitano. Impugnabile.
- Imposta: un giocatore con un Duca può prendere 3 monete dal tesoro. Non bloccabile, ma sfidabile.
La parte difficile di Coup è che i giocatori possono mentire su quali carte hanno! Non è necessario disporre di una carta per tentare di eseguire l'azione o il blocco ad essa associati.
Quando un giocatore esegue un'azione di una carta, qualsiasi avversario (anche uno che non è danneggiato da quell'azione) può sfidare l'attore e dire di non credere di avere la carta per quell'azione. Se lo sfidante ha ragione, l'azione viene annullata e l'attore deve scartare una carta a sua scelta (riprendendo le monete che ha speso, se applicabile). Altrimenti, l'azione viene intrapresa, l'attore restituisce al mazzo la carta sulla quale erano stati sfidati e ne pesca una nuova, e lo sfidante deve scartare una delle sue carte. I giocatori devono essere sinceri su quali carte possiedono quando vengono sfidati.
Le carte eliminate dal gioco con Assassinato, Colpo e sfide perse non vengono restituite al mazzo, ma le carte rivelate come parte di una sfida vinta vengono restituite al mazzo.
I blocchi possono essere sfidati proprio come le azioni. Ad esempio, se il giocatore A richiede un aiuto straniero e il giocatore B dice "Ho un duca e blocco il tuo aiuto straniero", A potrebbe dire "Non credo che tu abbia un duca". Se tale affermazione è corretta, B perde una carta per essere catturato in una bugia e A prende 2 monete; in caso contrario, A perde una carta e non ottiene monete, e B deve riportare il proprio Duca sul mazzo e pescare una nuova carta.
Il modo in cui blocchi e sfide funzionano con Assassinate deve essere chiarito. Supponiamo che il Giocatore A dica "Ho un Assassino e Assassino il Giocatore B". Se B non tenta di sfidare o bloccare A, l'assassinio subisce: B perde una carta e A paga 3 monete.
In alternativa, B può sfidare dicendo "Non credo che tu abbia un Assassino". Se questo è vero, allora A scarta una carta e le loro monete vengono restituite, mentre B non viene influenzato e il turno di A termina. Se la convinzione di B è errata e A detiene un Assassino, allora B perde entrambe le carte e fallisce, una per la sfida errata e una per Assassinio.
Invece di sfidare, B potrebbe dire "Ho una contessa e blocco l'assassinio". Se A crede a B, il turno di A termina e le loro monete non vengono restituite. Ma A può sfidare il blocco e dire "Non credo che tu abbia una Contessa." Se B detiene effettivamente una contessa, allora A perde una carta per la sfida errata. Ma se B non lo fa, allora B perde una carta per essere catturato in una bugia e un'altra dall'assassinio.
Una logica simile alla spiegazione precedente si applica all'abilità Rubare del Capitano, in cui l'azione o il blocco possono essere sfidati.
È possibile perdere entrambe le carte ed essere eliminati in un turno, se si sfida un Assassinato senza successo o si viene sorpresi a sostenere che si ha una Contessa per bloccare un Assassinio. Perdi una carta dalla sfida e una carta dall'assassinio.
Sfida
Il tuo compito è quello di scrivere un programma che riprodurrà Coup. Verrà fornito come argomento della riga di comando:
- Il nome di un file contenente l'elenco delle sue azioni e quelle dei suoi avversari finora.
- Un numero intero compreso tra 0 e 12 che indica il conteggio delle monete dell'avversario.
- Un numero intero compreso tra 0 e 12 che indica il conteggio delle monete.
- Una stringa lunga da uno a quattro caratteri che indica le sue carte. Normalmente questa sarà semplicemente una o due carte del tuo programma, ma se il tuo programma è appena riuscito in uno scambio, avrà una lunghezza di n + 2 caratteri, dove n è il tuo numero di carte rimanenti. Il tuo programma deve quindi emettere le n carte che desidera conservare su STDOUT. (I programmi non devono leggere o accedere a STDOUT se non per questo scopo - se si desidera produrre output di debug, scrivere a STDERR.)
- Uno o più argomenti che indicano le mosse legali che può effettuare.
(Esempio di invocazione:, che yourprogram file.txt 1 7 '~!' a c p q
significa "Il tuo avversario ha 1 moneta. Hai 7 monete, un Ambasciatore e una Contessa. Scrivi su file.txt la tua scelta di a, c, p o q data la storia del gioco e lo stato di gioco attuale. ")
Il programma deve aggiungere uno o (in due situazioni specifiche) due caratteri al file fornito che indica la sua azione. In caso contrario, non deve modificare il contenuto esistente del file. Può creare tutti i nuovi file che desidera, ma solo all'interno della directory in cui viene eseguito. Fornisci tutti i comandi necessari per compilare ed eseguire il tuo programma.
Di seguito ho fornito due esempi di concorrenti, scritti in Go.
Il formato di output è:
I\n
: Reddito. Risposte legali: qualsiasi azione di turno (supponendo che uno abbia le monete per Assassinare / Colpo di stato).F
: Aiuti esteri. Risposte legali:d
(blocca come duca),p
(lascialo passare).C
: Colpo di stato Risposte legali: a seconda di quale di_
,'
,<
,=
,0
è nelle tue mani.E
: Scambio. Risposte legali:q
(sfida, non credendo il giocatore ha un ambasciatore),p
.T
: Imposta. Risposte legali:q
(sfida, non credendo il giocatore ha un Duke),p
.A
: Assassinare. Risposte giuridiche:s
(a blocchi come Contessa),q
(sfida), e seconda di quale di_
,'
,<
,=
,0
è in mano.S
: Rubare. Risposte giuridiche:a
(a blocchi come un ambasciatore),c
(blocco come un capitano),q
(sfida, non credendo il giocatore ha un capitano),p
.d
: blocca gli aiuti esteri come duca. Risposte legali:\n
(accetta il blocco),q
(sfida, non credere che il giocatore abbia un Duca).a
: blocca un furto come ambasciatore. Risposte legali:\n
(accetta il blocco),q
(sfida, non credere che il giocatore abbia un Ambasciatore).c
: blocca un furto come capitano.\n
(accetta il blocco),q
(sfida, non credere che il giocatore abbia un Capitano).s
: blocca un Assassinato come Contessa. Risposte legali:\n
(accetta il blocco),q
(sfida, non credere che il giocatore abbia una contessa).p
: passa sfidando uno Scambio / Tasse / Ruba quando non è il tuo turno. Non utilizzato conA
; rifiutare di sfidare un Assassinio scrivere uno di_'<=0
. Risposta legale:\n
(termina il tuo turno), e se hai appena avuto successo in uno scambio, scrivi le carte che desideri conservare dal quarto argomento della riga di comando su STDOUT.q
: sfida l'azione o il blocco più recenti. Risposta legale: se hai la carta per l'azione che è stata contestata, qualunque~^*!$
essa fosse. Se non lo fai, qualunque sia la_'<=0
tua mano a cui vuoi rinunciare, seguita da una nuova linea se e solo se è il tuo turno.~
,^
,*
,!
,$
: Rivelano che si stava dicendo la verità circa la detenzione, rispettivamente, un ambasciatore, un Assassino, un capitano, un Contessa, e un Duca (utilizzato anche per rappresentare queste carte in argomenti della riga di comando, e STDOUT uscita in scambio ). Risposte legali: a seconda di quale di_
,'
,<
,=
,0
che avete in mano._
,'
,<
,=
,0
: Rinunciare, come punizione, rispettivamente, un ambasciatore, e assassino, un capitano, un Contessa, e un Duca perché hai perso una sfida o sono stati ASSASSINATO / couped. Risposta giuridica:\n
.\n
: termina il tuo turno, in tal modo diminuendo per sfidare un blocco, se applicabile. Risposte legali: qualsiasi azione in maiuscolo (supponendo che uno abbia le monete per Assassinare / Colpo e l'avversario abbia le monete per Rubare).
Il formato ha le seguenti proprietà utili:
- Le svolte iniziano con una lettera maiuscola.
- Le linee seguono il modello: lettere maiuscole, lettere minuscole, segni di punteggiatura opzionali o 0 per le carte rivelate, riga nuova.
- Un file che termina con una nuova riga o un file vuoto indica che è l'inizio del turno del programma e deve scegliere un'azione in maiuscolo.
- Le azioni legali che è consentito intraprendere su un'invocazione sono generalmente determinate in modo univoco dall'ultimo carattere nel file. L'eccezione è
q
, a cui sarà associata una logica. Vedi la funzioneget_legal_actions
nell'arbitro per capire questo. Oppure puoi semplicemente usare le azioni legali che ti vengono fornite sulla riga di comando. - Un numero pari di personaggi su una linea indica che il turno è tuo e al tuo programma viene chiesto di scegliere un'azione, sfidare un blocco o terminare il suo turno.
- Un numero dispari di personaggi su una linea indica che il turno non è tuo e al tuo programma viene chiesto di bloccare, sfidare o rivelare / consegnare una carta.
Farò un esempio per ogni azione.
I\n
è il più facile da capire. Un programma prende una moneta del reddito, quindi termina il suo turno. Questo è uno dei due casi in cui i programmi devono stampare due personaggi, poiché il reddito è l'unica azione in cui l'avversario non è influenzato e non può bloccare o sfidare.
Fp\n
significa che un programma ha preso aiuti esteri, quindi il suo avversario ha rifiutato di bloccare ( p
). Alla sua successiva invocazione, il primo programma ha notato che dalla lettera minuscola finale p
e / o dal numero pari di caratteri su questa linea ha preso questo turno, che non è ancora terminato, quindi sa di terminare il suo turno corrente stampando una nuova riga.
C=\n
significa che un programma ha lanciato un colpo di stato. Il suo avversario, sapendo che era chiamato a reagire per il numero dispari di lettere sulla linea, rinunciò a una Contessa. Ancora una volta, il primo programma sapeva che questa era la sua svolta incompleta alla sua successiva invocazione dal numero pari di caratteri sulla linea, quindi ha scritto una nuova riga per terminare la sua svolta.
Eq~<\n
significherebbe che un programma ha tentato uno scambio ( E
) e il suo avversario ha sfidato ( q
). Il programma di Scambio ha rivelato che aveva davvero un Ambasciatore ( ~
) e lo sfidante ha rinunciato a un Capitano come punizione ( <
). Dopo che lo sfidante è uscito, il programma di Scambio viene nuovamente invocato con una stringa di quattro caratteri come quarto argomento della riga di comando (o tre caratteri, se avesse solo una carta). Scrive i personaggi che rappresentano le carte che desidera conservare su STDOUT e una nuova riga nel file.
Tq'\n
significa che un programma ha tentato una tassa non veritiera, è stato sfidato e ha rinunciato a un assassino. Illustra l'altro caso in cui sono scritti due personaggi: se è il tuo turno e sei costretto a rinunciare a una carta - dalla sfida corretta di un avversario (come qui) o dalla sfida errata di un blocco - allora devi scrivere entrambi la carta che abbandoni e una nuova riga per terminare il tuo turno.
Asq!'\n
significherebbe che il giocatore B ha tentato di assassinare il giocatore A ( A
), ma A ha affermato di avere una Contessa per bloccarlo ( s
). B non credeva in A e lo sfidava ( q
). A ha rivelato che in effetti avevano una Contessa ( !
). B rinunciò a un Assassino come punizione, perdendo le monete e finì il loro turno ( '\n
), scrivendo due personaggi come in quel caso speciale. (Se A avesse deciso di non bloccare o sfidare, avrebbe potuto scrivere =
, e quindi il suo avversario avrebbe visto che il turno era finito e avrebbe scritto una nuova riga. La riga avrebbe quindi letto A=\n
, come nell'esempio Coup.)
Sq*0\n
significa che un programma tenta un furto; l'avversario sfida, non credendo che il ladro abbia un Capitano; e il programma originale rivela un Capitano, quindi la sfida non ha successo e lo sfidante rinuncia a un Duca come punizione. (Un'altra opzione per il suo avversario sarebbe quella di accettare lo Steal scrivendo p
. Il suo avversario rileverebbe quindi la fine del suo turno e scriverà \n
, risultando in una riga di Sp\n
.)
The Arbiter
I programmi saranno richiamati da questo script Python. Conduce dieci round, in cui ogni concorrente affronta tutti gli altri concorrenti, andando sia al primo che al secondo. Tiene traccia delle carte e del conteggio delle monete e determina il perdente dal primo programma per terminare due volte una linea con un segno di punteggiatura. I programmi che escono con uno stato diverso da zero, modificano il file, scrivono una mossa illegale nel file o tentano uno scambio illegale perderanno automaticamente. Se ogni giocatore esegue più di 100 azioni, inclusi blocchi e sfide, senza vincitori, entrambi i programmi perdono. A un vincitore viene assegnato un punto. Vince il giocatore il cui programma segna il maggior numero di punti.
Ti suggerisco di leggere il codice sorgente dell'Arbiter, in particolare la get_legal_actions
funzione. Può aiutarti a capire le specifiche e scrivere i tuoi programmi.
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)
miscellaneo
Un programma non può avere un codice specifico per un altro programma e i programmi non possono aiutarsi a vicenda. (Potresti avere più programmi, ma non possono interagire tra loro in alcun modo.)
Se il tuo programma perde entrambe le carte nello stesso turno, deve solo scriverne una. L'Arbiter rileverà che è stato eliminato.
È possibile e incoraggiato, ma non necessario, che i programmi esaminino la cronologia del gioco nel file. In questo modo possono determinare quali carte il loro avversario ha affermato di avere e catturarle in una bugia.
Nel vero gioco di Coup, puoi sfidare un'azione e quindi tentare di bloccarla nello stesso turno. Non potrei far funzionare le specifiche se lo consentissi, quindi potresti sfidare o bloccare una determinata azione, ma non entrambe.
Mi scuso con @PeterTaylor, che la volta precedente ho pubblicato questo suggerito di postarlo nella sandbox e rielaborare il protocollo per reindirizzare l'output avanti e indietro in STDOUT / STDIN. Ho provato così, così duramente per farlo funzionare, trascorrendo un'intera giornata (quando avevo già trascorso un'intera giornata a scrivere la sfida originale). Ma gli scambi si sono dimostrati molto complicati da implementare in quel modo, inoltre avrebbe aumentato la complessità degli invii richiedendo loro di tenere traccia del proprio conteggio delle monete. Quindi ho pubblicato la sfida più o meno com'era in origine.
S
, programma B blocchi scrivendo c
, A rifiuta di sfidare scrivendo \n
. Una sfida di successo di un furto sarebbe andata: A scrive S
, B sfida scrivendo q
, A ammette la sfida scrivendo ad es _\n
. Puoi prendere solo un'azione per turno, incluso Scambio. Le risposte legali a Exchange sono pass e challenge.