You are the Weakest Link, Goodbye

50

15

This challenge is based off of the game show, Weakest Link. For those unfamiliar with the show, the crux of this challenge deals with who you vote off:

  • If the other players are smarter than you, then you have less of a chance of getting the pot.
  • If the other players are dumber than you, then you have less of a pot to get.

At the start of each round, the Pot starts out with $0. A group of 9 players is formed, and each player is given a unique Smartness from 1 to 9.

At the start of each turn, Pot += Smartness for each player still in the round. Then, players vote on the player they wish to remove. The player with the most votes is removed. In case of a tie, the smarter player is kept.

When there are only 2 players are left in the round, they face off in a battle of wits. The chance of the player winning is Smartness/(Smartness+OpponentSmartness). The winning player then receives the entire pot.

The player who has received the most money at the end of the game wins.

Input / Output

Each turn, you will receive the current list of opponents. You will have access to your smartness and all players' entire voting history for the round via functions in the Player class.

As output, you must return a single integer, representing the player you wish to vote for (representing their smartness). Voting for yourself is allowed (but not recommended).

Rounds of 9 will repeat until all players have played at least 100010000 rounds, and all players have played in the same number of rounds.

You can find the controller here: https://github.com/nathanmerrill/WeakestLink

To create a player, you need to extend the Player class, and add your player to the PlayerFactory class. Your class must follow the following rules:

  1. Communication or interference with any other player (include your other players of the same type) is strictly prohibited.

  2. Reflection and static variables (except for constants) are not allowed.

  3. If you want to use randomness, I have provided a getRandom() function in the Player class. Use it, so simulations can be deterministic.

I have provided many functions in the Player class for easy access to data. You can find them online on Github. Your player will be instantiated each new round. "Dumb/suicidal" players are allowed (but not players with the same strategy).

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

Nathan Merrill

Posted 2015-12-01T05:09:06.250

Reputation: 13 591

1don't get this: "At the start of each round... A group of 9 players is formed, and each player is given a unique Smartness" not at the start of the game start? – CSᵠ – 2015-12-01T05:41:55.570

1@CSᵠ correct. Your smartness changes from round to round (it would be unfair otherwise). – Nathan Merrill – 2015-12-01T05:45:38.270

2must be the stress and joy – CSᵠ – 2015-12-01T05:56:14.203

1Should I expect an ant build config or some such? I'm kinda new to java, and I'm not sure how people usually set up little projects like this one. – Dale Johnson – 2015-12-01T07:12:00.897

4From within src\WeakestLink I used javac Game\*.java Players\*.java Main.java to compile and java -cp .. WeakestLink.Main to run. – Linus – 2015-12-01T07:22:05.893

I feel like this would be a lot more interesting if players could artificaily lower their smartness for each turn. – user253751 – 2015-12-01T23:20:08.203

@immibis I'm not sure how you think that would work. We refer to players by their smartness, so there would be a possibility of multiple players with the same smartness, or if we refer to players by something else, then we can track that their smartness changed. – Nathan Merrill – 2015-12-01T23:58:37.270

@DaleJohnson Or you could easily import the code into your i'd in a new project. – csga5000 – 2015-12-02T04:52:36.147

@NathanMerrill I would have loved having a way to know who had reason when they voted.Too bad for me :p. (Wanted to do a bot voting for the one who voted the most successfully ^^). – Katenkyo – 2015-12-02T07:51:58.357

@Katenkyo figuring out who voted most successfully is definitely possible with the information I've given you. You can track who was in the round last time, figure out who was removed, and then get all of the people that voted for them the last round. – Nathan Merrill – 2015-12-02T13:45:20.660

@NathanMerrill i though the only informations about others I had was : their smartness and their votes. As I can't identify by a name, nor know the exact changement in smartness for each one, I can't actually see an implementation without cases where I don't know who has been excluded. But if you say i can, I'll give it a go when I'll be back Home :). Anyway, well done, it's a pretty funny KotH ^^. – Katenkyo – 2015-12-02T13:49:44.570

1@Katenkyo People's smartness don't change from turn to turn (meaning you can track it within a round). You can't target players that were successful last round though (intentionally). – Nathan Merrill – 2015-12-02T14:01:54.850

