Король пагорба - кістки брехуни


22

Liar's Dice - досить проста гра в кубики. Я бачив кілька різних варіантів правил, але ось версія, з якою я найбільше знайома:

  • Кожен гравець починається з 5d6
  • За винятком випадків купівлі кісток в кінці раунду, кожен гравець може бачити свої власні кістки, але не ті, які мають будь-який противник
  • На початку будь-якого даного раунду всі гравці роблять усі кубики, які вони мають
  • Тоді один гравець (зазвичай це або переможець попереднього раунду, або гравець зліва від гравця, який стартував останній раз; ми будемо використовувати колишнього для цього KotH; з випадковим гравцем, який починає перший раунд) здогадується про те, скільки конкретної кількості стоїть на столі (ТОМИ ДИВАТИ)
  • Ставки продовжуються праворуч, щоразу піднімаючись вище (наприклад, 3 п'яти, 3 шістдесят і 4 двійки - це вище, ніж 3 четвірки, але 3 трійки - ні; 4 - також вище; 4 - також вище, але ставки на ті, ймовірно, ставлять вас на недолік); поки будь-який гравець не покликає гравця, який передує їм брехуном
  • У цей момент усі гравці розкривають свої кубики і підраховують кількість останньої ставки на номер на столі взагалі
  • Якщо загальна сума нижча, ніж ставка, гравець, який зробив ставку, повинен дати загибель гравцеві, який назвав їх брехуном, інакше гравець, який назвав учасника торгів брехуном, повинен дати загибель учаснику торгів (таким чином учасник виграє якщо їх принаймні стільки ж, скільки він запропонував, не повинно бути точного числа)
  • Коли у вас закінчиться кістки, ви програєте
  • Виграє останній стоїть гравець

Наприклад:

У гравця один 1,1,2,4,6
Гравець два має 1,2,2,3,5
Гравець три має 1,3,3,4,6
Гравець один: три шести.
Гравець два: чотири двійки.
Гравець три: чотири трійки.
Гравець один: п'ять двійників.
Гравець два: шість двоє.
Гравець три: шість троє.
Гравець один: шість четвереньків.
Гравець два: брехун!
Вони розкривають свої кістки і підраховують тих (бо дикі) та четвереньки.
Виявляється, насправді рівно шість четверень.
Тож гравець два дає гравцеві один штамб.
Вони відскакують, і один гравець починає наступний раунд.

Ви повинні написати бота, щоб грати в цю гру. Він повинен реалізувати такий абстрактний клас java:

public abstract class Player {
    public Player() {}
    public String toString() {
        return this.getClass().getSimpleName();
    }
    public abstract String bid(int yourId, int[] diceEachPlayerHas, int[] yourDice, String[] bids);
}
  • Ви повинні застосувати метод встановлення ставок
    • Перший аргумент - поточна позиція вашого бота в порядку повороту, другий - це масив, який показує, скільки кісток на даний момент має кожен гравець (включаючи себе), третій - це масив із значеннями, які наразі відображаються на ваших власних кубиках, а четвертий - масив усіх ставок, зроблених з початку поточного раунду - матиме довжину 0, якщо ви робите першу пропозицію раунду
    • Вихід повинен бути або рядком форми "число цифра", або рядком "Брехун!" називати попереднього учасника торгів брехуном.
    • Якщо ваш вихід форматований незаконно, ви будете усунені.
  • Ви можете перекрити метод toString, але цього не потрібно. Однак ви не можете редагувати його жодним чином, що заважає читати виводу контролера.
  • Вам дозволяється викликати будь-які інші публічні методи контролера, але не його основний метод.
  • Ви можете читати та редагувати лише файли у запущеному каталозі з префіксом власного імені вашого бота
  • Вам заборонено брати дані з будь-якого іншого джерела
  • Змінні екземплярів скидаються на початку кожної нової гри, але статичні змінні - ні.

Оцінка балів

  • Один набір з 1000 ігор, з 3-5 гравцями в кожній, буде імітуватися щоразу, коли додається бот (як тільки будуть подані три або більше ботів), забитий так, як показано у джерелі контролера (у будь-якій грі, ви отримуйте 1 на початку кожного свого ходу, 10 кожного разу, коли ви забираєте штамп, і 1000 бонусів, якщо ви виграєте); примусовий ліміт 5000 TURNS (не раундів) на кожну гру.
  • Ваш бот буде набраний його балом з останнього набору ігор; плюс десять разів більший за його кількість голосів, якщо це не заперечує. (Останнє навряд чи матиме суттєвий вплив на рахунок)

Джерело контролера можна знайти тут.

Оцінки станом на 19.06.2015:

Badnomial: 434,924 + 6x10 = 424,984
Nobody: 282,329 + 6x10 = 282,389
StraightShooter: 265,205 + 5x10 = 265,255
MostlyHonestAbe: 158,958 + 4x10 = 158,998
The Pirate: 157,005 + 1x10 = 157,015
Statistician: 144,012 + 2x10 = 144,032
Fidelio: 49,973 + 2x10 = 49,993
Absurd Bot: 6,831
DrHouse: 2,638 + 3x10 = 2,668

1
Ви повинні уточнити, що вихід повинен бути "2 3", а не "дві трійки", як показує ваш приклад. Також, чи є спосіб у контролері дивитись один матч?
Каїн

Не в офіційній версії, але я опублікую альтернативну версію, яка дозволяє це робити.
SuperJedi224

@Geobits: Якщо ви хочете. Це поставить вас у неприємність, якщо хтось подзвонить вам.
SuperJedi224

1
Я припускаю, що індекси масивів - це "ідентифікатори" гравців, так що diceEachPlayerHas[yourId]= ваш рахунок на кубики, і bids[yourId]це ваша перша ставка (або нульова, якщо це ваша перша черга). Це правильно?
Не те, щоб Чарльз

1
Я бачив ігри, де деякі представники грають більше ігор, ніж інші (Ніхто: 414 ігри, Прямий шутер: 409 ігор). Це не справедливо, ви можете виправити це?
CommonGuy

Відповіді:


6

Ніхто

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

Редагувати: виправлена ​​проблема, коли ніхто не давав би пропозицію назавжди, ніколи не телефонуючи брехуну.

public class Nobody extends Player{

    @Override
    public String bid(int myId, int[] diceEachPlayerHas, int[] myDice,
            String[] bids) {
        if (bids.length == 0)
            return "1 2";
        int wilds = 0;
        int players = Controller.numPlayers();
        double myKnowledge = (double)diceEachPlayerHas[myId]/Controller.diceInPlay();
        double previousKnowledge = (double)diceEachPlayerHas[(myId-1+players)%players] / Controller.diceInPlay();
        int[] dice = new int[5];
        for (int i = 0; i < myDice.length; i++) {
            if (myDice[i] == 1) {
                wilds++;
            } else {
                dice[myDice[i]-2]++;
            }
        }
        wilds = (int) (1/myKnowledge+wilds-1)+1;
        for (int i = 2; i <= 6; i++) {
            dice[i-2] += wilds;
        }
        String best = "0 0";
        for (int i = 2; i <= 6; i++) {
            if (Controller.isGreaterThan(dice[i-2] + " " + i, best)) {
                best = dice[i-2] + " " + i;
            }
        }
        if (Controller.isGreaterThan(best, bids[bids.length - 1])) {
            return best;
        }
        if (previousKnowledge > 0.4) {
            int prev = Integer.valueOf(bids[bids.length - 1].split(" ")[0]);
            int prevFace = Integer.valueOf(bids[bids.length - 1].split(" ")[1]);
            if (dice[prevFace - 2] +2 >= prev)
                return (prev+1) + " " + bids[bids.length - 1].split(" ")[1];
        }
        return "Liar!";
    }
}

Ваш останній набір оновлень справді допомагає.
SuperJedi224

6

Badnomial, бот, який приймає погані рішення на основі біноміальних розподілів: Edit: Виправлена ​​дурна помилка в обчисленнях ймовірностей, тепер припадає наступний, а також попередній учасник.

    public class Badnomial extends Player{
    public String toString() {return "Badnomial";}

  public String bid(int myId, int[] diceEachPlayerHas, int[] myDice, String[] bids) {
  int[] dieCounts = new int[7];
  for(int i:myDice)
   dieCounts[i]++;
  for(int i=2; i<7; i++)
   dieCounts[i] += dieCounts[1];

  if(bids.length > 0)
  {
   String[] lastBid = bids[bids.length - 1].split(" ");
   int bidCount = Integer.valueOf(lastBid[0]);
   int bidDie = Integer.valueOf(lastBid[1]);
   // Check if I hold a better bid
   boolean betterBid = false;
   int myBidDie;
   int myBidCount;
   int myHighestCount = 0;
   int myHighDie = bidDie +1;

   for(int i = 2; i < 7; i++) {
    if(dieCounts[i] >= myHighestCount) {
     myHighestCount = dieCounts[i];
     myHighDie = i;
    }
   } 
    if((myHighestCount > bidCount) || ((myHighestCount == bidCount) && (myHighDie > bidDie))) {
     betterBid = true;
     myBidDie = myHighDie;
     myBidCount = myHighestCount;
     }

   if(betterBid == false) {
    int unknownDice = Controller.diceInPlay() - myDice.length;
    int myDiceNeeded = bidCount - myHighestCount;
 if(myHighDie <= bidDie)
  myDiceNeeded++;
    int previousBidder = myId - 1;
    if(previousBidder < 0)
     previousBidder = Controller.numPlayers() -1;
    int bidderDiceNeeded = bidCount - dieCounts[bidDie] - (int)(diceEachPlayerHas[previousBidder]/3 +1);
    int bidderUnknown = Controller.diceInPlay() - diceEachPlayerHas[previousBidder] -myDice.length;
 int nextBidder = myId + 1;
 if(nextBidder == Controller.numPlayers())
  nextBidder = 0;
 int nbDiceNeeded = myDiceNeeded - (int)(diceEachPlayerHas[nextBidder]/3 +1);
    int nbUnknown = Controller.diceInPlay() - diceEachPlayerHas[nextBidder];
    //float myChances = (unknownDice/3 - myDiceNeeded)/((float)unknownDice/9);
    //float bidderChances = (bidderUnknown/3 - bidderDiceNeeded)/((float)bidderUnknown/9);
    double myChances = 1 - cumBinomialProbability(unknownDice, myDiceNeeded -1);
    double bidderChances;
    if(bidderDiceNeeded > 0)
     bidderChances = 1- cumBinomialProbability(bidderUnknown, bidderDiceNeeded -1);
    else bidderChances = 1.0;
    double nbChances;
    if(nbDiceNeeded > 0)
      nbChances = 1- cumBinomialProbability(nbUnknown, nbDiceNeeded -1 );
    else nbChances = 1.0;
    if(((myChances < .5) && (nbChances <.5)) || (bidderChances < .2))
     return "Liar!";
   }

   return (bidCount+1) + " " + myHighDie;
  }

  return 2 + " " + 2;
 } 

 private double cumBinomialProbability(int n, int k) {
   double sum = 0;
   for(int i = 0; i <=k; i++)
     sum += binomialProbability(n, i);
   return sum;
 }

 private double binomialProbability(int n, int k) {
   double nfact = 1;
   double dfact = 1;
   int greater;
   int lesser;
   if((n-k) > k) {
     greater = n - k;
     lesser = k;
   }
   else {
     greater = k;
     lesser = n-k;
   }
   for(int i = greater+1; i <= n; i++)
     nfact = nfact * i;
   for(int i = 2; i <= lesser; i++)
     dfact = dfact * i;
   return (nfact/dfact)*(Math.pow((1.0/3), k))*Math.pow(2.0/3, (n-k));
 }

}

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

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


Завдяки цим змінам Badnomial насправді здається віддаленим у порівнянні з іншими ботами.
Бездіяльність

5

Прямий шутер

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

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

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

public class StraightShooter extends Player{
    public String toString(){return "Straight Shooter";}
    public String bid(int me, int[] numDices, int[] dice, String[] bids){
        int[] counts = new int[7];
        double[] expected = new double[7];
        int unknown = Controller.diceInPlay() - dice.length;
        for(int i:dice)
            counts[i]++;
        for(int i=2;i<7;i++)
            expected[i] = counts[i] + unknown / 3d;
        int bidCount = 2;
        int bidDie = 2;
        if(bids.length > 0){
            String[] lastBid = bids[bids.length-1].split(" ");
            bidCount = Integer.valueOf(lastBid[0]);
            bidDie = Integer.valueOf(lastBid[1])+1;
            int possible = Controller.diceInPlay();
            for(int i=2;i<7;i++)
                if(i != bidDie)
                    possible -= counts[i];
            if(bidCount > possible)
                return "Liar!";

            if(bidDie > 6){
                bidDie = 2;
                bidCount++;
            }
        }
        double best = Double.MAX_VALUE;
        int bestCount = bidCount;
        int bestDie = bidDie;
        for(int count=bidCount;count<=Controller.diceInPlay();count++){
            for(int die=bidDie;die<7;die++){
                double score = Math.abs(expected[die]-bidCount);
                if(score < best){
                    best = score;
                    bestCount = count;
                    bestDie = die;
                }
            }
            bidDie = 2;
        }   
        return bestCount + " " + bestDie;
    }
}

Це і MostlyHonestAbe обоє неправдиво брехати або кликати брехуна, є кілька ігор, що йдуть до 2000 оборотів, коли я тестую ха-ха. : P
Каїн

Те саме в моєму. Це все нормально, адже кожен поворот - це додаткова точка до остаточного рахунку. Якщо я останній 2000 витків і не виграю, це краще, ніж виграти після 100 у своїй книзі;)
Геобіт

