Du bist das schwächste Glied, Auf Wiedersehen


50

Diese Herausforderung basiert auf der Game-Show Weakest Link . Für diejenigen, die mit der Show nicht vertraut sind, ist der Kern dieser Herausforderung, wen Sie abstimmen :

  • Wenn die anderen Spieler klüger sind als Sie, haben Sie weniger Chancen auf den Pot.
  • Wenn die anderen Spieler dümmer sind als Sie, haben Sie weniger Pot zu bekommen.

Zu Beginn jeder Runde beginnt der Pot mit 0 $. Eine Gruppe von 9 Spielern wird gebildet und jedem Spieler wird eine einzigartige Intelligenz von 1 bis 9 verliehen.

Zu Beginn jeder Runde Pot += Smartnessfür jeden Spieler, der noch in der Runde ist. Dann stimmen die Spieler über den Spieler ab, den sie entfernen möchten. Der Spieler mit den meisten Stimmen wird entfernt. Im Falle eines Gleichstands wird der intelligentere Spieler behalten.

Wenn nur noch 2 Spieler in der Runde sind, treten sie in einem Kampf um den Verstand gegeneinander an. Die Gewinnchance des Spielers ist Smartness/(Smartness+OpponentSmartness). Der Gewinner erhält dann den gesamten Pot.

Der Spieler, der am Ende des Spiels das meiste Geld erhalten hat, gewinnt.

Input-Output

In jeder Runde erhalten Sie die aktuelle Liste der Gegner. Über die Funktionen in der Spielerklasse haben Sie Zugriff auf Ihre Intelligenz und den gesamten Abstimmungsverlauf aller Spieler für die Runde.

Als Ausgabe müssen Sie eine einzelne Ganzzahl zurückgeben, die den Spieler darstellt, für den Sie stimmen möchten (für dessen Schlauheit). Das Wählen für sich selbst ist erlaubt (aber nicht empfohlen).

Runden mit 9 Runden werden wiederholt, bis alle Spieler mindestens 1000 bis 10000 Runden gespielt haben und alle Spieler die gleiche Anzahl von Runden gespielt haben.

Den Controller finden Sie hier: https://github.com/nathanmerrill/WeakestLink

Um einen Player zu erstellen, müssen Sie die Player-Klasse erweitern und Ihren Player der PlayerFactory-Klasse hinzufügen. Ihre Klasse muss die folgenden Regeln befolgen:

  1. Kommunikation oder Interferenzen mit anderen Spielern (einschließlich Ihrer anderen Spieler desselben Typs) sind strengstens untersagt.

  2. Reflexions- und statische Variablen (außer Konstanten) sind nicht zulässig.

  3. Wenn Sie die Zufälligkeit verwenden möchten, habe ich eine getRandom()Funktion in der Player-Klasse bereitgestellt . Verwenden Sie es, damit Simulationen deterministisch sein können.

Ich habe in der Player-Klasse viele Funktionen für den einfachen Zugriff auf Daten bereitgestellt. Sie können sie online auf Github finden . Ihr Spieler wird bei jeder neuen Runde instanziiert. "Dumme / Selbstmörderische" Spieler sind erlaubt (aber nicht Spieler mit der gleichen Strategie).

Scores

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
Verstehe das nicht: "Zu Beginn jeder Runde ... Eine Gruppe von 9 Spielern wird gebildet, und jedem Spieler wird eine einzigartige Intelligenz verliehen." Nicht zu Beginn des Spiels?
CSᵠ

1
@ CSᵠ richtig. Ihre Schlauheit ändert sich von Runde zu Runde (sonst wäre es unfair).
Nathan Merrill

2
muss der Stress und die Freude sein
CSᵠ

1
Sollte ich mit einer Ameisen-Build-Konfiguration oder einer solchen rechnen? Ich bin ein bisschen neu in Java, und ich bin mir nicht sicher, wie die Leute normalerweise kleine Projekte wie dieses aufsetzen.
Dale Johnson

