Czteroosobowy pojedynek

54

4-osobowa rozgrywka

Opis

Jakoś znalazłeś się w czterokierunkowej walce. Załadowana broń spoczywa w twoich rękach, a niektóre granaty są zaczepione o pasek.

Celem jest zdobycie jak największego zdrowia po zakończeniu pojedynku. Występuje koniec, gdy co najwyżej jedna osoba ma pozytywny poziom zdrowia.

Każdy gracz ma 5zdrowie i umiera, gdy jego zdrowie spadnie do / poniżej 0. Tura, w której umiera gracz, jest ostatnią turą, w której gracz może otrzymać obrażenia.

Jeśli na końcu meczu jest gracz na żywo, ten gracz wygrywa. W przeciwnym razie wygrywa gracz o najmniej ujemnym zdrowiu.

działania

  • Strzelaj : zastrzel kogoś.

    • 2 obrażenia, jeśli zastrzelisz żywego wroga
    • 0 obrażenia, jeśli strzelasz do martwego wroga
    • health_at_start_of_turn+2obrażenia, jeśli zastrzelisz siebie. (Zauważ, że to pozostawi Cię w stanie NAJBARDZIEJ -2zdrowia).
    • Jeśli jeden wróg strzela do ciebie w tej samej turze, w której strzelasz, zakończysz dystans z -4 pkt. Zdrowia (nadal otrzymujesz obrażenia od innych graczy w kolejce, w której się zabijesz).
    • Twoje działanie w następnej turze zostanie zignorowane (i będzie to miało miejsce Nothing).
  • Unik : Postaraj się uniknąć strzału jednego przeciwnika.

  • Przygotuj : Odczep granat i przygotuj się do jego rzucenia.

    • Masz tylko trzy tury, aby go rzucić, zanim zostaniesz wysadzony w powietrze ( 6obrażenia zadane sobie, 3obrażenia wszystkich żywych wrogów)
    • Umieranie z nie rzuconym granatem jest równoznaczne z nie rzucaniem granatu przez trzy tury.
  • Rzuć : rzuć granatem w stronę kogoś i miej nadzieję na najlepsze.

    • Cel otrzymuje 8obrażenia, jeśli żyje
    • Wszyscy inni (łącznie z tobą) otrzymują 3obrażenia, jeśli żyją
  • Nic : stój bezczynnie przez kolej i obserwuj, jak wszyscy umierają.

Wejście

Twój program otrzyma następujące informacje:

  • Zdrowie każdego gracza
  • Lista działań podjętych przez tego gracza od początku pojedynku Poniżej znajduje się format informacji przekazywanych na gracza:

    [Health],[Action 1],[Action 2],[Action 3],...
    

Działania będą podawane w formacie określonym w sekcji Wyjście .

Otrzymasz 4 takie ciągi znaków, oddzielone spacją i przekazane jako pojedynczy argument. Kolejność tych ciągów jest następująca:

[Player Info] [Opponent 1 Info] [Opponent 2 Info] [Opponent 3 Info]

Ciągi znaków są przekazywane jako drugi argument. Pierwszy argument zawiera liczbę całkowitą, która jednoznacznie identyfikuje wprowadzany odstęp. Gwarantowane odległości między tym samym zestawem graczy nie są równoczesne. Jednak wiele standoffs będzie występować w tym samym czasie.

Na przykład:

$./Player.bash 5 "3,S2,N 5,P,N 3,S0,N -2,S3,N"

Obecnie gracz i drugi przeciwnik mają 3 zdrowie, pierwszy przeciwnik ma 5 zdrowia, a trzeci przeciwnik -2 zdrowie i nie żyje.

W pierwszej turze:

  • Gracz 1 zastrzelił wroga 2
  • Wróg 1 przygotował granat
  • Gracz Enemy 2 strzał
  • Wróg 3 zastrzelił się

W drugiej turze:

  • Wszyscy gracze nic nie zrobili. (Gracz i wróg 2 nie mogą nic zrobić, ponieważ strzelili w poprzedniej turze. Wróg 3 nie żyje: zrobi to Nothingdo końca dystansu.)

Drugi argument na początku jest patowa: 5 5 5 5.

Wynik

Polecenie powinno zostać wypisane w poniższym formacie. Niepoprawne wyjście jest interpretowane jako „Nic”. Polecenie wymagające docelowego powinno nastąpić całkowitą ( 0-3z 0reprezentujący odtwarzacz i 1-3stanowiących wrogów 1-3).

  • S[target]: Strzela [cel].
  • D[target]: Próbuje uniknąć [cel].
  • P: Przygotuj granat.
  • T[target]: Rzuć granat w [cel].
  • N: Nic nie robić.

Komenda że potrzebuje cel, ale jest podawany cel nie między 0i 3czy nie karmiono cel zakładany w całości będzie kierować 0(gracza).

Punktacja

Na koniec każdego pojedynku gracze otrzymują wynik obliczony według następującego wzoru:

35 + health at end of standoff 

W przypadku, gdy gracz kończy impas z negatywnym dla zdrowia, to będzie otrzymać wynik poniżej 35 . Następujące punkty są również nagradzane jako bonus:

  • Najwięcej zdrowia: +4 punkty
  • Drugie pod względem zdrowia: +2 punkty
  • Trzecie miejsce pod względem zdrowia: +1 punkt.

W przypadku remisu przyznawana jest niższa premia (jeśli dwie osoby wiążą się z największą ilością zdrowia, obie mają przyznane +2; jeśli są 3 osoby z największą ilością zdrowia, +1, a jeśli wszyscy kończą się równo, +0).

Ostateczny wynik ustala się, obliczając średnią wszystkich indywidualnych wyników.

Zasady / Szczegóły

  • Kolejność wydarzeń w ramach tury jest następująca:
    • Wszyscy gracze wykonują swoje działania.
    • Gracze, którzy mają 0 lub mniej zdrowia, giną.
    • Nie rzucone granaty, które muszą eksplodować, wybuchną (gracze, którzy właśnie zginęli, nadal są ranni, ponieważ to jest kolej na ich śmierć).
  • Brak współpracy między wpisami.
  • Trzy * odstępy wystąpią między każdym zestawem 4 graczy. (Kolejność graczy może się różnić przy każdym pojedynku).
  • Wpisy zajmujące nadmierną ilość miejsca na dysku zostaną zdyskwalifikowane.
  • Czytanie lub modyfikowanie plików innych niż Twój wpis zdyskwalifikuje Twój wpis.
  • Ciężarówka, prowadzona przez pijaka, przejedzie po wszystkich żyjących graczach po 50thturze, jeśli nie dojdzie jeszcze do końca tej 50thtury.
    • Ta ciężarówka zadaje 20 obrażeń wszystkim żyjącym graczom.
  • Występy zdarzają się szybko. Programy są odcinane po 1 sekundzie.
  • Twój program będzie wywoływany co turę, nawet po twojej śmierci.
  • Możesz odczytywać lub zapisywać pliki tylko w swoim katalogu (jeśli twój wpis nazywa się JohnDoe, możesz zapisywać pliki w katalogu odtwarzacze / JohnDoe /); jednak NIE będzie to bieżący katalog podczas działania skryptu.
  • Awantury odbędą się na komputerze z systemem Arch Linux (wydanie 2014.08.01).

Kontroler jest dostępny na GitHub .

W swoim poście umieść następujące informacje:

  • Nazwa twojego bota
  • Polecenie powłoki do uruchomienia bota (np. java Doe.java) Dane wejściowe będą przekazywane przez wiersz polecenia jako pojedynczy argument ( java Doe.java 5 "-2,S0 -2,S1 -2,S2 5,N")
  • Kod twojego bota
  • Jak należy skompilować bota (jeśli dotyczy)
  • Język (i wersja, jeśli dotyczy, szczególnie dla Pythona)

* Kontroler trwa zbyt długo przez sześć.

Tablica wyników

                      Observer 43.280570409982
                   MuhammadAli 43.134861217214
                         Osama 43.031983702572
                    LateBoomer 42.560275019099
                 SimpleShooter 42.412885154062
             LessSimpleShooter 42.3772
                           Neo 42.3738
                        Scared 42.3678
                     Richochet 42.3263
                   Equivocator 42.2833
  TwentyFourthsAndAHalfCentury 42.2640
                        Darwin 42.1584
                       HanSolo 42.1025
                        Coward 42.0458
           ManipulativeBastard 41.8948
                        Sadist 41.7232
                     Aggressor 41.7058
                 CourageTheDog 41.5629
                     Grenadier 40.9889
                     Bomberman 40.8840
                         Spock 40.8713
                        Sniper 40.6346
                 DONTNUKEMEBRO 39.8151
               PriorityTargets 39.6126
                     Hippolyta 39.2480
                     EmoCowboy 39.2069
                      Zaenille 39.1971
                 AntiGrenadier 39.1919
      PoliticallyCorrectGunman 39.1689
                 InputAnalyzer 39.1517
                      Rule0Bot 39.1000
                     BiasedOne 39.0664
                      Pacifist 39.0481
               StraightShooter 39.0292
                         Ninja 38.7801
                           MAD 38.2543
                        Monkey 37.7089
                   Label1Goto1 36.2131
Generated: 2014/08/22 03:56:13.470264860 UTC

Logi: na GitHub

es1024
źródło
1
Czy masz dokładnie jeden granat, czy masz wiele? Czy możesz przygotowywać wiele granatów jednocześnie?
isaacg
2
@ Bob Jestem pewien, że EmoWolf został dodany do standardowych luk, które nie są już śmieszne . Chociaż samobójcze wejście może nie zrobić tego strasznie.
es1024,
3
Lekcja dla wszystkich: nie pij i nie jedź.
Mark Gabriel,
8
@ es1024 Tam, gdzie samobójstwo jest realną strategią, należy naprawdę zezwolić na poddanie się typu EmoWolf. Zwłaszcza, gdy dostępne działania wyraźnie obejmują samobójstwo! Czyż nie jest to już „luka”? I tak naprawdę nie jest to niesprawiedliwa przewaga, którą tak naprawdę jest większość tych luk. Ale to tylko moja opinia.
Bob
3
Na podstawie kilkukrotnego uruchomienia kontrolera wydaje się dość głośny. Jeśli ten konkurs kiedykolwiek zostanie zamknięty, prawdopodobnie powinieneś zwiększyć liczbę przebiegów, aby go nieco wygładzić.
Davis Yoshida,

Odpowiedzi:

7

Obserwator

Ten facet analizuje swoich wrogów. Celem jest przetrwanie, dopóki nie pozostanie tylko jeden „agresywny” przeciwnik, a następnie zabicie go w epickiej walce.

Kompiluj: javac Observer.javaUruchom:java Observer arg0 arg1

