In this challenge, bots (consisting of JS functions) move around an infinite factory (playing field), collecting characters. These characters can be used to build worker bots, or dropped for other bots to pick up.
This challenge is a modified redo of Bot Factory KoTH, which was broken by a mistake in the spec.
[39599.65] Ghost [12251.15] Shy Guy [8565.70] Camper [8339.95] Honnold [2862.50] True Neutral [51.575] Rabbit [10.65] Centrist [-8.85] The Luggage [-66.075] The Caveman
The bounty went to @Razetime, as their bots were consistently in the lead until Shy Guy showed up.
Feel free to keep posting bots, but the scoring might not get updated.
All bots start out randomly placed around the center of the factory,
[0, 0], where coordinates are arrays
[x, y]. North is -Y, and west is -X. Each round consists of up to 100000 turns. A bot may move one space in any cardinal direction (or build a worker, or drop a character) per turn.
Bots can move by returning
Characters will be randomly distributed, centered around
[0, 0]. There are always up to a total of 4 characters per bot at any given time (excluding those from dead bots).
Character's positions may overlap, and their character value (such as
() is selected from a pool of the source code of every bot and worker currently in the factory.
Bots collect characters by moving into the same position in the factory, and these collected characters are stored within the bot.
Bots may also drop a character they have previously collected in any of the four cardinal directions. This character is then removed from the bot's collected characters array.
Bots drop characters by returning
c is a string.
Bots have a score, which is initially
-floor(LEN / 2), where
LEN is the length of the bot's source code in characters. Worker bots start with a score of 0 regardless of their length.
Whenever a character is collected, this score value increments; when a character is dropped, it decrements.
When two or more bots collide (occupy the same position), whichever has the highest score survives (if there is a tie, none survive). All bots that die "drop" the characters they have collected, which are randomly distributed centered around the position they collided in.
Bots can switch places by moving into each others' previously occupied positions without colliding. Bots can collide with their own workers.
Bots can use the characters they have collected to build a worker bot. A worker bot's source code (provided as a function or arrow function) must be entirely made up of characters its owner has collected, which are then removed. Half of the length of the worker's source code is deducted from the owner's score.
Worker bots are placed randomly around the position of their owner, using the same system as characters, and are not immune to collision. Worker bots can also build worker bots, whose owner would be the worker.
Workers can be built by returning the result of the function
source is a string. If the bot cannot be built (such as not having all necessary characters), nothing happens.
All bots are functions. They are provided a single argument, an object that can be used for storage, and can access information about other bots and characters using the following functions:
bots(): Returns an array of bots (as objects)
chars(): Returns an array of characters (as objects)
self(): Returns the bot that called it (as an object)
owner(): Returns the owner of the bot that called it (as an object,
nullif owner is dead, or
self()if no owner)
A bot object has the following properties:
uid: An integer ID unique to each bot, randomly selected
owner: The UID of the bot's owner
score: The score of the bot
pos: The position of the bot formatted as
A bot object also has the following properties if it is the owner or worker of the bot:
chars: An array of characters the bot has collected
source: A string with the bot's source code
A character object has the following properties:
char: A string
pos: The position of the character formatted as
There are also the following library functions:
center(): Get average of bots' positions weighted by score
turn(): Get current turn (starts at 0)
at(pos): Returns an object:
uidof the bot at that location, or
nullif there is none
chars: An array of characters at that location
dir(from, to): Get direction from
to, which should be arrays formatted
dirTo(pos): Same as
dist(from, to): Get taxicab distance from
to, which should be arrays formatted
distTo(pos): Same as
Once all surviving bots are direct or indirect workers of the same initial bot, characters will no longer generate. Games automatically end when all characters are collected.
At the end of a game, all bots' scores (including their workers) are added up for each round with the highest winning.
- Bots may not use global variables in a way which produces side effects other than intended (such as to sabotage other bots or the controller, or communicate with any other bots)
- Bots which error will be killed and drop their characters
- Bots may only attempt to build workers which are valid functions
- Bots may not take an unnecessarily long time to run (no hard limitation, but be reasonable)
- Bots may not team with other which do not originate from the same owner (directly or not)
- Character and bot spawning radius is based on a geometric distribution (
p=0.1), with a random angle. The resulting coordinates are truncated to integers. Repeated until a position is found with no bots within a taxicab distance of 4
- For dead bots' drops,
p=0.2and there is no distance requirement
- For worker bot spawning, minimum taxicab distance is 3 for the owner
- Every time a character is picked up, one attempt is made to generate another. An attempt will only fail if there are already
4 * botCountcharacters not dropped by a bot (or a bots' death), where
botCountis the total number of alive bots (including workers).
4 * botCountcharacters are generated at the start.
ExampleBot uses an arrow function to keep its starting score higher, but still isn't well golfed. It likes characters which are in the middle of the action, which it finds by sorting the
chars() array and using the
center library functions. It will not be included in the competition game.
() => dirTo(chars().sort((a, b) => dist(center(), a.pos) - dist(center(), b.pos)).pos)
dirToreturned an array showing the vector towards
south(), etc. \$\endgroup\$