4
Von innen habe src\WeakestLinkich javac Game\*.java Players\*.java Main.javakompiliert und java -cp .. WeakestLink.Mainausgeführt.
Linus

Antworten:


22

Scharfschütze

Die allgemeine Idee ist, dass einer der dummen Spieler (dh diejenigen, die wir eher im Anspiel schlagen) nach Punkten schnappt. Danach versuchen wir, die anderen Spieler mit niedrigem Wert zu entfernen, um den Pot zu erhöhen. Aber wenn wir zu den intelligenten Spielern kommen, entscheiden wir uns dafür, die gefährlichsten zu entfernen, falls unser dummer Spieler entfernt wird. Auf diese Weise sollten wir jemanden finden, gegen den wir zumindest eine Chance haben, wenn wir niemanden haben, gegen den wir vorgehen können. Da wir immer mit einem Min- oder Max-Spieler abstimmen, bin ich davon überzeugt, dass wir uns recht effektiv durchsetzen können.

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;
    }
}

Offensichtlich entfernt Rollback keine Änderungen. Wenn es irgend möglich ist, möchte ich, dass Änderungen entfernt werden, um deutlich zu machen, dass es sich um die Originalversion handelt.
Linus

12

PrudentSniper

Scharfschütze , aber mit zwei besonderen Verhaltensweisen. Eine ist, dass wenn noch drei Bots übrig sind und PrudentSniper der klügste ist, er für den mittleren Bot stimmen wird, anstatt für den am wenigsten klugen. Dies ermöglicht es ihm, ein paar weitere Showdowns zu gewinnen. Das andere Verhalten ist, dass, wenn der intelligenteste Bot danach schießt (beim letzten Mal dafür gestimmt oder der analoge Bot) und der am wenigsten intelligente nicht, er in der Selbstverteidigung für den intelligentesten stimmt.

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;
    }
}

Ich bin mir nicht sicher, ob beide Fortschritte gleich viel wert sind. Hast du sie jeweils einzeln ausprobiert?
Linus

Das habe ich getan, und während der Fall der drei Bots eine eindeutige Verbesserung darstellt (zumindest gegenüber den Bots, die derzeit im Repo-Master sind), ist die Vergeltung im Netz ungefähr neutral. Ich habe es als eine Art vage Abschreckung hinterlassen, als Vorsichtsmaßnahme gegen Attentäter.
Histokrat


Ich habe kürzlich einen Fehler behoben, bei dem die Schlauheit 0-8 statt 1-9 war. Dies hat Ihren Code beschädigt und ich habe ihn behoben (Sie finden den aktualisierten Code im Repository): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

12

Der Kult

Die Kult-Spieler haben ein leicht esoterisches Abstimmungsschema, mit dem sie versuchen, sich gegenseitig zu identifizieren und als Gruppe abzustimmen, wobei sie nur den Abstimmungsbericht verwenden. Da jedes Mitglied des Kults weiß, wie man abstimmt, wird jeder, der anders abstimmt, als Nicht-Mitglied entlarvt und letztendlich zur Eliminierung ausgewählt.

Das Abstimmungsschema auf einen Blick:

  • Bei der ersten Abstimmung für den schwächsten Teilnehmer hilft die Zusammenarbeit mit min & sniper dem Kult, an Macht zu gewinnen
  • In den folgenden Runden stimmen Sie bekannte Nichtmitglieder ab, bis nur noch der Kult übrig ist (wir stimmen das Nichtmitglied mit dem niedrigsten Wert ab, um Punkte zu sammeln, solange wir glauben, die Kontrolle zu haben).
  • Wenn nur noch Mitglieder übrig sind, stimmen Sie Mitglieder mit niedrigem Wert für Punkte ab (tatsächlich opfern Sie sich für das Wohl des Kults).

Der Code:

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;
    }
}

Abschließende Gedanken:

Der Kult wählt nun die gefährlichsten Spieler, wenn nur noch zwei oder weniger Kultmitglieder für das Duell übrig sind. Ich habe es mehrmals mit cult_cnt>1und cult_cnt>2Bedingungen getestet und der spätere gewinnt öfter.