import java.util.List;
import java.util.ArrayList;
import java.util.Random;

class Observer {
    private static List<Integer> aggressiveEnemies = new ArrayList<>();
    private static List<Integer> enemyGrenadiers = new ArrayList<>();
    private static List<Integer> aliveEnemies = new ArrayList<>();

    public static void main(String[] args) {
        if (args[1].length() <= 7) { //first round
            Random rand = new Random();
            printResult("D" + (rand.nextInt(3) + 1));
        }
        String players[] = args[1].split(" ");

        if (truckIsOnWay(players[0])) {
            printResult("P");
        }       

        calcEnemyInfo(players);

        // end this standoff now
        if (truckWillHit(players[0])) {
            if (isGrenadier(players[0]))
                printResult("T" + aliveEnemies.get(0));
            else
                printResult("S0");
        }

        // shoot enemy who is not aggressive
        if (aggressiveEnemies.size() == 0) {
            printResult("S" + aliveEnemies.get(0));
        }

        // only one enemy to handle
        if (aggressiveEnemies.size() == 1) {
            String player = players[aggressiveEnemies.get(0)];
            if (isGrenadier(player)) {
                printResult("S" + aggressiveEnemies.get(0));
            } else if (shotLastTurn(player, aggressiveEnemies.get(0))) {
                //safe to shoot him without receiving damage
                printResult("S" + aggressiveEnemies.get(0));
            } else {
                printResult("D" + aggressiveEnemies.get(0));
            }
        }

        // multiple aggressive enemies
        if (enemyGrenadiers.size() > 0) {
            printResult("S" + enemyGrenadiers.get(0));
        } else {
            int id = aggressiveEnemies.get(0);
            for (int playerId : aggressiveEnemies) {
                if (!shotLastTurn(players[playerId], playerId)) {
                    id = playerId;
                }
            }
            printResult("D" + id);
        }
    }

    private static void printResult(String result) {
        System.out.print(result);
        System.exit(0);
    }

    private static boolean isAlive(String player) {
        return !(player.charAt(0) == '-' || player.charAt(0) == '0');
    }

    private static void calcEnemyInfo(String[] players) {
        for (int i = 1; i < players.length; i++) {
            if (isAlive(players[i])) {
                aliveEnemies.add(i);
                if (isAggressive(players[i], i)) {
                    aggressiveEnemies.add(i);
                }
                if (isGrenadier(players[i])) {
                    enemyGrenadiers.add(i);
                }
            }
        }
    }

    private static boolean truckIsOnWay(String player) {
        return player.length() - player.replace(",", "").length() == 48;
    }

    private static boolean truckWillHit(String player) {
        return player.length() - player.replace(",", "").length() == 49;
    }

    private static boolean isAggressive(String player, int id) {
        return (player.contains("S") || player.contains("P")) && !player.contains("S" + id);
    }

    private static boolean isGrenadier(String player) {
        return player.contains("P");
    }

    private static boolean shotLastTurn(String player, int id) {
        return player.charAt(player.length() - 2) == 'S' && !player.contains("S" + id);
    }
}
CommonGuy
źródło
!player.contains("S" + id)czy jest to warunek konieczny w funkcji „isAggressive”? Samobójczy gracz i tak będzie martwy
Cruncher
22

Grenadier

Pistolety są przereklamowane. A prawdziwy impas Szkota idzie tak:

  • Przygotować
  • Rzuć we wroga z największą ilością zdrowia
  • Powtórz (jeśli jakimś cudem nadal żyjesz)

Chociaż wydaje się to trywialne, prawdopodobnie nie jest to okropna strategia. Ponieważ oba pistolety i granaty mają cykl dwóch tur, jest to zdecydowanie bardziej skuteczny 1 sposób zadawania obrażeń.

Oczywiście, jeśli wszyscy trzej przeciwnicy zastrzelą mnie w pierwszej rundzie, to nie będzie dobrze. Ale niewiele więcej też by było.

public class Grenadier {
    public static void main(String[] args) {
        if(args.length < 2)
            return;
        String[] list = args[1].split(" ");
        if(list.length < 4)
            return;

        if(list[0].charAt(list[0].length()-1) != 'P'){
            System.out.print("P");
            return;
        }

        int target = 1;
        for(int i=2;i<4;i++)
            if(list[i].charAt(0)>list[target].charAt(0))
                target = i;

        System.out.print("T"+target);
    }
}

Skompiluj / uruchom w standardowy sposób Java:

> javac Grenadier.java
> java Grenadier arg0 arg1

1 Bezsensowny przypis

Geobity
źródło
41
hahaha przypis
dumny haskeller
Myślę, że rzucanie granatem, a następnie strzelanie jest bardziej wydajne. Szanse na przetrwanie 4 tur przy tej strategii są zdumiewająco niskie. Ale może 3 (tak, obaj biorą 2, ale druga tura strzelania jest po akcji, nie wcześniej)
Cruncher
@Cruncher Prawdopodobnie masz rację. Eric powiedział to samo na czacie. Powiedziałem mu, że mój facet nie wierzy w broń i jest zbyt uparty, by użyć tej logiki, więc opublikował tę strategię. Jednak nadal uważam, że jest to bardziej wydajne , jeśli ściśle mówimy o zadawanych obrażeniach. To nie znaczy, że jest bardziej skuteczny w wygrywaniu gry. Nawet jeśli umrę w trzeciej turze, mój drugi granat wciąż mi odpala. Więc jeśli do tego czasu będę żył, będzie to gwarantowane każdemu ponad 6 obrażeń, koniec gry.
Geobits,
@Geobits teraz, kiedy o tym myślę, może być lepiej. Najważniejsza jest różnica między tobą a przeciwnikami. Kiedy granat wysadzi w powietrze, zyskujesz +3 delty z kim go rzuciłeś, a +0 z resztą. Siatka +3. Strzelanie. Zyskujesz deltę +2 z kim strzelasz. +0 z resztą. Myślę, że problem polega na tym, że ty -3 z ludźmi, którzy już nie żyją. Powinieneś strzelać, jeśli ktoś nie żyje :)
Cruncher
2
@codebreaker Nigdy nie grałem. Jest to odniesienie z prawdziwego życia .
Geobits,
16

Zasada Asimowa Numer 0 Bot - Python

Robot nie może wyrządzić krzywdy ludzkości lub przez bezczynność pozwolić ludzkości wyrządzić krzywdę.

Całkiem prosto zaatakuje pierwszego gracza, którego widzi, trzymając granat, aby chronić większość ludzi. Jeśli nikt nie stanowi zagrożenia dla większości ludzi, nic nie zrobi.

import sys

def total_humans_alive(humans):
  return sum([is_alive(human) for human in humans])

def is_alive(x):
  return int(x.split(",")[0]) > 0  

def is_threat_to_humanity(lastAction):
  return lastAction == "P"

action = "N"
threat_id = 1
humans = sys.argv[2].split()[1:];

if total_humans_alive(humans) == 3:
  for human in humans:
    if is_threat_to_humanity(human[-1]):
      action = "S" + str(threat_id)
      break
    threat_id= threat_id+ 1

print action

Uruchom to jak:

python rule0bot.py
William Barbosa
źródło
2
Twój robot jest nielogiczny. Jeśli gracz trzymający granat rzuca, ludzkość otrzymuje 8 + 3 + 3 + 3 = 17 obrażeń. Jeśli zabijesz go strzałem, ludzkość otrzyma 2 + 6 + 3 + 3 + 3 = 17 obrażeń. W obu scenariuszach ten, kto wysadzi na nich granat, bierze 8, a wszyscy inni biorą 3 (chyba że wcześniej nie żyli). Nie ma to wpływu na ludzkość jako całość. Jednak nadal mi się podoba. +1: D
Geobity
4
W rzeczywistości najlepszym scenariuszem dla ludzkości jest nadzieja, że ​​granat zostanie rzucony w robota;)
Geobits
1
@Geobits Nie próbowanie powstrzymania kogoś, kto jest zagrożeniem, jest sprzeczne z naturą robotów. Będzie próbował powstrzymać kogoś trzymającego granat, aby zapobiec zranieniu większości (pozostałych dwóch). Czytałeś już ja, robocie? Logikę tę popierają Little Lost Robot i The Evitable Conflict.
William Barbosa,
Przeczytałem to, ale mówię, że strzelanie do nich nie kończy tego tutaj. Jeśli zginie, trzymając granat, nadal wybuchnie. Nie tylko to, ale łączna wartość szkód wyrządzonych ludzkości pozostaje taka sama. Wyrządzasz bezpośrednią szkodę człowiekowi, nie dając ludzkości żadnego zysku.
Geobits,
2
+1 Nie zgadzam się z głosowaniem Kyle'a Kanosa i chcę go unieważnić. Geobici nie mają racji, zakładając, że nie robi to nic, by pomóc ludzkości. Jasne, ludzkość może nie wyjść lepiej w najgorszym przypadku, ale jeśli pozostali dwaj gracze strzelą do granatu z biczem, wszyscy są na to lepsi.
FreeAsInBeer
14

Han Solo - Python

Han strzelił pierwszy. W takim przypadku najpierw strzela, wybierając najbliższy żywy cel.

import sys

def is_alive(player):
  return int(player.split(",")[0]) > 0

closest_living_target = 1;

for player in sys.argv[2].split()[1:]:
  if is_alive(player):
    action = "S" + str(closest_living_target)
    break

  closest_living_target = closest_living_target + 1

print action

Uruchom to jak:

python hansolo.py

Uwaga : jest to pierwsza rzecz, jaką napisałem w Pythonie, więc jeśli zauważysz jakieś złe praktyki specyficzne dla Pythona, daj mi znać.

William Barbosa
źródło
1
styl pep8 sugeruje, że twoja metoda powinna byćis_alive
Daenyth
4
@WilliamBarbosa rzucił okiem na pep8, jest to przewodnik po stylu python, którego wszyscy używają. legacy.python.org/dev/peps/pep-0008
Daenyth
2
Gratulujemy bycia jedynym botem o średnim zdrowiu większym niż 0 w rundzie 8/11.
isaacg,
6
IMO, „przewodniki po stylach” są przeznaczone dla fryzjerów, a nie programistów.
Kyle Kanos
2
@KyleKanos Fajnie jest jednak zachować spójność. Mam na myśli, że jeśli połowa twórców projektu użyje futerału wielbłąda, a druga połowa tego typu, to będzie „blergh”
William Barbosa,
12

EmoCowboy

Po co czekać na śmierć? Po prostu zabij się teraz. Mam nadzieję, że reszta głupców wysadzi się nawzajem do mniej niż -2.

