aBOTcalypse Now

8

aBOTcalypse

Entwerfe einen Bot, um an einer King-of-the-Hill-Herausforderung teilzunehmen! Hier ist eine Wiederholung eines Standard-Bot-Spiels.

Das Board ist 2D, wie ein Side-Scrolling-Videospiel (jedoch ohne Scrollen).

Ein gültiger Bot muss eine mehrzeilige Zeichenfolgendarstellung des Bereichs der Karte akzeptieren, den er sehen kann, und eine Bewegung für den Bot ausgeben.

Mechanik

Dies ist ein Überlebensspiel. Die Apokalypse ist gekommen und nur noch Bots (und ein endloser Vorrat an Steinen, die im Hammerspace gespeichert sind ) sind übrig. Jeder Bot erhält einen zufälligen Startort auf Höhe 0. In einer bestimmten Bewegung kann sich ein Bot ausruhen, bewegen, einen Stein werfen oder einen Stein fallen lassen. Bots können den Raum mit stationären Steinen teilen, aber ein Bot, der mit einem anderen Bot oder einem Meteor kollidiert, wird getötet, ebenso wie ein Bot, der von einem geworfenen Stein getroffen wird.

  • Schwerkraft: Bots und Steine ​​müssen auf dem Boden des Bretts oder auf einem anderen Stein ruhen. Wenn man sich auf etwas anderem ausruht (Luft, Meteor, Bot usw.), bleibt man "nicht unterstützt". Nicht unterstützte Bots oder Steine ​​fallen, bis sie unterstützt werden. Ein Sturz von mehr als einem Feld tötet einen Bot, und ein Bot unter einem fallenden Stein oder Bot wird ebenfalls getötet. Dies bedeutet, dass der Versuch, sich zu bewegen oder nach oben zu fallen, nur funktioniert, wenn der Bot gerade ein Feld mit einem Stein teilt (andernfalls fällt der Bot / Stein 1 Feld zurück). Ein Raum kann "nicht unterstützt" werden, wenn der darunter liegende Stein fällt oder von einem Meteor oder Projektil zerstört wird .
  • Meteore: In jeder Runde betritt ein Meteor von oben das Brett. Ein Meteor hat eine Geschwindigkeit der Größe 2 mit einem zufälligen Winkel, der gleichmäßig im Bereich [-180,0] gewählt wird, und einer zufälligen Startposition x. Meteore fallen in einer geraden Linie entlang der vorgegebenen Flugbahn, bis sie auf etwas treffen. An diesem Punkt verschwinden sie. Beachten Sie, dass die Rundung in der Bewegung eines Meteors in Richtung 0 erfolgt (gemäß Python int()).
  • Projektile: Ein Bot kann einen Stein in beliebiger Entfernung bis zu seiner Höhe werfen. Ein geworfener Stein bewegt sich in einer geraden Linie, bis er auf etwas trifft (alles in einer Runde, im Gegensatz zu einem Meteor; geworfene Steine ​​erscheinen nicht auf dem Brett), an einem Hang von - elevation / max distance. Beachten Sie, dass geworfene Steine ​​ihre Flugbahn bei x + - 1 Quadrat beginnen. Befindet sich ein Bot beispielsweise auf einer Höhe von 5 und wirft er einen Abstand von 1 nach links, beginnt (x-1,5)und endet der Stein bei (x-2,0). Die Kollision wird nur in Schritten von geprüft dx=1und dyauf 0 gerundet (gemäß Python int()).

Eingang

Jeder Bot kann ein Quadrat von 20 Pixeln in jeder Richtung (Chebyshev-Abstand = 20) bis zu den Grenzen des Bretts sehen. Jede Eingabezeichenfolge enthält 8 verschiedene Zeichen:

  • '#' (Brettgrenze)
  • '.' (Luft)
  • '@'(Meteor)
  • '&' (Felsen)
  • 'e'/ 's'(ein feindlicher Bot oder sich selbst)
  • 'E'/ 'S'(ein feindlicher Bot oder sich selbst, der ein Feld mit einem Stein teilt)

Hier ist eine Beispieleingabe (Zeilenumbrüche werden angezeigt \n):

