Wielkie polowanie na Wumpusa

22

KOMPLETNY

Sezon Wumpus zakończył się, a wraz z nim życie wielu okrutnych Wumpusów i odważnego Łowcy. Jak również niektórzy tchórzliwi, niemoralni i wręcz głupi Łowcy. Ale pod koniec dnia NascarHunter autorstwa dr Heckle'a przyniósł najwięcej łupów i chwały. Pozdrawiamy cię, och, dzielny ... kierowco?

W Wumpusach jest otwarty sezon, a łowcy z całego świata gromadzą się w Jaskiniach Wumpus, aby spróbować wzbogacić się o cenne Pelty Wumpusa.

Gra

Oparty na klasycznej grze Hunt the Wumpus , z kilkoma odmianami.

Mapa

Dwunastościan . Istnieje 20 pokoi, każde połączone z 3 innymi pokojami, tworząc w zasadzie 3 pierścienie z mostami pomiędzy nimi.

Wumpus

Wumpus to mistyczna bestia. Nikt nie jest pewien, jak to wygląda, ale wszyscy zgadzają się, że jest okrutny. Wumpus mieszka w jaskiniach i lubi jeść martwe rzeczy. Jeśli w jaskini obok Wumpusa znajduje się zwłoki, przeprowadzi się tam i je zje. Jeśli Wumpus zdoła przenieść się do jaskini zawierającej łowców, zabije je również. Jeśli Wumpus usłyszy strzałę w jego pobliżu, wpadnie w panikę i wpadnie do przypadkowego pokoju.

Cechy opcjonalne : Są one obecnie uwzględnione, aby gra była bardziej interesująca, ale można ją usunąć na popularne żądanie, jeśli dodają zbyt wiele losowości.

Wściekły Wumpus: Jeśli Wumpus zostanie postrzelony, ma 20% szans na przeżycie i szaleństwo przez 3 dni. Podczas szaleństwa będzie losowo poruszał się dwa razy dziennie, ale nadal będzie przyciągał zwłoki. Po 3 dniach umrze. Drugi strzał zabije Wumpusa.

Wędrujący Wumpus: Każdego dnia, jeśli nic więcej nie uruchamia Wumpusa, ma on 25% szansy na ruch.

Łowcy

Jednocześnie do jaskini może wejść czterech myśliwych. Jaskinie są ciemne, więc łowcy nie widzą, ale mogą użyć innych zmysłów. Łowcy mogą wąchać Wumpusa w sąsiednim pokoju, wąchać zwłoki w sąsiednim pokoju, słyszeć innych myśliwych poruszających się w sąsiednich pokojach i słyszeć, czy strzała trafi w sąsiedni pokój.

Łowcy mają dwie akcje: strzelaj lub poruszaj się. Łowca może wystrzelić strzałę do sąsiedniego pokoju lub własnego pokoju i poruszać się podobnie.

Rozgrywka

W każdej rundzie łowcy najpierw zauważą otoczenie, a następnie wykonają jeden ruch. Ruch następuje przed strzałami, więc jeśli strzała zostanie wystrzelona do pokoju, z którego wyprowadza się myśliwy, myśliwy przeżyje. Po wykonaniu wszystkich ruchów łowcy strzały są oceniane. Jeśli pojedynczy mieszkaniec i strzała znajdują się w tym samym pomieszczeniu, zostanie on zastrzelony i umrze. Jeśli dwóch lub więcej osób dzieli pokój, jeden zostanie losowo trafiony i umrze. Uwaga: Zwłoki są mieszkańcami, więc martwe ciało może służyć jako częściowa tarcza.

Po wszystkich ruchach łowcy Wumpus zareaguje. Jeśli myśliwy wprowadził się do pokoju z Wumpusem, Wumpus go zje. Jeśli Wumpus się poruszy, zje również mieszkańców nowego pokoju.

Po 100 dniach, jeśli myśliwi nie zabiją Wumpusa lub padną ofiarą, umrą z głodu w jaskiniach.

Kod

Cały kod źródłowy można znaleźć tutaj . Wszystkie zgłoszenia powinny być w Javie, chyba że ktoś chce mi napisać adapter stdIn / stdOut;)

Boty powinny rozszerzyć klasę Łowca. Aby nazwać Łowcę, dodaj konstruktor bez parametrów, które ustawiają pole nazwy. Aby odpowiedzieć, zastąp funkcję getResponse. W tej funkcji, w każdej turze, będziesz otrzymywać tablicę 5 booleanów, która mówi ci o twoim otoczeniu.

status 0 = „Pachniesz wumpusem”

status 1 = „Słyszysz innego łowcę”

status 2 = „Czujesz zwłoki”

status 3 = „Usłyszysz stukot strzałki”

status 4 = „Czujesz innego łowcę w tym samym pokoju co ty”

Klasa Hunter ma 2 miejsca: nextMove i nextDirection, które używają odpowiednio enums Move i Direction. Ruch może być MOVE lub SHOOT, kierunek może być LEWY, PRAWY, BACK lub TUTAJ. Kierunki są spójne, co oznacza, że ​​powrót zawsze spowoduje powrót do poprzedniego pokoju, w którym byłeś, a jeśli wchodzisz z tego samego pokoju, LEWO i PRAWO zawsze będą takie same. Jeśli jednak wejdziesz z innego kierunku, LEWO i PRAWO zabiorą Cię w różne miejsca.

