Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API brainstorming #1

Open
kazimuth opened this issue Oct 4, 2017 · 2 comments
Open

API brainstorming #1

kazimuth opened this issue Oct 4, 2017 · 2 comments

Comments

@kazimuth
Copy link
Contributor

kazimuth commented Oct 4, 2017

What should the game's API look like for players?

@kazimuth
Copy link
Contributor Author

kazimuth commented Oct 4, 2017

Brainstorming:

Python

Outer loop

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')

State management

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))

JS / TS

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');
});

@kazimuth
Copy link
Contributor Author

kazimuth commented Oct 6, 2017

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant