Tabla de clasificación
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
¡La calculadora, de Brilliand, es la ganadora! Su respuesta es aceptada, pero eso no significa que el desafío haya terminado. Siéntase libre de enviar nuevas entradas o editar las actuales e intentar sacarlo de su trono. Le otorgaré una recompensa al líder a fin de mes.
Reglas de juego
Coup es un juego de cartas diseñado para 2-6 jugadores, que jugaremos con dos. Consiste en un tesoro de monedas (infinito para nuestros propósitos) y un mazo de 15 cartas, que contiene 3 de cada uno de los siguientes tipos: Embajador, Asesino, Capitán, Contessa, Duque. Al comienzo del juego, cada jugador recibe una moneda y reparte dos cartas al azar, que mantienen en secreto hasta que sea necesario. El objetivo es ser el último jugador con cartas en tu mano.
En su turno, un jugador puede realizar una de las siguientes acciones independientemente de sus cartas:
- Ingresos: toma 1 moneda del tesoro. Desbloqueable e indiscutible.
- Ayuda extranjera: toma 2 monedas del tesoro. Puede ser bloqueado por un jugador con un duque. Inquebrantable
- Golpe: Retira del juego una carta de un oponente de tu elección. Cuesta 7 monedas. La víctima puede elegir qué carta descartar. Si un jugador tiene 10 o más monedas al comienzo de su turno, debe Golpear. Desbloqueable e indiscutible.
Dependiendo de sus cartas, los jugadores también pueden tomar una de las siguientes acciones como su turno:
- Intercambio: un jugador con un Embajador puede tomar dos cartas del mazo. Luego pueden elegir de su mano y de las cartas extraídas tantas cartas como tenían originalmente. (Es decir, si solo tenían una carta, pueden cambiarla por una de las cartas robadas o conservarla, y si tuvieran dos cartas, pueden elegir cualquiera de las cuatro cartas). Las dos cartas no deseadas se devuelven al mazo. . Desbloqueable, pero desafiante.
- Asesinar: un jugador con un Asesino puede gastar 3 monedas para eliminar una carta del oponente del juego. La víctima puede elegir qué carta descartar. Puede ser bloqueado por un jugador con una Contessa, en cuyo caso las monedas no se devuelven. Desafiable, en cuyo caso se devuelven las monedas .
- Robar: Un jugador con un Capitán puede tomar dos monedas de su oponente. Si el oponente tiene una moneda, tomará esa moneda. Si el oponente tiene cero monedas, no puede robar. Puede ser bloqueado por un jugador con un embajador o un capitán. Desafiable
- Impuesto: un jugador con un duque puede tomar 3 monedas del tesoro. Desbloqueable, pero desafiante.
¡La parte difícil de Coup es que los jugadores pueden mentir sobre las cartas que tienen! No es necesario tener una tarjeta para intentar realizar la acción o el bloqueo asociado a ella.
Cuando un jugador realiza la acción de una carta, cualquier oponente (incluso uno que no sea dañado por esa acción) puede desafiar al actor y decir que no cree que tenga la carta para esa acción. Si el retador es correcto, la acción se cancela y el actor debe descartar una carta de su elección (recuperando las monedas que gastaron si corresponde). Si no es así, se toma la acción, el actor devuelve la carta sobre la que fueron desafiados a la baraja y roba una nueva, y el retador debe descartar una de sus cartas. Los jugadores deben ser sinceros acerca de qué cartas tienen cuando son desafiados.
Las cartas eliminadas del juego con Assassinate, Golpe y desafíos perdidos no se devuelven al mazo, pero las cartas reveladas como parte de un desafío ganado se devuelven al mazo.
Los bloques pueden ser desafiados al igual que las acciones. Por ejemplo, si el jugador A reclama Ayuda Extranjera y el jugador B dice "Tengo un Duque y bloqueo tu Ayuda Extranjera", A puede decir "No creo que tengas un Duque". Si esa afirmación es correcta, B pierde una carta por ser atrapado en una mentira y A toma 2 monedas; si no es así, A pierde una carta y no recibe monedas, y B debe devolver a su Duque al mazo y robar una nueva carta.
La forma en que funcionan los bloques y los desafíos con Assassinate debe desarrollarse. Supongamos que el Jugador A dice "Tengo un Asesino y Asesino al Jugador B". Si B no intenta desafiar o bloquear a A, entonces el asesinato pasa: B pierde una carta y A paga 3 monedas.
Alternativamente, B puede desafiar diciendo "No creo que tengas un Asesino". Si eso es cierto, entonces A descarta una carta y sus monedas son devueltas, mientras que B no se ve afectado y el turno de A termina. Si la creencia de B es incorrecta y A tiene un Asesino, entonces B pierde ambas cartas y falla, una por el desafío incorrecto y otra por el Asesinato.
En lugar de desafiar, B podría decir "Tengo una Contessa y bloqueo el Asesinato". Si A cree en B, entonces el turno de A termina y no se devuelven sus monedas. Pero A puede desafiar el bloqueo y decir "No creo que tengas una Contessa". Si B tiene una Contessa, entonces A pierde una carta por el desafío incorrecto. Pero si B no lo hace, entonces B pierde una carta por ser atrapado en una mentira y otra por el Asesinato.
Una lógica similar a la explicación anterior se aplica a la habilidad Robar del Capitán, donde la acción o el bloqueo pueden ser desafiados.
Es posible perder ambas cartas y ser eliminado en un turno, si desafías sin éxito a un Asesino o si te atrapan diciendo falsamente que tienes una Contessa para bloquear un Asesinato. Pierdes una carta del desafío y una carta del Asesinato.
Desafío
Su tarea es escribir un programa que juegue Coup. Se dará como argumentos de línea de comando:
- El nombre de un archivo que contiene la lista de sus acciones y las de sus oponentes hasta el momento.
- Un número entero de 0 a 12 que indica el recuento de monedas del oponente.
- Un entero de 0 a 12 que indica su recuento de monedas.
- Una cadena de uno a cuatro caracteres que indica sus cartas. Normalmente, esta será simplemente una o dos tarjetas que tiene su programa, pero si su programa acaba de tener éxito en un intercambio, tendrá una longitud de n + 2 caracteres, donde n es el número de tarjetas que le quedan. Su programa debe generar las n tarjetas que desea mantener en STDOUT. (Los programas no deben leer ni acceder a STDOUT de otra manera que no sea para este propósito; si desea generar resultados de depuración, escriba a STDERR).
- Uno o más argumentos que indican los movimientos legales que puede hacer.
(Ejemplo de invocación: yourprogram file.txt 1 7 '~!' a c p q
significa "Tu oponente tiene 1 moneda. Tienes 7 monedas, un Embajador y una Contessa. Escribe en archivo.txt tu elección de a, c, p o q dado el historial de juego y el estado actual del juego. ")
Su programa debe agregar uno o (en dos situaciones específicas) dos caracteres al archivo proporcionado que indica su acción. De lo contrario, no debe alterar el contenido existente del archivo. Puede crear cualquier archivo nuevo que desee, pero solo dentro del directorio en el que se ejecuta. Proporcione todos los comandos necesarios para compilar y ejecutar su programa.
He proporcionado dos ejemplos de competidores a continuación, escritos en Go.
El formato de salida es:
I\n
: Ingresos. Respuestas legales: cualquier acción de turno (suponiendo que uno tenga las monedas para Assassinate / Coup).F
: Ayuda externa. Respuestas legales:d
(bloquear como duque),p
(dejarlo pasar).C
: Golpe de Estado. Respuestas legales: aquel de_
,'
,<
,=
,0
está en tu mano.E
: Intercambio. Respuestas legales:q
(desafío, no creer que el jugador tiene un embajador),p
.T
: Impuestos. Respuestas legales:q
(desafío, no creer que el jugador tiene un Duke),p
.A
: Asesinar. Respuestas legales:s
(bloque como Contessa),q
(desafío), y cualquiera de_
,'
,<
,=
,0
que está en su mano.S
: Robar. Respuestas legales:a
(bloque como Embajador),c
(bloque como capitán),q
(desafío, no creer que el jugador tiene un capitán),p
.d
: bloquear la ayuda extranjera como duque. Respuestas legales:\n
(acepta el bloqueo),q
(desafía, sin creer que el jugador tiene un duque).a
: bloquear un robo como embajador. Respuestas legales:\n
(acepta el bloqueo),q
(desafía, sin creer que el jugador tiene un Embajador).c
: bloquear un robo como capitán.\n
(acepta el bloqueo),q
(desafía, sin creer que el jugador tiene un Capitán).s
: bloquea a un Asesino como Contessa. Respuestas legales:\n
(acepta el bloqueo),q
(desafía, sin creer que el jugador tiene una Contessa).p
: pase desafiando un Intercambio / Impuesto / Robo cuando no es su turno. No se usa conA
; negarse a desafiar un asesinato escriba uno de_'<=0
. Respuesta legal:\n
(finaliza tu turno), y si acabas de tener éxito en un intercambio, escribe las cartas que deseas conservar desde el cuarto argumento de la línea de comando hasta STDOUT.q
: desafía la acción o bloque más reciente. Respuesta legal: si tiene la tarjeta para la acción que fue impugnada, la que~^*!$
sea. Si no lo hace, entonces cualquiera de_'<=0
su mano a la que desee renunciar, seguido de una nueva línea si es su turno.~
,^
,*
,!
,$
: Revelar que ha dicho la verdad sobre la celebración, respectivamente, un embajador, un asesino, un capitán, una condesa, y una de Duke (también se utiliza para representar estas tarjetas en los argumentos de línea de comandos, y la salida estándar de salida en un Intercambio ) Respuestas legales: aquel de_
,'
,<
,=
,0
que tiene en su mano._
,'
,<
,=
,0
: Renunciar como castigo, respectivamente, un embajador, y el asesino, un capitán, una condesa, y una de Duke porque perdió un reto o fueron asesinados / couped. Respuesta legal:\n
.\n
: finaliza tu turno, al hacerlo, rechazas desafiar un bloque si corresponde. Respuestas legales: cualquier acción de mayúscula (suponiendo que uno tenga las monedas para Assassinate / Coup y el oponente tenga las monedas para Steal).
El formato tiene las siguientes propiedades útiles:
- Los turnos comienzan con una letra mayúscula.
- Las líneas siguen el patrón: letras mayúsculas, letras minúsculas, opcionalmente signos de puntuación o 0 para tarjetas reveladas, nueva línea.
- Un archivo que termina con una nueva línea, o un archivo vacío, indica que es el comienzo del turno de su programa y debe elegir una acción de mayúscula.
- Las acciones legales que puede realizar en una invocación generalmente están determinadas de forma única por el último carácter del archivo. La excepción es
q
, que tendrá algo de lógica asociada. Vea la funciónget_legal_actions
en el árbitro para ayudar a entender esto. O simplemente puede usar las acciones legales que se le dan en la línea de comando. - Un número par de caracteres en una línea indica que el turno es suyo y se le pide a su programa que elija una acción, desafíe un bloqueo o finalice su turno.
- Un número impar de caracteres en una línea indica que el turno no es tuyo y se le pide a tu programa que bloquee, desafíe o revele / entregue una carta.
Daré un ejemplo para cada acción.
I\n
Es el más fácil de entender. Un programa toma una moneda de Ingresos, luego termina su turno. Este es uno de los dos casos en que los programas deben imprimir dos caracteres, ya que Ingresos es la única acción en la que el oponente no se ve afectado y no puede bloquear ni desafiar.
Fp\n
significa que un programa recibió ayuda extranjera, luego su oponente se negó a bloquear ( p
). En su próxima invocación, el primer programa señaló que por la letra minúscula final p
y / o el número par de caracteres en esta línea tomó este turno, que aún no ha finalizado, por lo que sabe finalizar su turno actual imprimiendo una nueva línea.
C=\n
significa que un programa lanzó un golpe. Su oponente, sabiendo que fue llamado a reaccionar por el número impar de letras en la línea, renunció a una Contessa. Nuevamente, el primer programa sabía que este era su turno incompleto en su próxima invocación por el número par de caracteres en la línea, por lo que escribió una nueva línea para finalizar su turno.
Eq~<\n
significaría que un programa intentó un intercambio ( E
) y su oponente desafió ( q
). El programa de Intercambio reveló que sinceramente tenía un Embajador ( ~
) y el retador entregó un Capitán como castigo ( <
). Después de que el retador sale, el programa de Intercambio se invoca nuevamente con una cadena de cuatro caracteres como su cuarto argumento de línea de comando (o tres caracteres, si solo tuviera una carta). Escribe los caracteres que representan las tarjetas que desea conservar en STDOUT y una nueva línea en el archivo.
Tq'\n
significa que un programa intentó un impuesto falso, fue desafiado y renunció a un Asesino. Ilustra el otro caso en el que se escriben dos personajes: si es tu turno y estás obligado a renunciar a una carta, ya sea del desafío correcto de un oponente (como aquí) o de tu desafío incorrecto de un bloque, entonces debes escribir ambos la carta que abandonas y una nueva línea para finalizar tu turno.
Asq!'\n
significaría que el jugador B intentó asesinar al jugador A ( A
), pero A afirmó tener una Contessa para bloquearlo ( s
). B no le creyó a A y desafió ( q
). A reveló que, de hecho, tenían una Contessa ( !
). B entregó un Asesino como castigo, perdiendo sus monedas, y terminó su turno ( '\n
), escribiendo dos personajes como en ese caso especial. (Si A hubiera decidido no bloquear o desafiar, podría haber escrito =
, y luego su oponente habría visto que el turno había terminado y escrito una nueva línea. La línea habría leído A=\n
, como el ejemplo del Golpe de Estado).
Sq*0\n
significa que un programa intenta un robo; el oponente desafía, sin creer que el ladrón tiene un Capitán; y el programa original revela un Capitán, por lo que el desafío no tiene éxito y el retador renuncia a un Duque como castigo. (Otra opción para su oponente sería aceptar el Steal por escrito p
. Su oponente detectaría el final de su turno y escribiría \n
, lo que daría como resultado una línea de Sp\n
).
El árbitro
Los programas serán invocados por este script de Python. Lleva a cabo diez rondas, en las que cada competidor se enfrenta a todos los demás competidores, yendo primero y segundo. Realiza un seguimiento de los recuentos de cartas y monedas y determina el perdedor por el primer programa para finalizar una línea con un signo de puntuación dos veces. Los programas que salen con un estado distinto de cero, modifican el archivo, escriben un movimiento ilegal en el archivo o intentan un intercambio ilegal se perderán automáticamente. Si cada jugador realiza más de 100 acciones, incluidos bloqueos y desafíos, sin ganador, ambos programas pierden. Un ganador recibe un punto. El jugador cuyo programa obtenga la mayor cantidad de puntos gana.
Le sugiero que lea el código fuente del árbitro, especialmente la get_legal_actions
función. Puede ayudarlo a comprender la especificación y escribir sus propios programas.
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)
Diverso
Un programa no puede tener código específico para otro programa, y los programas no pueden ayudarse entre sí. (Es posible que tenga varios programas, pero no pueden interactuar entre sí de ninguna manera).
Si su programa pierde ambas cartas en el mismo turno, solo necesita escribir una. El árbitro detectará que ha sido eliminado.
Es posible y alentado, pero no es obligatorio, que los programas examinen el historial del juego en el archivo. Al hacerlo, pueden determinar qué cartas ha afirmado tener su oponente y atraparlas en una mentira.
En el juego real de Coup, puedes desafiar una acción y luego intentar bloquearla en el mismo turno. No podría hacer que la especificación funcione si lo permitiera, por lo que puede desafiar o bloquear una acción determinada, pero no ambas.
Mis disculpas a @PeterTaylor, quien en la última vez que publiqué esto sugirió que lo publique en la caja de arena y vuelva a trabajar el protocolo para canalizar la salida de un lado a otro en STDOUT / STDIN. Lo intenté, muy duro, para hacer que eso funcionara, pasando un día completo (cuando ya había pasado un día completo escribiendo el desafío original). Pero los intercambios resultaron muy complicados de implementar de esa manera, además habría aumentado la complejidad de las presentaciones al exigirles que realicen un seguimiento de su propio recuento de monedas. Así que publiqué el desafío más o menos como era originalmente.
fuente
S
, el programa B bloquea al escribirc
, A se niega a desafiar al escribir\n
. Un desafío exitoso de un Steal iría: A escribeS
, B desafía al escribirq
, A reconoce el desafío al escribir_\n
, por ejemplo , solo puedes tomar una acción por turno, incluido el Intercambio. Las respuestas legales a Exchange son aprobadas y desafiadas.Respuestas:
Calculadora
Planea su serie ganadora de movimientos y desafía cualquier cosa que le impida ganar.
Renegado
Al principio dice la verdad, pero comienza a mentir cuando deja de ser desafiado. También tiene un comportamiento solucionador. (Una aproximación de cómo me comporto cuando juego este juego con humanos)
Bandido
Intenta deshacerte de los embajadores y capitanes del oponente y gana robando.
Asesinato sangriento
Una contraparte de Bandit, este va todo en una estrategia de Duke + Assassin.
fuente
Solucionador
Solver intenta recordar qué cartas se jugaron antes y cuáles fueron los movimientos anteriores del oponente.
Esta es la segunda versión aún no terminada (y ahora es un gran desastre)
para que funcione en el nodo 10, agregue
competitors.append(Player("Solver", ["node", "--experimental-modules", "./solver.mjs"]))
si el nodo 12
competitors.append(Player("Solver", ["node", "./solver.js"]))
ten cuidado con el tipo de archivo
fuente
Abogado
El Abogado se abre paso con cautela por el mundo, nunca miente, bloquea cuando es posible, desafía cuando no es en detrimento inmediato. No ataca, excepto cuando es requerido por el golpe, pero tomará monedas con la mayor frecuencia posible para golpear rápidamente. Es lo suficientemente inteligente como para sacrificar cartas que no usa primero, pero no lo suficientemente inteligente como para usarlas para deshacerse de ellas y obtener otras nuevas.
Probablemente hay errores en este programa. Cuando los encuentres, házmelo saber.
fuente
Aleatorio
Random no sabe qué hacer, por lo que selecciona aleatoriamente algo legal.
Desafiador
Challenger no confía en nadie en este juego de engaño. Si haces algo desafiante, él te desafiará. De lo contrario, solo toma ingresos cada turno e intenta golpearte si tiene las monedas.
Compile estos programas con
go build random.go/challenger.go
y ejecútelos con./random
o./challenger
.fuente
Recaudador de impuestos
El recaudador de impuestos está aquí para recaudar impuestos. Utiliza asesino si tienen uno. Solo bloquea si tienen la tarjeta para bloquear. Desafíos al azar.
Escrito en C #, pasé demasiado tiempo creando una jerarquía de clases para todas las diferentes acciones que se pueden tomar.
Editar: ahora con una lógica mejorada, como no pretender tener un duque cuando han renunciado a un duque después de ser desafiados. Además, ya no intenta asesinar continuamente si el oponente bloquea con contessa (y no es desafiado).
fuente
determine_turn_effects()
, la acción Steal está tomando todas las monedas del oponente. Debería tomar como máximo dos monedas.Rando Aggro Abogado
Al igual que el abogado, solo hace cosas legales. Sin embargo, Asesina, golpea antes, y elige algunas acciones al azar (como cuándo Desafiar).
fuente
Máscara
La máscara es un maestro del disfraz. Evita que los oponentes sigan sus cartas intercambiando cada vez que actúa o bloquea. Su estrategia ganadora es tomar 3 monedas como el duque, luego asesinar.
Compilar con
go build mask.go
, correr con./mask
.fuente
Jugador
El jugador tiene una estrategia desarrollada, pero confía en su instinto cuando una situación no se tiene en cuenta en su estrategia ganadora. Intenta robar mucho y golpea / asesina siempre que es posible.
Escrito en Python3:
Estadístico
Conoce su estrategia ganadora, al igual que el jugador, pero siempre confía en las probabilidades máximas en lugar de tomar muestras al azar de ellas.
fuente
Traceback (most recent call last): File "gambler.py", line 94, in <module> otherhand = guess_opponents_hand() File "gambler.py", line 61, in guess_opponents_hand card_counts[card_give_up.index(card_1)] -= 1 ValueError: ['_'] is not in list
.\n
lugar de la tarjeta que desean renunciar. En tal situación, es mejor luchar con un bloqueo o desafío. Si Gambler hubiera ganado los 5 juegos que perdió de esta manera, habría tomado el primer lugar.