Jesteś najsłabszym ogniwem, do widzenia


50

To wyzwanie na opiera się na teleturnieju Weakest Link . Dla tych, którzy nie znają tego programu, sedno tego wyzwania dotyczy tego, komu głosujesz :

  • Jeśli inni gracze są mądrzejsi od ciebie, masz mniejsze szanse na zdobycie puli.
  • Jeśli inni gracze są głupsi od ciebie, masz mniej puli do zdobycia.

Na początku każdej rundy, Pot zaczyna się od $ 0. Powstaje grupa 9 graczy, a każdy gracz otrzymuje unikalną inteligencję od 1 do 9.

Na początku każdej tury, Pot += Smartnessdla każdego gracza wciąż w rundzie. Następnie gracze głosują na gracza, którego chcą usunąć. Gracz z największą liczbą głosów zostanie usunięty. W przypadku remisu mądrzejszy gracz zostaje zachowany.

Gdy w rundzie zostają tylko 2 graczy, walczą oni w bitwie sprytu. Jest szansa na wygraną gracza Smartness/(Smartness+OpponentSmartness). Zwycięski gracz otrzymuje wtedy całą pulę.

Gracz, który otrzymał najwięcej pieniędzy na koniec gry, wygrywa.

Wejście wyjście

W każdej turze otrzymujesz aktualną listę przeciwników. Będziesz miał dostęp do swojej inteligencji i całej historii głosowania wszystkich graczy w rundzie dzięki funkcjom w klasie Gracza.

Jako wynik musisz zwrócić jedną liczbę całkowitą, reprezentującą gracza, na którego chcesz głosować (reprezentujący jego inteligencję). Głosowanie na siebie jest dozwolone (ale nie zalecane).

Rundy 9 będą się powtarzać, aż wszyscy gracze rozegrają co najmniej 1000 10000 rund, a wszyscy gracze rozegrają tę samą liczbę rund.

Kontroler można znaleźć tutaj: https://github.com/nathanmerrill/WeakestLink

Aby stworzyć gracza, musisz rozszerzyć klasę Player i dodać swojego gracza do klasy PlayerFactory. Twoja klasa musi przestrzegać następujących zasad:

  1. Komunikacja lub ingerencja w jakikolwiek inny odtwarzacz (w tym innych graczy tego samego typu) jest surowo zabroniona.

  2. Odbicie i zmienne statyczne (z wyjątkiem stałych) są niedozwolone.

  3. Jeśli chcesz użyć losowości, podałem getRandom()funkcję w klasie Player. Użyj go, aby symulacje mogły być deterministyczne.

Udostępniłem wiele funkcji w klasie Player dla łatwego dostępu do danych. Można je znaleźć online na Github . Twój gracz zostanie utworzony w każdej nowej rundzie. Gracze „głupi / samobójcy” są dozwoleni (ale nie gracze o tej samej strategii).

Wyniki

377195  WeakestLink.Players.PrudentSniper
362413  WeakestLink.Players.Sniper
353082  WeakestLink.Players.VengefulSniper
347574  WeakestLink.Players.AntiExtremist
298006  WeakestLink.Players.BobPlayer
273867  WeakestLink.Players.MedianPlayer
247881  WeakestLink.Players.TheCult
240425  WeakestLink.Players.Leech
235480  WeakestLink.Players.SniperAide
223128  WeakestLink.Players.Guard
220760  WeakestLink.Players.Anarchist
216839  WeakestLink.Players.RevengePlayer
215099  WeakestLink.Players.IndependentVoter
213883  WeakestLink.Players.SniperKiller
210653  WeakestLink.Players.MaxPlayer
210262  WeakestLink.Players.Bandwagon
209956  WeakestLink.Players.MeanPlayer
208799  WeakestLink.Players.Coward
207686  WeakestLink.Players.Spy
204335  WeakestLink.Players.Hero
203957  WeakestLink.Players.MiddleMan
198535  WeakestLink.Players.MinPlayer
197589  WeakestLink.Players.FixatedPlayer
197478  WeakestLink.Players.HighOrLowNotSelf
181484  WeakestLink.Players.RandomPlayer
165160  WeakestLink.Players.BridgeBurner

1
nie rozumiem tego: „Na początku każdej rundy ... Powstaje grupa 9 graczy, a każdy z nich otrzymuje wyjątkową Spryt” nie na początku gry?
CSᵠ

1
@ CSᵠ poprawne. Twoja inteligencja zmienia się z rundy na rundę (inaczej byłoby niesprawiedliwe).
Nathan Merrill,

2
musi być stres i radość
CSᵠ

1
Czy powinienem oczekiwać konfiguracji kompilacji mrówek czy czegoś takiego? Jestem trochę nowy w Javie i nie jestem pewien, jak ludzie zwykle tworzą małe projekty takie jak ten.
Dale Johnson,

4
Od wewnątrz src\WeakestLinkużyłem javac Game\*.java Players\*.java Main.java, aby skompilować i java -cp .. WeakestLink.Mainuruchomić.
Linus

Odpowiedzi:


22

Snajper

Ogólna idea polega na tym, aby trzymać jednego z głupich graczy (tj. Tych, których łatwiej pokonać w pojedynku), aby strzelać do punktów. Następnie staramy się usunąć innych graczy o niskiej wartości, aby podnieść pulę. Ale kiedy dochodzimy do inteligentnych graczy, wybieramy najbardziej niebezpiecznych, na wypadek gdyby nasz głupi gracz został usunięty. W ten sposób, jeśli nie będziemy mieli kogoś do strzelania, powinniśmy zdobyć kogoś, z kim przynajmniej mamy szansę. Ponadto, ponieważ zawsze głosujemy z graczem minimalnym lub maksymalnym, oczekuję, że jesteśmy dość skuteczni w dotarciu na naszą stronę.

package WeakestLink.Players;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
public class Sniper extends Player {
    @Override
    public int vote(Set<Integer> currentOpponents) {
        int smrt = getSmartness();

        //count number of players smarter/stupider than me
        Iterator<Integer> opps = currentOpponents.iterator();
        int cnt_smrt=0, cnt_stpd=0, opp_smrt, min_stpd=10, max_smrt=0;

        while(opps.hasNext()){
            opp_smrt = opps.next().intValue();
            if(opp_smrt > smrt){
                cnt_smrt++;
                if(opp_smrt > max_smrt) max_smrt = opp_smrt;
            }
            else if(opp_smrt < smrt){
                cnt_stpd++;
                if(opp_smrt < min_stpd) min_stpd = opp_smrt;
            }
        }

        //remove low-value, then dangerous players
        if(cnt_stpd>1)
            return min_stpd;
        else
            return max_smrt;
    }
}

Więc najwyraźniej wycofanie nie usuwa zmian. Jeśli to w ogóle możliwe, chciałbym, aby wszelkie zmiany zostały usunięte, aby było jasne, że jest to oryginalna wersja.
Linus

12

PrudentSniper

Snajper , ale z dwoma wyjątkowymi zachowaniami. Jednym z nich jest to, że jeśli pozostały trzy boty, a PrudentSniper jest najmądrzejszy, będzie głosował na środkowego bota zamiast najmniej inteligentnego. To pozwala mu wygrać jeszcze kilka pojedynków. Innym zachowaniem jest to, że jeśli najmądrzejszy bot strzela do niego (ostatnio głosował na niego lub analogicznego bota), a najmniej inteligentny nie, będzie głosował na najmądrzejszego bota w samoobronie.

