KOTH: Tantangan TNT Run


25

Ini terinspirasi oleh mini-game Minecraft. Aturannya cukup sederhana: Anda berlari dan melompat-lompat, dan setiap blok yang Anda injak menghilang begitu Anda menginjaknya. Tujuannya adalah menjadi yang terakhir tersisa.

Bot Anda harus merupakan program yang lengkap. Ini harus menerima input sebagai argumen baris perintah. Masukan akan menjadi peta "dunia"; berikut ini sebuah contoh:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxx xxxxxxxxxxxxxxxxxxxxxxxxxxx
xxx xxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxx x xxxxxxxxxxxxx@xxxxxxxxxxx
xxxxxx1xxxxxxxxxxxxx xxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxx
xxxxxxxxxx           xxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx
xxxxxxxxxxxxxxxxx x x xxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxx
xxxxxxxxxxxxxx xxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxx xxx xx3xxxxxxxxxx
xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx  x
xxxxxxxxxxxxxxxxxxxxxxxxxxx   xx
xxxxxxxxxxxxxxxxxxxxxxxxx      2
xxxxxxxxxxxxxxxxxxxxxxx         

Legenda adalah sebagai berikut:

x: solid block

 : empty air

@: your bot

1,2,3,4,5,6,7,8,9,0: other bots

Bot Anda harus menampilkan gerakan Anda sebagai sepasang bilangan bulat. Contoh: -1, 2akan memindahkan 1 blok ke kiri dan 2 blok ke bawah (koordinat asal ada di sudut kiri atas).

Anda dapat bergerak hingga empat blok, jarak manhattan, dari lokasi Anda saat ini. Jika Anda mencoba untuk bergerak lebih jauh dari itu, langkah tersebut tidak valid. Setiap langkah yang akan memindahkan Anda melewati tepi akan menempatkan Anda di tepi sebagai gantinya. Gerakan yang tidak valid akan diabaikan.

Setelah Anda mendarat di blok itu dihapus; jika Anda tetap di blok yang sama pada giliran berikutnya Anda akan jatuh. Dua bot dapat mendarat di blok yang sama pada belokan yang sama dan keduanya selamat; jika ini terjadi, kedua bot hanya akan melihat diri mereka sendiri dan bukan bot lainnya.

Jika Anda perlu menyimpan file untuk kegigihan, silakan lakukan di folder dengan nama bot Anda. Anda tidak boleh membaca data persisten bot lain jika ada.

Pengontrol pertandingan tersedia di https://paste.ee/p/Xf65d .

Silakan gunakan bahasa yang dapat dijalankan pada instalasi Linux atau OSX standar.

Hasil saat ini (100 putaran):

JumpBot                   31
LookBot                   27
ShyBot                    26
Slow Bot                  15
KnightBot                 2
Moat Builder              0
UpBot                     0
Random Bot                0

Mirip, meskipun perbedaan utama di sini adalah Anda dapat "melompat" beberapa blok - sehingga Anda tidak bisa begitu saja memblokir seseorang jika mereka melihat apa yang Anda lakukan.
Skyler

Anda tidak dapat menutup sebagai korban penipuan di kotak pasir dan saya pikir itu bukan salah
Biru

1
Apakah gerakannya simultan atau berurutan? Apakah input benar-benar merupakan string yang mengandung baris sebagai argumen baris perintah?
feersum

1
Saya sarankan memanggil bot sekali tanpa dunia untuk inisialisasi (Anda tidak tahu apakah negara Anda disimpan sebagai file dari putaran terakhir atau dari putaran ini)
bauen1

Gerakan @feersum simultan; input memang argumen baris perintah yang mengandung baris baru. Jika Anda membutuhkannya sebagai stdin, beri tahu saya dan saya mungkin bisa memodifikasi contoller untuk memungkinkannya.
Skyler

Jawaban:


9

Bot Lambat (Python)