Zapraszam również do wdrożenia własnych metod. Pamięć jest trwała przez cały turniej, co oznacza, że ​​twój łowca zostanie skonstruowany tylko raz. Jednak na początku każdej rundy wywoływana jest metoda newGame (), aby powiadomić myśliwego o rozpoczęciu nowej gry.

Punktacja

Jednocześnie rywalizuje czterech łowców. Jeśli zostanie zabity, skóra Wumpusa jest warta 60 punktów, równo podzielona pomiędzy wszystkich myśliwych, którzy przeżyli. W pełni okrągły styl robin, więc każda kombinacja 4 łowców będzie grać razem.

Uwzględniono 5 przykładowych Łowców: 4 z bardzo podstawową funkcjonalnością i jedną, która pozwala na wkład użytkownika do gry, do celów testowych.

Jeśli masz jakieś sugestie / prośby, daj mi znać!

Koniec jest w zasięgu wzroku!

Światowa populacja Wumpus jest ścigana w alarmującym tempie. Ustawa o ochronie naszych wumpusów ma zostać uchwalona w środę, 17 czerwca. Po tej dacie nie będzie więcej łowców w jaskiniach, a zwycięzca zostanie wybrany.

Tablica wyników

Uwaga : przepraszam, w kodzie był błąd, który mógł powodować, że Łowcy nie żyli w wielu grach. Po naprawieniu nie zmienia to bardzo ogólnie ogólnych rankingów, ale w dużej mierze zmienia statystyki.

Dostępne są wyniki, uruchamiając każdy zestaw myśliwego w 1000 grach. NascarHunter i FullCoverageHunter przewodzą paczce i chociaż dodatek AntiHunter zapewnił Wumpusom 2% doładowania, nadal trzęsą się z nóg przy 32% współczynniku przeżycia tego rodzaju. Strzały od innych myśliwych są bardziej niż kiedykolwiek największym zagrożeniem w jaskiniach.

1. NascarHunter : 16557175 (17.08)
2. FullCoverageHunter : 15195545 (15.68)
3. Trig : 14459385 (14.92)
4. Idomeneus : 13428570 (13.85)
5. Eats Shoots and Leaves : 12763945 (13.17)
6. WalkingIdiot : 12329610 (12.72)
7. NealHunter : 12287140 (12.68)
8. Unnamed : 11013720 (11.36)
9. MonsterHunter : 10686035 (11.02)
10. Pacer : 9187000 (9.48)
11. Badger : 9042570 (9.33)
12. Stay : 8721210 (9.0)
13. Emo Wumpus : 7831050 (8.08)
14. Paranoid : 7722965 (7.97)
15. Huddle : 7465420 (7.7)
16. ElmerFudd : 7245995 (7.47)
17. Laomedon : 6963845 (7.18)
18. Pacifist : 6944960 (7.16)
19. ScaredyCat : 6937370 (7.15)
20. Wumpus : 114170 (0.11)



Total rounds: 4845000
Humans killed by arrows: 5289674 (1.09)
Humans dead by starvation: 1046024 (0.21)
Humans killed by wumpus: 1887634 (0.38)
Wumpus victories: 1563372 (0.32)
Kain
źródło
1
Czy możesz trafić innego myśliwego strzałą?
MegaTom
1
Yessir lub ty, jeśli strzelisz w TUTAJ
Cain
1
Zamiast tablicy dla 5 logów, dlaczego nie przekazać intwartości 0-31? Jesteśmy tu dużymi chłopcami, możemy wykonywać operacje bitowe :)
DoctorHeckle
1
@DoctorHeckle Jasne, że jesteśmy, ale nadal jest bardziej przyjazne dla programistów, aby mieć tablicę niż pojedynczy int ^^.
Katenkyo
1
W przypadku strzał i zwłok, jeśli ktoś znajduje się w tym samym pomieszczeniu, co ty, masz ten sam status, jakby był obok. Łowcy są jedynymi, którzy mogą odróżnić przebywanie obok pokoju lub w pokoju.
Cain

Odpowiedzi:

11

NascarHunter

Nie ma w tym wiele logiki. Jego zasady są proste: skręć w lewo, spaloną ziemię, powtórz. I, hej, może mieć szczęście!

8 czerwca edycja:

Dodano dodatkową logikę do Nascar, aby uwzględnić przyleganie do Wumpusa w stosunku do jego ostatniego ruchu. Rozważ to jako pit stop, aby pozostać w temacie. Jeśli wyczuje Wumpusa po zestrzeleniu korytarza, to musiał przybyć do jednego z dwóch sąsiednich pokoi, ponieważ umarłby na strzale, który właśnie wziął myśliwy. Skutecznie daje albo Wumpus 2 tury do życia, jeśli nie ruszy się ponownie, albo Nascar 1 tury do życia, jeśli stoi na zwłokach. Uwzględnia również trzecią opcję, jeśli jest to pierwsza tura, ale tylko raz. W końcu prześlę port do FCH, zajęty.

package Hunters;

import Mechanics.*;

public class NascarHunter extends Hunter {

    private int state;
    private boolean shootHall;
    private boolean newGame;

