Berburu Harta Karun di Pulau Sepi

13

pengantar

Anda terdampar di pulau terpencil dengan beberapa pelayan dan sedang berburu harta karun. Semakin lama pencarian, semakin banyak harta yang ditemukan. Semakin sedikit orang yang mencari, semakin banyak setiap orang menemukan.

Karena persediaan terbatas, pemimpin telah memutuskan bahwa beberapa orang, hingga seperempat dari kelompok, harus dibiarkan mati setiap malam. Dia telah memutuskan untuk tidak memberi tahu siapa pun dengan pasti berapa banyak orang yang akan mati pada hari tertentu sebelumnya.

Anda mengendalikan sekelompok kecil 5 orang, yang akan keluar dari kamp untuk menemukan harta karun untuk Anda.

Objektif

Tujuan dari kompetisi ini adalah untuk mengumpulkan harta sebanyak mungkin. Setiap belokan yang pelayan Anda tidak berusaha kembali ke kemah, mereka akan menemukan sejumlah harta karun. Hamba Anda dapat kembali ke kemah pada waktu yang berbeda.

Setiap belokan yang ditinggalkan seorang pekerja untuk mencari harta karun, pekerja menemukan 1+Rpotongan-potongan harta, di mana Rjumlah pekerja (dari semua bot) sudah kembali ke kamp. Bot mati tidak memperhitungkan perhitungan ini.

Di awal setiap hari, nomor acak ( n) dari 2ke max(3, floor(num_live_players/4))akan dipilih. (Untuk 10 pemain pada hari 1, ini adalah 2untuk max(3,50/4)=12. Untuk 20 pemain pada hari 1, ini adalah 2untuk max(3,100/4)=25.) Angka ini mewakili jumlah pemain yang akan dibiarkan mati untuk hari itu, dan tidak akan diberikan ke program Anda .

Jika seorang pelayan adalah salah satu dari orang terakhir yang nkembali, dia akan mati dan tidak dapat memindahkan harta yang dia temukan kepada milikmu. Selain itu, pelayan tidak akan dapat berpartisipasi dalam perburuan harta karun selama sisa petualangan.

Skor akhir Anda adalah jumlah rata-rata harta yang Anda peroleh per petualangan (run of the controller).

Jika lebih banyak orang berusaha untuk kembali ke kemah pada giliran yang sama daripada yang ada slot terbuka, angka acak akan menentukan siapa yang masuk dan siapa yang mati.

Sehari di pulau ini dari matahari terbit hingga terbenam berlangsung selama 30 putaran. Karena ada banyak hewan berbahaya di malam hari, kegagalan untuk kembali saat matahari terbenam berarti Anda tidak akan diizinkan masuk ke kamp.

Input output

Program Anda harus dijalankan untuk keseluruhan simulasi.

Di awal simulasi, INDEX Iakan dimasukkan, di mana Iindeks bot Anda (indeks ini dihitung dari 1 ke atas).

Pada awal setiap hari, START_DAY D/Nakan dimasukkan ke program Anda, di mana Dnomor hari (mulai dari 1), dan Nsama dengan max(3, floor(num_live_players/4)), yang merupakan jumlah maksimum orang yang mungkin mati pada hari tertentu.

Pada awal setiap belokan, START_TURN Takan dimasukkan ke program Anda, di mana Tnomor belokan (mulai dari 1).

Setelah program Anda menerima ini, itu harus merespons dengan daftar gerakan pelayan Anda, masing-masing dipisahkan oleh koma.

Bergerak yang valid adalah:

  • R: Cobalah untuk kembali ke kemah.
  • S: Tetap mencari harta karun.
  • N: Hamba sudah mati atau di kamp.

Memasuki langkah yang tidak valid akan diartikan seolah- Solah bot itu hidup dan tidak di kamp, ​​dan Nsebaliknya.

Pada akhir setiap belokan, sebuah string akan diteruskan ke program Anda:

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

di mana setiap gerakan pelayan bot dipisahkan oleh koma.

Bergerak ini akan menjadi salah satu dari yang berikut:

  • R: Berhasil kembali ke kemah itu.
  • r: Gagal kembali ke kemah yang berbelok.
  • S: Masih mencari harta karun.
  • D: Meninggal pada giliran sebelumnya.
  • N: Sudah kembali di kemah.

Bot dan pelayan tetap dalam urutan yang sama di seluruh simulasi.

Sebagai contoh:

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

Di sini, Anda adalah bot kedua ( r,r,r,r,r), yang mencoba mengembalikan keempat pelayan yang masih hidup (dan sayangnya gagal pada keempatnya). Para pelayan Bot 1 semuanya kembali ke kemah. Bot 3 memiliki tiga pelayan yang mati, satu lagi di kamp, ​​dan seorang pelayan kelima yang berhasil kembali. Bot 4 memiliki satu pelayan yang tetap (dan akan mati, karena ini adalah pergantian terakhir dalam sehari), satu pelayan di kemah, dan tiga pelayan yang mati.