Мені просто довелося ще раз переглянути правила скорингу. Ціла нова гра XD
Каїн

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

1
Я не впевнений, що це матиме велике значення. Консервативність все одно буде перевагою лише тому, що у вас є менший шанс втратити смерть. Причина, що в реальному житті більше людей не грає так, це те, що це просто нудно, але що нудьга боту?
Геобіц

4

ПереважноHonestAbe

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

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;

public class MostlyHonestAbe extends Player{

    final boolean debug = false;
    boolean bluffedOnce = false;
    PrintStream out;
    @Override
    public String bid(int myId, int[] diceEachPlayerHas, int[] myDice, String[] bids) {
        try {
            File f = new File("abe.log.txt");
            out = new PrintStream(f);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
        if(debug){
            out = System.out;
        }

        //reset bluff counter on the first round
        if(bids.length < diceEachPlayerHas.length){
            bluffedOnce = false;
        }

        //Is it the first bid?
        if(bids.length == 0){
            out.println("I go first");
            return lowestViableBid(1,1, myDice, diceEachPlayerHas, true);
        }

        out.println("Last bid = " + bids[bids.length - 1]);
        out.print("My Dice = ");
        for(int d : myDice){
            out.print(d + ", ");
        }
        out.println();

        //What was the last bid?
        String[] lastBid = bids[bids.length -1].split(" ");
        return lowestViableBid(Integer.parseInt(lastBid[1]), Integer.parseInt(lastBid[0]), myDice, diceEachPlayerHas, false);


    }

    //Lowest honest bid, or liar
    private String lowestViableBid(int highestVal, int highestCount, int[] myDice, int[] otherDice, boolean firstTurn){

        //Make a better array for the dice
        //Include what the other players probably have
        int wilds = numDie(1, myDice);
        int[] diceCount = new int[6];
        diceCount[0] = wilds;
        int otherPlayerExpectedValue = 0;
        for(int d : otherDice){
            otherPlayerExpectedValue += d;
        }
        otherPlayerExpectedValue -= myDice.length;
        out.println("Number of other dice = " + otherPlayerExpectedValue);
        otherPlayerExpectedValue = otherPlayerExpectedValue / 4;
        //Note: Other player expected value is biased low, counting wilds the number should be divided by 3.

        out.println("playerExpectedVal = " + otherPlayerExpectedValue);
        for(int i = 1; i < 6; i++){
            diceCount[i] = numDie(i + 1, myDice) + wilds + otherPlayerExpectedValue;
        }


        //What's my array look like?
        for(int i = 0; i < diceCount.length; i++){
            out.println("diceVal = " + (i + 1) + ", diceCount = " + diceCount[i]);
        }

        //Can I bid the same number, but higher dice val?
        for(int diceVal = highestVal + 1; diceVal <= 6; diceVal++){
            if(diceCount[diceVal - 1] >= highestCount){ 
                out.println("1.Returning " + highestCount + " " + diceVal);
                return highestCount + " " + diceVal; }  
        }

        //What about more dice?
        for(int diceNum = highestCount + 1; diceNum <= myDice.length; diceNum++){
            for(int diceVal = highestVal + 1; diceVal <= 6; diceVal++){
                if(diceCount[diceVal - 1] == diceNum){ 
                    out.println("2.Returning " + (diceNum) + " " + diceVal);
                    return (diceNum) + " " + diceVal; } 
            }
        }

        if(firstTurn){ return "1 2"; }
        //If this is the first time I'm out of my league, bluff a round before calling liar.
        if(!bluffedOnce){
            out.println("bluffing " + (highestCount + 1) + " " + highestVal);
            bluffedOnce = true;
            return (highestCount + 1) + " " + highestVal;
        }
        out.println("Returning Liar!");
        //Well, wouldn't want to lie
        return "Liar!";
    }

    private int numDie(int i, int[] myDice){
        int result = 0;
        for(int j : myDice){
            if(i == j){ result++; }
        }
        return result;
    }
}

1
Ти мене жартуєш? Мені було менше п'яти хвилин від публікації HonestAbe . Тепер я повинен придумати нову назву: P
Geobits

1
Неможливо провести гру з Ліаром в імені без посилання Авраама Лінкольна десь.
Каїн

4

Доктор Хаус

Всі брешуть!

public class DrHouse extends Player
{   
  public String bid(int yourId, int[] diceEachPlayerHas, int[] yourDice, String[] bids)
  {
    return "Liar!";
  }
}

1
Я пропоную додати спеціальну логіку, коли у вас є перша ставка раунду.
SuperJedi224

4
@ SuperJedi224 Я думаю, що бот вважає, що контролер каже йому, що його черга - брехун
Натан Меррілл

Зробив мій день коханим
Рохан Джунджунвала

2

Фіделіо

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

public class Fidelio extends Player
{
    final String LIAR ="Liar!";
    @Override
    public String bid(int yourId, 
            int[] diceEachPlayerHas, 
            int[] yourDice,
            String[] bids) 
    {
        int[] myDices = new int[6];
        int valueToBid=1;
        for(int i : yourDice)
            myDices[i-1]++;
        for(int i=2;i<myDices.length;i++)
            if(myDices[i]>=myDices[valueToBid])
                valueToBid=i;
        if(bids.length==0)
            return 2+" "+valueToBid;
        int sum=0;
        String[] lastBidString=bids[bids.length-1].split(" ");
        int[] lastBid = new int[2];
        lastBid[0] = Integer.parseInt(lastBidString[0]);
        lastBid[1] = Integer.parseInt(lastBidString[1])-1;
        for(int i : diceEachPlayerHas)
            sum+=i;
        sum-=yourDice.length;
        if(lastBid[0]>sum/3+myDices[lastBid[1]]+myDices[0])
            return LIAR;
        if(lastBid[1]>= valueToBid)
        {
            if(lastBid[0]>=myDices[0]+myDices[valueToBid]+sum*2/5)
                return LIAR;
            return (lastBid[0]+1)+" "+myDices[valueToBid];
        }
        return lastBid[0]+" "+valueToBid;
    }
}

Сподіваюся, він добру справу зробить :).