Trotzdem ist dies eine Vorsichtsmaßnahme und der Kult ist wirklich nicht dafür gedacht, als Einzelspieler zu arbeiten. Je mehr neue Spieler hinzukommen, desto mehr sollte der Kult irgendwann verlieren.


Wäre es nicht besser, zuerst die klügsten Nichtmitglieder abzustimmen?
1.

Ich habe den Controller-Code so aktualisiert, dass die Zufallsvariable statisch ist (und über Game.random aufgerufen werden kann). Ich habe mir auch die Freiheit genommen, den Code auf github zu aktualisieren: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

1
@ NathanMerrill Danke, aber ich scheine bessere Ergebnisse zu erzielen, wenn ich zulasse, dass der Kult gegenüber unbekannten Nichtmitgliedern, die in seinem Interesse abstimmen, toleranter ist (siehe Abbildung).
Linus

@agweber, danke für den vorschlag. Dies macht das Volk wahrscheinlich zu einem besseren Einzelspieler, aber solange es die Zahlen hat, sollte es versuchen, den Pot aufzustocken. Ich denke, meine neue Version ist das Beste aus beiden Welten.
Linus,

2
TheCult hat mich gebeten zu verlangen, dass unusedPlayers.addAll(allPlayers);in Game.java etwa neun Mal dupliziert wird, damit alle Spieler in unterschiedlicher Vielfalt auftreten können (wie das Mischen mehrerer Kartenspiele) ... nein, natürlich nicht, das ist eine voreingenommene Anfrage, aber Es ist interessant zu sehen, wie effektiv die teambasierte Strategie sein kann, wenn sie nur eine geringe Chance hat, sich zusammenzusetzen.
Linus

7

BridgeBurner

Nicht irgendwo, wo ich das jetzt testen kann, und es kam mir wirklich hässlich / dumm vor, aber es sollte funktionieren.

Dieser Bot will einfach nur gehasst werden. Es stimmt für den, der am wenigsten dagegen gestimmt hat . Bei einem Unentschieden wird derjenige ermittelt, der am längsten gegangen ist, ohne dafür zu stimmen. Bei einem erneuten Unentschieden wird der schlaueste ausgewählt (vermutlich, weil er den schlimmsten Feind darstellt). Es wird nicht für sich selbst stimmen, weil niemand es wirklich hassen wird, wenn es nicht da ist.

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));
        }
    }
}

Ich konnte diesen Bot nicht zum Laufen bringen. Ich habe mehrere Fehler behoben und es wird jetzt für einen nicht existierenden Spieler abgestimmt. Die einzige Änderung, bei der ich nicht sicher war, ob es richtig war, war, dass "last_round_voted" nicht definiert ist, also habe ich sie in "last_voted_against" geändert. Sie können meine Änderungen hier finden: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@ NathanMerrill Dieser Code war anscheinend noch schlimmer als ich dachte. Jetzt, da ich es testen kann, schaue ich mir beide Versionen an und versuche, diese zum Laufen zu bringen.
SnoringFrog

@ NathanMerrill Gefunden ein paar Probleme. Ich habe nämlich Spieler nicht ignoriert, die nicht in der Liste waren, die nie für den Bot gestimmt haben, weshalb immer versucht wurde, für sie zu stimmen. Verwendete auch die falsche Liste, um einen Index von einem Punkt zu erhalten, was dazu führte, dass der Spieler -1gewählt wurde. Aber es sollte jetzt behoben sein.
SnoringFrog

1
Nun, es funktioniert, tut aber schrecklich. Herzlichen Glückwunsch zum Sieg gegen einen zufälligen Spieler!
Nathan Merrill

1
@ NathanMerrill gegen zufällige Spieler manchmal
SnoringFrog

6

Zug

Folgt der Menge bei der Abstimmung, es sei denn, er ist derjenige, der als Ziel ausgewählt wird.

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;
    }
}

