Hunger Gaming - Ăn hoặc Chết
Nếu bạn không ăn, bạn sẽ chết. Nếu bạn ăn, bạn sống (cho đến khi bạn chết). Bạn sẽ chết, vì vậy hãy cố gắng để chết cuối cùng.
Tổng quan
Có một hòn đảo với một đàn thú săn mồi. Bạn điều khiển một gói năm động vật ăn thịt. Đối tượng của bạn là để giữ cho gói của bạn còn sống. Làm điều này bằng cách ăn con mồi. Con mồi có xu hướng chạy khỏi những kẻ săn mồi, và cố gắng ở trong một đàn khác. Tất nhiên, gói của bạn sẽ nằm trên cùng một lĩnh vực như mọi gói khác , vì vậy cuộc thi sẽ cố gắng ăn chúng trước khi bạn có thể. Đừng để điều này làm bạn nản lòng, nếu không bạn sẽ chết đói.
Cách chơi
Tạo và gửi một chương trình dòng lệnh để chỉ đạo gói của bạn. Nó sẽ nhận thông tin trạng thái từ chương trình điều khiển trên STDIN và các lệnh đầu ra trên STDOUT. Các định dạng được phác thảo chi tiết dưới đây. Mỗi chương trình sẽ chỉ được thực hiện một lần và phải duy trì hoạt động cho đến khi không còn thành viên gói nào còn sống. Bạn sẽ cần phải đọc đầu vào khi nó đến, và trả lời nhanh chóng. Có thời gian chờ nghiêm ngặt là 200ms cho mỗi phản hồi. Nếu sau đó bạn chưa phản hồi, gói của bạn sẽ không nhận được hướng dẫn mới cho lượt hiện tại.
Nếu chương trình của bạn không thể được chạy bởi bộ điều khiển, nó sẽ không được coi là hợp lệ. Vui lòng bao gồm chuỗi dòng lệnh tôi sẽ cần sử dụng để chạy trình của bạn. Nếu có bất kỳ hướng dẫn đặc biệt nào (để thiết lập trình biên dịch, v.v.), vui lòng bao gồm chúng. Nếu tôi không thể làm cho nó hoạt động, tôi sẽ yêu cầu bạn giúp đỡ trong các ý kiến. Nếu bạn không trả lời, tôi sẽ không thể chấp nhận trình của bạn.
Giải đấu sẽ được tổ chức trên hệ thống Linux 64 bit. Hãy ghi nhớ điều này khi đưa ra bất kỳ hướng cần thiết nào.
Chi tiết
Vị trí và hướng của mỗi sinh vật ở dạng một cặp số dấu phẩy động chính xác kép (ví dụ
double
) tương ứng với chúngx
vày
tọa độ của chúng .Mỗi sinh vật là một điểm. Điều này có nghĩa là chúng có thể chồng lên nhau và chiếm cùng một không gian. Bạn sẽ không bị va chạm sang một bên, và không có khái niệm va chạm với các sinh vật khác.
Hòn đảo là một hình vuông, 500 đơn vị sang một bên. Nếu bạn cố gắng mạo hiểm vượt ra ngoài giới hạn đó, bạn sẽ bị kẹp vào cạnh. Nguồn gốc
{0,0}
nằm ở phía trên bên trái, vớix
tăng dần về bên phải vày
tăng xuống. Một lần nữa, bản đồ không bao bọc .Trò chơi bắt đầu với động vật săn mồi 1500 + (packCount * 50) . Họ sẽ được tập trung tại trung tâm của hòn đảo, nhưng nhanh chóng quyết định bắt đầu di chuyển.
Các gói sẽ được sắp xếp trong một vòng tròn cách đều nhau xung quanh chu vi. Thứ tự gói được xáo trộn, vì vậy đừng tính bắt đầu ở một vị trí cụ thể.
Động vật săn mồi có thể nhìn thấy tất cả các động vật khác trong bán kính 30 đơn vị. Họ có thể di chuyển tối đa 6.0 đơn vị mỗi lượt.
Động vật ăn thịt có thể nhìn thấy tất cả các động vật khác trong bán kính 50 đơn vị Chúng có thể di chuyển tối đa 6,1 đơn vị mỗi lượt. Điều này có nghĩa là chúng có thể nhìn thấy con mồi trước khi được nhìn thấy và (hầu như) vượt xa chúng.
Động vật ăn thịt sống và chết theo mức độ đói của chúng . Nó bắt đầu từ 1000 , và giảm từng lượt một. Nếu, sau khi di chuyển, một kẻ săn mồi ở trong 1 đơn vị con mồi, nó sẽ tự động ăn nó. Việc này sẽ loại bỏ con mồi và khiến cơn đói của kẻ săn mồi thành 1000. Mỗi kẻ săn mồi chỉ có thể ăn một con mồi mỗi lượt. Nếu có nhiều hơn một trong phạm vi, nó sẽ ăn bất cứ thứ gì mà vòng lặp đạt được trước tiên (không nhất thiết là gần nhất). Một động vật ăn thịt chết nếu cơn đói của nó bằng không.
Gói bắt đầu với năm thành viên mỗi. Cứ sau 5000 lượt, tất cả các gói vẫn còn trong trò chơi sẽ sinh ra một thành viên mới. Nó sẽ được đặt trong phạm vi có thể nhìn thấy của một thành viên gói. Hãy chắc chắn rằng các mục của bạn có thể xử lý nhiều hơn năm thành viên.
Cứ sau 1000 lượt, con mồi sẽ sinh sản nhiều hơn. Số lượng con mồi mới sẽ là số lượng động vật ăn thịt sống trừ đi một con.
Động vật ăn thịt không thể tấn công các động vật ăn thịt khác. Chúng ăn con mồi khi chúng bắt nó. Đó là nó.
Thứ tự trong một lượt là:
- Tất cả con mồi đưa ra quyết định
- Tất cả các động vật ăn thịt đưa ra quyết định
- Tất cả con mồi di chuyển
- Tất cả động vật ăn thịt di chuyển / ăn
Thứ tự mỗi gói đưa ra quyết định / di chuyển của chúng sẽ được chọn ngẫu nhiên trên mỗi lượt.
Giao thức (chung)
Tất cả các thông tin liên lạc được thực hiện ở định dạng chuỗi US-ASCII
. Các số được chuyển đổi thành chuỗi bằng Java Double.toString()
hoặc Integer.toString()
. Đầu ra của bạn phải được định dạng để Java có thể đọc được Double.valueOf(String)
(bạn sẽ không xuất ra số nguyên). Để biết chi tiết về các định dạng có thể phân tích cú pháp, xem tài liệu choDouble
. Tất cả các trường trên một dòng được phân tách bằng \t
ký tự chuẩn và dòng mới là \n
. Toàn bộ chuỗi sẽ được kết thúc sẽ là một byte null \0
.
Trong các ví dụ dưới đây, tôi đang sử dụng <>
để đánh dấu các trường cho mục đích dễ đọc. Đây không phải là hiện diện trong chuỗi thực tế.
Giao thức (Đầu vào)
Chuỗi đầu vào khác nhau về chiều dài, tùy thuộc vào số lượng sinh vật được hiển thị cho gói của bạn. Nó có thể vượt quá 100k ký tự, vì vậy hãy chuẩn bị cho điều đó. Các thiết lập cơ bản là:
Dòng 0: Thông tin cơ bản về trò chơi.
turn
là số lượt hiện tại và tổng số là tổng số con mồi và động vật ăn thịt còn lại trên sân. Đây làinteger
ở dạng chuỗi.<turn>\t<preyCount>\t<predatorCount>\n
Dòng 1: Id và mức độ đói duy nhất của thành viên gói của bạn. Chúng không được đưa ra theo cùng một thứ tự cho mỗi đầu vào. Sử dụng các id duy nhất để theo dõi các thành viên riêng lẻ, không theo thứ tự xuất hiện trong đầu vào. Một lần nữa, đây là
integer
như chuỗi. Đối với một gói hai, điều này sẽ là:<id[0]>\t<hunger[0]>\t<id[1]>\t<hunger[1]>\n
Dòng 2: Vị trí thành viên gói của bạn, theo cùng thứ tự như được đưa ra trên dòng 1 . Đây là
double
dưới dạng chuỗi:<x[0]>\t<y[0]>\t<x[1]>\t<y[1]>\n
Các dòng sau đây là khả năng hiển thị của mỗi thành viên gói, theo cùng thứ tự như được đưa ra trên dòng 1 . Chúng sẽ được đưa ra dưới dạng hai dòng trên mỗi thành viên.
Đầu tiên cho mỗi bao gồm các vị trí cho con mồi anh ta có thể nhìn thấy. Thứ hai là vị trí cho những kẻ săn mồi anh ta có thể nhìn thấy. Những địa điểm này không phải là duy nhất nói chung. Chẳng hạn, nếu hai thành viên gói có thể nhìn thấy cùng một con vật, nó sẽ nằm trong chuỗi của cả hai thành viên. Ngoài ra, các thành viên gói của riêng bạn sẽ được bao gồm. Nếu bạn muốn loại trừ chúng, bạn có thể muốn so sánh các vị trí với các thành viên của riêng bạn. Tất cả các vị trí ở double
dạng chuỗi.
Đối với mỗi thành viên sống:
<prey[0].x>\t<prey[0].y>\t<prey[1].x>\t<prey[1].y>\n
<predator[0].x>\t<predator[0].y>\t<predator[1].x>\t<predator[1].y>\n
Cuối cùng, ký tự cuối cùng sẽ là \0
, ở đầu dòng tiếp theo.
Ngoại lệ: Nếu bạn nhận được đầu vào dead\0
, gói của bạn đã chết. Kết thúc chương trình của bạn một cách duyên dáng, xin vui lòng. Bộ điều khiển sẽ tắt tất cả các quy trình sống khi đóng, nhưng tôi không muốn có các quy trình zombie ở khắp mọi nơi. Như một phép lịch sự, bạn có thể bao gồm thời gian chờ đầu vào. Chẳng hạn, lớp ví dụ của tôi kết thúc nếu nó không nhận được đầu vào trong 15 giây.
Giao thức (đầu ra)
Đầu ra rất đơn giản. Bạn sẽ đưa ra một cặp double
giá trị cho mỗi thành viên gói sống. Chúng đại diện cho phong trào bạn muốn họ thực hiện lần lượt này. Ví dụ: nếu sinh vật của bạn hiện đang ở {100.0, 100.0}
và bạn đưa cho chúng lệnh {-1.0, 1.0}
, chúng sẽ chuyển đến {99.0, 101.0}
. Tất cả các số sẽ nằm trên một dòng, cách nhau bởi tab.
Ví dụ: nếu bạn có 3 thành viên gói còn sống, đây sẽ là phản hồi hợp lệ:
1.0\t-1.0\t2.0\t-2.0\t3.0\t-3.0\0
Điều này sẽ di chuyển những sinh vật của bạn bằng {1.0,-1.0}
, {2.0,-2.0}
và {3.0,-3.0}
. Thứ tự giống như nhận được trong đầu vào. Đừng quên kết thúc \0
!
Nếu bạn cho đầu vào không hợp lệ, kết quả xấu sẽ theo sau. Nếu bất kỳ số nào không thể được phân tích cú pháp thành a double
, nó sẽ trở thành số không. Nếu toàn bộ chuỗi không thể được phân tích cú pháp, sẽ không có hướng dẫn mới nào được đưa ra và toàn bộ gói của bạn sẽ sử dụng các hướng dẫn từ lượt trước.
Tất cả các hướng sẽ được kẹp vào khoảng cách tối đa 6,1 đơn vị. Bạn có thể di chuyển chậm hơn thế này nếu bạn muốn. Ví dụ, {1, 0}
sẽ di chuyển cho bạn một đơn vị. {6,8}
(khoảng cách 10) sẽ chỉ di chuyển bạn 6,1 đơn vị và sẽ giảm xuống xung quanh {3.66, 4.88}
. Hướng không đổi.
Quan trọng: Chương trình điều khiển đọc cả STDOUT và STDERR của bạn . Nếu bạn ném một ngoại lệ và in ra STDERR, rất có thể tin nhắn đó sẽ ở dạng phản hồi hợp lệ. Cố gắng tránh làm điều này.
Chương trình điều khiển / Kiểm tra
Nguồn cho bộ điều khiển có thể được tìm thấy ở đây tại bitbucket.org . Bạn sẽ cần phải biên dịch nó trước khi chạy. Lớp chính là Game
và tất cả các lớp nằm trong gói mặc định. Để chạy, bao gồm lệnh của mỗi gói như là một đối số riêng biệt. Chẳng hạn, nếu bạn muốn chạy Java ChaserPack và Python LazyPack.py, bạn có thể sử dụng:
java Game "java ChaserPack" "python LazyPack.py"
Trên bản đồ, con mồi xuất hiện màu xanh lá cây và động vật ăn thịt màu đỏ. Tuy nhiên, gói nào là gói đầu tiên được đưa ra làm đối số sẽ có màu xanh lam thay thế. Điều này nhằm phân biệt chúng dễ dàng hơn cho mục đích thử nghiệm. Động vật ăn thịt cũng sẽ nhấp nháy màu trắng trong năm khung khi chúng ăn.
Trò chơi sẽ tiến hành cho đến khi kẻ săn mồi cuối cùng chết đói, viết lên bàn điều khiển khi các sự kiện chết đói hoặc tuyệt chủng xảy ra. Khi trò chơi hoàn tất, điểm sẽ được trao cho mỗi gói. Nếu bạn không muốn xem các sự kiện chết đói / tuyệt chủng, bạn có thể sử dụng -silent
đối số. Sau đó, nó sẽ chỉ xuất điểm số cuối cùng. Bạn phải vượt qua điều này như là đối số đầu tiên :
java Game -silent "java ChaserCat" "./someOtherPack"
Bao gồm là một gói Java bộ xương có tên GenericPack
. Nó bao gồm các hoạt động đầu vào / đầu ra cơ bản cần thiết. Nó ở đó để đưa ra một ví dụ rõ ràng về cách phân tích và trả lời. Nếu bạn muốn thêm một mẫu bằng ngôn ngữ khác, hãy cho tôi biết.
Cũng bao gồm là một động vật ăn thịt dựa trên mẫu , ChaserPack
. Nó sẽ không được bao gồm trong giải đấu, và chỉ được bao gồm cho mục đích thử nghiệm. Nó thực hiện khá tệ, do một lỗ hổng nhắm mục tiêu có chủ ý. Nếu bạn không thể đánh bại nó, hãy tiếp tục cố gắng.
Dưới đây là một ví dụ chạy chương trình điều khiển (bấm vào video). Chất lượng video không tốt (xin lỗi), nhưng bạn có thể cảm nhận được cách con mồi di chuyển. ( thận trọng: âm thanh )
Chấm điểm
Người chiến thắng sẽ được xác định theo giải đấu, giành được điểm trong mỗi vòng.
Mỗi vòng tiến hành cho đến khi tất cả động vật ăn thịt đã chết. Mỗi gói sẽ được tính điểm dựa trên thời điểm thành viên cuối cùng của nó chết vì đói. Sau đó, họ sẽ được chỉ định điểm dựa trên thứ tự. Điểm sẽ tích lũy trong mười vòng, và người chiến thắng là gói có tổng số điểm cao nhất.
Vị trí đầu tiên cho mỗi vòng sẽ nhận được 100 điểm. Đối với mỗi nơi sau đó, phần thưởng sẽ giảm 20% (làm tròn xuống). Điều này sẽ tiếp tục cho đến khi các điểm đạt đến không (sau vị trí thứ 17). Địa điểm 18+ sẽ không nhận được điểm nào cho vòng đấu. Gói người buộc sẽ nhận được điểm bằng nhau. Ví dụ:
1st : 100
2nd : 80
3rd : 64 (T)
3rd : 64 (T)
4th : 51
...
17th: 1
18th: 0
19th: 0
Điểm tối đa có thể trong suốt giải đấu là 1000, từ vị trí đầu tiên tất cả mười lần.
Nếu nhiều chương trình kết thúc giải đấu gắn liền với vị trí đầu tiên, một giải đấu vòng mười khác sẽ được tổ chức chỉ với các mục đầu tiên được gửi. Điều này sẽ tiếp tục cho đến khi một người chiến thắng xuất hiện.
Tôi sẽ cố gắng để chạy một giải đấu khoảng hàng tuần, hoặc khi đệ trình mới đến.
Quy tắc bổ sung (chơi công bằng!)
Bạn không thể đọc hoặc ghi vào bất kỳ tài nguyên bên ngoài. Vì bạn sẽ không gọi chương trình nhân đôi chương trình của mình, bất kỳ thông tin trạng thái nào cũng có thể được lưu trữ nội bộ.
Không can thiệp vào các quá trình / đệ trình khác. Điều này không có nghĩa là đừng cố gắng đánh cắp con mồi của chúng, vượt qua chúng, v.v. Điều đó có nghĩa là đừng can thiệp vào quá trình chạy. Đây là theo ý của tôi.
Thí sinh được giới hạn tối đa ba mục. Nếu bạn gửi thêm, tôi sẽ chỉ ghi được ba lần gửi đầu tiên. Nếu bạn muốn thu hồi nó, hãy xóa nó.
Các mục có thể không tồn tại chỉ để chống đỡ các mục khác. Mỗi người nên chơi để giành chiến thắng trên giá trị riêng của mình.
Chương trình của bạn có thể sinh ra tối đa một quá trình con tại một thời điểm ( tổng số con cháu, không trực tiếp). Dù bằng cách nào, hãy đảm bảo bạn không vượt quá thời gian chờ. Bạn không được gọi
Game
chính nó theo bất kỳ cách nào.
Kết quả - 29 tháng 4 năm 2014
Dưới đây là kết quả của giải đấu mười vòng mới nhất:
Clairvoyant : 1000
EcoCamels : 752
Netcats : 688
RubySpiders : 436
RubyVultures : 431
CivilizedBeasts : 382
LazyPack : 257
Các gói được gửi trước 09:00 EDT 2014/04/29 được bao gồm trong lần chạy này.
Bạn cũng có thể xem chi tiết cho mỗi vòng . Vì một số lý do, tôi quyết định đánh số vòng ngược, vì vậy nó bắt đầu bằng "vòng 10".
Cập nhật
23/03/2014: FGreg đã báo cáo một lỗi liên quan đến thời gian chờ (cảm ơn!). Một bản sửa lỗi đã được thực hiện, vì vậy những người kiểm tra sẽ muốn cập nhật mã chương trình kiểm soát của họ.