Build Your First Bot (Custom Logic)
In this guide, we will write a complete bot from scratch. While the seamaster library provides powerful Templates (see Writing Your Bot), writing your own logic gives you maximum control.
We will build a Harvester Bot that autonomousy manages its energy, harvests algae, and deposits it at a bank.
Copy-Paste Friendly
The code blocks in this guide have aligned line numbers. You can copy and paste them sequentially into your file to build the complete bot.
1. Imports and Setup
Create a new file my_first_bot.py. We start by importing the necessary components from the library.
| from seamaster import GameAPI
from seamaster.botbase import BotController
from seamaster.constants import Ability, ABILITY_COSTS, SCRAP_COSTS, Direction
from seamaster.models import EnergyPad, Bank
from seamaster.translate import move, harvest, deposit
from seamaster import utils
import random
|
2. Defining the Bot Class
We inherit from BotController and define our capabilities.
| class harvester_bot(BotController):
ABILITIES = [Ability.HARVEST] # (1)
ability_scrap_cost = SCRAP_COSTS[Ability.HARVEST]
ability_energy_cost = ABILITY_COSTS[Ability.HARVEST]
def __init__(self, ctx):
super().__init__(ctx)
|
- Capabilities: We declare that this bot needs the
HARVEST ability. The game engine uses this to calculate spawn costs.
3. The Brain (act)
The act() method is the heart of your bot. It runs every tick. Our logic follows a simple priority system:
- Survival: If energy is low, find a charger.
- Banking: If carrying any algae, go deposit immediately.
- Work: Otherwise, find algae and harvest.
| def act(self):
# 1. Survival: If energy is below 50%, head to recharge ports
current_energy = self.ctx.get_energy()
if current_energy < 25:
nearest_energy_pad : EnergyPad = self.ctx.get_nearest_energy_pad()
# Calculate path to energy pad
move_priorities = utils.get_optimal_next_hops(self.ctx.get_location(), nearest_energy_pad.location) # (1)
if move_priorities:
return move(move_priorities[0]) # (2)
# 2. Banking: If I'm carrying algae, deposit it
if self.ctx.get_algae_held() > 0:
# Find banks owned by me
banks: list[Bank] = {
bank for bank in self.ctx.api.banks()
if bank.is_bank_owner == True
}
if banks:
# Find nearest bank
nearest_bank: Bank = min(banks, key=lambda bank: utils.manhattan_distance(self.ctx.get_location(), bank.location))
dist_to_bank = utils.get_shortest_distance_between_points(self.ctx.get_location(), nearest_bank.location)
# If adjacent, deposit. Else, move towards it.
if not dist_to_bank or dist_to_bank < 2:
return deposit(utils.direction_from_point(self.ctx.get_location(), nearest_bank.location)) # (3)
else:
move_priorities = utils.get_optimal_next_hops(self.ctx.get_location(), nearest_bank.location)
if move_priorities:
return move(move_priorities[0])
# 3. Work: Find and harvest algae
nearest_algae = self.ctx.get_nearest_algae()
dist_to_algae = utils.manhattan_distance(self.ctx.get_location(), nearest_algae.location)
if dist_to_algae >= 2:
alg_move_priorities = utils.get_optimal_next_hops(self.ctx.get_location(), nearest_algae.location)
if alg_move_priorities:
return move(alg_move_priorities[0])
elif dist_to_algae < 2 and dist_to_algae > 0:
return harvest(utils.direction_from_point(self.ctx.get_location(), nearest_algae.location)) # (4)
else:
return harvest(None)
|
- Pathfinding:
utils.get_optimal_next_hops helps navigate around obstacles.
- Action: We execute the move command.
- Deposit: Uses
direction_from_point to target the specific bank tile.
- Harvest: Targeted harvest ensures we grab the specific algae we want.
4. The Spawn Policy
Finally, we tell the engine to create our bots.
Spawn Policy
This function must be declared at the top level of the file and named spawn_policy. Your code will not run if this is not present.
| def spawn_policy(gameAPI: GameAPI):
# Spawn a harvester in every tick
spawn_rules = []
# spawn a harvester at a random X location
spawn_x = random.randint(0, gameAPI.view.width-1)
spawn_rules.append(harvester_bot.spawn(spawn_x)) # (1)
return spawn_rules
|
- Spawn: We invoke the
spawn class method on our custom bot class.
Next Steps
Congratulations! You've written a custom bot from scratch.
To go further: