Ein Spiel von atomaren Ausmaßen

21

Deine Aufgabe ist es, einen Bot zu machen, der Atomas mit der höchsten Punktzahl spielt.

Wie das Spiel funktioniert:

Das Spielfeld beginnt mit einem Ring aus 6 "Atomen" mit Nummern von 1bis3 . Sie können ein Atom zwischen zwei Atomen oder auf einem anderen Atom "spielen", abhängig von dem Atom selbst.

Sie können entweder ein normales Atom oder ein spezielles Atom haben.

Das normale Atom:

Sie können ein normales Atom zwischen zwei beliebigen Atomen auf dem Brett spielen.

Sie beginnen mit Atomen im Bereich 1 to 3, aber der Bereich erhöht sich alle 40 Züge um 1 (nach 40 Zügen wird der Bereich also größer 2 to 4).

Wenn sich Atome auf dem Brett befinden, die niedriger als die Reichweite sind, besteht die 1 / no. of atoms of that number on the boardGefahr des Laichens.

Nehmen wir an, Sie müssen 2spielen, und das Brett sieht folgendermaßen aus:

   1 1 2 1

Lassen Sie uns 2die rechts von der platzieren 1.

Das Board wird jetzt:

   1 1 2 1 2

Hinweis: Das Board wickelt sich um, sodass sich 1das ganz links neben dem befindet2 dem ganz rechts befindet. Dies wird später wichtig sein.

Es gibt 4 Arten von "speziellen" Atomen:

Das +Atom:

Dieses Atom wird zwischen zwei Atomen gespielt. Es besteht eine Wahrscheinlichkeit von 1 zu 5, dass es laicht.

Wenn die Atome auf beiden Seiten des +Atoms gleich sind, kommt es zur Fusion. So funktioniert das:

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.

Beispiel:

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

Wenn die Atome auf beiden Seiten des +Atoms unterschiedlich sind, verbleiben die Atome +auf dem Brett.

Beispiel:

   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)

Das -Atom:

Dieses Atom wird auf einem anderen Atom gespielt. Es besteht eine Wahrscheinlichkeit von 1 zu 10, dass es laicht.

Das -Atom entfernt ein Atom von der Tafel und gibt Ihnen die Wahl zwischen:

  • Spiele das entfernte Atom in der nächsten Runde oder
  • Verwandle es in ein + Atom, um die nächste Runde zu spielen.

Beispiel:

   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)

Das schwarze +Atom (B ):

Dieses Atom wird zwischen 2 Atomen gespielt. Es hat eine Chance von 1 zu 80 zu laichen und erscheint nur, wenn Ihre Punktzahl> 750 ist.

Dieses Atom ist im Grunde dasselbe wie das +Atom, mit der Ausnahme, dass es zwei beliebige Atome miteinander verschmilzt +. Von da an folgt es der +Regel (es verschmilzt nur Atome, wenn die Atome auf beiden Seiten des verschmolzenen Atoms gleich sind).

Das verschmolzene Atom infolge des Schwarzen +ist gleich:

  • das Atom mit der höheren Zahl in der Fusion + 3
  • 4wenn die beiden verschmolzenen Atome +‚s

Beispiel:

   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)

Ein anderes Beispiel:

   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)

Das Klonatom ( C):

Dieses Atom wird auf einem anderen Atom gespielt. Es hat eine 1: 60-Chance zu laichen und erscheint nur, wenn Ihre Punktzahl> 1500 ist.

Mit dem Klonatom können Sie ein Atom auswählen und es in der nächsten Runde spielen.

Beispiel:

   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

Hier ist mein Build des Spiels 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()

So funktioniert das Bot-Ding:

Eingang

  • Ihr Bot erhält 2 Eingänge: das Atom, das gerade im Spiel ist, und den Status des Boards.
  • Das Atom wird so aussehen:
    • +für ein +Atom
    • -für ein -Atom
    • Bfür ein schwarzes +Atom
    • C für ein Klonatom
    • {atom} für ein normales Atom
  • Der Status des Boards sieht dann so aus:
    • atom 0 atom 1 atom 2... atom nmit durch Leerzeichen getrennten Atomen ( atom numschließt atom 1, um ein "Ring" -Spielbrett zu simulieren)
  • Diese beiden werden durch ein getrennt /.

Beispieleingaben:

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)

