Săn tìm kho báu trên một hòn đảo hoang vắng


13

Giới thiệu

Bạn bị mắc kẹt trên một hòn đảo hoang vắng với một số người hầu và đang săn lùng kho báu. Càng tìm kiếm lâu, người ta càng tìm thấy nhiều kho báu. Càng ít người tìm kiếm, mỗi người càng tìm thấy nhiều hơn.

Do nguồn cung hạn chế, nhà lãnh đạo đã quyết định rằng một vài người, đến một phần tư của nhóm, sẽ bị bỏ lại mỗi đêm. Anh ta quyết định không nói cho ai biết chính xác có bao nhiêu người sẽ chết vào bất kỳ ngày nào trước thời hạn.

Bạn đang kiểm soát một nhóm nhỏ gồm 5 người, những người sẽ mạo hiểm ra khỏi trại để tìm kho báu cho bạn.

Mục tiêu

Mục tiêu của cuộc thi này là tích lũy càng nhiều kho báu càng tốt. Mỗi lượt mà người hầu của bạn không cố gắng quay trở lại trại, họ sẽ tìm thấy một số lượng kho báu nhất định. Người hầu của bạn có thể trở lại trại vào những thời điểm khác nhau.

Mỗi lượt mà một công nhân ở lại để tìm kiếm kho báu, công nhân tìm thấy 1+Rcác mảnh kho báu, trong đó Rsố công nhân (trong số tất cả các bot) đã trở lại trại. Các bot chết không tính đến yếu tố này.

Vào đầu mỗi ngày, một số ngẫu nhiên ( n) từ 2đến max(3, floor(num_live_players/4))sẽ được chọn. (Đối với 10 cầu thủ vào ngày 1, đây là 2đến max(3,50/4)=12. Đối với 20 người chơi vào ngày 1, điều này sẽ 2đếnmax(3,100/4)=25 .) Con số này đại diện cho số lượng người chơi người sẽ còn lại để chết cho ngày hôm đó, và sẽ không được trao cho chương trình của bạn .

Nếu một người hầu là một trong những người cuối cùng n người trở về, anh ta / cô ta sẽ chết và không thể chuyển kho báu mà anh ta / cô ta tìm thấy để sở hữu. Hơn nữa, người hầu sẽ không thể tham gia săn tìm kho báu trong phần còn lại của cuộc phiêu lưu.

Điểm cuối cùng của bạn là số lượng kho báu trung bình bạn có được trong mỗi chuyến phiêu lưu (chạy bộ điều khiển).

Nếu nhiều người cố gắng quay trở lại trại trên cùng một lượt so với các vị trí mở, các số ngẫu nhiên sẽ xác định ai vào và ai chết.

Một ngày trên hòn đảo này từ bình minh đến hoàng hôn kéo dài 30 lượt. Vì có nhiều động vật nguy hiểm vào ban đêm, việc không trở về vào lúc hoàng hôn có nghĩa là bạn sẽ không được phép vào trại.

Đầu ra đầu vào

Chương trình của bạn sẽ chạy cho toàn bộ mô phỏng.

Khi bắt đầu mô phỏng, INDEX Isẽ được nhập vào, Ichỉ mục bot của bạn ở đâu (chỉ số này được tính từ 1 trở lên).

Vào đầu mỗi ngày, START_DAY D/Nsẽ được nhập vào chương trình của bạn, Dsố ngày (bắt đầu từ đâu 1) và Nbằng với max(3, floor(num_live_players/4)), đó là số người tối đa có thể chết vào ngày cụ thể đó.

Khi bắt đầu mỗi lượt, START_TURN Tsẽ được nhập vào chương trình của bạn, Tsố lượt (bắt đầu từ đâu 1).

Khi chương trình của bạn nhận được điều này, nó sẽ phản hồi với một danh sách các bước di chuyển của người hầu, mỗi lần được phân tách bằng dấu phẩy.

Di chuyển hợp lệ là:

  • R: Cố gắng trở về trại.
  • S: Ở lại tìm kiếm kho báu.
  • N: Người hầu đã chết hoặc đang ở trong trại.