    public NascarHunter(){

        name = "NascarHunter";
        state = 0;
        shootHall = true;
        newGame = true;

    }

    public void newGame(){

        state = 0;
        newGame = true;

    }

    public void getResponse(boolean[] status){

        // Wumpus about - stand and deliver
        if( status[0] ){

            nextMove = Move.SHOOT;

            switch( state ){

            case 0: // Must be in either Right or Back
                if(newGame){

                    // try Left if this is the first turn, just in case
                    nextDirection = Direction.LEFT;
                    newGame = false;

                }
                else if(shootHall) nextDirection = Direction.BACK;
                else               nextDirection = Direction.RIGHT;
                shootHall = !shootHall;
                break;
            case 2: // Must be in either Left or Back
                if(newGame){

                    // try Right if this is the first turn, just in case
                    nextDirection = Direction.RIGHT;
                    newGame = false;

                }
                else if(shootHall) nextDirection = Direction.BACK;
                else               nextDirection = Direction.LEFT;
                shootHall = !shootHall;
                break;
            default: // Must be in either Left or Right
                if(newGame){

                    // try Back if this is the first turn, just in case
                    nextDirection = Direction.BACK;
                    newGame = false;

                }
                else if(shootHall) nextDirection = Direction.RIGHT;
                else               nextDirection = Direction.LEFT;
                shootHall = !shootHall;
                break;

            }

        }else{

            // disregard state, shove out and light 'em up!
            switch( state ){

            case 0: // move out
                nextMove = Move.MOVE;
                nextDirection = Direction.LEFT;
                state++;
                break;
            case 1: // shoot right
                nextMove = Move.SHOOT;
                nextDirection = Direction.RIGHT;
                state++;
                break;
            case 2: // shoot behind
                nextMove = Move.SHOOT;
                nextDirection = Direction.BACK;
                state++;
                break;
            case 3: // shoot left
                nextMove = Move.SHOOT;
                nextDirection = Direction.LEFT;
                state = 0;
                break;

            }

        }

    }

}

FullCoverageHunter

Podąża za tym samym credo NascarHunter, ale zmienia na przemian jego ścieżkę, co gwarantuje utworzenie pętli o długości 10 unikalnych pokoi. Ponieważ każdy pokój jest wyjątkowy, a my strzelamy w każdym kierunku na pokój, wszystkie pokoje zostają zwolnione. Dotyczy to każdego pokoju początkowego (postulowane przez mojego kumpla Neala, dzięki Neal!). Dodekaedry są takie fajne!

Chciałbym zauważyć, że jest to coś innego niż nasz przyjaciel, MonsterHunter, ponieważ nie próbuje żadnych sztuczek ani prawdziwych „taktyk”. Siłą tego jest fakt, że każde pomieszczenie zostaje ponownie zwolnione: rozwiązanie brutalnej siły. Ma to teoretyczną nogę w NascarHunter, ponieważ Nascar trafi tylko 10 z 20 pokoi, zajmując tylko połowę powierzchni.

11 czerwca edycja:

Dodano wzorzec logiki wykrywania Wumpus z NascarHunter. Powinien obiektywnie poprawić wynik.

package Hunters;

import Mechanics.*;

public class FullCoverageHunter extends Hunter {

    private int state;
    private boolean headLeft;
    private boolean shootHall;
    private boolean newGame;

    public FullCoverageHunter(){

        name = "FullCoverageHunter";
        state = 0;
        headLeft = false;
        shootHall = true;

    }

    public void newGame() {
        state = 0;
        headLeft = false;
        newGame = true;
    }


    public void getResponse(boolean[] status){

        // Wumpus about - stand and deliver
        if( status[0] ){

            nextMove = Move.SHOOT;

            switch( state ){

            case 0: // Must be in either Right or Back
                if(newGame){

                    // try Left if this is the first turn, just in case
                    nextDirection = Direction.LEFT;
                    newGame = false;

                }
                else if(shootHall) nextDirection = Direction.BACK;
                else               nextDirection = Direction.RIGHT;
                shootHall = !shootHall;
                break;
            case 2: // Must be in either Left or Back
                if(newGame){

                    // try Right if this is the first turn, just in case
                    nextDirection = Direction.RIGHT;
                    newGame = false;

                }
                else if(shootHall) nextDirection = Direction.BACK;
                else               nextDirection = Direction.LEFT;
                shootHall = !shootHall;
                break;
            default: // Must be in either Left or Right
                if(newGame){

                    // try Back if this is the first turn, just in case
                    nextDirection = Direction.BACK;
                    newGame = false;

                }
                else if(shootHall) nextDirection = Direction.RIGHT;
                else               nextDirection = Direction.LEFT;
                shootHall = !shootHall;
                break;

            }

        }else{

            // disregard state, shove out (in an alternating fashion!) and light 'em up!
            switch( state ){

            case 0: // move out, change alternation state
                nextMove = Move.MOVE;
                if(headLeft) nextDirection = Direction.LEFT;
                else         nextDirection = Direction.RIGHT;
                state++;
                headLeft = !headLeft;
                break;
            case 1: // shoot into non-exit path
                nextMove = Move.SHOOT;
                if(headLeft) nextDirection = Direction.RIGHT;
                else         nextDirection = Direction.LEFT;
                state++;
                break;
            case 2: // shoot behind
                nextMove = Move.SHOOT;
                nextDirection = Direction.BACK;
                state++;
                break;
            default: // shoot into next room,
                nextMove = Move.SHOOT;
                if(headLeft) nextDirection = Direction.LEFT;
                else         nextDirection = Direction.RIGHT;
                state = 0;
                break;

            }

        }

    }

}