Ich vermute, dass dies die Scharfschützen nur stärker macht, wenn sie ihnen folgen, aber es auch verhindert, dass der Kult und die Scharfschützen-Helfer auf eine etwas effektive Art und Weise angegriffen werden. Es kann auch ein Schutzschild für Scharfschützenmörder sein oder ihnen helfen, wenn es mehr von ihnen gibt. (Muss mit den neuesten Updates getestet werden).

Verwendung von Java 8-Funktionen, da das Spiel dies sowieso benötigt, um zu laufen.


1
Es ist schön, gut geschriebenen Code zu sehen :)
Nathan Merrill

6

RevengePlayer

Dieser Bot wählt, wer am häufigsten für ihn gestimmt hat, wobei der Tiebreaker der klügste Spieler ist. Die Theorie ist, dass ein Spieler, der in der Vergangenheit für Sie gestimmt hat, wahrscheinlich wieder für Sie stimmen wird.

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;
    }
}

Ich habe kürzlich einen Fehler behoben, bei dem die Schlauheit 0-8 statt 1-9 war. Dadurch wurde Ihr Code beschädigt, und ich habe ihn behoben (den aktualisierten Code finden Sie im Repository): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@ NathanMerrill Ihr Update für meinen Code hatte einen kleinen Fehler. Ich habe meinen Code bearbeitet, um ihn zu verbessern.
MegaTom

5

MeanPlayer

Weder die dümmsten noch die klügsten Spieler wählen, und er trägt eine Waffe (hat sie an der Sicherheit vorbei geschlichen)

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];
    }
}

Ich verstehe nicht, warum dieser Spieler etwas gemeiner ist als der Rest / Sarc
Nathan Merrill

Pass auf @ Nathan Merrill, er hat eine Waffe! Ich würde meine Worte sorgfältig wählen, wenn ich Sie wäre ...
CSᵠ

10
@ CSᵠ Ich mache mir keine Sorgen. Wenn er der durchschnittliche Spieler ist, benutzt er die Waffe auf sich.
Quintopia

14
Diese Spielerin ist weniger gemein als sie sein könnte. Sie scheint mehr im Median als im Mittel zu sein.
Yakk

7
Hah ... brauchte eine Minute
Setzen Sie Monica

5

AntiExtremist

Dieser extreme Sozialist glaubt, dass alle Menschen gleich klug sein sollten. Er versucht, diejenigen zu töten, die viel schlauer oder dümmer sind als er. Er denkt über beides nach, bevorzugt aber generell Dummheiten. Er bevorzugt dumme Leute am Anfang und kluge am Ende, aber es hängt davon ab, wie extrem diese Leute sind.

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;

    }

}

HINWEIS: Laut Linus wird dies die meiste Zeit das Gleiche wie der Scharfschütze sein (525602: 1228).


Ich werde den aktuellen Lauf fürs Erste auf 10K halten (für schnellere Tests). Wenn ich den letzten Durchgang mache, werde ich ihn wahrscheinlich größer machen.
Nathan Merrill

Ich versuche nicht, Ihnen irgendetwas vorzuwerfen, aber dies stimmt in etwa 99,7% der Fälle mit Sniper überein, es wird im Grunde genommen ein Münzwurf sein, wer gewinnt, da sie der gleichen Strategie so nahe sind.
Linus

Woher haben Sie diese Statistik? Ich gebe zu, es hat eine halbähnliche Strategie, aber mein Ziel war es, etwas so Einfaches wie deins zu verbessern, indem ich für Leute stimme, die sehr schlau sind, wenn sie bedeutend schlauer als ich sind (auch wenn ich wahrscheinlich nicht gewinnen werde) Topf, wenn sie überleben)
csga5000