..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............@...............#
.....................E........#
.....................&........#
.....................&........#
.....................&........#
.....................&........#
...........@.........&........#
....................s&........#
###############################

Ausgabe

Es gibt vier Aktionen, die ein Bot in jeder Runde ausführen kann.

  • rest (buchstäblich sitzen und nichts tun)
  • move <direction>bewegt den bietet einen Raum in jedem der vier Richtungen, up, down, left, oder right. Durch Bewegung fällt der Bot, wenn der neue Raum nicht vom Boden oder einem Stein getragen wird ( fall > 1 = bot.kill()).
  • drop <direction>platziert ("Tropfen") einen Stein in der angegebenen Richtung. Wenn Sie einen Stein nach oben fallen lassen (dh einen Stein auf das Quadrat legen [bot_x, bot_y+1]) oder zur Seite legen , fällt er bis zur Unterstützung (möglicherweise fällt er währenddessen auf den Bot drop up). drop downPlatziert einen Stein an der gleichen Position wie der Bot, wenn dort noch kein Stein ist.
  • throw <direction> <distance>wirft einen Stein gemäß der obigen "Projektil" -Mechanik mit der angegebenen maximalen Entfernung. Die maximale Entfernung ist für das Werfen nach oben oder unten irrelevant - das Projektil kollidiert mit dem Quadrat unter (für down) oder versucht, mit dem Quadrat über (für up) und dann mit dem Quadrat des Bots zu kollidieren, wenn es nichts trifft (den Bot töten). .

Ein Bot im Wettbewerb muss beim Empfang der Eingabezeichenfolge eine skalare Zeichenfolge mit ihrer Aktion ausgeben.

Schnittstelle

Ein Bot muss aus einem einzigen Programm bestehen, das über eine Python 2 aufgerufen werden kann subprocess. Alle Befehle sollen angegeben werden, und werden in einer Datei mit dem Namen gespeichert werden command.txt; Bevor ein Spiel beginnt, führt der Controller jeden Befehl der command.txtReihe nach aus. Anschließend wird der letzte Befehl verwendet, um die Eingabe an den Bot weiterzuleiten.

Ein Bot kann eine einzelne Speicherdatei storage.txtin seinem Ordner haben. Der Bot "Default Thrower" zeigt eine Beispielimplementierung, bei der json verwendet wird, um seinen Status während verschiedener Runden zu speichern. Sie können die Debugging-Ausgabe auch in eine Nur-Schreib-Ausgabe aufnehmen errlog.txt, die ich weitergeben werde, falls Ihr Bot während eines Laufs ausfällt. Ich werde sicherstellen, dass mit jedem Bot mehrere Tests durchgeführt werden, um Fehler im Voraus zu finden.

Wertung

Die Gesamtpunktzahl eines Bots entspricht der Anzahl der Runden, die er überlebt hat und die sich über X Spiele mit maximaler Länge Y angesammelt haben X,Y = 10, 500. Wenn Bots eine lange Zeit dauern, werde ich Y erhöhen, und wenn sie eine kurze Zeit dauern, werde ich X erhöhen.

Der Controller-Code befindet sich in controller.py . Vielen Dank an @Nathan Merrill für sein DDOS-Koth, von dem ich den Communicator-Code angepasst habe.

Sirpercival
quelle
Was hindert Bots daran, Strukturen wie z &&&\n&S&\n###. Sie wären für fallende Meteore unverwundbar.
LegionMammal978
gar nichts. Sie müssten jedoch einen Teil der Struktur neu aufbauen, wenn sie von irgendetwas getroffen würde (was bedeutet, dass sie während des Wartungsprozesses auf einer der äußeren Schichten freigelegt wird), und sie müssten sich immer noch mit anderen Bots befassen.
Sirpercival
Soweit ich sehen kann, gibt es keine Möglichkeit, Steine ​​zu graben.
LegionMammal978
was meinst du mit "graben"? Jeder Bot hat so viele Steine ​​wie er will, die im Hammerspace gespeichert sind (ich werde diesen Link in der Frage bearbeiten). oder willst du felsen zerstören? Wenn dies der Fall ist, wird ein Stein zerstört, wenn er von einem Projektil getroffen wird, nicht nur von einem Meteor. Erkenne auch, dass andere Bots direkt in deine Festung walzen können.
Sirpercival
1
Sie sollten die Tatsache hinzufügen, dass Meteore / Projektile Steine ​​zerstören.
LegionMammal978