Ausgabe

  • Sie geben eine Zeichenfolge aus, je nachdem, um welches Atom es sich handelt.

    • Wenn das Atom zwischen zwei Atomen gespielt werden soll:

      • Geben Sie die Lücke aus, in der Sie das Atom spielen möchten. Die Lücken sind wie zwischen den einzelnen Atomen:

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

        ( gap nGibt an, dass Sie das Atom zwischen atom 1und Atom platzieren möchten. n) Geben 2Sie dies also aus, wenn Sie das Atom spielen möchten gap 2.

    • Wenn das Atom auf einem Atom gespielt werden soll:
      • Geben Sie das Atom aus, auf dem Sie es spielen möchten, 2wenn Sie also das Atom spielen möchten atom 2.
    • Wenn das Atom a ist -:
      • Geben Sie das Atom aus, auf dem Sie es spielen möchten, gefolgt von einem Leerzeichen, gefolgt von der y/nWahl, das Atom in ein +späteres zu verwandeln . 2, "y"Wenn Sie also das Atom anspielen möchten atom 2, und Sie möchten es in ein verwandeln +. Hinweis: Dies erfordert 2 Eingänge anstelle von 1.

Beispielausgaben:

(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)
  • Um den Bot zum Laufen zu bringen, müssen Sie zu dem PopenBit gehen (ungefähr am Ende des Codes) und es durch das ersetzen, was Ihr Programm als Pythonic-Liste laufen lässt (wenn es also ein Programm ist derp.java, ersetzen Sie es ["python", "bot.py"]durch ["java", "derp.java"]).

Antwortspezifische Angaben:

  • Fügen Sie den gesamten Code Ihres Bots in die Antwort ein. Wenn es nicht passt, zählt es nicht.
  • Jeder Benutzer darf mehr als einen Bot haben, alle sollten sich jedoch in separaten Antwortposts befinden.
  • Geben Sie Ihrem Bot auch einen Namen.

Wertung:

  • Der Bot mit der höchsten Punktzahl gewinnt.
    • Ihr Bot wird für 20 Spiele getestet und das Endergebnis ist der Durchschnitt der 20 Spiele.
  • Der Tie-Breaker ist der Zeitpunkt des Uploads der Antwort.
  • Ihre Antwort wird also folgendermaßen formatiert:

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

Viel Glück!

Clismique
quelle
Wie funktioniert das +für ein -Atom erzeugte ? Wenn Sie sich entscheiden, ywerden Sie garantiert +beim nächsten Zug dabei sein?
Ton Hospel
4
Ich schlage vor, Ihren Bot-Treiber so zu ändern, dass er jedes eigenständige Programm verarbeiten kann, das Eingaben in STDIN entgegennimmt und ein Ergebnis in STDOUT liefert. Das sollte Sprachunabhängigkeit geben und die meisten Sprachen, die auf dieser Site verwendet werden, können dies leicht tun. Dies bedeutet natürlich, dass ein striktes E / A-Format festgelegt wird, z. B. input_atom\natom0 atom1 .... atomn\nfür STDIN
Ton Hospel vom
1
Der Code scheint in der Lage zu sein, +in die Elementliste aufgenommen zu werden, aber dies ist nirgends in der textuellen Beschreibung zu finden
Ton Hospel
1
Ah, ich sehe, Sie haben das Programm dazu gebracht, externe Bots aufzurufen. Sie müssen jedoch auch die aktuelle Zugnummer und Punktzahl auf STDIN übergeben, da der Bot sonst nicht vorhersagen kann, wie wahrscheinlich es ist, dass die einzelnen Atome in der Zukunft auftreten
Ton Hospel,
1
Idk, wenn die Leute Zeit damit verbringen, eine Lösung zu erstellen, wenn der Controller nicht verbessert wird. Ich mag die Frage, aber nicht die Umsetzung.
mbomb007

Antworten:

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

Ich fand, dass der Controller:

  • stürzt ab, wenn die Punktzahl 1500 überschreitet;
  • verschmilzt nicht richtig Atome in den gleichen Fällen.
mdahmoune
quelle
0

Python, RandomBot, Score = 7,95

Nichts Besonderes, nur ein zufälliger Bot.

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

Nur ein sehr schlechter Bot, der den Controller oft zum Absturz bringt

TuxCrafting
quelle
Wie kommt es zum Absturz des Controllers? Und wenn ja, liegt ein Problem mit dem Controller oder Ihrem Bot vor?
mbomb007
@ mbomb007 Ich erinnere mich nicht, warum es abstürzt, aber die Abstürze waren im Controller
TuxCrafting
Dieser Bot sollte fehlerfrei funktionieren, ändern Sie einfach den Code ein wenig, um das aktualisierte "stdin" -Ding zu berücksichtigen.
Clismique