package WeakestLink.Players;
import WeakestLink.Game.Vote;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
public class PrudentSniper extends Player {
    @Override
    public int vote(Set<Integer> currentOpponents) {
        int smrt = getSmartness();

        //count number of players smarter/stupider than me, find max/min
        Iterator<Integer> opps = currentOpponents.iterator();
        int cnt_smrt=0, cnt_stpd=0, opp_smrt, min_stpd=10, max_smrt=0;

        while(opps.hasNext()){
            opp_smrt = opps.next().intValue();
            if(opp_smrt > max_smrt) max_smrt = opp_smrt;
            if(opp_smrt < min_stpd) min_stpd = opp_smrt;
            if(opp_smrt > smrt){
                cnt_smrt++;
            }
            else if(opp_smrt < smrt){
                cnt_stpd++;
            }
        }

        //identify enemies
        Iterator<Vote> votes = getRecentVotes().iterator();
        boolean[] voted_for_me = new boolean[9];

        while(votes.hasNext()) {
          Vote opp_vote = votes.next();
          voted_for_me[opp_vote.getVoter()] = (opp_vote.getVoted() == getSmartness() ||
                                              (opp_vote.getVoted() < getSmartness() && cnt_stpd < 1) ||
                                              (opp_vote.getVoted() > getSmartness() && cnt_smrt < 1));
        }

        if (currentOpponents.size() < 3 || cnt_stpd < 2 || (voted_for_me[max_smrt] && !voted_for_me[min_stpd] && cnt_smrt > 0) )
          return max_smrt;
        else
          return min_stpd;
    }
}

Nie jestem pewien, czy oba osiągnięcia mają taką samą wartość. Czy wypróbowałeś je osobno?
Linus

Zrobiłem to i chociaż sprawa trzech botów stanowi jednoznaczną poprawę (przynajmniej w porównaniu z botami obecnie znajdującymi się w master na repo), kara jest neutralna w sieci. Zostawiłem to jako niejasny środek odstraszający, środek ostrożności przeciwko zabójcom.
histocrat


Ostatnio naprawiłem błąd, w którym inteligencja wynosiła 0–8 zamiast 1–9. To zepsuło twój kod, więc go naprawiłem (możesz znaleźć zaktualizowany kod w repozytorium): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

12

Kult

Kultowi gracze mają nieco ezoteryczny schemat głosowania, w którym próbują się wzajemnie zidentyfikować i głosować jako grupa, wykorzystując tylko zapis głosowania. Ponieważ każdy członek kultu wie, jak głosować, każdy, kto głosuje inaczej, zostaje ujawniony jako osoba niebędąca członkiem i ostatecznie jest celem eliminacji.

Schemat głosowania w skrócie:

  • w pierwszej turze głosuj na najsłabszego zawodnika, współpraca z min & snajperem pomaga kultowi zyskać siłę
  • w kolejnych turach głosuj na znanych nie-członków, dopóki nie pozostanie tylko kult (głosujemy na nie-członków o najniższej wartości, aby zdobywać punkty, o ile uważamy, że mamy kontrolę).
  • gdy pozostali tylko członkowie, głosuj na członków o niskiej wartości na punkty (rzeczywiście poświęcając się dla dobra kultu).

Kod:

package WeakestLink.Players;
import WeakestLink.Game.Vote;
import java.util.Iterator;
import java.util.Set;
public class TheCult extends Player {
    private int cult_vote;
    private boolean[] isMember = null;
    @Override
    public int vote(Set<Integer> currentOpponents) {
        //on first turn, vote the code
        if(isMember == null){
            isMember = new boolean[10];
            for(int i=10; --i!=0;) isMember[i]=true; //runs 9-1
            return cult_vote = 1;
        }
        //on all other turn, assess who is not voting with the cult
        Vote opp_vote;
        int cult_cnt=0;
        Iterator<Vote> votes = getRecentVotes().iterator();
        while(votes.hasNext()){
            opp_vote = votes.next();
            if(opp_vote.getVoted() != cult_vote)
                isMember[opp_vote.getVoter()] = false;
            else
                cult_cnt++;
        }
        //find weakest and stongest non-members, and weakest members
        Iterator<Integer> opps = currentOpponents.iterator();
        int opp_smrt, min_mem=10, min_non=10, max_non=0;
        while(opps.hasNext()){
            opp_smrt = opps.next().intValue();
            if(isMember[opp_smrt]){
                if(opp_smrt < min_mem) min_mem = opp_smrt;
            }else{
                if(opp_smrt < min_non) min_non = opp_smrt;
                if(opp_smrt > max_non) max_non = opp_smrt;
            }
        }
        if(cult_cnt>2 && min_non!=10) cult_vote = min_non;
        else if(max_non!=0)           cult_vote = max_non;
        else                          cult_vote = min_mem;
        return cult_vote;
    }
}

Końcowe przemyślenia:

Kult przełącza się teraz na głosowanie na najgroźniejszych graczy, gdy do pojedynku pozostaje tylko dwóch lub mniej członków kultu. Przetestowałem go kilka razy cult_cnt>1i cult_cnt>2warunków oraz późniejszych zwycięstw częściej.

Jest to jednak środek ostrożności, a kult naprawdę nie jest przeznaczony do działania jako samotny gracz, więc wraz ze wzrostem liczby nowych graczy kult powinien ostatecznie stracić.


Czy nie lepiej byłoby najpierw zagłosować na najmądrzejszych nie-członków?
agweber,

Zaktualizowałem kod kontrolera, aby zmienna losowa była statyczna (i można uzyskać do niej dostęp za pośrednictwem Game.random). Pozwoliłem
Nathan Merrill

1
@NathanMerrill Dzięki, ale wydaje mi się, że osiągam lepsze wyniki, jeśli pozwolę, aby kult był bardziej tolerancyjny (patrz figura) wobec nieznanych nie-członków, którzy głosują w jego interesie.
Linus

@agweber, dzięki za sugestię. Prawdopodobnie sprawia to, że kult jest lepszym samotnym graczem, ale dopóki ma numery, powinien spróbować zwiększyć pulę. Myślę, że moja nowa wersja jest najlepsza z obu światów.
Linus

2
TheCult poprosił mnie, żebym zażądał , aby unusedPlayers.addAll(allPlayers);w Game.java powielić się około dziewięć razy, aby wszyscy gracze mogli występować w różnej różnorodności (jak tasowanie wielu talii kart) ... nie, oczywiście, to całkowicie stronnicze żądanie, ale ciekawe jest to, jak potężna może być nadal strategia zespołowa, jeśli mają nawet niewielką szansę na połączenie.
Linus

7

BridgeBurner

Nie gdzieś, gdzie mogę to teraz przetestować, a wyszło mi to na prawdę jak brzydki / głupi kod, ale powinno działać.

Ten bot po prostu chce być znienawidzony. Głosuje za tym, kto głosował przeciwko temu najmniej . W przypadku remisu wybiera ten, kto przeszedł najdłużej, nie głosując na niego. W przypadku kolejnego remisu wybiera najmądrzejszego z nich (prawdopodobnie dlatego, że będzie najgorszym wrogiem). Nie zagłosuje na siebie, ponieważ nikt tak naprawdę nie będzie go nienawidził, gdy go nie będzie w pobliżu.

package WeakestLink.Players;

import WeakestLink.Game.Vote;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BridgeBurner extends Player{
    @Override
    public int vote(Set<Integer> currentOpponents) {
        List<Integer> votes_against = Stream.generate(() -> 0).limit(9).collect(Collectors.toList());
        List<Integer> last_voted_against = Stream.generate(() -> 0).limit(9).collect(Collectors.toList());
        Iterator<Vote> votes_against_me = getVotesForSelf().iterator();

        for (int c = 0; c < 9; c++){
            if (!currentOpponents.contains(c)){
                votes_against.set(c,-1);
                last_voted_against.set(c,-1);
            }
        }

        while(votes_against_me.hasNext()){
            Vote vote = votes_against_me.next();

            int voter = vote.getVoter();
            int round = vote.getRound();

            if (currentOpponents.contains(voter)){
                votes_against.set(voter, votes_against.get(voter)+1);
                last_voted_against.set(voter, Math.max(round, last_voted_against.get(voter)));
            } else {
                votes_against.set(voter, -1);
                last_voted_against.set(voter, -1);
            }
        }

        int min_tally = Collections.max(votes_against);
        for (int c = 0; c < 9; c++){
            int current_tally = votes_against.get(c);
            if (current_tally != -1 && current_tally < min_tally){
                min_tally = current_tally;
            }
        }

        if (Collections.frequency(votes_against, min_tally) == 1){
            return votes_against.indexOf(min_tally);
        } else {
            List<Integer> temp_last_against = new ArrayList<>();
            for (int c = 0; c < 9; c++){
                if (votes_against.get(c) == min_tally){
                    temp_last_against.add(last_voted_against.get(c));
                }
            }
            return last_voted_against.lastIndexOf(Collections.min(temp_last_against));
        }
    }
}