Bước vào một nước đi không hợp lệ sẽ được diễn giải như Sthể bot còn sống và không ở trong trại, và Nnếu không.

Vào cuối mỗi lượt, một chuỗi sẽ được chuyển đến chương trình của bạn:

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

nơi di chuyển của mỗi người hầu của bot được phân tách bằng dấu phẩy.

Những động thái này sẽ là một trong những điều sau đây:

  • R: Thành công trở lại trại lần lượt.
  • r: Không thể trở lại trại lần lượt.
  • S: Vẫn đang tìm kiếm kho báu.
  • D: Chết trên một lượt trước đó.
  • N: Đã trở lại trại.

Bots và người hầu vẫn theo thứ tự trong toàn bộ mô phỏng.

Ví dụ:

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

Ở đây, bạn là bot thứ hai ( r,r,r,r,r), người đã cố gắng trả lại cả bốn người hầu vẫn còn sống (và thất bại một cách không may mắn trên cả bốn người). Những người hầu của Bot 1 đều quay trở lại trại. Bot 3 có ba người hầu đã chết, một người nữa trở lại trại và một người hầu thứ năm đã trở về thành công. Bot 4 có một người hầu ở lại (và sẽ chết, vì đây là lượt cuối cùng của một ngày), một người hầu trong trại và ba người hầu đã chết.

Sau mỗi chuỗi này, trừ khi một chuỗi báo hiệu kết thúc ngày cũng đã được xuất ra (xem bên dưới), chương trình của bạn là để xuất các bước tiếp theo của người hầu, được phân tách bằng dấu phẩy. Tất cả người hầu phải được tính (với Nnếu đã ở trong trại và Dnếu đã chết). Di chuyển không hợp lệ sẽ được xử lý như Sthể người hầu chưa ở trong trại / đã chết. Thí dụ:

N,N,S,S,R

nghĩa là:

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.

Vào cuối một ngày, chuỗi sau sẽ được chuyển sau ENDchuỗi của lượt cuối cùng , thông báo cho mọi người biết ai còn sống:

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

trong đó trạng thái là một danh sách được phân tách bằng dấu phẩy là A(còn sống) hoặc D(đã chết). Ngày tiếp theo bắt đầu ngay sau đó.

Mô phỏng kết thúc khi có ít hơn 6 người hầu sống. Chương trình của bạn sẽ nhận được đầu vào sau vào cuối mô phỏng:

EXIT

Quy tắc / Chi tiết

  • Chỉ đến lượt mà hành động của bạn là Sbạn sẽ tìm thấy kho báu.
  • Số lượng mô phỏng chạy: 1000 lần
  • Chương trình của bạn không nên mất hơn 1 giây để xác định di chuyển.
  • Chương trình của bạn không nên thoát sớm; nó sẽ được bắt đầu chính xác một lần.
  • Đảm bảo rằng bộ đệm đầu ra (nếu có) được tuôn ra sau mỗi đầu ra.
  • Các tập tin có thể được ghi vào thư mục bot của bạn ( ./players/BotName/). Tên bot của bạn là bất cứ tên nào bạn đặt tên cho bot của mình, với tất cả các ký tự không phải là chữ và số được xóa và viết bằng CamelCase. Các mục nhập có thể lưu dữ liệu giữa các lần chạy của bộ điều khiển, vì các lần chạy được thực hiện tuần tự.
  • Chương trình của bạn phải thoát sau khi nhận được EXIT.
  • Các chương trình không biên dịch hoặc ném lỗi hoặc xuất văn bản không hợp lệ (không ở định dạng 5 ký tự được phân tách bằng dấu phẩy) có thể được loại trừ khỏi cuộc thi. Một dòng mới phải theo từng đầu ra.
  • Bộ điều khiển có thể được tìm thấy trên GitHub .

Vui lòng bao gồm tên bot, ngôn ngữ + phiên bản, mã và lệnh để biên dịch (nếu có) và chạy bot của bạn.

Thí dụ

Văn bản được xuất ra bởi chương trình có tiền tố ở đây với a >. Chương trình của bạn không nên xuất ký tự này.

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ểm cho ví dụ trên là:

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

Do đó, người chiến thắng là người chơi, bot 2. Lưu ý rằng người chiến thắng không phải sống sót đến cuối cùng tuyệt đối. (Cũng lưu ý rằng người chơi có thể duy trì đến 30 tuổi vào ngày 1, vì trại sẽ không đầy cho đến khi người chơi gửi thêm một bot nữa).

Điểm số

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

Nhật ký có sẵn trên GitHub . Kết quả cho mỗi thử nghiệm có sẵn trên bảng tính google này .


Nếu một người hầu không trở về, anh ta có được tính vào số người chết trong ngày này không?
EagleV_Attnam

@EagleV_Attnam Ngày kết thúc khi có đủ người hầu đã quay trở lại, hoặc 30 lượt đã trôi qua, trong đó tất cả những người không quay trở lại sẽ chết, bất kể số người chết được xác định trước đó.
es1024

Phải, đó là ngớ ngẩn, xin lỗi.
EagleV_Attnam

Nếu một người hầu trở về trại, anh ta có thể giao kho báu được tìm thấy cho đến nay và sau đó ra ngoài để tìm kiếm lại vào cùng ngày đó không?
Logic Knight

1
@MikeSweeney Không. Một khi người hầu trở về, anh ta ở lại.
es1024

Câu trả lời:


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

Để biên dịch:

g++ -o Bob.exe Bob.cpp

Chạy:

./players/Bob/Bob.exe

6

Thống kê, Python 3

Các nhà thống kê luôn làm việc cùng nhau. Ở lượt đầu tiên, họ trở lại trại khi hai phần ba đối thủ của họ đã làm như vậy. Ở các lượt tiếp theo, họ dựa vào dữ liệu họ đã thu thập từ các lượt trước để dự đoán thói quen của những người hầu khác và cố gắng quay trở lại trại vào giây phút an toàn cuối cùng.

Chương trình

# 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

Như bạn có thể thấy, tôi đã xấu hổ đánh cắp cấu trúc chương trình từ @Mike Sweeney.

Chỉ huy

python3 statisticians.py

EDIT: Đã sửa lỗi kiểm tra khi trở về nhà. Họ nên thực hiện phần nào tốt hơn bây giờ.

EDIT 2: Các nhà thống kê bây giờ thông minh hơn trước: họ theo dõi những người hầu đã trở lại trại trong ngày hiện tại và điều chỉnh dự đoán của họ cho phù hợp. Ngoài ra, họ chấp nhận nhiều rủi ro hơn, quay trở lại trại khi 3/4 số người hầu chết tối đa vẫn còn. Điều này đẩy họ trở lại đỉnh cao (chỉ vừa đủ; Bob đã trở nên rất nguy hiểm).


5

Người say rượu, Perl 5

Một chút rượu quá nhiều và họ sẽ không bao giờ tìm được đường trở lại trại.

Mục này chủ yếu là một ví dụ, nhưng sẽ tham gia.

Chương trình

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

Chỉ huy

perl ./players/Drunkards/Drunkards.pl

Nên mã của bạn $status[$i] eq 'A' ? 'S' : 'D';được $status[$i] eq 'A' ? 'S' : 'N';đáp ứng spec?
Logic Knight

@MikeSweeney Bắt tốt. Tôi đã quên sửa nó khi tôi thay đổi thông số kỹ thuật trong khi thử thách này vẫn nằm trong hộp cát.
es1024

4

Chim buổi sáng

Con chim đầu bắt sâu!!!

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

}

Chỉnh sửa: Làm cho nó để bất cứ ai cũng có thể dễ dàng phân lớp nó. Chỉ cần xác định lại doMove(int playerNumber)cho bot của riêng bạn. Tôi đã thêm một số lĩnh vực và phương pháp hữu ích. Tôi đã thử nghiệm rộng rãi nó. Nó không lưu các trạng thái từ các mô phỏng trước đó. Xin vui lòng cho tôi biết nếu có bất kỳ vấn đề.