Daj mi znać, jeśli wystąpią jakieś błędy, pakiet nie grał dobrze z moim IDE :(

DoctorHeckle
źródło
1
Jestem prawie pewien, że powinno się to nazywać MadMaxHunter, ponieważ nie przypominam sobie zbyt wielu wyścigów NASCAR z ostrzałem między pojazdami. Wydaje się, że dobrze sobie radzi!
Ralph Marshall
Musiałem umieścić nawiasy wokół headLeft w instrukcjach if, aby FullCoverageHunter działał. Oba boty radzą sobie bardzo dobrze - NascarHunter jest nieco lepszy
euanjt
Zmienna newGame w FullCoverageHunter wydaje się nigdy nie zostać zadeklarowana. Dodałem prywatną wartość logiczną newGame i ustawiłem ją na true w metodzie newGame (), czy to jest to, co zamierzałeś?
Cain
@Cain whoops! Tak, duży niedopatrzenie ode mnie, zredaguję to tutaj, mój zły.
DoctorHeckle,
7

Borsuk

On nie lubi gości.

package Hunters;

import Mechanics.*;

public class Badger extends Hunter {

    public Badger(){
        name = "Badger";
    }

    @Override
    public void getResponse(boolean[] status){
        nextMove = Move.SHOOT;
        nextDirection = Direction.values()[((int) (Math.random() * 3))];
    }
}
Numer jeden
źródło
6

Elmer Fudd

„Ciii. Bądź bardzo cichy, poluję na Wumpusa”

Elmer jest skupiony na zdobyczy i ignoruje wszystko oprócz zwłok i Wumpusa. Próbuje znaleźć zwłoki, potem się wycofuje i zaczyna strzelać. Jeśli poczuje Wumpusa, cofnie się, a jeśli nadal będzie go wąchał, strzeli.

Przepraszam wszystkich programistów Java, jest to prawdopodobnie wyjątkowo brzydkie, pełne błędów składniowych i prawdopodobnie popsułem moją logikę.

package Hunters;

import Mechanics.*;

public class ElmerFudd extends Hunter {

    private state int;
    private previousDir int;

    public ElmerFudd(){
        name = "ElmerFudd";
    }

    public void newGame() {
        state=0;
        previousDir = Direction.LEFT;
    }

    public void getResponse(boolean[] status){

        nextMove = Move.MOVE;
        switch (previousDir) {
            case Direction.LEFT:
                nextDirection = Direction.RIGHT;
                break;
            case Direction.RIGHT:
                nextDirection = Direction.LEFT;
                break;
        }   

        if(status[2]&&state==0) {
            state = 1;
            return;
        }

        if(state==1){
            if(status[2]){
                state=2;
            };
            nextDirection = Direction.BACK;
            return;
        }

        if(state==2){
            nextMove = Move.SHOOT;
            nextDirection = Direction.BACK;
            return;
        }

        if(state==3&&status[0])
            nextMove = Move.SHOOT;
            nextDirection = Direction.BACK;
            return;
        }

        if(state==3) {
            state = 0;
        }

        if(status[0]){
            state=3;
            nextDirection = Direction.BACK;
        }

    }
}

Pacyfista

Ten facet jest moralnie przeciwny wszelkiemu sportowi krwi i zastanawia się, jak się w ogóle pojawił w tej sytuacji. Ucieknie od jakiegokolwiek kontaktu i nigdy nie oddaje strzału.

package Hunters;

import Mechanics.*;

public class Pacifist extends Hunter {


    public Pacifist(){
        name = "Pacifist";
    }

    public void getResponse(boolean[] status){
        nextMove = Move.MOVE;
        if(status[0]||status[1]||status[2]||status[3]||status[4]){
            nextDirection = Direction.values()[((int) (Math.random() * 3))];
            return;
        }
        nextDirection = Direction.HERE;
    }
}
MickyT
źródło
1
Myślę, że to może zadziałać. Wszystko, co musisz zrobić w grze, to mieć nadzieję, że ktoś dostanie wumpusa, zanim go dostanie i otrzymasz pełny kredyt.
Ralph Marshall
1
To był ogólny pomysł. Niech inni
wykonają
1
Właśnie dlatego czekałem na to, aby to zakodować, mimo że najpierw o tym pomyślałem :-)
Mawg
5

Łowca potworów

Polujemy na potwora i mamy 4 lata ... Przypomina mi to moją ulubioną grę! Ten myśliwy przejdzie większą część mapy, poruszając się naprzemiennie w lewo-prawo, a jeśli Wumpus będzie w pobliżu, zwabi go, cofając się, aby móc dokładnie określić, gdzie on jest.

Mogłem pozbyć się lastDirection, ale zachowuję semantykę i czytelność :). W rzeczywistości umiera dość często, ale kontroler często umieszcza 2/3 łowcy w tym samym pokoju na początku, a często w pobliżu Wumpusa (może być również w tym samym pokoju) ... więc insta death ^^ '.