Nie udało mi się uruchomić tego bota. Naprawiłem kilka błędów i teraz głosuje na nieistniejącego gracza. Jedyną zmianą, której nie byłem pewien, czy to prawda, było to, że „last_round_voted” nie jest zdefiniowany, więc zmieniłem go na „last_voted_against”. Moje zmiany możesz znaleźć tutaj: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@NathanMerrill Ten kod był najwyraźniej jeszcze gorszy niż myślałem. Teraz, gdy mogę to przetestować, przyjrzę się obu wersjom i spróbuję uruchomić to.
SnoringFrog,

@NathanMerrill Znaleziono kilka problemów. Mianowicie, nie ignorowałem graczy, którzy nie byli w znalezisku, którzy nigdy nie głosowali na bota, dlatego zawsze starał się na nich głosować. Używał również niewłaściwej listy, aby uzyskać indeks z jednego miejsca, w wyniku czego -1głosowano na gracza . Ale należy to teraz naprawić.
SnoringFrog,

1
Cóż, działa, ale działa okropnie. Gratulujemy pokonania losowego gracza!
Nathan Merrill,

1
@NathanMerrill o pokonaniu czasami
SnoringFrog,

6

Wóz dla orkiestry

Śledzi tłum podczas głosowania, chyba że to on jest celem.

package WeakestLink.Players;

import WeakestLink.Game.Vote;
import java.util.Map;
import java.util.Set;

/**
 * Votes for the currently most voted bot in the game. Or the lowest one.
 */
public class Bandwagon
        extends Player {

    @Override
    public int vote(Set<Integer> currentOpponents) {
        int self = getSmartness(), vote = -1;
        java.util.Map<Integer, Integer> votes = new java.util.TreeMap<>();
        getVotingHistory().stream().map((Vote v)-> v.getVoted()).filter((Integer i)-> !i.equals(self)).forEach((Integer tgt)-> {
            if(!votes.containsKey(tgt)) {
                votes.put(tgt, 1);
            } else {
                votes.put(tgt, votes.get(tgt) + 1);
            }
        });

        do {
            if(votes.entrySet().isEmpty()) {
                vote = currentOpponents.stream().filter((Integer i)-> !i.equals(self)).sorted().findFirst().get();
            } else {
                if(votes.containsKey(vote)) {
                    votes.remove(vote);
                    vote = -1;
                }

                for(Map.Entry<Integer, Integer> vv: votes.entrySet()) {
                    Integer key = vv.getKey();
                    Integer value = vv.getValue();

                    if((vote == -1) || (value > votes.get(vote))) {
                        vote = key;
                    }
                }
            }
        } while(!currentOpponents.contains(vote));

        return vote;
    }
}

Domyślam się, że ten tylko wzmocni snajperów, podążając za nimi, ale także pozwoli uniknąć celowania przez kult i pomocników snajperskich w nieco skuteczny sposób. Równie dobrze może być tarczą mięsną dla zabójców snajperów lub pomóc im, jeśli jest ich więcej. (Konieczność przetestowania przy użyciu najnowszych aktualizacji).

Korzystanie z funkcji Java 8, ponieważ gra i tak musi ją uruchomić.


1
Miło jest zobaczyć dobrze napisany kod :)
Nathan Merrill,

6

RevengePlayer

Ten bot będzie głosował na tego, kto głosował na niego najwięcej razy, a tiebreaker jest najmądrzejszym graczem. Teoria jest taka, że ​​gracz, który głosował na ciebie w przeszłości, prawdopodobnie zagłosuje na ciebie ponownie.

package WeakestLink.Players;
import java.util.Collections;
import java.util.Set;
import java.util.Iterator;
import WeakestLink.Game.Vote;
public class RevengePlayer extends Player{

    @Override
    public int vote(Set<Integer> opponents) {
        int[] A;
        A = new int[10];
        for(int i = 1;i < 10;i++)
            A[i] = opponents.contains(i)? i+1 : 0;
        Set<Vote> H = getVotingHistory();
        Iterator<Vote> I = H.iterator();
        while(I.hasNext()){
            Vote v = I.next();
            if(v.getVoted() == getSmartness())
                A[v.getVoter()] += A[v.getVoter()] != 0?10:0;
        }
        int maxI = 0;
        for(int i = 1;i < 10;i++)
            if(A[i] > A[maxI])
                maxI = i;
        return maxI;
    }
}

Ostatnio naprawiłem błąd, w którym inteligencja wynosiła 0–8 zamiast 1–9. To zepsuło twój kod, więc go naprawiłem (możesz znaleźć zaktualizowany kod w repozytorium): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@NathanMerrill Twoja poprawka dla mojego kodu miała mały błąd. Zmodyfikowałem swój kod, aby go ulepszyć.
MegaTom,

5

MeanPlayer

Nie głosuj ani na najgłupszych, ani na najmądrzejszych graczy, a on niesie broń (przemknął przez zabezpieczenia)

public class MeanPlayer extends Player{

    @Override
    public int vote(Set<Integer> currentOpponents) {
        int mid = currentOpponents.size() / 2;
        Object[] sortedOpponents = currentOpponents.toArray();
        Arrays.sort(sortedOpponents);
        return (int) sortedOpponents[mid];
    }
}

Nie rozumiem, dlaczego ten gracz jest wredniejszy niż reszta / sark
Nathan Merrill,

Uważaj @NathanMerrill, on ma broń!
Wybrałbym

10
@ CSᵠ Nie martwię się. Kiedy jest przeciętnym graczem, używa pistoletu na sobie.
kwintopia

14
Ten gracz jest mniej wredny, niż mogłaby być. Wydaje się być bardziej mediana niż średnia.
Jak

7
Hah .... zajęło mi chwilę
przywróć Monikę

5

AntiExtremist

Ten skrajny socjalista uważa, że ​​wszyscy ludzie powinni być jednakowo inteligentni. Próbuje zabić tych, którzy są znacznie mądrzejsi lub głupsi niż on. Rozważa oba, ale ogólnie preferuje głupie. Na początku faworyzuje głupich ludzi, a na koniec mądrych, ale zależy to od tego, jak skrajni są ci ludzie.

package WeakestLink.Players;
import java.util.Arrays;
import java.util.Set;

public class AntiExtremist extends Player {

    Object[] currentPlayers;

    @Override
    public int vote(Set<Integer> currentOpponents) {

        currentPlayers = (Object[]) currentOpponents.toArray();
        Arrays.sort(currentPlayers);

        int smartness = getSmartness();
        int turns = getTurnNumber();

        //// Lets get an idea of who's smart and who's dumb ////

        int smarter = 0, dumber = 0;

        int max_smart = 0, min_smart = 10;

        currentOpponents.toArray();

        for (int i = 0; i < currentPlayers.length; i++) {
            int osmart = (int)currentPlayers[i];

            if (osmart == smartness)
                continue;

            if (osmart > smartness) {
                smarter++;

                if (osmart > max_smart)
                    max_smart = osmart;
            }
            else if (osmart < smartness) {
                dumber++;

                if (osmart < min_smart)
                    min_smart = osmart;
            }

        }

        // int total = smarter+dumber;

        double smarter_ratio = smarter > 0 ? (max_smart-smartness)/4.5 : 0; 
        double dumber_ratio = dumber > 0 ? (smartness-min_smart)/3.0 : 0;//Favor dumber

        smarter_ratio*=.25+(turns/9.0*.75);
        dumber_ratio*=1-(turns/8.0*.75);

        return smarter_ratio > dumber_ratio ? max_smart : min_smart;

    }

}

UWAGA: Według Linusa będzie to głosować tak samo jak snajpera przez większość czasu (525602: 1228).


Na razie zamierzam utrzymać bieżący przebieg do 10 000 (dla szybszego testowania). Kiedy wykonam ostatni bieg, prawdopodobnie powiększę go.
Nathan Merrill,

Nie próbuję cię o nic oskarżać, ale to głosuje tak, jak Sniper ~ 99,7% czasu, w zasadzie będzie to rzut monetą, kto wygra, ponieważ są tak blisko tej samej strategii.
Linus