Dia bergerak dalam pola garis dan memeriksa gerakannya sebelum membuatnya (juga bunuh diri ketika dia yang terakhir hidup untuk mencegah runtime panjang) Dia memenangkan 195/200 Battels di turnamen pengujian saya.

import sys
import re


class vec2(object):
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __add__(self, other):
        return vec2(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return vec2(self.x - other.x, self.y - other.y)

    def __iadd__(self, other):
        return self + other

    def __isub__(self, other):
        return self - other

    def __neg__(self):
        return vec2(-self.x, -self.y)


def xy_to_i(vec=vec2(0, 0)):
    vec -= vec2(1, 1)
    vec.y += (vec.x - vec.x % 32) / 32
    return vec.x + vec.y * 33


def i_to_xy(i=0):
    vec = vec2(0, 0)
    vec.x = i % 33
    vec.y = (i - vec.x) / 32 + 1
    vec.x += 1
    return vec


class World(object):
    def __init__(self, map=''):
        self.map = map

    def getPlayerPosition(self):
        return i_to_xy(re.search('@', self.map).start())

    def getNumOtherBots(self):
        return len(re.findall('([0123456789])', ' ' + self.map + ' '))

    def get_tile(self, vec=vec2(0, 0)):
        i = xy_to_i(vec)
        return self.map[i:i + 1]


world = World(sys.argv[1])
pos = world.getPlayerPosition()


def check_moveV(vecd=vec2(0, 0)):
    try:
        vecn = pos + vecd

        if vecn.x > 32 or vecn.x < 1 or vecn.y > 32 or vecn.y < 1 \
            or abs(vecd.x) + abs(vecd.y) > 4:
            return False

        # Note: this will also avoid positions other bots are on (will disappear in the next step).

        return world.get_tile(vecn) == 'x'
    except:
        raise
        return False


def check_move(x=0, y=0):
    return check_moveV(vec2(x, y))


def run():
    if world.getNumOtherBots() == 0:
        return '0 0'  # Suicide if we are the only one left.

    # this creates the "line" pattern

    if check_move(0, -1):
        return '0 -1'

    if check_move(0, 1):
        return '0 1'

    if check_move(1, 0):
        return '1 0'

    if check_move(1, -1):
        return '1 -1'

    # If we get here, we are desperate and need to find a safe place to jump.

    for dx in range(-2, 2):
        for dy in range(-2, 2):
            if check_move(dx, dy):
                return '%i %i' % (dx, dy)

    # If we can't find a place to jump in close range, try long range.

    for dx in range(-4, 4):
        for dy in range(-4, 4):
            if check_move(dx, dy):
                return '%i %i' % (dx, dy)

    # If we get here, we are dead no matter what; accept our fate.

    return '0 0'


print(run())

Saya bukan ahli dalam python dan mungkin ada 100 cara melakukannya lebih pendek / lebih baik


1
Hanya satu hal, jika Anda berada di ruang yang sama dengan bot lain dan Anda adalah dua yang terakhir, milik Anda akan berpikir itu adalah yang terakhir dan bunuh diri.
Timtech

ketika saya menerapkan kegigihan, dia akan menunggu 5 putaran sampai bunuh diri
bauen1

Bagus, itulah yang akan saya sarankan. Omong-omong, jawaban yang bagus.
Timtech

6

JumpBot (C)

Cobalah untuk melompat ke bidang dengan gerakan paling mungkin di babak selanjutnya.

#include <stdio.h>
#include <stdlib.h>

typedef struct map {
     char *raw_map;
     int size;
     int lines;
     char *pos;
} *MAP;

typedef struct cdata {
     int result;
     MAP m;
     int x;
     int y;
} *CDATA;

typedef struct mdata {
     int x;
     int y;
     int moves;
     int bx;
     int by;
     MAP m;
} *MDATA;

int numberOfMoves(MAP, int, int);
char getAt(MAP, int, int);

int abs(int x)
{
    return x < 0 ? x*-1 : x;
}

void count(void *data, int x, int y)
{
    CDATA d = (CDATA)data;
    char c = getAt(d->m, d->x + x, d->y + y);
    if(c != 'x') return;
    d->result++;
}

void choose(void *data, int x, int y)
{
    MDATA m = (MDATA)data;
    char c = getAt(m->m, m->x + x, m->y + y);
    if(c != 'x') return;
    int moves = numberOfMoves(m->m, m->x+x, m->y+y);
    if(moves > m->moves || (!m->bx && !m->by)) {
        m->moves = moves;
        m->bx = x;
        m->by = y;
    }
}

MAP parse_input(char *input)
{
    MAP m = malloc(sizeof *m);
    if(!m) {
        fprintf(stderr, "failed to alloc map\n");
        return NULL;
    }

    m->size=0;
    m->lines=1;
    m->pos=0;

    char *temp;
    for(temp = input;*temp;temp++) {
        switch(*temp) {
            case '\n': m->lines++; break;
            default: break;
        }
    }
    m->size = (temp + 1) - (input + m->lines);
    m->raw_map = malloc(m->size);
    if(!m->raw_map) {
        fprintf(stderr, "failed to alloc raw_map\n");
        return NULL;
    }

    int index = 0;
    for(temp = input; *temp; temp++) {
        if(*temp == '@') m->pos = m->raw_map + index;
        if(*temp != '\n') m->raw_map[index++] = *temp;
    }

    return m;
}

char getAt(MAP m, int x, int y)
{
    return m->raw_map[x + y*(m->size / m->lines)];
}

void posToXY(MAP m, int *x, int *y)
{
    int index = m->pos - m->raw_map;
    int length = m->size / m->lines;
    *x = index % length;
    *y = index / length;
}

typedef void (*DOFUNC)(void *, int, int);
void processMoves(MAP m, int x, int y, DOFUNC proc, void *data)
{
    int length = m->size / m->lines;    
    int left = x>=4 ? 4 : x;
    int right = x + 4 <= length ? 4 : length - (x + 1);
    int up = y >= 4 ? 4 : y;
    int down = y + 4 <= m->lines ? 4 : m->lines - (y + 1);

    for(int i=-left; i<=right; i++) {
        for(int j=-up; j<=down; j++) {
            if((abs(i) + abs(j) <= 4) && (i || j)) (*proc)(data, i, j);
        }
    }
}

int numberOfMoves(MAP m, int x, int y)
{
    struct cdata d;
    d.result = 0;
    d.x = x;
    d.y = y;
    d.m = m;
    processMoves(m, x, y, &count, &d);
    return d.result;
}

void getMove(MAP m, int *x, int *y)
{
    struct mdata d;
    posToXY(m, &d.x, &d.y);
    d.moves = 0;
    d.bx = 0;
    d.by = 0;
    d.m = m;
    processMoves(m, d.x, d.y, &choose, &d);
    *x = d.bx;
    *y = d.by;
}

int main(int argc, char *argv[])
{
    if(argc != 2) {
        fprintf(stderr, "bad number of arguments %d\n", argc);
        return -1;
    }

    MAP m = parse_input(argv[1]);
    int x=0, y=0;
    getMove(m, &x, &y);
    printf("%d %d\n", x, y);
    return 0;
}

5

LookBot (C)

Bot sederhana yang memiliki kinerja yang mirip dengan Bot Lambat, kecuali bot yang satu ini memungkinkan gerakan acak. Rencanakan untuk meningkatkan ini ke PredictBot.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <sys/time.h>

#define WORLDSZ (32)
#define WORLDSZ_2 (WORLDSZ*WORLDSZ)

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}