@NathanMerrill Ho, didn't understand that, feel stupid now... Voting right gives you an immunity so? Ok taking note, will have to revert it and vote for the least successful so. – Katenkyo – 2015-12-02T14:05:55.683

1Nothing makes you immune from being voted off? What do you mean by "so" – Nathan Merrill – 2015-12-02T14:07:11.483

@NathanMerrill "You can't target players that were successful last round though" wasn't this meaning "they are immune the next turn"? Using the vote list, I could tell if they were right or not, right? and the so was more like "so I will have to revert...." – Katenkyo – 2015-12-04T10:38:04.153

@Katenkyo You have complete information of what has happened in the current round, but the current round only. A round starts with 9 people, and lasts until 1 remains. While the winners of the previous rounds aren't immune, you can't specifically target them, because you have no idea who they are. – Nathan Merrill – 2015-12-04T13:56:13.973

@NathanMerrill My bad here, by round, I was meaning turn ^^' – Katenkyo – 2015-12-04T14:09:45.740

@NathanMerrill It looks like the smartness values in your code are 0-8, doesn't this adversely affect the face-off & pot? Not to mention I wrote some of my code assuming it was 1-9. – Linus – 2015-12-06T09:30:17.610

@Linus what a huge bug. I fixed it (and several players that broke because of the bug). Scores have been updated. – Nathan Merrill – 2015-12-06T14:06:10.253

1@TheNumberOne within a round, you can store as much data as you'd like. Each new round, I make a new instance of your bot, so storing results statically is not allowed. That said, if you can do some statistics on your personal time, and store the results in constants in the code you submit, that's fine as well. – Nathan Merrill – 2015-12-08T00:04:41.590

Answers

22

Sniper

The general idea is to keep around one of the stupid players (i.e. ones we are more likely to beat in the face-off) to snipe for the points. After that we try to remove the other low-value players to raise the pot. But when we get to the intelligent players we opt to remove for the most dangerous ones in case our stupid player gets removed. That way if we don't have someone to snipe we should get someone we at least stand a chance against. Also, since we always vote with either a min or max player, I expect we are fairly effective in getting our way.

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

Linus

Posted 2015-12-01T05:09:06.250

Reputation: 1 948

So apparently rollback doesn't remove edits. If at all possible I'd like any edits removed to make it abundantly clear this is the original version. – Linus – 2015-12-02T20:38:12.453

12

TheCult

The cult players have a mildly esoteric voting scheme by which they attempt to identify each other and vote as a group, using only the voting record. Since each member of the cult knows how to vote, anyone who votes differently is revealed as a non-member and eventually targeted for elimination.

The voting scheme at a glance:

  • on the first turn vote for weakest contestant, working in concert with min & sniper helps the cult gain power
  • on subsequent turns vote off known non-members until only the cult remains (we vote off the lowest-value non-member to rack up points as long as we think we are in control).
  • when only members remain, vote off low-value members for points (indeed sacrificing yourself for the good of the cult).

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

Final Thoughts:

The cult now switch's to voting for the most dangerous players when there are only two or fewer cult-members remaining for the face-off. I tested it several times with cult_cnt>1 and cult_cnt>2 conditions and the later wins more often.

Still, this is a precaution and the cult really isn't designed to work as lone player, so as the number of new players increase the cult should still lose eventually.

Linus

Posted 2015-12-01T05:09:06.250

Reputation: 1 948

Would this not be better to vote off the smartest non-members first? – agweber – 2015-12-01T20:24:34.237

I have updated the controller code so that the random variable is static (and can be accessed via Game.random). I've also taken the liberty of updating the code on github: https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/TheCult.java

– Nathan Merrill – 2015-12-01T20:33:09.173

1@NathanMerrill Thanks, but I'm seem to get better results if I allow the cult to be more tolerant (go figure) to unknown non-members who vote in it's interest. – Linus – 2015-12-01T20:57:00.540

@agweber, Thanks for the suggestion. This probably makes thecult a better sole-player, but as long as it has the numbers it should try to run up the pot. I think my new version is the best of both world. – Linus – 2015-12-01T20:59:15.380

