Un gioco di proporzioni atomiche


21

Il tuo compito è creare un bot che riproduca Atomas , con il punteggio più alto.

Come funziona il gioco:

Il tabellone inizia con un anello di 6 "atomi", con numeri che vanno da 1a 3. Puoi "suonare" un atomo tra due atomi o su un altro atomo, a seconda dell'atomo stesso.

Puoi avere un atomo normale o un atomo speciale.

L'atomo normale:

Puoi giocare un normale atomo tra due atomi disponibili sul tabellone.

Inizi con atomi nell'intervallo 1 to 3, ma l'intervallo aumenta di 1 ogni 40 mosse (quindi dopo 40 mosse, l'intervallo diventa 2 to 4).

Se ci sono atomi sul tabellone che sono più bassi della portata, ha la 1 / no. of atoms of that number on the boardpossibilità di generarsi.

Diciamo che devi 2giocare, e il tabellone è simile al seguente:

   1 1 2 1

Posizioniamo il 2a destra del 1.

La scheda ora diventa:

   1 1 2 1 2

Nota: la scheda si avvolge, quindi l' 1estrema sinistra è in realtà accanto 2all'estrema destra. Questo sarà importante in seguito.

Esistono 4 tipi di atomi "speciali", e sono:

L' +atomo:

Questo atomo si gioca tra due atomi. Ha una probabilità 1 su 5 di spawnare.

Se gli atomi su entrambi i lati +dell'atomo sono uguali, si verifica la fusione. Ecco come funziona:

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.

Esempio:

   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].

Se gli atomi su entrambi i lati +dell'atomo sono diversi, i +resti sulla scheda.

Esempio:

   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)

L' -atomo:

Questo atomo è giocato su un altro atomo. Ha una possibilità 1 su 10 di spawnare.

L' -atomo rimuove un atomo dal tabellone e ti dà la possibilità di scegliere:

  • gioca l'atomo rimosso il prossimo round, oppure
  • trasformalo in un atomo + per giocare il prossimo round.

Esempio:

   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)

L' +atomo nero ( B):

Questo atomo è giocato tra 2 atomi. Ha una possibilità 1 su 80 di spawn e si genera solo quando il tuo punteggio è> 750.

Questo atomo è sostanzialmente lo stesso +dell'atomo, tranne per il fatto che fonde due atomi insieme, anche quelli +. Da quel momento, segue la +regola (fonde gli atomi solo se gli atomi su entrambi i lati dell'atomo fuso sono uguali).

L'atomo fuso come risultato del nero +è uguale a:

  • l'atomo numero più alto nella fusione + 3
  • 4se i due atomi fusi sono +di

Esempio:

   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)

Un altro esempio:

   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)

L'atomo clone ( C):

Questo atomo è giocato su un altro atomo. Ha una probabilità 1 su 60 di spawn e si genera solo quando il tuo punteggio è> 1500.

L'atomo clone ti consente di scegliere un atomo e giocarlo il prossimo round.

Esempio:

   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

Ecco la mia build del gioco, in 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()

Come funziona la cosa bot:

Ingresso

  • Il tuo bot otterrà 2 input: l'atomo che è attualmente in gioco e lo stato del tabellone.
  • L'atomo sarà così:
    • +per un +atomo
    • -per un -atomo
    • Bper un +atomo nero
    • C per un atomo di clone
    • {atom} per un atomo normale
  • Lo stato del consiglio sarà così:
    • atom 0 atom 1 atom 2... atom n, con gli atomi separati da spazi ( atom ntorna a atom 1, per simulare un tabellone "ring")
  • Questi due saranno separati da a /.

Input di esempio:

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)

Produzione

  • Emetterai una stringa, a seconda dell'atomo in gioco.

    • Se l'atomo è pensato per essere giocato tra due atomi:

      • Emetti il ​​gap in cui vuoi riprodurre l'atomo. Gli spazi vuoti sono simili tra ogni atomo, in questo modo:

        atom 0, GAP 0, atom 1, GAP 1, atom 2, GAP 2... atom n, GAP N
        

        ( gap nindica che si desidera posizionare l'atomo tra atom 1e atomo n) Quindi emettere 2se si desidera riprodurre l'atomo gap 2.

    • Se l'atomo è pensato per essere giocato su un atomo:
      • Emetti l'atomo su cui vuoi giocare, quindi 2se vuoi riprodurre l'atomo atom 2.
    • Se l'atomo è un -:
      • Emetti l'atomo su cui vuoi giocare, seguito da uno spazio, seguito da una y/nscelta di trasformare l'atomo in un +successivo, quindi 2, "y"se vuoi giocare l'atomo su atom 2e vuoi trasformarlo in a +. Nota: ciò richiede 2 ingressi, anziché 1.

Esempi di output:

(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)
  • Per far funzionare il bot, devi andare al Popenbit (intorno alla fine del codice) e sostituirlo con qualunque cosa faccia funzionare il tuo programma come un elenco Pythonic (quindi se il tuo programma lo è derp.java, sostituiscilo ["python", "bot.py"]con ["java", "derp.java"]).

Specifiche specifiche della risposta:

  • Inserisci l'intero codice del tuo bot nella risposta. Se non si adatta, non conta.
  • A ogni utente è consentito avere più di 1 bot, tuttavia, dovrebbero essere tutti in post di risposta separati.
  • Inoltre, dai un nome al tuo bot.

punteggio:

  • Vince il bot con il punteggio più alto.
    • Il tuo bot verrà testato per 20 partite e il punteggio finale è la media delle 20 partite.
  • Il tie-breaker sarà il momento del caricamento della risposta.
  • Quindi la tua risposta sarà formattata in questo modo:

    {language}, {bot name}
    Score: {score}
    

In bocca al lupo!


Come funziona il generato +per un -atomo? Se scegli y, avrai la garanzia di ottenere una +mossa successiva?
Ton Hospel,

4
Suggerisco di cambiare il driver del bot in modo che possa gestire qualsiasi programma autonomo che accetta input su STDIN e dia un risultato su STDOUT. Ciò dovrebbe garantire l'indipendenza linguistica e la maggior parte delle lingue utilizzate in questo sito può farlo facilmente. Ovviamente questo significa definire un formato I / O rigoroso, ad esempio input_atom\natom0 atom1 .... atomn\nper STDIN
Ton Hospel,

1
Il codice sembra essere in grado di +
inserirsi

1
Ah, vedo che hai reso il programma in grado di chiamare robot esterni. Tuttavia, devi anche passare il numero di mossa attuale e segnare su STDIN, altrimenti il ​​robot non può prevedere le possibilità che ogni atomo si verifichi in futuro
Ton Hospel,

1
Idk se le persone passeranno il tempo a creare una soluzione se il controller non è migliorato. Mi piace la domanda, ma non l'implementazione.
mbomb007,

Risposte:


1

Python, draftBot, Score = 889

import random
def h(b):
    s=0
    for x in b:
        try:
            s+=int(x)
        except: 
            s+=0
    return s
def d(i):g=i.split("/");a=g[0];b=g[1].split(" ");return(a,b)
def p(a,_,j):
    v=[]
    for x in _:
        try:
            v.append(int(x))
        except: 
            v.append(0)
    try:
        v=v[:j+1]+[int(a)]+v[j+1:]
    except: 
        v=v[:j+1]+[a]+v[j+1:]
    r1=[[]];b=[x for x in v];m=range(len(b)+1)
    for k in m:
        for i in m:
            for j in range(i):
                c = b[j:i + 1]
                if len(c)%2==0 and c==c[::-1] and 0 not in c:r1.append(c)
        b.insert(0, b.pop())
    q1=max(r1,key=len)
    r2=[[]];b=[x for x in v];m=range(len(b)+1)
    for k in m:
        for i in m:
            for j in range(i):
                c = b[j:i + 1]
                if len(c)>2 and len(c)%2==1 and c==c[::-1] and "+" in c and 0 not in c:r2.append(c)
        b.insert(0, b.pop())
    q2=max(r2,key=h)
    with open('f.log', 'a') as f:f.write('pal '+str(_)+' : '+str(q1)+' : '+str(q2)+'\n')
    if q2!=[]:return 100+h(q2)
    else:return len(q1)
i=raw_input()
(a,b)=d(i)
if a in ['C','B']:print('0')
elif a=='-':print("0 y" if random.randint(0, 1) == 1 else "0 n")
else:q,j=max((p(a,b,j),j)for j in range(len(b)));print(str(j))

Ho scoperto che il controller:

  • si arresta in modo anomalo quando il punteggio supera 1500;
  • non unisce correttamente gli atomi negli stessi casi.

0

Python, RandomBot, Punteggio = 7,95

Niente di speciale, solo un robot a caso.

import random

game_input = raw_input().split("/")
current_atom = game_input[0]
board = game_input[1].split(" ")

if current_atom != "-":
    print(random.randint(0, len(board) - 1))
else:
    random_choice = " y" if random.randint(0, 1) == 1 else " n"
    print(str(random.randint(0, len(board) - 1)) + random_choice)

0

Python, BadPlayer, Punteggio = 21.45

import random

try:
    raw_input
except:
    raw_input = input

game_input = raw_input().split("/")
current_atom = game_input[0]
board = game_input[1].split(" ")

def get_chain(board, base):
    chain = []
    board = board[:]
    try:
        while board[base] == board[base + 1]:
            chain = [board[base]] + chain + [board[base + 1]]
            del board[base]
            del board[base]
            base -= 1
    except IndexError:
        pass
    return chain

def biggest_chain(board):
    chains = []
    base = 0
    i = 0
    while i < len(board) - 1:
        chains.append([i, get_chain(board, i)])
        i += 1
    return sorted(chains, key=lambda x: len(x[1]) / 2)[-1]

def not_in_chain():
    a, b = biggest_chain(board)
    if len(b) == 0:
        print(random.randint(0, len(board) - 1))
    elif random.randint(0, 1) == 0:
        print(random.randint(a + len(b)/2, len(board) - 1))
    else:
        try:
            print(random.randint(0, a - len(b)/2 - 1))
        except:
            print(random.randint(a + len(b)/2, len(board) - 1))

if current_atom in "+B":
    a, b = biggest_chain(board)
    if len(b) == 0:
        print(0)
    else:
        print(a)
elif current_atom == "C":
    not_in_chain()
elif current_atom == "-":
    a, b = biggest_chain(board)
    if len(b) == 0:
        print(str(random.randint(0, len(board) - 1)) + " n")
    elif random.randint(0, 1) == 0:
        print(str(random.randint(a + len(b)/2, len(board) - 1)) + " n")
    else:
        try:
            print(str(random.randint(0, a - len(b)/2 - 1)) + " n")
        except:
            print(str(random.randint(0, len(board) - 1)) + " n")
else:
    not_in_chain()

Solo un bot molto brutto che spesso causa il crash del controller


Come si blocca il controller? E se lo fa, è un problema con il controller o il tuo bot?
mbomb007,

@ mbomb007 Non ricordo perché si è schiantato, ma gli arresti anomali erano nel controller
TuxCrafting

Questo bot dovrebbe funzionare senza alcun bug, basta modificare un po 'il codice per adattarlo alla cosa "stdin" aggiornata.
clismique,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.