struct Position{
    int x,y;
};
typedef struct Position Position;

struct World{
    Position me;
    double enemymap[WORLDSZ][WORLDSZ]; //chance of enemy present
    bool open[WORLDSZ][WORLDSZ];
};
typedef struct World World;

void world_read(World *world,const char *arg){
    int x,y,i=0;
    for(y=0;y<WORLDSZ;y++,i++){
        for(x=0;x<WORLDSZ;x++,i++){
            if(arg[i]=='@'){world->me.x=x; world->me.y=y;}
            world->enemymap[y][x]=arg[i]>='0'&&arg[i]<='9';
            world->open[y][x]=arg[i]=='x';
        }
    }
}

//returns relative position
Position world_calcmove(World *world){
    const int mex=world->me.x,mey=world->me.y;
    int dx,dy;
    Position poss[40];
    int nposs=0;
    for(dy=max(-mey,-4);dy<=min(WORLDSZ-1-mey,4);dy++){
        const int absdy=abs(dy);
        for(dx=max(-mex,absdy-4);dx<=min(WORLDSZ-1-mex,4-absdy);dx++){
            if(!world->open[mey+dy][mex+dx])continue;
            poss[nposs].x=dx;
            poss[nposs++].y=dy;
        }
    }
    if(nposs==0){
        poss[0].x=poss[0].y=0;
        return poss[0];
    }
    return poss[rand()%nposs];
}

