Охота за сокровищами на необитаемом острове

13

Вступление

Вы оказались на необитаемом острове с несколькими слугами и охотитесь за сокровищами. Чем дольше человек ищет, тем больше сокровищ он находит. Чем меньше людей ищут, тем больше каждый человек находит.

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

Вы управляете небольшой группой из 5 человек, которая отправится из лагеря в поисках сокровищ для вас.

Задача

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

Каждый ход, когда рабочий остается в поисках сокровищ, он находит 1+Rкусочки сокровищ, где Rнаходится количество рабочих (из всех ботов), уже вернувшихся в лагерь. Мертвые боты не учитываются при расчете.

В начале каждого дня будет выбрано случайное число ( n) от 2до max(3, floor(num_live_players/4)). (Для 10 игроков на 1 -й день, это 2к max(3,50/4)=12. Для 20 игроков на 1 -й день, это было бы 2в max(3,100/4)=25.) Это число означает количество игроков , которые будут оставлены умирать в этот день, и не будут переданы программе ,

Если слуга будет одним из последних, nкто вернется, он / она умрет и не сможет передать найденное им сокровище в ваше владение. Кроме того, слуга не сможет участвовать в поиске сокровищ до конца приключения.

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

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

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

Ввод, вывод

Ваша программа должна работать на протяжении всего моделирования.

В начале симуляции INDEX Iбудет введено, где Iнаходится индекс вашего бота (этот индекс считается от 1 до).

В начале каждого дня, START_DAY D/Nбудет введен в программу, где Dесть номер дня (начиная с 1), а Nравно max(3, floor(num_live_players/4)), что максимальное количество людей , которые могут умереть в этот день.

В начале каждого хода START_TURN Tбудет введена ваша программа, где Tуказан номер поворота (начиная с 1).

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

Допустимые ходы:

  • RПопробуй вернуться в лагерь.
  • S: Ищите сокровища.
  • NСлуга уже мертв или находится в лагере.

Ввод неверного хода будет интерпретироваться как Sесли бы бот был жив, а не в лагере, и Nиначе.

В конце каждого хода в вашу программу передается строка:

