Deepmind 开放了自己的星际争霸机器学习环境,现在只需要安装对应的 pysc2 包,就可以自己写一个星际2 AI啦!本文是Rest探路者分享在博客园的一个相关项目,里面有非常详尽的代码,有兴趣的小伙伴可以参考。
作者:Rest探路者
出处:http://www.cnblogs.com/Java-Starter/
准备
我的环境是python3.6,sc2包0.11.1,机器学习包:pysc2,地图下载链接maps:https://github.com/Blizzard/s2client-proto#downloads。
pysc2是DeepMind开发的星际争霸Ⅱ学习环境。它是封装星际争霸Ⅱ机器学习API,同时也提供Python增强学习环境。以神族为例编写代码,神族建筑科技图如下:
采矿
# -*- encoding: utf-8 -*- ''' @File : __init__.py.py @Modify Time @Author @Desciption ------------ ------- ----------- 2019/11/3 12:32 Jonas None ''' import sc2 from sc2 import run_game, maps, Race, Difficulty from sc2.player import Bot, Computer class SentdeBot(sc2.BotAI): async def on_step(self, iteration: int): await self.distribute_workers() run_game(maps.get("AcidPlantLE"), [ Bot(Race.Protoss, SentdeBot()), Computer(Race.Terran, Difficulty.Easy) ],realtime = True)
注意game_data.py的assert self.id != 0注释掉pixel_map.py的assert self.bits_per_pixel % 8 == 0, "Unsupported pixel density"注释掉,否则会报错
运行结果如下,农民开始采矿
可以正常采矿
建造农民和水晶塔
import sc2 from sc2 import run_game, maps, Race, Difficulty from sc2.player import Bot, Computer from sc2.constants import * class SentdeBot(sc2.BotAI): async def on_step(self, iteration: int): await self.distribute_workers() await self.build_workers() await self.build_pylons() # 建造农民 async def build_workers(self): # 星灵枢纽(NEXUS)无队列建造,可以提高晶体矿的利用率,不至于占用资源 for nexus in self.units(UnitTypeId.NEXUS).ready.noqueue: # 是否有50晶体矿 if self.can_afford(UnitTypeId.PROBE): await self.do(nexus.train(UnitTypeId.PROBE)) ## 建造水晶 async def build_pylons(self): ## 供应人口和现有人口之差小于5且水晶不是正在建造 if self.supply_left<5 and not self.already_pending(UnitTypeId.PYLON): nexuses = self.units(UnitTypeId.NEXUS).ready if nexuses.exists: if self.can_afford(UnitTypeId.PYLON): await self.build(UnitTypeId.PYLON,near=nexuses.first) ## 启动游戏 run_game(maps.get("AcidPlantLE"), [ Bot(Race.Protoss, SentdeBot()), Computer(Race.Terran, Difficulty.Easy) ],realtime = True)
运行结果如下,基地造农民,农民造水晶
收集气体和开矿
代码如下
import sc2 from sc2 import run_game, maps, Race, Difficulty from sc2.player import Bot, Computer from sc2.constants import * class SentdeBot(sc2.BotAI): async def on_step(self, iteration: int): await self.distribute_workers() await self.build_workers() await self.build_pylons() await self.build_assimilators() await self.expand() # 建造农民 async def build_workers(self): # 星灵枢纽(NEXUS)无队列建造,可以提高晶体矿的利用率,不至于占用资源 for nexus in self.units(UnitTypeId.NEXUS).ready.noqueue: # 是否有50晶体矿 if self.can_afford(UnitTypeId.PROBE): await self.do(nexus.train(UnitTypeId.PROBE)) ## 建造水晶 async def build_pylons(self): ## 供应人口和现有人口之差小于5且建筑不是正在建造 if self.supply_left < 5 and not self.already_pending(UnitTypeId.PYLON): nexuses = self.units(UnitTypeId.NEXUS).ready if nexuses.exists: if self.can_afford(UnitTypeId.PYLON): await self.build(UnitTypeId.PYLON, near=nexuses.first) ## 建造吸收厂 async def build_assimilators(self): for nexus in self.units(UnitTypeId.NEXUS).ready: # 在瓦斯泉上建造吸收厂 vaspenes = self.state.vespene_geyser.closer_than(15.0,nexus) for vaspene in vaspenes: if not self.can_afford(UnitTypeId.ASSIMILATOR): break worker = self.select_build_worker(vaspene.position) if worker is None: break if not self.units(UnitTypeId.ASSIMILATOR).closer_than(1.0,vaspene).exists: await self.do(worker.build(UnitTypeId.ASSIMILATOR,vaspene)) ## 开矿 async def expand(self): if self.units(UnitTypeId.NEXUS).amount<3 and self.can_afford(UnitTypeId.NEXUS): await self.expand_now() ## 启动游戏 run_game(maps.get("AcidPlantLE"), [ Bot(Race.Protoss, SentdeBot()), Computer(Race.Terran, Difficulty.Easy) ], realtime=False)
run_game的realtime设置成False,可以在加速模式下运行游戏。
运行效果如下:
可以建造吸收厂和开矿
建造军队
import sc2 from sc2 import run_game, maps, Race, Difficulty from sc2.player import Bot, Computer from sc2.constants import * class SentdeBot(sc2.BotAI): async def on_step(self, iteration: int): await self.distribute_workers() await self.build_workers() await self.build_pylons() await self.build_assimilators() await self.expand() await self.offensive_force_buildings() await self.build_offensive_force() # 建造农民 async def build_workers(self): # 星灵枢纽(NEXUS)无队列建造,可以提高晶体矿的利用率,不至于占用资源 for nexus in self.units(UnitTypeId.NEXUS).ready.noqueue: # 是否有50晶体矿 if self.can_afford(UnitTypeId.PROBE): await self.do(nexus.train(UnitTypeId.PROBE)) ## 建造水晶 async def build_pylons(self): ## 供应人口和现有人口之差小于5且建筑不是正在建造 if self.supply_left < 5 and not self.already_pending(UnitTypeId.PYLON): nexuses = self.units(UnitTypeId.NEXUS).ready if nexuses.exists: if self.can_afford(UnitTypeId.PYLON): await self.build(UnitTypeId.PYLON, near=nexuses.first) ## 建造吸收厂 async def build_assimilators(self): for nexus in self.units(UnitTypeId.NEXUS).ready: # 在瓦斯泉上建造吸收厂 vaspenes = self.state.vespene_geyser.closer_than(15.0,nexus) for vaspene in vaspenes: if not self.can_afford(UnitTypeId.ASSIMILATOR): break worker = self.select_build_worker(vaspene.position) if worker is None: break if not self.units(UnitTypeId.ASSIMILATOR).closer_than(1.0,vaspene).exists: await self.do(worker.build(UnitTypeId.ASSIMILATOR,vaspene)) ## 开矿 async def expand(self): if self.units(UnitTypeId.NEXUS).amount<2 and self.can_afford(UnitTypeId.NEXUS): await self.expand_now() ## 建造进攻性建筑 async def offensive_force_buildings(self): if self.units(UnitTypeId.PYLON).ready.exists: pylon = self.units(UnitTypeId.PYLON).ready.random if self.units(UnitTypeId.PYLON).ready.exists: # 根据神族建筑科技图,折跃门建造过后才可以建造控制核心 if self.units(UnitTypeId.GATEWAY).ready.exists: if not self.units(UnitTypeId.CYBERNETICSCORE): if self.can_afford(UnitTypeId.CYBERNETICSCORE) and not self.already_pending(UnitTypeId.CYBERNETICSCORE): await self.build(UnitTypeId.CYBERNETICSCORE,near = pylon) # 否则建造折跃门 else: if self.can_afford(UnitTypeId.GATEWAY) and not self.already_pending(UnitTypeId.GATEWAY): await self.build(UnitTypeId.GATEWAY,near=pylon) # 造兵 async def build_offensive_force(self): # 无队列化建造 for gw in self.units(UnitTypeId.GATEWAY).ready.noqueue: if self.can_afford(UnitTypeId.STALKER) and self.supply_left>0: await self.do(gw.train(UnitTypeId.STALKER)) ## 启动游戏 run_game(maps.get("AcidPlantLE"), [ Bot(Race.Protoss, SentdeBot()), Computer(Race.Terran, Difficulty.Easy) ], realtime=False)