Biên dịch với: javac ./players/MorningBirds/MorningBirds.java

Chạy với: java players.MorningBirds.MorningBirds


Có ổn không nếu tôi thực hiện các phương thức và biến được bảo vệ và sau đó thực hiện một lớp con của điều này cho thử thách?
TheNumberOne

Vui lòng sử dụng nhiều tệp nguồn nếu cần hoặc sử dụng lại mã từ các mục khác, miễn là các mục không hoạt động cùng nhau.
es1024

@ es1024 Trong thử nghiệm tôi nhận thấy rằng một con bot chết nếu nó không làm gì cả ngày kể từ lượt 1. Điều đó có ý định không?
TheNumberOne

Một bot không bao giờ trở lại ( R) vào bất kỳ ngày nào sẽ luôn chết vào ngày đó.
es1024

Bộ điều khiển trở nên không phản hồi nếu tôi thêm người chơi SlowReturners và Randomators. Lưu ý: Xin lỗi tôi đang đăng bình luận ở đây. Tôi không có danh tiếng cần thiết để đăng ở nơi khác.
TheNumberOne

3

Ngẫu nhiên - Ruby

Chỉ cần làm rối các bot điều khiển thống kê, các ngẫu nhiên là khá khó đoán. Tất cả đều quay trở lại cùng một lúc, trong một lần rẽ ngẫu nhiên trong nỗ lực mắc kẹt người khác.

(Không bị ảnh hưởng bởi những người chơi khác.)

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

Lừa lang thang, Python 2

Đây là một bot Python đơn giản gửi các người hầu cho đến khi đạt được thời gian "goback" cài sẵn, sau đó họ cố gắng vào trại và ở lại cho đến ngày hôm sau.

Nó cũng là một khung cơ bản cho các bot phức tạp hơn mà những người khác có thể muốn sử dụng. Tuy nhiên, nó chưa được kiểm tra với công cụ đánh giá, vì vậy hãy cho tôi biết nếu tôi đã gây ra lỗi.

Chương trình

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)

Chỉ huy

python WanderingFools.py

Chỉnh sửa: Thay đổi mã quyết định hành động sau khi làm rõ quy tắc.


2

Phát triển

Tôi đã sử dụng lập trình di truyền (thông qua JGAP) để tạo bot này. Nó đã đưa ra một câu trả lời đơn giản đánh bại tất cả những người khác (hầu như không).

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

Biên dịch với: javac players/Evolved/Evolved.java

Chạy với: java players.Evolved.Evolved

Chỉnh sửa: Grrr ... Bob làm phiền tôi !!!

Chỉnh sửa: Yay !!! Bob, bị giết bởi một bệnh dịch khó chịu !!!


1

SlowReturners - Ruby

Gửi một người hầu trở lại sau mỗi 5 lượt.

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

Tai họa

Bệnh dịch hạch là một căn bệnh. Nó không hợp lý. Đó là dự đoán. Bệnh không thể thu thập kho báu, họ cũng không quan tâm đến kho báu. Bệnh dịch hạch làm cho những người chơi khác bị bệnh. Những người khôn ngoan ở nhà và quên đi kho báu. Những người ngu ngốc luôn luôn ngu ngốc và sẽ không bao giờ nhận được nhiều kho báu. Tiến hóa là (may mắn thay) miễn dịch với bệnh dịch hạch. Anh cũng khôn ngoan. Anh ta đi và thu thập kho báu, và không chết.

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

Biên dịch với: javac players/Plague/Plague.java

Chạy với: java players.Plague.Plague

Bob và Statisticians hiện đang chống lại bệnh dịch hạch.


hmm ... khi tôi chạy bot này, nó luôn chết vào ngày đầu tiên ...

Tôi đã sử dụng một thuật toán di truyền để thực hiện điều này. Nó sẽ chết vào ngày thứ hai. Nó làm rối các bot điều khiển thống kê để chúng hoạt động khá tệ so với Evolve.
TheNumberOne
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.