Skąd masz tę statystykę? Przyznaję, że ma częściowo podobną strategię, ale moim celem była próba ulepszenia czegoś tak prostego, jak twój, poprzez głosowanie na ludzi, którzy są bardzo mądrzy, jeśli są znacznie mądrzejsi ode mnie (inaczej mówiąc, raczej nie wygram puli, jeśli przeżyją)
csga5000

1
Dałem twojej klasie static Sniper S = new Sniper()a static long agrees=0, disagrees=0;. W metodzie głosowania dodaję, S.setSmartness(getSmartness()); int sniper_answer=S.vote(currentOpponents);która oblicza, jak snajper zagłosowałby na twoim stanowisku, a następnie umieściłem twoją odpowiedź w zmiennej, aby policzyć, czy się zgodziła, czy nie, przed zwrotem odpowiedzi. Po zakończeniu gry możesz wydrukować zgody: disagress, który wynosił 525602: 1228.
Linus

1
@Linus To ma sens, brzmi legalnie. Dodam notatkę na ten temat.
csga5000,

5

Szpieg

Szpieg jest zarezerwowany. Nie lubi strzelać do najmądrzejszych ludzi. Podobnie nie lubi wybierać bezbronnych idiotów. Dlatego lubi sprytnie eliminować tych, którzy są mu najbliżsi.

package WeakestLink.Players;

import java.util.Iterator;
import java.util.Set;

public class Spy extends Player{
  @Override
  public int vote(Set<Integer> currentOpponents) {
    int selfIntel = getSmartness();
    int closestIntel = 100; // default
    // get closest player
    Iterator<Integer> enemies = currentOpponents.iterator();
    while(enemies.hasNext()){
      int enemyIntel = enemies.next().intValue();
      if(Math.abs(enemyIntel - selfIntel) < closestIntel) closestIntel = enemyIntel;
    }
    return closestIntel;
  }
}

Właśnie zostałeś dźgnięty w plecy, mes amis . Nie obchodzi go, czy wygra. On po prostu lubi dźwięk noża w twoich plecach, kiedy z powodzeniem cię głosuje.

Właśnie zostałeś dźgnięty w plecy.


4
Ale ten obraz. +1
Addison Crump,

Myślę, że to ma błąd. Math.abs(enemyIntel - selfIntel) < closestIntelpowinno być Math.abs(enemyIntel - selfIntel) < Math.abs(closestIntel - selfIntel).
MegaTom,

@MegaTom Myślę, że masz rację. Sprawdzę to dalej, gdy będę mieć dostępną Javę. Dzięki za możliwy połów!
Conor O'Brien,

4

MedianPlayer

Ten gracz stara się być najgorszym (cóż, mediana).

Głosuje, aby wyeliminować najmądrzejszych i najgłupszych przeciwników (z lekką tendencją do głosowania na najmądrzejszych), w zależności od tego, czy są bardziej lub mniej mądrzejsi / głupsi od nich samych.

package WeakestLink.Players;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
public class MedianPlayer extends Player {
  @Override
  public int vote(Set<Integer> currentOpponents) {
    int smrt = getSmartness();

    //count number of players smarter/stupider than me
    Iterator<Integer> opps = currentOpponents.iterator();
    int cnt_smrt=0, cnt_stpd=0, min_stpd=10, max_smrt=0;

    while(opps.hasNext()){
      int opp_smrt = opps.next().intValue();
      if(opp_smrt > smrt){
        cnt_smrt++;
        if(opp_smrt > max_smrt)
          max_smrt = opp_smrt;
      } else if(opp_smrt < smrt){
        cnt_stpd++;
        if(opp_smrt < min_stpd)
          min_stpd = opp_smrt;
      }
    }

    // the middle must hold
    if(cnt_stpd>cnt_smrt)
      return min_stpd;
    else
      return max_smrt;
  }
}

ramy rażąco skradzione z @Linus powyżej.


Sprawiłeś, że moje IDE narzeka na powielony kod!
Nathan Merrill,

@NathanMerrill Atak kopiowania makaronu! Uwaga Zmieniłem nazwę klasy, odkąd opublikowałem. Podejrzewam, że powielanie cudzych nazwisk klas, aby upewnić się, że nie możesz się z nimi sprzeczić, byłoby sprzeczne z duchem zasad.
Jak

2
Dzięki za rażące kradzież mojej pracy lub przynajmniej przyznanie się do tego.
Linus,

2
@Linus Nie ma za co! Mam nadzieję, że imitacja jest najlepszą pochlebstwem.
Jak

2
@ csga5000 rażąco ukradł to jego żart, a ja po prostu się bawiłem . Każdy na wpół kompetentny programista (np. Ja) napisałby pętlę w ten sam sposób, więc tak naprawdę tylko kradł moje nazwy zmiennych. Gdybym pomyślał o ich prawach autorskich, może mógłbym naliczyć tantiemy; )
Linus,

4

Tchórz

package WeakestLink.Players;
import WeakestLink.Game.Vote;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
public class Coward extends Player {
  @Override
  public int vote(Set<Integer> currentOpponents) {

    boolean[] currentOpponent = new boolean[10];

    Iterator<Integer> opps = currentOpponents.iterator();
    while(opps.hasNext()){
      currentOpponent[opps.next().intValue()] = true;
    }

    int[] voteCounts = new int[9];
    for(int i=0; i<9; i++) {
        voteCounts[i] = 0;
    }

    Iterator<Vote> votes = getRecentVotes().iterator();

    while(votes.hasNext()){
      Vote opp_vote = votes.next();
      if(currentOpponent[opp_vote.getVoter()])
        voteCounts[opp_vote.getVoted()] += 1;
      else
        voteCounts[opp_vote.getVoter()] += 100;
    }

    int previous_weakest = -1;
    int max_votes_gotten = 0;
    for(int i=0;i<9;i++){
      if (voteCounts[i] > max_votes_gotten) {
        max_votes_gotten = voteCounts[i];
        previous_weakest = i;
      }
    }
    int min_closeness = 10;
    int to_vote = -1;
    int opp;
    int closeness;
    opps = currentOpponents.iterator();
    while(opps.hasNext()){
      opp = opps.next();
      closeness = Math.abs(opp - previous_weakest);
      if(closeness <= min_closeness) {
        to_vote = opp;
        min_closeness = closeness;
      }
    }

    return to_vote;

  }
}

Po prostu nie chce się głosować, więc głosuj na przeciwnika najbardziej podobnego do gracza, który został głosowany w ostatniej rundzie, aby zmaksymalizować szansę na bycie w zwycięskiej drużynie.

W tej chwili nie robi się szczególnie dobrze, ale równie dobrze może wrzucić to do miksu.


Ostatnio naprawiłem błąd, w którym inteligencja wynosiła 0–8 zamiast 1–9. To zepsuło twój kod, więc go naprawiłem (możesz znaleźć zaktualizowany kod w repozytorium): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

4

Bohater

Głosuj na tych, którzy wybierają słabych ... lub denerwują go.

package WeakestLink.Players;

import WeakestLink.Game.Game;
import WeakestLink.Game.Vote;

import java.util.*;

/**
 * Created by thenumberone on 12/2/15.
 * @author thenumberone
 */
public class Hero extends Player{

    @Override
    public int vote(Set<Integer> currentOpponents) {
        int me = getSmartness();
        Set<Vote> history = getVotingHistory();
        history.removeIf(vote -> !currentOpponents.contains(vote.getVoter()) || vote.getVoter() == me);
        int[] evilnessLevel = new int[Game.NUMBER_PLAYERS_PER_ROUND];
        for (Vote vote : history){
            evilnessLevel[vote.getVoter()] += vote.getVoted() == me ? 1_000_000 : Game.NUMBER_PLAYERS_PER_ROUND - vote.getVoted();
        }
        int mostEvilOpponent = -1;
        for (int opponent : currentOpponents){
            if (mostEvilOpponent == -1 || evilnessLevel[opponent] > evilnessLevel[mostEvilOpponent]){
                mostEvilOpponent = opponent;
            }
        }
        return mostEvilOpponent;
    }
}

