Вы самая слабая ссылка, до свидания


50

Это испытание для основано на игровом шоу Weakest Link . Для тех, кто не знаком с сериалом, суть этой проблемы связана с тем, за кого вы проголосовали :

  • Если другие игроки умнее вас, у вас меньше шансов получить банк.
  • Если другие игроки тупее, чем вы, то у вас меньше пота.

В начале каждого раунда Пот начинается с $ 0. Формируется группа из 9 игроков, и каждому игроку присваивается уникальный Интеллект от 1 до 9.

В начале каждого хода, Pot += Smartnessдля каждого игрока все еще в раунде. Затем игроки голосуют за игрока, которого хотят удалить. Игрок с наибольшим количеством голосов удаляется. В случае ничьей умный игрок остается.

Когда в раунде остается только 2 игрока, они сражаются в битве умов. Вероятность выигрыша игрока есть Smartness/(Smartness+OpponentSmartness). Затем выигравший игрок получает весь банк.

Игрок, получивший наибольшее количество денег в конце игры, побеждает.

Ввод, вывод

Каждый ход вы будете получать текущий список противников. Вы будете иметь доступ к своей сообразительности и всей истории голосования всех игроков за раунд с помощью функций в классе Player.

В качестве результата вы должны вернуть одно целое число, представляющее игрока, за которого вы хотите проголосовать (представляющее их ум). Голосование для себя это разрешено (но не рекомендуется).

Раунды по 9 повторяются до тех пор, пока все игроки не сыграют не менее 1000 10000 раундов, и все игроки не сыграют за одинаковое количество раундов.

Вы можете найти контроллер здесь: https://github.com/nathanmerrill/WeakestLink

Чтобы создать игрока, вам нужно расширить класс Player и добавить игрока в класс PlayerFactory. Ваш класс должен следовать следующим правилам:

  1. Общение или вмешательство в игру любого другого игрока (включая других игроков того же типа) строго запрещено.

  2. Отражение и статические переменные (кроме констант) не допускаются.

  3. Если вы хотите использовать случайность, я предоставил getRandom()функцию в классе Player. Используйте его, чтобы моделирование могло быть детерминированным.

Я предоставил много функций в классе Player для легкого доступа к данным. Вы можете найти их онлайн на Github . Ваш игрок будет создан каждый новый раунд. Допускаются «тупые / самоубийственные» игроки (но не игроки с одинаковой стратегией).

множество

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
не понимаю: «В начале каждого раунда ... Формируется группа из 9 игроков, и каждому игроку присуща уникальная интеллектуальность», а не в начале игры?
CSᵠ

1
@ CSᵠ правильно. Ваша сообразительность меняется от раунда к раунду (иначе было бы нечестно).
Натан Меррилл

2
должно быть стресс и радость
CSᵠ

1
Стоит ли ожидать конфигурацию сборки ant или что-то подобное? Я немного новичок в Java, и я не уверен, как люди обычно создают маленькие проекты, подобные этому.
Дейл Джонсон

4
Изнутри src\WeakestLinkя привык javac Game\*.java Players\*.java Main.javaкомпилировать и java -cp .. WeakestLink.Mainзапускать.
Линус

Ответы:


22

снайпер

Общая идея состоит в том, чтобы держать одного из глупых игроков (то есть тех, кого мы с большей вероятностью победим в вбрасывании), чтобы набирать очки. После этого мы пытаемся удалить других игроков с низкой стоимостью, чтобы поднять банк. Но когда мы добираемся до умных игроков, мы выбираем удаление самых опасных в случае, если наш глупый игрок будет удален. Таким образом, если у нас нет кого-то, чтобы стрелять, мы должны найти кого-то, с кем у нас есть хотя бы шанс. Кроме того, поскольку мы всегда голосуем как с минимальным, так и с максимальным игроком, я ожидаю, что мы достаточно эффективно продвинемся.

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

Таким образом, очевидно, что откат не удаляет изменения. Если это вообще возможно, я бы хотел, чтобы какие-либо изменения были удалены, чтобы было совершенно ясно, что это оригинальная версия.
Линус

12

PrudentSniper