Я отримую IndexOutOfBoundsException у рядку 13. Пам'ятайте, що масиви 0-індексуються в Java.
SuperJedi224

Тепер я отримую один на іншому кінці в рядку 19, за індексом -1. Здавалося б, він намагався прочитати останній елемент з порожнього масиву, вам слід включити чек на це.
SuperJedi224

Виправлено, перевірка, чи (bids.length == 0) була зроблена після того, як я використав ставки ...
Katenkyo

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

А, значить, ця запропонована редакція більше не потрібна?
mbomb007

2

Статистик

У вас є 1/3 шансу мати будь-яке число, окрім тузів. Один хлопець одного разу сказав мені, що не перевіряючи свої кубики та знаючи шанси, це може змусити вас виграти цю гру. EDIT: Ставки були занадто високими. Але це не значно покращує бал.

public class Statistician extends Player{
    public String toString(){return "Statistician";}
    public String bid(int me, int[] numDices, int[] dice, String[] bids){
        int totalDices = 0;
        int currentBid, max;
        for (int i : numDices)
            totalDices += i;
        max = totalDices/3;
        if(bids.length>0){
            currentBid = Integer.valueOf(bids[bids.length-1].split(" ")[0]);
            if(currentBid>max)
                return "Liar!";
        }
        return max+" 6";
    }
}

