Die Ostereiersuche auf dem Hügel

17

Ostereiersuche

Bot finden Ei vor Hase finden Ei. Bot glücklich.

Überblick

Dies ist eine Herausforderung zu Ehren von Ostern und der Osterei-Jagdtradition!

Ihr Bot hat eine Vision von zwei Räumen in jeder Richtung, einschließlich Diagonalen, wodurch ein 5x5-Quadrat um Sie herum entsteht, das Sie sehen können. Es sucht nach Eiern, und wer die meisten Eier findet, gewinnt!

Die Tafel

Das Brett besteht aus os, die Ostereier sind, #s, die Wände sind, *s, die andere Spieler sind, und s, die leere Räume sind.

  • Es wird ein Quadrat mit Kantenlänge sein (number of entries) * 3.
  • Es wird von Mauern umgeben sein.
  • Innerhalb der Wände befindet sich eine Auswahl zufällig platzierter, gerader Wände von #, die eine zufällige Länge zwischen 2 und 10 einschließlich haben. Es wird (number of entries) * 3von ihnen sein.
  • Die Eier werden dann zufällig platziert. Es wird (number of entries) * 4von ihnen geben, und sie werden nur auf leeren ( ) Feldern generiert .
  • Es müssen mindestens 7 Elemente vorhanden sein, damit der Board-Generierungsprozess ordnungsgemäß funktioniert.

Hier ist eine JSFiddle, die ein zufälliges Board generiert , mit dem Sie testen können. Hier ist ein Beispiel mit (number of entries) = 7:

#####################
#        o         ##
#    #    o        ##
#    #o    ######  ##
######     #       ##
## o #     #       ##
##  o#   #o#    o o##
##   #o  # # o  #   #
##   # o # #    #   #
##  ##   # #  o #   #
##  #    #  o   # # #
##  # o  #   ## # # #
##  #           # # #
# o #          ## # #
# o oo         ##o  #
#o  ####### oo ##   #
#        #      #   #
#   o o o#          #
#   o ####   o     o#
#                   #
#####################

Nachdem das Brett generiert wurde, wird jeder Spieler auf ein zufälliges Feld (leeres Feld) gelegt.

Eingang

Sie werden sechs Eingabezeilen nehmen. Die ersten fünf Zeilen sind Ihr Sichtfeld (Felder außerhalb der Grenzen der Tafel werden durch dargestellt X, und das mittlere Feld ist immer *Sie selbst), und die sechste Zeile ist (zunächst) leer.

Ausgabe

Sie werden drei Zeilen ausgeben. Zunächst die Richtung, in die Sie sich bewegen möchten:

1  2  3
8 YOU 4
7  6  5

(9 ist ein No-Op, wenn Sie sich nicht bewegen möchten), zweitens eine von ATack, CCounter oder Netwas anderem (dies wird in Kürze näher erläutert), und die dritte Zeile ist eine beliebige Zeichenfolge mit einer Länge von bis zu 1024 Dies wird das Gedächtnis Ihres Bots sein. Sie können es für beliebige Zwecke verwenden oder leer lassen. Dieser Speicher ist dann die sechste Eingabezeile für Ihr Programm bei der nächsten Ausführung.

Alle weiteren Ausgabezeilen werden ignoriert, und wenn nur eine Zeile vorhanden ist, wird angenommen, dass die zweite leer ist.

Ziehen um