int main(int argc,char **argv){
    if(argc!=2){
        fprintf(stderr,"Call with world!\n");
        return 1;
    }
    struct timeval tv;
    gettimeofday(&tv,NULL);
    srand(tv.tv_sec*1000000ULL+tv.tv_usec);

    World world;
    world_read(&world,argv[1]);
    Position move=world_calcmove(&world);
    printf("%d %d\n",move.x,move.y);
}

5

Moat Builder (Python)

Jika saya menggali parit di sekitar saya, tidak ada orang di luar yang bisa mengacaukan saya.

... juga dikenal sebagai "Cat diri Anda menjadi simulator sudut 2016".

import numpy
import sys
import math
import os

if not os.path.exists('./moatbuilder'):
    os.mkdir('./moatbuilder')

raw_field = sys.argv[1]
field = numpy.array([numpy.array(list(i)) for i in raw_field.splitlines()])
field_size = len(field)
x, y = raw_field.replace('\n','').index('@')%field_size, int(raw_field.replace('\n','').index('@')/field_size)
# If there are no holes, it's the first round - reset persistence
if raw_field.count(' ')==0:
    open('./moatbuilder/persistent','w').write('')

def bigmove(target):
    if x < target[0]:
        return min(4, target[0] - x), 0
    elif x > target[0]:
        return max(-4, target[0] - x), 0
    elif y < target[1]:
        return 0, min(4, target[1] - y)
    else:
        return 0, max(-4, target[1] - y)

def smallmove(target):
        if x < target[0]:
        try:
            return min(max(1, list(field[y][x:x+4]).index('x')), target[0] - x), 0
        except:
            return 0, 0
        elif x > target[0]:
        try:
            return max(min(-1, 0-list(reversed(field[y][x-4:x])).index('x')), target[0] - x), 0
        except:
            return 0, 0
        elif y < target[1]:  
        try:
                    return 0, min(max(1, list(field[:,x][y:y+4]).index('x')), target[1] - y)
        except:
            return 0, 0
        else:
        try:
            return 0, max(min(-1, 0-list(reversed(field[:,x][y-4:y])).index('x')), target[1] - y)
        except:
            return 0, 0


try:
    mode = int(open('./moatbuilder/persistent').read())
except:
    mode = 1

# Modes:
# 1 - go to the center
# 2 - go to an outside edge
# 3 - dig moat
if mode==1:
    dx, dy = bigmove((int(field_size/2), int(field_size/2)))
    if dx==0 and dy==0:
        open('./moatbuilder/persistent', 'w').write('2')
        mode = 2
if mode==2:
    dx, dy = bigmove((int(field_size-1), int(field_size/2)))
    if dx==0 and dy==0:
        dy = 1
        open('./moatbuilder/persistent', 'w').write('3')
        mode = 3
elif mode==3:
    direction = max(field_size-x, field_size-y)%2
    if direction == 1:
        if x > y:
            dx, dy = smallmove((y, y))
        else:
            dx, dy = smallmove((x, field_size - 1))
        if dx==0 and dy==0:
            dx = 1
    else:
        if y > x:
            dx, dy = smallmove((x, x))
        else:
            dx, dy = smallmove((field_size - 1, y))
        if dx==0 and dy==0:
            dy = 1