Wynik zwykle wynosi -2. Czasami -4, jeśli ludzie decydują się mnie zestrzelić. Rzadko więcej, co oznacza, że ​​powinno to pokonać kilka z bieżących zgłoszeń.

Pyton

print('S0')

python EmoCowboy.py

EDYCJA: To nie jest żart, i generalnie dlatego te emo są odrzucane. To uzasadniona strategia. Bycie żywym jest śmiertelne!

Cruncher
źródło
11

Pacyfista

To prawdziwy, spuchnięty facet, właśnie złapał niewłaściwy tłum.

main = putStr "N"

Uruchom jako runghc pacifist.hs, ale możesz chcieć skompilować go z opcją -O3, jeśli wydajność stanowi problem.

zabójca
źródło
1
Zmień nazwę na Luigi i zobaczmy, czy on coś wygra!
William Barbosa,
1
@WilliamBarbosa Luigi? Powiedziałeś Luigi ?
killmous,
7
Lol jakby -O3robi dziwną różnicę.
tomsmeding
@tomsmeding Z boku jest wolny runghc. W rzeczywistości jest 10 razy wolniejszy na moim Linux-ie.
Ray
5
To implikuje przemoc, implikację, której nasz pacyfista nie jest gotowy poradzić sobie
zabójczy
9

Monkey - Python (pierwszy w historii!)

Monkey see, monkey do. Powtórzy dokładnie ostatnią akcję wykonaną przez losowego gracza.

import sys, random
targetData = sys.argv[2].split()[random.randint(0,3)]
print(targetData.split(',')[len(targetData.split(','))-1])

Można uruchomić w następujący sposób: „python monkey.py args” Nie są wymagane dodatkowe kroki.

Elias Benevedes
źródło
2
Mam nadzieję, że nie strzelali do ciebie! Python obsługuje ujemne indeksy tablicowe, więc nie musisz obliczać długości i odejmować jednego; po prostu użyj -1bezpośrednio.
wszechstronny
@comperendinous Powiedz, że jestem S3 na ich liście. Jeśli wykonam S3, to mnie nie głupie. Ponadto indeks -1 zwróci ostatni element? Jeśli tak, to świetnie! Na pewno go dodam.
Elias Benevedes,
I nie zapomnij o pierwszym (całkowitym) argumencie. Musisz argv[2]przejrzeć historię graczy.
kompleksowy
Mam tylko nadzieję, że nie dorównasz Emo Cowboy.
codebreaker
6

Simple Shooter - Perl (naprawiony błąd)

Ten bot strzela do przeciwnika o największym zdrowiu. To bardzo prosta strategia, ale myślę, że ma przyzwoitą szansę na dobre wyniki.

@history = map([split(",",$_)],split(" ",$ARGV[1]));
$target = 1;
for(2..3){
 if($history[$_][0] >= $history[$target][0]){$target = $_}
}
print "S$target"

Oto jak uruchomić go za pomocą przykładowych danych wejściowych:

perl simpleshooter.plx 7 "3,S2,N 5,P,N 3,S0,N -2,S3,N"
PhiNotPi
źródło
Łał. Prosty i elegancki.
Soham Chowdhury,
6

Spock w Pythonie 3.x

Ten kod jest raczej eksperymentem (stąd jego nazwa pochodzi od Spocka, ponieważ ... jest wulkanem i są całkiem dobrzy w tego typu sprawach), ale mimo to budowanie go było fajne. Głównym powodem tego całego kodu są założenia, które zrobiłby dobry, logiczny byt, jak Spock, gdyby przestrzegał zasad gry:


Celem tej gry jest zmaksymalizowanie wyniku, który byłby wykonywany przez wszystkich stojących w bezruchu, co nie jest możliwe z powodu ciężarówki.

  • Jedną z dyrektyw, których musi przestrzegać Spock, jest zapobieganie pojawianiu się ciężarówki, upewniając się, że wszyscy oprócz jednej nie żyją, zanim pojawi się ciężarówka.

Sposób, w jaki Spock gra w pozostałej części gry, można podsumować jego słynnym cytatem: „ Potrzeby wielu przeważają nad potrzebami niewielu ”. Innymi słowy, Spock musi zadbać o to, aby doznał jak najmniejszej szkody, zabijając tych, którzy to robią. Jak on to robi:

  • Jeśli żaden gracz nie przygotował granatu, celuj w najmniej zdrowego gracza, który wciąż gra.
  • Jeśli są gracze, którzy przygotowali granaty, od tych, którzy celują w najmniej zdrowe.

Powodem jest to, że atakując najsłabszych graczy, eliminujemy źródła obrażeń. Granaty leżą u podstaw tego, że niezależnie od tego wybuchają i zadają mniej obrażeń, jeśli nie zostaną rzucone.


I tak działa ten bot. Nie testowałem dokładnie pod kątem błędów wejściowych (więc proszę ostrzegaj mnie, jeśli coś pójdzie nie tak), ale jestem pewien, że udało mi się rozwiązać większość problemów. Oparłem niewielką część kodu z bota HanSolo, ale w większości jest to splątany bałagan kodu. Cieszyć się.

def IsAlive(player):
  return int(player[1].split(",")[0]) > 0
def IsTarget(player, target_health):
  return int(player[1].split(",")[0]) < target_health
def HasGrenade(player):
  max_range = max(-4,-current_turn)
  for foo in range(-1,max_range,-1):
    if "P" in player[1].split(",")[foo]:
      for bar in range(-1,foo-1,-1):
        if player[1].split(",")[bar] not in ["T0", "T1", "T2", "T3"]:
          return True
  return False

import sys
info_list = sys.argv[2].split()
current_turn = len(info_list[0].split(","))
action = "N"

def Startgame():
  global action

  target = 1
  target_health = 5
  grenade_list=[]

  for player in zip(range(1,4),info_list[1:]):
    if HasGrenade(player):
      grenade_list.append(player)

  if not grenade_list:
    foo_list = []
    for player in zip(range(1,4),info_list[1:]):
      foo_list.append(player)
    target_list = foo_list
  else:
    target_list = grenade_list

  # Choose the least healthy player
  for player in target_list:
    if IsAlive(player) and IsTarget(player, target_health):
      target = player[0]
      target_health = int(player[1][0])

  action = "S" + str(target)

def Endgame(turn):
  global action

  if turn in [47, 49]:
    # Check if in 2 moves he can do enough damage
    rem_health = 0
    for player in zip(range(1,4),info_list[1:]):
      if IsAlive(player): rem_health += player[0]

    if rem_health < 5:
      Startgame() # It's lazy, but it should work
      return
    else:
      action = "P"
      return

  if turn in [48, 50]:
    # If Spock shot someone before, it needs to shoot again
    if info_list[0].split(",")[-1] in ["S0", "S1", "S2", "S3"]:
      Startgame()
      return
    else:
    # There's no rule against throwing grenades to dead bodies, so if
    # possible it will be thrown there.    
      target = 1
      target_health = 5

      foo_list = []
      for player in zip(range(1,4),info_list[1:]):
        foo_list.append(player)
      target_list = foo_list

      for player in target_list:
        if IsTarget(player, target_health):
          target = player[0]
          target_health = int(player[1][1])

      action = "T" + str(target)
      return

if current_turn > 46:
  Endgame(current_turn)
else:
  Startgame()

print(action)

Uruchom to jak:

python spock.py

2014-08-12 - Drobne poprawki błędów w wykrywaniu granatów
14.08.2014 - Drobne poprawki błędów w grze końcowej, dzięki isaacgowi za wskazanie tego wcześniej

Doktoro Reichard
źródło
Nie wolno strzelać więcej niż raz na dwie rundy. Przeczytaj specyfikację fotografowania.
isaacg,
@isaacg Dzięki za przypomnienie (które wyjaśnia zachowanie), ale wydaje się, że są jakieś ukryte błędy. Na przykład w tym Spocku powinien zastrzelić InputAnalyser, ponieważ miał granat na żywo (nawet jeśli Solo miałby więcej 2 zdrowia).
Doktoro Reichard,
Traceback (most recent call last): File "./players/Spock/Spock.py", line 87, in <module>: Endgame(current_turn) File "./players/Spock/Spock.py", line 79, in Endgame: if IsTarget(player, target_health): File "./players/Spock/Spock.py", line 4, in IsTarget: return int(player[1].split(",")[0]) < target_health TypeError: unorderable types: int() < str()
es1024,
player[1][1]powinno być int(player[1][1]).
isaacg
@isaacg jeszcze raz dziękuję za pomoc. Zrobiłbym to wcześniej, ale byłem zalany rzeczami. Spock został ostatecznie zbudowany na błędnej koncepcji tego, jak to się rozegra, stąd stosunkowo niski wynik, jaki uzyskał. Mam kilka pomysłów na nowe boty, ale przy tak wielu muszę teraz upewnić się, że główny pomysł jest oryginalny.
Doktoro Reichard
5

Politycznie poprawny bandyta

Bardzo politycznie poprawne, ponieważ niczego nie dyskryminuje. Dlatego nie jest zbyt mądry.

import random

array = ["P", "N", "S0", "S1", "S2", "S3", "D1", "D2", "D3", "T1", "T2", "T3"]

print(array[random.randrange(0,11)])

To ... nie ma znaczenia, jakie argumenty zostaną mu przekazane. python politicallycorrectgunman.py

Cofnij
źródło
Nie sądzę, aby nawiasy kwadratowe miały stanowić część wyniku. Być może @ es1024 może to potwierdzić. A czy wiesz o random.choice? Jest świetny do tego rodzaju selekcji.
wszechstronny
nic nie może być przed działaniem i celem w danych wyjściowych, ale
późniejsze elementy
Czy to wygląda lepiej @ es1024?
Cofnij
@ Cofnij Tak, działa teraz idealnie
es1024,
7
Nie możesz po prostu użyć random.choice(array)?
user2357112,
5

Straight Shooter

Jest wyszkoloną częścią kawalerii i mówi w wielu językach, ale mrugając, Straight Shooter widzi tylko jednego wroga przed sobą. Będąc koniem, nie rozumie, że musisz czekać między strzałami.

print('S2')

Perl, Python 2/3, Ruby: ten koń naprawdę jest poligonem.

I tak wygrywam. Nie mogę przegrać Możesz mnie zastrzelić, ale nie możesz mnie zabić. Pan Ed mnie nie obchodzi!

Aby uzyskać odpowiedź, która zawiera nieco więcej przemyślenia (i paradygmatu funkcjonalnego), zobacz Dwudziesty Czwarty i Pół wieku .

wszechstronny
źródło
5

Przeciw grenadierowi

Granaty są złe. Bardzo źle. Więc jeśli ktoś je przygotowuje, najlepiej jest je zastrzelić. W przeciwnym razie po prostu spędzimy wolny czas.