Снайпер , но с двумя особыми случаями. Во-первых, если осталось три бота, а PrudentSniper - самый умный, он будет голосовать за среднего бота вместо наименее умного. Это позволяет выиграть еще несколько разборок. Другое поведение состоит в том, что если за него стреляет самый умный бот (за него проголосовали или за аналогичного бота в прошлый раз), а наименее умный - нет, он будет голосовать за самого умного в самообороне.

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

Я не уверен, что оба продвижения имеют одинаковую ценность. Вы пробовали их каждый в отдельности?
Линус

Я так и сделал, и хотя случай с тремя ботами является однозначным улучшением (по крайней мере, по отношению к ботам, которые в настоящее время находятся в мастер-репо), расплата почти нейтральна в сети. Я оставил это как некое смутное сдерживающее средство, предосторожность против убийц.
гистократ


Недавно я исправил ошибку, в которой хитрость была 0-8 вместо 1-9. Это сломало ваш код, поэтому я исправил его (вы можете найти обновленный код в репозитории): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

12

Культ

Участники культа имеют слегка эзотерическую схему голосования, с помощью которой они пытаются идентифицировать друг друга и голосовать как группа, используя только протокол голосования. Поскольку каждый член культа знает, как голосовать, любой, кто голосует по-разному, раскрывается как неучастник и в конечном итоге подвергается исключению.

Схема голосования с первого взгляда:

  • на первом повороте проголосуйте за самого слабого участника, совместная работа с min & sniper помогает культу обрести власть
  • на последующих ходах голосуйте против известных не-членов, пока не останется только культ (мы выбираем не-член с самым низким значением, чтобы набрать очки, пока мы думаем, что мы контролируем).
  • когда остаются только члены, проголосуйте за малоценных членов за баллы (на самом деле жертвуя собой ради блага культа).

Код:

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

Последние мысли:

Культ теперь переключается на голосование за самых опасных игроков, когда для вбрасывания осталось только два или меньше члена культа. Я проверил это несколько раз cult_cnt>1и cult_cnt>2условий и более поздние победами чаще.

Тем не менее, это мера предосторожности, и культ на самом деле не предназначен для работы в качестве одинокого игрока, поэтому, поскольку количество новых игроков увеличивается, культ все равно должен проиграть.


Не лучше ли будет сначала проголосовать за самых умных не членов?
августа

Я обновил код контроллера, так что случайная переменная является статической (и может быть доступна через Game.random). Я также позволил себе обновить код на github: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

1
@NathanMerrill Спасибо, но я, кажется, получу лучшие результаты, если позволю культу быть более терпимым (поймите, что есть) к неизвестным не членам, которые проголосуют в его интересах.
Линус

@agweber, спасибо за предложение. Это, вероятно, делает культ лучшим игроком-одиночкой, но до тех пор, пока у него есть числа, ему следует попытаться увеличить банк. Я думаю, что моя новая версия - лучшая в мире.
Линус

2
TheCult предлагает мне сделать так, чтобы unusedPlayers.addAll(allPlayers);в Game.java дублировалось около девяти раз, чтобы все игроки могли встречаться с разной кратностью (например, перетасовывать несколько колод карт) ... нет, конечно, это необъективный запрос, но Интересно посмотреть, насколько мощной может быть командная стратегия, если у них даже есть небольшой шанс собраться вместе.
Линус

7

BridgeBurner

Не где-то, где я могу проверить это прямо сейчас, и это выглядело как действительно уродливый / тупой код, но это должно сработать.

Этот бот просто хочет, чтобы его ненавидели. Он голосует за того, кто проголосовал против него меньше всего . В случае ничьей он выбирает того, кто прошел дольше всех без голосования. В случае другой связи, он выбирает самых умных из них (предположительно, потому что они сделают худшего врага). Он не будет голосовать за себя, потому что никто не будет его ненавидеть, когда его нет рядом.

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

Я не смог заставить этого бота работать. Я исправил несколько ошибок, и теперь он голосует за несуществующего игрока. Единственное изменение, в котором я не был уверен, правильно ли это, заключалось в том, что «last_round_voted» не определено, поэтому я изменил его на «last_voted_against». Вы можете найти мои изменения здесь: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