print "%i %i" % (dx, dy)

Ini sebenarnya bekerja dengan sangat baik, tetapi itu akan kalah melawan bot yang hidup untuk waktu yang lama (itulah sebabnya saya memilih pola garis btw)
bauen1

Anda mungkin ingin memperbaiki indentasi Anda di smallmove () ... Python saya tidak makan ini :)
tommeding

5

Monte (Python)

Maaf, permainan kata itu harus dilakukan.

Bagaimanapun, bot ini bekerja dengan melakukan Pencarian Pohon Monte Carlo di semua set pemindahan yang mungkin. Pikirkan JumpBot, hanya lebih mendalam.

Untuk menjalankannya, diperlukan argumen baris perintah tambahan (dapat ditentukan dalam controller). Ia mengontrol berapa banyak waktu yang harus dicari bot (dalam ms); Saya menggunakan 750-1500 dalam pengujian.

Kode:

import sys
import math
import copy
#from profilestats import profile
pmap = sys.argv[2].split("\n")
pmap = [list(r) for r in pmap]

#find a player
#@profile
def find(tmap,bot):
   r,c=-1,-1
   for row in range(len(tmap)):
      for col in range(len(tmap[row])):
         if tmap[row][col]==bot:
            r,c=row,col
   return r,c

mer,mec=find(pmap,'@')
bots=[(mer,mec)]

#find all the other players
for b in range(10):
   r,c=find(pmap,str(b))
   if r != -1:
      bots.append((r,c))

#getter function, treats oob as spaces
def get(tmap,r,c):
   if r<0 or r>=len(tmap) or c<0 or c>=len(tmap[r]):
      return ' '
   return tmap[r][c]

#returns manhattan distance between 2 positions  
def dist(r1,c1,r2,c2):
   return abs(r1-r2)+abs(c1-c2)

#gets all possible moves from a map
#@profile 
def moves(tmap,ther=-1,thec=-1):
   if ther==-1: ther,thec = find(tmap,'@')
   pos=[]
   for r in range(-4,5):
      for c in range(-4,5):
         if abs(r)+abs(c)<=4 and get(tmap,ther+r,thec+c)=='x':
            pos.append((r,c))
   return pos


ttlmoves = 40
#monte-carlo tree node
class MCNode:
   def __init__(self):
      self.wins=0
      self.simu=0
      self.chld=[]
      self.cmap=[[]]
      self.prnt=None
      self.r=-1
      self.c=-1
   def add(self, cnode):
      self.chld.append(cnode)
      cnode.prnt = self
   #used to balance exploitation and exploration
   #@profile
   def param(self,cin):
      return self.chld[cin].wins/self.chld[cin].simu\
             + 1.414 * math.sqrt( math.log(self.simu) / \
             self.chld[cin].simu )
   #finds the child with the highest param
   #@profile
   def best(self):
      vals = [self.param(x) for x in range(len(self.chld))]
      binx = 0
      bval = vals[0]
      for x in range(len(vals)):
         if vals[x]>bval:
            binx=x
            bval=vals[x]
      return self.chld[binx]


#update all the parents 
#@profile   
def backprog(leaf):
   par = leaf.prnt
   if not (par is None):
      par.wins+=leaf.wins
      par.simu+=leaf.simu
      backprog(par)

#expand all the moves from a position
#@profile
def expand(rootn):
   ther,thec = rootn.r,rootn.c
   for r,c in moves(rootn.cmap,rootn.r,rootn.c):
      nmap = copy.deepcopy(rootn.cmap)
      nmap[ther+r][thec+c] = '@'
      nmap[ther][thec]=' '
      nnode = MCNode()
      nm = moves(nmap,ther+r,ther+c)
      nnode.wins = len(nm)
      nnode.simu = ttlmoves
      nnode.r=ther+r
      nnode.c=thec+c
      nnode.cmap = nmap
      rootn.add(nnode)
      backprog(nnode)