package Hunters;

import Mechanics.*;

public class MonsterHunter extends Hunter 
{
    private Direction lastDirection=Direction.HERE;
    private boolean[] lastStatus=new boolean[5];
    private int   shooted=0;
    private boolean   walkMode=true;
    private int         turnStayed=0;

    public MonsterHunter(){
        super();
        name = "MonsterHunter";
    }

    @Override
    public void getResponse(boolean[] status)
    {
        if(status[0])
        {
            if(!lastStatus[0]||shooted==0)
            {
                nextDirection=(walkMode)?Direction.RIGHT:Direction.LEFT;;
                nextMove=Move.SHOOT;
            }
            else if(lastStatus[0]&&shooted==1)
            {
                nextDirection=Direction.BACK;
                nextMove=Move.MOVE;
            }
            else
            {
                nextDirection=Direction.BACK;
                nextMove=Move.SHOOT;
            }
        }

        else if(status[2])
        {
            nextMove=Move.MOVE;
            if(Math.random()*6<turnStayed)
            {
                nextDirection=Direction.HERE;
                turnStayed++;
            }
            else
                nextDirection=(walkMode)?Direction.RIGHT:Direction.LEFT;
        }
        else
        {
            nextMove=(!status[1]&&Math.random()<0.5)?Move.MOVE:Move.SHOOT;
            nextDirection=(walkMode)?Direction.RIGHT:Direction.LEFT;
        }

        if(nextMove==Move.MOVE)
        {
            if(shooted>0)
                walkMode=walkMode^(shooted>0);
            if(lastStatus[0]&&shooted==1)
                shooted++;
            else
                shooted=0;
            lastDirection=nextDirection;
        }
        else
            shooted++;
        for(int i=0;i<status.length;i++)
            lastStatus[i]=status[i];
    }
}
Katenkyo
źródło
Dziękujemy za zwrócenie uwagi, że kontroler jest naprawiony, dzięki czemu każdy z mieszkańców ma niepowtarzalny początek
Cain
4

PacingHunter

Tam iz powrotem, pomiędzy pokojami. jeśli pachnie Wumpusem lub słyszy gracza, strzela w lewo, a potem w prawo. jeśli Wumpus jest obok niego na początku, to strzela do pokoju, do którego się przeprowadzi.

package Hunters;

import Mechanics.Direction;
import Mechanics.Hunter;
import Mechanics.Move;

public class PacingHunter extends Hunter {

    int state = 0;//Pacing
    int turn = 0;

    public PacingHunter() {
        name = "Pacer";
    }

    public void newGame() {
        turn =  0;
        state = 0;
    }

    public void getResponse(boolean[] status){
        turn += 1;
        if(state == 0 && status[0] && turn == 1){
            nextMove = Move.SHOOT;
            nextDirection = Direction.BACK;
            return;
        }
        if(state == 0 &&(status[0] || status[1])){
            nextMove = Move.SHOOT;
            nextDirection = Direction.LEFT;
            state = 1;
            return;
        }
        if(state == 1 && (status[0] || status[1])){
            nextMove = Move.SHOOT;
            nextDirection = Direction.RIGHT;
            state = 0;
            return;
        }
        if(status[1] && state == 0){
            nextMove = Move.SHOOT;
            nextDirection = Direction.BACK;
            state = 0;
            return;

    }
    nextMove = Move.MOVE;
    nextDirection = Direction.BACK;
}

}

MegaTom
źródło
4

ScaredyCat

ScaredyCat boi się wszystkiego. Jeśli pachnie wumpusem lub zwłokami albo słyszy strzałę lub łowcę, biegnie w losowym kierunku. W przeciwnym razie po prostu strzela strzały w losowych kierunkach.

package Hunters;

import Mechanics.*;

public class ScaredyCat extends Hunter {

    public ScaredyCat(){
        name = "ScaredyCat";
    }

    @Override
    public void getResponse(boolean[] status){

        for(int i=0; i<status.length; i++)
            if(status[i])
            {
                nextMove = Move.MOVE;
                nextDirection = Direction.values()[((int) (Math.random() * 3))];
                return;
            }

        nextMove = Move.SHOOT;
        nextDirection = Direction.values()[((int) (Math.random() * 3))];
    }
}
Spikatrix
źródło
6
Lol Nie wiem, czy to było zamierzone, ale przestraszy się, strzelając strzałami, a następnie uciekając.
Cain
4

Zjada pędy i liście

W przeciwieństwie do Pandy sławy książki gramatycznej, ten myśliwy tak naprawdę nic nie je, ale albo strzelamy, jeśli jest Wumpus, albo wyruszamy na szlak, który, mam nadzieję, powstrzyma nas przed chodzeniem w kółko.

package Hunters;

import java.util.Random;

import Mechanics.Hunter;
import Mechanics.Move;
import Mechanics.Direction;
import Mechanics.Room;

public class EatsShootsAndLeaves extends Hunter {

    private static Direction [] allDirections = { Direction.LEFT, Direction.RIGHT, Direction.BACK, Direction.HERE };
    private static Direction [] movePath = { Direction.LEFT, Direction.RIGHT, Direction.LEFT, Direction.BACK, Direction.RIGHT, Direction.BACK };

