Leaderboard
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
Доступен архив с последним совпадением, включая журнал и все выходные файлы.
Калькулятор от Brilliand - победитель! Его ответ принят, но это не значит, что вызов окончен. Не стесняйтесь отправлять новые записи или редактировать свои текущие и попытаться сбить его с трона. Я награду награду лидеру в конце месяца.
Правила игры
Coup - карточная игра, рассчитанная на 2-6 игроков, в которую мы будем играть с двумя. Он состоит из сокровищницы монет (бесконечной для наших целей) и колоды из 15 карт, содержащих по 3 каждого из следующих типов: Ambassador, Assassin, Captain, Contessa, Duke. В начале игры каждому игроку дают одну монету и сдают наугад две карты, которые они держат в секрете до тех пор, пока это не будет необходимо. Цель состоит в том, чтобы быть последним игроком с картами в вашей руке.
В свою очередь, игрок может выполнить одно из следующих действий независимо от своих карт:
- Доход: возьмите 1 монету из сокровищницы. Не блокируется и не подлежит сомнению.
- Иностранная помощь: возьмите 2 монеты из сокровищницы. Может быть заблокирован игроком с герцогом. Неоспоримый.
- Переворот: удалите карту одного оппонента по вашему выбору из игры. Стоит 7 монет. Жертва может выбрать, какую карту выбросить. Если у игрока есть 10 или более монет в начале своего хода, он должен сделать ставку. Не блокируется и не подлежит сомнению.
В зависимости от своих карт игроки также могут выполнять одно из следующих действий в свою очередь:
- Обмен: игрок с послом может взять две карты из колоды. Затем они могут выбрать из своей руки и вытянутых карт столько карт, сколько у них было изначально. (То есть, если у них была только одна карта, они могут обменять ее на одну из вытянутых карт или оставить ее, а если у них было две карты, они могут выбрать любые две из четырех карт.) Две нежелательные карты возвращаются в колоду , Неблокируемый, но сложный.
- Убийство: игрок с убийцей может потратить 3 монеты, чтобы удалить карту противника из игры. Жертва может выбрать, какую карту выбросить. Может быть заблокирован игроком с графиней, в этом случае монеты не возвращаются. Подлагется, в этом случае монеты будут возвращены.
- Кража: игрок с капитаном может взять две монеты у своего противника. Если у противника есть одна монета, он возьмет эту одну монету. Если у противника ноль монет, он не может украсть. Может быть заблокирован игроком с послом или капитаном. Подлагется.
- Налог: игрок с герцогом может взять 3 монеты из сокровищницы. Неблокируемый, но сложный.
Хитрость Coup в том, что игрокам разрешено лгать о том, какие у них карты! Не нужно иметь карту, чтобы попытаться выполнить действие или блок, связанный с ним.
Когда игрок выполняет действие карты, любой противник (даже тот, кто не пострадал от этого действия) может бросить вызов актеру и сказать, что он не считает, что у него есть карта для этого действия. Если претендент прав, действие отменяется, и актер должен сбросить одну карту по своему выбору (возвращая все потраченные монеты, если это применимо). Если нет, действие выполняется, актер возвращает карту, в которой он был брошен вызов, в колоду и берет новую, а претендент должен сбросить одну из своих карт. Игроки должны быть правдивыми о том, какие карты они держат, когда им бросают вызов.
Карты, исключенные из игры с Assassinate, Coup и потерянными испытаниями, не возвращаются в колоду, но карты, раскрытые как часть выигранного вызова, возвращаются в колоду.
Блоки могут быть оспорены как действия. Например, если игрок A требует иностранной помощи, а игрок B говорит: «У меня есть герцог, и я блокирую вашу иностранную помощь», A может сказать: «Я не верю, что у вас есть герцог». Если это утверждение верно, B теряет карту за то, что его поймали на лжи, а A берет 2 монеты; если это не так, A теряет карту и не получает монет, а B должен вернуть своего Герцога в колоду и взять новую карту.
То, как блоки и вызовы работают с Убийцей, должно быть уточнено. Предположим, игрок А говорит: «У меня есть убийца, и я убиваю игрока Б». Если B не пытается бросить вызов или блокировать A, то убийство проходит: B теряет карту, а A выплачивает 3 монеты.
Кроме того, B может бросить вызов, сказав: «Я не верю, что у вас есть убийца». Если это правда, то А сбрасывает карту, и их монеты возвращаются, в то время как В не затрагивается, и ход А заканчивается. Если вера Б неверна и А держит Ассассина, то Б теряет обе свои карты и терпит неудачу: одна за неправильный вызов, другая - за Убийство.
Вместо того, чтобы бросать вызов, Б мог сказать: «У меня есть графиня, и я блокирую убийцу». Если А верит В, то ход А заканчивается и их монеты не возвращаются. Но А может бросить вызов блоку и сказать: «Я не верю, что у тебя есть графиня». Если B действительно держит графиню, то A теряет карту за неправильный вызов. Но если B нет, то B теряет одну карту за то, что ее поймали на лжи, а другую - за убийство.
Логика, аналогичная приведенному выше объяснению, применима и к способности «Кража капитана», где действие или блок могут быть оспорены.
Можно потерять обе свои карты и быть уничтоженным за один ход, если вы безуспешно бросаете вызов Убийце или вас ловят, ложно утверждая, что у вас есть Графиня, чтобы заблокировать Убийство. Вы теряете одну карту от испытания и одну карту от Убийства.
Вызов
Ваша задача - написать программу, которая будет играть в Coup. Это будет дано в качестве аргументов командной строки:
- Название файла, содержащего список действий его и его противников.
- Целое число от 0 до 12, указывающее количество монет противника.
- Целое число от 0 до 12, указывающее количество монет.
- Строка длиной от одного до четырех символов, обозначающая ее карточки. Обычно это просто одна или две карточки, которые есть в вашей программе, но если ваша программа только что преуспела в обмене, она будет иметь длину n + 2 символа, где n - это количество оставшихся карточек. Ваша программа должна затем вывести n карт, которые она хочет сохранить в STDOUT. (Программы не должны читать или получать доступ к STDOUT, кроме как для этой цели - если вы хотите произвести отладочный вывод, пожалуйста, напишите в STDERR.)
- Один или несколько аргументов, указывающих законные шаги, которые он может сделать.
(Пример вызова: yourprogram file.txt 1 7 '~!' a c p q
означает «у вашего оппонента 1 монета. У вас есть 7 монет, посол и графиня. Запишите в file.txt ваш выбор a, c, p или q с учетом истории игры и текущего состояния игры. «)
Ваша программа должна добавить один или (в двух конкретных ситуациях) два символа в предоставленный файл, указывающий его действие. Он не должен иначе изменять существующее содержимое файла. Он может создавать любые новые файлы, которые он пожелает, но только внутри каталога, в котором он запущен. Пожалуйста, предоставьте все необходимые команды для компиляции и запуска вашей программы.
Ниже я привел два примера конкурентов, написанных на Go.
Выходной формат:
I\n
Доход Юридические ответы: любое действие хода (при условии, что у вас есть монеты для Убийства / Переворот).F
: Иностранная помощь. Юридические ответы:d
(заблокировать как герцог),p
(пусть это пройдет).C
: Переворот Юридические ответы: в зависимости от того из_
,'
,<
,=
,0
находится в ваших руках.E
: Обмен. Юридические ответы:q
(вызов, не веря, что у игрока есть посол)p
.T
Налог. Юридические ответы:q
(вызов, не веря, что у игрока есть герцог)p
.A
Убийство. Юридические ответы:s
(блок как графиня),q
(вызов), и в зависимости от того из_
,'
,<
,=
,0
в ваших руках.S
Украсть Юридические ответы:a
(заблокировать как посол),c
(заблокировать как капитан),q
(вызов, не веря, что у игрока есть капитан)p
,.d
: block Foreign Aid как герцог. Юридические ответы:\n
(принять блок),q
(вызов, не веря, что у игрока есть герцог).a
: заблокировать кражу в качестве посла. Юридические ответы:\n
(принять блок),q
(вызов, не веря, что у игрока есть посол).c
: заблокировать кражу в качестве капитана.\n
(принять блок),q
(вызов, не веря, что у игрока есть капитан).s
: заблокировать убийцу как графиню Юридические ответы:\n
(принять блок),q
(вызов, не веря, что у игрока есть графиня).p
Пройти оспаривание обмена / налога / кражи, когда не твоя очередь. Не используется сA
; отказаться от вызова убийства написать один из_'<=0
. Юридический ответ:\n
(закончите свою очередь), и, если вы только что преуспели в Exchange, записываете карточки, которые вы хотите сохранить, из четвертого аргумента командной строки в STDOUT.q
: вызов самого последнего действия или блока. Юридический ответ: если у вас есть карточка для оспариваемого действия, в зависимости от того,~^*!$
что было. Если вы этого не сделаете, то от того,_'<=0
с какой руки вы хотите отказаться, за которой следует новая строка, если и только если это ваша очередь.~
,^
,*
,!
,$
: Показывает , что вы говорили правду о проведении, соответственно, посол, убийца, капитан, Contessa, и Duke (также используется для представления этих карт в аргументах командной строки, и STDOUT выхода в Обмена ). Юридические ответы: в зависимости от того из_
,'
,<
,=
, у0
вас есть в вашей руке._
,'
,<
,=
,0
: Отказаться в качестве наказания, соответственно, посол, и убийцу, а капитан, графиня, и герцог , потому что вы потеряли вызов или были убиты / Couped. Правовая характеристика:\n
.\n
: закончите свой ход, отказавшись бросить вызов блоку, если это применимо. Юридические ответы: любое действие с заглавной буквой (при условии, что у одного есть монеты для Assassinate / Coup, а у противника есть монеты для кражи).
Формат имеет следующие полезные свойства:
- Повороты начинаются с заглавной буквы.
- Строки следуют шаблону: заглавные буквы, строчные буквы, опциональные знаки пунктуации или 0 для раскрытых карточек, новая строка.
- Файл, заканчивающийся символом новой строки, или пустой файл, указывает, что это начало хода вашей программы, и он должен выбрать действие с большой буквы.
- Юридические действия, которые вам разрешено выполнять при вызове, обычно однозначно определяются последним символом в файле. Исключение составляет
q
логика, связанная с ним. Смотрите функциюget_legal_actions
в арбитре, чтобы помочь понять это. Или вы можете просто использовать законные действия, которые вы дали в командной строке. - Четное число символов в строке указывает на то, что ход принадлежит вам, и вашей программе предлагается выбрать действие, вызвать блок или завершить свой ход.
- Нечетное количество символов в строке указывает на то, что ход не принадлежит вам, и вашей программе предлагается заблокировать, вызвать или открыть / сдать карту.
Я приведу пример для каждого действия.
I\n
проще всего понять. Программа берет одну монету Дохода, затем заканчивает свой ход. Это один из двух случаев, когда программы должны печатать два символа, так как Income - единственное действие, когда противник не затронут и не может блокировать или бросать вызов.
Fp\n
означает, что одна программа взяла Foreign Aid, а ее противник отказался от block ( p
). При следующем вызове первая программа заметила, что по последнему строчному p
и / или четному количеству символов в этой строке она прошла этот ход, который еще не закончился, поэтому она знает, что нужно завершить текущий ход, печатая новую строку.
C=\n
означает, что одна программа запустила Coup. Его противник, зная, что он призван реагировать нечетным количеством букв в строке, отказался от графиня. Опять же, первая программа знала, что это был ее неполный поворот при следующем вызове четным числом символов в строке, поэтому она написала новую строку, чтобы завершить свой ход.
Eq~<\n
будет означать, что одна программа попыталась выполнить обмен ( E
), а ее оппонент - вызов ( q
). Программа «Обмен» показала, что в ней действительно был посол ( ~
), а претендент отказался от капитана в качестве наказания ( <
). После выхода претендента программа «Обмен» снова вызывается с четырехсимвольной строкой в качестве четвертого аргумента командной строки (или тремя символами, если у нее была только одна карточка). Он записывает символы, представляющие карты, которые он хочет сохранить в STDOUT, и перевод строки в файл.
Tq'\n
означает, что одна программа попыталась создать неправдивый налог, была оспорена и отказалась от ассасина. Он иллюстрирует другой случай, когда написаны два символа: если настала ваша очередь и вы вынуждены отказаться от карты - либо из-за правильного вызова противника (как здесь), либо из-за неправильного вызова блока - тогда вы должны написать оба карта, которую вы сдаете, и перевод строки, чтобы закончить свой ход.
Asq!'\n
будет означать, что игрок B попытался убить игрока A ( A
), но A утверждал, что у него есть графиня, чтобы заблокировать его ( s
). Б не верил А и оспаривал ( q
). Выяснилось, что у них действительно есть графиня ( !
). Б оставил Ассасина в качестве наказания, потерял свои монеты и закончил свой ход ( '\n
), написав два символа, как в этом особом случае. (Если бы А решил не блокировать и не бросить вызов, он мог бы написать =
, и тогда его противник увидел бы, что поворот окончен, и написал новую строку. Строка тогда бы прочитала A=\n
, как пример переворота.)
Sq*0\n
означает, что одна программа пытается украсть; противник бросает вызов, не веря, что у вора есть капитан; и оригинальная программа показывает капитана, так что вызов неудачен, и претендент отказывается от герцога в качестве наказания. (Другой вариант для оппонента - принять кражу в письменном виде p
. Затем оппонент обнаружит конец своего хода и напишет \n
, в результате чего получится строка Sp\n
.)
Арбитр
Программы будут вызываться этим скриптом Python. Он проводит десять раундов, в которых каждый участник сталкивается с каждым другим участником, одновременно занимая первое и второе места. Он отслеживает количество карточек и монет и определяет проигравшего по первой программе, которая дважды заканчивает строку знаком препинания. Программы, которые выходят с ненулевым статусом, изменяют файл, записывают недопустимое перемещение в файл или предпринимают попытку незаконного обмена, автоматически утрачивают силу. Если каждый игрок выполняет более 100 действий, включая блоки и вызовы, без победителя, то обе программы проигрывают. Победителю предоставляется одно очко. Игрок, чья программа набирает наибольшее количество очков, выигрывает.
Я предлагаю вам прочитать исходный код Арбитра, особенно get_legal_actions
функцию. Это может помочь вам понять спецификацию и написать свои собственные программы.
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)
Разнообразный
Одна программа не может иметь код, специфичный для другой программы, и программы не могут помочь друг другу. (У вас может быть несколько программ, но они никак не могут взаимодействовать друг с другом.)
Если ваша программа теряет обе свои карты в один и тот же ход, ей нужно написать только одну. Арбитр обнаружит, что он был устранен.
Это возможно и рекомендуется, но не обязательно, чтобы программы изучали историю игры в файле. Поступая так, они могут определить, какие карты претендуют на то, что их противник заявил, и поймать их на лжи.
В реальной игре Coup вы можете бросить вызов действию, а затем попытаться заблокировать его в тот же ход. Я не смог бы заставить работать спецификацию, если бы позволил, так что вы можете либо бросить вызов, либо заблокировать данное действие, но не оба.
Приношу свои извинения @PeterTaylor, который в предыдущий раз, когда я разместил это, предложил мне отправить его в песочницу и переработать протокол для передачи вывода туда и обратно в STDOUT / STDIN. Я так старался, так усердно, чтобы сделать эту работу, потратив на это целый день (когда я уже потратил целый день на написание оригинального задания). Но обмены оказались очень сложными для реализации таким образом, плюс это усложнило бы подачу заявок, потребовав от них отслеживать количество своих монет. Таким образом, я отправил вызов более или менее, как это было изначально.
источник
S
, программа B блокирует записьc
, A отказывается бросать вызов записью\n
. Успешная попытка кражи: «А» пишетS
, «В» - письменноq
, «А» уступает, «написав», например_\n
, вы можете выполнять только одно действие за ход, включая Exchange. Юридические ответы на бирже проходят и оспариваются.Ответы:
Калькулятор
Планирует его выигрышную серию ходов и бросает вызов всему, что помешает ему выиграть.
перебежчик
Сначала говорит правду, но начинает лгать, когда перестает быть вызывающим. Также имеет некоторое решающее поведение. (Примерное поведение в игре с людьми)
разбойник
Пытается избавиться от послов и капитанов противника и победить воровством.
Кровавое убийство
Этот аналог бандита идет олл-ин на стратегию Duke + Assassin.
источник
решающее устройство
Солвер попытается вспомнить, какие карты играли раньше и какими были предыдущие ходы противника.
это вторая версия еще не закончена (и это большой беспорядок сейчас)
чтобы заставить его работать на добавлении узла 10
competitors.append(Player("Solver", ["node", "--experimental-modules", "./solver.mjs"]))
если узел 12
competitors.append(Player("Solver", ["node", "./solver.js"]))
быть осторожным с типом файла
источник
Юрист
Адвокат осторожно пробирается сквозь мир, никогда не лжет, блокирует, когда это возможно, бросает вызов, когда не причиняет ему немедленного вреда. Он не атакует, за исключением случаев, когда это необходимо для соединения, но он будет брать монеты как можно чаще, чтобы быстро совершить переворот. Он достаточно умен, чтобы жертвовать картами, которые он не использует первым, но недостаточно умен, чтобы использовать их, чтобы избавиться от них и получить новые.
Возможно, в этой программе есть ошибки. Когда вы найдете их, пожалуйста, дайте мне знать.
источник
случайный
Рэндом не знает, что делать, поэтому он случайным образом выбирает что-то законное.
претендент
Претендент никому не доверяет в этой игре обмана. Если вы сделаете что-то вызывающее, он бросит вам вызов. В противном случае он просто получает доход каждый ход и пытается соединить вас, если у него есть монеты.
Скомпилируйте эти программы
go build random.go/challenger.go
и запустите с помощью./random
или./challenger
.источник
сборщик налогов
Налоговик здесь, чтобы собрать налог. Использует убийцу, если он есть. Блокирует только если у них есть карта для блокировки. Случайно бросает вызов.
Написанный на c #, я слишком долго строил иерархию классов для всех возможных действий.
Изменить: Теперь с улучшенной логикой, как не претендовать на герцога, когда они бросили герцога после того, как его бросили вызов. Также больше не пытается непрерывно убивать, если противник блокирует с контрасой (и не оспаривается).
источник
determine_turn_effects()
результате действия Steal забираются все монеты противника. Это должно быть не более двух монет.Рандо Агро Адвокат
Подобно адвокату, он занимается только законными делами. Однако он убивает, совершает переворот раньше, и он выбирает некоторые действия случайным образом (например, когда бросить вызов).
источник
маскировать
Маска - мастер маскировки. Он мешает оппонентам отслеживать свои карты, обмениваясь каждый раз, когда он действует или блокирует. Его выигрышная стратегия - взять в качестве герцога 3 монеты, а затем убить.
Скомпилировать
go build mask.go
, запустить с./mask
.источник
Азартный игрок
Игрок имеет конкретную стратегию, но доверяет своей интуиции, когда ситуация не учитывается в его выигрышной стратегии. Он пытается много воровать и совершает перевороты / убийства, когда это возможно.
Написано на Python3:
статистик
Знает свою выигрышную стратегию, как и игрок, но всегда доверяет максимальным вероятностям вместо случайной выборки из них.
источник
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
вместо карты, которую они хотят сдать. В такой ситуации лучше дать отпор блоком или вызовом. Если бы Gambler выиграл 5 игр, которые он утратил таким образом, он бы занял первое место.