Der folgende Prozess wird verwendet, um festzustellen, wo Sie umgezogen sind:

  • Wenn Sie sich bei Ihrem Umzug in ein leeres Feld begeben ( ), wird Ihr Spieler in dieses Feld gestellt.
  • Wenn Sie in einer Mauer landen ( #), wird Ihr Zug ignoriert und Sie verlieren Ihren Zug.
  • Wenn Sie in einem Ei ( o) oder auf einem Spieler ( *) landen , werden diese Informationen gespeichert und verwendet, nachdem alle umgezogen sind.

Nachdem alle umgezogen sind, werden Unklarheiten gelöst.

Wenn zwei Spieler auf dem gleichen Feld gelandet sind, kommt es zu einem Kampf! Hier wird die A/ C/ Num Spiel kommt. Attack schlägt etwas Nanderes (normaler Angriff), Nttack schlägt etwas Canderes (man kann nichts kontern) und Cttack schlägt etwas Aanderes (Gegenangriff). Der Spieler, der diesen Kampf gewinnt, bleibt auf seinem Feld und der Spieler, der verliert, kehrt zu dem ursprünglichen Feld zurück, auf dem er begonnen hat. Bei einem Unentschieden kehren beide Spieler zu ihrem ursprünglichen Standort zurück.

Wenn ein verlierender oder gebundener Spieler zu seinem ursprünglichen Platz zurückkehrt und dort ein anderer Spieler ist, gibt es keinen Kampf und der andere Spieler kehrt ebenfalls zu seinem ursprünglichen Platz zurück. Wenn dieses Feld einen anderen Spieler hat , geht dieser zurück und dies wird fortgesetzt, bis sich alle Spieler in verschiedenen Feldern befinden.

Wenn sich drei oder mehr Spieler auf einem Feld befinden, kehren alle zu ihren ursprünglichen Positionen zurück.

Wenn noch ein Spieler auf einem Ei steht ...

  • Wenn der Spieler wählt A, wird das Ei zerstört.
  • Wenn der Spieler gewählt hat C, passiert nichts und der Spieler kehrt zu seinem ursprünglichen Platz zurück.
  • Wenn der Spieler gewählt hat N, nimmt der Spieler das Ei auf! Die Punktzahl des Spielers wird um eins erhöht und das Ei wird entfernt.

Sprachen

Sie können jede Sprache verwenden, die unter Windows, OSX und Linux frei verfügbar ist, um die Fairness zwischen den Teilnehmern zu gewährleisten. Wenn der Code nicht frei ausführbar ist, sondern kompiliert oder in ein Format gepackt werden kann, geben Sie dies bitte auch in Ihrer Antwort an. Wenn Sie Ihren Code in einer allgemeineren Sprache (z. B. CoffeeScript -> JavaScript) kompilieren können, tun Sie dies im Idealfall.

Wertung

Ihre Punktzahl ist die durchschnittliche Anzahl von Eiern, die Sie in zehn Läufen sammeln. Ein Lauf endet, wenn alle Eier eingesammelt sind oder die (number of entries * 25)Züge abgelaufen sind. Ich werde manuell sicherstellen, dass es möglich ist, alle Eier für jede Karte zu erreichen (indem kontinuierlich Karten erstellt werden, bis alle Eier erreichbar sind).

Anzeigetafel

Eine Anzeigetafel wird hinzugefügt, wenn alle folgenden Bedingungen erfüllt sind:

  • Es wurden mindestens sieben gültige Beiträge mit einer positiven oder Null-Punktzahl (nicht herabgestuft) eingereicht
  • Mindestens 48 Stunden sind vergangen, seit diese Herausforderung erstellt wurde (UTC 14:23)

Die Regeln werden während dieser Vorwettbewerbsperiode nicht geändert, es sei denn, es wurde klargestellt, wo eine Regel unklar war. Sobald die Anzeigetafel erstellt ist, wird auch das Testprogramm hier veröffentlicht, damit Sie Ihre Eingaben testen können. Der Testcode dafür ist noch in Arbeit, aber er kann abgespielt werden und funktioniert. Hier ist das GitHub-Repo.

Türknauf
quelle
4
Können wir das Testprogramm erhalten, bevor 7 Einträge veröffentlicht wurden? Ich teste gerne vor dem Posten, auch wenn es gegen "dumme" Test-Bots ist. Es scheint ein erheblicher Vorteil zu sein, erst dann zu posten, wenn mehrere andere es getan haben.
Geobits
1
In Bezug auf Spieler, die zurückgehen. Ich könnte also möglicherweise Pech haben und gegen einen Gegner gewinnen, aber er tritt in einen anderen Spieler zurück und startet eine Kaskade, die sich zum Ort unseres Kampfes zurückzieht, sodass der Spieler, der dort angefangen hat, mich ebenfalls einen Schritt zurückschickt? (Wenn das nicht klar ist, werde ich einen Github-Artikel mit einem Beispiel veröffentlichen.)
Martin Ender,
1
Ein Beispielsteuerprogramm wäre hier sehr nützlich.
Starbeamrainbowlabs
3
Ich mag die Memory-Line-Idee
Einacio
2
Sind Sie sich auch der Auswirkungen Ihrer Regeln bewusst: Wenn ein Spieler (A) wählt 9, kann er niemals sinnvoll angegriffen werden. Wenn ein anderer Spieler (B) das Feld dieses Spielers betritt und gewinnt, wird A auf das ursprüngliche Feld (das das gleiche ist) zurückgesetzt. Aber jetzt gibt es einen Konflikt, weil sowohl A als auch B da sind, also muss B zu seinem eigenen Feld zurückkehren. Das Ergebnis ist also unabhängig vom eigentlichen Kampf, B geht immer zum Ausgangsquadrat zurück und A bleibt immer gesetzt. Das würde mir erlauben, beides zu schreiben, was einem anderen Beitrag helfen könnte, indem ein Pfad für alle anderen blockiert wird.
Martin Ender

Antworten:

3

Cart'o'Gophers

Hier ist eine weitere Einreichung - und diese soll tatsächlich wettbewerbsfähig sein. Wieder ist es in Ruby. Also mach mit ruby cartogophers.rb. Das hat viel länger gedauert als erwartet ...

require 'zlib'
require 'base64'

def encode map, coords
    zipped = Zlib::Deflate.deflate map.join
    encoded = Base64.encode64(zipped).gsub("\n",'')
    "#{coords[:x]}|#{coords[:y]}|#{map.length}|#{encoded}"
end

def decode memory
    memory =~ /^(\d+)[|](\d+)[|](\d+)[|](.*)$/
    coords = {x: $1.to_i, y: $2.to_i}
    n_rows = $3.to_i
    encoded = $4
    decoded = Base64.decode64 encoded
    unzipped = Zlib::Inflate.inflate decoded
    n_cols = unzipped.length / n_rows;
    return unzipped.scan(/.{#{n_cols}}/), coords
end

def update map, fov, coords
    if coords[:x] < 2
        map.map! { |row| '?' << row }
        coords[:x] += 1
    elsif coords[:x] >= map[0].length - 2
        map.map! { |row| row << '?' }
    end

    if coords[:y] < 2
        map.unshift '?' * map[0].length
        coords[:y] += 1
    elsif coords[:y] >= map.length - 2
        map.push '?' * map[0].length
    end

    fov.each_index do |i|
        map[coords[:y]-2+i][coords[:x]-2, 5] = fov[i]
    end

    return map, coords
end

def clean_up map
    map.each do |row|
        row.gsub!('*', ' ')
    end
end

DIRECTIONS = [
    [],
    [-1,-1],
    [ 0,-1],
    [ 1,-1],
    [ 1, 0],
    [ 1, 1],
    [ 0, 1],
    [-1, 1],
    [-1, 0],
    [ 0, 0]
]

def move_to dir, coords
    {
        x: coords[:x] + DIRECTIONS[dir][0],
        y: coords[:y] + DIRECTIONS[dir][1]
    }
end

def get map, coords
    if coords[:x] < 0 || coords[:x] >= map[0].length ||
       coords[:y] < 0 || coords[:y] >= map.length
        return '?'
    end
    map[coords[:y]][coords[:x]]
end

def set map, coords, value
    unless coords[:x] < 0 || coords[:x] >= map[0].length ||
       coords[:y] < 0 || coords[:y] >= map.length
        map[coords[:y]][coords[:x]] = value
    end
    map[coords[:y]][coords[:x]]
end

def scan_surroundings map, coords
    not_checked = [coords]
    checked = []
    cost = { coords => 0 }
    direction = { coords => 9 }
    edges = {}

    while not_checked.length > 0
        current = not_checked.pop

        checked.push current
        (-1..1).each do |i|
            (-1..1).each do |j|
                c = { x: current[:x]+i, y: current[:y]+j }
                unless not_checked.include?(c) || checked.include?(c)
                    if get(map, c) == '#'
                        checked.push c
                    elsif get(map, c) == '?'
                        checked.push c
                        edges[current] = { cost: cost[current], move: direction[current] }
                    else
                        not_checked.unshift c

                        cost[c] = cost[current] + 1
                        if direction[current] == 9 # assign initial direction
                            direction[c] = DIRECTIONS.find_index([i,j])
                        else
                            direction[c] = direction[current]
                        end

                        if get(map, c) == 'o'
                            return direction[c], if cost[c] == 1 then 'N' else 'A' end
                        end

                        edges[c] = { cost: cost[c], move: direction[c] } if c[:x] == 0 || c[:x] == map[0].length - 1 ||
                                                                            c[:y] == 0 || c[:y] == map.length - 1
                    end
                end
            end
        end
    end

    # If no egg has been found return the move to the closest edge
    nearest_edge = edges.keys.sort_by { |c| edges[c][:cost] }.first
    if edges.length > 0
        return edges[nearest_edge][:move], 'A'
    else
        # The entire map has been scanned and no more eggs are left.
        # Wait for the game to end.
        return 9, 'N'
    end
end

input = $<.read.split "\n"
fov = input[0..4]
memory = input[5]

if memory
    map, coords = decode memory
    map, coords = update(map, fov, coords)
else
    map = fov
    coords = {x: 2, y: 2}
end
clean_up map

move, attack = scan_surroundings(map, coords)

memory = encode map, move_to(move, coords)

puts "#{move}
#{attack}
#{memory}"

Dieser Bot merkt sich, was er zuvor gesehen hat und versucht, in jeder Runde eine größere Karte zu erstellen. Dann sucht es mit einer Breitensuche nach dem nächsten Ei und geht auf diese Weise voran. Wenn auf der aktuellen Karte kein Ei erreicht werden kann, bewegt sich der Bot zum nächsten offenen Rand seiner Karte (um die Karte schnell in eine Richtung zu erweitern, in die er sich noch bewegen kann).

Dieser Bot hat noch kein Konzept für andere Bots und auch keine Kampfstrategie. Da ich keinen zuverlässigen Weg gefunden habe, um festzustellen, ob mein Umzug erfolgreich war, kann dies zu Problemen führen. Ich gehe einfach immer davon aus, dass der Umzug erfolgreich war. Wenn dies nicht der Fall war, werden an den falschen Stellen neue Patches in die Karte geladen, die für die Pfadfindung möglicherweise schädlich sind oder nicht.

Der Bot verwendet den Speicher, um die Karte und ihre neue Position auf der Karte zu speichern (vorausgesetzt, die Bewegung ist erfolgreich). Die Karte wird ohne Zeilenumbrüche gespeichert, komprimiert und base64-codiert (zusammen mit der Anzahl der Zeilen der Karte, damit die Zeilenumbrüche erneut eingefügt werden können). Durch diese Komprimierung wird die Größe auf etwa ein Drittel der unkomprimierten Karte reduziert. Bei einem Schatten von über 1000 Bytes könnte ich also eine Karte mit etwa 3000 Zellen speichern, was ungefähr der vollständigen Erkundung einer Karte mit 18 Bots entspricht. Solange es nicht annähernd so viele Einreichungen gibt, kann ich mir nicht die Mühe machen, eine Lösung für diesen Fall zu finden.

Nach ein paar Testläufen gegen 5 dumbbots und 1 naivebot(mein anderes Ergebnis) schnitt es entweder sehr schlecht ab (wie 1 oder 2 Eier) oder übertraf die anderen um einiges (7 bis 9 Eier). Ich denke vielleicht über eine bessere Kampfstrategie nach und wie ich feststellen kann, ob ich tatsächlich umgezogen bin oder nicht. Möglicherweise können beide die Punktzahl etwas verbessern.

Oh und wenn du dich über den Namen des Bots wunderst, solltest du The Order of The Stick ( letztes Panel in diesem Comic ) lesen .

BEARBEITEN: Es gab einige Fehler beim Erkennen der Kanten der entdeckten Karte. Jetzt, wo ich sie repariert habe, bekommt dieser Bot immer Punkte 20gegen 5 dumbbots und 1 naivebot. Das ist eher so! Wenn Sie $stderr.puts mapjetzt zu meinem Bot hinzufügen , können Sie wirklich sehen, wie er die Karte systematisch aufdeckt und in der Zwischenzeit alle Eier sammelt. Ich habe auch zu wählen , entschied sich Astatt Nauf ein Ei , wenn nicht verstärkt, um die Wahrscheinlichkeit der Bewegung zurück in die ursprüngliche Zelle bot (die teilweise Schrauben auf der Karte) zu reduzieren.

(Gegen 6 naivebots läuft es nicht ganz so gut , zumal es sehr gut möglich ist, mit einem anderen Bot in einen "Deadlock" zu geraten, wenn beide wiederholt ein Ei nehmen und wählen wollen N. Ich muss darüber nachdenken ... )

Martin Ender
quelle
3

Java-Häschen

Dieses Häschen ist noch nicht erwachsen geworden (ich plane noch Änderungen), aber es ist ein Ausgangspunkt für den Moment. Er sucht nach dem nächsten Ei und geht darauf zu. Es gibt (noch) keine Wanderkennung oder Grenzüberschreitungserkennung. Er wird gehen, um das Ei aufzunehmen, auf dem er landet, aber sonst wird er versuchen, sich herumzudrücken und alles andere anzugreifen. Wenn keine Eier in der Nähe sind, folgt er dem nächsten Hasen. Sie könnten etwas wissen, was er nicht weiß. Andernfalls wählt er einfach eine zufällige Richtung zum Laufen. Und er ist ziemlich vergesslich (keine Verwendung der Speichervariable).

Pläne für die Zukunft:

  • Treffen Sie Entscheidungen basierend auf Wänden / außerhalb der Grenzen
  • Wählen Sie Pfade nicht zufällig, sondern mit einem bestimmten Zweck
  • Verwenden Sie das Gedächtnis, um die Richtung zu bestimmen, in die ich vorher gegangen bin

Update 1 Mein Hase folgt anderen Hasen, wenn er kein Ei sieht. Außerdem wurde der Code "find next egg" in seine eigene Methode überarbeitet.

import java.util.*;

public class EasterEggHunt {

    // board chars
    public static final char EGG = 'o';
    public static final char WALL = '#';
    public static final char BUNNY = '*';
    public static final char SPACE = ' ';
    public static final char OUT_OF_BOUNDS = 'X';

    // player moves
    public static final char ATTACK = 'A';
    public static final char COUNTER = 'C';
    public static final char NOTHING = 'N';

    // directions
    public static final int UPPER_LEFT = 1;
    public static final int UP = 2;
    public static final int UPPER_RIGHT = 3;
    public static final int RIGHT = 4;
    public static final int LOWER_RIGHT = 5;
    public static final int DOWN = 6;
    public static final int LOWER_LEFT = 7;
    public static final int LEFT = 8;
    public static final int STAY = 9;


    // the size of the immediate area
    // (I'll be at the center)
    public static final int VISION_RANGE = 5;

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        char[][] immediateArea = new char[VISION_RANGE][VISION_RANGE];

        for (int i = 0; i < VISION_RANGE; ++i) {
            String line = input.nextLine();
            for (int j = 0; j < VISION_RANGE; ++j) {
                immediateArea[i][j] = line.charAt(j);
            }
        }

        String memory = input.nextLine();

        int moveDirection = decideMoveDirection(immediateArea, memory);
        System.out.println(moveDirection);

        char action = decideAction(immediateArea, memory, moveDirection);
        System.out.println(action);

        // change the memory?
        System.out.println(memory);

    }

    private static int decideMoveDirection(char[][] immediateArea, String memory) {

        // if there's a nearby egg, go towards it
        int direction = nearestBoardObject(immediateArea, EGG);

        // if we didn't find an egg, look for a bunny
        // (maybe he knows where to find eggs)
        if (direction == STAY)
            direction = nearestBoardObject(immediateArea, BUNNY);

        // otherwise, pick a random direction and go
        // we want to also have the chance to stop and catch our breath
        if (direction == STAY)
            direction = new Random().nextInt(STAY + 1);

        return direction;
    }

    private static int nearestBoardObject(char[][] immediateArea, char boardObject) {

        // start at the center and go outward (pick a closer target over a farther one)
        int spacesAway = 1;
        int meX = immediateArea.length / 2;
        int meY = immediateArea[meX].length / 2;

        while (spacesAway <= immediateArea.length / 2) {

            // I like to look right, and go clockwise
            if (immediateArea[meX][meY + spacesAway] == boardObject)
                return RIGHT;
            if (immediateArea[meX + spacesAway][meY + spacesAway] == boardObject)
                return LOWER_RIGHT;
            if (immediateArea[meX + spacesAway][meY] == boardObject)
                return DOWN;
            if (immediateArea[meX + spacesAway][meY - spacesAway] == boardObject)
                return LOWER_LEFT;
            if (immediateArea[meX][meY - spacesAway] == boardObject)
                return LEFT;
            if (immediateArea[meX - spacesAway][meY - spacesAway] == boardObject)
                return UPPER_LEFT;
            if (immediateArea[meX - spacesAway][meY] == boardObject)
                return UP;
            if (immediateArea[meX - spacesAway][meY + spacesAway] == boardObject)
                return UPPER_RIGHT;

            ++spacesAway;
        }

        // if the target object isn't in the immediate area, stay put
        return STAY;

    }

    private static char decideAction(char[][] immediateArea, String memory, int moveDirection) {

        char destinationObject = getDestinationObject(immediateArea, moveDirection);

        switch (destinationObject) {

            case EGG:
                // don't break the egg
                return NOTHING;
            default:
                // get really aggressive on everything else
                // other players, walls, doesn't matter
                return ATTACK;

        }

    }

    private static char getDestinationObject(char[][] immediateArea, int moveDirection) {

        // start at my spot (middle of the board) and figure out which direction I'm going
        int targetX = immediateArea.length / 2;
        int targetY = immediateArea[targetX].length / 2;

        switch (moveDirection) {

            case RIGHT:
                ++targetY;
                break;
            case LOWER_RIGHT:
                ++targetX;
                ++targetY;
                break;
            case DOWN:
                ++targetX;
                break;
            case LOWER_LEFT:
                ++targetX;
                --targetY;
                break;
            case LEFT:
                --targetY;
                break;
            case UPPER_LEFT:
                --targetX;
                --targetY;
                break;
            case UP:
                --targetX;
                break;
            case UPPER_RIGHT:
                --targetX;
                ++targetY;
                break;
            // otherwise we aren't moving

        }

        return immediateArea[targetX][targetY];

    }

}
Brian J
quelle
Ich habe auch gelernt, dass Java-Aufzählungen für Klassen ziemlich voll sind, und ich mag .NET-Aufzählungen viel besser.
Brian J
0

NaiveBot (in Ruby)

Hier ist ein sehr simpler Bot, um das Ei ins Rollen zu bringen (wir wollen diese 7 Einreichungen schnell treffen, oder?). Mein Ruby ist nicht sehr idiomatisch, so dass dieser Code die richtigen Rubyisten vor Schmerzen zusammenzucken lässt. Lesen Sie auf eigenes Risiko.

input = $<.read
$data = input.split("\n")

def is_egg x, y
    $data[y+2][x+2] == 'o'
end

def is_wall x, y
    $data[y+2][x+2] == '#'
end

def is_empty x, y
    $data[y+2][x+2] == ' '
end

def is_player x, y
    $data[y+2][x+2] == '*'
end

if (is_egg(-2,-2) || is_egg(-2,-1) || is_egg(-1,-2)) && !is_wall(-1,-1) || is_egg(-1,-1)
    dir = 1
elsif is_egg(0,-2) && !is_wall(0,-1) || is_egg(0,-1)
    dir = 2
elsif (is_egg(2,-2) || is_egg(2,-1) || is_egg(1,-2)) && !is_wall(1,-1) || is_egg(1,-1)
    dir = 3
elsif is_egg(2,0) && !is_wall(1,0) || is_egg(1,0)
    dir = 4
elsif (is_egg(2,2) || is_egg(2,1) || is_egg(1,2)) && !is_wall(1,1) || is_egg(1,1)
    dir = 5
elsif is_egg(0,2) && !is_wall(0,1) || is_egg(0,1)
    dir = 6
elsif (is_egg(-2,2) || is_egg(-2,1) || is_egg(-1,2)) && !is_wall(-1,1) || is_egg(-1,1)
    dir = 7
elsif is_egg(-2,0) && !is_wall(-1,0) || is_egg(-1,0)
    dir = 8
else
    dir = rand(8) + 1
end

attack = 'N'
puts "#{dir}
#{attack}
"

Laufen Sie mit ruby naivebot.rb.

Ich codiere einfach ein paar Fälle, in denen ein Ei sichtbar ist und nicht durch eine Wand blockiert wird. Es geht nicht einmal um das nächste Ei, sondern um den ersten Schritt, der Sinn macht. Wird kein solches Ei gefunden, macht der Bot einen zufälligen Zug. Es ignoriert alle anderen Spieler und greift niemals an oder kontert.

Martin Ender
quelle
0

WallFolower

(absichtliches Wortspiel) in Python 3 :

import sys
import random

#functions I will use
dist       = lambda p1,p2: max(abs(p2[1] - p1[1]), abs(p2[0] - p1[0]))
distTo     = lambda p    : dist((2,2), p)
cmp        = lambda x,y  : (x > y) - (x < y)
sgn        = lambda x    : (-1,0,1)[(x>0)+(x>=0)]
move       = lambda p    : (sgn(p[0] - 2), sgn(p[1] - 2))
unmove     = lambda p    : (p[0] * 2 + 2, p[1] * 2 + 2)
outputmove = lambda p    : (1,2,3,8,9,4,7,6,5)[(sgn(p[0] - 2) + 1) + 3*(sgn(p[1]-2) + 1)]
def noeggfinish(move):
    print(outputmove(unmove(move)))
    print('ACN'[random.randint(0, 2)])
    print("1"+move)
    sys.exit(0)

#beginning of main body
view    = [list(l) for l in map(input, ('',)*5)] #5 line input, all at once.
memory  = input() #currently used only as last direction moved in a tuple
eggs    = []
enemies = []
for y in range(5):
    for x in range(5):
        if   view[y][x] == 'o': eggs    += [(x,y)]
        elif view[y][x] == '*': enemies += [(x,y)]

eggs.sort(key = lambda p:distTo(p)) #sort by how close to me they are.

tiedeggs = []
end = 0
for egg in eggs[:]:
    if end:break
    for enemy in enemies:
        exec({
            -1: 'eggs.remove(egg)',
             0: 'tiedeggs += egg',
             1: 'end=1'
        }[cmp(dist(enemy, egg), distTo(egg))])
        if end:break
if eggs:
    print(outputmove(eggs[0]))
    print('N')              #no attack here
    print("0"+move(eggs[0]))
    sys.exit(0)
elif tiedeggs:
    print(outputmove(tiedeggs[0]))
    print('N')              #no attack here
    print("0"+move(tiedeggs[0]))
    sys.exit(0) 
#now there are no eggs worth going for
#do a LH wall follow

lastmove = eval(memory[1:]) #used to resolve ambiguity
if lastmove[0] and lastmove[1]:
    lastmove[random.randint(0,1)] = 0 #disregard diagonal moves
if eval(memory[0]):
    exec("check=view[%n][%n]"%{(0,-1):(0,0),(1,0):(4,0),(0,1):(4,4),(-1,0):(0,4)}[lastmove])
    if check == '#':
        noeggfinish(lastmove)
    else:pass
#currently unimplemented
#move randomly
noeggfinish(tuple([(x,y) for x in [-1,0,1] for y in [-1,0,1] if (x,y) != (0,0)))

Geht zu einem Ei, wenn ein Ei in Sicht ist, aber nur, wenn es näher an diesem Ei liegt als ein anderer Roboter. Wenn es in der Ferne ein Unentschieden gibt, geht es trotzdem. Ansonsten folgt eine linke Wand (derzeit nicht gut implementiert).

Müssen noch Arbeiten an der Wand folgen, aber ich werde dies trotzdem hier posten.

Justin
quelle
1
Wenn ich Ihren Bot mit dem tester.py laufen, bekomme ich diesen Fehler in der Konsole: pastebin.com/cT5xGdSW
starbeamrainbowlabs
Hier gilt das gleiche. Könnten Sie das untersuchen? Ich möchte meinen neuen Bot dagegen testen.
Martin Ender
@ m.buettner Was passiert , wenn Sie ändern sys.exit(0)zu exit(0)? Außerdem muss ich daran arbeiten (im Moment nimmt es an, dass es sich um ein `` handelt), aber ich habe nicht wirklich die Zeit. Wenn ich Zeit habe, werde ich kommen und das regeln.
Justin
@Quincunx daran hat sich leider nichts geändert.
Martin Ender