Ostatnio naprawiłem błąd, w którym inteligencja wynosiła 0–8 zamiast 1–9. To zepsuło twój kod, więc go naprawiłem (możesz znaleźć zaktualizowany kod w repozytorium): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@NathanMerrill Dziękuję :)
TheNumberOne

4

Kok

Bob jest po prostu przeciętnym facetem, który uważa, że ​​jest mądrzejszy, niż jest naprawdę. Nie mogę wygrać rodziny snajperów, ale przez większość czasu zdobywam piątkę w moich symulacjach.

package WeakestLink.Players;

import java.util.Collections;
import java.util.Set;

import WeakestLink.Game.Vote;

public class BobPlayer extends Player {


    @Override
    public int vote(Set<Integer> currentOpponents) {
        int smartness;

        // Bob sometimes thinks he is smarter than he really is
        if (getRandom().nextInt(10) == 0) {
            smartness = 10;
        } else {
            smartness = getSmartness();
        }

        // If there is still some competition
        if (currentOpponents.size() > 3) {
            // And Bob is the dumbest
            if (smartness < Collections.min(currentOpponents)) {
                // Go for the smartest one
                return Collections.max(currentOpponents);
                // But if he is the smartest
            } else if (smartness > Collections.max(currentOpponents)) {
                // Go for the weak link
                return Collections.min(currentOpponents);
            } else {
                // Else revenge!
                for (Vote v : getRecentVotes()) {
                    if (v.getVoted() == smartness && currentOpponents.contains(v.getVoter())) {
                        return v.getVoter();
                    }
                }
            }
            return Collections.min(currentOpponents);
        } else {
            //If there are few opponents just revenge!
            for (Vote v : getRecentVotes()) {
                if (v.getVoted() == smartness && currentOpponents.contains(v.getVoter())) {
                    return v.getVoter();
                }
            }
            return Collections.max(currentOpponents);
        }
    }



}

4

FixatedPlayer

Wybiera losowy cel, a następnie głosuje na niego, aż zniknie. Nie zagłosuje jednak na siebie.

package WeakestLink.Players;

import WeakestLink.Game.Vote;

import java.util.*;

public class FixatedPlayer extends Player{
    @Override
    public int vote(Set<Integer> currentOpponents) {
        int self = getSmartness();
        Vote previous_vote = getLastVote();
        if (previous_vote == null || !currentOpponents.contains(previous_vote.getVoted())){
            return (int) currentOpponents.toArray()[getRandom().nextInt(currentOpponents.size())];
        }
        else {
            return previous_vote.getVoted();
        }
    }
}

Ten kod również nie działał, ale był łatwą poprawką. Twój czas na odejście nie jest w rzeczywistości konieczny, ponieważ nie daję ci twojej inteligencji, kiedy przekazuję ci twoich obecnych przeciwników. Naprawiony kod można znaleźć tutaj: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@NathanMerrill Zredagowałem poprawiony kod w mojej odpowiedzi, aby każdy, kto na niego patrzy, zobaczył, co jest aktualnie uruchamiane
SnoringFrog,

4

Statystyka

To nie jest wejście do konkursu. Jest to tylko sposób na uzyskanie przydatnych statystyk gry. Te statystyki drukują procentowe prawdopodobieństwo, że dany gracz zostanie wykluczony w danej rundzie.

Aby to zrobić, dodaj następujące wiersze, aby Round.javagóra pliku wyglądała tak:

package WeakestLink.Game;

import WeakestLink.Players.Player;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Round {

    private static int[][] statistics = new int[Game.NUMBER_PLAYERS_PER_ROUND - 2][Game.NUMBER_PLAYERS_PER_ROUND + 1];
    private static int[] counts = new int[Game.NUMBER_PLAYERS_PER_ROUND - 2];

    static {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            for (int i = 0; i < Game.NUMBER_PLAYERS_PER_ROUND - 2; i++){
                System.out.println();
                System.out.println("For " + (i+1) + "th round:");
                for (int j = 1; j <= Game.NUMBER_PLAYERS_PER_ROUND; j++){
                    System.out.println(String.format("%f%% voted for %d", 100.0*statistics[i][j]/counts[i], j));
                }
            }
        }));
    }

...

Następnie zmodyfikuj metodę głosowania, aby wyglądała tak:

private Vote vote(Player player){
    player.setVotingHistory(new HashSet<>(votes));
    player.setTurnNumber(currentTurn);
    player.setPot(pot);
    Set<Integer> players = currentPlayers.stream()
            .filter(p -> p != player)
            .map(playerToSmartness::get)
            .collect(Collectors.toSet());
    int vote = player.vote(players);
    if (!currentPlayers.contains(smartnessToPlayer.get(vote))){
        throw new RuntimeException(player.getClass().getSimpleName()+" voted off non-existent player");
    }
    Vote v = new Vote(playerToSmartness.get(player), vote, currentTurn);
    counts[v.getRound()]++;
    statistics[v.getRound()][v.getVoted()]++;
    return v;
}

Przykładowe dane wyjściowe:

For 1th round:
55.554756% voted for 1
4.279166% voted for 2
1.355189% voted for 3
1.778786% voted for 4
3.592771% voted for 5
3.952368% voted for 6
1.779186% voted for 7
6.427149% voted for 8
21.280630% voted for 9

For 2th round:
2.889877% voted for 1
34.080927% voted for 2
6.826895% voted for 3
4.990010% voted for 4
5.914753% voted for 5
4.985510% voted for 6
3.302524% voted for 7
11.304360% voted for 8
25.705144% voted for 9

For 3th round:
2.152783% voted for 1
13.005153% voted for 2
21.399772% voted for 3
7.122286% voted for 4
6.122008% voted for 5
6.761774% voted for 6
11.687049% voted for 7
19.607500% voted for 8
12.141674% voted for 9

For 4th round:
2.122183% voted for 1
10.105719% voted for 2
11.917105% voted for 3
17.547460% voted for 4
8.626131% voted for 5
12.079103% voted for 6
18.819449% voted for 7
11.065111% voted for 8
7.717738% voted for 9

For 5th round:
1.689826% voted for 1
7.364821% voted for 2
9.681763% voted for 3
11.704946% voted for 4
20.336237% voted for 5
20.691914% voted for 6
13.062855% voted for 7
9.332565% voted for 8
6.135071% voted for 9

For 6th round:
1.456188% voted for 1
6.726546% voted for 2
10.154619% voted for 3
16.355569% voted for 4
22.985816% voted for 5
17.777558% voted for 6
11.580207% voted for 7
7.757938% voted for 8
5.205558% voted for 9

For 7th round:
1.037992% voted for 1
6.514748% voted for 2
15.437876% voted for 3
22.151823% voted for 4
17.015864% voted for 5
14.029088% voted for 6
11.907505% voted for 7
7.957136% voted for 8
3.947968% voted for 9

1
1, 2, 3? Proponuję zmienić go tak, aby drukował „Do rundy 1” itp.
Skyler,

3

MaxPlayer

Wiem wszystko. Woli usuwać każdego, kto ma wysoką inteligencję (który może zatem rzucić wyzwanie swojemu niezrównanemu intelektowi)

public class MaxPlayer extends Player{

    @Override
    public int vote(Set<Integer> currentOpponents) {
        return Collections.max(currentOpponents);
    }
}

3

Strzec

Głosuj na tych, którzy wybierają mocnych ... lub tych, którzy go denerwują.

package WeakestLink.Players;

import WeakestLink.Game.Game;
import WeakestLink.Game.Vote;

import java.util.Set;

/**
 * Created by thenumberone on 12/2/15.
 * @author thenumberone
 */
public class Guard extends Player{

    @Override
    public int vote(Set<Integer> currentOpponents) {
        int me = getSmartness();
        Set<Vote> history = getVotingHistory();
        history.removeIf(vote -> !currentOpponents.contains(vote.getVoter()) || vote.getVoter() == me);
        int[] evilnessLevel = new int[Game.NUMBER_PLAYERS_PER_ROUND];
        for (Vote vote : history){
            evilnessLevel[vote.getVoter()] += vote.getVoted() == me ? 1_000_000 : vote.getVoted();
        }
        int mostEvilOpponent = -1;
        for (int opponent : currentOpponents){
            if (mostEvilOpponent == -1 || evilnessLevel[opponent] > evilnessLevel[mostEvilOpponent]){
                mostEvilOpponent = opponent;
            }
        }
        return mostEvilOpponent;
    }
}