END_TURN [Turn #] [Bot 1 Moves] [Bot 2 Moves] ...

где движения каждого бота разделены запятыми.

Эти шаги будут одним из следующих:

  • R: Успешно вернулся в лагерь в этот ход.
  • r: Не удалось вернуться в лагерь в этот ход.
  • S: Все еще в поисках сокровищ.
  • DУмер на более ранней очереди.
  • NУже в лагере.

Боты и слуги остаются в том же порядке на протяжении всей симуляции.

Например:

INDEX 2
....
END_TURN 8 N,N,N,N,N r,r,r,r,D D,D,D,N,R S,D,D,N,D

Здесь вы второй бот ( r,r,r,r,r), который попытался вернуть всех четырех слуг, которые все еще живы (и, к несчастью, потерпели неудачу на всех четырех). Слуги Бота 1 все вернулись в лагерь. Бот 3 имеет трех мертвых слуг, еще одного в лагере и пятого слугу, который успешно вернулся. У бота 4 есть один слуга, который остался (и умрет, так как это последний ход дня), один слуга в лагере и три мертвых слуги.

После каждой из этих строк, если только не была выведена строка, обозначающая конец дня (см. Ниже), ваша программа должна выводить следующие шаги ваших слуг, разделенные запятыми. Все слуги должны быть учтены (с, Nесли уже в лагере, и Dесли уже мертв). Неверные ходы будут рассматриваться, как Sесли бы слуга еще не был в лагере / мертвеце. Пример:

N,N,S,S,R

что значит:

Servant # | Action
     1    | Do nothing.
     2    | Do nothing.
     3    | Stay put (keep looking for treasure).
     4    | Stay put (keep looking for treasure).
     5    | Try to return to camp.

В конце дня после строки последнего хода передается следующая ENDстрока, информирующая всех о том, кто жив:

END_DAY [Day #] [Bot 1 Status] [Bot 2 Status] 

где статус - разделенный запятыми список либо A(живой), либо D(мертвый). Следующий день начинается сразу после.

Симуляция заканчивается, когда есть менее 6 живых слуг. Ваша программа получит следующий вход в конце симуляции:

EXIT

Правила / Подробнее

  • Только на поворотах, где ваши действия Sвы найдете сокровище.
  • Количество симуляций: 1000 раз
  • Ваша программа не должна занимать больше 1 секунды, чтобы определить ходы.
  • Ваша программа не должна выходить рано; это будет начато ровно один раз.
  • Убедитесь, что выходной буфер (если применимо) сбрасывается после каждого вывода.
  • Файлы могут быть записаны в папку вашего бота ( ./players/BotName/). Ваше имя бота - это то, что вы называете своим ботом, все не алфавитно-цифровые символы удалены и записаны в CamelCase. Записи могут сохранять данные между прогонами контроллера, поскольку прогоны выполняются последовательно.
  • Ваша программа должна выйти после получения EXIT.
  • Программы, которые не могут скомпилировать или выдать ошибки или вывести недопустимый текст (не в формате 5 символов, разделенных запятыми), могут быть исключены из конкурса. Новая строка должна следовать за каждым выводом.
  • Контроллер можно найти на GitHub .

Пожалуйста, укажите имя бота, язык + версию, код и команду для компиляции (если применимо) и запуска вашего бота.

пример

Текст, выводимый программой, начинается с префикса >. Ваша программа не должна выводить этот символ.

INDEX 2
START_DAY 1/3
START_TURN 1
>S,S,S,S,S
END_TURN 1 S,R,S,S,S S,S,S,S,S
START_TURN 2
>S,S,S,S,S
END_TURN 2 S,N,S,R,S S,S,S,S,S
START_TURN 3
>R,R,S,S,S
END_TURN 3 R,N,R,N,R R,R,S,S,S
START_TURN 4
>N,N,S,S,S
END_TURN 4 N,N,N,N,N N,N,S,S,S
START_TURN 5
>N,N,R,R,R
END_TURN 5 N,N,N,N,N N,N,r,r,R
END_DAY 1 A,A,A,A,A A,A,D,D,A
START_DAY 2/3
START_TURN 1
>S,S,N,S,N
END_TURN 1 R,R,R,R,R S,S,D,D,N
END_DAY 2 A,A,A,A,A D,D,D,D,D
EXIT

Баллы за приведенный выше пример:

Bot#    Day 1   Day 2   Total
1       10      0       10
  S1    1+2     0       3
  S2    0       0       0
  S3    1+2     0       3
  S4    1       0       1
  S5    1+2     0       3

2       20      0       20
  S1    1+2     0       3
  S2    1+2     0       3
  S3    0       0       0
  S4    0       0       0
  S5    1+2+3+8 0       14

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

множество

Bot               Score
Bob               2939.422
Statisticians     2905.833
Morning Birds     1652.325
Evolved           1578.285
Slow Returners    1224.318
Wandering Fools   1065.908
Randomizers       735.313
Drunkards         0     
Plague            0

Логи доступны на GitHub . Результаты по каждой пробной версии доступны в этой электронной таблице Google .

es1024
источник
Если слуга не возвращается, учитывается ли он в числе людей, которые умирают в этот день?
EagleV_Attnam
@EagleV_Attnam День заканчивается либо тогда, когда вернулось достаточно слуг, либо прошло 30 ходов, в которых все, кто не вернулся, умрут, независимо от ранее определенного количества смертей.
es1024
Да, это было глупо, извини.
EagleV_Attnam
Если слуга вернется в лагерь, сможет ли он доставить найденное до сих пор сокровище, а затем снова отправиться на поиски в тот же день?
Логика Найт
1
@ MikeSweeney Нет. Как только слуга возвращается, он остается.
es1024

Ответы:

5

Боб - C ++

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>

using namespace std;

int compare(int i, int j)
  {
  if (i < j)
    return (-1);
  if (i == j)
    return (0);
  if (i > j)
    return (1);
  }

int main()
  {
  int index;
  int day;
  int turn;
  int slash_index;
  int to_die;
  int num_alive;
  int mine_alive;
  int turn_to_return;
  bool returned;
  string line;
  vector<int> last_returns;
  vector<int> today_returns;

  getline(cin, line);

  if (line.compare(0, 6, "INDEX ") != 0)
    {
    cerr << "INVALID INDEX LINE \"" << line << "\"" << endl;

    return (-1);
    }

  index = atoi(line.substr(6).c_str()) - 1;

  while (1) // Day loop
    {
    getline(cin, line);
    if (line.compare(0, 4, "EXIT") == 0)
      {
      return (0);
      }
    else if (line.compare(0, 9, "START_DAY") != 0 || (slash_index = line.find('/')) == string::npos)
      {
      cerr << "INVALID START_DAY \"" << line << "\"" << endl;
      return (-1);
      }

    day = atoi(line.substr(10, slash_index - 10).c_str());
    to_die = atoi(line.substr(slash_index + 1, line.length() - slash_index - 1).c_str());

    if (day != 1)
      {
      if (to_die > num_alive)
        {
        turn_to_return = 30;
        }
      else
        {
        turn_to_return = last_returns[last_returns.size() - to_die] - 1;
        }
      }

    returned = false;

    for (turn = 1; turn <= 30; ++turn)
      {
      getline(cin, line);

      if (line.compare(0, 4, "EXIT") == 0)
        {
        return (0);
        }
      if (line.compare(0, 7, "END_DAY") == 0)
        {
        goto end_day;
        }
      if (line.compare(0, 10, "START_TURN") != 0)
        {
        cerr << "INVALID START_TURN \"" << line << "\"" << endl;
        }

      if (day == 1)
        {
        switch (compare(turn, 30))
          {
            case -1:
              cout << "S,S,S,S,S" << endl;
              break;

            case 0:
              cout << "R,R,R,R,R" << endl;
              break;

            case 1:
              cout << "N,N,N,N,N" << endl;
              break;
          }
        }
      else
        {
        if (returned)
          {
          cout << "N,N,N,N,N" << endl;
          }
        /*
        else if (num_alive - today_returns.size() < to_die)
          {
          cout << "R,R,R,R,R" << endl;
          returned = true;
          }
        */
        else if (turn >= turn_to_return)
          {
          cout << "R,R,R,R,R" << endl;
          returned = true;
          }
        else
          {
          cout << "S,S,S,S,S" << endl;
          }
        }

      getline(cin, line);

      if (line.compare(0, 4, "EXIT") == 0)
        {
        return (0);
        }
      if (line.compare(0, 8, "END_TURN") != 0)
        {
        cerr << "INVALID END_TURN \"" << line << "\"" << endl;
        }

      stringstream ss(line);
      string item;
      int i = 0;
      while (getline(ss, item, ' '))
        {
        i++;
        if (i > 2 && i - 3 != index)
          {
          int num_to_add = count(item.begin(), item.end(), 'R'); // Add turn to today_returns for each servant that returned
          for (int j = 0; j < num_to_add; j++)
            {
            today_returns.push_back(turn);
            }
          }
        }

      }

    getline(cin, line);

  end_day:

    if (line.compare(0, 4, "EXIT") == 0)
      {
      return (0);
      }
    else if (line.compare(0, 7, "END_DAY") != 0)
      {
      cerr << "INVALID END_DAY \"" << line << "\"" << endl;
      return (-1);
      }

    stringstream ss(line);
    string item;
    int i = 0;
    num_alive = 0;
    while (getline(ss, item, ' '))
      {
      i++;
      if (i > 2 && i - 3 != index)
        {
        num_alive += count(item.begin(), item.end(), 'A');
        }
      else if (i - 3 == index)
        {
        mine_alive = count(item.begin(), item.end(), 'A');
        }
      }

    last_returns = today_returns;
    today_returns.clear();

    }

  return (0);
  }

Компилировать:

g++ -o Bob.exe Bob.cpp

Бежать:

./players/Bob/Bob.exe

источник
6

Статистика, Питон 3

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

программа

# Team of treasure-hunting statisticians
# Run with:
# python3 statisticians.py

num_others = None
running = True
while running:
    msg = input().split()
    msg_type = msg.pop(0)
    if msg_type == "INDEX":
        my_index = int(msg[0])-1
    elif msg_type == "START_DAY":
        day, max_deaths = tuple(map(int, msg[0].split('/')))
    elif msg_type == "START_TURN":
        turn = int(msg[0])
        if day == 1:
            if turn == 1:
                print("S,S,S,S,S")
            elif turn == 30 or num_active <= max_deaths * 4/5:
                print("R,R,R,R,R") # On first day, return when 4/5 of  maximum number of dying servants remain
            else:
                print("S,S,S,S,S")
        elif turn >= 29 or len(expected_servants[turn+1]) <= max(2, max_deaths * 3/4) or len(expected_servants[turn]) <= max(2, max_deaths * 1/4):
            print("R,R,R,R,R") # If many servants are expected to return next turn or someone is sure to die, return to camp
        else:
            print("S,S,S,S,S") # Otherwise, keep going
    elif msg_type == "END_TURN":
        turn = int(msg.pop(0))
        others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]]
        if num_others is None: # End of first turn, initialize variables that depend on number of servants
            num_others = len(others_moves)
            others_history = [{} for i in range(num_others)]
        if day == 1:
            num_active = sum([move.count('S') for move in others_moves])
        for i, moves in enumerate(others_moves): # Log the return habits of other bots
            if turn == 1:
                others_history[i][day] = [0]*5
            for j, move in enumerate(moves):
                if move == "R": # Only safely returned servants are taken into account
                    others_history[i][day][j] = turn
                    if day > 1:
                        for future_turn in range(turn, 30):
                            expected_servants[future_turn].discard((i,j))
    elif msg_type == "END_DAY":
        day = int(msg.pop(0))
        my_statuses = tuple(msg[my_index].split(','))
        others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]]
        expected_servants = [set() for i in range(30)] # Compute the sets of expected servants for each turn
        for i in range(num_others):
            for j in range(5):
                if others_statuses[i][j] == 'A':
                    turn_sum = 0
                    for day_num in others_history[i]:
                        turn_sum += others_history[i][day_num][j]
                    for turn in range(turn_sum//day):
                        expected_servants[turn].add((i,j))
    elif msg_type == "EXIT":
        running = False

Как видите, я бесстыдно украл структуру программы у @Mike Sweeney.

команда

python3 statisticians.py

РЕДАКТИРОВАТЬ: Исправлена ​​ошибка в проверке для возвращения домой. Они должны работать несколько лучше сейчас.

РЕДАКТИРОВАТЬ 2: Статистики теперь умнее, чем раньше: они отслеживают, какие слуги вернулись в лагерь в текущий день, и соответствующим образом корректируют свои прогнозы. Кроме того, они рискуют, возвращаясь в лагерь, когда остается 3/4 от максимального числа умирающих слуг. Это толкает их обратно к вершине (едва; Боб стал очень опасным).

Zgarb
источник
5

Пьяница, Perl 5

Слишком много алкоголя, и они никогда не найдут дорогу обратно в лагерь.

Эта запись в первую очередь пример, но будет участвовать.

программа

#!/usr/bin/perl
use 5.10.1;
$| = 1; # disable buffering
@actions = qw(S S S S S);

$_ = <>; ~/^INDEX (\d+)/;
$index = $1;

while(<>){
    if(index($_, 'START_TURN') == 0){
        say join(',', @actions);
    }elsif(index($_, 'END_DAY') == 0){ 
        # update actions based on who is alive
        # index 1-indexed; first bot at position 2.
        # this is not actually necessary for Drunkards, as all of Drunkards'
        #  servants will die on day 1 in any case.
        # This check is here simply as an example.
        my @status = split(',',(split(' '))[$index + 1]);
        my $i;
        for($i = 0; $i < 5; ++$i){
            # action is S if alive, N if dead. Servants will never be in camp.
            $actions[$i] = $status[$i] eq 'A' ? 'S' : 'N';
        }
    }elsif(index($_, 'EXIT') == 0){
        exit 0;
    }
}

команда

perl ./players/Drunkards/Drunkards.pl
es1024
источник
Если ваш код $status[$i] eq 'A' ? 'S' : 'D';будет $status[$i] eq 'A' ? 'S' : 'N';встретить спецификации?
Логика Найт
@MikeSweeney Хороший улов. Я забыл исправить это, когда я изменил спецификацию, пока этот вызов был еще в песочнице.
es1024
4

Утренние Птицы

Ранняя пташка ловит червя !!!

package players.MorningBirds;

import java.io.*;
import java.util.*;

/*
 * Java 7
 * 
 * Compile with "javac ./players/MorningBirds/MorningBirds.java"
 * Run with "java players.MorningBirds.MorningBirds"
 * 
 * Servants find treasure from morning until noon.
 * At noon they go to bed to prepare for next day.
 * 
 * According to Benjamin Franklin, "Early to bed, early to rise, keeps a 
 *      man healthy, WEALTHY, and wise."
 * 
 * 
 */
public class MorningBirds {

    protected final static String STARTDAY = "START_DAY";

    protected final static String STARTTURN = "START_TURN";

    protected final static String ENDTURN = "END_TURN";

    protected final static String ENDDAY = "END_DAY";

    protected final static String MOVERETURN = "R";

    protected final static String MOVESEARCH = "S";

    protected final static String MOVENOTHING = "N";

    protected final static String RETURNED = "R";

    protected final static String FAILEDRETURN = "r";

    protected final static String SEARCHING = "S";

    protected final static String DEAD = "D";

    protected final static String SLEEPING = "N";

    protected final static String EXIT = "EXIT";

    protected final static String ALIVE = "A";

    protected enum Status{SEARCHING, DEAD, RETURNED}

    protected enum Move{RETURN, SEARCH, NOTHING}

    protected int index;

    protected int day;

    protected int turnNum;

    protected int howManyTeams;

    protected int howManyWillDieTodayAtMost;

    protected int howManyHaveDiedToday;

    protected int howManyEnemyPlayers;

    protected int howManyAliveEnemyPlayers;

    protected int howManyEnemyTeams;

    protected int howManyDeadEnemyPlayers;

    protected int howManyReturnedEnemyPlayers;

    protected int howManySearchingEnemyPlayers;

    protected int howManyTotalPlayers;

    protected int howManyTotalAlivePlayers;

    protected int howManyTotalDeadPlayers;

    protected int howManyTotalReturnedPlayers;

    protected int howManyTotalSearchingPlayers;

    protected int howManyOwnAlivePlayers;

    protected int howManyOwnDeadPlayers;

    protected int howManyOwnReturnedPlayers;

    protected int howManyOwnSearchingPlayers;

    protected Status[] statuses = new Status[5];

    protected Status[][] allStatuses = null;

    protected List<Status[][]> allDayStatuses = null;

    protected List<List<Status[][]>> allTimeStatuses = new ArrayList<>();

    protected BufferedReader in = new BufferedReader(
            new InputStreamReader(System.in));

    public static void main (String args[]) throws Exception{
        new MorningBirds().start();
    }

    public void start() throws Exception{

        index = Integer.parseInt(in.readLine().split("\\s")[1]);
        Arrays.fill(statuses, Status.SEARCHING);

        while(true){
            String[] input = in.readLine().split("\\s");
            if (input[0].equals(ENDTURN) || input[0].equals(ENDDAY)){
                updateStatus(input);
            } else if (input[0].equals(EXIT)){
                return;
            } else if (input[0].equals(STARTDAY)){
                updateDay(input);
            } else if (input[0].equals(STARTTURN)){
                updateTurn(input);
                doTurn(input);
            }

        }

    }

    protected void updateStatus(String[] input){
        if (allStatuses == null && input[0].equals(ENDTURN)){
            allStatuses = new Status[input.length - 2][5];
            for (Status[] enemyStatus : allStatuses){
                Arrays.fill(enemyStatus, Status.SEARCHING);
            }
            howManyTeams = input.length - 2;
            howManyEnemyTeams = input.length - 3;
            howManyTotalPlayers = howManyTeams * 5;
            howManyTotalAlivePlayers = howManyTotalPlayers;
            howManyTotalSearchingPlayers = howManyTotalAlivePlayers;
            howManyAliveEnemyPlayers = howManyTotalPlayers - 5;
            howManyEnemyPlayers = howManyEnemyTeams * 5;
            howManyOwnAlivePlayers = 5;
            howManyOwnSearchingPlayers = 5;
            howManySearchingEnemyPlayers = howManyAliveEnemyPlayers;
        }
        for ( int j = 0; j < howManyTeams; j++){
            String[] stats = input[j + 2].split(",");
            for(int i = 0; i < 5; i++){
                switch (stats[i]){
                    case "R":
                    case "N":
                        if (allStatuses[j][i] != Status.RETURNED){
                            howManyTotalReturnedPlayers++;
                            howManyTotalSearchingPlayers--;
                            if (j == index - 1) {
                                howManyOwnReturnedPlayers++;
                                howManyOwnSearchingPlayers--;
                            } else {
                                howManyReturnedEnemyPlayers++;
                                howManySearchingEnemyPlayers--;
                            }
                        }
                        allStatuses[j][i] = Status.RETURNED;
                        break;
                    case "A":
                    case "S":
                        if (allStatuses[j][i] != Status.SEARCHING){
                            howManyTotalReturnedPlayers--;
                            howManyTotalSearchingPlayers++;
                            if (j == index - 1) {
                                howManyOwnReturnedPlayers--;
                                howManyOwnSearchingPlayers++;
                            } else {
                                howManyReturnedEnemyPlayers--;
                                howManySearchingEnemyPlayers++;
                            }
                        }
                        allStatuses[j][i] = Status.SEARCHING;
                        break;
                    case "r":
                    case "D":
                        if (allStatuses[j][i] != Status.DEAD){
                            howManyTotalAlivePlayers--;
                            howManyTotalDeadPlayers++;
                            howManyHaveDiedToday++;
                            howManyTotalSearchingPlayers--;
                            if (j == index - 1){
                                howManyOwnAlivePlayers--;
                                howManyOwnDeadPlayers++;
                                howManyOwnSearchingPlayers--;
                            } else {
                                howManyAliveEnemyPlayers--;
                                howManyDeadEnemyPlayers++;
                                howManySearchingEnemyPlayers--;
                            }
                        }
                        allStatuses[j][i] = Status.DEAD;
                        break;
                    default:
                        break;
                }
            }
        }
        statuses = allStatuses[index - 1];
        if (input[0].equals(ENDTURN)){
            allDayStatuses.add(allStatuses.clone());
        }
        if (input[0].equals(ENDDAY)){
            Status[][] statusesToAdd = new Status[howManyTeams][5];
            for (int i = 0; i < statusesToAdd.length; i++){
                for (int j = 0; j < statusesToAdd[i].length; j++){
                    if (allStatuses[i][j] == Status.SEARCHING){
                        statusesToAdd[i][j] = Status.RETURNED;
                    } else {
                        statusesToAdd[i][j] = Status.DEAD;
                    }
                }
            }
            while (turnNum <= 30){
                allDayStatuses.add(statusesToAdd.clone());
                turnNum++;
            }
            allTimeStatuses.add(allDayStatuses);
        }
    }

    protected void updateDay(String[] input) throws Exception{
        day = Integer.parseInt(input[1].split("/")[0]);
        howManyWillDieTodayAtMost = Integer.parseInt(input[1].split("/")[1]);
        howManyHaveDiedToday = 0;
        allDayStatuses = new ArrayList<>();
        if (day == 1){
            Arrays.fill(statuses, Status.SEARCHING);
            howManyOwnAlivePlayers = 5;
            howManyOwnSearchingPlayers = 5;
        }
    }

    protected void updateTurn(String[] input){
        turnNum = Integer.parseInt(input[1]);
    }

    protected void doTurn(String[] input){
        Move[] moves = new Move[5];
        for (int i = 0; i < 5; i++){
            if (statuses[i] == Status.DEAD ||
                        statuses[i] == Status.RETURNED) {
                moves[i] = Move.NOTHING;
                continue;
            } else {
                moves[i] = doMove(i);
            }
        }
        String[] outputs = new String[5];
        for (int i = 0; i < 5; i++){
            switch (moves[i]){
                case SEARCH:
                    outputs[i] = MOVESEARCH;
                    break;
                case RETURN:
                    outputs[i] = MOVERETURN;
                    break;
                case NOTHING:
                    outputs[i] = MOVENOTHING;
            }
        }
        String totalOutput = "";
        for(String output : outputs){
            if (totalOutput != ""){
                totalOutput += ",";
            }
            totalOutput += output;
        }
         System.out.println(totalOutput);
    }

    //Implement this method differently for different 
    //strategies. 
    public Move doMove(int playerNumber){
        if (turnNum >= 15){
            return Move.RETURN;
        }
        return Move.SEARCH;
    }

    /**
     * Returns the status of one of your players. 
     * Your players have numbers 1 to 5 inclusive.
     * Throws exception if number is outside range.
     * 
     */
    protected Status getStatus(int player){
        if (player > 5 || player < 1){
            throw new IllegalArgumentException(
                    "getStatus(" + player +") failed.");
        }
        return statuses[player - 1];
    }

    /**
     * Returns the status of a player in a team.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     * Returns Status.SEARCHING if day == 1 and turnNum == 1 and argument 
     * team >= 1.
     */
    protected Status getStatus(int team, int player){
        if (team < 1 || player < 1 || player > 1 || 
                (team > howManyTeams && day == 1 && turnNum == 1)){
            throw new IllegalArgumentException(
                    "getStatus(" + team + ", " + player + ") failed.");
        }
        if (day == 1 && turnNum == 1 && team >= 1){
            return Status.SEARCHING;
        }
        return allStatuses[team - 1][player - 1];
    }

    /**
     * Returns the status of a player in a team at the end of argument
     * turn.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Turns have numbers 0 to 30 inclusive.
     * Status at turn 0 is equal to status at start of turn 1.
     * Throws exception if argument turn hasn't happened yet.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     */
    protected Status getStatus(int turn, int team, int player){
        if (turn == 0){
            if (day == 1){
                return Status.SEARCHING;
            } else {
                return getStatus(day - 1, 30, team, player);
            }
        }
        if (turnNum <= turn || turn < 0|| player > 5 || player < 1 ||
                team < 1 || team > howManyTeams){
            throw new IllegalArgumentException("getStatus(" + turn + 
                    ", " + team + ", " + player + ") failed.");
        }
        return allDayStatuses.get(turn - 1)[team - 1][player - 1];
    }

    /**
     * Returns the status of a player in a team at the end of argument
     * turn on the day of argument day.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Turns have numbers 0 to 30 inclusive.
     * Days have numbers 1 inclusive and up.
     * Status at turn 0 is equal to status at start of turn 1.
     * Throws exception if argument day hasn't ended yet or is less 
     * than one.
     * Throws exception if argument turn is out of range.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     */
    protected Status getStatus(int day, int turn, int team, int player){
        if (turn == 0){
            if (day == 1){
                return Status.SEARCHING;
            } else {
                return getStatus(day - 1, 30, team, player);
            }
        }
        if (this.day <= day || day < 1 || turn > 30 || turn < 0 || 
                player > 5 || player < 1 ||
                team < 1 || team > howManyTeams){
            throw new IllegalArgumentException("getStatus(" + day + ", "
                    + turn + ", " + team + ", " + player + ") failed.");
        }
        return allTimeStatuses.get(day - 1).get(turn - 1)[team - 1][player - 1];
    }

}

Изменить: Сделано так, чтобы любой мог легко разделить его на подклассы. Просто переопределите doMove(int playerNumber)свой собственный бот. Я добавил несколько полезных полей и методов. Я тщательно проверил это. Это не сохраняет статусы от предыдущих симуляций. Пожалуйста, скажите мне, если есть какие-либо проблемы.

Компилировать с: javac ./players/MorningBirds/MorningBirds.java

Бежать с: java players.MorningBirds.MorningBirds

Номер один
источник
Было бы хорошо, если бы я сделал методы и переменные защищенными, а позже сделал подкласс этого для вызова?
TheNumberOne
Не стесняйтесь использовать несколько исходных файлов, если это необходимо, или повторно использовать код из других записей, если записи не работают вместе.
es1024
@ es1024 В экспериментах я заметил, что бот умирает, если он ничего не делает весь день с первого хода. Это предназначено?
TheNumberOne
Бот, который никогда не вернется ( R) в любой данный день, всегда умрет в этот день.
es1024
Контроллер перестает отвечать на запросы, если я добавляю игроков SlowReturners и Randomizer. Примечание: извините, я размещаю комментарии здесь. У меня нет репутации, необходимой для публикации в другом месте.
TheNumberOne
3

Рандомайзеры - Ruby

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

(Не зависит от других игроков.)

def min(a,b);(a<b)?a:b;end
x=""
r=0
while x != "EXIT"
  x=gets.chomp
  if x =~ /^START_DAY/
    r = min(rand(30),rand(30))
  end
  if x =~ /^START_TURN (\d*)/
    puts ($1.to_i>r)?'R,R,R,R,R':'S,S,S,S,S'
  end
end
MegaTom
источник
2

Блуждающие Дураки, Питон 2

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

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

программа

import sys
from random import randint, choice
team = range(5)

while True:
    inp = sys.stdin.readline().split()
    cmd = inp.pop(0)
    if cmd == 'INDEX':
        teamnum = int(inp[0]) - 1   # using zero based indexing
    elif cmd == 'START_DAY':
        daynum, deadnum = [int(v) for v in inp[0].split('/')]
        # Set up strategy for the day:
        goback = [randint(5,25) for i in team]
    elif cmd == 'START_TURN':
        turn = int(inp[0])
        # Output actions [R]eturn, [S]earch, [N]othing here:
        actions = ['S' if turn < goback[i] else 'R' for i in team]
        sys.stdout.write( (','.join(actions)) + '\n' )
        sys.stdout.flush()
    elif cmd == 'END_TURN':
        endturn = int(inp.pop(0))
        status = [v.split(',') for v in inp]  # R,r,S,D,N
        # [R]eturned, [r]ejected, [S]earching, [D]ead, [N]othing
        mystatus = status[teamnum]
    elif cmd == 'END_DAY':
        endturn = int(inp.pop(0))
        alive = [v.split(',') for v in inp]  # [A]live or [D]ead
        myalive = alive[teamnum]
    elif cmd == 'EXIT':
        sys.exit(0)

команда

python WanderingFools.py

Редактировать: Изменено действие решающего кода после уточнения правил.

Логика Найт
источник
2

Evolved

Я использовал Генетическое Программирование (через JGAP), чтобы сделать этого бота. Он придумал простой ответ, который побеждает всех остальных (едва).

package players.Evolved;

import players.MorningBirds.*;
import java.util.*;

public class Evolved extends MorningBirds{

    List<Integer> scrambled = new ArrayList<>();

    public static void main(String[] args) throws Exception{
        new Evolved().start();
    }

    public Evolved() throws Exception{
        super();
    }

    @Override
    public MorningBirds.Move doMove(int playerNum){
        if (!(howManyTotalSearchingPlayers < (turnNum - getScrambled(index)))){
            return Move.SEARCH;
        } else {
            return Move.RETURN;
        }
    }

    @Override
    protected void updateStatus(String[] input){
        super.updateStatus(input);
        if (input[0].equals(ENDTURN) && (Integer.parseInt(input[1]) == 1)){
            for (int i = 1; i <= howManyTeams; i++){
                scrambled.add(i);
            }
            Collections.shuffle(scrambled);
        }
    } 

    public int getScrambled(int in){
        if (in > scrambled.size() || in < 1 ){
            return in;
        }
        return scrambled.get(in - 1);
    }
}

Компилировать с: javac players/Evolved/Evolved.java

Бежать с: java players.Evolved.Evolved

Редактировать: Grrr ... Боб испортил меня !!!

Редактировать: Yay !!! Боб, был убит мерзкой чумой !!!

Номер один
источник
1

SlowReturners - Ruby

Посылает одного слугу обратно каждые 5 ходов.

x=""
while x != "EXIT"
  x=gets.chomp
  if x =~ /^START_TURN (\d*)/
    puts (1..5).map{|i|(i<=$1.to_i/5)?"R":"S"}.join(",")
  end
end
MegaTom
источник
1

мор

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

package players.Plague;

import players.MorningBirds.MorningBirds;

public class Plague extends MorningBirds{

    public static void main(String[] args) throws Exception{
        new Plague().start();
    }

    public Plague() throws Exception{
        super();
    }

    @Override
    public MorningBirds.Move doMove(int playerNum){
        if (day > howManyTotalDeadPlayers){
            return Move.SEARCH;
        } else {
            return Move.RETURN;
        }
    }
}

Компилировать с: javac players/Plague/Plague.java

Бежать с: java players.Plague.Plague

Боб и статистика теперь устойчивы к чуме.

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