    private static int numGames = 0;
    private static int totalLife = 0;

    private static class RoomInfo  {

        public boolean hasWumpus = false;
        public boolean hasLocalHunter = false;
        public boolean hasNeighborHunter = false;
        public boolean hasCorpse = false;
        public boolean hasArrow = false;
        public RoomInfo(Room r) {
            boolean [] status = r.getInfo();
            hasWumpus = status[0];
            hasNeighborHunter = status[1];
            hasCorpse = status[2];
            hasArrow = status[3];
            hasLocalHunter = status[4];
        }

        public String toString() {
            return new String("Status: "
                              + (hasWumpus ? "Wumpus " : "")
                              + (hasNeighborHunter ? "Close Hunter " : "")
                              + (hasCorpse ? "Corpse " : "")
                              + (hasArrow ? "Arrow " : "")
                              + (hasLocalHunter ? "Local Hunter " : ""));
        }
    }

    int turnsAlive = 0;
    int shots = 0, moves = 0;

    public EatsShootsAndLeaves(){
        name = "Eats Shoots and Leaves";
    }

    public void newGame() {

        totalLife += turnsAlive;
        numGames++;

        turnsAlive = shots = moves = 0;
    }

    public void getResponse(boolean[] status){

        turnsAlive++;

        RoomInfo info = new RoomInfo(this.getRoom());
        if (info.hasNeighborHunter || info.hasWumpus) {
            nextMove = Move.SHOOT;
            nextDirection = allDirections[shots++ % 3];
        } else {
            nextMove = Move.MOVE;
            nextDirection = movePath[moves++ % movePath.length];
        }
    }
}
Ralph Marshall
źródło
3

Idomeneus

Idomeneus jest dość prosty - jeśli w pobliżu znajduje się Wumpus lub inny myśliwy, wszędzie strzela ogniem i modli się, by bogini polowania była po jego stronie. Jeśli jest blisko zwłok, czeka na Wumpusa. Nie lubi innych łowców i ucieknie, jeśli zaczną strzelać do niego w pobliżu lub jeśli znajdą się w tym samym pokoju co on. Wreszcie, jeśli się nudzi, losowo krąży po wiecznych korytarzach.

package Hunters;
import Mechanics.Direction;
import Mechanics.Hunter;
import Mechanics.Move;
import java.util.Random;



public class Idomeneus extends Hunter
{
    int direction;
    Random r;
    public Idomeneus()
    {
        super();
        name = "Idomeneus";
        direction = 0;
        r = new Random();
    }

    @Override
    public void getResponse(boolean[] status){
        boolean wumpusNear = status[0];
        boolean hunterNear = status[1];
        boolean corpseNear = status[2];
        boolean arrowNear = status[3];
        boolean hunterHere = status[4];
        direction++;

        if(wumpusNear)
        {
            //ATTACK!!!
            nextMove = Move.SHOOT;
            nextDirection = Direction.values()[direction%3];
        }
        else if(hunterHere || arrowNear)
        {
            //Run away
            nextMove = Move.MOVE;
            nextDirection = Direction.values()[r.nextInt(3)];
        }
        else if(hunterNear)
        {
            //ATTACK!!!
            nextMove = Move.SHOOT;
            nextDirection = Direction.values()[direction%3];
        }
        else if(corpseNear)
        {
            //Stay and wait...
            nextMove = Move.MOVE;
            nextDirection = Direction.HERE;
        }
        else
        {
            //wander around
            nextMove = Move.MOVE;
            nextDirection = Direction.values()[r.nextInt(3)];
        }

    }

    public void newGame(){}



}
euanjt
źródło
Uważaj: według @Cain możesz strzelać do siebie, jeśli strzelasz do swojego pokoju.
DoctorHeckle,
3

Emo Wumpus (łowca)

Emo Wumpuses (związane z Wilkami Emo, które czasami używają broni i samolotów latających) ) nienawidzą wszystkiego (szczególnie Javy). Nie rozróżniają Łowców i Wumpusów i próbują zastrzelić ich jednakowo. Nienawidzą także kierowców Nascar i zawsze będą strzelać dobrze. Jeśli w pobliżu nie ma nikogo, kto mógłby strzelać, porusza się w prawo, ale zrobi to tylko trzynaście razy z rzędu, zanim jeszcze bardziej wpadnie w depresję z powodu bycia samemu i spróbuje się zastrzelić (trzynaście to pechowa liczba). Na 99. etapie, jeśli nadal żyją, spróbują się zastrzelić, ponieważ głód jest tak kiepskim sposobem na śmierć.

Wumpusy są większe (i cięższe) niż Wilki, ale ten wciąż głodował do 424 bajtów (w przeciwieństwie do potężnego 2,72 kb NascarHunter).

package Hunters;import Mechanics.*;public class EmoWumpus extends Hunter{private int c, t;public EmoWumpus(){name="Emo Wumpus";this.c=0;this.t=0;}public void newGame(){this.c=0;this.t=0;}public void getResponse(boolean[] status){nextMove=Move.SHOOT;if(c<13 && t<100){if(status[0]||status[1]){nextDirection=Direction.RIGHT;}else{nextMove=Move.MOVE;nextDirection=Direction.RIGHT;c++;}}else{nextDirection=Direction.HERE;}t++;}}

