Caccia al tesoro su un'isola deserta


13

introduzione

Sei bloccato su un'isola deserta con alcuni servi e stai cercando il tesoro. Più a lungo si cerca, più tesoro si trova. Meno persone cercano, più ogni persona trova.

A causa di scorte limitate, il leader ha deciso che alcune persone, fino a un quarto del gruppo, dovranno morire ogni notte. Ha deciso di non dire a nessuno esattamente quante persone moriranno in un dato giorno prima.

Hai il controllo di un piccolo gruppo di 5 persone, che si avventureranno fuori dal campo per trovare tesori per te.

Obbiettivo

L'obiettivo di questa competizione è quello di accumulare il maggior tesoro possibile. Ogni turno in cui i tuoi servi non tentano di tornare al campo, troveranno un certo numero di tesori. I tuoi servi possono tornare al campo in momenti diversi.

Ogni turno in cui un lavoratore rimane fuori alla ricerca di un tesoro, il lavoratore trova 1+Rpezzi di tesoro, dove si Rtrova il numero di lavoratori (tra tutti i robot) già rientrati nel campo. I robot morti non tengono conto di questo calcolo.

All'inizio di ogni giorno, verrà scelto un numero casuale ( n) da 2a max(3, floor(num_live_players/4)). (Per i 10 giocatori il giorno 1, questo è 2per max(3,50/4)=12. Per 20 giocatori in 1 giorno, questo sarebbe 2amax(3,100/4)=25 .) Questo numero rappresenta il numero di giocatori che saranno lasciati a morire per quel giorno, e non sarà dato al vostro programma .

Se un servitore è una delle ultime npersone a tornare, morirà e non sarà in grado di trasferire il tesoro che ha trovato in tuo possesso. Inoltre, il servitore non sarà in grado di partecipare alla caccia al tesoro per il resto dell'avventura.

Il tuo punteggio finale è la quantità media di tesori ottenuti per avventura (corsa del controller).

Se più persone tentano di tornare al campo nello stesso turno di quante sono le slot aperte, i numeri casuali determineranno chi entra e chi muore.

Una giornata su quest'isola dall'alba al tramonto dura 30 turni. Dato che ci sono molti animali pericolosi di notte, il mancato ritorno al tramonto significa che non ti sarà permesso entrare nel campo.

Input Output

Il programma dovrebbe essere eseguito per l'intera simulazione.

All'inizio della simulazione, INDEX Iverrà inserito, dove si Itrova l'indice del tuo bot (questo indice viene conteggiato da 1 in su).

All'inizio di ogni giorno, START_DAY D/Nverrà inserito nel tuo programma, dove si Dtrova il numero del giorno (a partire da 1), ed Nè uguale max(3, floor(num_live_players/4)), che è il numero massimo di persone che possono morire in quel particolare giorno.

All'inizio di ogni turno, START_TURN Tverrà inserito il tuo programma, dove si Ttrova il numero di turno (a partire da 1).

Una volta che il tuo programma lo riceve, dovrebbe rispondere con un elenco di mosse dei tuoi servitori, ognuna separata da una virgola.

Le mosse valide sono:

  • R: Prova a tornare al campo.
  • S: Resta in cerca di tesori.
  • N: Il servo è già morto o in campo.

L'immissione di una mossa non valida verrà interpretata come Sse il bot fosse vivo e non in campo, e Naltrimenti.

Alla fine di ogni turno, una stringa deve essere passata al tuo programma:

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

dove le mosse dei servitori di ogni bot sono separate da virgole.

Queste mosse saranno una delle seguenti:

  • R: È tornato al campo con successo in quel turno.
  • r: Impossibile tornare al campo in quel turno.
  • S: Sto ancora cercando un tesoro.
  • D: È morto in un turno precedente.
  • N: Già tornato al campo.

Robot e servitori rimangono nello stesso ordine per tutta la simulazione.

Per esempio:

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