root = MCNode()
m = moves(pmap,mer,mec)
root.wins = len(m)
root.simu = ttlmoves
root.cmap=copy.deepcopy(pmap)
root.r=mer
root.c=mec
expand(root)

#simulate a bunch of outcomes
import time
curt  = lambda: int(round(time.time() * 1000))
strt = curt()
ttme = int(sys.argv[1])
while curt()-strt < ttme:
   tnode=root
   while tnode.chld:
      tnode=tnode.best()
   expand(tnode)

#choose the most explored one
bnode = max(root.chld,key=lambda n:n.simu)

#output
print("{} {}".format((bnode.c-mec),(bnode.r-mer)))

Percobaan

25 putaran:

MonteBot            14
JumpBot             6
ShyBot              5
LookBot             1
KnightBot           0
SlowBot             0

100 putaran:

JumpBot             38
MonteBot            36
ShyBot              15
LookBot             14
SlowBot             2
KnightBot           0

200 putaran:

MonteBot            87
JumpBot             64
LookBot             33
ShyBot              21
SlowBot             5
KnightBot           0

Semua simulasi di atas menggunakan waktu pencarian 750. Bot ini mungkin akan lebih baik dengan waktu pencarian yang lebih lama (saya tidak tahu apa maks yang diizinkan).

Perbaikan

Bot ini masih membutuhkan peningkatan di:

  1. Kinerja: perlu seluruh waktu untuk mencari.
  2. Prediksi: itu tidak akan menjelaskan pergerakan bot lain.
  3. Saldo: Saya tidak yakin apakah rumus UCT yang saya gunakan untuk menghitung simpul mana yang harus saya jelajahi optimal.

4

ShyBot (Python)

Bot ini benar-benar tidak suka bot lain dan akan mencoba untuk menjauhkan diri jika memungkinkan. ShyBot juga sangat berhati-hati tentang di mana ia melangkah; bahkan tidak akan menginjak bot lain. Namun, ShyBot masih sering kehilangan yang membuat tidak aman.

import sys
map = sys.argv[1]
map = map.split("\n")
map = [list(r) for r in map]

def find(map,bot):
   r,c=-1,-1
   for row in range(len(map)):
      for col in range(len(map[row])):
         if map[row][col]==bot:
            r,c=row,col
   return r,c


mer,mec=find(map,'@')
bots=[(mer,mec)]

for b in range(10):
   r,c=find(map,str(b))
   if r != -1:
      bots.append((r,c))

avg=[0,0]

for b in bots:
   avg[0]+=b[0]
   avg[1]+=b[1]

avg[0] = avg[0]/len(bots)
avg[1] = avg[1]/len(bots)

def get(map,r,c):
   if r<0 or r>=len(map) or c<0 or c>=len(map[r]):
      return ' '
   return map[r][c]

def dist(r1,c1,r2,c2):
   return abs(r1-r2)+abs(c1-c2)

pos=[]
for r in range(-4,5):
   for c in range(-4,5):
      if abs(r)+abs(c)<=4 and get(map,mer+r,mec+c)=='x':
         pos.append((r,c))

if len(pos)==0:
   bestr,bestc=0,0
else:
   bestr,bestc=pos[0]

for r,c in pos:
   if dist(mer+r,mec+c,avg[0],avg[1])>dist(mer+bestr,mec+bestc,avg[0],avg[1]):
      bestr,bestc=r,c

print(str(bestc)+" "+str(bestr))

4

KnightBot (Jawa)

Ini bekerja seperti catur, dan dinamai seperti Twitch ...

...

.........

............................Maaf...

