Open kazimuth opened 6 years ago
Brainstorming:
The top level of the player's code should maybe look like one of the following? It would start with:
from battlecode import *
and then would have one of a variety of types of loops, depending on what type of control the player wants:
# simplest loop; player code has control when it's their turn, blocks otherwise.
for state in run_game('mybot'):
# `state` is an object containing the state of the world for a particular turn.
# new turns would return new states, leaving old ones untouched.
run_my_turn(state)
print('finished')
# or, alternatively:
game = Game('mybot')
for state in game.run():
run_my_turn(state)
print('finished')
# sometimes it's the other team's turn, and players don't have any control, but they
# can still use the extra time for processing
# (instead of doing nothing for the whole enemy turn).
# code still blocks while waiting for the next turn.
for state in run_game('mybot', all_turns=True):
if state.active_team == state.my_team:
run_my_turn(state):
else:
intermediate_processing(state)
print('finished')
# entirely non-blocking; player code checks repeatedly for new messages from the server,
# never pauses waiting for things to happen
game = Game('mybot')
while not game.finished:
state = game.poll()
if state:
if state.active_team == state.my_team:
run_my_turn(state)
state.submit_actions()
else:
intermediate_processing(state)
else:
# state is None, no new turn has happened
background_processing()
print('finished')
# reduce copying overhead?
for state in run_game('mybot', copy_state=False):
# state is the same object, updated repeatedly;
# instead of a new copy of the state each round
run_my_turn(state)
print('finished')
# current API; does not return copies of the game state, blocks
game = Game('mybot')
while True:
game.next_turn()
run_my_turn(game)
if game.done:
break
print('finished')
on_my_team = state.entities(team=state.my_team)
for ent in on_my_team:
ent.queue_move(ent.loc + (1,0))
ent.queue_move(NORTH_WEST)
nearby = list(state.entities(loc=(5,6), within_sq=8))
can_move = set(state.entities(cooldown=0))
nearby_can_move_on_my_team = state.entities(
team=state.my_team,
loc=(5,6),
within_sq=8,
cooldown=0
)
by_id = state.entity(id=37)
by_id.queue_build(SOUTH_EAST)
holding = state.entity(loc=(5,6))
holding.queue_throw(holding.loc + (7,8))
const game = new Game('mybot');
game.on('my-turn', (state) => {
runMyTurn(state);
});
game.on('their-turn', (state) => {
intermediateProcessing(state);
});
game.on('end', (state) => {
console.log('finished');
});
game.run();
runGame('mybot', async (game) => {
// ES7 async iterators
async for (const state of game.iter()) {
}
console.log('finished');
});
Players need to know about actions that succeeded / failed, for debugging purposes, as well as for cheaply updating i.e. spatial indices or machine learning models.
The API could look like:
# process last turn's actions
for action in state.successful_actions_last_turn:
# action is a Move, Throw, etc. with attached information
# can use it to update spatial indexes, train ML models, etc.
for action in state.failed_actions_last_turn:
# update ML model, etc.
As well as showing failed actions in the viewer somehow.
We could even make the forward facing api be:
state.submit_action(Move(entityid, location))
# or
game.submit_action(Move(entityid, location))
So that things are symmetric, although that could be confusing.
What should the game's API look like for players?