Ostatnio naprawiłem błąd, w którym inteligencja wynosiła 0–8 zamiast 1–9. To zepsuło twój kod, więc go naprawiłem (możesz znaleźć zaktualizowany kod w repozytorium): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

3

Pijawka

Polega na innych botach, aby głosować na najmądrzejszych i najgłupszych facetów.

On jest zadowolony z stawili się gdzieś w środku i ostatecznie podział puli ze zwycięzcą (bo jest rzeczywiście bardzo przyzwoity facet bot).

package WeakestLink.Players;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;

public class Leech extends Player {
    /**
     * Copyrighted (not really, use this however you want friends) by Sweerpotato :~)!
     */
    @Override
    public int vote(Set<Integer> currentOpponents) {
        int mySmartness = getSmartness();

        ArrayList<Integer> opponentSmartness = new ArrayList<Integer>();
        opponentSmartness.addAll(currentOpponents);
        opponentSmartness.add(mySmartness);
        Collections.sort(opponentSmartness);

        if(mySmartness > 4 && mySmartness > Collections.min(opponentSmartness)) {
            //There's somebody dumber than me, vote that dude off
            return opponentSmartness.get(opponentSmartness.indexOf(mySmartness) - 1);
        }
        else {
            //Vote off the smartest guy, so we have a better chance to win
            if(mySmartness == Collections.max(opponentSmartness)) {
                //Apparently, we're the smartest guy
                return opponentSmartness.get(opponentSmartness.indexOf(mySmartness) - 1);
            }
            else {
                return Collections.max(opponentSmartness);
            }
        }
    }
}

2
Lubię. Obawiam się, że to nie będzie dobrze, ponieważ niewielu głosuje tak samo jak ty. To jedna z wad tej konkurencji - wydaje mi się, że inne boty zmuszają cię do dostosowania się do określonego rodzaju strategii.
csga5000,

3
Nadal fajnie! Wygrywanie to nie wszystko: ~)!
sweerpotato,

3

SniperKiller

Kolejna odpowiedź bezwstydnie skradziona z kodu Linusa . Ten zabije wszystkich snajperów, a nie ich ochroni. Jeśli wie, że nie ma już snajperów, będzie działał jak sam snajper.

package WeakestLink.Players;
import WeakestLink.Game.Vote;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;

public class SniperKiller extends Player {
    boolean[] sniperish;
    int[] sniperwouldvote;

    @Override
    public int vote(Set<Integer> currentOpponents) {
        int smrt = getSmartness();
        currentOpponents.add(smrt);
        if(sniperish==null){
            sniperish = new boolean[10];
            sniperwouldvote = new int[10];
            for(int i=10;--i!=0;){
                sniperish[i] = true;
                sniperwouldvote[i] = 1;
            }
            sniperish[smrt]=false; //knows we are not the sniper
            return 1;
        }
        //figure out who isn't a sniper
        Vote opp_vote;
        int opp_smrt;
        Iterator<Vote> votes = getRecentVotes().iterator();
        while(votes.hasNext()){
            opp_vote = votes.next();
            opp_smrt = opp_vote.getVoter();
            if(opp_vote.getVoted() != sniperwouldvote[opp_smrt])
                sniperish[opp_smrt] = false;
        }
        //figure out how snipers would vote this round
        Iterator<Integer> opps = currentOpponents.iterator();
        int cnt_opp=0, min_opp=10, max_opp=0;
        int[] snpr_votes = new int[10];
        while(opps.hasNext()){
            opp_smrt = opps.next().intValue();
            if(smrt == opp_smrt) continue;
            sniperwouldvote[opp_smrt] = hypothetically(opp_smrt, currentOpponents);
            cnt_opp++;
            if(sniperish[opp_smrt]){
                snpr_votes[sniperwouldvote[opp_smrt]]++;
            }
            if(opp_smrt<min_opp) min_opp=opp_smrt;
            if(opp_smrt>max_opp) max_opp=opp_smrt;
        }
        for(int i = 1;i<10;i++){//hit the weakest sniper.
            if(sniperish[i] && currentOpponents.contains(i))
                return i;
        }
        return hypothetically(smrt, currentOpponents);
    }

    private int hypothetically(int smrt, Set<Integer> currentOpponents) {
        Iterator<Integer> opps = currentOpponents.iterator();
        int cnt_smrt=0, cnt_stpd=0, opp_smrt, min_stpd=10, max_smrt=0;
        while(opps.hasNext()){
            opp_smrt = opps.next().intValue();
            if(opp_smrt > smrt){
                cnt_smrt++;
                if(opp_smrt > max_smrt) max_smrt = opp_smrt;
            }
            else if(opp_smrt < smrt){
                cnt_stpd++;
                if(opp_smrt < min_stpd) min_stpd = opp_smrt;
            }
        }
        if(cnt_stpd>1) return min_stpd;
        return max_smrt;
    }
}

1
Podoba mi się ten pomysł, ale wydaje się, że istnieje kultura głosowania na min. Lub maks. Gracza. głosowanie na kogoś innego może spowodować odrzucenie Twojego głosu . Może jeśli sprawdzisz, czy maksimum jest snajperskie, zanim zagłosujesz na kogoś innego, trochę nadrobisz zaległości ... (nie mogę sprawdzić przez telefon)
Linus

2

RandomPlayer

public class RandomPlayer extends Player{

    @Override
    public int vote(Set<Integer> currentOpponents) {
        return (int) currentOpponents.toArray()[getRandom().nextInt(currentOpponents.size())];
    }
}

2

MinPlayer

Elitarysta. Woli usunąć każdego o niskiej inteligencji.

public class MinPlayer extends Player {

    @Override
    public int vote(Set<Integer> currentOpponents) {
        return Collections.min(currentOpponents);
    }
}

2

VengefulSniper

Zaczęło się to od czegoś, co myślałem , że nazywało się pierwotnie StupidBuffering(imię, którego nienawidziłem się poddawać), a potem stało się po prostu PrudentSniper, który nie dbał o to, czy był celem. To także był jedyny powód, dla którego nie był w stanie pokonać PrudentSniper, więc poprawiłem trochę, żeby się skupić.

Teraz jest to po prostu snajper, ale jeśli najbystrzejszy lub najgłupszy bot namierzy go, będzie celował w każdego, kto uzyskał najwięcej głosów w ostatniej rundzie. Jeśli obaj otrzymali taką samą liczbę głosów i obaj go zaatakowali, wraca do normalnego zachowania snajperskiego. W moich testach ten rzeczywisty czasami pokonuje PrudentSniper.

package WeakestLink.Players;

import java.util.*;

import WeakestLink.Game.Vote;

public class VengefulSniper extends Player{
    @Override
    public int vote(Set<Integer> currentOpponents) {
        int me = getSmartness();
        int smartOpp = Collections.max(currentOpponents);
        int dumbOpp = Collections.min(currentOpponents);
        int votesAgainstSmart=0, votesAgainstDumb=0;
        Boolean targetedBySmart = false, targetedByDumb = false;

        Set<Vote> votesForMe = getRecentVotes();
        Iterator<Vote> votes = votesForMe.iterator();
        while(votes.hasNext()){
            Vote vote = votes.next();
            int voter = vote.getVoter();
            int voted = vote.getVoted();

            if(voted == me){
                if(voter == smartOpp){
                    targetedBySmart = true;
                }
                if(voter == dumbOpp){
                    targetedByDumb = true;
                }
            } else if (voted == smartOpp){
                votesAgainstSmart++;
            } else if (voted == dumbOpp){
                votesAgainstDumb++;
            }
        }

        // If being targeted by smartest or dumbest, take them out
        // Try to go with the rest of the crowd if they both targeted me
        if(targetedBySmart ^ targetedByDumb){
            return targetedBySmart ? smartOpp : dumbOpp;
        } else if (targetedBySmart && targetedByDumb){
            if (votesAgainstSmart > votesAgainstDumb){
                return smartOpp;
            } else if (votesAgainstDumb > votesAgainstSmart){
                return dumbOpp;
            }
        }

        Iterator<Integer> opps = currentOpponents.iterator();
        int cnt_stpd=0;
        while(opps.hasNext()){
            int opp_smrt = opps.next().intValue();
            if(opp_smrt < me){
                cnt_stpd++;
            }
        }

        if (cnt_stpd < 2 || (currentOpponents.size() < 4)){ //buffer is small, protect myself
            return smartOpp;
        } else {
            return dumbOpp;
        }
    }
}