public class KnightBot{
   private static String[] map;
   private static int myx;
   private static int myy;
   public static void main(String[] args){
      map=args[0].split("\n");
      for(int y=0;y<map.length;y++){
         if(map[y].indexOf("@")!=-1){
            myy = y;
            myx = map[y].indexOf("@");
            break;
         }
      }
      System.out.println(move((int)(Math.random()*4),4));
   }
   public static String move(int dir,int tries){
      if(tries==0)return "0 0";
      int x=dir<2?1:-1;
      int y=dir%2==0?2:-2;
      if((myx+x<0||myx+x>=map[0].length()||myy+y<0||myy+y>=map.length)||map[y+myy].charAt(myx+x)!='x'){
         x=dir<2?2:-2;
         y=dir%2==0?1:-1;
      }
      if((myx+x<0||myx+x>=map[0].length()||myy+y<0||myy+y>=map.length)||map[y+myy].charAt(myx+x)!='x')
         return move(++dir>3?0:dir,tries-1);
      return x+" "+y;
   }
}

SwirlyBot (Java)

Ini jelas bukan solusi optimal, tapi saya harap akan berguna untuk pengujian tingkat menengah.

public class SwirlyBot{
   private static String[] map;
   private static int myx;
   private static int myy;
   public static void main(String[] args){
      map=args[0].split("\n");
      for(int y=0;y<map.length;y++){
         if(map[y].indexOf("@")!=-1){
            myy = y;
            myx = map[y].indexOf("@");
            break;
         }
      }
      System.out.println(move(0));
   }
   public static String move(int dir){
      switch(dir){
         case 0:
            if(!safe(0,1)){
               if(safe(1,1)){
                  return "1 1";//Down-Right
               }else{
                  if(safe(1,0)){
                     return "1 0";//Right
                  }
               }
            }
            break;
         case 1:
            if(!safe(1,0)){
               if(safe(1,-1)){
                  return "1 -1";//Up-Right
               }else{
                  if(safe(0,-1)){
                     return "0 -1";//Up
                  }
               }
            }
            break;
         case 2:
            if(!safe(0,-1)){
               if(safe(-1,-1)){
                  return "-1 -1";//Up-Left
               }else{
                  if(safe(-1,0)){
                     return "-1 0";//Left
                  }
               }
            }
            break;
         case 3:
            if(!safe(-1,0)){
               if(safe(-1,1)){
                  return "-1 1";//Down-Left
               }else{
                  if(safe(0,1)){
                     return "0 1";//Down
                  }
               }
            }
            break;
         case 4:
            if(safe(0,-1))return "0 -1";
            break;
         case 5:
            if(!safe(0,2)){
               if(safe(1,2)){
                  return "1 2";//Down-Right
               }else{
                  if(safe(2,2)){
                     return "2 2";
                  }else{
                     if(safe(2,1)){
                        return "2 1";
                     }else{
                        if(safe(2,0)){
                           return "2 0";//Right
                        }
                     }
                  }
               }
            }
            break;
         case 6:
            if(!safe(2,0)){
               if(safe(2,-1)){
                  return "2 -1";//Up-Right
               }else{
                  if(safe(2,-2)){
                     return "2 -2";
                  }else{
                     if(safe(1,-2)){
                        return "1 -2";
                     }else{
                        if(safe(0,-2)){
                           return "0 -2";//Up
                        }
                     }
                  }
               }
            }
            break;
         case 7:
            if(!safe(0,-2)){
               if(safe(-1,-2)){
                  return "-1 -2";//Up-Left
               }else{
                  if(safe(-2,-2)){
                     return "-2 -2";
                  }else{
                     if(safe(-2,-1)){
                        return "-2 -1";
                     }else{
                        if(safe(-2,0)){
                           return "-2 0";//Left
                        }
                     }
                  }
               }
            }
            break;
         case 8:
            if(!safe(-2,0)){
               if(safe(-2,1)){
                  return "-2 1";//Down-Left
               }else{
                  if(safe(-2,2)){
                     return "-2 2";
                  }else{
                     if(safe(-1,2)){
                        return "-1 2";
                     }else{
                        if(safe(0,2)){
                           return "0 2";//Down
                        }
                     }
                  }
               }
            }
            break;
      }
      if(dir<8)return move(dir+1);
      return "0 -1";
   }
   public static boolean safe(int x, int y){
      return !((myx+x<0||myx+x>=map[0].length()||myy+y<0||myy+y>=map.length)||map[y+myy].charAt(myx+x)!='x');
   }
}

