Es ist das Leben, Jim, aber nicht so, wie wir es kennen

58

Sie kennen wahrscheinlich Conways Spiel des Lebens , den berühmten Zellularautomaten, den der Mathematiker John Conway erfunden hat. Das Leben besteht aus einer Reihe von Regeln, mit denen Sie zusammen eine zweidimensionale Zelle simulieren können. Die Regeln entscheiden, welche Zellen auf dem Brett leben und welche sterben. Mit einigem Einfallsreichtum könnte man sagen, dass Life ein Null-Spieler-Spiel ist: ein Spiel mit dem Ziel, Muster mit interessantem Verhalten zu finden, wie der berühmte Segelflugzeug.

Segelflugzeug

Ein Zero-Player-Spiel ... Bis heute. Sie müssen ein Programm schreiben, das das Spiel des Lebens spielt - und es spielt, um zu gewinnen, im King of the Hill-Stil. Ihr Gegner (Singular) versucht natürlich dasselbe. Der Gewinner ist entweder der letzte Bot mit lebenden Zellen oder der Spieler mit den meisten lebenden Zellen nach 10000 Generationen.

Spielregeln

Die Regeln sind fast die gleichen wie normal (B3 / S23)

  • Eine lebende Zelle mit weniger als zwei freundlichen Nachbarn stirbt an Hunger.
  • Eine lebende Zelle mit zwei oder drei freundlichen Nachbarn überlebt.
  • Eine lebende Zelle mit mehr als drei befreundeten Nachbarn stirbt an Überbevölkerung.
  • Eine tote Zelle mit genau drei Nachbarn desselben Spielers wird lebendig, um für diesen Spieler zu kämpfen, vorausgesetzt, es gibt keine feindlichen Nachbarn .

... aber nach jeder Generation haben Sie und Ihr Gegner die Möglichkeit, einzugreifen. Sie können bis zu 30 Zellen aufwecken, um für Sie zu kämpfen. (Wer zuerst geht, entscheidet der Server.)

Die Tafel ist ein (x, y) Zellenquadrat. Alle Felder sind anfangs tot. Die Grenzen wickeln sich nicht um (dies ist keine torusförmige Welt) und sind dauerhaft tot.

Dies ist ein Wettbewerb im Geiste von Battlebots und Core Wars . Es gibt einen zentralen Server, auf dem Bots ausgeführt werden. Diesen finden Sie hier

Protokoll

Der Arena-Server spricht ein einfaches JSON-Protokoll, das über argv kommuniziert wird

Wobei Werte eine JSON-codierte Zeichenfolge ist

  • y_size: Die maximale y-Koordinate der Kacheln, bevor sie verschwinden
  • x_size: die maximalen x Kacheln, bevor sie verschwinden
  • tick_id: die aktuelle Ticknummer
  • board: ein Wörterbuch mit Schlüsseln in der Form '(y, x)' und Werten in der Form bot_id(int)
  • bot_id: Fliesen in der Tafel mit dieser ID gehören dir

Beispiel:

 {"y_size":2000,"x_size":2000,"board":{},"bot_id":1,"tick_id":1}

Teilen Sie dem Server Ihre Wahl mit:

  • Schicken Sie dem Server eine Liste mit Kacheln, um Ihre Farbe zu ändern.
  • Nur die leeren werden geändert
  • Listenformat für verschachtelte Koordinaten
    • [[0,0], [0,1], [100,22]...]

HINWEIS: Ihr Bot muss die Kacheln überhaupt nicht aktualisieren - der Server führt die Aktualisierung selbst durch