1
Ich habe deiner Klasse ein static Sniper S = new Sniper()und gegeben static long agrees=0, disagrees=0;. In Ihrer Abstimmungsmethode füge ich hinzu, S.setSmartness(getSmartness()); int sniper_answer=S.vote(currentOpponents);welche berechnet, wie ein Scharfschütze in Ihrer Position abstimmen würde, und setze dann Ihre Antwort in eine Variable, um zu zählen, ob sie zugestimmt oder nicht zugestimmt hat, bevor die Antwort zurückgegeben wird. Sobald das Spiel vorbei ist, können Sie ausdrucken: Nicht übereinstimmen, was 525602: 1228 war.
Linus

1
@Linus Das macht Sinn, klingt echt. Ich werde eine Anmerkung dazu hinzufügen.
csga5000

5

Spion

Spion ist reserviert. Er mag es nicht, für die klügsten Leute zu schießen. Ebenso mag er es nicht, viertelwehrlose Idioten aufzuspüren . Er mag es also, diejenigen, die ihm am nächsten sind, mit Schlauheit zu eliminieren.

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;
  }
}

Du wurdest gerade verprügelt, mes amis . Es ist ihm egal, ob er gewinnt. Er mag den Klang des Messers in Ihrem Rücken, als er Sie erfolgreich abstimmt.

Du wurdest gerade erst gestochen.


4
Das Bild allerdings. +1
Addison Crump

Ich denke das hat einen Bug. Math.abs(enemyIntel - selfIntel) < closestIntelsollte sein Math.abs(enemyIntel - selfIntel) < Math.abs(closestIntel - selfIntel).
MegaTom

@ MegaTom Ich denke du hast recht. Ich werde dies weiter überprüfen, wenn ich Java zur Verfügung habe. Danke für den möglichen Fang!
Conor O'Brien

4

MedianPlayer

Dieser Spieler versucht, der gemeinste (naja, mittelmäßige) zu sein, der noch übrig ist.

Es wird gewählt, um die klügsten und dümmsten Gegner zu eliminieren (mit einer leichten Neigung, die klügsten abzuwählen), je nachdem, ob es mehr oder weniger kluge / dümmer als sie selbst gibt.

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;
  }
}

Rahmen eklatant von @Linus oben gestohlen.


Sie haben meine IDE dazu gebracht, sich über doppelten Code zu beschweren!
Nathan Merrill

@ NathanMerrill Copy-Pasta-Angriff! Hinweis: Ich habe den Namen der Klasse geändert, seit ich gepostet habe. Ich nehme an, das Duplizieren des Klassennamens einer anderen Person, um sicherzustellen, dass du nicht gegen sie verstoßen kannst, verstößt gegen den Geist der Regeln.
Yakk

2
Danke, dass du meine Arbeit offen gestohlen hast oder zumindest zugibst.
Linus

2
@Linus Gern geschehen! Nachahmung ist die beste Schmeichelei, hoffe ich.
Yakk,

2
@ csga5000 krass gestohlen war sein Witz, und ich habe nur mitgespielt . Jeder halbwegs kompetente Programmierer (z. B. ich) würde die Schleife auf die gleiche Weise schreiben, also hat er wirklich nur meine Variablennamen gestohlen. Wenn ich daran gedacht hätte, sie urheberrechtlich zu schützen, könnte ich möglicherweise Lizenzgebühren erheben; )
Linus

4

Feigling

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;

  }
}

Will einfach nicht abgewählt werden, also stimmen Sie für den Gegner, der dem Spieler am ähnlichsten ist, der in der letzten Runde abgewählt wurde, um die Chance zu maximieren, im Gewinnerteam zu sein.

Macht sich momentan nicht besonders gut, könnte aber genauso gut in die Mischung eingehen.


Ich habe kürzlich einen Fehler behoben, bei dem die Schlauheit 0-8 statt 1-9 war. Dies hat Ihren Code beschädigt und ich habe ihn behoben (Sie finden den aktualisierten Code im Repository): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

4

Held

Stimmen Sie diejenigen ab, die sich für die Schwachen entscheiden ... oder ihn ärgern.

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;
    }
}