@Linus Funny enough, this bot pushed RandomPlayer to the bottom. – Nathan Merrill – 2015-12-01T21:08:30.860

2TheCult bid me to request that unusedPlayers.addAll(allPlayers); in Game.java be duplicated around nine times, so that all players can occur in varied multiplicity (like shuffling together multiple decks of cards)... no don't of course, that's totally a biased request but it's interesting to see just how powerful the team based strategy can still be if they have even a small chance of getting put together. – Linus – 2015-12-02T07:52:05.480

12

PrudentSniper

Sniper, but with two special-case behaviors. One is that if there are three bots left, and PrudentSniper is the smartest, it will vote for the middle bot instead of the least smart. This allows it to win a few more showdowns. The other behavior is that if the smartest bot is gunning for it (voted for it or the analogous bot last time) and the least smart isn't, it will vote for the smartest in self defense.

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

histocrat

Posted 2015-12-01T05:09:06.250

Reputation: 20 600

I'm not sure that both advancements are of equal worth. Have you tried them each separately? – Linus – 2015-12-02T22:28:20.247

I did, and while the three bots case is an unambiguous improvement (at least against the bots currently in master on the repo), the retribution is about neutral, on net. I left it in as a sort of vague deterrent, a precaution against assassins. – histocrat – 2015-12-02T22:57:38.170

relevant ;) – Conor O'Brien – 2015-12-03T18:44:30.317

I recently fixed a bug where smartness was 0-8 instead of 1-9. This broke your code, so I fixed it (you can find the updated code on the repository): https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/PrudentSniper.java

– Nathan Merrill – 2015-12-06T14:11:13.180

7

BridgeBurner

Not somewhere where I can test this right now, and this came out feeling like really ugly/dumb code, but it should work.

This bot just wants to be hated. It votes for whoever has voted against it the least. In the event of a tie, it picks whoever has gone the longest without voting for it. In the event of another tie, it picks the smartest of those (presumably because they will make the worst enemy). It will not vote for itself, because no one will really hate it when it's not around.

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

SnoringFrog

Posted 2015-12-01T05:09:06.250

Reputation: 1 709

I was unable to get this bot to work. I fixed several bugs, and it is now voting for a non-existent player. The one change I wasn't sure if it was right was that "last_round_voted" isn't defined, so I changed it to "last_voted_against". You can find my changes here: https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/BridgeBurner.java

– Nathan Merrill – 2015-12-03T03:00:30.907

@NathanMerrill This code was apparently even worse than I thought. Now that I can test it, I'll look at both versions and try to get this working. – SnoringFrog – 2015-12-03T15:02:04.337

@NathanMerrill Found a couple issues. Namely, I didn't ignore players who were not in the found that never voted for the bot, which is why it always tried to vote for them. Also used the wrong list to get an index from at one point, resulting in player -1 being voted for. But it should be fixed now. – SnoringFrog – 2015-12-03T18:32:22.857

1Well, it works, but does terrible. Congrats on beating random player! – Nathan Merrill – 2015-12-03T18:42:40.487

1@NathanMerrill on beating random player sometimes – SnoringFrog – 2015-12-03T21:49:01.227

I recently fixed a bug where smartness was 0-8 instead of 1-9. This broke your code, so I fixed it (you can find the updated code on the repository) – Nathan Merrill – 2015-12-06T14:08:27.313

+1 "because no one will really hate it when it's not around" – NonlinearFruit – 2016-09-06T02:31:03.650

6

RevengePlayer

This bot will vote for whoever voted for him the most times, tiebreaker being the smartest player. The theory is that a player that voted for you in the past will likely vote for you again.

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

MegaTom

Posted 2015-12-01T05:09:06.250

Reputation: 3 787

I recently fixed a bug where smartness was 0-8 instead of 1-9. This broke your code, so I fixed it (you can find the updated code on the repository): https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/RevengePlayer.java

– Nathan Merrill – 2015-12-06T14:10:45.047

@NathanMerrill your fix for my code had a small bug. I edited my code to make it better. – MegaTom – 2015-12-09T15:46:09.990

6

Bandwagon

Follows the crowd in voting, unless he's the one being targeted.

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