Dlaczego nie popełnisz samobójstwa? Emo Wumpuses wierzą, że jedynym dobrem, który może uczynić, jest zakończenie cierpienia innych przed samobójstwem. Dlatego zabiją wszystko, co mogą, zanim nadejdzie ich czas na śmierć.

Wumpus? (Anti-Hunter)

Um, co robi Wumpus na liście łowców? Ten facet bardzo się wkurzył, że ludzie zabijają jego krewnych, więc postanowił przebrać się za jednego z nich i dołączyć do polowania. Jego głównym celem jest zabijanie myśliwych. Próbuje ukryć się przy zwłokach, co da mu szansę na tarczę przed łowcami. Jeśli w pobliżu nie ma żadnych łowców, będzie poruszał się w określonym kierunku, dopóki nie zostaną wykryci łowcy, w takim przypadku spróbuje ich zabić, zanim ruszy w innym kierunku.

Niestety większość Wumpusów jest głupia i nadal będzie próbowała go zabić. Niezależnie od tego uważa, że ​​jego ofiary są niezbędne dla dobra Wumpusów wszędzie.

package Hunters;

import Mechanics.*;

public class AntiHunter extends Hunter {

private boolean left;

public AntiHunter() {
    name = "Wumpus";
    this.left = true;
}

public void newGame() {
    this.left = true;
}

public void getResponse(boolean[] status) {
    if(status[4]) {
        nextMove = Move.SHOOT;
        nextDirection = Direction.HERE;
    }
    else if(status[2] || status[1]) {
        nextMove = Move.SHOOT;
        if(this.left) {
            this.left = false;
            nextDirection = Direction.LEFT;
        }
        else {
            this.left = true;
            nextDirection = Direction.RIGHT;
        }
    }
    else {
        nextMove = Move.MOVE;
        if(this.left)
            nextDirection = Direction.LEFT;
        else
            nextDirection = Direction.RIGHT;
    }
}

}

Michael Brandon Morris
źródło
1
Już nie śmieszne.
Martin Ender
Dobrze, że to nie jest golf golfowy. Zastanawiałem się, ile czasu minie, zanim pojawi się bot Emo, lol.
DoctorHeckle,
@Martin Pamiętaj, że to nie tylko samobójstwo. Spośród botów dostępnych do testowania nie zajął on ostatniej pozycji.
Michael Brandon Morris,
1
EmoSolution jest zawsze zabawny!
Mawg,
2

Laomedon

Laomedon wędruje bez celu, próbując znaleźć zwłoki. Po znalezieniu jednego i znalezieniu go, pozostaje w tym samym miejscu obok zwłok. Kiedy wącha Wumpusa, strzela do pokoju Zwłok.

package Hunters;
import Mechanics.Direction;
import Mechanics.Hunter;
import Mechanics.Move;
public class Laomedon extends Hunter {
    private enum status
    {
        START,
        SEARCHED_LEFT,
        SEARCHED_RIGHT,
        INITIAL_CORPSE_LEFT,
        INITIAL_CORPSE_RIGHT,
        SMELT_CORPSE,
        CORPSE_BEHIND,
        CORPSE_LEFT
    }

    status myState;
    public Laomedon() {
        this.name = "Laomedon";
    }
    @Override
    public void getResponse(boolean[] status) {
        boolean wumpusNear = status[0];
        boolean hunterNear = status[1];
        boolean corpseNear = status[2];
        boolean arrowNear = status[3];
        boolean hunterHere = status[4];
        switch (myState) {
        case CORPSE_BEHIND:
            if(wumpusNear)
            {
                this.nextDirection = Direction.BACK;
                this.nextMove = Move.SHOOT;
            }
            else
            {
                this.nextDirection = Direction.HERE;
                this.nextMove = Move.MOVE;
            }
            break;
        case CORPSE_LEFT:
            if(wumpusNear)
            {
                this.nextDirection = Direction.LEFT;
                this.nextMove = Move.SHOOT;
            }
            else
            {
                this.nextDirection = Direction.HERE;
                this.nextMove = Move.MOVE;
            }
            break;
        case INITIAL_CORPSE_LEFT:
            if(corpseNear)
            {
                this.nextDirection = Direction.RIGHT;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.INITIAL_CORPSE_RIGHT;
            }
            else
            {
                this.nextDirection = Direction.BACK;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.SEARCHED_LEFT;
            }
            break;
        case INITIAL_CORPSE_RIGHT:
            if(corpseNear)
            {
                this.nextDirection = Direction.LEFT;
                this.nextMove = Move.MOVE;
                myState = Laomedon.status.INITIAL_CORPSE_LEFT;
            }
            else
            {
                this.nextDirection = Direction.BACK;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.SEARCHED_LEFT;
            }
            break;
        case SEARCHED_LEFT:
            if(corpseNear)
            {
                this.nextDirection = Direction.LEFT;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.SMELT_CORPSE;
            }
            else
            {
                this.nextDirection = Direction.RIGHT;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.SEARCHED_RIGHT;
            }
            break;
        case SEARCHED_RIGHT:
            if(corpseNear)
            {
                this.nextDirection = Direction.LEFT;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.SMELT_CORPSE;
            }
            else
            {
                this.nextDirection = Direction.LEFT;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.SEARCHED_LEFT;
            }
            break;
        case SMELT_CORPSE:
            if(corpseNear)
            {
                this.nextDirection = Direction.BACK;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.CORPSE_BEHIND;
            }
            else
            {
                this.nextDirection = Direction.BACK;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.CORPSE_LEFT;
            }
            break;
        case START:
            if(corpseNear)
            {
                this.nextDirection = Direction.LEFT;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.INITIAL_CORPSE_LEFT;
            }
            else
            {
                this.nextDirection = Direction.LEFT;
                this.nextMove = Move.MOVE;
                this.myState = Laomedon.status.SEARCHED_LEFT;
            }
            break;
        }
    }