Setelah masing-masing string ini, kecuali string yang menandakan akhir hari juga telah dikeluarkan (lihat di bawah), program Anda adalah untuk menampilkan gerakan pelayan Anda berikutnya, dipisahkan dengan koma. Semua pelayan harus diperhitungkan (dengan Njika sudah di kamp, ​​dan Djika sudah mati). Perpindahan yang tidak valid akan diperlakukan seolah- Solah pelayan belum berada di kemah / mati. Contoh:

N,N,S,S,R

yang berarti:

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.

Pada akhir hari, string berikut harus dilewatkan setelah ENDstring belokan terakhir , memberi tahu semua orang tentang siapa yang hidup:

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

di mana statusnya adalah daftar yang dipisahkan koma baik A(hidup) atau D(mati). Hari berikutnya dimulai segera setelahnya.

Simulasi berakhir ketika ada kurang dari 6 pelayan hidup. Program Anda akan menerima input berikut di akhir simulasi:

EXIT

Aturan / Detail

  • Hanya secara bergantian di mana tindakan SAnda akan Anda menemukan harta karun.
  • Jumlah simulasi yang dijalankan: 1000 kali
  • Program Anda tidak boleh lebih dari 1 detik untuk menentukan gerakan.
  • Program Anda tidak boleh keluar lebih awal; itu akan dimulai tepat sekali.
  • Pastikan buffer output (jika ada) memerah setelah setiap output.
  • File dapat ditulis ke dalam folder bot Anda ( ./players/BotName/). Nama bot Anda adalah apa pun yang Anda beri nama bot Anda, dengan semua karakter non-alfanumerik dihapus dan ditulis dalam CamelCase. Entri dapat menyimpan data di antara run dari controller, karena run dilakukan secara berurutan.
  • Program Anda harus keluar setelah menerima EXIT.
  • Program yang gagal menyusun atau melempar kesalahan atau menghasilkan teks yang tidak valid (tidak dalam format 5 karakter yang dipisahkan oleh koma) dapat dikecualikan dari kompetisi. Baris baru harus mengikuti setiap output.
  • Pengontrol dapat ditemukan di GitHub .

Harap sertakan nama bot, bahasa + versi, kode, dan perintah untuk dikompilasi (jika ada) dan jalankan bot Anda.

Contoh

Teks yang dihasilkan oleh program diawali di sini dengan a >. Program Anda seharusnya tidak menampilkan karakter ini.

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

Skor untuk contoh di atas adalah:

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

Karena itu pemenangnya adalah pemain, bot 2. Perhatikan bahwa pemenang tidak harus bertahan sampai akhir mutlak. (Juga perhatikan bahwa pemain bisa tetap sampai 30 pada hari 1, karena kamp tidak akan penuh sampai pemain mengirim satu bot lagi).

Skor

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

Log tersedia di GitHub . Hasil per setiap percobaan tersedia di google spreadsheet ini .

es1024
sumber
Jika seorang pelayan tidak kembali, apakah ia diperhitungkan dengan jumlah orang yang meninggal hari ini?
EagleV_Attnam
@EagleV_Attnam Hari berakhir baik ketika ada cukup banyak pelayan yang telah kembali, atau 30 putaran telah berlalu, di mana setiap orang yang belum kembali akan mati, terlepas dari jumlah kematian yang ditentukan sebelumnya.
es1024
Benar, itu konyol, maaf.
EagleV_Attnam
Jika seorang pelayan kembali ke kemah, dapatkah dia mengirimkan harta yang ditemukan sejauh ini dan kemudian pergi mencari lagi pada hari yang sama?
Logic Knight
1
@MikeSweeney No. Begitu seorang pelayan kembali, dia tinggal.
es1024

Jawaban:

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

Untuk Mengkompilasi:

g++ -o Bob.exe Bob.cpp

Untuk berlari:

./players/Bob/Bob.exe

sumber
6

Ahli statistik, Python 3

Para ahli statistik selalu bekerja bersama. Pada belokan pertama, mereka kembali ke kamp ketika dua pertiga dari lawan mereka melakukannya. Pada belokan berikutnya, mereka mengandalkan data yang telah mereka kumpulkan dari belokan sebelumnya untuk memprediksi kebiasaan para pelayan lainnya, dan mencoba untuk kembali ke kamp pada saat aman terakhir.

Program

# 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

Seperti yang Anda lihat, saya tanpa malu-malu mencuri struktur program dari @ Mike Sweeney.

Perintah

python3 statisticians.py

EDIT: Memperbaiki bug di cek untuk kembali ke rumah. Mereka seharusnya tampil agak lebih baik sekarang.

EDIT 2: Para ahli statistik sekarang lebih pintar dari sebelumnya: mereka melacak para pelayan yang telah kembali ke kamp pada hari ini, dan menyesuaikan prediksi mereka sesuai dengan itu. Juga, mereka mengambil lebih banyak risiko, kembali ke kamp ketika 3/4 dari jumlah maksimum pelayan yang sekarat tetap ada. Ini mendorong mereka kembali ke atas (nyaris saja; Bob telah menjadi sangat berbahaya).

