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

欢迎继续一起学习用Python编写AI玩爆星际争霸系列之二,上一节中我们学习开发环境的配置以及游戏初始化,实现了游戏开局和让神族工人单位开始采矿。现在我们试着生成更多神族工人单位进行采矿加快采集速度。

timg

首先,我们打开上节完成的代码:

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


class MrBot(sc2.BotAI):
    async def on_step(self, iteration):
        # what to do every step
        await self.distribute_workers()  # in sc2/bot_ai.py


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

这段功能实现非常简单,因为其中分配工人进行工作,已经有相应的方法可以调用。但是没有永远免费的午餐。现在就需要我们开始构造自己的方法:build_workers(建造工人):

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

其中build_workers就是我们需要构造的方法。为了建造农工贸,我们首先需要在游戏中拥有神族NEXUS(中心枢纽),这个枢纽就像是基地可以生产神族的工人单位Probes(探机),因此我们需要建造的工人单位Probes类继承PROBE对象,所以需要首先引入NEXUS和PROBE:

from sc2.constants import NEXUS, PROBE

现在,为了建造工人单位,我们需要使用NEXUS,如果矿物足够,则建造工人;这里有个机制,一个基地可以创建生产列队,一次最多可以连续生产5个(如果是人玩游戏的,通常可以把生产队列排满,可以减少因为遗忘或者操作来不及而耽误生产工人)。但如果是AI进行控制的话,为了有效利用资源(因为排入生产列队会预先占用资源)。AI可以严格执行指令,不会有人的操控限制影响,因此可以保证每次基地只需要两个生产列队即可。和AI比起来,人类的效率明显慢,效率低:)

    async def build_workers(self):
        # nexus = command center
        for nexus in self.units(NEXUS).ready.noqueue:
            if self.can_afford(PROBE):
                await self.do(nexus.train(PROBE))

1

这里我们不得不说下,星际争霸2这游戏还有另外一个人口机制,就是每个种族需要建造自己的补给建筑支持人口扩张,神族的补给建筑(可以称为房子)是Pylon(水晶)。当建造单位快到人口上限时,需要提前开始建造补给建筑。因此在on_step方法中增加建造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()  
        await self.build_pylons()  # pylons 是神族的房子

接下来我们需要构造build_pylons方法。这里我们需要在剩余人口快不足2时,就分配农民建造Pylon(一个Pylon的建造时间约等于2个工人的建造时间)。同时神族的水晶需要建造在基地的一定范围内(这是神族移动特殊属性),这个范围叫“Psionic Matrix”,Pylon建好后,又可以扩大基地的范围。

 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)

同时,我们还需要注意,我们时候已经有一个Pylon正在建造,否则我们可能会浪费资源同时建造了多个Pylon,而无法生产其他单位。
 2

所以完整代码如下:

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()
        await self.build_pylons()    
 
    async def build_workers(self):
        for nexus in self.units(NEXUS).ready.noqueque:
            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)       

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

 

3

 

本节就到这里。下次继续打造游戏AI

 

 

 

 

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

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