Ich habe kürzlich einen Fehler behoben, bei dem die Schlauheit 0-8 statt 1-9 war. Dies hat Ihren Code beschädigt und ich habe ihn behoben (Sie finden den aktualisierten Code im Repository): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@ NathanMerrill Vielen Dank :)
TheNumberOne

4

Bob

Bob ist nur der Durchschnittsbürger, der denkt, er sei schlauer als er wirklich ist. Ich kann die Scharfschützenfamilie nicht gewinnen, erreiche aber die meiste Zeit die Top 5 in meinen Simulationen.

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

Wählt ein zufälliges Ziel und wählt es, bis es verschwunden ist. Wirst aber nicht für sich selbst stimmen.

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();
        }
    }
}

Dieser Code funktionierte auch nicht, war aber eine einfache Lösung. Dein Do-while ist eigentlich nicht nötig, denn ich gebe dir nicht deine Schlauheit, wenn ich dir deine aktuellenOpponents übergebe. Der feste Code kann hier gefunden werden: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@ NathanMerrill Ich habe den korrigierten Code in meine Antwort geändert, damit jeder, der ihn hier ansieht, sieht, was tatsächlich ausgeführt wird
SnoringFrog

4

Statistiken

Dies ist kein Beitrag zum Wettbewerb. Dies ist lediglich eine Möglichkeit, nützliche Statistiken eines Spiels abzurufen. Diese Statistiken geben die prozentuale Wahrscheinlichkeit an, mit der ein bestimmter Spieler in einer Runde abgewählt wird.

Fügen Sie dazu die folgenden Zeilen hinzu, Round.javadamit der Anfang der Datei wie folgt aussieht:

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));
                }
            }
        }));
    }

...

Ändern Sie dann die Abstimmungsmethode wie folgt:

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;
}

Beispielausgabe:

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.? Ich würde vorschlagen, es zu ändern, um "Für Runde 1" usw. zu drucken
Skyler

3

Max Spieler

Ein Besserwisser. Entfernt lieber jemanden mit hoher Intelligenz (der daher seinen unübertroffenen Intellekt herausfordern kann)

public class MaxPlayer extends Player{

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

3

Bewachen

Stimmen Sie diejenigen ab, die sich für die Starken entscheiden ... oder diejenigen, die ihn ärgern.

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;
    }
}

Ich habe kürzlich einen Fehler behoben, bei dem die Schlauheit 0-8 statt 1-9 war. Dies hat Ihren Code beschädigt und ich habe ihn behoben (Sie finden den aktualisierten Code im Repository): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

3

Blutegel

Verlässt sich auf andere Bots, um die klügsten und dümmsten Typen abzuwählen.

Er ist zufrieden damit, irgendwo in der Mitte aufzutauchen und irgendwann den Pot mit dem Gewinner zu teilen (da er eigentlich ein wirklich anständiger Typ Bot ist).

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
Ich mag. Ich mache mir Sorgen, dass es nicht gut wird, weil nicht viele genauso abstimmen werden wie Sie. Das ist ein Manko bei diesem Wettbewerb, es scheint mir, dass die anderen Bots Sie dazu zwingen, sich an eine bestimmte Art von Strategie zu halten.
csga5000

3
Trotzdem viel Spaß! Gewinnen ist nicht alles: ~)!
Sweerpotato

3

SniperKiller

