KOTH: TNT Run Challenge


25

สิ่งนี้ได้รับแรงบันดาลใจจากเกมมินิ Minecraft กฎนั้นค่อนข้างเรียบง่าย: คุณวิ่งและกระโดดไปมาและทุก ๆ บล็อกที่คุณเหยียบหายไปเมื่อคุณเหยียบมัน เป้าหมายคือการเป็นคนสุดท้ายที่เหลืออยู่

บอทของคุณควรเป็นโปรแกรมที่สมบูรณ์ มันควรจะยอมรับอินพุตเป็นอาร์กิวเมนต์บรรทัดคำสั่ง ข้อมูลที่ป้อนจะเป็นแผนที่ของ "โลก" นี่คือตัวอย่าง:

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         

ตำนานมีดังนี้:

x: solid block

 : empty air

@: your bot

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

บอทของคุณควรออกการเคลื่อนไหวของคุณเป็นจำนวนเต็มคู่ ตัวอย่าง: -1, 2จะย้าย 1 บล็อกไปทางซ้ายและ 2 บล็อกลง (พิกัดจุดกำเนิดอยู่ที่มุมซ้ายบน)

คุณสามารถเลื่อนได้ถึงสี่ช่วงระยะแมนฮัตตันจากตำแหน่งปัจจุบันของคุณ หากคุณพยายามเคลื่อนที่มากกว่านั้นการเคลื่อนไหวจะไม่ถูกต้อง การเคลื่อนไหวใด ๆ ที่จะทำให้คุณก้าวผ่านขอบจะทำให้คุณอยู่ที่ขอบแทน การเคลื่อนไหวที่ไม่ถูกต้องจะถูกละเว้น

เมื่อคุณลงจอดบนบล็อกมันจะถูกลบออก; หากคุณยังคงอยู่ในบล็อกเดียวกันในเทิร์นถัดไปคุณจะตก สองบ็อตอาจลงจอดบนบล็อกเดียวกันในเทิร์นเดียวกันและทั้งสองอยู่รอด หากสิ่งนี้เกิดขึ้นบอททั้งคู่จะเห็นตัวเองไม่ใช่บอทคนอื่น

หากคุณต้องการจัดเก็บไฟล์เพื่อคงอยู่โปรดทำเช่นนั้นในโฟลเดอร์ที่มีชื่อบอทของคุณ คุณไม่สามารถอ่านข้อมูลถาวรของบ็อตอื่นหากมีอยู่

ควบคุมการแข่งขันที่มีอยู่ในhttps://paste.ee/p/Xf65d

โปรดใช้ภาษาที่สามารถใช้งานได้บนการติดตั้ง Linux หรือ OSX มาตรฐาน

ผลลัพธ์ปัจจุบัน (100 รอบ):

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

ในทำนองเดียวกันแม้ว่าความแตกต่างที่สำคัญคือคุณสามารถ "ข้าม" บล็อกหลาย ๆ บล็อกได้ดังนั้นคุณจะไม่สามารถบล็อกใครบางคนได้หากพวกเขาเห็นสิ่งที่คุณทำ
Skyler

คุณไม่สามารถปิดเหมือนล่อลวงในกล่องทรายและฉันไม่คิดว่ามันจะเป็นหนึ่งเดียว
Blue

1
การเคลื่อนไหวพร้อมกันหรือตามลำดับหรือไม่ อินพุตเป็นสตริงที่มีการขึ้นบรรทัดใหม่จริงๆเป็นอาร์กิวเมนต์บรรทัดคำสั่งหรือไม่?
feersum

1
ฉันขอแนะนำให้เรียกบอทหนึ่งครั้งโดยที่ไม่มีโลกสำหรับการเริ่มต้น (คุณไม่ทราบว่ารัฐของคุณบันทึกเป็นไฟล์มาจากรอบสุดท้ายหรือจากรอบนี้)
bauen1

@feersum ย้ายพร้อมกัน; อินพุตเป็นอาร์กิวเมนต์บรรทัดคำสั่งที่ขึ้นบรรทัดใหม่ หากคุณต้องการเป็น stdin แทนให้ฉันรู้และฉันอาจแก้ไขตัวควบคุมเพื่ออนุญาต
Skyler