I'm guessing this one will just make snipers stronger by following them, but also avoids being targeted by the cult and sniper-aides in a slightly effective manner. It may as well be a meatshield for sniper killers or aid them if there's more of them. (Need to test with the latest updates).

Using java 8 features because the game needs that to run anyway.

SolarAaron

Posted 2015-12-01T05:09:06.250

Reputation: 61

1It's nice to see some well written code :) – Nathan Merrill – 2015-12-03T14:33:25.737

5

MeanPlayer

Vote neither the stupidest nor the smartest players, and he's carrying a gun (sneaked it past security)

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

CSᵠ

Posted 2015-12-01T05:09:06.250

Reputation: 484

I don't understand why this player is any meaner than the rest /sarc – Nathan Merrill – 2015-12-01T06:03:20.560

Watch out @NathanMerrill, he's got a gun! I'd choose my words carefully if I were you... – CSᵠ – 2015-12-01T06:11:15.493

10@CSᵠ I'm not worried. When he's the average player, he uses the gun on himself. – quintopia – 2015-12-01T07:42:40.190

@quintopia True, that's a sure vote, but maybe he escapes being also voted by others. Remember... he has a gun... – CSᵠ – 2015-12-01T07:49:28.797

14This player is less mean than she could be. She appears to be more median than mean. – Yakk – 2015-12-01T15:11:36.670

7Hah.... took me a minute – David says Reinstate Monica – 2015-12-01T15:33:12.220

@Yakk In this case median and mean are the same. – Paŭlo Ebermann – 2015-12-01T19:30:11.577

@PaŭloEbermann that's not strictly true, because players can be voted off. There could be 1,6,7,8,9 left, with a mean of 6.2 and a median of 7. – Nathan Merrill – 2015-12-01T20:15:44.053

@NathanMerrill true, they are only the same at the start (and maybe randomly after). Thanks – Paŭlo Ebermann – 2015-12-01T23:35:09.193

5

AntiExtremist

This extreme socialist believes that all people should be of equal smartness. He tries to kill those who are much smarter or dumber than he is. He considers both but he favors dumb in general. He favors dumb people in the beginning and smart in the end, but it's weighted based on how extreme those people are.

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;

    }

}

NOTE: According to Linus this will vote the same as sniper the vast majority of the time (525602:1228).

csga5000

Posted 2015-12-01T05:09:06.250

Reputation: 360

I'm going to keep the current run to 10K for now (for quicker testing). When I do the final run through, I'll likely make it larger. – Nathan Merrill – 2015-12-02T01:42:19.920

I'm not trying to accuse you of anything, but this votes the way Sniper would ~99.7% of the time, it's basically going to be a coin flip as to who wins, since they are so close to the same strategy. – Linus – 2015-12-02T06:40:47.473

Where did you get that statistic from? I admit it has a semi-similar strategy but my goal was to try at improve upon something as simple as yours by choosing to vote for people whom are very smart if they are significantly smarter than me(aka I'm not likely to win the pot if they survive) – csga5000 – 2015-12-02T20:39:48.977

@Linus Originally I also tried targeting those whom had targeted me recently, but that decreased my effectiveness – csga5000 – 2015-12-02T20:45:34.917

1I gave your class a static Sniper S = new Sniper() and static long agrees=0, disagrees=0;. In your voting method I add S.setSmartness(getSmartness()); int sniper_answer=S.vote(currentOpponents); which calculates how a sniper would vote in your position, then put your answer into a variable to counted whether it agreed or disagreed before returning its answer. Once the game is over you can print agrees:disagress which was 525602:1228. – Linus – 2015-12-02T20:52:10.540

1@Linus That makes sense, sounds legit. I'll add a note about that. – csga5000 – 2015-12-02T21:06:40.600

5

Spy

Spy is reserved. He doesn't like to gun for the smartest people. Likewise, he doesn't like picking on quartata defenseless idiots. So, he likes to eliminate those closest to him in smartness.

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

You've just been backstabbed, mes amis. He doesn't care if he wins. He just like the sound of the knife in your back as he votes you off successfully.

You've just been backstabbed.

Conor O'Brien

Posted 2015-12-01T05:09:06.250

Reputation: 36 228

4That image, though. +1 – Addison Crump – 2015-12-03T20:12:48.390

I think this has a bug. Math.abs(enemyIntel - selfIntel) < closestIntel should be Math.abs(enemyIntel - selfIntel) < Math.abs(closestIntel - selfIntel). – MegaTom – 2015-12-09T17:46:34.247

@MegaTom I think you're right. I will check on this further when I have Java available. Thanks for the possible catch! – Conor O'Brien – 2015-12-09T19:00:51.523

4

MedianPlayer

This player attempt to be the meanest (well, medianness) one left.

It votes to eliminate the smartest and dumbest opponents (with a slight bias towards voting off the smartest), depending on if there are more or less smarter/dumber than themself.

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

framework blatantly stolen from @Linus above.

Yakk

Posted 2015-12-01T05:09:06.250

Reputation: 859

You made my IDE complain about duplicated code! – Nathan Merrill – 2015-12-01T19:45:37.143

@NathanMerrill Copy-pasta attack! Note I changed the name of the class since I posted. As I suppose duplicating someone else's class name to ensure that you cannot go against them would be against the spirit of the rules. – Yakk – 2015-12-01T19:50:15.810

Two classes with the same name would actually throw an exception, so its definitely not allowed :) – Nathan Merrill – 2015-12-01T19:52:24.437