2

Pośrednik

MiddleMan dokłada wszelkich starań, aby zmaksymalizować zyski, jednocześnie uważając, aby nie został odcięty od gry. Utrzymuje mniejszych zawodników, aby zwiększyć swoją szansę na przejście do następnej rundy (i pozostawić łatwe zakończenie). Głosuje za kimś mądrzejszym od niego tylko wtedy, gdy jest więcej mądrzejszych zawodników niż mniejszych. Niezależnie od tego, która z dwóch grup zawsze głosuje na najniższą z grup, aby pula nadal rosła.

package WeakestLink.Players;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
public class MiddleMan extends Player {
    @Override
    public int vote(Set<Integer> currentOpponents) {
        int smrt = getSmartness();

        //count number of players smarter/stupider than me
        Iterator<Integer> opps = currentOpponents.iterator();
        int cnt_smrt=0, cnt_stpd=0, opp_smrt, min_stpd=9, min_smrt=9;

        while(opps.hasNext()){
            opp_smrt = opps.next().intValue();
            if(opp_smrt > smrt){
                cnt_smrt++;
                if(opp_smrt < min_smrt) min_smrt = opp_smrt;
            }
            else if(opp_smrt < smrt){
                cnt_stpd++;
                if(opp_smrt < min_stpd) min_stpd = opp_smrt;
            }
        }

        //Keep myself in the middle of the pack, favoring the point earners
        if(cnt_stpd>cnt_smrt)
            return min_stpd;
        else
            return min_smrt;
    }
}

PS mam nadzieję, że się skompiluje, nie jestem facetem z Javy.

Miałem ten plan na myśli przed przeczytaniem innych wpisów. Potem byłem zaskoczony, jak blisko (ale krytycznie różny) był Sniper, więc zacząłem używać go jako punktu wyjścia, ponieważ nie znam składni Java. Dzięki @Linus


1
Sprawdź swój kod. nie próbuj pisać odpowiedzi w językach, których nie znasz
TanMath

@TanMath - Dziękujemy za Twój wkład. Mam duże doświadczenie w językach C / Java, jednak nie w Javie, więc jestem pewien, że mój kod jest poprawny i będzie działał. Biorąc to pod uwagę, jeśli wystąpi błąd i nie będzie działał, nie obrażę się, jeśli mistrz gry zdyskwalifikuje wpis.
tbernard

Masz rację. Dzięki @Linus. Edytowane.
tbernard

1
@tbernard Z przyjemnością naprawiam błędy, ale twój kod nie miał żadnych :)
Nathan Merrill

Ojej. Nie poszło tak dobrze, jak się spodziewałem. Wydawało mi się, że pomagam snajperowi, więc wydaje mi się, że to haha.
tbernard

2

ApproximatePosition

Ten bot próbuje strzelać w przybliżeniu wokół brakujących wartości inteligencji, zakładając, że grupa będzie kontynuować z tym samym wzorem, co oznacza, że ​​będzie celować w ten sam typ celu. Zawsze głosuje na najmądrzejszego z dwóch graczy, gdy jest wybór.

Dawno nie korzystałem z Javy, a obecnie pracuję, więc ... Nie mogę tego przetestować, mam nadzieję, że nie jest zbyt wadliwy, bądź łagodny proszę :).

Nawiasem mówiąc, używa awt.Point tylko dlatego, że jestem zbyt leniwy, aby zaimplementować krotkę n_n.

package WeakestLink.Players;
import WeakestLink.Game.Vote;

import java.util.*;
import java.awt.Point;

public class ApproximatePosition extends Player
{

    @Override
    public int vote(Set<Integer> currentOpponent)
    {
        List<Integer> present = new ArrayList<>(currentOpponent);
        List<Integer> emptyPosition = new ArrayList<Integer>();
        Collections.sort(present);

        //If it is the first round, vote for the smartest buddy
        if(present.size()==8)
            return present.get(present.size()-1);


        int lastCheck=present.get(0);
        if(lastCheck>0)
            for(int i=0;i<lastCheck;i++)
                if(i!=getSmartness()&&!emptyPosition.contains(i))
                    emptyPosition.add(i);
        for(int i=1;i<present.size();i++)
        {
            if(present.get(i)-lastCheck>1)
                for (int j=lastCheck+1;j<present.get(i);j++)
                    if(j!=getSmartness()&&!emptyPosition.contains(j))
                        emptyPosition.add(j);
            lastCheck=present.get(i);
        }
        //untill there's at least 3 excluded members, we continue with this behaviour
        if(emptyPosition.size()<=2)
        {
            if(emptyPosition.isEmpty()) return present.get(present.size()-1);
            return decide(emptyPosition.get(0),present.get(present.size()-1),present.get(0),present);
        }

        Point maxRangeOfBlank=new Point(present.get(present.size()-1),present.get(present.size()-1));
        for (int i=0;i<emptyPosition.size()-1;i++)
            if(emptyPosition.get(i+1)-emptyPosition.get(i)==1)
            {
                int size=0;
                while(i+size+1<emptyPosition.size() && emptyPosition.get(i+size+1)-emptyPosition.get(i+size)==1)
                    size++;
                if(size>=sizeOfRange(maxRangeOfBlank))
                    maxRangeOfBlank=new Point(emptyPosition.get(i),emptyPosition.get(size));
                i+=size;
            }

        return decide(maxRangeOfBlank,present.get(present.size()-1),present.get(0),present);
    }

    private int decide(int blankSeat, int smartest,int dumbest,List<Integer> present)
    {
        return decide(new Point(blankSeat,blankSeat),smartest,dumbest,present);
    }

    private int decide(Point rangeBlankSeat, int smartest,int dumbest,List<Integer> present)
    {
        int target= smartest;
        if (rangeBlankSeat.getY()==smartest||((int)rangeBlankSeat.getY()+1)==getSmartness()){
            if ((rangeBlankSeat.getX()==dumbest||(int)rangeBlankSeat.getX()-1==getSmartness())){
                target= smartest; //should not happen
            } else {
                target= (int) rangeBlankSeat.getX()-1; //Vote for dumber than the missing
            }
        } else {
            target= (int) rangeBlankSeat.getY() +1; //Vote for smarter than the missing, default comportment
        }
        if(present.contains(target))
            return target;
        return smartest;
    }
    //Return the number of consecutive values between X and Y (included)
    private int sizeOfRange(Point range)
    {
        return (int)(range.getY()-range.getX())+1;
    }

}

Było więc kilka błędów. :) Po pierwsze, niestety obsada Integer [] nie działa, musi to być obsada Object [] (której nie lubię). Więc wszystko to zapakowałem w ArrayList zamiast w tablicę. Po drugie, ta linia: emptyPosition[emptyPosition.length]=j;zawsze da ci tablicę poza granicami. Wreszcie, nie jestem pewien, dlaczego, ale zagłosujesz za graczami, którzy nie są w rundzie.
Nathan Merrill,

Aha, twój trójskładnikowy blok zwracał podwójne zamiast int i był bardzo zawiły, zamieniłem go w standard if / else. Wszystkie moje zmiany można znaleźć na Github: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@NathanMerrill Wow, wielkie dzięki. Albowiem emptyPosition[emptyPosition.length]jest to głupi błąd jak długość jest zawsze jeden w ciągu ostatniego indeksu ^^. Dzięki za zmiany, użyję tej nowej wersji, aby ją poprawić. O bloku trójskładnikowym ... tak, miałem ochotę go użyć, a może zbyt przyzwyczajony do pisania dla siebie, chyba nie był przydatny do czytania. Robienie poprawek i aktualizacja.
Katenkyo,

2

SniperAide