@NathanMerrill Этот код был явно хуже, чем я думал. Теперь, когда я могу это проверить, я посмотрю обе версии и попытаюсь заставить это работать.
SnoringFrog

@NathanMerrill Нашел пару проблем. А именно, я не игнорировал игроков, которые не были найдены, которые никогда не голосовали за бота, поэтому он всегда пытался проголосовать за них. Также использовал неправильный список, чтобы получить индекс из одной точки, в результате чего за игрока -1проголосовали. Но это должно быть исправлено сейчас.
SnoringFrog

1
Ну, это работает, но делает ужасно. Поздравляю с избиением случайного игрока!
Натан Меррилл

1
@NathanMerrill иногда
SnoringFrog

6

повальное увлечение

Следит за толпой при голосовании, если только он не является целью.

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

Я предполагаю, что это только сделает снайперов сильнее, следуя за ними, но также избегает попадания в цель культа и помощников-снайперов в несколько более эффективной манере. Это может быть также щит для снайперских убийц или помощь, если их больше. (Нужно тестировать с последними обновлениями).

Использование функций Java 8, потому что игра все равно нуждается в этом.


1
Приятно видеть хорошо написанный код :)
Nathan Merrill

6

RevengePlayer

Этот бот будет голосовать за того, кто голосовал за него больше всего раз, а тай-брейк был самым умным игроком. Теория заключается в том, что игрок, который голосовал за вас в прошлом, скорее всего, снова проголосует за вас.

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

Недавно я исправил ошибку, в которой хитрость была 0-8 вместо 1-9. Это сломало ваш код, поэтому я исправил его (вы можете найти обновленный код в хранилище): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

@NathanMerrill в вашем исправлении для моего кода была небольшая ошибка. Я отредактировал свой код, чтобы сделать его лучше.
MegaTom

5

MeanPlayer

Не голосуйте ни за самых глупых, ни за умных игроков, и у него в руках пистолет (проскользнул мимо безопасности)

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

Я не понимаю, почему этот игрок более подлый, чем остальные / сарка
Натан Меррилл

Берегись @NathanMerrill, у него есть пистолет! Я бы тщательно выбрал свои слова на вашем месте ...
CSᵠ

10
@ CSᵠ Я не волнуюсь. Когда он средний игрок, он использует пистолет на себя.
Quintopia

14
Этот игрок менее подлый, чем она могла бы быть. Похоже, она более срединная, чем средняя.
Якк

7
Ха .... у меня заняло минуту
Восстановить Монику

5

AntiExtremist

Этот крайний социалист считает, что все люди должны быть одинаково умны. Он пытается убить тех, кто намного умнее или тупее, чем он. Он считает, что оба, но он предпочитает тупой в целом. Он одобряет глупых людей в начале и умных в конце, но это зависит от того, насколько экстремальны эти люди.

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;

    }

}

ПРИМЕЧАНИЕ. Согласно Линусу, большинство голосов будут голосовать так же, как и снайперы (525602: 1228).


Сейчас я собираюсь сохранить текущий пробег до 10 КБ (для более быстрого тестирования). Когда я сделаю последний проход, я, вероятно, увеличу его.
Натан Меррилл

Я не пытаюсь вас ни в чем обвинять, но это голосует так, как Снайпер будет ~ 99,7% времени, в основном это будет бросок монеты в отношении того, кто победит, так как они так близки к одной и той же стратегии.
Линус