Qui, sei il secondo bot ( r,r,r,r,r), che ha cercato di restituire tutti e quattro i servitori che sono ancora vivi (e sfortunatamente fallito su tutti e quattro). I servitori di Bot 1 sono tutti tornati al campo. Bot 3 ha tre servi morti, uno in campo e un quinto che è tornato con successo. Il Bot 4 ha un servitore che è rimasto (e morirà, poiché questo è l'ultimo turno di un giorno), un servo nel campo e tre servi morti.

Dopo ciascuna di queste stringhe, a meno che non sia stata emessa anche una stringa che segnala la fine della giornata (vedi sotto), il tuo programma è quello di produrre le mosse successive dei tuoi servitori, separate da virgole. Tutti i servitori devono essere contabilizzati (con Nse già nel campo e Dse sono già morti). Le mosse non valide verranno trattate come Sse il servitore non fosse già in campo / morto. Esempio:

N,N,S,S,R

che significa:

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.

Alla fine di una giornata, la stringa seguente deve essere passata dopo l'ultima ENDstringa del turno , informando tutti su chi è vivo:

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

dove lo stato è un elenco separato da virgole di A(vivo) o D(morto). Il giorno seguente inizia immediatamente dopo.

La simulazione termina quando ci sono meno di 6 servi attivi. Il tuo programma riceverà il seguente input al termine della simulazione:

EXIT

Regole / Dettagli

  • Solo nei turni in cui si trova la tua azione Stroverai tesoro.
  • Numero di simulazioni eseguite: 1000 volte
  • Il tuo programma non dovrebbe richiedere più di 1 secondo per determinare le mosse.
  • Il tuo programma non dovrebbe uscire presto; verrà avviato esattamente una volta.
  • Assicurarsi che il buffer di output (se applicabile) sia scaricato dopo ogni output.
  • I file possono essere scritti nella cartella del bot ( ./players/BotName/). Il nome del tuo bot è come ti chiami, con tutti i caratteri non alfanumerici rimossi e scritti in CamelCase. Le voci possono salvare i dati tra le esecuzioni del controller, poiché le esecuzioni vengono eseguite in sequenza.
  • Il programma deve uscire dopo aver ricevuto EXIT.
  • I programmi che non riescono a compilare o generare errori o produrre testo non valido (non nel formato di 5 caratteri separati da virgole) possono essere esclusi dalla competizione. Una nuova riga deve seguire ogni output.
  • Il controller può essere trovato su GitHub .

Includere il nome del bot, lingua + versione, codice e comando per compilare (se applicabile) ed eseguire il bot.

Esempio

Il testo emesso dal programma è preceduto da un >. Il tuo programma non dovrebbe generare questo carattere.

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

I punteggi per l'esempio sopra sono:

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

Il vincitore è quindi il giocatore, bot 2. Nota che il vincitore non deve sopravvivere fino alla fine assoluta. (Nota anche che il giocatore sarebbe potuto rimanere fino al turno 30 del primo giorno, poiché l'accampamento non sarebbe stato pieno fino a quando il giocatore non avesse rispedito un altro robot).

I punteggi

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

I log sono disponibili su GitHub . I risultati per ciascuna prova sono disponibili su questo foglio di calcolo di Google .


Se un servo non ritorna, viene conteggiato per il numero di persone che muoiono oggi?
EagleV_Attnam,

@EagleV_Attnam La giornata termina quando ci sono abbastanza servitori che sono tornati, o sono trascorsi 30 turni, in cui moriranno tutti coloro che non sono tornati, indipendentemente dal numero di morti precedentemente determinato.
es1024

Giusto, era sciocco, scusa.
EagleV_Attnam,

Se un servitore torna al campo, può consegnare il tesoro trovato finora e poi uscire di nuovo a cercare lo stesso giorno?
Logic Knight,

1
@MikeSweeney No. Una volta tornato, un servitore rimane.
es1024,

Risposte:


5

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

Compilare:

g++ -o Bob.exe Bob.cpp

Correre:

./players/Bob/Bob.exe

6

Statistici, Python 3

Gli statistici lavorano sempre insieme. Al primo turno, ritornano al campo quando due terzi dei loro avversari lo hanno fatto. Nei turni successivi, si basano sui dati raccolti nei turni precedenti per prevedere le abitudini degli altri servitori e tentano di tornare al campo all'ultimo momento sicuro.

Programma

# 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

Come puoi vedere, ho spudoratamente rubato la struttura del programma a @Mike Sweeney.

Comando

python3 statisticians.py

EDIT: corretto un bug nel controllo per il ritorno a casa. Dovrebbero esibirsi un po 'meglio ora.

EDIT 2: Gli statistici sono ora più intelligenti di prima: tengono traccia di quali servitori sono tornati al campo nel giorno corrente e modificano le loro previsioni di conseguenza. Inoltre, corrono più rischi, tornando al campo quando rimangono 3/4 del numero massimo di servitori morenti. Questo li riporta in cima (a malapena; Bob è diventato molto pericoloso).


5

Ubriachi, Perl 5

Un po 'troppo alcolici e non troveranno mai la strada per tornare al campo.

Questa voce è principalmente un esempio, ma parteciperà.

Programma

#!/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;
    }
}