Zgarb
sumber
5

Pemabuk, Perl 5

Terlalu banyak alkohol dan mereka tidak akan pernah menemukan jalan kembali ke kemah.

Entri ini terutama merupakan contoh, tetapi akan berpartisipasi.

Program

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

Perintah

perl ./players/Drunkards/Drunkards.pl
es1024
sumber
Harus kode Anda $status[$i] eq 'A' ? 'S' : 'D';menjadi $status[$i] eq 'A' ? 'S' : 'N';untuk memenuhi spec?
Logic Knight
@ MikeSweeney Tangkapan yang bagus. Saya lupa memperbaikinya ketika saya mengubah spek saat tantangan ini masih di kotak pasir.
es1024
4

Burung Pagi

Burung awal menangkap cacing !!!

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

}

Sunting: Dibuat agar siapa pun dapat dengan mudah mensubklasifikasikan. Tetapkan ulang doMove(int playerNumber)untuk bot Anda sendiri. Saya telah menambahkan beberapa bidang dan metode yang bermanfaat. Saya sudah banyak mengujinya. Itu tidak menyimpan status dari simulasi sebelumnya. Tolong beritahu saya jika ada masalah.

Kompilasi dengan: javac ./players/MorningBirds/MorningBirds.java

Jalankan dengan: java players.MorningBirds.MorningBirds

TheNumberOne
sumber
Apakah tidak apa-apa jika saya membuat metode dan variabel terlindungi dan kemudian membuat subkelas ini untuk tantangan?
TheNumberOne
Jangan ragu untuk menggunakan banyak file sumber jika perlu, atau menggunakan kembali kode dari entri lain, selama entri tidak bekerja bersama.
es1024
@ es1024 Dalam percobaan saya perhatikan bahwa bot mati jika tidak melakukan apa-apa sepanjang hari dari belokan 1. Apakah itu dimaksudkan?
TheNumberOne
Bot yang tidak pernah kembali ( R) pada hari tertentu akan selalu mati pada hari itu.
es1024
Kontroler menjadi tidak responsif jika saya menambahkan pemain SlowReturners dan Randomizers. Catatan: Maaf saya memposting komentar di sini. Saya tidak memiliki reputasi yang diperlukan untuk mengirim di tempat lain.
TheNumberOne
3

Pengacak - Ruby

Hanya untuk mengacaukan statistik yang digerakkan oleh bot, pengacak cukup tidak dapat diprediksi. Semua dari mereka kembali sekaligus, secara acak dalam upaya untuk menelantarkan orang lain.

(Tidak dipengaruhi oleh pemain lain.)

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
sumber
2

Mengembara Bodoh, Python 2

Ini adalah bot Python sederhana yang mengirimkan para pelayan sampai waktu "goback" yang telah ditentukan tercapai, kemudian mereka mencoba memasuki perkemahan dan tinggal sampai hari berikutnya.

Ini juga merupakan kerangka dasar untuk bot yang lebih kompleks yang mungkin ingin digunakan orang lain. Namun, mesin ini tidak diuji dengan mesin juri, jadi beri tahu saya jika saya membuat kesalahan.

Program

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)

Perintah

python WanderingFools.py

Sunting: Mengubah tindakan memutuskan kode setelah klarifikasi aturan.

Ksatria Logika
sumber
2

Berkembang

Saya menggunakan Pemrograman Genetik (melalui JGAP) untuk membuat bot ini. Itu muncul dengan jawaban sederhana yang mengalahkan semua yang lain (nyaris).

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

Kompilasi dengan: javac players/Evolved/Evolved.java

Jalankan dengan: java players.Evolved.Evolved

Sunting: Grrr ... Bob mengacaukan saya !!!

Sunting: Yay !!! Bob, terbunuh oleh wabah jahat !!!

TheNumberOne
sumber
1

SlowReturners - Ruby

Mengirim satu pelayan kembali setiap 5 putaran.

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
sumber
1

Wabah

Wabah adalah penyakit. Itu tidak rasional. Bisa ditebak. Penyakit tidak bisa mengumpulkan harta, juga tidak peduli harta. Wabah membuat pemain lain sakit. Orang bijak tinggal di rumah dan melupakan harta. Orang-orang bodoh selalu bodoh dan tidak akan pernah mendapatkan banyak harta. Evolved (untungnya) kebal terhadap Wabah. Ia juga bijaksana. Dia pergi dan mengumpulkan harta, dan tidak mati.

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

Kompilasi dengan: javac players/Plague/Plague.java

Jalankan dengan: java players.Plague.Plague

Bob dan Statistik sekarang tahan terhadap wabah.

TheNumberOne
sumber
hmm ... ketika saya menjalankan bot ini, ia selalu mati pada hari pertama ...
Saya menggunakan algoritma genetika untuk membuatnya. Seharusnya mati di hari kedua. Ini mengacaukan bot yang didorong statistik sehingga kinerjanya sangat buruk dibandingkan dengan Evolved.
TheNumberOne