Wettbewerbsregeln

  • Wenn Ihre Implementierung das Protokoll nicht befolgt, verfällt der Spielzug. Der Server nimmt keine Statusänderung an
  • Sie dürfen einen Fehler im Arenaserver nicht vorsätzlich ausnutzen.
  • Lassen Sie Ihre KI in einer vernünftigen Zeit über Züge entscheiden. Bitte senden Sie Ihren nächsten Schritt so schnell wie möglich.
  • Zum Schluss sei bitte nett zum Server. Es ist für Ihren Genuss da.
  • Die Nichtbeachtung dieser Regeln kann zur Disqualifikation führen.
  • Im Falle eines Unentschieden haben beide Spieler 1 Gewinn zu ihrer Gesamtsumme hinzugefügt

Führen Sie den Controller selbst aus

Die Quelle für den Controller finden Sie hier . Es gibt zwei Möglichkeiten, den Controller auszuführen:

  • Wettbewerbsmodus (Terminal)
    • Eingerichtet mit python3 get_answers.py
    • Führen Sie einen Alles-gegen-Alles-Wettbewerb durch, bei dem jeder Bot gegeneinander antritt.
  • Testmodus (GUI)
    • Lauf python3 nice_gui.py
    • Klicken Pull Answers
    • Wenn Sie vor dem Posten eine eigene Antwort hinzufügen möchten, klicken Sie auf, File -> Add manual answersuchen Sie die Datei und wählen Sie die Sprache aus, in der sie geschrieben ist.
    • Wenn Ihre Sprache nicht vorhanden ist, rufen Sie mich an und ich werde versuchen, sie auf dem Server zu installieren. Ich werde sie ausführen (Installations- und Ausführungsanweisungen wären auch nett!)
    • Wähle 2 Bots, um gegeneinander anzutreten
    • Klicken Run
    • Schau das Spiel...
  • Installation
    • Benötigt python3
    • get_answers benötigt bs4 und html5lib
    • Controller erfordert eine Möglichkeit zum Ausführen von .sh-Dateien (MinGW unter Windows)

Beispielbild der App

Wertung

Der Bot mit den meisten Gewinnen ab dem 12/07/201612. Juli 14/07/2016 (14. Juli) konnte nicht herausfinden, wie man einen Bot ausführt), gewinnt.


In diesem Chatraum kann um Hilfe beim Controller / der GUI gebeten werden


Diese Frage befindet sich seit 2014 in der Entwicklung und war die am häufigsten gestellte Frage im Sandkasten. Besonderer Dank geht an Wander Nauta (Originalautor und Konzept), PPCG Chat (Kommentare und Hilfe) und alle, die im Sandbox-Beitrag kommentiert haben (weitere Kommentare).

Blau
quelle
25
Huh, ich dachte, das würde es nie aus dem Sandkasten schaffen. Toll!
Luis Mendo
Tippfehler
Luis Mendo
4
+1. Sie haben den AED Award verdient, weil Sie diese großartige Frage aus dem Sandkasten geholt haben!
Am
1
@ KevinLau-notKenny oh, okay. Können Sie einen Befehl in einer Datei ausführen?
6.
1
@Magenta Wenn ich sie bekomme (ich hatte das völlig vergessen, obwohl es in einem ständig geöffneten Tab war), starte ich es jetzt
Blue

Antworten:

4

Python 3, Exploder

Legt kleine Sprengsätze um den Platz, ohne Rücksicht darauf, ob sich dort bereits ein Block befindet.

from random import randint
import sys,json,copy
q=json.loads(sys.argv[1])
x=q["x_size"];y=q["y_size"];F=[[0,1],[1,0],[1,1],[1,2],[2,0],[2,2]];D=[]
for g in [0]*5:
 X=randint(0,x);Y=randint(0,y);A=copy.deepcopy(F)
 for C in A:C[0]+=Y;C[1]+=X
 D+=A
print(D)
Magenta
quelle
1
Ich kann nicht glauben, dass mein einfaches exploderbasiertes System nach all meiner Arbeit bei der Einrichtung von Schaltern zur Herstellung von Blöcken für unbegrenztes Wachstum und einem System, das speziell für den Abriss von Wachstumsstrukturen entwickelt wurde, meine im Kampf besiegt hat: o
Value Ink
Ich weiß auch nicht, wie es funktioniert, weil ich den Controller aus irgendeinem Grund nicht ausführen kann.
Magenta
8