คำตอบ:


9

บอทช้า (Python)

เขาเคลื่อนไหวในรูปแบบของเส้นและตรวจสอบการเคลื่อนไหวของเขาก่อนที่จะทำให้พวกเขา (ยังฆ่าตัวตายเมื่อเขาเป็นคนสุดท้ายที่มีชีวิตอยู่เพื่อป้องกันไม่ให้รันไทม์นาน) เขาได้รับรางวัล 195/200 Battels ในทัวร์นาเมนต์ทดสอบของฉัน

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

ฉันไม่ใช่ผู้เชี่ยวชาญในงูหลามและอาจมีวิธีที่ทำให้มันสั้นกว่า / ดีกว่า 100 วิธี


1
มีเพียงสิ่งเดียวถ้าคุณอยู่ในพื้นที่เดียวกันกับบอทตัวอื่นและคุณเป็นสองคนสุดท้ายคุณจะคิดว่ามันเป็นครั้งสุดท้ายและการฆ่าตัวตาย
Timtech

เมื่อฉันใช้ความเพียรเขาจะรอ 5 รอบจนกว่าจะฆ่าตัวตาย
bauen1

เยี่ยมมากนั่นคือสิ่งที่ฉันอยากจะแนะนำ คำตอบที่ยอดเยี่ยมโดยวิธีการ
Timtech

6

JumpBot (C)

พยายามข้ามไปยังสนามที่มีท่าที่เป็นไปได้มากที่สุดในรอบต่อไป

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

บอทธรรมดาที่มีประสิทธิภาพใกล้เคียงกับบอทช้ายกเว้นอันนี้ทำให้สามารถเคลื่อนที่แบบสุ่มได้ วางแผนที่จะปรับปรุงสิ่งนี้เป็น 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

เครื่องมือสร้างคูเมือง (Python)

ถ้าฉันขุดคูเมืองรอบตัวเองไม่มีใครอยู่ข้างนอกมันสามารถทำให้ฉันกลัว

... ยังเป็นที่รู้จักกันในนาม "วาดภาพตัวเองในมุมจำลอง 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)

มันใช้งานได้ดีจริง ๆ แต่มันจะแพ้บอทที่มีชีวิตอยู่เป็นเวลานาน (นั่นเป็นเหตุผลว่าทำไมฉันถึงเลือกรูปแบบบรรทัด btw)
bauen1

คุณอาจต้องการที่จะแก้ไขการเยื้องของคุณใน smallmove () ... หลามของฉันไม่กินนี้ :)
tomsmeding

5

มอนเต (Python)

ขออภัยที่ปุนต้องทำ

อย่างไรก็ตามบ็อตนี้ทำงานโดยใช้การค้นหาต้นไม้มอนติคาร์โลในชุดเคลื่อนย้ายที่เป็นไปได้ทั้งหมด นึกถึง JumpBot ในเชิงลึกเท่านั้น

ในการรันจำเป็นต้องมีอาร์กิวเมนต์บรรทัดคำสั่งพิเศษ (สามารถระบุได้ในคอนโทรลเลอร์) มันควบคุมเวลาที่บอทควรค้นหา (เป็นมิลลิวินาที) ฉันใช้ 750-1500 ในการทดสอบ

รหัส:

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

การทดลอง

25 รอบ:

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

100 รอบ:

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

200 รอบ:

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

การจำลองทั้งหมดข้างต้นใช้เวลาในการค้นหา 750 บ็อตนี้น่าจะดียิ่งขึ้นเมื่อใช้เวลาค้นหานานขึ้น (ฉันไม่รู้ว่าค่าสูงสุดคืออะไร)

ปรับปรุง

บอทนี้ยังต้องการการปรับปรุงใน:

  1. ประสิทธิภาพการทำงาน: ต้องการเวลาทั้งหมดในการค้นหา
  2. การทำนาย: มันจะไม่พิจารณาการเคลื่อนไหวของบอทอื่น
  3. ยอดคงเหลือ: ฉันไม่แน่ใจว่าสูตร UCT ที่ฉันใช้เพื่อคำนวณว่าโหนดใดที่ฉันควรสำรวจนั้นเหมาะสมที่สุด

4

ShyBot (Python)