Eine weitere Antwort, die schamlos aus Linus 'Code gestohlen wurde . Dieser tötet alle Scharfschützen, schützt sie aber nicht. Wenn es weiß, dass keine Scharfschützen mehr übrig sind, verhält es sich wie ein Scharfschütze.

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
Ich mag die Idee, aber es scheint eine Abstimmungskultur für Min- oder Max-Spieler zu geben. Wenn Sie für eine andere Person stimmen, wird Ihre Stimme möglicherweise verworfen . Wenn du prüfst, ob das Maximum scharf ist, bevor du für jemanden abstimmst, holst du vielleicht ein bisschen nach ... (Ich kann es nicht überprüfen, am 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

Ein Elitist. Entfernt lieber jemanden mit geringer Intelligenz.

public class MinPlayer extends Player {

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

2

VengefulSniper

Dies begann als etwas, von dem ich dachte, dass es ursprünglich genannt wurdeStupidBuffering (ein Name, den ich nicht aufgeben wollte), und endete dann als PrudentSniper, dem es egal war, ob er ins Visier genommen wurde. Dies schien auch der einzige Grund zu sein, warum er PrudentSniper nicht schlagen konnte, also habe ich die Dinge ein wenig verändert, um ihn zu fokussieren.

Das ist im Grunde genommen ein Scharfschütze, aber wenn der klügste oder dümmste Bot auf ihn zielt, zielt er auf denjenigen, der in der letzten Runde die meisten Stimmen erhalten hat. Wenn beide die gleiche Anzahl von Stimmen erhielten und beide auf ihn abzielten, kehrt er zum normalen Scharfschützenverhalten zurück. In meinen Tests schlägt dieses Produkt gelegentlich 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

Mittelsmann

Der MiddleMan versucht sein Bestes, um die Gewinne zu maximieren, und achtet dabei darauf, dass er nicht aus dem Spiel ausscheidet. Er hält sich mit weniger Teilnehmern zusammen, um seine Chance auf den Einzug in die nächste Runde zu verbessern (und ein leichtes Ziel zu erreichen). Er wird jemanden abwählen, der klüger ist als er, nur wenn es mehr klügere Kandidaten als weniger Kandidaten gibt. Unabhängig davon, welche der beiden Gruppen er ist, wählt er immer die niedrigste der Gruppe, um den Pot am Klettern zu halten.

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 hoffe, es kompiliert, ich bin kein Java-Typ.

Hatte dieses Schema im Hinterkopf, bevor ich die anderen Einträge las. Dann war ich überrascht, wie nah (aber kritisch anders) Sniper war, also ging ich voran und benutzte dies als Ausgangspunkt, da ich die Java-Syntax nicht kenne. Danke @Linus


1
Bitte testen Sie Ihren Code. Versuche nicht, Antworten in Sprachen zu schreiben, die du nicht kennst
TanMath

@ TanMath - Vielen Dank für Ihre Eingabe. Ich habe viel Erfahrung mit C / Java-ähnlichen Sprachen, jedoch nicht speziell mit Java, und bin daher ziemlich sicher, dass mein Code tatsächlich korrekt ist und funktionieren wird. Abgesehen davon, wenn es einen Fehler gibt und er nicht läuft, werde ich nicht beleidigt sein, wenn der Spielleiter den Eintrag disqualifiziert.
Tbernard

Du hast recht. Danke @Linus. Bearbeitet
tbernard

1
@ tbernard Ich bin froh, Fehler zu beheben, aber Ihr Code hatte keine :)
Nathan Merrill

Autsch. Hat sich nicht so gut geschlagen, wie ich gehofft hatte. Ich schien dem Scharfschützen zu helfen, also denke ich, haha.
tbernard

2

ApproximatePosition

Dieser Bot versucht, ungefähr um die fehlenden Smartness-Werte herum zu schießen, vorausgesetzt, die Gruppe wird mit demselben Muster fortfahren, was bedeutet, dass sie denselben Zieltyp anvisiert. Es wird immer für den klügsten von zwei Spielern gestimmt, wenn es eine Wahl gibt.

Lange habe ich kein Java verwendet und bin gerade auf der Arbeit, also ... Kann es nicht testen, hoffe es ist nicht zu fehlerhaft, sei bitte sanft :).

Übrigens wird awt.Point nur verwendet, weil ich zu faul bin, ein Tupel n_n zu implementieren.

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;
    }

}

Es gab also einige Bugs. :) Erstens funktioniert die Besetzung von Integer [] leider nicht, es muss eine Besetzung von Object [] sein (was mir nicht gefällt). Also habe ich alles in eine ArrayList anstatt in ein Array gewickelt. Zweitens gibt diese Zeile: emptyPosition[emptyPosition.length]=j;Ihnen immer ein Array außerhalb der Grenzen. Schließlich weiß ich nicht warum, aber Sie stimmen Spieler ab, die nicht in der Runde sind.
Nathan Merrill