Ruby, InterruptingBlockMaker

Anstatt Segelflugzeuge wie den TrainingBot zu initialisieren, wird versucht, an einer beliebigen Stelle im Labyrinth eine 5x5-Blockschaltmaschine zu erstellen, wie auf Wikipedia erwähnt . Bei den verbleibenden Aktivierungen werden nur noch feindliche Punkte gefunden und versucht, die Umgebung mit Ihren Zellen zu pfeffern, um sie daran zu hindern, zu wachsen und möglicherweise ihre Muster durcheinander zu bringen. Ihre Zellen werden in der nächsten Generation sterben, aber vielleicht haben sie auch ein wenig Wachstum gestoppt, um Ihren Gegner zu verlangsamen!

v2: Leicht optimiert (?), um Zeitüberschreitungen zu minimieren.

v3: Optimierter Unterbrechungscode, um eine Teilmenge der aktiven Blöcke vorab abzutasten, bevor unsere eigenen Zellenstandorte abgelehnt werden, um Zeitüberschreitungen weiter zu vermeiden, was zu einer gewissen Wirksamkeit der Angriffe auf Unterbrechungszellen führt.

require 'json'

class Range
  def product range2
    self.to_a.product range2.to_a
  end
end

args = JSON.parse(ARGV[0])
bot_id = args["bot_id"]
width  = args["x_size"]
height = args["y_size"]
board  = args["board"]

generator = [[2,2], [2,3], [2,6], [3,2], [3,5], [4,2], [4,5], [4,6], [5,4], [6,2], [6,4], [6,5], [6,6]]

targets = []

iterations = 50
gen_location = nil
while !gen_location && iterations > 0
  y = rand height - 9
  x = rand width  - 9
  temp = (0...9).product(0...9).map{|_y, _x| [y + _y, x + _x]}
  if temp.all?{|_y,_x| !board["(#{y},#{x})"]}
    gen_location = temp
    targets += generator.map{|_y, _x| [y + _y, x + _x]}
  end

  iterations -= 1
end

enemies = board.keys.sample(100).reject {|k| board[k] == bot_id}
interrupts = []
enemies.each do |location|
  y, x = location.scan(/\d+/).map &:to_i
  interrupts |= ((y-1)..(y+1)).product((x-1)..(x+1)).reject{|y, x| gen_location.include?([y,x]) || board["(#{y},#{x})"]}
end

targets += interrupts.sample(30 - targets.size)

puts JSON.dump(targets)
Wert Tinte
quelle
@muddyfish danke, das hat es behoben! Jetzt besteht das einzige Problem darin, dass Windows-Befehlszeilenbefehle ein festes Limit von 8191 haben. Dies bedeutet, dass die Bots an einem bestimmten Punkt in der Simulation abstürzen, weil sie den abgeschnittenen JSON-String nicht analysieren können. Es ist ein Problem mit dem Betriebssystem, also muss ich in eine Linux-Cloud-Box schauen oder so, um meinen Bot zu testen ~
Value Ink
@muddyfish Ich habe bereits erwähnt, dass Windows aufgrund der Befehlszeilenbeschränkung Probleme hat. Der letzte Fehler war auf Cloud9, bei dem es sich angeblich um eine Linux-Box handelt. Wie ergeht es meinem Bot auf Ihrer Linux-Box (da Sie implizierten, dass Sie eine hatten)?
Wert Tinte
Es stellte sich heraus, dass ich es nicht begangen hatte, aber die Zahlen in bot_scorezeigen, wie viele Siege jeder Bot gegen andere Bots hat
Blue
OK, danke! Leider hat Cloud9 in der Tat keine GUI und Windows kann die Simulation immer noch nicht ausführen, ohne irgendwann das Befehlslimit zu überschreiten, aber zumindest habe ich einen kurzen Blick darauf geworfen, wie die Bots gegeneinander abschneiden. Außerdem sehe ich manchmal, wie mein Bot bis zum Ende gegen sich selbst kämpft, weil er sich gegenseitig angreift und genug Wachstum verhindert, um das Zeichenlimit zu überschreiten, obwohl es gelegentlich zu einer
Zeitüberschreitung kommt
4