บอทนี้ไม่ชอบบ็อตอื่น ๆ และจะพยายามหลีกเลี่ยงตัวเองถ้าเป็นไปได้ ShyBot ยังระวังให้ดีว่ามันอยู่ตรงไหน มันจะไม่ได้เหยียบแม้แต่บอทตัวอื่น อย่างไรก็ตาม ShyBot ยังมีการสูญเสียบ่อยครั้งซึ่งทำให้ไม่ปลอดภัย

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

มันใช้งานได้เหมือนหมากรุกและมีชื่อเหมือน Twitch ...

...

.........

............................ ขอโทษ ...

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)

สิ่งเหล่านี้เห็นได้ชัดว่าไม่ใช่คำตอบที่ดีที่สุด แต่ฉันหวังว่าจะเป็นประโยชน์สำหรับการทดสอบระดับกลาง

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');
   }
}

สวัสดีและยินดีต้อนรับสู่ PPCG! คำตอบที่ดี!
NoOneIsHere

2

บอทสุ่ม UpBot

บอทสองตัวเพื่อเริ่มแข่งขัน:

บอทแบบสุ่ม:บอทตัวอย่างที่เคลื่อนที่แบบสุ่ม

import random

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

UpBot:บอทตัวอย่างที่เลื่อนขึ้น

print '0 -1'

ฉันวิ่งทดสอบรอบ 10 รอบสำหรับคำตอบวอล์คเกอร์แบบสุ่ม (ตอนนี้ลบ) ของฉันและเฮฮา UpBot ทำได้ดีมาก เขาได้ 7 จาก 10 รอบ
user48538



UpBot ทำได้ดีเพราะเขาย้ายเพียงครั้งละหนึ่งบล็อกเท่านั้นดังนั้นโดยทั่วไปแล้วจะใช้เวลานานกว่าที่จะวิ่งเข้าไปในกำแพงมากกว่าที่บอทแบบสุ่มจะเดินเข้าไปในรู
Skyler

1
@ zyabin101: คุณรู้คุณสามารถเรียกใช้มันกด 'y' เพื่อเล่นทัวร์นาเมนต์เต็มรูปแบบและป้อน 10 รอบ
Skyler

1

StalkerBot (Python)

จะเข้าใกล้บอทที่ใกล้ที่สุดเท่าที่จะเป็นไปได้ เป้าหมายการฆ่าตัวตายอัตโนมัติของ Bot (ช้าๆ) (ถ้าฉันอยู่ในจตุรัสเดียวกันกับที่และไม่มีผู้เล่นคนอื่นมันจะไม่เห็นฉันและจะฆ่าตัวตาย)

#!/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
เพียงแค่ FYI โดยทั่วไปเราไม่อนุมัติการแก้ไขที่แก้ไขโค้ด (เช่นเดียวกับที่คุณทำกับคำตอบอื่นสำหรับคำถามนี้) ฉันอนุมัติว่าเนื่องจากดูเหมือนว่ามันไม่ได้สัมผัสตรรกะหรืออะไรเลย แต่เพิ่งทำความสะอาดมัน แต่นั่นไม่ใช่คำตอบส่วนใหญ่ คนนั้นสามารถใช้มันได้อย่างแน่นอน
Rɪᴋᴇʀ

@Riker เข้าใจ มันสมเหตุสมผลแล้วที่จะไม่เปลี่ยนตรรกะ แต่ฉันมีปัญหาในการอ่านรหัสนั้นดังนั้นฉันจึงตัดสินใจล้างข้อมูลการจัดรูปแบบ
โซโลมอน Ucko

1
ไม่มีปัญหา แต่โปรดจำไว้ว่าการแก้ไขการเล่นกอล์ฟและสิ่งที่คล้ายกันนั้นมีแนวโน้มที่จะถูกปฏิเสธในคำถามอื่น ๆ ในอนาคต ฉันยอมรับว่ารหัสที่คุณแก้ไขเป็นสิ่งที่ไม่ดีนัก
Rɪᴋᴇʀ

1
@Riker โดยทั่วไปอย่าทำการแก้ไขใด ๆ ที่อาจส่งผลกระทบต่อคะแนน
โซโลมอน Ucko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.