Python编写AI机器人玩爆星际争霸系列(3)


timg

这一节我们继续让AI可以采集另一个游戏的主要战略资源:Gas(气),同时可以扩张到新的资源点。

上一节的代码实际执行之后,当第一个主基地的晶体矿每个矿脉上有三个工人时,这个矿就饱和了;这个时候就可以考虑扩张(实际游戏中,扩张资源点需要根据战局综合考虑),在最近的资源点新建基地生成工人更快地采集矿物资源。这里的扩张方法又是一个免费的午餐,暴雪开发的API中已经有相应的方法:await self.expand(),我们只要将这个方法添加到on_step()方法中:

    async def on_step(self, iteration):
        # what to do every step
        await self.distribute_workers()  # in sc2/bot_ai.py
        await self.build_workers()  # 建造工人
        await self.build_pylons()  # 建造神族补给建筑
        await self.expand()

这里扩张的方法如下:

 async def expand(self):
        if self.units(NEXUS).amount < 2 and self.can_afford(NEXUS):
            await self.expand_now() #sc2/bot_ai.py中

这里我们将扩张的基地数量限制在2个。self.expand_now()方法的定义在sc2/bot_ai.py中。

完整代码如下:

import sc2
from sc2 import run_game, maps, Race, Difficulty
from sc2.player import Bot, Computer

from sc2.constants import NEXUS, PROBE, PYLON

class MrBot(sc2.BotAI):
    async def on_step(self, iteration):
        # what to do every step
        await self.distribute_workers()  # in sc2/bot_ai.py
        await self.build_workers()  # workers bc obviously
        await self.build_pylons()  # pylons are protoss supply buildings
        await self.expand()


    async def build_workers(self):
        # nexus = command center
        for nexus in self.units(NEXUS).ready.noqueue:
            # we want at least 20 workers, otherwise let's allocate 70% of our supply to workers.
            # later we should use some sort of regression algo maybe for this?

            if self.can_afford(PROBE):
                await self.do(nexus.train(PROBE))

    async def build_pylons(self):
        if self.supply_left < 2 and not self.already_pending(PYLON):
            nexuses = self.units(NEXUS).ready
            if nexuses.exists:
                if self.can_afford(PYLON):
                    await self.build(PYLON, near=nexuses.first)

    async def expand(self):
        if self.units(NEXUS).amount < 2 and self.can_afford(NEXUS):
            await self.expand_now()


run_game(maps.get("(2)CatalystLE"), [
    Bot(Race.Protoss, MrBot()),
    Computer(Race.Terran, Difficulty.Easy)
], realtime=False)

分基地

接下来,我们还要为建造科技建筑和作战单位采集足够的气体,神族采集气体的建筑叫做Assimilator,我们需要把这个建在气体矿上方。首先我们需要引入ASSIMILATOR:

from sc2.constants import NEXUS, PROBE, PYLON, ASSIMILATOR

接下来我们需要建造ASSIMILATOR:

class SentdeBot(sc2.BotAI):
    async def on_step(self, iteration):
        await self.distribute_workers()  # in sc2/bot_ai.py
        await self.build_workers()  # 建造工人
        await self.build_pylons()  # 建造补给建筑
        await self.expand()  # 扩张新建基地
        await self.build_assimilator()  # 建造气体采集建筑

我们试想一下采集气体的流程:首先我们需要找到合适的气体矿,即找到基地附近可用的气矿,然后分配一个这个基地附近的工人去建造采气建筑。幸运的是,暴雪API已经提供了很多方法帮我们实现很多功能:

 async def build_assimilator(self):
        for nexus in self.units(NEXUS).ready:
            vaspenes = self.state.vespene_geyser.closer_than(25.0, nexus) # 找到基地25方格内的气矿
            for vaspene in vaspenes:
                if not self.can_afford(ASSIMILATOR): # 确保矿物资源足够
                    break
                worker = self.select_build_worker(vaspene.position) # 分配工人建造采气建筑
                if worker is None:
                    break
                if not self.units(ASSIMILATOR).closer_than(1.0, vaspene).exists:
                    await self.do(worker.build(ASSIMILATOR, vaspene))

 

这样我们目前完成的代码如下:

import sc2
from sc2 import run_game, maps, Race, Difficulty
from sc2.player import Bot, Computer
from sc2.constants import NEXUS, PROBE, PYLON, ASSIMILATOR


class SentdeBot(sc2.BotAI):
    async def on_step(self, iteration):
        await self.distribute_workers()  # in sc2/bot_ai.py
        await self.build_workers()  # workers bc obviously
        await self.build_pylons()  # pylons are protoss supply buildings
        await self.expand()  # expand to a new resource area.
        await self.build_assimilator()  # getting gas

    async def build_workers(self):
        # nexus = command center
        for nexus in self.units(NEXUS).ready.noqueue:
            # we want at least 20 workers, otherwise let's allocate 70% of our supply to workers.
            # later we should use some sort of regression algo maybe for this?

            if self.can_afford(PROBE):
                await self.do(nexus.train(PROBE))

    async def build_pylons(self):
        if self.supply_left < 2 and not self.already_pending(PYLON):
            nexuses = self.units(NEXUS).ready
            if nexuses.exists:
                if self.can_afford(PYLON):
                    await self.build(PYLON, near=nexuses.first)

    async def expand(self):
        if self.units(NEXUS).amount < 2 and self.can_afford(NEXUS):
            await self.expand_now()

    async def build_assimilator(self):
        for nexus in self.units(NEXUS).ready:
            vaspenes = self.state.vespene_geyser.closer_than(25.0, nexus)
            for vaspene in vaspenes:
                if not self.can_afford(ASSIMILATOR):
                    break
                worker = self.select_build_worker(vaspene.position)
                if worker is None:
                    break
                if not self.units(ASSIMILATOR).closer_than(1.0, vaspene).exists:
                    await self.do(worker.build(ASSIMILATOR, vaspene))


run_game(maps.get("(2)CatalystLE"), [
    Bot(Race.Protoss, SentdeBot()),
    Computer(Race.Terran, Difficulty.Easy)
], realtime=False)

分基地

本节到此,下节继续~

未经允许不得转载:Mr.开发者 » Python编写AI机器人玩爆星际争霸系列(3)

赞 (0)
分享到:更多 ()