Comando

perl ./players/Drunkards/Drunkards.pl

Il tuo codice dovrebbe $status[$i] eq 'A' ? 'S' : 'D';essere $status[$i] eq 'A' ? 'S' : 'N';conforme alle specifiche?
Logic Knight,

@MikeSweeney Buona cattura. Ho dimenticato di sistemarlo quando ho cambiato le specifiche mentre questa sfida era ancora nella sandbox.
es1024,

4

Morning Birds

Il mattino ha l'oro in bocca!!!

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

}

Modifica: creato in modo che chiunque potesse facilmente sottoclassarlo. Basta ridefinire doMove(int playerNumber)per il tuo bot. Ho aggiunto diversi campi e metodi utili. L'ho ampiamente testato. Essa non salvare gli stati da simulazioni precedenti. Per favore dimmi se ci sono problemi.

Compilare con: javac ./players/MorningBirds/MorningBirds.java

Corri con: java players.MorningBirds.MorningBirds


Andrebbe bene se avessi protetto i metodi e le variabili e successivamente ne avessi fatto una sottoclasse per la sfida?
TheNumberOne

Sentiti libero di usare più file sorgente se necessario, o riutilizzare il codice da altre voci, purché le voci non funzionino insieme.
es1024,

@ es1024 Nell'esperimento ho notato che un robot muore se non fa nulla per tutto il giorno dal turno 1. È previsto?
TheNumberOne

Un bot che non ritorna mai ( R) in un dato giorno morirà sempre quel giorno.
es1024,

Il controller non risponde se aggiungo giocatori SlowReturners e Randomizer. Nota: mi dispiace, sto postando commenti qui. Non ho la reputazione necessaria per pubblicare altrove.
TheNumberOne

3

Randomizer - Ruby

Solo per rovinare i robot basati sulle statistiche, i randomizzatori sono piuttosto imprevedibili. Tutti ritornano subito, a turno, nel tentativo di incagliare gli altri.

(Non influenzato da altri giocatori.)

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

2

Pazzo errante, Python 2

Questo è un semplice bot Python che invia i servi fino a quando non viene raggiunto un tempo di "goback" predefinito, quindi cercano di entrare nel campo e rimanere fino al giorno successivo.

È anche un framework di base per robot più complessi che altri potrebbero voler usare. Tuttavia, non è stato testato con il motore del giudice, quindi fatemi sapere se ho fatto un errore.

Programma

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)

Comando

python WanderingFools.py

Modifica: codice di decisione dell'azione modificato dopo il chiarimento della regola.


2

Evolved

Ho usato la programmazione genetica (tramite JGAP) per creare questo bot. Ha avuto una risposta semplice che batte tutti gli altri (a malapena).

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

Compilare con: javac players/Evolved/Evolved.java

Corri con: java players.Evolved.Evolved

Modificare: Grrr ... Bob mi ha incasinato !!!

Modifica: Yay !!! Bob, sono stato ucciso da una brutta pestilenza !!!


1

Ritorno lento - Rubino

Invia un servitore indietro ogni 5 turni.

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

1

Peste

La peste è una malattia. Non è razionale. È prevedibile. Le malattie non possono raccogliere tesori, né si preoccupano per il tesoro. La peste fa star male gli altri giocatori. I saggi rimangono a casa e dimenticano il tesoro. Quelli sciocchi sono sempre sciocchi e non avranno mai molto tesoro. Evoluto è (fortunatamente) immune alla peste. È anche saggio. Va e raccoglie tesori, e non muore.

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

Compilare con: javac players/Plague/Plague.java

Corri con: java players.Plague.Plague

Bob e gli statistici sono ora resistenti alla peste.


hmm ... quando

Ho usato un algoritmo genetico per farlo. Dovrebbe morire il secondo giorno. Confonde i robot basati sulle statistiche in modo che si comportino piuttosto male rispetto a Evolved.
TheNumberOne il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.