    @Override
    public void newGame() {

        super.newGame();
        myState = status.START;
    }
}

Na nieszczęście dla niego, inni myśliwi nie doceniają jego umiejętności i wydaje się, że dużo go zastrzelili ...

euanjt
źródło
2

NealHunter

Po rozmowie na ten temat z moim przyjacielem DoctorHeckle pomyślałem, że fajnie byłoby spróbować samemu. Użyłem pomysłu na przemian w lewo i w prawo, aby pokryć jak najwięcej obszarów, a następnie postanowiłem dodać trochę odpowiedzi do stanów, ale tylko 0 i 1 - niezależnie od tego, czy Wumpus lub myśliwy są w pobliżu. Nie działa tak dobrze jak NascarHunter, co na początku mnie zaskoczyło. Po zastanowieniu zdałem sobie jednak sprawę, że wystrzelenie strzały w losowym kierunku (tak jak to robi) po usłyszeniu łowcy / wąchaniu Wumpusa nie zrobi nic, jeśli poruszą się w tej turze, ponieważ strzały są strzelane do pomieszczeń, ale ruch odbywa się zanim je zabije. Nie do końca tak skuteczny, jak myślałem ... ale nadal działa dobrze!

package Hunters;

import Mechanics.*;
import java.util.Random;

public class NealHunter extends Hunter {

    private boolean goLeft;

    public NealHunter(){
        name = "NealHunter";
        goLeft = false;
    }

    public void newGame() {
        goLeft = false;
    }

    public void getResponse(boolean[] status){

        Random rand = new Random();

        if(status[0] || status[1]){
            nextMove = Move.SHOOT;

            switch ( rand.nextInt(3) ){
                case 0:
                    nextDirection = Direction.LEFT;
                    break;
                case 1:
                    nextDirection = Direction.BACK;
                    break;
                case 2:
                    nextDirection = Direction.RIGHT;
                    break;
            }
        } else {
            nextMove = Move.MOVE;
            if (goLeft) {
                nextDirection = Direction.LEFT;
            } else {
                nextDirection = Direction.RIGHT;
            }

            goLeft = !goLeft;
        }
    }
}
Neal
źródło
1

WalkingIdiot

Ten idzie, dopóki nie znajdzie wumpusa. Następnie strzela w prawo. Jeśli wumpus nadal tam jest, musi znajdować się po lewej stronie, więc strzel jeszcze raz. Po drodze nie troszczy się o innych myśliwych ani zwłoki, stąd nazwa.

package Hunters;

import Mechanics.*;

public class WalkingIdiot extends Hunter {
    private boolean wumpusNear = false;

    @Override
    public void newGame() {
        wumpusNear = false;
    }

    public WalkingIdiot(){
        name = "WalkingIdiot";
    }

    @Override
    public void getResponse(boolean[] status){
        boolean wumpusWasNear = wumpusNear;
        wumpusNear = status[0];
        if (status[0]) {
            nextMove = Move.SHOOT;
            if (wumpusWasNear) {
                nextDirection = Direction.LEFT;
            } else {
                nextDirection = Direction.RIGHT;
            }
            return;
        }
        nextMove = Move.MOVE;
        nextDirection = Math.random() < 0.5 ? Direction.LEFT : Direction.RIGHT;
    }
}

Zostać

Pobyt nie lubi chodzić. Po prostu strzela i pamięta, czy zastrzelił myśliwego.

package Hunters;

import Mechanics.*;

public class Stay extends Hunter {
    private Direction lastShot = Direction.LEFT;
    private Direction corpse = null;
    private boolean hunterNear = false;

    public Stay(){
        name = "Stay";
    }

    @Override
    public void newGame() {
        corpse = null;
        hunterNear = false;
        lastShot = Direction.LEFT;
    }

    @Override
    public void getResponse(boolean[] status){
        nextMove = Move.SHOOT;//always
        boolean hunterWasNear = hunterNear;
        hunterNear = status[1];

        if (hunterWasNear && status[2] && !status[1]) {
            corpse = lastShot;
        }

        if (status[0]) {
            if (corpse != null) {
                nextDirection = corpse;
                return;
            }
        }
        if ((status[1] && !status[4]) || status[0]) {
            switch (lastShot) {
                case LEFT: lastShot = nextDirection = Direction.RIGHT; break;
                case RIGHT: lastShot = nextDirection = Direction.BACK; break;
                case BACK: lastShot = nextDirection = Direction.LEFT; break;
            }
            return;
        }

        //default
        lastShot = nextDirection = Direction.LEFT;
    }
}
CommonGuy
źródło