8
\$\begingroup\$

aBOTcalypse

Design a bot to compete in a King-of-the-Hill challenge! Here's a replay of a default bot game.

The board is 2D, like a side-scrolling video game (but without any scrolling).

A valid bot must accept a multiline string representation of the region of the board it can see, and output a move for the bot.

Mechanics

This is a survival game. The apocalypse has come, and only bots (and an endless supply of rocks stored in hammerspace) remain. Each bot is given a random starting location, at elevation 0. In a given move, a bot can rest, move, throw a rock, or drop a rock. Bots can share space with stationary rocks, but a bot that collides with another bot or a meteor is killed, as is a bot hit by a thrown rock.

  • Gravity: bots and rocks must rest on top of the floor of the board or on top of another rock; resting on something else (air, a meteor, a bot, etc.) leaves one "unsupported". Unsupported bots or rocks will fall until they are supported; a fall of greater than one space will kill a bot, and a bot underneath a falling rock or bot is also killed. This means that trying to move or drop up will only work if the bot is currently sharing a space with a rock (otherwise the bot/rock will fall back down 1 space). A space can become "unsupported" if the rock beneath it falls or is destroyed by a meteor or projectile.
  • Meteors: Each turn a meteor enters the board from the top. A meteor has a velocity of magnitude 2, with a random angle chosen uniformly in the range [-180,0], and a random starting x position. Meteors fall in a straight line along the given trajectory until they hit something, at which point they disappear. Note that rounding in a meteor's movement is towards 0 (as per python's int()).
  • Projectiles: A bot can choose to throw a rock any distance up to its elevation. A thrown rock moves in a straight line until it hits something (all in one turn, unlike a meteor; thrown rocks don't appear on the board), at a slope of - elevation / max distance. Note that thrown rocks begin their trajectory at x +- 1 square. For example, if a bot is at an elevation of 5, and throws left a distance of 1, the rock will begin at (x-1,5) and end at (x-2,0). Collision is only checked in steps of dx=1, and dy is rounded towards 0 (as per python's int()).

Input

Each bot can see a square 20 pixels in each direction (Chebyshev distance = 20), up to the boundaries of the board. There are 8 different characters in each input string:

  • '#' (board boundary)
  • '.' (air)
  • '@' (meteor)
  • '&' (rock)
  • 'e'/'s' (an enemy bot, or itself)
  • 'E'/'S' (an enemy bot, or itself, sharing a space with a rock)

Here's an example input (line breaks will be \n):

..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............................#
..............@...............#
.....................E........#
.....................&........#
.....................&........#
.....................&........#
.....................&........#
...........@.........&........#
....................s&........#
###############################

Output

There are four actions that a bot can take each turn.

  • rest (literally sit and do nothing)
  • move <direction> moves the bot one space in any of the four directions, up, down, left, or right. Movement causes the bot to fall if the new space is not supported by the floor or a rock (fall > 1 = bot.kill()).
  • drop <direction> places ("drops") a rock in the indicated direction. Dropping a rock up (i.e., placing a rock in the square [bot_x, bot_y+1]) or to the side causes it to fall until supported (possibly falling onto the bot during drop up). drop down places a rock in the same position as the bot, if there is not a rock there already.
  • throw <direction> <distance> throws a rock as per the "projectiles" mechanics above, with the indicated max distance. Max distance is irrelevant for throwing upward or downward - the projectile collides with the square below (for down), or attempts to collide with the square above (for up) and then with the bot's square if it doesn't hit anything (killing the bot).

A bot in the contest must output a scalar string with its action upon receiving the input string.

Interface

A bot must consist of a single program which can be called via a python 2 subprocess. Any commands should be indicated, and will be saved in a file called command.txt; before a game begins, the controller will execute each command in command.txt, in order, and then the final command will be used to pass input to the bot from then on.

A bot may have a single storage file called storage.txt in its folder; the "Default Thrower" bot shows an example implementation, using json to save its state during various turns. In addition, feel free to include debugging output in a write-only errlog.txt, which I'll pass along in case your bot fails during a run. I'll make sure to run several tests with each bot, to try and find any errors beforehand.

Scoring

A bot's total score is equal to the number of turns it survives, accumulated over X games of maximum length Y. At the moment, X,Y = 10, 500; if bots are lasting a long time, I'll increase Y, and if they are lasting a short time, I'll increase X.

Controller code is found in controller.py; many thanks to @Nathan Merrill for his DDOS koth from which I adapted the Communicator code.