2Thanks for blatantly stealing my work, or admitting so at least. – Linus – 2015-12-01T19:52:31.783

2@Linus You are welcome! Imitation is the best flattery, I hope. – Yakk – 2015-12-01T20:18:24.100

@Linus he stole some pretty intuitive stuff, and his decision making is different so.. It doesn't strike me as especially grievous – csga5000 – 2015-12-02T20:44:54.180

2@csga5000 blatantly stole was his joke, and i was just playing along. Any half-competent coder (e.g. myself) would write the loop the same way, so all he really did was steal my variable names. If i had thought to copyright them maybe I could charge royalties ; ) – Linus – 2015-12-03T09:13:24.463

4

Coward

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;

  }
}

Just doesn't want to get voted off, so votes for the opponent most similar to the player that got voted off last round in order to maximize the chance of being on the winning team.

Doesn't do particularly well right now, but might as well throw it in the mix.

histocrat

Posted 2015-12-01T05:09:06.250

Reputation: 20 600

I recently fixed a bug where smartness was 0-8 instead of 1-9. This broke your code, so I fixed it (you can find the updated code on the repository): https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/Coward.java

– Nathan Merrill – 2015-12-06T14:11:51.750

4

Hero

Votes off those who pick on the weak ... or annoy him.

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

TheNumberOne

Posted 2015-12-01T05:09:06.250

Reputation: 10 855

I recently fixed a bug where smartness was 0-8 instead of 1-9. This broke your code, so I fixed it (you can find the updated code on the repository): https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/Hero.java

– Nathan Merrill – 2015-12-06T14:11:41.957

@NathanMerrill Thank you :) – TheNumberOne – 2015-12-06T14:31:49.933

4

FixatedPlayer

Picks a random target, then votes for them until they're gone. Won't vote for himself though.

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

SnoringFrog

Posted 2015-12-01T05:09:06.250

Reputation: 1 709

This code didn't work either, but was an easy fix. Your do-while is actually not necessary, because I don't give you your smartness when I pass you your currentOpponents. The fixed code can be found here: https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/FixatedPlayer.java

– Nathan Merrill – 2015-12-03T03:01:43.920

@NathanMerrill I edited the corrected code into my answer so anyone looking at it here see's what's actually being run – SnoringFrog – 2015-12-03T18:37:52.717

4

Bob

Bob is just the average guy that thinks he is smarter then he really is. Cannot win the sniper family but get top 5 in my simulations most of the time.

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



}

Averroes

Posted 2015-12-01T05:09:06.250

Reputation: 3 771

4

Statistics

This is not an entry to the contest. This is merely a way to get useful statistics of a game. These statistics print off the percentage likelihood that a particular player will be voted off in a round.

To do this add the following lines to Round.java so that the top of the file looks like this:

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

...

Then modify the vote method to look like this:

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

Example Output:

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

TheNumberOne

Posted 2015-12-01T05:09:06.250