Python 2, TrainingBot

Weil jeder eine davon braucht!

import random, copy
import sys, json

args = json.loads(sys.argv[1])
bot_id = args["bot_id"]
x_size = args["x_size"]
y_size = args["y_size"]
cur_tick = args["tick_id"]
board = args["board"]

glider = [[1,2],[2,1],[0,0],[0,1],[0,2]]

x_add = random.randrange(x_size)
y_add = random.randrange(y_size)
new_glider = copy.deepcopy(glider)
for coord in new_glider:
    coord[0]+=y_add
    coord[1]+=x_add
move = new_glider
print json.dumps(move)
Blau
quelle
4

Java, Troll Bot

Troll Bot hat darüber nachgedacht und bemerkt, dass er sich NICHT um den Feind kümmert. Tatsächlich spammt er diese Fabriken nur, um mehr seiner Leute zufällig auf der ganzen Karte zu produzieren. Nach einer Weile stellte er fest, dass zusätzliche Zellen am besten in Klumpen verwendet werden. Diese Viererblöcke halten zusammen und halten Segelflugzeuge auf ihren Spuren an! Er glaubt nicht, dass er nur kämpft. Er ist auch ein großer Befürworter der ausführlichen objektorientierten Programmierung. Der Troll geht auch davon aus, dass die Koordinaten im Format y, x vorliegen und bittet darum, getestet zu werden. Legen Sie ihn einfach in eine Datei mit dem Namen "TrollBot.java" und er wird eingestellt!

package trollbot;

/**
 *
 * @author Rohans
 */
