60
17
Hunger Gaming - Eat or Die
If you don't eat, you die. If you eat, you live (until you die). You will die, so try to die last.
Overview
There is an island populated with a herd of prey animals. You control a pack of five predators. Your object is to keep your pack alive. Do this by eating prey. The prey tend to run from predators, and try to stay in a flock otherwise. Of course, your pack will be on the same field as every other pack, so the competition will try to eat them before you can. Do not let this discourage you, or you will starve.
How to play
Create and submit a command line program to direct your pack. It will receive state information from the control program on STDIN, and output commands on STDOUT. The format is outlined in detail below. Each program will only be executed once and must stay running until it has no more pack members alive. You will need to read input as it comes in, and respond quickly. There is a strict timeout of 200ms for each response. If you have not responded by then, your pack will not receive new instructions for the current turn.
If your program cannot be run by the controller, it will not be considered valid. Please include the command line string I will need to use to run your submission. If there are any special instructions(to setup compilers, etc), please include them. If I cannot get it working, I will ask you for assistance in comments. If you do not respond, I will not be able to accept your submission.
Tournament will be held on a 64bit Linux system. Keep this in mind when giving any necessary directions.
Details
Each creature's position and direction are in the form of a pair of double-precision floating point numbers (eg
double
) representing theirx
andy
coordinates, respectively.Each creature is a considered a point. This means they can overlap and occupy the same space. You will not be bumped aside, and there is no concept of collision with other creatures.
The island is a square, 500 units to a side. If you try to venture beyond those bounds, you will be clamped onto the edge. The origin
{0,0}
is in the upper-left, withx
increasing to the right andy
increasing downward. Again, the map does not wrap.The game starts with 1500 + (packCount * 50) prey animals. They will be gathered in the center of the island, but quickly decide to start moving.
Packs will be arranged in an evenly spaced circle around the perimeter. The pack order is shuffled, so don't count on starting in a particular location.
Prey animals can see all other animals within a 30 unit radius. They can move at a maximum of 6.0 units per turn.
Predators can see all other animals within a 50 unit radius They can move at a maximum of 6.1 units per turn. This means they can see prey before being seen and (barely) outrun them.
Predators live and die according to their hunger level. It starts at 1000, and decreases by one each turn. If, after movement, a predator is within 1 unit of prey, it will automatically eat it. This removes the prey and sets the predator's hunger to 1000. Each predator may only eat one prey per turn. If there are more than one within range, it will eat whichever one the loop gets to first( not necessarily the closest). A predator dies if its hunger reaches zero.
Packs start with five members each. Every 5000 turns, all packs still in the game will spawn one new member. It will be placed within visible range of a fellow pack member. Make sure your entries can handle more than five members.
Every 1000 turns, more prey will spawn. The number of new prey will be the number of living predators minus one.
Predators cannot attack other predators. They eat prey when they catch it. That's it.
The order within a turn is:
- All prey make decisions
- All predators make decisions
- All prey move
- All predators move/eat
The order each pack makes their decisions/moves in will be randomized on each turn.
Protocol (General)
All communications are done in string format US-ASCII
. Numbers are converted to strings using Java's Double.toString()
or Integer.toString()
. Your output must be formatted so that it can be read by Java's Double.valueOf(String)
(you will not be outputting integers). For details on parseable formats, see the documentation for Double
. All fields on a line are separated by the standard \t
character, and newlines are \n
. The whole string will be terminated will a null byte \0
.
In the examples below, I'm using <>
to mark the fields for readability's sake. These are not present in the actual strings.
Protocol (Input)
The input string varies in length, depending on how many creatures are visible to your pack. It can exceed 100k characters, so be prepared for that. The basic setup is:
Line 0: Basic information about the game.
turn
is the current turn number, and the counts are the total number of prey and predators left on the field. These areinteger
in string form.<turn>\t<preyCount>\t<predatorCount>\n
Line 1: Your pack members' unique ids and hunger levels. These are not given in the same order for every input. Use the unique ids to track individual members, not the order in which they appear in the input. Again, these are
integer
as strings. For a pack of two, this would be:<id[0]>\t<hunger[0]>\t<id[1]>\t<hunger[1]>\n
Line 2: Your pack members' positions, in the same order as given on line 1. These are
double
as string:<x[0]>\t<y[0]>\t<x[1]>\t<y[1]>\n
The following lines are each pack member's visibility, in the same order as given on line 1. These will be given as two lines per member.
The first for each consists of locations for the prey he can see. The second is locations for the predators he can see. These locations are not unique as a whole. For instance, if two pack members can see the same animal, it will be in both member's string. Also, your own pack members will be included. If you want to exclude them, you may want to compare locations with your own members. All locations are in double
as string format.
For each living member:
<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
Finally, the last character will be \0
, at the beginning of the next line.
Exception: If you receive the input dead\0
, your pack is dead. End your program gracefully, please. The controller should shut down all living processes when closed, but I'd rather not have zombie processes all over the place. As a courtesy, you may include an input timeout. For instance, my example class ends if it does not receive input for 15 seconds.
Protocol (Output)
Output is simple. You will give a pair of double
values for each live pack member. These represent the movement you would like them to take on this turn. For example, if your creature is currently at {100.0, 100.0}
and you give them a command of {-1.0, 1.0}
, they will move to {99.0, 101.0}
. All numbers will be on a single line, separated by tab.
For example, if you had 3 pack members alive, this would be a valid response:
1.0\t-1.0\t2.0\t-2.0\t3.0\t-3.0\0
This would move your creatures by {1.0,-1.0}
, {2.0,-2.0}
, and {3.0,-3.0}
. The order is the same as received in the input. Don't forget the ending \0
!
If you give invalid input, bad results will follow. If any single number cannot be parsed to a double
, it will become zero. If the string as a whole can't be parsed, no new instructions will be given, and your entire pack will use the directions from the previous turn.
All directions will be clamped to a maximum distance of 6.1 units. You can move slower than this if you'd like. For instance, {1, 0}
will move you one unit. {6,8}
(distance 10) will only move you 6.1 units, and will reduce to around {3.66, 4.88}
. The direction remains constant.
Important: The control program reads both your STDOUT and STDERR. If you throw an exception and print to STDERR, it's very unlikely that message will be in the form of a valid response. Try to avoid doing this.
Control Program / Testing
The source for the controller can be found here at bitbucket.org. You will need to compile it before running. The main class is Game
, and all classes are in the default package. To run, include each pack's command as a separate argument. For instance, if you want to run a Java ChaserPack and a Python LazyPack.py, you could use:
java Game "java ChaserPack" "python LazyPack.py"
On the map, prey appear in green, and predators in red. However, whichever pack is the first pack given as an argument will be colored blue instead. This is intended to distinguish them more easily for testing purposes. Predators will also flash white for five frames when they eat.
The game will proceed until the last predator starves, writing to the console as starvation or extinction events happen. Once the game is complete, the score will be given for each pack. If you want don't want to see the starvation/extinction events, you can use the -silent
argument. Then it will only output the final score. You must pass this as the first argument:
java Game -silent "java ChaserCat" "./someOtherPack"
Included is a skeleton Java pack named GenericPack
. It includes the basic input/output operations needed. It is there to give a clear example of how to parse and reply. If you'd like to add a template in another language, let me know.
Also included is a predator based on the template, ChaserPack
. It will not be included in the tournament, and is only included for testing purposes. It performs quite badly, due to an intentional targeting flaw. If you can't beat it, keep trying.
Below is an example run of the control program (click for video). The video quality's not great (sorry), but you can get a feel for how the prey move. (caution: audio)
Scoring
Winner will be determined by tournament, gaining points in each round.
Each round proceeds until all predators are dead. Each pack will be scored based on when its last member died of starvation. They will then be assigned points based on the order. Points will accumulate for ten rounds, and the victor is the pack with the highest total points.
First place for each round will receive 100 points. For each place after that, the reward will be reduced by 20%(rounded down). This will continue until the points reach zero(after 17th place). Places 18+ will receive no points for the round. Packs who tie will receive equal points. For example:
1st : 100
2nd : 80
3rd : 64 (T)
3rd : 64 (T)
4th : 51
...
17th: 1
18th: 0
19th: 0
The maximum possible points over the course of the tournament is 1000, from first place all ten times.
If multiple programs end the tournament tied for first place, another ten round tournament will be held with only the first-place entries submitted. This will continue until one victor emerges.
I will try to run a tournament roughly weekly, or as new submissions come in.
Additional Rules (play fair!)
You may not read or write to any external resources. Since you're not going to be invoking your program mutliple times, any state information can be stored internally.
Do not interfere with other processes/submissions. This does not mean don't try to steal their prey, outrun them, etc. It means don't interfere with the running of the process. This is at my discretion.
Contestants are limited to a maximum of three entries. If you submit more, I will only score the first three submitted. If you want to revoke one, delete it.
Entries may not exist solely to prop up other entries. Each should play to win on its own merit.
Your program may spawn a maximum of one child process at a time (total descendants, not direct). Either way, ensure you don't go over the timeout. You may not invoke the
Game
class itself in any way.
Results - 29 April 2014
Here are the results of the latest ten-round tournament:
Clairvoyant : 1000
EcoCamels : 752
Netcats : 688
RubySpiders : 436
RubyVultures : 431
CivilizedBeasts : 382
LazyPack : 257
Packs submitted before 09:00 EDT 2014/04/29 are included in this run.
You can also view the details for each round. For some reason I decided to number the rounds backwards, so it starts with "round 10".
Updates
2014/04/23: FGreg reported a bug related to timeouts (thanks!). A fix has been implemented, so testers will want to update their control program code.
@Geobits, I know this is old, but just to bump this thread so that in case you still have the code available, you can rerun the tournament with the latest code =D – justhalf – 2017-04-18T12:43:29.993
28I'm liking these king of the hill questions! – Cruncher – 2014-04-14T15:26:31.473
@Cruncher there sure are a lot of them lately! – TheDoctor – 2014-04-14T16:24:37.900
Great challenge, especially the examples! Sadly, windows doesn't support \n in stdin/out, so I have to create a VM... – CommonGuy – 2014-04-16T08:37:48.163
2@Manu I wrote the example bots on Windows 7, and tested on both win and linux. What problems are you having with them? – Geobits – 2014-04-16T11:12:52.243
@Geobits I only got the first line, everything after that didn't reach my bot... I will try it again, maybe I was too tired... – CommonGuy – 2014-04-16T12:37:54.510
@Manu I tried the hangman solver with STDIN/STDOUT as well and it didnt work on my Windows 7, but this game works just fine! Let's give it a try! (Man, this game is complicated) – Herjan – 2014-04-17T10:14:32.547
@Herjan Cool! HangmanSolver as well as BattleBots didn't work, I thought this won't work either. But it was something with my java installation... – CommonGuy – 2014-04-17T10:22:08.247
Interesting challenge, good thing my test week is over ;) – ɐɔıʇǝɥʇuʎs – 2014-04-17T13:23:44.627
2These king of the hill questions are quite awesome, and this one is definitely interesting. I've got two different packs in the works now! – mackthehobbit – 2014-04-18T09:37:27.963
Is symbiotic (across packs) behavior legal? Using other packs' behavioral patterns to my advantage is one thing. Writing 3 allowed packs whose purpose is longest survival of only one of them is another. Ah, I see "may not exist solely to prop up other entries". Still, it will be difficult to judge. – user2846289 – 2014-04-18T23:01:24.780
@VadimR Right. As long as that's followed, no problem. It's a bit subjective, but I think it should be pretty easy to tell in general. – Geobits – 2014-04-18T23:04:03.733
The Game program output refers to individual turns as rounds, whereas the question refers to complete runs until all predators are dead as rounds. I'm guessing it's the program that needs changing? It runs fine - just a cosmetic change to remove the ambiguity. – trichoplax – 2014-04-21T07:53:28.560
I don't know if it's too late to make a change, or if you'd even want to, but killing a pack that does not respond to input in time instead of waiting 0.2 seconds every turn makes a significant improvement to running speed when there is a slow responding pack in play. I don't think it would affect any of the current answers, if that makes a difference. – trichoplax – 2014-04-21T11:08:24.357
2@githubphagocyte I don't really want to kill off a pack on the first timeout, simply because I've seen even simple programs time out once every 40k+ turns or similar. I did commit the naming change in the controller. Turns are now known as turns throughout the program, unless I missed one somewhere. – Geobits – 2014-04-21T18:36:28.370
I hope this doesn't close too soon; I want to give it a try once my finals are over! Speaking of which... better get off pcg.so... – krs013 – 2014-04-21T19:08:32.353
1@krs013 It won't be closing any time soon, but the current bounty will expire in three days. If it's after that, you can still compete, just without the extra. – Geobits – 2014-04-21T19:10:57.167
2@Geobits eh, that's fine by me. You know, this looks really similar to a research project one of my physics professors is doing, which I might be helping with over the summer. I'll explain a bit about that later if I can. – krs013 – 2014-04-21T19:53:52.397
To better watch Games, I'd suggest changing colors: adding
frame.setBackground(Color.DARK_GRAY);
toGame.java
(otherwise white frame around black field == too much contrast and strain for the eyes; then make prey gray withcolor = Color.GRAY;
(instead ofGREEN
) inCreature.java
; then add bright colors for packs inPredator.java
(my sequence is green - red - cyan - orange - yellow - magenta - blue. Blue's too dark therefore the last for me). – user2846289 – 2014-04-22T23:22:02.513Could we split our code into modules (for ease of maintenance)? – golfer9338 – 2014-04-23T21:22:25.837
@golfer9338 I'd prefer a single file, but as long as I can drag/drop/run without much hassle, I suppose it's okay. Maybe zip them up for ease of grabbing? Try to limit it, though. I don't want 37 files per submission, for example. – Geobits – 2014-04-23T21:24:33.670
Netcats is way too pro already. In one of my runs it can finish all the preys in turn 32808 =.= – justhalf – 2014-04-24T09:03:34.360
1Finally beat that Netcats! =D – justhalf – 2014-04-24T11:21:35.417
I think that it would be fun to show a set of "Achievements" after the game is over, such as First blood for first kill, Almost dead for eating at hunger level below 10, Honorable for never eat when hunger level above 900, On diet for eating only when hunger level below 100, Loyal for always keeping the members see at least one member from the pack, Double kill for eating when hunger level above 990, Longevity for having 8 members during a game, Careful for never move 6.1 steps, etc. – justhalf – 2014-04-24T19:31:26.757
Actually looking at the behaviour of packs, it would be interesting to have a challenge where everybody cooperate to clear the field as fast as possible. Then each pack can specialize to a specific function. Interesting, haha – justhalf – 2014-04-25T09:53:32.743
Is this challenge still live? I submitted a new entry quite a while ago and still no match... – None – 2014-08-25T08:53:22.223
1@kuroineko Sorry about that. You posted it on my birthday, so it slipped past me. Will try to get an updated scoreboard in the next couple days. – Geobits – 2014-08-25T12:41:45.920
1@Geobits no problem, dude. Happy birthday, and thanks for this extremely funny challenge :). – None – 2014-08-25T14:45:47.343
1sameless bump. Is this challenge dead or alive, birthday notwhitstanding? – None – 2014-09-07T22:17:33.650