Halo, dan selamat datang di PPCG! Jawaban bagus!
NoOneIsHere

2

Bot Acak, UpBot

Dua bot awal untuk bersaing:

Bot Acak: Contoh bot yang bergerak secara acak.

import random

x = random.randint(-4, 4)
y = random.randint(max(-4, -4 + abs(x)), min(4, 4 - abs(x)))
print x, y

UpBot: Contoh bot yang bergerak ke atas.

print '0 -1'

Saya menjalankan 10 putaran tes untuk jawaban Random Walker saya (sekarang dihapus), dan dengan meriah, UpBot bekerja dengan sangat baik. Dia mendapat 7 dari 10 putaran.
user48538


Berikut adalah hasil tes lengkap , yang disediakan sebagai file zip.
user48538

UpBot bekerja dengan baik karena dia hanya bergerak satu blok pada satu waktu, jadi biasanya dia membutuhkan waktu lebih lama untuk berlari ke dinding daripada Random Bot untuk berjalan ke dalam lubang.
Skyler

1
@ zyabin101: Anda tahu, Anda bisa menjalankannya, tekan 'y' untuk bermain turnamen penuh, dan masukkan 10 untuk putaran.
Skyler

1

StalkerBot (Python)

Akan sedekat mungkin ke bot terdekat yang dilihatnya. Menargetkan bunuh diri otomatis Slow Bot (sia-sia). (Jika saya berada di lapangan yang sama dengan itu dan tidak ada pemain lain, itu tidak akan melihat saya dan akan bunuh diri.)

#!/usr/bin/python3
from math import inf
from sys import argv

class Vector:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)

    def __neg__(self):
        return Vector(-self.x, -self.y)

    def __abs__(self):
        return self.x ** 2 + self.y ** 2  # Technically the square of the magnitude, but we only need it for comparison.

    def __iter__(self):
        yield self.x
        yield self.y

def get_location(grid, target='@'):
    for i, line in enumerate(grid):
        for j, char in enumerate(line):
            if char == target:
                return Vector(i, j)

def main(grid):
    my_location = get_location()

    min_distance = inf
    min_distance_direction = None

    for i in range(10):
        enemy_location = get_location(str(i))

        if enemy_location is not None:
            direction = enemy_location - my_location
            distance = abs(direction)

            if distance < current_min:
                min_distance = distance
                min_distance_direction = direction

            if distance == 1:
                break

    if min_distance_direction is not None:
        return min_distance_direction

    for d in range(1, 5):
        for x in range(-d, d):
            for y in (d - abs(x), abs(x) - d):
                if grid[x][y] == ' ':
                    return x, y

    return 0, 0

if __name__ == '__main__':
    print(*main(argv[1].splitlines()))

1
Hanya FYI, secara umum kami tidak menyetujui pengeditan yang mengubah kode (seperti yang Anda lakukan pada jawaban lain untuk pertanyaan ini). Saya menyetujui itu karena sepertinya tidak menyentuh logika atau apa pun tetapi hanya membersihkannya, tapi itu tidak akan terbang pada sebagian besar jawaban. Yang itu pasti bisa menggunakannya.
Rɪᴋᴇʀ

@ Pengemudi Memahami. Masuk akal untuk tidak mengubah logika, tetapi saya kesulitan membaca kode itu, jadi saya memutuskan untuk membersihkan format.
Solomon Ucko

1
Tidak masalah, tetapi perlu diingat bahwa suntingan golf dan sejenisnya kemungkinan akan ditolak pada pertanyaan lain ke depan. Saya setuju bahwa kode yang Anda edit agak miring.
Rɪᴋᴇʀ

1
@ Pengendara Pada dasarnya, jangan melakukan pengeditan yang dapat memengaruhi skor.
Solomon Ucko
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.