Oh, auch, Ihr ternärer Block hat ein Double anstelle von int zurückgegeben und war sehr verworren. Ich habe es zu einem Standard gemacht, wenn / sonst. Sie können alle meine Änderungen auf Github finden: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Nathan Merrill

@ NathanMerrill Wow, vielen Dank. Für die emptyPosition[emptyPosition.length]ist es ein blöder Fehler, da Länge immer eins über dem letzten Index ist ^^. Vielen Dank für die Änderungen. Ich werde diese neue Version verwenden, um sie zu korrigieren. Über den ternären Block ... Ja, ich hatte das Gefühl, ihn zu benutzen, und vielleicht war ich es zu gewohnt, für mich selbst zu schreiben. Korrekturen vornehmen und aktualisieren.
Katenkyo

2

SniperAide

Vor der Zugabe von PrudentSniper ich einen Bot schrieb Hilfe Sniper schlagen AntiExtremist und andere Betrügereien (benutze ich das Wort mit Liebe). Der Bot, SniperAide, sucht nach Spielern, die wie Scharfschützen abstimmen und abstimmen, so wie es der Fall ist, wenn Konsens herrscht. Wenn alle Spieler wie Scharfschützen aussehen, wählt er das Maximum und schützt die unteren Scharfschützen (die zu diesem Zeitpunkt ebenfalls zum Maximum wechseln würden), auch wenn es sich selbst handelt.

Der Code :

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;
    }
}

Er hilft derzeit nicht viel gegen PrudentSniper.


Basierend auf Ihrer Beschreibung und Theorie sehe ich nicht, wie dies einem Scharfschützen-ähnlichen Bot helfen würde, andere Scharfschützen zu schlagen. Wenn irgendetwas nicht würde, würde es einfach alle Scharfschützen schützen? Tut mir leid, ich habe keine Zeit mehr, mich mit Ihrem Code zu befassen und ihn wirklich für mich selbst zu verstehen.
csga5000

@ csga5000, Da Sie Sniper jetzt möglicherweise selten anhand von Abstimmungsergebnissen identifizieren, werden sie alle ein wenig geschützt. Aber wenn ein Unterschied klar ist, handelt er immer im Interesse der Scharfschützen und ist daher meistens eine Art Krawattenbrecher. Der Fokus auf das Gewinnen liegt auf makroskopischen Spielen, nicht auf einzelnen Runden. In den meisten Runden kann es wirklich nichts anderes tun, als die Situation des Münzwurfs aufrechtzuerhalten.
Linus

1

HighOrLowNotSelf

Entfernt zufällig den niedrigsten oder höchsten Intelligenzspieler (aber nicht das Selbst).

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;
    }
}

Es gibt also ein paar Fehler bei dieser Einreichung. Erstens gibt Math.round () ein long, nicht int. Zweitens opsenthält sich nicht. (Wenn Sie für sich selbst abstimmen möchten, müssen Sie dies ausdrücklich angeben.) Schließlich ist das von Ihnen angegebene if / else kein gültiges Java. Ich habe deinen Code korrigiert
Nathan Merrill

1

Anarchist

Der Anarchist mag keine Regime.
Der Anarchist wird versuchen, den gegenwärtigen Präsidenten zu töten.
Wenn der Anarchist Präsident ist, beschließt er, seine Macht zu missbrauchen und nutzlose Friedensstifter zu töten. Es sei denn, er wurde von einem seiner Untergebenen angegriffen, denn sie sollten stattdessen brennen.

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

Dieser Bot weiß, dass die allgemeine Bevölkerung immer falsch liegt! Also stimmt es für den, der die geringsten Stimmen bekommt.

Code ist fast identisch mit SolarAarons "Bandwagon", aber die Endlogik ist gespiegelt.

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;
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.