-- Antigrenadier
local args = {...}  -- command line arguments

match = args[2]     -- store the set of matches

-- why this isn't standard in Lua....
function string:split( inSplitPattern, outResults )
  if not outResults then
    outResults = { }
  end
  local theStart = 1
  local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
  while theSplitStart do
    table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
    theStart = theSplitEnd + 1
    theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
  end
  table.insert( outResults, string.sub( self, theStart ) )
  return outResults
end

-- set up the players
players = match:split(" ")

-- search other players for someone who pulled a grenade
for i=2,#players do
   moves = players[i]
   -- test if person is alive
   if moves:sub(1,1) ~= "-" then
      -- cycle through all elements of the string
      for j=#moves,2,-1 do
         -- if found, shoot!
         if moves:sub(j,j) == "P" then
            print("S"..i-1)
            os.exit()
         end
      end
   end
end

-- otherwise we just relax
print("N")
Kyle Kanos
źródło
4

Rykoszet - Perl

Proste strategie wydają się sprawdzać w tym wyzwaniu, więc oto kolejne. Strzela losowego żywego gracza. Ma dodatkową funkcję popełnienia samobójstwa na końcu, aby uniknąć ciężarówki.

@history = map([split(",",$_)],split(" ",$ARGV[1]));
$health = $history[0][0];
@options = ();
for(1..3){
 if($history[$_][0] > 0){
  push(@options,$_);
 }
}
$target = @options[int(rand(~~@options))];
if(~~@{$history[0]} == 50){
 $target = 0;
}
print"S$target";

Uruchom tak:

perl ricochet.plx 5 "-2,S0 -2,S1 -2,S2 5,N" 
PhiNotPi
źródło
4

Agresor

Ciągnie w pierwszej rundzie, rzuca przeciwnikowi o najwyższym zdrowiu w drugiej rundzie, następnie strzela w przeciwnika o najwyższym zdrowiu.

#include <cstdio>
#include <cstring>

int main(int argc, char** argv){
   char* t;
   t = strtok(argv[2]," ");
   int len = strlen(t);
   int max = -50, maxP;
   for(int i=1;i<4;i++){
      int cur;
      t = strtok(NULL," ");
      if(t[0]=='-'){cur = -1*(t[1]-'0');}
      else{cur = t[0]-'0';}
      if(cur>max){
         max = cur;
         maxP = i;
      }
   }
   if(len == 1){printf("P\n"); return 0;}
   if(len == 3){printf("T%d\n",maxP); return 0;}
   printf("S%d\n",maxP);
   return 0;
}

Uruchom to jak ./agg ID „5 5 5 5”.

Eric Tressler
źródło
4

Ninja

Po prostu unika się losowo, próbując uniknąć trafienia.

math.randomseed(os.time())
print("D"..tostring(math.random(4)-1))

Uruchom jako

lua ninja.lua

Argumenty są niepotrzebne, ale można je dodać bez problemu.

Kyle Kanos
źródło
2
@KyleKanos czy Ninja uniknie własnych ujęć?
skeggse
2
@distilledchaos: ... tak, tak będzie.
Kyle Kanos,
4

Nazwa : PriorityTargets

Polecenie powłoki : ruby ​​PriorityTargets.rb 5 [game_state]

Język : Ruby V2.1.2

Opis : PriorityTargets próbuje znaleźć popularne style gry. Następnie decyduje, na podstawie tych stylów gry, kogo chce zaatakować i jakiej broni użyć.

Uwaga : przesyłanie pierwszego kodu do gry w golfa! Znacznie większy niż inne zgłoszenia, ponieważ trochę oszalałem.

#!/usr/bin/env ruby

class PriorityTargets
  class PlayerAction
    SHOOT = 'S'
    DODGE = 'D'
    PREPARE_GRENADE = 'P'
    THROW_GRENADE = 'T'
    NOTHING = 'N'
    attr_accessor :action, :target

    def initialize(action_string)
        @action = action_string[0, 1]
        @target = self.has_target? ? action_string[1, 1].to_i : false
    end

    def to_s
      string = @action
      string << @target.to_s if self.has_target?
      string
    end

    def has_cooldown?
      [SHOOT].include? @action
    end

    def is_aggressive?
      [SHOOT, PREPARE_GRENADE, THROW_GRENADE].include? @action
    end

    def has_target?
      [SHOOT, DODGE, THROW_GRENADE].include? @action
    end
  end


  class Player
    attr_reader :identifier, :health, :history
    attr_accessor :playstyles

    def initialize(player_identifier, player_string)
      @identifier = player_identifier
      @playstyles = []

      player_info = player_string.split(',')
      @health = player_info.shift.to_i
      @history = parse_history(player_info)
    end


    def has_attacked?(player, round = nil)
      round ||= self.history.length - 1
      player.history[0, round].each do |turn|
        did_attack = true and break if turn.is_aggressive? && turn.has_target? && turn.target == player.identifier
      end
      did_attack ||= false
    end

    def is_holding_grenade?(round = nil)
      round ||= self.history.length
      turn_history = self.history[0, round]
      is_holding = false

      turn_history.each_with_index do |turn, curr_round|
        if turn.action == PlayerAction::PREPARE_GRENADE && curr_round >= round - 3
          is_holding = true if turn_history.drop(curr_round).select{|turn| turn.action == PlayerAction::THROW_GRENADE }.length == 0
        end
      end

      is_holding
    end

    def is_dead?; self.health <= 0; end
    def is_on_cooldown?
      return false if self.history.length == 0
      self.history.last.has_cooldown?
    end

    def turn_at_round(round); self.history[round-1]; end

    private

      def parse_history(history_array)
        parsed = []
        history_array.each {|action_string| parsed << PlayerAction.new(action_string) }
        parsed
      end
  end

  class PlayerList
    include Enumerable

    def initialize(player_list = [], filter_list = false)
      @list = player_list
      @filter = filter_list if filter_list
    end

    #Enumerable Methods
    def each
      list = @list.select{|player| @filter.include?(player.identifier) } if @filter
      list = @list unless @filter
      list.each {|player| yield(player) }
    end

    def <<(player); @list << player; end
    def [](key)
      player = @list.select{|player| @filter.include?(player.identifier) }[key] if @filter
      player = @list[key] unless @filter
      player
    end

    def length
      list = @list.select{|player| @filter.include?(player.identifier) } if @filter
      list = @list unless @filter
      list.length
    end

    def empty?; self.length == 0; end
    def not_empty?; self.length > 0; end

    def create_filtered_list(player_ids)
      new_player_list = PlayerList.new(@list, player_ids)
      new_player_list
    end

    #PlayerList Methods
    def includes_playstyle?(playstyle)
      (self.with_playstyle(playstyle).length > 0)
    end

    def have_executed_action?(action)
      action_found = false
      self.each {|player| action_found = true and break if player.history.select {|turn| turn.action == action}.length > 0 }
      action_found
    end

    def direct_damages(round = nil)
      round ||= self.first.history.length

      damage_list = {}
      @list.each {|player| damage_list[player.identifier] = 0 }

      if round >= 1
        @list.each do |player|
          player.history[0, round].each_with_index do |turn, curr_round|

            if turn.has_target?
              target_player = @list.select{|curr_player| curr_player.identifier == turn.target }.first
              target_turn = target_player.turn_at_round(curr_round)

              damage_list[turn.target] += 8 if turn.action == PlayerAction::THROW_GRENADE

              if turn.action == PlayerAction::SHOOT
                damage_list[turn.target] += 2 unless target_turn.action == PlayerAction::DODGE && target_turn.target == player.identifier
              end
            end
          end
        end
      end

      damage_list.select! {|key| @filter.include? key } if @filter
      damage_list
    end


    def filtered_with_condition(&condition_block)
      player_ids = []
      self.each {|player| player_ids << player.identifier if condition_block.call(player) }
      create_filtered_list(player_ids)
    end

    def on_cooldown; filtered_with_condition {|player| player.is_on_cooldown?} end
    def not_on_cooldown; filtered_with_condition {|player| !player.is_on_cooldown?} end

    def dead; filtered_with_condition {|player| player.is_dead?} end
    def not_dead; filtered_with_condition {|player| !player.is_dead?} end

    def with_playstyle(playstyle); filtered_with_condition {|player| player.playstyles.include?(playstyle)} end
    def not_with_playstyle(playstyle); filtered_with_condition {|player| !player.playstyles.include?(playstyle)} end

    def with_max_health(round = nil)
      round ||= self.first.history.length
      player_damages = direct_damages(round)
      filtered_with_condition {|player| player_damages[player.identifier] == player_damages.values.min }
    end

    def with_identifier(identifier)
      matches = self.with_identifiers([ identifier ])
      return nil if matches.empty?
      matches.first
    end

    def with_identifiers(identifiers)
      create_filtered_list(identifiers)
    end
  end

  class PlayerTypes
    GRENADIER = :GRENADIER
    COWBOY = :COWBOY
    SKIDDISH = :SKIDDISH
    AGGRESSOR = :AGGRESSOR
    DEFENSIVE = :DEFENSIVE
    ANTI_GRENADIER = :ANTI_GRENADIER
    PLAYSTYLE_ORDER = [GRENADIER, COWBOY, SKIDDISH, AGGRESSOR, DEFENSIVE, ANTI_GRENADIER]

    def initialize(player_list)
      @players = player_list
    end

    def analyze_playstyles
      return if @players.first.history.length == 0

      PLAYSTYLE_ORDER.each do |playstyle|
        check_fnc = "is_"+playstyle.to_s+'?'
        @players.each {|player| player.playstyles << playstyle if self.send(check_fnc, player) }
      end
    end

    def is_GRENADIER?(player)
      #Grenade on first turn
      #Used more than one grenade
      #Never used gun, only grenade
      shoot_count = player.history.count {|turn| turn.action == PlayerAction::SHOOT }
      grenade_count = player.history.count {|turn| turn.action == PlayerAction::PREPARE_GRENADE }

      profiled ||= true if player.history.first.action == PlayerAction::PREPARE_GRENADE
      profiled ||= true if grenade_count > 1
      profiled ||= true if shoot_count == 0 && grenade_count > 0
      profiled ||= false
    end

    def is_COWBOY?(player)
      #Never used grenade, only gun
      shoot_count = player.history.count {|turn| turn.action == PlayerAction::SHOOT }
      grenade_count = player.history.count {|turn| turn.action == PlayerAction::PREPARE_GRENADE }

      profiled ||= true if grenade_count == 0 && shoot_count > 0
      profiled ||= false
    end

    def is_SKIDDISH?(player)
      #Dodged more than once
      #Never hurts anybody
      dodge_count = player.history.count {|turn| turn.action == PlayerAction::DODGE }
      attack_count = player.history.count {|turn| turn.is_aggressive? }

      profiled ||= true if dodge_count > 1
      profiled ||= true if attack_count == 0 && player.history.length > 1
      profiled ||= false
    end

    def is_AGGRESSOR?(player)
      #Only shoots person >= most health
      profiled = false
      player.history.each {|turn| profiled = true if turn.is_aggressive? && turn.has_target? }

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          profiled = false if [email protected]_max_health(round).include? @players.with_identifier(turn.target)
        end
      end
      profiled
    end

    def is_DEFENSIVE?(player)
      #Only hurts people who hurt them first
      player.history.each {|turn| profiled = true if turn.is_aggressive? && turn.has_target? }

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          target_player = @players.with_identifier(turn.target)
          profiled = false unless target_player.has_attacked?(player, round)
        end
      end
      profiled ||= false
    end

    def is_ANTI_GRENADIER?(player)
      #After a Grenadier has been shown, only shoots grenadier
      shots_fired = 0
      shots_fired_while_holding = 0

      player.history.each_with_index do |turn, round|
        if turn.is_aggressive? && turn.has_target?
          target_player = @players.with_identifier(turn.target)
          shots_fired += 1
          shots_fired_while_holding += 1 if target_player.is_holding_grenade?(round)
        end
      end

      (shots_fired > 0 && shots_fired/2.0 <= shots_fired_while_holding)
    end
  end




  def initialize(game_state)
    players_info = game_state.split(' ')
    @player = Player.new(0, players_info.shift)
    @players = PlayerList.new
    @players << @player
    enemy_identifiers = []

    players_info.each_with_index {|info, index| @players << Player.new(index+1, info); enemy_identifiers << index+1; }

    @enemies = @players.with_identifiers(enemy_identifiers  )
  end

  def analyze_playstyles
    types = PlayerTypes.new(@players)
    types.analyze_playstyles
  end

  def find_dodge_target
    armed_aggressors = @enemies.with_playstyle(PlayerTypes::AGGRESSOR).not_on_cooldown().not_dead()

    if armed_aggressors.not_empty?
      return armed_aggressors.with_max_health().first if @players.with_max_health().include?(@player) && @players.with_max_health().length == 1
    end

    return @enemies[Random.rand(3)] if @player.history.length == 0
    nil
  end

  def find_target
    unarmed_aggressors = @enemies.with_playstyle(PlayerTypes::AGGRESSOR).on_cooldown().not_dead()
    anti_grenadiers = @enemies.with_playstyle(PlayerTypes::ANTI_GRENADIER).not_dead()
    grenadiers = @enemies.with_playstyle(PlayerTypes::GRENADIER).not_dead()
    cowboys = @enemies.with_playstyle(PlayerTypes::COWBOY).not_dead()
    skiddish = @enemies.with_playstyle(PlayerTypes::SKIDDISH).not_dead()
    defensive = @enemies.with_playstyle(PlayerTypes::DEFENSIVE).not_dead()

    if unarmed_aggressors.not_empty?
      return unarmed_aggressors.with_max_health().first if @players.with_max_health().include?(@player) && @players.with_max_health().length == 1
    end

    return anti_grenadiers.with_max_health().first if anti_grenadiers.not_empty?
    return grenadiers.with_max_health().first if grenadiers.not_empty?
    return cowboys.with_max_health().first if cowboys.not_empty?
    return skiddish.with_max_health().first if skiddish.not_empty?
    return defensive.with_max_health().first if defensive.not_empty?
    return @enemies.with_max_health().not_dead().first if @enemies.with_max_health().not_dead().length > 0
    nil
  end

  def find_weapon
    return PlayerAction::THROW_GRENADE if @player.is_holding_grenade?

    anti_grenadiers = @enemies.with_playstyle(PlayerTypes::ANTI_GRENADIER).not_dead()

    return PlayerAction::PREPARE_GRENADE if anti_grenadiers.empty? && @enemies.have_executed_action?(PlayerAction::PREPARE_GRENADE)
    PlayerAction::SHOOT
  end

  def make_decision
    dodge_target = self.find_dodge_target
    target = self.find_target
    weapon = self.find_weapon

    decision ||= PlayerAction.new(PlayerAction::NOTHING) if @player.is_on_cooldown? || @enemies.with_max_health().not_dead().length == 0
    decision ||= PlayerAction.new(PlayerAction::DODGE + dodge_target.identifier.to_s) if dodge_target
    decision ||= PlayerAction.new(weapon + target.identifier.to_s)
    STDOUT.write decision.to_s
  end