Откуда вы взяли эту статистику? Я признаю, что у него есть полусхожая стратегия, но моя цель состояла в том, чтобы попытаться улучшить что-то столь же простое, как ваше, выбрав голосовать за людей, которые очень умны, если они значительно умнее меня (иначе я вряд ли выиграю
Пот,

1
Я дал твой класс static Sniper S = new Sniper()а static long agrees=0, disagrees=0;. В вашем методе голосования я добавляю, S.setSmartness(getSmartness()); int sniper_answer=S.vote(currentOpponents);который подсчитывает, как снайпер будет голосовать за вашу позицию, а затем помещает ваш ответ в переменную, чтобы подсчитать, согласен он или нет, прежде чем возвращать свой ответ. Как только игра закончится, вы можете распечатать согласие: disagress, который был 525602: 1228.
Линус

1
@ Линус Это имеет смысл, звучит законно. Я добавлю заметку об этом.
csga5000

5

шпион

Шпион зарезервирован. Он не любит стрелять для самых умных людей. Кроме того, он не любит ковыряться в беззащитных четвертных идиотах. Таким образом, он любит устранять самых близких ему по сообразительности.

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

Вы только что получили удар в спину, mes amis . Ему все равно, если он победит. Ему просто нравится звук ножа в твоей спине, когда он успешно голосует против тебя.

Вы только что получили удар в спину.


4
Это изображение, хотя. +1
Аддисон Крамп

Я думаю, что в этом есть ошибка. Math.abs(enemyIntel - selfIntel) < closestIntelдолжно быть Math.abs(enemyIntel - selfIntel) < Math.abs(closestIntel - selfIntel).
MegaTom

@ MegaTom Я думаю, что ты прав. Я проверю это дальше, когда у меня будет Java. Спасибо за возможный улов!
Конор О'Брайен

4

MedianPlayer

Этот игрок пытается быть самым подлым (ну, медианой) оставшимся.

Он голосует за устранение самых умных и глупых противников (с небольшим уклоном в сторону голосования против самых умных), в зависимости от того, есть ли более или менее умнее / тупее, чем они сами.

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

рамки явно украдены у @Linus выше.


Вы заставили мою IDE жаловаться на дублированный код!
Натан Меррилл

@NathanMerrill Copy-pasta attack! Обратите внимание, что я изменил название класса с момента публикации. Как я полагаю, дублирование чужого имени класса, чтобы вы не могли пойти против них, противоречило бы духу правил.
Якк

2
Спасибо за откровенное воровство моей работы или хотя бы признание.
Линус

2
@Linus Добро пожаловать! Надеюсь, имитация - лучшая лесть.
Якк

2
@ csga5000 явно украл его шутку, а я просто подыгрывал. Любой полукомпетентный кодер (например, я) написал бы цикл таким же образом, поэтому все, что он действительно делал, это украл мои имена переменных. Если бы я подумал об авторском праве на них, возможно, я мог бы взимать роялти; )
Линус

4

трус

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;

  }
}

Просто не хочет, чтобы за него проголосовали, поэтому голосуйте за противника, наиболее похожего на игрока, за которого проголосовали в последнем туре, чтобы максимально увеличить шанс оказаться в команде-победителе.

Не очень хорошо сейчас, но может с таким же успехом бросить это в микс.


Недавно я исправил ошибку, в которой хитрость была 0-8 вместо 1-9. Это сломало ваш код, поэтому я исправил его (вы можете найти обновленный код в репозитории): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

4

герой

Отбрасывайте голоса тех, кто выбирает слабых ... или раздражает его.

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

Недавно я исправил ошибку, в которой хитрость была 0-8 вместо 1-9. Это сломало ваш код, поэтому я исправил его (вы можете найти обновленный код в репозитории): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

@NathanMerrill Спасибо :)
TheNumberOne

4

боб

Боб просто обычный парень, который думает, что он умнее, чем он есть на самом деле. Невозможно выиграть семейство снайперов, но большую часть времени я получаю топ-5 в моих симуляциях.

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

Выбирает случайную цель, затем голосует за них, пока они не исчезнут. Не буду голосовать за себя, хотя.

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

Этот код тоже не работал, но это было легко исправить. Твои дела на самом деле не нужны, потому что я не даю тебе твоей смекалки, когда я передаю тебе твоих текущих оппонентов. Фиксированный код можно найти здесь: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

@NathanMerrill Я отредактировал исправленный код в своем ответе, так что любой, кто смотрит на него, видит, что на самом деле выполняется
SnoringFrog

4

Статистика

Это не вход в конкурс. Это просто способ получить полезную статистику игры. Эта статистика выводит процентную вероятность того, что конкретный игрок будет исключен в раунде.

