Ти найслабший зв’язок, до побачення


50

Цей виклик заснований на ігровому шоу Weakest Link . Для незнайомих із шоу суть цього виклику стосується того, за кого ви голосуєте :

  • Якщо інші гравці розумніші за вас, у вас менше шансів отримати банк.
  • Якщо інші гравці дурніші за вас, то вам доведеться отримати менше горщика.

На початку кожного раунду Пот починається з 0 доларів. Сформована група з 9 гравців, і кожному гравцеві надається унікальна Smartness від 1 до 9.

На початку кожного ходу, Pot += Smartnessдля кожного гравця, який ще перебуває в раунді. Потім гравці голосують за гравця, якого хочуть видалити. Гравець, який отримав найбільше голосів, видаляється. У разі вирівнювання, розумніший гравець зберігається.

Коли в раунді залишаються лише 2 гравці, вони стикаються в битві дотепності. Шанс виграти гравця є Smartness/(Smartness+OpponentSmartness). Потім переможець отримує весь горщик.

Гравець, який отримав найбільше грошей в кінці гри, виграє.

Введення-виведення

Кожного кроку ви отримуватимете поточний список супротивників. Ви матимете доступ до своєї кмітливості та всієї історії голосування всіх гравців за раунд через функції класу Player.

Як вихід, ви повинні повернути одне ціле число, представляючи гравця, за якого ви хочете проголосувати (представляючи їх розумність). Голосування для себе це дозволено (але не рекомендується).

Раунди 9 повторюватимуться, поки всі гравці не зіграють принаймні 1000 10000 раундів, а всі гравці зіграли в однаковій кількості раундів.

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

Щоб створити програвач, потрібно розширити клас програвача та додати гравця до класу PlayerFactory. Ваш клас повинен дотримуватися таких правил:

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

  2. Відображення та статичні змінні (крім констант) не допускаються.

  3. Якщо ви хочете використовувати випадковість, я надав getRandom()функцію в класі 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
Чи варто очікувати конфігурації збірки мурашок або якоїсь такої? Я якось новачок у 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

TheCult

У культових гравців є м'яко езотерична схема голосування, за допомогою якої вони намагаються ідентифікувати один одного і голосувати як група, використовуючи лише записи про голосування. Оскільки кожен з членів культу знає, як голосувати, кожен, хто голосує по-різному, виявляється як член, який не є членом, і в кінцевому підсумку націлений на усунення.

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

  • на першому етапі голосування за найслабшого учасника, співпраця з 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умовами, а пізніше перемагає частіше.

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


Чи не краще це спочатку проголосувати за найрозумніших не членів?
agweber

Я оновив код контролера, щоб випадкова змінна була статичною (і доступ до неї можна отримати через 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 Цей код був, мабуть, ще гіршим, ніж я думав. Тепер, коли я можу це протестувати, я перегляну обидві версії та спробую налагодити це.
ХропінняFrog

@NathanMerrill Знайшов пару проблем. А саме, я не ігнорував гравців, які не були знайденими, які ніколи не голосували за бота, тому завжди намагалися проголосувати за них. Також використали неправильний список, щоб отримати індекс в один момент, в результаті чого гравця -1проголосували за. Але це слід виправити зараз.
ХропінняFrog

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
Приємно бачити якийсь добре написаний код :)
Натан Мерріл

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

Я не розумію, чому цей гравець гірший за решту / sarc
Nathan Merrill

Остерігайся @NathanMerrill, у нього пістолет! Я б ретельно вибирав свої слова, якби ти був ...
CSᵠ

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

14
Ця гравець є меншою, ніж вона могла бути. Вона, здається, більше середня, ніж середня.
Якк

7
Га .... зайняв мене хвилинку
відновіть Моніку

5

АнтиЕкстреміст

Цей крайній соціаліст вважає, що всі люди повинні мати рівну кмітливість. Він намагається вбити тих, хто набагато розумніший або тупіший, ніж він. Він вважає і те, і інше, але вболіває за німого. Він надає перевагу тупим людям на початку та розумним у підсумку, але це зважується на основі того, наскільки вони крайні.

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% часу, це в основному буде монетним переворотом щодо того, хто виграє, оскільки вони настільки близькі до тієї ж стратегії.
Лінус

Звідки ви взяли цю статистику? Я визнаю, що у неї є подібна стратегія, але моя мета полягала в тому, щоб спробувати вдосконалити щось таке просте, як ваше, вибравши голосувати за людей, які дуже розумні, якщо вони значно розумніші за мене (так як я, швидше за все, не виграю горщик, якщо вони виживають)
csga5000

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

1
@Linus Це має сенс, звучить законно. Додам до цього записку.
csga5000

5

Шпигун

Шпигун зарезервований. Він не любить стріляти за найрозумніших людей. Крім того, він не любить задирати quartata беззахисних ідіотів. Отже, він любить ліквідувати тих, хто йому найближчий.

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. Дякуємо за можливий вилов!
Conor O'Brien

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 Копіювати-макаронні атаки! Примітка. Я змінив назву класу з моменту публікації. Як я вважаю, дублювання чужого імені класу, щоб переконатися, що ви не можете проти них, було б протилежним духу правил.
Якк

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-й? Я б запропонував змінити його на друк "Для 1 раунду" тощо
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
Ще весело, хоча! Перемога - це не все: ~)!
ласощі

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, тому я повністю впевнений, що мій код насправді правильний і працює. При цьому, якщо в ньому є помилка, і вона не запуститься, я не буду ображатися, якщо майстер гри дискваліфікує запис.
tbernard

Ти правий. Дякую @Linus. Відредаговано.
tbernard

1
@tbernard Я радий виправляти помилки, але у вашого коду не було :)
Nathan Merrill

Ой. Не так добре, як я сподівався. Я, здається, допомагав снайперу, хоча це я щось гадаю, ха-ха.
tbernard

2

Приблизне положення

Цей бот намагається здійснити зйомку приблизно навколо пропущених значень розумності, припускаючи, що група продовжуватиметься за тим самим малюнком, тобто означає, що буде націлена на один і той же тип цілі. Він завжди голосує за найрозумнішого з двох гравців, коли є вибір.

Я давно не користувався 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 [] не працює, він повинен бути об’єктом [] (що мені не подобається). Тому я загорнув це все в ArrayList замість масиву. По-друге, цей рядок: emptyPosition[emptyPosition.length]=j;завжди надасть вам масив поза межами. Нарешті, не впевнений, чому, але ви проголосуєте гравців, які не в турі.
Натан Меррілл

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

@NathanMerrill Вау, спасибі велике Для 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, ні int. По-друге, opsне містить себе. (Якщо ви хочете проголосувати за себе, ви явно повинні включити його). Нарешті, включений if / else недійсний Java. Я виправив ваш код і додав його до github
Натан Меррілл

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

Цей бот знає, що широке населення завжди помиляється! Тож він голосує за того, хто набере найменше голосів.

Код майже ідентичний "Прокладці" SolarAaron, але кінцева логіка перевернута.

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.