end

priority_targets = PriorityTargets.new(ARGV[1])
priority_targets.analyze_playstyles
priority_targets.make_decision
fingerco
źródło
1
Podoba mi się twoje podejście, nie mogę się doczekać, aby zobaczyć, jak to się stanie.
overactor
Niestety wydaje się, że miał w sobie błąd, który stworzył Grenadiera. Ach cóż, następnym razem będzie lepiej :)
fingerco
3

Tchórz - Perl

Działa bardzo tchórzliwie. Kiedy czuje się zdrowy, wybiera wroga, który tak nie czuje, i strzela do niego. Punkty bonusowe dla tych wrogów, którzy strzelali w ostatniej turze (ponieważ są znani z tego, że wykonują Nothingtę turę i dlatego są absolutnie bezbronni). Kiedy nie czuje się tak dobrze, biegnie po kryjówkę, by ocalić swoją skórę, od czasu do czasu zastrzeliwując kogoś.

#!/usr/bin/perl

@allinfo = map { [split/,/] } split / /, $ARGV[1];
@life = map { $_->[0] } @allinfo;
@action = map { @$_>1 ? $_->[-1] : () } @allinfo;

if($life[0] < 3 && rand() < .5 )
{
    printf "D%d", +(sort { ($life[$a]>0)*($action[$a] eq "N") <=> ($life[$b]>0)*($action[$b] eq "N") } 1..3)[2]
}
else
{
    @score = map { $life[$_]>0 ? (5/$life[$_] + 2*($action[$_] =~ /S./)) : 0 } 1..3;
    printf "S%d", +(sort { $score[$a] <=> $score[$b] } 1..3);
}

Całkiem standardowy kod Perla; zapisz go w jakimś pliku, a następnie uruchom perl file argument argument [...]. Sprawdziłem składnię i było OK, więc mam nadzieję, że nie będzie z tym żadnych problemów.

E: wyeliminowano potencjał dzielenia przez błąd 0.

Ramillies
źródło
3

Bomberman

Bot napisany w R, wiersz poleceń powinien brzmieć: Rscript Bomberman.R arg0 arg1
po rozpoczęciu pisania tego bota zrozumiałem, że Geobits już zrobił grenadiera, ale myślę, że mój jest znacznie inny, ponieważ sprawdza, czy jego zdrowie jest wyższe niż 3 przed przygotowaniem granatu, rzuca go w ostatni strzelec pierwszy, a najzdrowszy drugi, a jeśli jego zdrowie spadnie poniżej 3, uniknie niebezpiecznego gracza (ani martwego, ani strzelającego w ostatniej rundzie) lub zastrzeli jednego z pozostałych graczy.

input <- commandArgs(TRUE)
history <- do.call(rbind,strsplit(scan(textConnection(input[2]),"",quiet=TRUE),","))
health <- as.integer(history[,1])
last_shooter <- which(grepl("S",history[-1,ncol(history)]))
last_prepare <- which(history[1,]=="P")
if(!length(last_prepare)) last_prepare <- -1
last_throw <- which(grepl("T",history[1,]))
if(!length(last_throw)) last_throw <- 0
most_healthy <- which.max(health[-1])
dead <- which(health[-1]<=0)
inoffensive <- c(last_shooter,dead)
danger <- which(!(1:3)%in%inoffensive)
alive <- which(!(1:3)%in%dead)
if(health[1]>3 & last_throw > last_prepare) out <- "P"
if(last_throw < last_prepare) out <- ifelse(length(last_shooter),paste("T",last_shooter[1],sep=""),paste("T",most_healthy[1],sep=""))
if(health[1]<=3 & last_throw > last_prepare){
    if(length(danger)){
        out <- paste("D",sample(danger,1),sep="")
    }else{
        out <- paste("S",sample(alive,1),sep="")
    }
}
cat(out)

Edytować

Wygląda na to, że jest jakiś problem z komunikacją między tym botem a twoim kontrolerem, ponieważ wszystkie logi, które szukałem, pokazały, że mój bot tylko generuje dane wyjściowe N. Oto ten sam bot, ale przepisany w Pythonie, w nadziei, że jeśli ten również będzie miał problem z komunikacją, ktoś to zobaczy.
Do połączenia z python Bomberman.py arg0 arg1.

import sys,re,random

history = sys.argv[2]
history = [k.split(",") for k in history.split()]
health = [k[0] for k in history]
last_turn = [k[-1] for k in history]
last_shooter = [i for i,x in enumerate(last_turn) if re.search(r'S[0-3]',x)]
last_prepare = [i for i,x in enumerate(history[0]) if x=='P']
if not len(last_prepare):
    last_prepare = [-1]

last_throw = [i for i,x in enumerate(history[0]) if re.search(r'T[0-3]',x)]
if not len(last_throw):
    last_throw = [0]

most_healthy = [i for i,x in enumerate(health) if x==max(health)]
dead = [i for i,x in enumerate(health) if x<=0]
inoffensive = last_shooter+dead
danger = [k for k in range(1,4) if k not in inoffensive]
alive = [k for k in range(1,4) if k not in dead]
if health[0]>3 and last_throw[-1] > last_prepare[-1]:
    out = 'P'

if last_throw[-1] < last_prepare[-1]:
    if len(last_shooter):
        out = 'T'+random.choice(last_shooter)
    else:
        out = 'T'+random.choice(most_healthy)

if health[0]<=3 and last_throw[-1] > last_prepare[-1]:
    if len(danger):
        out = 'D'+random.choice(danger)
    else:
        out = 'S'+random.choice(alive)

print(out)
plannapus
źródło
Nazwa bota jest stosunkowo słaba, ale zabrakło mi pomysłu, jeśli ktoś może wymyślić lepszą nazwę, proszę o komentarz :)
plannapus
GymnastBomber !!
Cruncher
3

Neo

Unikaj żyjącego gracza, który nie strzelił w ostatniej turze. Jeśli wszyscy żywi zastrzelili w ostatniej turze, zastrzel losowego żyjącego gracza. Samobójstwo, gdy zobaczysz reflektory.