Для этого добавьте следующие строки, Round.javaчтобы верхняя часть файла выглядела так:

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

...

Затем измените метод голосования, чтобы он выглядел так:

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

Пример вывода:

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? Я бы предложил поменять его на печать «Для первого раунда» и т. Д.
Skyler

3

MaxPlayer

Всезнайка. Предпочитает удалить кого-либо с высоким интеллектом (который может поэтому бросить вызов его непревзойденному интеллекту)

public class MaxPlayer extends Player{

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

3

охрана

Отбрасывает голоса тех, кто выбирает сильных ... или тех, кто его раздражает.

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

Недавно я исправил ошибку, в которой хитрость была 0-8 вместо 1-9. Это сломало ваш код, поэтому я исправил его (вы можете найти обновленный код в репозитории): github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

3

пиявка

Полагается на других ботов, чтобы голосовать за самых умных и глупых парней .. вроде.

Он доволен тем, что оказался где-то посередине и в итоге разделил банк с победителем (так как он на самом деле очень приличный парень- бот).

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
Мне нравится. Я обеспокоен тем, что это не будет хорошо, потому что не многие проголосуют так же, как вы. В этом соревновании есть один недостаток: мне кажется, что другие боты заставляют вас придерживаться определенного типа стратегии.
csga5000

3
Все еще весело, хотя! Победа не все: ~)!
Sweerpotato

3

SniperKiller

Еще один ответ бесстыдно украден из кода Линуса . Этот убьет всех снайперов, а не защитит их. Если он знает, что снайперов не осталось, он будет действовать как сам снайпер.

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
Мне нравится идея, но, похоже, существует культура голосования за минимального или максимального игрока. голосование за кого-то другого может означать отказ от вашего голоса . Может быть, если вы проверите, является ли максимум снайперским, прежде чем голосовать за кого-то другого, вы немного наверстаете упущенное ... (я не могу проверить, по телефону)
Линус

2

RandomPlayer

public class RandomPlayer extends Player{

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

2

MinPlayer

Элитарный. Предпочитает удалить кого-либо с низким интеллектом.

public class MinPlayer extends Player {

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

2

VengefulSniper

Все началось с того, что, как мне показалось, называлось оригинально StupidBuffering(имя, которое я ненавидел бросать), а затем оказалось просто PrudentSniper, которому было все равно, если он был целью. Это также, казалось, было единственной причиной, по которой он не мог победить PrudentSniper, поэтому я немного подправил вещи, чтобы сделать его своим фокусом.

Теперь, по сути, это снайпер, но если на него нацелится самый умный или самый тупой бот, то он нацелится на тот, кто наберет наибольшее количество голосов в последнем раунде. Если они оба получили одинаковое количество голосов и оба нацелены на него, он возвращается к нормальному поведению снайпера. В моих тестах это фактическое время от времени побеждает 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

перекупщик

MiddleMan делает все возможное, чтобы максимизировать прибыль, сохраняя осторожный взгляд, что он не вырезан из игры. Он держит вокруг меньших участников, чтобы улучшить его шанс сделать это к следующему раунду (и оставить легкий конец). Он будет голосовать против кого-то умнее его, только если будет больше умных участников, чем меньших участников. Какой бы из двух групп он ни голосовал, он всегда голосует за самую низкую группу, чтобы сохранить рост банка.

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 надеюсь, что это скомпилируется, я не Java-парень.

Имел эту схему в виду, прежде чем читать другие записи. Затем я был удивлен, насколько близок (но критически отличается) Снайпер, поэтому я пошел дальше и использовал это как отправную точку, поскольку не знаю синтаксиса Java. Спасибо @Linus


1
Пожалуйста, проверьте ваш код. не пытайтесь писать ответы на языках, которые вы не знаете
TanMath

@TanMath - Спасибо за ваш вклад. У меня большой опыт работы с C / Java-подобными языками, но не с Java, поэтому я вполне уверен, что мой код на самом деле правильный и будет работать. При этом, если в нем есть ошибка, и она не запустится, я не обижусь, если мастер игры дисквалифицирует запись.
Тбернард

Вы правы. Спасибо @Linus. Ред.
tbernard

1
@tbernard Я рад исправить ошибки, но в вашем коде их не было :)
Nathan Merrill

Уч. Не так хорошо, как я надеялся. Хотя, похоже, я помог снайперу, так что, думаю, ха-ха.
tbernard

2

ApproximatePosition

Этот бот пытается стрелять примерно по отсутствующим значениям сообразительности, предполагая, что группа продолжит с тем же шаблоном, то есть будет нацелена на тот же тип цели. Он всегда голосует за самого умного из двух игроков, когда есть выбор.

Долгое время я не пользовался Java, и в настоящее время на работе, так что ... Не могу проверить это, надеюсь, что это не слишком глючит, будьте осторожны, пожалуйста :).