Antworten:

1

Python 2, Edgebot

Edgebot will sich in einer Ecke verstecken und einen Turm bauen. Sie rennen zu einem Ende, bauen sich ein wenig auf und lassen dann Steine ​​fallen, um eine Mauer zu bauen. Edgebot mag keine Besucher und wirft Steine ​​auf jeden, der zu nahe an seinen Turm kommt. Wenn alles schrecklich schief geht und der Kantenanschlag abstürzt, lässt er einen Stein auf seinen eigenen Kopf fallen

import sys
from random import randint
class edgebot():    

    def playtime(self,board):
        try:   
            self.max_height = 5    
            board = board.splitlines()

            #find edgebot
            for y in xrange(0,len(board)):
                row = board[y]
                symbol = 's' if row.count('s') else 'S'
                x = row.find(symbol)
                if x >= 0:
                    self.height = 20 - y
                    break

            ground = board[len(board)-2]
            floor = board[len(board)-1]
            nasty_person = 'e' if ground.count('e') else 'E'
            bad_x = ground.find(nasty_person)
            side = ground.find('#')
            if abs(side - x) ==1:
                self.end_found = 1
            else:
                self.end_found = 0

            if side - x == -1:
                self.direction = 'right'
            else:
                self.direction = 'left'       


            #Bad edgebot! No climbing out of the game!           
            if floor[x] != '#':
                if board[self.height-1][x] == '&':
                    dist = randint(3,self.height)
                    return 'throw ' + self.direction + ' ' + `dist`
                elif symbol =='S':
                    return 'drop up'
                else:
                    return 'move down'

            #Edgebot will go through you to find a corner. You have been warned.    
            elif abs(x - bad_x) <=2:
                if x - bad_x >0:
                    return 'throw left 1'
                else:
                    return 'throw right 1'

            #edgebot wants to hide in a corner
            elif self.end_found ==0:
                if side == -1:
                    return 'move right'#edgebot is right-handed
                elif side - x < -1:
                    return 'move left'
                elif side - x > 1:
                    return 'move right'

            #Too close! Throw rocks at it!
            elif self.height+1>= abs(x-bad_x) and abs(x-bad_x) >=3:
                distance = abs(x - bad_x) - 2
                if distance < 1:
                    return 'throw ' + self.direction + ' 1'
                else:
                    return 'throw ' + self.direction + ' ' +`distance - 1`
                self.max_height += 2 #people came close, edgebot needs to be higher up!

            #edgebot wants a home in the corner        
            elif self.height <self.max_height :
                if symbol =='S':
                    return 'move up'
                else:
                    return 'drop down'

            #edgebot wants a wall. edgebot has, at best, a limited understanding of architecture        
            elif bad_x < 3 or self.height+1<abs(x-bad_x):
                if self.direction == 'right' and row[x+1] == '&':
                    self.max_height += 2
                    return 'drop down'
                elif self.direction == 'left' and row[x-1] == '&':
                    self.max_height += 2
                    return 'move down'
                else:
                    return 'drop ' + self.direction         

            else:
                return 'drop down' #Not sure? Hide under a rock!
        except:
            return 'drop up' #All gone horribly wrong? Squish.


print edgebot().playtime(sys.argv[1])  

Entschuldigung für alle Änderungen, vor dem Absenden wurden nicht genügend Testfälle ausgeführt. Es gibt ein kleines Problem, dass der kleine Kerl versuchen wird, mit genügend Zeit von der Spitze des Bretts zu klettern, aber hoffentlich wird das in den meisten Spielen kein Problem sein. Edgebot sollte jetzt nur zufällige Steine ​​werfen, sobald es hoch genug geklettert ist

Letzte Bearbeitung für jetzt. Edgebot wirft jetzt Steine ​​auf jeden, der nahe genug zwischen ihm und der Wand liegt. Es macht keinen Sinn, sich durch jemanden zu rennen

LogicianWithAHat
quelle