\$\endgroup\$
13
  • \$\begingroup\$ What prevents bots from making structures such as &&&\n&S&\n###? They would be invulnerable to falling meteors. \$\endgroup\$ May 12, 2015 at 19:47
  • \$\begingroup\$ nothing at all. however, they'd have to rebuild part of the structure if it was struck by anything (which involves being exposed on one of the outer layers during the maintenance process), and they'd still have to deal with other bots. \$\endgroup\$ May 12, 2015 at 20:09
  • \$\begingroup\$ As far as I can see, there is no way to dig rocks. \$\endgroup\$ May 12, 2015 at 20:22
  • \$\begingroup\$ what do you mean by "dig"? each bot has as many rocks as it wants, stored in hammerspace (i'll edit that link into the question). or do you mean to destroy rocks? if that's the case, then a rock is destroyed when it's hit by any projectile, not just a meteor. also realize that other bots can waltz right into your stronghold. \$\endgroup\$ May 12, 2015 at 20:26
  • 1
    \$\begingroup\$ You should add the fact that meteors/projectiles destroy rocks. \$\endgroup\$ May 12, 2015 at 20:28

1 Answer 1

1
\$\begingroup\$

Python 2, Edgebot

Edgebot wants to hide in a corner and build a tower. They'll run to one end, build up a bit, then start dropping rocks to build a wall. Edgebot does not like visitors, and will throw rocks at anyone who gets too close to their tower. If it all goes horribly wrong and edgebot crashes, it'll drop a rock on its own head

import sys
from random import randint
class edgebot():    

    def playtime(self,board):
        try:   
            self.max_height = 5    
            board = board.splitlines()

            #find edgebot
            for y in xrange(0,len(board)):
                row = board[y]
                symbol = 's' if row.count('s') else 'S'
                x = row.find(symbol)
                if x >= 0:
                    self.height = 20 - y
                    break

            ground = board[len(board)-2]
            floor = board[len(board)-1]
            nasty_person = 'e' if ground.count('e') else 'E'
            bad_x = ground.find(nasty_person)
            side = ground.find('#')
            if abs(side - x) ==1:
                self.end_found = 1
            else:
                self.end_found = 0

            if side - x == -1:
                self.direction = 'right'
            else:
                self.direction = 'left'       


            #Bad edgebot! No climbing out of the game!           
            if floor[x] != '#':
                if board[self.height-1][x] == '&':
                    dist = randint(3,self.height)
                    return 'throw ' + self.direction + ' ' + `dist`
                elif symbol =='S':
                    return 'drop up'
                else:
                    return 'move down'

            #Edgebot will go through you to find a corner. You have been warned.    
            elif abs(x - bad_x) <=2:
                if x - bad_x >0:
                    return 'throw left 1'
                else:
                    return 'throw right 1'

            #edgebot wants to hide in a corner
            elif self.end_found ==0:
                if side == -1:
                    return 'move right'#edgebot is right-handed
                elif side - x < -1:
                    return 'move left'
                elif side - x > 1:
                    return 'move right'

            #Too close! Throw rocks at it!
            elif self.height+1>= abs(x-bad_x) and abs(x-bad_x) >=3:
                distance = abs(x - bad_x) - 2
                if distance < 1:
                    return 'throw ' + self.direction + ' 1'
                else:
                    return 'throw ' + self.direction + ' ' +`distance - 1`
                self.max_height += 2 #people came close, edgebot needs to be higher up!

            #edgebot wants a home in the corner        
            elif self.height <self.max_height :
                if symbol =='S':
                    return 'move up'
                else:
                    return 'drop down'

            #edgebot wants a wall. edgebot has, at best, a limited understanding of architecture        
            elif bad_x < 3 or self.height+1<abs(x-bad_x):
                if self.direction == 'right' and row[x+1] == '&':
                    self.max_height += 2
                    return 'drop down'
                elif self.direction == 'left' and row[x-1] == '&':
                    self.max_height += 2
                    return 'move down'
                else:
                    return 'drop ' + self.direction         

            else:
                return 'drop down' #Not sure? Hide under a rock!
        except:
            return 'drop up' #All gone horribly wrong? Squish.


print edgebot().playtime(sys.argv[1])  

Sorry for all the edits, didn't run enough test cases before submitting. There's a small problem in that the little guy will try to climb off the top of the board given enough time, but hopefully that won't be an issue in most matches. Edgebot should now just throw rocks random distances once it's climbed high enough

Last edit for now. Edgebot will now throw rocks at anyone close enough between it and the wall. No sense it taking itself out by running through someone

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.