1

Абсурдний бот

Стверджує, що всі кубики - це 6, якщо вони не можуть. Якщо бот не може цього зробити, це означає, що це неможлива ситуація або майже неможлива ситуація. Через це це називає брехуном. Мені цікаво, наскільки ефективним буде цей бот.

public class AbsurdBot extends Player {
    @Override
    public String bid(int yourId, int[] diceEachPlayerHas,int[] yourDice,String[] bids)
    {
        String[] lastbid;
        int a, b, d;
        d = 0;
        for (int dice : diceEachPlayerHas)
            d += dice;
        if (bids.length != 0)
            {
                lastbid = bids[bids.length-1].split(" ");
                a = Integer.parseInt(lastbid[0]);
                b = Integer.parseInt(lastbid[1]);
                if (a > d || a == d && b == 6)
                    return "Liar!";
            }
        return d + " 6";
    }
}

Щодо ефективності: Основна його функція, здається, - передача кісток тому, хто за ним виконує: P
Geobits

@Geobits Я виправив код. Це те, що відбувається при спробі перейти на мову програмування, яку ви раніше не запрограмували ...
frederick,

@Geobits Дякую за всю допомогу. Я думаю, що це нарешті справно працює. Робить це? (Java плутає)
frederick

Так, це працює зараз. Однак стратегія є шалено самогубною. Він набирає лише ~ 2% від наступного найнижчого гравця.
Геобіц

