È la vita, Jim, ma non come la conosciamo


58

Probabilmente conosci Conway's Game of Life , il famoso automa cellulare inventato dal matematico John Conway. La vita è un insieme di regole che, insieme, ti consentono di simulare un pannello di celle bidimensionale. Le regole decidono quali celle sul tabellone vivono e quali muoiono. Con un po 'di immaginazione, potresti dire che la vita è un gioco a zero giocatori: un gioco con l'obiettivo di trovare schemi con comportamenti interessanti, come il famoso aliante.

aliante

Un gioco a giocatore zero ... Fino ad oggi. Devi scrivere un programma che riproduca il Gioco della vita - e lo giochi per vincere, in stile King of the Hill. Il tuo avversario (singolare) ovviamente cerca di fare lo stesso. Il vincitore è l'ultimo bot con qualsiasi cellula viva o il giocatore con il maggior numero di cellule vive dopo 10000 generazioni.

Regole del gioco

Le regole sono quasi le stesse del normale (B3 / S23) Vita:

  • Una cellula viva con meno di due vicini amichevoli muore di fame.
  • Sopravvive una cellula viva con due o tre vicini amici.
  • Una cellula viva con più di tre vicini amichevoli muore per sovrappopolazione.
  • Una cellula morta con esattamente tre vicini dello stesso giocatore prende vita per combattere per quel giocatore purché non ci siano vicini nemici .

... ma dopo ogni generazione, sia tu che il tuo avversario avete l'opportunità di intervenire. Puoi svegliarti fino a un massimo di 30 celle per combattere per te. (Chi inizia per primo è deciso dal server.)

La scheda è un quadrato di celle (x, y). Tutti i quadrati sono inizialmente morti. I bordi non si avvolgono (questo non è un mondo a forma di toro) e sono permanentemente morti.

Questa è una gara nello spirito di Battlebots e Core Wars . C'è un server centrale che eseguirà i robot e può essere trovato qui

Protocollo

Il server arena parla un semplice protocollo JSON comunicato tramite argv

Dove Valori è una stringa codificata JSON

  • y_size: il massimo y corde di tessere prima che scompaiano
  • x_size: il massimo x corde di tessere prima che scompaiano
  • tick_id: il numero attuale di tick
  • board: un dizionario con chiavi nel formato '(y, x)' e valori nel modulo bot_id(int)
  • bot_id: le tessere nel tabellone con questo ID sono tue

Esempio:

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

Dire al server la tua scelta:

  • Invia al server un elenco di tessere per passare al tuo colore.
  • Solo quelli vuoti verranno cambiati
  • Formato dell'elenco dei coordini nidificati
    • [[0,0], [0,1], [100,22]...]

NOTA: il bot non deve affatto aggiornare i riquadri: il server esegue l'aggiornamento stesso

Regole di concorrenza

  • Se l'implementazione non riesce a seguire il protocollo, il turno che lo farà verrà perso; Il server non assumerà alcun cambiamento di stato
  • Non è consentito sfruttare intenzionalmente un errore nel server arena.
  • Chiedi alla tua IA di decidere le mosse in un tempo ragionevole. Invia la tua prossima mossa il più velocemente ragionevolmente possibile.
  • Infine, per favore sii gentile con il server. È lì per il tuo divertimento.
  • Non seguire queste regole può portare alla squalifica.
  • In caso di pareggio, entrambi i giocatori hanno 1 vittoria aggiunta al loro totale

Esegui il controller da solo

La fonte per il controller può essere trovata qui . Esistono 2 modi per eseguire il controller:

  • Modalità competizione (terminale)
    • Installa con python3 get_answers.py
    • Esegui una competizione a tutto tondo con ogni bot confrontandolo.
  • Modalità test (GUI)
    • Correre python3 nice_gui.py
    • Clic Pull Answers
    • Se vuoi aggiungere la tua risposta per provarla prima di pubblicare, fai clic File -> Add manual answere trova il file e scegli la lingua in cui è scritto.
    • Se la tua lingua non è presente eseguimi il ping e proverò a installarlo sul server su cui eseguirò (anche le istruzioni di installazione e esecuzione andrebbero bene!)
    • Scegli 2 robot da mettere l'uno contro l'altro
    • Clic Run
    • Guarda il gioco ...
  • Installazione
    • Richiede python3
    • get_answers richiede bs4 e html5lib
    • controller richiede un modo per eseguire i file .sh (MinGW su Windows)

