Bảng xếp hạng
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
Một kho lưu trữ của trận đấu mới nhất, bao gồm nhật ký và tất cả các tệp đầu ra, có sẵn.
Máy tính, bởi Brilliand, là người chiến thắng! Câu trả lời của anh ấy được chấp nhận, nhưng điều đó không có nghĩa là thử thách đã kết thúc. Vui lòng gửi các mục mới hoặc chỉnh sửa các mục hiện tại của bạn và cố gắng đánh bật ngai vàng của anh ấy. Tôi sẽ trao một khoản tiền thưởng cho nhà lãnh đạo vào cuối tháng.
Luật chơi
Coup là một trò chơi bài được thiết kế cho 2-6 người chơi, chúng ta sẽ chơi với hai người. Nó bao gồm một kho tiền xu (vô hạn cho mục đích của chúng tôi) và một bộ gồm 15 thẻ, chứa 3 loại sau: Đại sứ, Sát thủ, Thuyền trưởng, Contessa, Duke. Khi bắt đầu trò chơi, mỗi người chơi được phát một đồng xu và chia hai lá bài ngẫu nhiên, họ giữ bí mật cho đến khi cần thiết. Đối tượng là người chơi cuối cùng có thẻ trong tay bạn.
Đến lượt mình, người chơi có thể thực hiện một trong các hành động sau bất kể thẻ của họ là gì:
- Thu nhập: lấy 1 xu từ kho bạc. Không thể chặn và không thể vượt qua.
- Viện trợ nước ngoài: lấy 2 xu từ kho bạc. Có thể bị chặn bởi một người chơi với Công tước. Không thể vượt qua.
- Cuộc đảo chính: Loại bỏ một thẻ của một đối thủ bạn chọn khỏi chơi. Chi phí 7 xu. Nạn nhân có thể chọn loại thẻ nào để loại bỏ. Nếu người chơi có từ 10 đồng xu trở lên khi bắt đầu lượt chơi, họ phải đảo chính. Không thể chặn và không thể vượt qua.
Tùy thuộc vào thẻ của họ, người chơi cũng có thể thực hiện một trong các hành động sau đây lần lượt:
- Trao đổi: một người chơi có Đại sứ có thể lấy hai thẻ từ bộ bài. Sau đó, họ có thể chọn từ tay của mình và các thẻ được rút ra nhiều thẻ như ban đầu. (Nghĩa là, nếu họ chỉ có một thẻ, họ có thể đổi nó lấy một trong những thẻ đã rút hoặc giữ nó, và nếu họ có hai thẻ, họ có thể chọn bất kỳ hai trong bốn thẻ.) Hai thẻ không mong muốn được trả lại cho bộ bài . Không thể chặn, nhưng thách thức.
- Sát thủ: một người chơi có Sát thủ có thể chi 3 xu để xóa thẻ của đối thủ khỏi trò chơi. Nạn nhân có thể chọn loại thẻ nào để loại bỏ. Có thể bị chặn bởi người chơi có Contessa, trong trường hợp đó, tiền không được trả lại. Thách thức, trong trường hợp tiền được trả lại.
- Ăn cắp: Một người chơi có Thuyền trưởng có thể lấy hai đồng xu từ đối thủ của họ. Nếu đối thủ có một đồng, họ sẽ lấy một đồng đó. Nếu đối thủ không có xu, họ có thể không Ăn cắp. Có thể bị chặn bởi người chơi có Đại sứ hoặc Thuyền trưởng. Thử thách.
- Thuế: Một người chơi có Công tước có thể lấy 3 đồng xu từ kho bạc. Không thể chặn, nhưng thách thức.
Phần khó khăn của Coup là người chơi được phép nói dối về những thẻ bài họ có! Bạn không cần phải có thẻ để cố gắng thực hiện hành động hoặc chặn liên quan đến nó.
Khi người chơi thực hiện hành động của thẻ, bất kỳ đối thủ nào (ngay cả một người không bị tổn hại bởi hành động đó) có thể thách thức diễn viên và nói rằng họ không tin rằng họ có thẻ cho hành động đó. Nếu người thách đấu là chính xác, hành động sẽ bị hủy và diễn viên phải loại bỏ một thẻ theo lựa chọn của họ (lấy lại bất kỳ đồng tiền nào họ đã chi nếu có). Nếu không, hành động được thực hiện, diễn viên trả lại thẻ mà họ bị thách thức lên boong và rút một cái mới, và người thách đấu phải loại bỏ một trong những thẻ của họ. Người chơi phải trung thực về những thẻ bài họ giữ khi bị thách đấu.
Các lá bài bị loại khỏi cuộc chơi với Assassination, Coup và các thử thách bị mất không được trả lại cho bộ bài, nhưng các lá bài được tiết lộ là một phần của một thử thách giành chiến thắng được đưa trở lại bộ bài.
Các khối có thể được thử thách giống như hành động. Ví dụ: nếu người chơi A yêu cầu Viện trợ nước ngoài và người chơi B nói "Tôi có Công tước và tôi chặn Viện trợ nước ngoài của bạn", A có thể nói "Tôi không tin rằng bạn có Công tước". Nếu khẳng định đó là đúng, B sẽ mất một thẻ vì bị nói dối và A mất 2 xu; nếu không, A mất một thẻ và không nhận được tiền, và B phải trả lại Công tước của họ cho bộ bài và rút một thẻ mới.
Cách thức các khối và thử thách hoạt động với Assassination phải được bổ sung. Giả sử Người chơi A nói "Tôi có Sát thủ và Tôi ám sát Người chơi B". Nếu B không cố gắng thách thức hoặc chặn A, thì vụ ám sát sẽ diễn ra: B mất thẻ và A trả 3 xu.
Ngoài ra, B có thể thách thức bằng cách nói "Tôi không tin rằng bạn có Sát thủ". Nếu đó là sự thật, thì A sẽ loại bỏ một thẻ và tiền của họ được trả lại, trong khi B không bị ảnh hưởng và lượt của A kết thúc. Nếu niềm tin của B là không chính xác và A giữ một Assassin, thì B sẽ mất cả hai thẻ của họ và thất bại, một cho thử thách không chính xác và một cho ám sát.
Thay vì thử thách, B có thể nói "Tôi có một Contessa và tôi chặn Kẻ ám sát". Nếu A tin B, thì lượt của A kết thúc và tiền của họ không được trả lại. Nhưng A có thể thách thức khối và nói "Tôi không tin rằng bạn có Contessa." Nếu B thực tế giữ một Contessa, thì A sẽ mất một thẻ cho thử thách không chính xác. Nhưng nếu B không, thì B sẽ mất một thẻ vì bị nói dối và một thẻ khác từ Vụ ám sát.
Logic tương tự như lời giải thích ở trên áp dụng cho khả năng Steal của Captain, trong đó hành động hoặc khối có thể bị thách thức.
Có thể mất cả hai thẻ của bạn và bị loại trong một lượt, nếu bạn không thành công thách thức một Kẻ ám sát hoặc bạn bị bắt khi tuyên bố rằng bạn có một Contessa để chặn một vụ ám sát. Bạn mất một thẻ từ thử thách và một thẻ từ Vụ ám sát.
Thử thách
Nhiệm vụ của bạn là viết một chương trình sẽ chơi Coup. Nó sẽ được đưa ra như là đối số dòng lệnh của nó:
- Tên của một tệp chứa danh sách các hành động của nó và đối thủ của nó cho đến nay.
- Một số nguyên từ 0 đến 12 cho biết số xu của đối thủ.
- Một số nguyên từ 0 đến 12 chỉ số đếm xu của nó.
- Một chuỗi dài từ một đến bốn ký tự chỉ ra các thẻ của nó. Thông thường, đây chỉ đơn giản là một hoặc hai thẻ mà chương trình của bạn có, nhưng nếu chương trình của bạn vừa thành công tại Sàn giao dịch, nó sẽ dài n + 2 ký tự, trong đó n là số thẻ còn lại của bạn. Chương trình của bạn sau đó phải xuất ra n thẻ mà nó muốn giữ thành STDOUT. (Các chương trình không được đọc hoặc truy cập STDOUT ngoài mục đích này - nếu bạn muốn tạo đầu ra gỡ lỗi, vui lòng ghi vào STDERR.)
- Một hoặc nhiều đối số chỉ ra các động thái pháp lý mà nó có thể thực hiện.
(Ví dụ gọi : yourprogram file.txt 1 7 '~!' a c p q
, có nghĩa là "Đối thủ của bạn có 1 xu. Bạn có 7 xu, Đại sứ và Contessa. Viết vào file.txt bạn chọn a, c, p hoặc q với lịch sử trò chơi và trạng thái trò chơi hiện tại. ")
Chương trình của bạn phải nối thêm một hoặc (trong hai tình huống cụ thể) hai ký tự vào tệp được cung cấp cho biết hành động của nó. Nó không được thay đổi nội dung hiện có của tập tin. Nó có thể tạo bất kỳ tập tin mới nào nó muốn, nhưng chỉ trong thư mục mà nó được chạy. Vui lòng cung cấp tất cả các lệnh cần thiết để biên dịch và chạy chương trình của bạn.
Tôi đã cung cấp hai ví dụ đối thủ cạnh tranh dưới đây, được viết bằng Go.
Định dạng đầu ra là:
I\n
: Thu nhập = earnings. Phản ứng pháp lý: bất kỳ hành động lần lượt nào (giả sử người ta có tiền cho Assassination / Coup).F
: Viện trợ nước ngoài. Phản ứng pháp lý:d
(chặn như một Công tước),p
(để nó qua).C
: Cuộc đảo chính. Phản ứng theo pháp luật: bất cứ của_
,'
,<
,=
,0
là trong tay của bạn.E
: Đổi. Phản hồi pháp lý:q
(thách thức, không tin người chơi có Đại sứ)p
,.T
: Thuế. Phản ứng pháp lý:q
(thách thức, không tin người chơi có Công tước)p
,.A
: Ám sát. Phản ứng theo pháp luật:s
(khối như một Contessa),q
(thách thức), và bất cứ của_
,'
,<
,=
,0
là trong tay của bạn.S
: Lấy trộm. Phản hồi về mặt pháp lý:a
(chặn làm Đại sứ),c
(chặn làm Thuyền trưởng),q
(thách thức, không tin người chơi có Thuyền trưởng) ,p
.d
: chặn Viện trợ nước ngoài như một Công tước. Phản ứng pháp lý:\n
(chấp nhận khối),q
(thách thức, không tin người chơi có Công tước).a
: chặn Steal làm Đại sứ. Phản ứng pháp lý:\n
(chấp nhận khối),q
(thách thức, không tin người chơi có Đại sứ).c
: chặn Steal làm Thuyền trưởng.\n
(chấp nhận chặn),q
(thách thức, không tin người chơi có Thuyền trưởng).s
: chặn một Kẻ ám sát như một Contessa. Phản hồi pháp lý:\n
(chấp nhận chặn),q
(thách thức, không tin người chơi có Contessa).p
: vượt qua thử thách Trao đổi / Thuế / Ăn cắp khi không đến lượt bạn. Không được sử dụng vớiA
; từ chối thách thức một Assassination viết một trong số đó_'<=0
. Phản hồi pháp lý:\n
(kết thúc lượt của bạn) và nếu bạn vừa thành công tại Sàn giao dịch, hãy viết các thẻ bạn muốn giữ từ đối số dòng lệnh thứ tư sang STDOUT.q
: thách thức hành động hoặc khối gần đây nhất. Phản ứng pháp lý: nếu bạn có thẻ cho hành động bị thách thức, bất kể~^*!$
đó là hành động nào . Nếu bạn không, thì bất cứ điều gì_'<=0
từ tay bạn muốn từ bỏ, tiếp theo là một dòng mới nếu và chỉ khi đến lượt bạn.~
,^
,*
,!
,$
: Tiết lộ rằng bạn đang nói sự thật về tổ chức, tương ứng, một đại sứ, một Assassin, một thuyền trưởng, một Contessa và Duke (còn sử dụng để đại diện cho các thẻ này trong đối số dòng lệnh, và STDOUT đầu ra trong Exchange ). Phản ứng theo pháp luật: bất cứ của_
,'
,<
,=
,0
bạn có trong tay của bạn._
,'
,<
,=
,0
: Từ bỏ như sự trừng phạt, tương ứng, một Đại sứ, và Assassin, một thuyền trưởng, một Contessa và Duke vì bạn mất một thách thức hoặc bị ám sát / Couped. Phản ứng pháp lý :\n
.\n
: kết thúc lượt của bạn, làm như vậy từ chối để thách thức một khối nếu có. Phản hồi về mặt pháp lý: mọi hành động viết hoa (giả sử người ta có tiền cho Assassination / Coup và đối thủ có tiền cho Steal).
Định dạng có các thuộc tính hữu ích sau:
- Lần lượt bắt đầu với một chữ in hoa.
- Các dòng theo mẫu: chữ in hoa, chữ thường, dấu chấm câu tùy chọn hoặc 0 cho các thẻ được tiết lộ, dòng mới.
- Một tệp kết thúc bằng một dòng mới hoặc một tệp trống, cho biết rằng đó là bắt đầu lượt của chương trình của bạn và nó phải chọn một hành động viết hoa.
- Các hành động pháp lý mà bạn được phép thực hiện một yêu cầu thường được xác định duy nhất bởi ký tự cuối cùng trong tệp. Ngoại lệ là
q
, sẽ có một số logic liên quan đến nó. Xem chức năngget_legal_actions
trong trọng tài để giúp hiểu điều này. Hoặc bạn chỉ có thể sử dụng các hành động pháp lý bạn đưa ra trên dòng lệnh. - Số lượng ký tự chẵn trên một dòng cho biết lượt chơi là của bạn và chương trình của bạn được yêu cầu chọn một hành động, thách thức một khối hoặc kết thúc lượt của nó.
- Số lượng ký tự lẻ trên một dòng cho biết rằng lượt chơi không phải của bạn và chương trình của bạn được yêu cầu chặn, thách thức hoặc tiết lộ / đầu hàng thẻ.
Tôi sẽ đưa ra một ví dụ cho mọi hành động.
I\n
là dễ hiểu nhất. Một chương trình lấy một xu Thu nhập, sau đó kết thúc lượt của nó. Đây là một trong hai trường hợp các chương trình phải in hai ký tự, vì Thu nhập là hành động duy nhất mà đối thủ không bị ảnh hưởng và không thể chặn hoặc thách thức.
Fp\n
có nghĩa là một chương trình đã lấy Viện trợ nước ngoài, sau đó đối thủ của nó đã từ chối chặn ( p
). Trong lần gọi tiếp theo, chương trình đầu tiên lưu ý rằng bằng chữ thường cuối cùng p
và / hoặc số ký tự chẵn trên dòng này, đến lượt nó, nó vẫn chưa kết thúc, vì vậy nó biết kết thúc lượt hiện tại của mình bằng cách in một dòng mới.
C=\n
có nghĩa là một chương trình đã phát động một cuộc đảo chính. Đối thủ của nó, biết rằng nó được kêu gọi để phản ứng bởi số lượng chữ cái lẻ trên dòng, đã từ bỏ một Contessa. Một lần nữa, chương trình đầu tiên biết rằng đây là lần đầu tiên nó chưa hoàn thành trong lần gọi tiếp theo bởi số lượng ký tự chẵn trên dòng, vì vậy nó đã viết một dòng mới để kết thúc lượt của mình.
Eq~<\n
sẽ có nghĩa là một chương trình đã cố gắng trao đổi ( E
) và đối thủ của nó đã thách thức ( q
). Chương trình Trao đổi tiết lộ rằng nó thực sự có một Đại sứ ( ~
) và người thách thức đã từ bỏ một Thuyền trưởng như một hình phạt ( <
). Sau khi kẻ thách thức thoát ra, chương trình Trao đổi được gọi lại với một chuỗi bốn ký tự làm đối số dòng lệnh thứ tư của nó (hoặc ba ký tự, nếu nó chỉ có một thẻ). Nó viết các ký tự đại diện cho các thẻ mà nó muốn giữ cho STDOUT và một dòng mới cho tệp.
Tq'\n
có nghĩa là một chương trình đã cố gắng đánh thuế không trung thực, bị thách thức và từ bỏ một Sát thủ. Nó minh họa trường hợp khác có hai ký tự được viết: nếu đến lượt bạn và bạn buộc phải từ bỏ một thẻ - từ thử thách chính xác của đối thủ (như ở đây) hoặc từ thử thách không chính xác của bạn về khối - thì bạn phải viết cả hai Thẻ bạn từ bỏ và một dòng mới để kết thúc lượt của bạn.
Asq!'\n
sẽ có nghĩa là Người chơi B đã cố gắng ám sát người chơi A ( A
), nhưng A tuyên bố có Contessa để chặn nó ( s
). B không tin A và thách thức ( q
). Một tiết lộ rằng trên thực tế, họ đã có một Contessa ( !
). B đã từ bỏ một Assassin như một hình phạt, mất tiền của họ và kết thúc lượt của họ ( '\n
), viết hai nhân vật như trong trường hợp đặc biệt đó. (Nếu A đã quyết định không để chặn hoặc thách thức, nó có thể đã được viết =
, và sau đó đối thủ của nó sẽ thấy vui về nó đã kết thúc và viết một dòng mới. Điểm mấu sau đó đã có thể đọc A=\n
, giống như ví dụ Coup.)
Sq*0\n
có nghĩa là một chương trình cố gắng ăn cắp; đối thủ thách đấu, không tin kẻ trộm có Thuyền trưởng; và chương trình ban đầu tiết lộ một Thuyền trưởng, vì vậy thử thách không thành công và người thách đấu từ bỏ Công tước như một hình phạt. (Một lựa chọn khác cho đối thủ của nó là chấp nhận Steal bằng cách viết p
. Đối thủ của nó sau đó sẽ phát hiện kết thúc lượt của nó và viết \n
, dẫn đến một dòng Sp\n
.)
Trọng tài
Các chương trình sẽ được gọi bởi tập lệnh Python này. Nó tiến hành mười vòng, trong đó mọi đối thủ phải đối mặt với mọi đối thủ khác trong khi đi cả thứ nhất và thứ hai. Nó theo dõi số lượng thẻ và số xu và xác định người thua cuộc bằng chương trình đầu tiên kết thúc một dòng bằng dấu chấm hai lần. Các chương trình thoát với trạng thái khác không, sửa đổi tệp, viết di chuyển bất hợp pháp vào tệp hoặc cố gắng trao đổi bất hợp pháp sẽ tự động bị mất. Nếu mỗi người chơi thực hiện hơn 100 hành động, bao gồm các khối và thử thách, không có người chiến thắng, thì cả hai chương trình đều thua. Một người chiến thắng được cấp một điểm. Người chơi có chương trình ghi được nhiều điểm nhất sẽ thắng.
Tôi đề nghị bạn đọc mã nguồn của Trọng tài viên, đặc biệt là get_legal_actions
chức năng. Nó có thể giúp bạn hiểu các đặc điểm kỹ thuật và viết chương trình của riêng bạn.
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)
Điều khoản khác
Một chương trình không thể có mã cụ thể cho chương trình khác và các chương trình không thể giúp đỡ lẫn nhau. (Bạn có thể có nhiều chương trình, nhưng chúng không thể tương tác với nhau theo bất kỳ cách nào.)
Nếu chương trình của bạn mất cả hai thẻ trong cùng một lượt, nó chỉ cần viết một thẻ. Trọng tài sẽ phát hiện ra rằng nó đã bị loại bỏ.
Có thể và khuyến khích, nhưng không bắt buộc, đối với các chương trình kiểm tra lịch sử của trò chơi trong tệp. Bằng cách đó, họ có thể xác định được những quân bài mà đối thủ của họ đã tuyên bố có và bắt họ nói dối.
Trong trò chơi Coup thực sự, bạn có thể thách đấu một hành động và sau đó cố gắng chặn nó trong cùng một lượt. Tôi không thể làm cho đặc tả hoạt động nếu tôi cho phép điều đó, vì vậy bạn có thể thách thức hoặc chặn một hành động nhất định, nhưng không phải cả hai.
Tôi xin lỗi @PeterTaylor, người mà lần trước tôi đã đăng bài này đề nghị tôi đăng nó lên hộp cát và làm lại giao thức để đầu ra đường ống qua lại trong STDOUT / STDIN. Tôi đã cố gắng rất nhiều để thực hiện công việc đó, dành trọn một ngày cho nó (khi tôi đã dành trọn một ngày để viết thử thách ban đầu). Nhưng Exchanges tỏ ra rất phức tạp khi thực hiện theo cách đó, cộng với việc nó sẽ làm tăng sự phức tạp của việc gửi bằng cách yêu cầu họ theo dõi số lượng xu của chính họ. Vì vậy, tôi đã đăng thử thách ít nhiều như ban đầu.
S
, chương trình khối B bằng cách viết c
, A từ chối thách thức bằng cách viết \n
. Thử thách thành công của Steal sẽ diễn ra: A viết S
, B thách thức bằng cách viết q
, A thừa nhận thử thách bằng cách viết _\n
, ví dụ: Bạn chỉ có thể thực hiện một hành động mỗi lượt, bao gồm Trao đổi. Các phản ứng pháp lý đối với Exchange là vượt qua và thách thức.