public class TrollBot{
public static class coord{
    public int x;
    public int y;
    public coord(int inX,int inY){
        x = inX;
        y = inY;
    }
    @Override
    public String toString(){
        return"["+x+","+y+"]";
    }
}
    /**
     * Input the JSON as the first cla
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       String JSON="{\"bot_id\":1,\"y_size\":1000,\"x_size\":1000,\"board\":{}}";
    String[] JArray=args[0].split(",");
       int botId=Integer.parseInt(JSON.charAt(10)+"");
    int xSize=Integer.parseInt(JArray[2].substring(JArray[2].indexOf(":")+1));
    int ySize=Integer.parseInt(JArray[1].substring(JArray[1].indexOf(":")+1));
    int[][] board = new int[xSize][ySize];//0 indexed
//todo: parse the board to get an idea of state
    String soldiers="[";    
//for now just ignore whats on the board and put some troll cells on
    //Attempts to create 3 10 cells factories of cells, hoping it does not place it on top of allies
    //Then puts random 2/2 blocks
  boolean[][] blockspam=new boolean[10][8];
  blockspam[7][1]=true;
  blockspam[5][2]=true;
  blockspam[7][2]=true;
  blockspam[8][2]=true;
  blockspam[5][3]=true;
  blockspam[7][3]=true;
  blockspam[5][4]=true;
  blockspam[3][5]=true;
  blockspam[1][6]=true;
  blockspam[3][6]=true;
  for(int z=0;z<3;z++){
     int xOffSet=(int) (Math.random()*(xSize-11));
     int yOffSet=(int) (Math.random()*(ySize-9));
     //stay away from edges to avoid odd interactions
     for(int i=0;i<blockspam.length;i++){
         for(int j=0;j<blockspam[i].length;j++){
             if(blockspam[i][j])
             soldiers+=new coord(j+yOffSet,i+xOffSet).toString()+",";
         }
     }
  }
  soldiers=soldiers.substring(0,soldiers.length()-1);
  for(int i=0;i<8;i++){
            int y=(int ) (Math.random()*(ySize-1));
            int x = (int) (Math.random()*(xSize-1));
      soldiers+=new coord(y,x).toString()+",";
                          soldiers+=new coord(y+1,x).toString()+",";
                          soldiers+=new coord(y,x+1).toString()+",";
                          soldiers+=new coord(y+1,x).toString()+",";

  }
  soldiers+="\b]";

  System.out.println(soldiers);
  //GO GO GO! Lets rule the board
    }

}
Rohan Jhunjhunwala
quelle
3

Python 3, RandomBot

Dieser Bot hat Probleme, intelligente Entscheidungen zu treffen, aber er weiß zumindest, dass er nicht versuchen soll, Dinge über andere Dinge zu stellen. Es werden nach dem Zufallsprinzip Segelflugzeuge, Boote, C / 2-Orthogonale und 2x2-Blöcke mit verschiedenen Ausrichtungen erstellt, um sicherzustellen, dass sie sich nicht mit etwas anderem, Verbündeten oder Feinden überlappen, wenn sie platziert werden.

Dieser Bot wurde nicht getestet, da ich beim Versuch, die GUI auszuführen, alle möglichen Fehler erhalte. Außerdem habe ich den TrainingBot als Basis verwendet und nur bearbeitet, sodass Ähnlichkeiten im Code wahrscheinlich darauf zurückzuführen sind.

import random, copy
import sys, json
args = json.loads(sys.argv[1])
bot_id = args["bot_id"]
x_size = args["x_size"]
y_size = args["y_size"]
board = args["board"]
occupied = [tuple(key) for key,value in iter(board.items())]
cellsleft=30
move=[]
choices = [[[1,2],[2,1],[0,0],[0,1],[0,2]],
           [[0,0],[0,1],[1,1],[1,0]],
           [[0,1],[1,0],[0,2],[0,3],[1,3],[2,3],[3,3],[4,3],[5,2],[5,0]],
           [[0,0],[1,0],[0,1],[2,1],[2,2]]]
while cellsleft>0:
    x_add = random.randrange(x_size)
    y_add = random.randrange(y_size)
    new_glider = copy.deepcopy(random.choice(choices))
    randomdirection = random.choice([[1,1],[1,-1],[-1,1],[-1,-1]])
    maxy=max([y[0] for y in new_glider])
    maxx=max([x[1] for x in new_glider])
    for coord in new_glider:
        coord[0]=coord[0]*randomdirection[0]+y_add
        coord[1]=coord[1]*randomdirection[1]+x_add
        cellsleft-=1
    set([tuple(x) for x in new_glider]) 
    if not set([tuple(x) for x in new_glider]) & (set(occupied)|set([tuple(x) for x in move])) and cellsleft>0:
        if min(y[0] for y in new_glider)<0: new_glider = [[y[0]+maxy,y[1]] for y in new_glider]
        if min(y[1] for y in new_glider)<0: new_glider = [[y[0],y[1]+maxx] for y in new_glider]
        move += new_glider
    elif set([tuple(x) for x in new_glider]) & (set(occupied)|set([tuple(x) for x in move])):
        cellsleft+=len(new_glider)

print(json.dumps(move))
Steven H.
quelle
1
Die grafische print(sys.argv[1])Benutzeroberfläche schlägt höchstwahrscheinlich aufgrund Ihrer Online-Verbindung 3 fehl, wodurch die Ausgabe durcheinander gebracht wird (der Simulator erwartet nur die Koordinatenfolge, die Sie aufwachen möchten). Außerdem fehlt in der letzten Zeile Ihres Programms eine abschließende Klammer.
Wert Tinte
@ KevinLau-notKenny Die grafische Benutzeroberfläche des Trainings-Bots und des Ruby-Bots war fehlerhaft. Ich habe diese Zeile jedoch entfernt und wieder in die abschließende Zeile eingefügt (ich denke, die letztere war ein Fehler beim Kopieren und Einfügen).
Steven H.
Auf welchem ​​Betriebssystem arbeiten Sie und welche Fehler werden in der Befehlszeile angezeigt, wenn Sie es ausführen? Derzeit ist ein Fehler bekannt, bei dem Windows die Sim nicht ordnungsgemäß ausführen kann, da Argumente, die über die Befehlszeile übergeben werden, abgeschnitten werden, wenn sie die Zeichenbegrenzung für die Befehlszeile von ca. 8000 überschreiten.
Wert Ink
@ KevinLau-notKenny Ich verwende Windows 10 und habe ... nun, viele Fehler. Das erste, was BeautifulSoup nicht finden wollte, war html5lib, nicht den Ordner zu finden , der alle Bots enthielt (ich musste den Code für beide ändern), und seitdem hat das Ausführen eines der beiden Python-Bots zu einem Nicht-0-Rückkehrcode geführt 1.
Steven H.
Windows kann den Code immer noch nicht ausführen, wenn zu viele aktive Zellen auf dem Bildschirm sind ... Aber was Ihre anderen Fehler betrifft, könnte es sein, dass TrainingBot Python 2 möchte?
Wert Tinte
3

Python, GuyWithAGun

Er ist ein Typ, er hat eine Waffe; er ist verrückt. Er wirft einfach überall Flugwaffen ab, ohne Rücksicht darauf, was jemand anderes tut

import random, copy
import sys, json

args = json.loads(sys.argv[1])
bot_id = args["bot_id"]
x_size = args["x_size"]
y_size = args["y_size"]
tick_id = args["tick_id"]
board = args["board"]

start_squares = [[0,5],[2,5],[1,6],[2,6],
                 [35,3],[36,3],[35,4],[36,4]]
gun = [[11,5],[11,6],[11,7],
       [12,4],[12,8],
       [13,3],[13,9],
       [14,3],[14,9],
       [15,6],
       [16,4],[16,8],
       [17,5],[17,6],[17,7],
       [18,6],
       [21,3],[21,4],[21,5],
       [22,3],[22,4],[22,5],
       [23,2],[23,6],
       [25,1],[25,2],[25,6],[25,7]]

templates = [start_squares, gun]

def add_squares(pos, coords):
    new_squares = copy.deepcopy(coords)
    for coord in new_squares:
        coord[0]+=pos[0]
        coord[1]+=pos[1]
    return new_squares

def get_latest_pos():
    seed, template_id = divmod(tick_id, 2)
    random.seed(seed)
    cur_pos = [random.randrange(y_size),
               random.randrange(x_size)]
    cur_template = templates[template_id]
    try:
        return add_squares(cur_pos, cur_template)
    except IndexError:
        return []

move = get_latest_pos()

print json.dumps(move)
Blau
quelle
2

Python 3, SquareBot

Platziert überall - vielleicht

Quadrate sind statische Objekte im Leben - sie bewegen sich nicht. Wenn ich also genügend träge Gegenstände um den Ort platziere, werden die Segelflugzeuge und Explosionen, die andere verursachen, möglicherweise blockiert oder zumindest gedämpft.

-Angepasst von TrainingBot

from random import randint
import sys,json,copy
args=json.loads(sys.argv[1])
x=args["x_size"];y=args["y_size"]
square=[[0,0],[0,1],[1,0],[1,1]];D=[]
for g in range(7):
 X=randint(0,x);Y=randint(0,y)
 A=copy.deepcopy(square)
 for C in A:C[0]+=Y;C[1]+=X
 D+=A
print(D)

Obwohl ich Probleme habe, es zu testen

Magenta
quelle
Ich kann bestätigen, dass dieser Bot tatsächlich das tut, wofür er gedacht ist - und es hat mir dabei geholfen, einen Fehler im Controller zu finden und zu beheben
Blue