Immagine di esempio dell'app

punteggio

Il bot con il maggior numero di vittorie a partire dal 12/07/2016(12 luglio) 14/07/2016 (14 luglio, non è riuscito a capire come far funzionare un bot) vince.


In questa chat room è possibile richiedere assistenza con controller / gui


Questa domanda è in fase di sviluppo dal 2014 ed è stata la domanda più votata nella sandbox. Un ringraziamento speciale va a Wander Nauta (autore originale e concept), PPCG Chat (commenti e aiuto) e a chiunque abbia commentato nel post sandbox (altri commenti).


25
Eh, ho pensato che questo non sarebbe mai uscito dalla sandbox. Grande!
Luis Mendo,

Errore di battitura: 12/06/2016 (12 luglio)
Luis Mendo,

4
+1. Ti meriti il ​​premio DAE per aver tirato fuori questa grande domanda dalla sandbox!
agtoever,

1
@ KevinLau-notKenny oh, ok. Puoi eseguire un comando in un file?
Rɪᴋᴇʀ

1
@Magenta Quando li avrò (me ne ero completamente dimenticato, anche se era in una scheda costantemente aperta), lo sto eseguendo ora
Blue

Risposte:


4

Python 3, Exploder

Mette piccoli esplodenti intorno al luogo, indipendentemente dal fatto che ci sia già un blocco lì.

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)

1
Non riesco a credere che, dopo tutto il mio lavoro, ho impostato interruttori per la produzione di blocchi per la crescita indefinita e un sistema appositamente progettato per demolire le strutture di crescita, un semplice sistema basato su un exploit ha superato il mio in combattimento: o
Value Ink

Non so neanche come, perché non riesco a far funzionare il controller per nessun motivo.
Magenta

8

Ruby, InterruptingBlockMaker

Invece di inizializzare gli alianti come il TrainingBot, tenta di creare una macchina switch di blocco 5x5 come menzionato su Wikipedia in un punto casuale nel labirinto. Quindi, con le rimanenti attivazioni, trova solo punti nemici e cerca di riempire l'area vicina con le tue cellule nel tentativo di interromperle dalla crescita e forse rovinare i loro schemi. Le tue cellule moriranno nella prossima generazione, ma forse hanno anche bloccato la crescita per rallentare il tuo avversario!

v2: leggermente ottimizzato (?) per cercare di ridurre al minimo i timeout.

v3: codice di interruzione ottimizzato per pre-campionare un sottoinsieme di blocchi attivi prima di rifiutare le posizioni delle nostre celle, per prevenire ulteriori timeout a scapito di una certa efficacia negli attacchi di celle di interruzione.

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)

@muddyfish grazie, che risolto! Ora l'unico problema è che i comandi della riga di comando di Windows hanno un limite hardcoded di 8191, il che significa che a un certo punto della simulazione i robot si bloccheranno per non essere in grado di analizzare la stringa JSON troncata. Si tratta di un problema con il sistema operativo, quindi immagino di dover esaminare un cloud box Linux o qualcosa del genere per testare il mio bot ~
Value Ink

@muddyfish Ho già detto che Windows ha problemi a causa del limite della riga di comando, che l'ultimo errore era su Cloud9 che è apparentemente una scatola di Linux. Come funziona il mio bot sul tuo box Linux (dal momento che hai implicato di averne uno)?
Value Ink

Si scopre che non l'ho commesso, ma i numeri in bot_scoremostra mostrano quante vittorie ha ogni bot contro altri bot
Blue