@Geobits Я ніколи не намагався запустити його проти інших гравців. Ти заводив це проти інших?
frederick

1

Пірат

Я зробив кілька простих ботів під час тестування контролера, і це єдиний, який справді є корисним.

Ймовірно, буде покращено пізніше.

import java.util.Arrays;
import java.util.Scanner;

public class Pirate extends Player{
    public Pirate() {
    }
    public String toString(){
        return "The Pirate";
    }
    private String bid(int[] t,int tol){
        int[]z=t.clone();
        Arrays.sort(z);
        int j=0;
        for(int i=0;i<6;i++){
            if(t[i]==z[5]){j=i;break ;}
        }
        return (tol+t[j])+" "+(j+1);
    }
    @Override
    public String bid(int yourId, int[] diceEachPlayerHas, int[] yourDice,
            String[] bids) {
        int[] t=new int[6];
        for(int i=0;i<yourDice.length;i++){
            t[yourDice[i]-1]++;
        }
        for(int i=1;i<t.length;i++)t[i]+=t[0];
        int tol=(Controller.diceInPlay()-yourDice.length)/4;
        if(bids.length==0)return bid(t,1);
        Scanner i=new Scanner(bids[bids.length-1]);
        int x=i.nextInt(),y=i.nextInt();
        i.close();
        if(t[y-1]>x)return (t[y-1]+2)+" "+y;
        int nd=Controller.diceInPlay();
        if(x>nd+t[y-1]-yourDice.length)return "Liar!";
        if(Controller.isGreaterThan(bid(t,tol), bids[bids.length-1])){
            int z=Controller.valueOf(bids[bids.length-1]);
            for(int j=1;j<=tol;j++)if(Controller.valueOf(bid(t,j))>z)return bid(t,j);
        }
        return "Liar!";
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.