Ваша задача сделать бота, который играет в Atomas , с наибольшим количеством очков.
Как работает игра:
Игра начинается с кольца из 6 «атомов» с числами от 1до 3. Вы можете «сыграть» атом между двумя атомами или на другом атоме, в зависимости от самого атома.
Вы можете иметь нормальный атом или специальный атом.
Нормальный атом:
Вы можете сыграть нормальный атом между любыми двумя доступными атомами на доске.
Вы начинаете с атомов в диапазоне 1 to 3, но диапазон увеличивается на 1 один раз каждые 40 ходов (поэтому после 40 ходов диапазон становится 2 to 4).
Если на доске есть атомы, которые находятся ниже диапазона, он может 1 / no. of atoms of that number on the boardпоявиться.
Допустим, у вас есть 2игра, и доска выглядит так:
1 1 2 1
Разместим 2справа от 1.
Доска теперь становится:
1 1 2 1 2
Примечание: доска оборачивается, поэтому 1крайний левый на самом деле находится рядом с2 крайним правым. Это будет важно позже.
Есть 4 типа «специальных» атомов, и они:
+Атом:
Этот атом играется между двумя атомами. Вероятность появления 1 к 5.
Если атомы с обеих сторон +атома одинаковы, происходит слияние. Вот как это работает:
The two atoms fuse together to create an atom one higher.
(So, two 3 atoms fuse together to form one 4 atom.)
While the atoms on both sides of the fused atom are equal:
If the atoms on the side >= the fused atom:
The new fused atom = the old fused atom's value + 2.
If the atoms on the side < the fused atom:
The new fused atom = the old fused atom's value + 1.
Пример:
1 1 3 2 2 3 (the 1 on the left-hand side "wraps back"
to the 3 on the right-hand side)
Let's use the + on the two 2's in the middle.
-> 1 1 3 3 3 (the two 2's fused together to make a 3)
-> 1 1 5 (the two 3's fused with the 3, and because 3 >= 3,
the new fused atom = 3 + 2 = 5)
-> 6 (the two 1's fused with the 5, since the board wraps,
and because 1 < 5, the new fused atom = 5 + 1 = 6)
Because the atoms on the sides of the 6 don't exist, fusion stops,
and the board is now [6].
Если атомы на обеих сторонах +атома разные, то +остается на доске.
Пример:
1 3 2 3 1 1
Let's use the + on the 2 and 3 in the middle.
-> 1 3 2 + 3 1 1 (2 != 3, so the + stays on the board)
-Атом:
Этот атом играется на другом атоме. Вероятность появления 1: 10.
-Атом удаляет атом с доски, и дает вам выбор, либо:
- сыграть удаленный атом в следующем раунде, или
- превратите его в + атом, чтобы играть в следующем раунде.
Пример:
1 3 2 3 1 1
Let's use the - on the left-hand 2.
-> 1 3 3 1 1 (the 2 is now removed from the board)
Let's turn it into a +, and place it in between the 3's.
-> 1 4 1 1 (the two 3's fused together to make a 4)
-> 5 1 (the two 1's fused with the 4, and because 1 < 4,
the new fused atom = 4 + 1 = 5)
Черный +атом (B ):
Этот атом играется между 2 атомами. Вероятность появления 1: 80, и появляется только после того, как ваш счет> 750.
Этот атом в основном такой же, как +атом, за исключением того, что он соединяет любые два атома, даже +с атомами . С этого момента он следует +правилу (он объединяет атомы только в том случае, если атомы с обеих сторон конденсированного атома равны).
Слитый атом в результате черного +равен:
- большее число атомов в слиянии + 3
4если два слитых атомы+«ы
Пример:
1 3 2 1 3 1
Let's use the black + on the 2 and 1 in the middle.
-> 1 3 5 3 1 (the 2 and 1 fused together to make a 2 + 3 = 5)
-> 1 6 1 (+ rule)
-> 7 (+ rule)
Другой пример:
2 + + 2
Let's use the black + on the two +'s.
-> 2 4 2 (the two +'s fused together to make a 4)
-> 5 (+ rule)
Атом клона ( C):
Этот атом играется на другом атоме. Вероятность появления 1 к 60, и появляется только после того, как ваш счет> 1500.
Атом клона позволяет выбрать атом и сыграть его в следующем раунде.
Пример:
1 1 2 1
Let's use the clone on the 2, and place it to the right of the 1.
-> 1 1 2 1 2
Вот моя сборка игры в Python 2:
import random
import subprocess
logs='atoms.log'
atom_range = [1, 3]
board = []
score = 0
move_number = 0
carry_over = " "
previous_moves = []
specials = ["+", "-", "B", "C"]
def plus_process(user_input):
global board, score, previous_moves, matches
previous_moves = []
matches = 0
def score_calc(atom):
global score, matches
if matches == 0:
score += int(round((1.5 * atom) + 1.25, 0))
else:
if atom < final_atom:
outer = final_atom - 1
else:
outer = atom
score += ((-final_atom + outer + 3) * matches) - final_atom + (3 * outer) + 3
matches += 1
if len(board) < 1 or user_input == "":
board.append("+")
return None
board_start = board[:int(user_input) + 1]
board_end = board[int(user_input) + 1:]
final_atom = 0
while len(board_start) > 0 and len(board_end) > 0:
if board_start[-1] == board_end[0] and board_end[0] != "+":
if final_atom == 0:
final_atom = board_end[0] + 1
elif board_end[0] >= final_atom:
final_atom += 2
else:
final_atom += 1
score_calc(board_end[0])
board_start = board_start[:-1]
board_end = board_end[1:]
else:
break
if len(board_start) == 0:
while len(board_end) > 1:
if board_end[0] == board_end[-1] and board_end[0] != "+":
if final_atom == 0:
final_atom = board_end[0]
elif board_end[0] >= final_atom:
final_atom += 2
else:
final_atom += 1
score_calc(board_end[0])
board_end = board_end[1:-1]
else:
break
if len(board_end) == 0:
while len(board_start) > 1:
if board_start[0] == board_start[-1] and board_start[0] != "+":
if board_start[0] >= final_atom:
final_atom += 2
else:
final_atom += 1
score_calc(board_start[0])
board_start = board_start[1:-1]
else:
break
if matches == 0:
board = board_start + ["+"] + board_end
else:
board = board_start + [final_atom] + board_end
for a in range(len(board) - 1):
if board[a] == "+":
if board[(a + 1) % len(board)] == board[a - 1]:
board = board[:a - 1] + board[a:]
plus_process(a)
break
def minus_process(user_input, minus_check):
global carry_over, board
carry_atom = board[int(user_input)]
if user_input == len(board) - 1:
board = board[:-1]
else:
board = board[:int(user_input)] + board[int(user_input) + 1:]
if minus_check == "y":
carry_over = "+"
elif minus_check == "n":
carry_over = str(carry_atom)
def black_plus_process(user_input):
global board
if board[int(user_input)] == "+":
if board[int(user_input) + 1] == "+":
inter_atom = 4
else:
inter_atom = board[int(user_input) + 1] + 2
else:
if board[int(user_input)] + 1 == "+":
inter_atom = board[int(user_input)] + 2
else:
inter_list = [board[int(user_input)], board[int(user_input) + 1]]
inter_atom = (inter_list.sort())[1] + 2
board = board[int(user_input) - 1:] + [inter_atom] * 2 + board[int(user_input) + 1:]
plus_process(int(user_input) - 1)
def clone_process(user_input):
global carry_over
carry_over = str(board[int(user_input)])
def regular_process(atom,user_input):
global board
if user_input == "":
board.append(random.randint(atom_range[0], atom_range[1]))
else:
board = board[:int(user_input) + 1] + [int(atom)] + board[int(user_input) + 1:]
def gen_specials():
special = random.randint(1, 240)
if special <= 48:
return "+"
elif special <= 60 and len(board) > 0:
return "-"
elif special <= 64 and len(board) > 0 and score >= 750:
return "B"
elif special <= 67 and len(board) > 0 and score >= 1500:
return "C"
else:
small_atoms = []
for atom in board:
if atom not in specials and atom < atom_range[0]:
small_atoms.append(atom)
small_atom_check = random.randint(1, len(board))
if small_atom_check <= len(small_atoms):
return str(small_atoms[small_atom_check - 1])
else:
return str(random.randint(atom_range[0], atom_range[1]))
def specials_call(atom, user_input):
specials_dict = {
"+": plus_process,
"-": minus_process,
"B": black_plus_process,
"C": clone_process
}
if atom in specials_dict.keys():
if atom == "-":
minus_process(user_input[0], user_input[1])
else:
specials_dict[atom](user_input[0])
else:
regular_process(atom,user_input[0])
def init():
global board, score, move_number, carry_over, previous_moves
board = []
score = 0
for _ in range(6):
board.append(random.randint(1, 3))
while len(board) <= 18:
move_number += 1
if move_number % 40 == 0:
atom_range[0] += 1
atom_range[1] += 1
if carry_over != " ":
special_atom = carry_over
carry_over = " "
elif len(previous_moves) >= 5:
special_atom = "+"
else:
special_atom = gen_specials()
previous_moves.append(special_atom)
bot_command = "python yourBot.py"
bot = subprocess.Popen(bot_command.split(),
stdout = subprocess.PIPE,
stdin = subprocess.PIPE)
to_send="/".join([
# str(score),
# str(move_number),
str(special_atom),
" ".join([str(x) for x in board])
])
bot.stdin.write(to_send)
with open(logs, 'a') as f:f.write(to_send+'\n')
bot.stdin.close()
all_user_input = bot.stdout.readline().strip("\n").split(" ")
specials_call(special_atom, all_user_input)
print("Game over! Your score is " + str(score))
if __name__ == "__main__":
for a in range(20):
with open(logs, 'a') as f:f.write('round '+str(a)+'-'*50+'\n')
init()
Как работает бот:
вход
- Ваш бот получит 2 входа: атом, который в данный момент находится в игре, и состояние доски.
- Атом будет выглядеть так:
+для+атома-для-атомаBдля черного+атомаCдля атома клона{atom}для нормального атома
- Состояние платы будет примерно таким:
atom 0 atom 1 atom 2... atom n, с атомами, разделенными пробелами (atom nпереносится назадatom 1, для имитации "кольцевой" игровой доски)
- Эти два будут разделены
/.
Пример входных данных:
1/1 2 2 3 (the atom in play is 1, and the board is [1 2 2 3])
+/1 (the atom in play is +, and the board is [1] on its own)
Выход
Вы выведете строку в зависимости от атома в игре.
Если атом предназначен для игры между двумя атомами:
Выведите промежуток, в котором вы хотите сыграть атом. Промежутки между каждым атомом примерно такие:
atom 0, GAP 0, atom 1, GAP 1, atom 2, GAP 2... atom n, GAP N(
gap nуказывает на то, что вы хотите поместить атом междуatom 1и атомомn). Так что выводите,2если хотите включить атомgap 2.
- Если атом предназначен для игры на атоме:
- Выведите атом, на котором вы хотите играть, поэтому,
2если вы хотите включить атомatom 2.
- Выведите атом, на котором вы хотите играть, поэтому,
- Если атом
-:- Выведите атом, на котором вы хотите его воспроизвести, за которым следует пробел, за которым следует
y/nвыбор превращения атома в более+поздний, поэтому,2, "y"если вы хотитеatom 2включить атом , и хотите превратить его в a+. Примечание: для этого требуется 2 входа вместо 1.
- Выведите атом, на котором вы хотите его воспроизвести, за которым следует пробел, за которым следует
Пример выходов:
(Atom in play is a +)
2 (you want to play the + in gap 2 - between atom 2 and 3)
(Atom in play is a -)
3 y (you want to play the - on atom 3, and you want to change it to a +)
2 n (you want to play the - on atom 2, and you don't want to change it)
- Чтобы заставить бот работать, вам нужно перейти к
Popenначалу (примерно в конце кода) и заменить его на то, что заставляет вашу программу работать в виде списка Pythonic (поэтому, если ваша программа естьderp.java, замените ее["python", "bot.py"]на["java", "derp.java"]).
Специфичные для ответа характеристики:
- Поместите весь код вашего бота в ответ. Если это не подходит, это не считается.
- Каждому пользователю разрешено иметь более 1 бота, однако все они должны быть в отдельных ответных сообщениях.
- Также дайте вашему боту имя.
Подсчет очков:
- Бот с наибольшим количеством очков побеждает.
- Ваш бот будет проверен на 20 игр, а итоговый результат будет средним из 20 игр.
- Тай-брейк будет временем загрузки ответа.
Таким образом, ваш ответ будет отформатирован так:
{language}, {bot name} Score: {score}
Удачи!
input_atom\natom0 atom1 .... atomn\nдля STDIN
+в список элементов, но это нигде не найдено в текстовом описании
+для-атома? Если вы выбрали,yбудет ли гарантировано, что вы получите+на следующем ходу?