Reputation: 10 855

11th, 2th, 3th? I'd suggest changing it to print "For round 1" etc. – Skyler – 2015-12-17T18:18:52.840

3

MaxPlayer

A know-it-all. Prefers to remove anybody with high-intelligence (who can therefore challenge his unmatched intellect)

public class MaxPlayer extends Player{

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

Nathan Merrill

Posted 2015-12-01T05:09:06.250

Reputation: 13 591

3

Guard

Votes off those that pick on the strong ... or those that annoy him.

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

TheNumberOne

Posted 2015-12-01T05:09:06.250

Reputation: 10 855

I recently fixed a bug where smartness was 0-8 instead of 1-9. This broke your code, so I fixed it (you can find the updated code on the repository): https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/Guard.java

– Nathan Merrill – 2015-12-06T14:11:31.320

3

Leech

Relies on other bots to vote the smartest and dumbest guys off.. sort of.

He is satisfied with turning up somewhere in the middle and eventually splitting the pot with the winner (since he is actually a really decent guy 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);
            }
        }
    }
}

sweerpotato

Posted 2015-12-01T05:09:06.250

Reputation: 2 457

2I like. I'm concerned it won't do well though because not many will vote the same as you. That's one flaw with this competition is it seems to me that the other bots force you to conform to a certain type of strategy. – csga5000 – 2015-12-02T21:01:27.393

3Still fun though! Winning isn't everything :~)! – sweerpotato – 2015-12-03T16:59:36.257

3

SniperKiller

Another answer shamelessly stolen from Linus's code. This one in will kill all snipers, not protect them. If it knows that no snipers are left it will act like a sniper itself.

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

MegaTom

Posted 2015-12-01T05:09:06.250

Reputation: 3 787

1I like the idea, but there seems to be a culture of voting for min or max player. voting for someone else might be throwing your vote away. Maybe if you check if the max is sniperish before voting for someone else you'll catch up a bit... (i can't check, on phone) – Linus – 2015-12-03T09:29:16.500

2

RandomPlayer

public class RandomPlayer extends Player{

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

Nathan Merrill

Posted 2015-12-01T05:09:06.250

Reputation: 13 591

2

MinPlayer

An Elitist. Prefers to remove anybody with low intelligence.

public class MinPlayer extends Player {

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

Nathan Merrill

Posted 2015-12-01T05:09:06.250

Reputation: 13 591

2

ApproximatePosition

This bot is trying to shooting approximately around the missing smartness values, assuming that the group will continue with the same pattern, meaning it will target the same type of target. It always vote for the smartest of two player when there's a choice.

Long time I didn't use Java, and currently at work so... Can't test it, hope it's not too buggy, be gentle please :).

By the way, it uses awt.Point only because I'm too lazy to implement a tuple 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;
    }

}

Katenkyo

Posted 2015-12-01T05:09:06.250

Reputation: 2 857

So, there were some bugs. :) First, unfortunately, the Integer[] cast doesn't work, it has to be an Object[] cast (which I don't like). So I wrapped it all into an ArrayList instead of an array. Secondly, this line: emptyPosition[emptyPosition.length]=j; will always give you array out of bounds. Finally, not sure why, but you will vote off players that aren't in the round. – Nathan Merrill – 2015-12-02T13:59:34.417

Oh, also, your ternary block was returning a double instead of int, and was super convoluted, I turned it into a standard if/else. You can find all of my changes on Github: https://github.com/nathanmerrill/WeakestLink/blob/master/src/WeakestLink/Players/ApproximatePosition.java

– Nathan Merrill – 2015-12-02T14:05:26.877

@NathanMerrill Wow, thanks a lot. For the emptyPosition[emptyPosition.length], it is a dumb mistake as length is always one over the last index ^^. Thanks for the changes, I will use this new version to correct it. About the ternary block... yeah, felt like using it, and maybe way too used to writing for myself, wasn't handy to read I guess. Doing the corrections and updating it. – Katenkyo – 2015-12-02T14:11:00.480

2

SniperAide