Кстати, он использует awt.Point только потому, что мне лень реализовывать кортеж 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;
    }

}

Итак, были некоторые ошибки. :) Во-первых, к сожалению, Integer [] не работает, это должен быть Object [] (что мне не нравится). Поэтому я обернул все это в ArrayList вместо массива. Во-вторых, эта строка: emptyPosition[emptyPosition.length]=j;всегда будет давать вам массив вне границ. Наконец, не уверен почему, но вы будете голосовать против игроков, которые не в раунде.
Натан Меррилл

О, кроме того, ваш троичный блок возвращал двойное число вместо целого и было очень запутанным, я превратил его в стандарт if / else. Вы можете найти все мои изменения на Github: github.com/nathanmerrill/WeakestLink/blob/master/src/…
Натан Меррилл

@NathanMerrill Wow, большое спасибо. Для emptyPosition[emptyPosition.length], это глупая ошибка, поскольку длина всегда равна единице за последний индекс ^^. Спасибо за изменения, я буду использовать эту новую версию, чтобы исправить это. Насчет троичного блока ... да, я чувствовал, что хотел бы его использовать, и, может быть, слишком привык писать для себя, не думаю, что читать было удобно. Делать исправления и обновлять их.
Катенкё

2

SniperAide

Перед добавлением PrudentSniper я написал бота, чтобы помочь Sniper победить AntiExtremist и другие мошенники (я использую это слово с любовью). Бот, SniperAide, ищет игроков, которые голосуют как снайперы и голосуют так, как он думает, когда будут согласие. Если все игроки выглядят как снайперы, он голосует за максимума, защищая нижних снайперов (которые также переключатся на максимум в этой точке), даже если это он сам.

Код :

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

В настоящее время он не сильно помогает против PrudentSniper.


Основываясь на вашем описании и теории, я не понимаю, как это помогло бы любому боту, похожему на снайпера, победить других снайперов ... если что-то не защитило бы всех снайперов? Извините, у меня нет больше времени копаться в вашем коде и по-настоящему понять его для себя.
csga5000

@ csga5000, так как вы можете редко идентифицировать Снайпера по результатам голосования, теперь он немного их защищает. Но когда разница очевидна, она всегда действует в интересах Снайперов, так что это в основном своего рода тай-брейк. Фокус на выигрыше - макроскопические игры, а не отдельные раунды, в большинстве раундов он действительно не может сделать ничего, кроме как поддерживать ситуацию с монетой.
Линус

1

HighOrLowNotSelf

Удаляет случайно низшего или самого высокого интеллекта игрока (но не самого себя).

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

Итак, есть несколько ошибок с этим представлением. Во-первых, Math.round () возвращает a long, not int. Во-вторых, opsне содержит себя. (Если вы хотите проголосовать за себя, вы должны явно включить его). Наконец, включенный if / else не является допустимым Java. Я исправил твой код и добавил его в github
Nathan Merrill

1

анархист

Анархист не любит режимы.
Анархист попытается убить действующего президента.
Если анархист - президент, он решает злоупотребить своей властью и убивать бесполезных пагентов. Если только он не стал мишенью одного из его подчиненных, потому что вместо этого они должны были сгореть.

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

Этот бот знает, что население в целом всегда ошибается! Так что он голосует за тех, кто набирает наименьшее количество голосов.

Код почти идентичен Solarwaron "Bandwagon", но логика конца перевернута.

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;
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.