Va bene grazie! Sfortunatamente, Cloud9 in realtà non ha una GUI e Windows non può ancora eseguire la simulazione senza infrangere il limite di comando alla fine, ma almeno ho avuto una breve occhiata a come si comportano i robot l'uno contro l'altro. Inoltre, vedo il mio bot combattere contro se stesso fino alla fine alcune volte perché continuano ad attaccarsi l'un l'altro e impediscono una crescita sufficiente per infrangere il limite del personaggio, anche se occasionalmente scade ...
Value Ink

4

Python 2, TrainingBot

Perché tutti hanno bisogno di uno di questi!

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)

4

Java, Troll Bot

Troll Bot ci ha pensato e si rende conto che NON gli importa del nemico. In effetti ha appena fatto spam in queste fabbriche per produrre più dei suoi ragazzi in modo casuale su tutta la mappa. Dopo un po 'si rese conto che tutte le celle aggiuntive venivano utilizzate al meglio nei ciuffi. Questi blocchi di quattro celle si uniranno e fermeranno gli alianti sulle loro tracce! Non pensa di combattere. Inoltre è un grande sostenitore della programmazione dettagliata orientata agli oggetti. Il troll presume anche che i coord siano nel formato y, x e chiede di essere testato. Inseriscilo in un file chiamato "TrollBot.java" e verrà impostato!

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
    }

}

3

Python 3, RandomBot

Questo bot ha difficoltà a prendere decisioni intelligenti, ma almeno sa di non provare a mettere le cose in cima ad altre cose. Creerà casualmente alianti, barche, C / 2 Orthagonal s e blocchi 2x2 con vari orientamenti, assicurando che quando vengono posizionati non si sovrappongono con qualcos'altro, alleato o nemico.

Questo bot non è stato testato, visto che ricevo tutti i tipi di errori quando provo a eseguire la GUI. Inoltre, ho usato TrainingBot come base e ho appena modificato, quindi ogni somiglianza nel codice è probabilmente dovuta a questo.

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

1
Molto probabilmente la GUI sta fallendo a causa della tua print(sys.argv[1])linea 3, che incasina l'output (il simulatore si aspetta solo la stringa di coordinate che vuoi svegliare). Inoltre, nell'ultima riga del programma manca una parentesi di chiusura.
Value Ink

@ KevinLau-notKenny La GUI non funzionava sul bot di allenamento e anche sul bot Ruby. Ho rimosso quella riga, tuttavia, e aggiunto di nuovo nella parentesi di chiusura (penso che quest'ultima fosse un errore di copia e incolla).
Steven H.

Su quale sistema operativo sei e quali errori compaiono nella riga di comando quando lo esegui? Attualmente è un bug noto che Windows non può eseguire correttamente la sim a causa del troncamento degli argomenti passati dalla riga di comando quando superano il limite di caratteri della riga di comando di circa 8000.
Inchiostro valore

@ KevinLau-notKenny Sto usando Windows 10 e ho ottenuto ... beh, molti errori. La prima cosa è che BeautifulSoup non voleva trovare html5lib, quindi non trovava la cartella contenente tutti i bot (dovevo cambiare il codice per entrambi), e da allora l'esecuzione di entrambi i bot Python ha prodotto un codice di ritorno diverso da 0 1.
Steven H.

Windows non può ancora eseguire il codice se ci sono troppe celle attive sullo schermo ... Ma per quanto riguarda gli altri tuoi errori, potrebbe essere perché TrainingBot vuole Python 2?
Value Ink

3

Python, GuyWithAGun

È un ragazzo, ha una pistola; lui è matto. Scarica semplicemente pistole da aliante ovunque, indipendentemente da ciò che fanno gli altri

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)

2

Python 3, SquareBot

Mette quadrati ovunque- forse

I quadrati sono oggetti statici in Life: non si muovono. Quindi, se posiziono abbastanza oggetti inerti attorno al luogo, gli alianti e le esplosioni che altri creano potrebbero essere bloccati o almeno smorzati.

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

Anche se ho problemi a testarlo



Posso confermare che questo bot in effetti fa quello che dovrebbe - e mi ha aiutato a trovare e correggere un bug nel controller
Blue
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.