import java.util.Random;
public class Neo {
    public static void main(String[] args) {
        if(args.length < 2)
            return;
        String[] list = args[1].split(" ");
        if(list.length < 4)
            return;
        Random rand = new Random();
        int turn = list[0].split(",").length;
        if(turn == 49){
            System.out.print("S0");
            return;
        }
        int target=0;
        for(int i=1;i<4;i++)
            if(list[i].length()<2 || (list[i].charAt(0)!='-' && list[i].charAt(list[i].length()-2)!='S'))
                target=i;
        if(target>0){
            System.out.print("D"+target);
            return;
        }
        while(target<1){
            int i=rand.nextInt(3)+1;
            if(list[i].charAt(0)!='-')
                target=i;
        }
        System.out.print("S"+target);
    }
}

Nie oczekuję wiele od tego faceta w stosunku do uchwytów granatów, ale w stosunku do strzelców może działać całkiem dobrze. Zobaczymy.

Geobity
źródło
W swojej odpowiedzi wykorzystałem część twojego kodu na płycie głównej . Mam nadzieję, że to w porządku.
overactor
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1 at java.lang.String.charAt(String.java:658) at Neo.main(Neo.java:17)
es1024,
@ es1024 Powinno być już dobrze i nie robić nic za każdym razem.
Geobits
2

Dwudziesty czwarty i pół wieku

Ten wpis w Pythonie uchyla się i unika, dopóki nie pozostaną tylko pasywni gracze lub pojedynczy agresywny gracz, a następnie zacznie strzelać. Ma nadzieję, że przechodzący Marsjanin zajmie się grenadierami i pijanymi kierowcami ciężarówek.

O ile nie zrobiłem czegoś złego, jest to funkcjonalny Python. Z pewnością nie wygląda to na Python, który napisałem, zanim Haskell i przyjaciele mnie odnaleźli, i nie sądzę, żebym coś zmutował. Ale jeśli wiesz lepiej, proszę, powiedz mi.

#!/usr/bin/env python
import sys
import random

## ==== Move Types ================================================== ##
def move_type (move):
    if "" == move:
        return "N"
    return move[0]

def is_passive_move (move):
    if "N" == move:
        return True
    if "D" == move_type (move):
        return True
    return False

def is_aggressive_move (move):
    return not is_passive_move (move)

def passive_moves (moves):
    return [m for m in moves if is_passive_move (m)]

def aggressive_moves (moves):
    return [m for m in moves if is_aggressive_move (m)]
## ================================================== Move Types ==== ##

## ==== Player Model ================================================ ##
class Player:
    def __init__ (self, number, health, moves):
        self.number = number
        self.health = health
        self.moves  = moves

    def last_move (self):
        if 0 == len (self.moves):
            return ""
        return self.moves[-1]

def player_from (number, player_string):
    x = player_string.split (",")
    health = int (x[0].strip ())
    moves = [move.strip () for move in x[1:]]

    return Player (number, health, moves)

def players_from (game_state):
    return [player_from (n, p) for (n, p) in
                                   zip (range(4), game_state.split ())]

def is_alive (player):
    return 0 < player.health

def i_am_dead (me):
    return not is_alive (me)

def can_shoot (player):
    return "S" != move_type (player.last_move ())

def is_passive (player):
    passive_move_count = len (passive_moves (player.moves))
    aggressive_move_count = len (aggressive_moves (player.moves))

    return passive_move_count > (aggressive_move_count + 1)

def players_who_can_breathe (players):
    return [p for p in players if is_alive (p)]

def players_who_can_shoot (players):
    return [p for p in players if can_shoot (p)]

def players_who_stand_around (players):
    return [p for p in players if is_passive (p)]
## ================================================ Player Model ==== ##

## ==== Actions ===================================================== ##
def shoot_randomly_at (possible_targets):
    chosen_target = random.choice (possible_targets)
    return "S{0}".format (chosen_target.number)

def dodge_one_of_the (potential_shooters):
    chosen_shooter = random.choice (potential_shooters)
    return "D{0}".format (chosen_shooter.number)

def do_nothing ():
    return "N"

def pick_move (game_state):

    players = players_from (game_state)
    me = players[0]
    enemies = players[1:]

    if i_am_dead (me):
        return do_nothing ()

    living_enemies = players_who_can_breathe (enemies)
    if 1 == len (living_enemies):
        return shoot_randomly_at (living_enemies)

    passive_enemies = players_who_stand_around (living_enemies)
    if len (living_enemies) == len (passive_enemies):
        return shoot_randomly_at (passive_enemies)

    potential_shooters = players_who_can_shoot (living_enemies)
    if 0 < len (potential_shooters):
        return dodge_one_of_the (potential_shooters)

    return do_nothing ()
## ===================================================== Actions ==== ##

if "__main__" == __name__:

    game_state = sys.argv[2]
    print (pick_move (game_state))

Uruchom jako:

python twenty-fourth-and-a-halfth-century.py 0 "5 5 5 5"
wszechstronny
źródło
2

Przerażony

To zgłoszenie boi się wszystkich. Ale szczególnie boi się niektórych osób. Więc zastanawia się, kto jest najbardziej niebezpieczny, i strzela do nich. Jeśli wielu wrogów wygląda najbardziej niebezpiecznie, strzela do losowego.

import sys
import random


def is_alive(player):
    return int(player.split(",")[0]) > 0


# Anyone with a live grenade who is alive is dangerous
def is_dangerous(player):
    return player.count("P") > player.count("T") and \
        int(player.split(",")[0]) > 0


def health(player):
    return int(player.split(",")[0])


# Failing that, healthy people are dangerous
def danger_rating(player):
    return 6 if is_dangerous(player) else health(player)

enemies = sys.argv[2].split()[1:]

highest_danger = max(danger_rating(enemy) for enemy in enemies)
most_dangerous_enemy = random.choice(
    [enemy_num+1 for enemy_num in range(len(enemies))
     if danger_rating(enemies[enemy_num]) == highest_danger])

print("S"+str(most_dangerous_enemy))

To jest python (2 lub 3, taki sam wynik w obu przypadkach.) Zapisz jako scared.py, uruchom zpython3 scared.py

isaacg
źródło
2

Manipulacyjny drań - Python

Przygotowuje i rzuca granaty. Jeśli myśli, że nie ma czasu lub jest zbyt mało wrogów, strzela. Jeśli jest sam, próbuje przechytrzyć drugiego faceta.

import sys

def health(p):
    return int(p[0])

def is_alive(p):
    return health(p) > 0

def can_act(p):
    return is_alive(p) and p[-1][0] != 'S'

def can_throw(p):
    return is_alive(p) and p[-1][0] == 'P'

def shot_first(p):
    if len(p) == 1:
        return False
    return p[1][0] == 'S'

def act(a):
    print a
    sys.exit(0)

player = sys.argv[2].split()[0].split(',')
enemies = [e.split(',') for e in sys.argv[2].split()[1:]]
healthiest = sorted(enumerate(enemies, 1), key=lambda e:health(e[1]))[-1]
alive = sum(is_alive(e) for e in enemies)

if alive == 1:
    i, e = healthiest
    if health(e) <= 2 and not can_act(e):
        act('S%d' % i)
    if can_throw(player):
        act('T%d' % i)
    if can_throw(e):
        act('S%d' % i)
    if can_act(e) and shot_first(e) and len(player) < 40:
        act('D%d' % i)
    if len(player) > 45:
        act('P')
    act('S%d' % i)

if can_throw(player):
    i, e = healthiest
    act('T%d' % i)

if len(player) > 45:
    act('P')

if health(player) <= 2 or any(can_throw(e) for e in enemies) or alive == 2:
    i, e = healthiest
    act('S%d' % i)

act('P')
fhyqrkka
źródło
2

Osama

Próbowałem tego przez około dzień, teraz nadszedł czas, aby opublikować i zobaczyć, jak w międzyczasie ewoluowali inni.

module Main where

import Data.List
import Data.Ord
import System.Environment

