Таблиця лідерів
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, переможець! Його відповідь прийнята, але це не означає, що виклик закінчений. Не соромтеся надсилати нові записи чи редагувати свої поточні та намагайтеся збити його з трону. Я присуджую нагороду лідеру наприкінці місяця.
Правила гри
Купон - карткова гра, розрахована на 2-6 гравців, в яку ми будемо грати з двома. Він складається із скарбниці монет (нескінченна для наших цілей) та колоди з 15 карт, що містять 3 кожного з наступних типів: посол, вбивця, капітан, Контеса, герцог. На початку гри кожному гравцеві дають одну монету і роздають дві картки навмання, які вони зберігають у секреті до необхідності. Об'єкт - бути останнім гравцем з картами в руці.
Своєю чергою, гравець може вчинити одну з наступних дій незалежно від своїх карт:
- Дохід: візьміть 1 скарбничку з скарбниці. Неблокований і незаперечний.
- Іноземна допомога: візьміть із скарбниці 2 монети. Може бути заблокований гравцем з герцогом. Беззаперечний.
- Переворот: вийміть з гри гру одного гравця, який ви обрали. Коштує 7 монет. Потерпілий може вибрати, яку карту викинути. Якщо у гравця є 10 і більше монет на початку своєї черги, він повинен провести купон. Неблокований і незаперечний.
Залежно від своїх карт, гравці також можуть виконувати одну з наступних дій як свою чергу:
- Обмін: гравець з послом може взяти дві карти з колоди. Тоді вони можуть вибирати зі своєї руки та намальованих карт стільки карток, скільки раніше мали. (Тобто, якщо вони мали лише одну карту, вони можуть обміняти її на одну з намальованих карт або зберегти її, а якщо у них дві карти, вони можуть вибрати будь-яку дві з чотирьох карт.) Дві небажані картки повертаються на колоду . Розблокування, але складне.
- Вбивця: гравець з Assassin може витратити 3 монети, щоб вийняти з гри карту противника. Потерпілий може вибрати, яку карту викинути. Може бути заблокований гравцем із Contessa, і в цьому випадку монети не повертаються. Подлагется, в цьому випадку монети будуть повернуті.
- Викрасти: Гравець з капітаном може взяти у суперника дві монети. Якщо опонент має одну монету, він візьме цю одну монету. Якщо опонент має нульові монети, він може не красти. Може бути заблокований гравцем з послом або капітаном. Виклик.
- Податок: Гравець з герцогом може взяти з казни 3 монети. Розблокування, але складне.
Хитра частина перевороту полягає в тому, що гравцям дозволяється брехати про те, які у них карти! Не потрібно мати карту для спроби виконати дію або блок, пов'язаний з нею.
Коли гравець виконує дії картки, будь-який противник (навіть той, кому ця дія не пошкоджений) може кинути виклик актору і сказати, що він не вірить, що має карту для цієї дії. Якщо претендент правильний, дія скасовується, і актор повинен викинути одну карту за власним вибором (повернення будь-яких монет, які вони витратили, якщо це застосовується). Якщо ні, то дія робиться, актор повертає на палубу карту, яку вони оскаржили, і витягує нову, а претендент повинен відкинути одну зі своїх карт. Гравці повинні бути правдивими щодо того, які карти вони тримають, коли їх оскаржують.
Карти, вилучені з гри з Assassinate, Coup та програлими завданнями, не повертаються на колоду, але картки, виявлені як частина виграного виклику, повертаються на колоду.
Блоки можуть бути оскаржені, як і дії. Наприклад, якщо гравець А претендує на Іноземну допомогу, а гравець В каже: "У мене є герцог, і я блокую вашу іноземну допомогу", А може сказати: "Я не вірю, що у вас є герцог". Якщо це твердження правильне, Б втрачає карту за те, що потрапив у брехню, а А бере 2 монети; якщо його немає, А втрачає карту і не отримує монет, і Б повинен повернути свого герцога на колоду і оформити нову карту.
Те, як блоки та завдання працювати з Assassinate, повинні бути чітко розроблені. Припустимо, гравець A каже: "У мене є вбивця, і я вбиваю гравця B". Якщо B не намагається кинути виклик чи блокувати A, то вбивство проходить через: B втрачає карту, а A платить 3 монети.
Як варіант, Б може кинути виклик, сказавши: "Я не вірю, що у вас є вбивця". Якщо це правда, тоді A скидає картку та їх монети повертаються, тоді як B не впливає, і черга А закінчується. Якщо віра В невірна і А тримає вбивцю, то Б втрачає як свої картки, так і невдачу, одну за неправильне виклик та одну від Вбивства.
Замість того, щоб кинути виклик, Б міг би сказати: "Я маю Контесу, і я блокую Заступника". Якщо А вірить В, то поворот А закінчується, а їхні монети не повертаються. Але A може кинути виклик блоку і сказати: "Я не вірю, що ти маєш Contessa". Якщо B насправді тримає Contessa, то A втрачає карту за неправильне виклик. Але якщо Б цього немає, то Б втрачає одну карту за те, що її спіймали у брехні, а другу - від Вбивства.
Аналогічна логіка до вищезгаданого пояснення стосується здатності капітана до викрадення, де може бути оскаржено дії або блок.
Можна втратити обидві картки і бути ліквідованими за один виток, якщо ви невдало киньте виклик вбивці або вас помилково заявляють, що у вас є Contessa для блокування вбивства. Ви втрачаєте одну карту від виклику та одну карту від Вбивства.
Виклик
Ваше завдання - написати програму, яка буде грати Coup. Він буде наведений як аргументи його командного рядка:
- Назва файлу, що містить перелік його дій та дій його опонентів до цього часу.
- Ціле число від 0 до 12, що вказує кількість монет противника.
- Ціле число від 0 до 12, що вказує на його кількість монет.
- Рядок від одного до чотирьох символів із зазначенням його карт. Зазвичай це просто одна чи дві картки у вашій програмі, але якщо ваша програма щойно перейшла на біржу, вона буде мати n + 2 символи, де n - ваша кількість карт. Потім ваша програма повинна вивести n карт, які вона хоче зберегти в STDOUT. (Програми не повинні читати або отримувати доступ до STDOUT, окрім як для цієї мети - якщо ви хочете отримати вихід налагодження, будь ласка, напишіть на STDERR.)
- Один або кілька аргументів, які вказують на юридичні кроки, які він може зробити.
(Приклад виклику:, що yourprogram file.txt 1 7 '~!' a c p q
означає "У вашого суперника є 1 монета. У вас є 7 монет, посол і Contessa. Напишіть у file.txt свій вибір а, с, р або q з урахуванням історії гри та поточного стану гри. ")
Ваша програма повинна додати один або (у двох конкретних ситуаціях) два символи до наданого файлу із зазначенням його дії. Він інакше не повинен змінювати наявний вміст файлу. Він може створювати будь-які нові файли, які бажає, але лише в каталозі, в якому він запущений. Будь ласка, надайте всі необхідні команди для складання та запуску програми.
Я подав два приклади конкурентів нижче, написані на Go.
Формат виводу:
I\n
: Дохід. Юридичні відповіді: будь-які поворотні дії (якщо припустимо, що в них є монети за вбивство / переворот).F
: Іноземна допомога. Юридичні відповіді:d
(блокуй як герцог),p
(нехай проходить).C
: Переворот. Юридичні відповіді: в залежності від того з_
,'
,<
,=
,0
знаходиться в ваших руках.E
: Обмін. Юридичні відповіді:q
(виклик, не рахуючи того , як гравець посла),p
.T
: Податок. Юридичні відповіді:q
(виклик, не рахуючи , що гравець має Duke),p
.A
: Вбивця. Юридичні відповіді:s
(блок як графині),q
(виклик), і в залежності від того з_
,'
,<
,=
,0
в ваших руках.S
: Вкрасти. Юридичні відповіді:a
(блок в якості посла),c
(блок , як капітан),q
(виклик, не рахуючи , що гравець має капітан),p
.d
: блокувати іноземну допомогу як герцог. Юридичні відповіді:\n
(прийміть блок),q
(киньте виклик, не віривши, що у гравця є герцог).a
: заблокувати крадіжку як посол. Юридичні відповіді:\n
(прийміть блок),q
(киньте виклик, не віривши, що у гравця є посол).c
: заблокувати крадіжку як капітан.\n
(прийміть блок),q
(киньте виклик, не вірячи, що у гравця є Капітан).s
: заблокувати вбивцю як Contessa. Юридичні відповіді:\n
(прийміть блок),q
(киньте виклик, не віривши, що гравець має Contessa).p
: пройдіть виклик біржі / податку / крадіжці, коли не ваша черга. Не використовується зA
; відмовитися від оскарження вбивства написати один із_'<=0
. Юридична відповідь:\n
(завершіть свою чергу), і якщо ви тільки що досягли успіху на біржі, написайте картки, які ви хочете зберегти, від аргументу четвертого командного рядка до STDOUT.q
: киньте виклик останній дії або блоку. Юридична відповідь: якщо у вас є картка для дії, яка була оскаржена, залежно від того, яка~^*!$
вона була. Якщо ви цього не зробите, то, від кого б_'<=0
ви не хотіли відмовитись, слідуйте за новим рядком, якщо і тільки, якщо ваша черга.~
,^
,*
,!
,$
: Показує , що ви говорили правду про проведення, відповідно, посол, вбивця, капітан, Contessa, і Duke (також використовується для представлення цих карт в аргументах командного рядка, і STDOUT виходу в Обміну ). Юридичні відповіді: в залежності від того з_
,'
,<
,=
, у0
вас є у вашій руці._
,'
,<
,=
,0
: Відмовитися в якості покарання, відповідно, посол, і вбивцю, а капітан, графиня, і герцог , тому що ви втратили виклик або були вбиті / Couped. Правова характеристика:\n
.\n
: завершіть свою чергу, тим самим відмовляючись оскаржувати блок, якщо це застосовно. Юридичні відповіді: будь-які дії з великої літери (якщо припустити, що в них є монети за вбивство / переворот, а опонент має монети для крадіжки).
Формат має такі корисні властивості:
- Повороти починаються з великої літери.
- Рядки дотримуються шаблону: великі літери, малі літери, необов'язково розділові знаки або 0 для виявлених карток, новий рядок.
- Файл, що закінчується новим рядком, або порожній файл, вказує, що це початок черги вашої програми, і він повинен вибрати велику літеру.
- Юридичні дії, дозволених здійснити виклик, зазвичай однозначно визначаються останнім символом у файлі. Виняток - це те
q
, що з нею буде пов'язана певна логіка. Дивіться функціюget_legal_actions
арбітра, щоб допомогти зрозуміти це. Або ви можете просто скористатися юридичними діями, які вам надано в командному рядку. - Рівна кількість символів у рядку вказує на те, що черга за вами, і програму пропонують вибрати дію, оскаржити блок або закінчити свою чергу.
- Непарна кількість символів у рядку вказує на те, що черга не ваша, і вашу програму пропонується заблокувати, оскаржити або відкрити / здати карту.
Я наведу приклад для кожної дії.
I\n
є найпростішим для розуміння. Програма бере одну монету доходу, а потім закінчує свою чергу. Це один з двох випадків, коли програми повинні надрукувати два символи, оскільки дохід - це єдине дію, коли опонент не впливає і не може блокувати чи кинути виклик.
Fp\n
означає, що одна програма взяла Foreign Aid, тоді її противник відмовився від блокування ( p
). Під час свого наступного виклику перша програма зазначила, що підсумковим p
рядком та / або парною кількістю символів у цьому рядку вона пройшла цей поворот, який ще не закінчився, тому знає закінчити свій поточний поворот, надрукувавши новий рядок.
C=\n
означає, що одна програма запустила переворот. Його опонент, знаючи, що його покликали реагувати непарною кількістю літер на лінії, відмовився від Contessa. Знову ж таки, перша програма знала, що це її неповна черга при наступному виклику парною кількістю символів на рядку, тому вона написала новий рядок, щоб закінчити свою чергу.
Eq~<\n
означало б, що одна програма намагалася обміняти обмін ( E
), а його противник ( q
). Програма обміну виявила, що в ній правдиво був посол ( ~
), а претендент відмовився від капітана як покарання ( <
). Після виходу виклику програма Обмін знову викликається чотирьох символьним рядком як четвертий аргумент командного рядка (або три символи, якщо вона мала лише одну карту). Він записує символи, що представляють картки, які він хоче зберегти в STDOUT, та новий рядок у файл.
Tq'\n
означає, що одна програма спробувала неправдивий податок, була оскаржена і відмовилася від вбивці. Він ілюструє інший випадок, коли написано два символи: якщо вам черга, і ви змушені відмовитись від картки - або від правильного виклику опонента (як тут), або від неправильного виклику блоку - тоді ви повинні написати обидва карту, яку ви віддаєте, і новий рядок, щоб закінчити свою чергу.
Asq!'\n
означатиме, що Гравець В намагався вбити гравця A ( A
), але А стверджував, що має Contessa, щоб заблокувати його ( s
). Б не повірив А і кинув виклик ( q
). Виявлено, що вони насправді мали Contessa ( !
). Б відмовився від вбивці як покарання, втративши монети, і закінчив свою чергу ( '\n
), написавши двох символів, як у тому спеціальному випадку. (Якби A вирішив не блокувати чи кидати виклик, це могло б написати =
, і тоді його опонент побачив би, що черга закінчилася і написала новий рядок. Потім рядок прочитав A=\n
би, як приклад перевороту.)
Sq*0\n
означає, що одна програма намагається викрасти; супротивник кидає виклик, не вірячи, що у злодія є Капітан; і оригінальна програма розкриває капітана, тому виклик не вдається, і претендент відмовляється герцогу в якості покарання. (Іншим варіантом для його опонента було б прийняти крадіжку, написавши письмово p
. Потім її противник виявить кінець своєї черги та напише \n
, в результаті чого вийде рядок Sp\n
.)
Арбітр
Програми будуть викликані цим сценарієм Python. Він проводить десять раундів, в яких кожен учасник стикається з кожним іншим учасником, переходячи як перший, так і другий. Він відслідковує підрахунки карт і монет і визначає програв першою програмою, щоб закінчити рядок з розділовим знаком двічі. Програми, які виходять із ненульовим статусом, змінюють файл, записують незаконне переміщення у файл або намагаються незаконно обмінятися, Exchange автоматично втрачається. Якщо кожен гравець виконує більше 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)
Різне
Одна програма не може мати код, специфічний для іншої програми, і програми не можуть допомогти один одному. (У вас може бути кілька програм, але вони ніяк не можуть взаємодіяти між собою.)
Якщо ваша програма втрачає обидві картки за один і той же поворот, їй потрібно написати лише одну. Арбітр виявить, що його було ліквідовано.
Програми можуть вивчати історію гри у файлі та заохочувати її, але не потрібно, але це не потрібно. Роблячи це, вони можуть визначити, які картки претендував їхній опонент, і впіймати їх у брехні.
У реальній грі на перевороті ви можете оскаржити дію, а потім спробувати заблокувати її тим же ходом. Я не міг зробити так, щоб специфікація працювала, якщо я дозволив це, тому ви можете або оскаржити, або заблокувати певну дію, але не обидва.
Мої вибачення у @PeterTaylor, який попереднього разу я опублікував це, запропонував відправити його в пісочну скриньку і переробити протокол, щоб виводити трубку назад і назад в STDOUT / STDIN. Я постарався так, так важко зробити цю роботу, витративши на неї цілий день (коли я вже витратив цілий день на написання оригінального виклику). Але Біржі виявилися дуже складними для здійснення цього шляху, плюс це збільшило б складність подань, вимагаючи від них відстежувати свій рахунок монет. Тому я виклав виклик більш-менш, як це було спочатку.
S
, програма B блокується письмом c
, A відмовляється кинути виклик написанням \n
. Успішний виклик крадіжки піде: A пише S
, B кидає виклики письмово q
, A визнає виклик, написавши, наприклад _\n
, Ви можете вживати лише одну дію за поворот, включаючи обмін. Юридичні відповіді на біржі є прийнятими та складними.