Better support for build orders
I'm thinking about something like build order class, that could just specify step-by-step instructions for the first parts of the game. Also simplifying expansion-taking and building placement would be a good thing to add.
I'm currently testing a build order implementation that can be used as follows:
build_order = [
(supply_is(12), train(UnitTypeId.SCV, on_building=UnitTypeId.COMMANDCENTER)),
(minerals_at_least(100), build(UnitTypeId.SUPPLYDEPOT)),
(supply_is(13), train(UnitTypeId.SCV, on_building=UnitTypeId.COMMANDCENTER)),
(supply_is(14), train(UnitTypeId.SCV, on_building=UnitTypeId.COMMANDCENTER)),
(minerals_at_least(150), build(UnitTypeId.BARRACKS)),
(supply_is(15), train(UnitTypeId.SCV, on_building=UnitTypeId.COMMANDCENTER)),
(supply_is(16), train(UnitTypeId.SCV, on_building=UnitTypeId.COMMANDCENTER)),
(supply_is(17), train(UnitTypeId.SCV, on_building=UnitTypeId.COMMANDCENTER)),
(None, build(UnitTypeId.BARRACKS)),
(supply_is(18), build(UnitTypeId.SUPPLYDEPOT, around_building=first_barracks)),
(supply_is(18), train(UnitTypeId.SCV, on_building=UnitTypeId.COMMANDCENTER)),
]
self.build_order = BuildOrder(self, build_order)
and then it would be invoked as
async def on_step(self, state, iteration):
await self.build_order.execute_build(state)
I'll create a PR so you can review. Is this something that you think would be a good way to do it?
Here's a sample usage: https://github.com/reypader/python-sc2/blob/build-order-support/examples/terran_build_order.py
and here's the source https://github.com/reypader/python-sc2/blob/build-order-support/sc2/build_order.py
It's currently WIP but as of writing, it's working for simple build orders based on resource and supply counts.
This looks quite good. I like how the build order is used inside the bot. This is quite modular way to do this, and allows the bot still control the situation if it's attacked, or when the build order is completed.
However, I feel like having a submodule for this would be a better idea. The function names you defined are named similarly to the methods in units or BotAI, so they might cause confusion. Moreover, the build orders are not that clearly a part of SC2 API. I'm think adding build order support to the library is a good idea, I also feel like placing them to a new submodule makes the separation between the parts cleaner. Also, it might be a good idea to move the state conditions to a dedicated state_condition module.
The conditions look reasonable. I feel we should somehow allow referencing to other conditions or events. Something I'd like to support (as a pseudocode build-order):
13 supply: build supplydepot
15 supply: build cc
17 supply: take gas
18 supply: build barracks
cc complete: build factory
factory complete: train siegetank
factory complete: take gas
Other thing that might be a good idea to support is messaging from/into the build order. Having a flag to turn on/off automatic supply or worker production and things like that.
I though about referencing previous build orders, actually. Though, the way it is now, it would probably be through counting how many buildings are complete rather than actually referring to the result of a previous build order action.
13 supply: build supplydepot
15 supply: build cc
17 supply: take gas
18 supply: build barracks
1 cc is ready: build factory
1 factory is ready: train siegetank
2 factory is ready: take gas
The challenge here would be to make the build order know which one is already executed while also allowing the bot to restore a build order in case of an attack. I'll see if creating an "Intent" class or something to represent the action would open new ways of implementing this.
Also, I agree with moving it into a submodule just to be clear that it's not part of the core abstraction of SC2 API.
confer #53