words' "" = []
words' s = s' : words' (tail' s'')
  where
    (s', s'') = break (==',') s
    tail' (',':r) = r
    tail' r = r

nRound = length . words'

lastAction = last . words'

health :: String -> Int
health = read . head . words'

alive = (>0) . health

grenadeAge :: String -> Int
grenadeAge p | not (alive p) = 0
             | otherwise = g 0 $ tail $ words' p
  where
    g n (a:b:r) | head a == 'S' = g (if n>0 then n+2 else 0) r
    g 0 ("P":r) = g 1 r
    g n (('T':_):r) | n>0 = g 0 r
    g n (_:r) | n>0 = g (n+1) r
    g n (_:r) = g n r
    g n [] = n

prepared :: String -> Bool
prepared p = alive p && head (lastAction p) /= 'S'

nShotMe = length . filter (=="S0") . words'

getPlayer = (!!)

action players@(me:them) | not (prepared me) = "S2" -- bogus
                         | nRound me >= 49 = "S0"
                         | grenadeAge me >= 1 = 'T':(show $ maximumBy (comparing (nShotMe . getPlayer players)) l)
                         | any prepared them && nRound me > 0 = 'D':(show $ maximumBy (comparing (nShotMe . getPlayer players)) l)
                         | otherwise = 'S':(show $ maximumBy (comparing (health . getPlayer players)) l)
  where l = filter (alive . (getPlayer players)) [1..3]



main = do
  players <- fmap (words . head . tail) getArgs
  putStrLn $ action players

Skompiluj ghc -O2 osama.hs, a następnie uruchom za pomocą ./players/Osama/osama.

TheSpanishInquisition
źródło
2

Sniper - Lua

W pierwszej turze zastrzelą losową osobę, a następnie zastrzelą wszystkich graczy, których mogą zabić (2 lub 1 zdrowie). Jeśli żadna z nich nie zadziała, spróbuje zastrzelić gracza, który postrzelił go jako ostatni, w przeciwnym razie zastrzeli losowego gracza. Biegnij zlua Sniper.lua

turns = arg[2]
health = string.sub(turns, 1, 1)
--make random numbers random
math.randomseed(io.popen("date +%s%N"):read("*all"))
math.random(); math.random(); math.random()
function Split(str, delim, maxNb)
    -- Eliminate bad cases...
    if string.find(str, delim) == nil then
        return { str }
    end
    if maxNb == nil or maxNb < 1 then
        maxNb = 0    -- No limit
    end
    local result = {}
    local pat = "(.-)" .. delim .. "()"
    local nb = 0
    local lastPos
    for part, pos in string.gmatch(str, pat) do
        nb = nb + 1
        result[nb] = part
        lastPos = pos
        if nb == maxNb then break end
    end
    -- Handle the last field
    if nb ~= maxNb then
        result[nb + 1] = string.sub(str, lastPos)
    end
    return result
end
enemies = Split(turns, " ")
--first turn
if #enemies[1] == 1 then
  print(string.format("S%i",math.random(1,3)))
  os.exit()
end
--kills if possible
for enemy=1,3 do
  if (tonumber(string.sub(enemies[enemy + 1],1,1)) or 0) < 3 and string.sub(enemies[enemy + 1],1,1) ~= "-" then
    print(string.format("S%i",enemy))
    os.exit()
  end
end
--shoots the last person that shot at it
for enemy=1,3 do
  if string.sub(enemies[enemy + 1],#enemies[enemy + 1]-1) == "S0" and tonumber(string.sub(enemies[enemy + 1],1,1)) > 0 then
    print(string.format("S%i",enemy))
    os.exit()
  end
end
--otherwise shoot a random alive person
local aliveEnemies = {}
for enemy=1,3 do
  if string.sub(enemies[enemy + 1],1,1) ~= "-" then
    aliveEnemies[#aliveEnemies+1]=enemy
  end
end
print(string.format("S%i",math.random(1,#aliveEnemies)))
waylon531
źródło
Najpierw zostanie uruchomiony z dodatkowym argumentem; np lua Sniper.lua 3 "5,S1 3,D3 5,N 5,P". Może być konieczne sprawdzenie swojego argindeksu.
kompleksowy
@comperendinous, dzięki, naprawiono teraz
waylon531
Cześć, @ waylon531, pytanie o Lua: losowo posadzony math.randoms "math.randomseed (os.time ()) math.random (); math.random (); math.random ()" nie wystarczy, aby losowo scenariusz?
AndoDaan,
1
AndoDaan, zgodnie z lua-users.org/wiki/MathLibraryTutorial, niektóre systemy operacyjne zawsze zwracają ten sam numer przy pierwszym wywołaniu math.random ().
waylon531,
lua: ./players/Sniper/Sniper.lua:38: attempt to compare nil with number./players/Sniper/Sniper.lua:38: in main chunk [C]: in ?
śledzenie
2

Darwin

Przetrwanie najsilniejszych oznacza, że ​​najmniej zdrowi muszą umrzeć.

Racjonalne uzasadnienie

Patrząc na zestaw wyników z wtorku (12), wydaje się, że istnieją trzy odrębne grupy: osoby, które przeżyły; skutecznie samobójcze; i gorsze niż bezużyteczne. Ocalali dzielą proste strategie oparte na strzelaniu. Podczas gdy kilka innych botów ( Spock , Tchórz ) będzie atakowało najmniej zdrowego wroga, komplikują również swoje strategie innymi działaniami. Ten nie. Podobnie jak Simple Shooter , ma jasną definicję celu i trzyma się jej bezlitośnie. Ciekawie będzie zobaczyć, gdzie pasuje do wyników.

#!/usr/bin/env python

import sys
import random

## ==== Player Model ================================================ ##
class Player:
    def __init__ (self, number, health):
        self.number = number
        self.health = health

def player_from (number, player_string):
    x = player_string.split (",")
    health = int (x[0].strip ())

    return Player (number, health)

def players_from (game_state):
    return [player_from (n, p) for (n, p) in
                                   zip (range(4), game_state.split ())]

def is_alive (player):
    return 0 < player.health

def i_am_dead (me):
    return not is_alive (me)

def players_who_can_breathe (players):
    return [p for p in players if is_alive (p)]

def players_by_health (players):
    return sorted (players, key=lambda p: p.health)

def least_healthy_players (players):
    sorted_living_players = \
        players_by_health (players_who_can_breathe (players))
    lowest_living_health = sorted_living_players[0].health
    return [p for p in players if lowest_living_health == p.health]
## ================================================ Player Model ==== ##

## ==== Actions ===================================================== ##
def shoot_randomly_at (possible_targets):
    chosen_target = random.choice (possible_targets)
    return "S{0}".format (chosen_target.number)

def do_nothing ():
    return "N"

def pick_move (game_state):
    players = players_from (game_state)
    me = players[0]
    enemies = players[1:]

    if i_am_dead (me):
        return do_nothing ()

    least_healthy_enemies = least_healthy_players (enemies)
    return shoot_randomly_at (least_healthy_enemies)
## ===================================================== Actions ==== ##

if "__main__" == __name__:

    game_state = sys.argv[2]
    print (pick_move (game_state))

To jest okrojona, nieco zmodyfikowana wersja mojego wcześniejszego dwudziestego czwartego i półwiecza , i podziela jej przywołanie:

python darwin.py 3 "5 5 5 5"
wszechstronny
źródło
2

Zaenille - C

Priorytety:

  1. Strzelaj, jeśli pozostało 1 na 1
  2. Strzelaj do grenadierów
  3. Unik
  4. Nic (tylko trochę pomylić)

Kompiluj z gcc <filename.c>.

Uruchom z ./a.out <parameters>.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
    char* input = argv[2];
    int enemyCount=1;
    int aliveCount=0;
    int aliveEnemy=0;

    //default
    char action = 'N';
    int target = NULL;

    const char delim[1] = " ";
    char *token;

    //first turn
    if(strcmp(input,"5 5 5 5")==0){
        printf("D1");
        return 0;
    }

    token = strtok(input, delim);
    token = strtok(NULL, delim); //skip to the first enemy

    while(token != NULL){
        //if someone is alive :
        if(strstr(token,"-")==NULL && token[0]!='0'){
            aliveCount++;
            aliveEnemy=enemyCount;
            //if that person did nothing this turn, take it as a tip that he will shoot next turn, and dodge
            if(strstr(token, "N")!=NULL){
                action = 'D';
                target=enemyCount;
            }

            //if that person prepared a grenade, shoot him down
            if(strstr(token, "P")!=NULL){
                action = 'S';
                target=enemyCount;
            }
        }

        token = strtok(NULL, delim);
        enemyCount++;
    }

    //if there is 1 enemy left, shoot him down
    if(aliveCount==1){
        action='S';
        target=aliveEnemy;
    }

    printf(action=='N'?"N":"%c%d",action,target);

    return 0;
}
Mark Gabriel
źródło
1
Pierwszy argument (liczba całkowita) nie wskazuje liczby rund, jeśli przykłady podane w pytaniu są do przejścia. Nie chciałbyś strzelać do siebie w pierwszej turze tylko dlatego, że przydzielono cię do
walki z
Naprawdę? D: Dzięki @comperendinous. Zmieni kod.
Mark Gabriel
2

InputAnalyzer

Kluczem do takiej gry jest analiza, w jaki sposób grają wszyscy przeciwnicy, aby odpowiednio zareagować. Mój bot zrobi to samo, używając skomplikowanych algorytmów, które spowodują użycie moich przeciwników, a moja przewaga da decydujące zwycięstwo!

Edycja: ja teraz

  1. unikaj każdego gracza, który ma granat na żywo
  2. nie będę już próbował się pokazywać / rzucać / unikać.

import System.Environment   
import Data.Char (ord)
import Data.List.Split

main = do 
    args <- getArgs
    let secondArg = (last args)
    let opt = (argCount secondArg 0)
    let list = (splitOn " " secondArg)
    let enemysToCheck = [1,2,3]
    let target = (avoidShootingSelf (findTarget (last args) 0 0 0 0))
    putStrLn (decide list enemysToCheck opt target)

argCount :: String -> Int -> Int
argCount (s:str) i
    |(length str) == 0 = i `mod` 4
    | otherwise = (argCount str (i + (ord s)))

--myPseudo takes number 0-3, and a possible target and translates it to a command 
myPseudo :: Int -> Int -> String
myPseudo 0 b = "S" ++ (show b)
myPseudo 1 b = "D" ++ (show b)
myPseudo 2 b = "P"
myPseudo 3 b = "T" ++ (show b)

decide :: [String] -> [Int] -> Int -> Int -> String
decide [] [] a b = (myPseudo a b)
decide (x:xs) [] a b = (myPseudo a b)
decide xs (y:ys) a b
    | (liveGrenade z 0) == True = "D" ++ (show y)
    | otherwise = (decide xs ys a b)
    where z = xs!!y

--checks if a player has a live grenade
liveGrenade :: String -> Int -> Bool
liveGrenade [] a = a > 0
liveGrenade (s:str) a
    | s == 'T' = (liveGrenade str (a - 1))
    | s == 'P' = (liveGrenade str (a + 1))
    | otherwise = (liveGrenade str a)

--findTarget picks a target by doing some irrelevant string processing on the 2nd argument
findTarget :: String -> Int -> Int -> Int -> Int -> Int
findTarget [] a b c d = ((maximum [a,b,c,d]) `mod` 4)
findTarget (s:str) a b c d
    | s == 'S' = (findTarget str (a + 1) b c d)
    | s == 'D' = (findTarget str a (b + 1) c d)
    | s == 'P' = (findTarget str a b (c + 1) d)
    | s == 'T' = (findTarget str a b c (d + 1))
    | s == 'N' = (findTarget str a b c (d + 1))
    | otherwise = (findTarget str a b c d)

--Makes sure I do target myself takes int 0-3
avoidShootingSelf :: Int -> Int
avoidShootingSelf 0 = 1
avoidShootingSelf a = a

Skompiluj bota za pomocą następującego polecenia (musisz mieć ghc)

ghc --make InputAnalyzer.hs

Polecenie powłoki do uruchomienia powinno być następujące

./InputAnalyzer

Uwaga: Testowałem na Windowsie, więc jeśli masz problemy z kompilacją / uruchomieniem, powiedz to w komentarzu, a ja postaram się znaleźć właściwe polecenie.

Sahar Rabinoviz
źródło
1
Cóż, przypuszczam, że jest to jeden ze sposobów uzyskania ważonego generatora pseudolosowego w Haskell.
wszechstronny
2

Pies o imieniu Odwaga

Po pierwsze - strzelaj do złych w zasięgu wzroku. Następnie unikaj losowo, aż ktoś przygotuje granat. Potem, kiedy wszyscy do niego strzelą, przygotuj mój granat i rzuć go na każdego. Ale człowiek rozpraszający uwagę.

Edycja: Teraz zaimplementowane tak, jak myślałem, że powinno być. Wcześniej wynik wynosił: 35,9

Zaktualizowano: Czasami strzela zamiast uniku

couragethedog.py

import sys
from collections import defaultdict as ddict
from random import choice
args = sys.argv
info = " ".join(args[2:]).strip('"').split(" ")
players = ddict(dict)
for i,s in enumerate(info):
    parts = s.split(",")
    players[i]["health"]=int(parts[0])
    players[i]["last"]=parts[-1]
    players[i]["history"]=parts[1:]
    players[i]["turn"]=len(parts)
me=0
others=[1,2,3]
turn=players[me]["turn"]
alive = filter(lambda p:players[p]["health"]>0,others)
def act():
    if turn is 1:
        return "S%d" % choice(alive)
    if "P" == players[me]["history"][-1]:
        targets = set(alive)
        for i in alive:
            if "P" == players[i]["history"][-2]:
                targets.remove(i)
        return "T%d" % choice(list(targets))
    for i in others:
        if players[i]["history"][-1] is "P":
            return "P"
    if choice([True,False,False]):
        return "S%d" % choice(alive)
    return "D%d" % choice(alive)
print act()

Uruchom jako

python couragethedog.py
loa_in_
źródło
2

MAD - Java

Bot MAD wierzy w siłę zastraszania poprzez wzajemnie gwarantowane zniszczenie . Ilekroć nie ma gotowego granatu, przygotowuje go. Następnie unika możliwych strzelców, dopóki albo ktoś nie zada mu obrażeń, albo jego granat zaraz wybuchnie. Od momentu zaatakowania rzuca granatami na każdego, kto do tej pory próbował zadać mu więcej obrażeń. Jeśli jego granat ma wybuchnąć, bombarduje wiodącego gracza. MAD nie jest przeciwny strzelaniu do kogoś, kiedy nie ma się czego uchylić ani bezpośrednio rzucić granatem, a jego granat jest nadal dobry na co najmniej jedną turę.

    import java.util.ArrayList;
import java.util.Random;

public class MAD 
{
    public static void main(String[] args) 
    {
        if(args.length < 2)
        {
            return; // nothing to do here
        }
        String[] players = args[1].split(" ");
        if(players.length < 4 || !isAlive(players[0]))
        {
            return; // nothing to do here
        }
        Random rand = new Random();

        int grenadeExplodes = grenadeExplodes(players[0]);        
        if(grenadeExplodes==-1)
        {
            System.out.print("P"); // I don't feel safe without a prepared grenade in my hand
            return;
        }

        int highestDamage = -1;
        int playerToShoot = -1;        
        for(int i=1; i<4; i++) // did anyone try to hit me?
        {
            int damage = damageAttempted(players[i], 0);
            if(isAlive(players[i]) && (damage>highestDamage || (damage==highestDamage && rand.nextDouble()>0.5)))
            {
                highestDamage = damage;
                playerToShoot = i;
            }           
        }

        if(highestDamage > 0)
        {
            System.out.print("T" + Integer.toString(playerToShoot)); // don't tell me I didn't warn you
            return;
        }

        int highestHealth = -1;
        int healthiestPlayer = -1;      
        for(int i=1; i<4; i++) // who is doing too well for their own good?
        {
            int health = getHealth(players[i]);
            if(health>highestHealth || (health==highestHealth && rand.nextDouble()>0.5))
            {
                highestHealth = health;
                healthiestPlayer = i;
            }
        }

        if(grenadeExplodes==0)
        {
            System.out.print("T" + Integer.toString(healthiestPlayer).charAt(0)); // get this hot head outta here!!
            return;
        }

        // I've got time to flaunt my grenade around

        ArrayList<Integer> playersToDodge = new ArrayList<Integer>();       
        for(int i=1; i<4; i++) // lets see who could shoot me
        {
            if(canMove(players[i]) && grenadeExplodes(players[i])!=0)
            {
                playersToDodge.add(i);
                if(grenadeExplodes(players[i])==-1) // players who have no grenade are more likely to shoot
                {
                    playersToDodge.add(i);
                }
            }
        }

        if(playersToDodge.size()>0)
        {
            System.out.print("D" + Integer.toString(playersToDodge.get(rand.nextInt(playersToDodge.size() - 1))).charAt(0)); // what do we say to would-be gunners?
            return;
        }

        if(grenadeExplodes!=1)
        {
            System.out.print("S" + Integer.toString(healthiestPlayer).charAt(0)); // seems like I can take a free shot at someone
        }
        else
        {
            System.out.print("N"); // wouldn't want to end up with an exploding grenade in my hand while being unable to throw it.
        }

    }

    public static boolean isAlive(String player) 
    {
        return player.charAt(0)!='-'; 
    }

    public static boolean canMove(String player)
    {
        return isAlive(player) && player.charAt(player.length()-2)!='S';
    }

    public static int grenadeExplodes(String player)
    {
        String[] actions = player.split(",");

        if(actions.length>3 && actions[actions.length - 3].charAt(0)=='P' 
            && actions[actions.length - 2].charAt(0)=='T' 
            && actions[actions.length - 1].charAt(0)=='P')
        {
            return 0;
        } 
        else if(actions.length>2 && actions[actions.length - 2].charAt(0)=='P' 
            && actions[actions.length - 1].charAt(0)=='T')
        {
            return 1;
        } 
        else if(actions.length>1 && actions[actions.length - 1].charAt(0)=='P')
        {
            return 2;
        }
        else
        {
            return -1;
        }
    }

    public static int damageAttempted(String player, int target)
    {
        String[] actions = player.split(",");
        int damage = 0;
        char targetChar = Integer.toString(target).charAt(0);
        for(int i=0; i<actions.length; i++)
        {
            if(actions[i].charAt(0)=='S' && actions[i].charAt(1)==targetChar)
            {
                damage += 2;
            } 
            else if (actions[i].charAt(0)=='T')
            {
                if(actions[i].charAt(1)==targetChar)
                {
                    damage += 8;
                }
                else
                {
                    damage += 3;
                }
            }
        }

        return damage;
    }

    public static int getHealth(String player)
    {
        return Integer.parseInt(player.split(",")[0]);
    }
}

Ten bot prawdopodobnie będzie działał słabo, ale i tak spodobał mi się ten pomysł. MAD prawdopodobnie lepiej poradziłby sobie na polu z inteligentnymi botami, które rejestrują zachowanie innych botów, a więcej dopasowań działa między 4 botami.

overactor
źródło
Pewne kredyty należy się Geobitom, ukradłem kod płyty kotłowej jego wpisu Neo.
overactor
Nie
wziąłeś
Wywołanie java MAD 43 "5 5 5 5"wydaje się nic nie dawać.
es1024
2

Sadysta

pyton

Jego priorytetem jest spowodowanie bólu i zranienia granatów. Ciągnie pierwszą turę. Lubi zabijać, kiedy nie możesz zaatakować. Bawi się SSS (pojedyncze proste strzelanki), unikając i ciągnąc, aby przedłużyć dominację. On nawet decyduje się zaatakować tych, którzy nic nikomu nie zrobili.

Ponieważ używa granatów, on (i wszyscy inni) zwykle nie przeżyją drugiej lub trzeciej rundy. Jeśli zostanie sparowany z innym granatem, wszyscy zginą. Oznacza to, że nie spodziewam się wygranej, ale napisałem to, aby nauczyć się pytona (nigdy wcześniej go nie używałem i próbuję uzyskać wprowadzenie do wielu nowych języków). Istnieje kilka innych „pull first”, więc jeśli uważasz, że jest to zbyt symetryczne, daj mi znać. Inni nie wydają się jednak gotowi ciągnąć, a następnie unikać.

import sys    

def ident(thatguy):

    return int(thatguy.split(",")[0])

def health(thatguy):
    return int(thatguy.split(",")[1])

def shooter(thatguy):
    if(len(thatguy.split(","))<3):
        return 1==1
    else: return thatguy.split(",")[2][0]=="S"

def mosthealth(group):
    bigbad=group[0]
    for foe in group:
        if (health(foe)>health(bigbad)): bigbad=foe
    return bigbad

def igotanuke(mine):
    return mine.count("P")-mine.count("T")>0

def guytonuke(allguys,fighters):
    backup=allguys[:]
    for Aguy in backup:
        if(health(Aguy)<4):
            allguys.remove(Aguy)
            if (shooter(Aguy)): fighters.remove(Aguy)

    if(len(allguys)==0): return mosthealth(backup)
    if (len(allguys)==len(fighters)):
        return mosthealth(allguys)
    else:
        for fighter in fighters: allguys.remove(fighter)
        return mosthealth(allguys)

raw = sys.argv[2]
player = raw.split(" ")
thisisme=player.pop(0)
turn = len(player[0].split(","))-1

guys=[]
gunners=[]
c=1
for dude in player:
    dude=str(c)+","+dude
    c+=1
    if (health(dude)>0): 
        guys.append(dude)
        if (shooter(dude)):
            gunners.append(dude)

if (turn==0): print "P"
elif(turn==49): print"S0"
elif(igotanuke(thisisme))&( turn % 2 == 1): print "T"+str(ident(guytonuke(guys,gunners)))
elif(len(guys)<2)&(len(gunners)>0) & (turn % 2 == 1): print P
elif(turn % 2 == 0) & (len(gunners)>0): print "D"+str(ident(mosthealth(gunners)))
elif(turn % 2 == 1) & (len(gunners)>0): print "S"+str(ident(mosthealth(gunners)))
else: print "S"+str(ident(mosthealth(guys)))
Kaine
źródło
Nie sądzę, żeby raw_inputto zadziałało. sys.argv[2]wydaje się być konsensusem dla wpisów w Pythonie. Możesz również znaleźć zastosowanie dla pop, które pozwolą ci skondensować thisisme=player[0];player.remove(player[0])się w prostsze thisisme=player.pop(0).
wspaniały
@comperendinous Testowałem kod w Ideone i sys.argv w ogóle nie działa (prawdopodobnie z powodu importu sys). Dlatego użyłem raw_input. Czy istnieje różnica, która sprawiłaby, że ta ostatnia nie działałaby? Jeśli tak, prawdopodobnie będę musiał znaleźć inny kompilator online dla Pythona. Dzięki za sugestię pop! Nie zdawałem sobie sprawy, że to polecenie pozwala na określenie indeksu. Użyję go do każdego przyszłego kodu Pythona.
kaine
1
raw_inputpobiera z STDIN, ale historia odtwarzacza jest przekazywana do twojego programu jako argument wiersza poleceń, dlatego potrzebujesz sys.argv. Dla celów testowych możesz ustawić go ręcznie za pomocą sys.argv = ["sadist.py", "0", "5 5 5 5"]. Powinieneś być w stanie zadzwonić player=sys.argv[2].split(). Jeśli importowanie sysjest naprawdę niemożliwe, w celu przetestowania możesz nawet upuścić kropkę i wywołać tablicę sysargv. Tak długo, jak wszystko inne działa, a ty wracasz do sys.argvswojego zgłoszenia, powinno być dobrze.
wspaniały
@comperendinous, aby potwierdzić, jeśli wywołam sys.argv, zwróci jako tablicę nazwę programu w 0, ten pojedynczy numer w 1 i faktyczną część, której używam w 2? Wszystkie są strunami. Dzięki tym informacjom powinienem móc poprawnie go edytować. Dziękuję Ci bardzo!
kaine