Un jeu aux proportions atomiques

21

Votre tâche consiste à créer un bot qui joue Atomas , avec le meilleur score.

Fonctionnement du jeu:

Le plateau de jeu commence par un anneau de 6 "atomes", avec des nombres allant de 1à 3. Vous pouvez "jouer" un atome entre deux atomes, ou sur un autre atome, selon l'atome lui-même.

Vous pouvez soit avoir un atome normal, soit un atome spécial.

L'atome normal:

Vous pouvez jouer un atome normal entre deux atomes disponibles sur le plateau.

Vous commencez avec des atomes dans la plage 1 to 3, mais la plage augmente de 1 une fois tous les 40 mouvements (donc après 40 mouvements, la plage devient 2 to 4).

S'il y a des atomes sur la carte qui sont inférieurs à la plage, il a une 1 / no. of atoms of that number on the boardchance de se reproduire.

Disons que vous avez un 2jeu à jouer, et le tableau ressemble à ceci:

   1 1 2 1

Plaçons le 2à droite de la 1.

Le tableau devient maintenant:

   1 1 2 1 2

Remarque: la carte s'enroule, donc l' 1extrême gauche est en fait à côté de 2l'extrême droite. Ce sera important plus tard.

Il existe 4 types d'atomes "spéciaux", à savoir:

L' +atome:

Cet atome se joue entre deux atomes. Il a 1 chance sur 5 de se reproduire.

Si les atomes des deux côtés de l' +atome sont identiques, la fusion se produit. Voici comment ça fonctionne:

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.

Exemple:

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

Si les atomes des deux côtés de l' +atome sont différents, alors les +restes sur le plateau.

Exemple:

   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' -atome:

Cet atome est joué sur un autre atome. Il a 1 chance sur 10 de se reproduire.

L' -atome supprime un atome de la carte et vous donne le choix entre:

  • jouer l'atome retiré le tour suivant, ou
  • transformez-le en atome + pour jouer le tour suivant.

Exemple:

   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' +atome noir ( B):

Cet atome se joue entre 2 atomes. Il a 1 chance sur 80 de se reproduire et n'apparaît qu'une fois votre score> 750.

Cet atome est fondamentalement le même que l' +atome, sauf qu'il fusionne deux atomes ensemble, même +des atomes . À partir de là, il suit la +règle (il ne fusionne les atomes que si les atomes des deux côtés de l'atome fusionné sont égaux).

L'atome fusionné résultant du noir +est égal à:

  • l'atome de nombre le plus élevé dans la fusion + 3
  • 4si les deux atomes fusionnés sont +de

Exemple:

   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 autre exemple:

   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'atome clone ( C):

Cet atome est joué sur un autre atome. Il a 1 chance sur 60 de se reproduire et n'apparaît qu'une fois votre score> 1500.

L'atome clone vous permet de choisir un atome et de le jouer au tour suivant.

Exemple:

   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

Voici ma version du jeu, en 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()

Comment fonctionne le robot:

Contribution

  • Votre bot obtiendra 2 entrées: l'atome actuellement en jeu et l'état de la carte.
  • L'atome sera ainsi:
    • +pour un +atome
    • -pour un -atome
    • Bpour un +atome noir
    • C pour un atome de clone
    • {atom} pour un atome normal
  • L'état du conseil sera le suivant:
    • atom 0 atom 1 atom 2... atom n, avec les atomes séparés par des espaces ( atom nrevient à atom 1, pour simuler un plateau de jeu "en anneau")
  • Ces deux seront séparés par un /.

Exemples d'entrées:

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)

Production

  • Vous produirez une chaîne, en fonction de l'atome en jeu.

    • Si l'atome est destiné à être joué entre deux atomes:

      • Générez l'espace dans lequel vous voulez jouer l'atome. Les espaces sont comme entre chaque atome, comme ceci:

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

        ( gap nindique que vous voulez placer l'atome entre atom 1et atome n) Donc sortez 2si vous voulez jouer l'atome dessus gap 2.

    • Si l'atome est destiné à être joué sur un atome:
      • Sortez l'atome sur lequel vous voulez jouer, donc 2si vous voulez jouer sur l'atome atom 2.
    • Si l'atome est un -:
      • Sortez l'atome sur lequel vous voulez le jouer, suivi d'un espace, suivi d'un y/nchoix de transformer l'atome en un +plus tard, donc 2, "y"si vous voulez jouer l'atome atom 2et que vous voulez le transformer en un +. Remarque: cela nécessite 2 entrées, au lieu de 1.

Exemples de sorties:

(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)
  • Pour faire fonctionner le bot, vous devez aller dans le Popenbit (à la fin du code) et le remplacer par tout ce qui fait que votre programme fonctionne comme une liste Pythonic (donc si votre programme l'est derp.java, remplacez ["python", "bot.py"]par ["java", "derp.java"]).

Spécifications spécifiques à la réponse:

  • Placez le code entier de votre bot dans la réponse. Si ça ne va pas, ça ne compte pas.
  • Chaque utilisateur est autorisé à avoir plus d'un bot, cependant, ils doivent tous être dans des messages de réponse séparés.
  • Donnez également un nom à votre robot.

Notation:

  • Le bot avec le score le plus élevé gagne.
    • Votre bot sera testé pendant 20 matchs, et le score final est la moyenne des 20 matchs.
  • Le bris d'égalité sera le moment du téléchargement de la réponse.
  • Votre réponse sera donc formatée comme ceci:

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

Bonne chance!

clismique
la source
Comment fonctionne le généré +pour un -atome? Si vous avez choisi, yserez-vous assuré d'obtenir un +sur le prochain déménagement?
Ton Hospel
4
Je suggère de changer votre pilote de bot pour qu'il puisse gérer n'importe quel programme autonome qui prend des entrées sur STDIN et donne un résultat sur STDOUT. Cela devrait donner une indépendance linguistique et la plupart des langues utilisées sur ce site peuvent facilement le faire. Bien sûr, cela signifie définir un format d'E / S strict, par exemple input_atom\natom0 atom1 .... atomn\npour STDIN
Ton Hospel
1
Le code semble pouvoir être mis +dans la liste des éléments, mais cela ne se trouve nulle part dans la description textuelle
Ton Hospel
1
Ah, je vois que vous avez rendu le programme capable d'appeler des bots externes. Cependant, vous devez également passer le numéro de coup actuel et marquer sur STDIN sinon le bot ne peut pas prédire les chances que chaque atome se produise dans le futur
Ton Hospel
1
Idk si les gens vont passer du temps à créer une solution si le contrôleur n'est pas amélioré. J'aime la question, mais pas la mise en œuvre.
mbomb007

Réponses:

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))

J'ai trouvé que le contrôleur:

  • se bloque lorsque le score dépasse 1500;
  • ne fusionne pas correctement les atomes dans les mêmes cas.
mdahmoune
la source
0

Python, RandomBot, Score = 7,95

Rien d'extraordinaire, juste un robot aléatoire.

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)
clismique
la source
0

Python, BadPlayer, Score = 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()

Juste un très mauvais bot qui fait souvent planter le contrôleur

TuxCrafting
la source
Comment cela fait-il planter le contrôleur? Et si c'est le cas, c'est un problème avec le contrôleur, ou votre bot?
mbomb007
@ mbomb007 Je ne me souviens pas pourquoi il s'est bloqué, mais les plantages étaient dans le contrôleur
TuxCrafting
Ce bot devrait fonctionner sans aucun bogue, il suffit de modifier un peu le code pour tenir compte de la chose "stdin" mise à jour.
clismique