Before the addition of PrudentSniper I wrote a bot to help Sniper beat AntiExtremist and other frauds (I use the word with love). The bot, SniperAide, looks for players who vote like snipers and votes as it thinks they would when there is a consensuses. If all players look like snipers he votes for the max, protecting lower Snipers (who would also switch to the max at this point), even if it is himself.

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

He currently is not much help against PrudentSniper.

Linus

Posted 2015-12-01T05:09:06.250

Reputation: 1 948

Based on your description and theory I don't see how this would help any sniper-like bot beat any other snipers.. if anything wouldn't it just protect all snipers? Sorry I don't have more time to dig into your code and really understand it for myself. – csga5000 – 2015-12-02T21:55:50.047

@csga5000, Since you may rarely identify Sniper by voting record now it does protect them all a little bit. But when a difference is clear it always acts in the Snipers interest, so it mostly a kind of tie-breaker. The focus on winning is macroscopic games, not individual rounds, in most rounds it really can't do anything more than maintain the coin-flip situation. – Linus – 2015-12-02T22:15:08.647

2

VengefulSniper

This started as something I thought was original called StupidBuffering (a name I hated to give up), then ended up being just a PrudentSniper who didn't care if he was being targeted. This also seemed to be the only reason he couldn't beat PrudentSniper, so I tweaked things around a bit to make that his focus.

Now, this is basically a sniper, but if the smartest or dumbest bot targets him, he will target whichever one got the most votes last round. If they both got the same number of votes and both targeted him, he goes back to normal sniper-y behavior. In my tests, this actual beats PrudentSniper on occasion.

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

SnoringFrog

Posted 2015-12-01T05:09:06.250

Reputation: 1 709

2

MiddleMan

The MiddleMan trys his best to maximize profits while keeping a wary eye that he's not cut from the game. He keeps around lesser contestants to improve his chance of making it to the next round (and to leave an easy finish). He will vote off someone smarter than him only if there are more smarter contestants than there are lesser contestants. Whichever of the two groups, he always votes for the lowest of the group to keep the pot climbing.

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

P.S. hope it compiles, I'm not a Java guy.

Had this scheme in mind before reading the other entries. Then I was surprised how close (but critically different) Sniper was so I went ahead and used that as a jumping off point since I don't know Java syntax. Thanks @Linus

tbernard

Posted 2015-12-01T05:09:06.250

Reputation: 121

1Please test your code. don't try to write answers in languages you do not know – TanMath – 2015-12-04T05:06:50.590

@TanMath - Thanks for your input. I have much experience in C/Java-like languages, however not Java specifically, so I'm quite confident that my code is in fact correct and will work. That being said, if there is an error in it and it won't run I wont be offended if the game master disqualifies the entry. – tbernard – 2015-12-04T05:10:43.080

You're right. Thanks @Linus. Edited. – tbernard – 2015-12-04T08:22:57.120

1@tbernard I'm happy to fix bugs, but your code didn't have any :) – Nathan Merrill – 2015-12-04T14:56:03.907

Ouch. Didn't do as well as I'd hoped. I did seem to help out sniper though, so that's something I guess haha. – tbernard – 2015-12-04T22:02:04.227

1

HighOrLowNotSelf

Removes randomly lowest or highest intelligence player (but not self).

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

username.ak

Posted 2015-12-01T05:09:06.250

Reputation: 411

So, there are a couple of bugs with this submission. First, Math.round() returns a long, not int. Secondly, ops does not contain yourself. (If you wanted to vote for yourself, you'd explicitly have to include it). Finally, the if/else you included isn't valid Java. I've fixed your code, and added it to github

– Nathan Merrill – 2015-12-03T20:14:57.380

1

Anarchist

The anarchist doesn't like regimes.
The anarchist will try to kill the current president.
If the anarchist is president, he decides to abuse his power and kill useless peagents. Unless he was targeted by one of his inferiors, for they should burn instead.

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

}

Bassdrop Cumberwubwubwub

Posted 2015-12-01T05:09:06.250

Reputation: 5 707

1

IndependentVoter

This bot knows that the general population is always wrong! So it votes for whoever is getting the least votes.

Code is nearly Identical to SolarAaron's "Bandwagon", but the end logic is flipped.

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

MegaTom

Posted 2015-12-01T05:09:06.250

Reputation: 3 787