Przed dodaniem PrudentSniper pisałem bota pomóc snajper pokazał AntiExtremist i innych oszustw (używam tego słowa z miłością). Bot, SniperAide, szuka graczy, którzy głosują jak snajperzy i głosują tak, jak sądzą, że zrobiliby to w przypadku konsensu. Jeśli wszyscy gracze wyglądają jak snajperzy, głosuje na maksimum, chroniąc niższych snajperów (który również w tym momencie przeszedłby na maksimum), nawet jeśli to on sam.

Kod :

package WeakestLink.Players;
import WeakestLink.Game.Vote;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;

public class SniperAide extends Player {
    boolean[] sniperish;
    int[] sniperwouldvote;

    @Override
    public int vote(Set<Integer> currentOpponents) {
        int smrt = getSmartness();
        if(sniperish==null){
            sniperish = new boolean[10];
            sniperwouldvote = new int[10];
            for(int i=10;--i!=0;){
                sniperish[i] = true;
                sniperwouldvote[i] = 1;
            }
            sniperish[smrt]=false; //knows we are not the sniper
            return 1;
        }
        //figure out who might isn't a sniper
        Vote opp_vote;
        int opp_smrt;
        Iterator<Vote> votes = getRecentVotes().iterator();
        while(votes.hasNext()){
            opp_vote = votes.next();
            opp_smrt = opp_vote.getVoter();
            if(opp_vote.getVoted() != sniperwouldvote[opp_smrt])
                sniperish[opp_smrt] = false;
        }
        //include ourself in the simulation of other snipers.
        currentOpponents.add(smrt);
        //figure out how snipers would vote this round
        Iterator<Integer> opps = currentOpponents.iterator();
        int cnt_snpr=0, cnt_opp=0, min_opp=10, max_opp=0;
        int[] snpr_votes = new int[10];
        while(opps.hasNext()){
            opp_smrt = opps.next().intValue();
            if(smrt == opp_smrt) continue;
            sniperwouldvote[opp_smrt] = hypothetically(opp_smrt, currentOpponents);
            cnt_opp++;
            if(sniperish[opp_smrt]){
                cnt_snpr++;
                snpr_votes[sniperwouldvote[opp_smrt]]++;
            }
            if(opp_smrt<min_opp) min_opp=opp_smrt;
            if(opp_smrt>max_opp) max_opp=opp_smrt;
        }
        //figure out how to vote in sniper's intrest when not identified
        if(cnt_snpr == cnt_opp)
            return max_opp;
        if(cnt_snpr == 0)
            return hypothetically(smrt, currentOpponents);
        //if multiple hypothetical snipers only vote how they agree
        int onlyvote = -1;
        for(int i=10; --i!=0;){
            if(onlyvote>0 && snpr_votes[i]!=0) onlyvote=-2;
            if(onlyvote==-1 && snpr_votes[i]!=0) onlyvote=i;
        }
        if(onlyvote>0) return onlyvote;
        return max_opp;
    }

    private int hypothetically(int smrt, Set<Integer> currentOpponents) {
        Iterator<Integer> opps = currentOpponents.iterator();
        int cnt_smrt=0, cnt_stpd=0, opp_smrt, min_stpd=10, max_smrt=0;
        while(opps.hasNext()){
            opp_smrt = opps.next().intValue();
            if(opp_smrt > smrt){
                cnt_smrt++;
                if(opp_smrt > max_smrt) max_smrt = opp_smrt;
            }
            else if(opp_smrt < smrt){
                cnt_stpd++;
                if(opp_smrt < min_stpd) min_stpd = opp_smrt;
            }
        }
        if(cnt_stpd>1) return min_stpd;
        return max_smrt;
    }
}

Obecnie nie jest zbyt pomocny przeciwko PrudentSniper.


Na podstawie twojego opisu i teorii nie widzę, w jaki sposób pomógłby to jakiemukolwiek botowi snajperskiemu pokonać innych snajperów .. gdyby nic nie chroniłoby wszystkich snajperów? Przepraszam, nie mam więcej czasu, aby zagłębić się w twój kod i naprawdę go zrozumieć.
csga5000,

@ csga5000, Ponieważ rzadko możesz zidentyfikować Snajpera poprzez głosowanie, teraz chroni je trochę. Ale kiedy różnica jest wyraźna, zawsze działa w interesie Snajperów, więc najczęściej jest to rodzaj rozstrzygnięcia. Zwycięstwo koncentruje się na grach makroskopowych, a nie pojedynczych rundach, w większości rund naprawdę nie można zrobić nic więcej niż utrzymać sytuację, w której można rzucić monetą.
Linus

1

HighOrLowNotSelf

Usuwa losowo najniższego lub najwyższego gracza inteligencji (ale nie siebie).

public class HighOrLowNotSelf extends Player{
    @Override
    public int vote(Set<Integer> ops) {
        int b=Math.round(Math.random()*1);
        int p;
        if(b==1) p=Collections.max(ops) else p=Collections.min(ops);
        if(p==getSmartness()) {
            return vote(ops);
        }
        return p;
    }
}

W związku z tym zgłoszeniem istnieje kilka błędów. Po pierwsze, Math.round () zwraca a long, a nie int. Po drugie, opsnie zawiera siebie. (Jeśli chcesz głosować na siebie, musisz to wyraźnie dołączyć). Wreszcie, jeśli podałeś / jeśli nie jest prawidłową Javą. Naprawiłem twój kod i dodałem go do github
Nathan Merrill,

1

Anarchista

Anarchista nie lubi reżimów.
Anarchista będzie próbował zabić obecnego prezydenta.
Jeśli anarchista jest prezydentem, postanawia nadużyć swojej władzy i zabić bezużytecznych peagentów. Chyba że jeden z jego podwładnych był celem, bo zamiast tego powinni się palić.

package WeakestLink.Players;

import WeakestLink.Game.Vote;

import java.util.LinkedList;
import java.util.Set;

public class Anarchist extends Player {

    LinkedList<Integer> opponents;

    @Override
    public int vote(Set<Integer> currentOpponents) {
        opponents = new LinkedList();
        opponents.addAll(currentOpponents);
        opponents.sort(Integer::compare);

        int me = getSmartness();

        if (getPresident() != me) {
            return getPresident();
        } else {
            // treason ?
            Vote voteForMe = getRecentVotes().stream().filter(v -> v.getVoted() == me).findAny().orElse(null);
            if (voteForMe == null) {
                // No treason ! Hurray. Kill the peagants.
                return getPeagant();
            } else {
                // TREASON!
                return opponents.get(opponents.indexOf(voteForMe.getVoter()));
            }
        }
    }

    private int getPresident() {
        return opponents.getLast();
    }

    private int getPeagant() {
        return opponents.getFirst();
    }

}

1

IndependentVoter

Ten bot wie, że ogólna populacja zawsze się myli! Głosuje więc na każdego, kto otrzyma najmniej głosów.

Kod jest prawie identyczny z „Bandwagon” SolarAarona, ale logika końca jest odwrócona.

package WeakestLink.Players;

import WeakestLink.Game.Vote;
import java.util.Map;
import java.util.Set;

/**
 * Votes for the currently lest voted bot in the game.
 * Or the lowest one.
 */
public class IndependentVoter
        extends Player {

    @Override
    public int vote(Set<Integer> currentOpponents) {
        int self = getSmartness(), vote = -1;
        java.util.Map<Integer, Integer> votes = new java.util.TreeMap<>();
        getVotingHistory().stream().map((Vote v)-> v.getVoted()).filter((Integer i)-> !i.equals(self)).forEach((Integer tgt)-> {
            if(!votes.containsKey(tgt)) {
                votes.put(tgt, 1);
            } else {
                votes.put(tgt, votes.get(tgt) + 1);
            }
        });

        do {
            if(votes.entrySet().isEmpty()) {
                vote = currentOpponents.stream().filter((Integer i)-> !i.equals(self)).sorted().findFirst().get();
            } else {
                if(votes.containsKey(vote)) {
                    votes.remove(vote);
                    vote = -1;
                }

                for(Map.Entry<Integer, Integer> vv: votes.entrySet()) {
                    Integer key = vv.getKey();
                    Integer value = vv.getValue();

                    if((vote == -1) || (value < votes.get(vote))) {
                        vote = key;
                    }
                }
            }
        } while(!currentOpponents.contains(vote));

        return vote;
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.