前言
将Screeps的代码进行模块化后,可以将各个功能进行分离,互相不影响,本文将会介绍Screeps中如何进行creep的数量控制来维持房间资源的平衡和发展。本文仅为作者本人的游戏思路,并不是最佳实践,如有更好的实现方法可在评论区提出。
如何抽取配置项可以看专栏的文章《Screeps工程化之配置化》
核心实现逻辑
/*** @module creep数量控制模块*/
import {BUILDER, DEFENDER} from "../constant/roleConstant.js";
import {creatCreep, creepNum, getSortedRolesByWeight} from "../config/creepNum/creepNumCore.js";
import {countOccurrences} from "../utils.js";/*** @description creep数量控制器*/
export const creepNumController = (roomKey) => {deleteDeadCreep()const spawns = Memory.Rooms[roomKey].spawns.map((id) => Game.getObjectById(id))for (const spawn of spawns) {// const spawn = Game.spawns[name]if (!spawn.spawning) {creepNumJudge(spawn, roomKey)}}}
/*** 生成creep核心判断逻辑* @param {StructureSpawn} spawn* @param {string} roomKey*/
const creepNumJudge = (spawn, roomKey) => {//1.根据权重信息组成role的列表通过权重排序const role_list = getSortedRolesByWeight(roomKey, DEFENDER)//2.遍历新组装的角色信息for (const role of role_list) {//针对builder的特殊判断条件if (role === BUILDER) {if (judge(role, roomKey) && Game.rooms[roomKey].find(FIND_CONSTRUCTION_SITES).length !== 0) {creatCreep(spawn, roomKey, role)return;}} else {if (judge(role, roomKey)) {creatCreep(spawn, roomKey, role)return;}}}
}
/*** @description 判断数量是否满足生成creep的条件* @param {string} role* @param {string} roomKey* @returns {boolean}*/
export const judge = (role, roomKey) => {return countOccurrences(getRoleList(roomKey), role) < creepNum(role, roomKey)
}/***@description 删除内存中死亡的creep*/
const deleteDeadCreep = () => {for (let name in Memory.creeps) {if (!Game.creeps[name]) {delete Memory.creeps[name]}}
}/*** @description 获取内存中存活的creep的角色* @returns {string[]}*/
const getRoleList = (roomKey) => {deleteDeadCreep()/*** @description 角色列表* @type {string[]}*/const roleList = []for (const creep of Game.rooms[roomKey].find(FIND_MY_CREEPS)) {roleList.push(creep.memory.role)}return roleList
}
详细介绍:
- deleteDeadCreep方法:在每次一进入该模块中就会删除一次已死亡的creep的内存。
- getRoleList方法:获取该房间内存活的creep并将其creep的role存入一个列表然后返回。
- judge方法:判断该房间,指定角色的creep是否为配置文件中的数量
- creepNumJudge方法:数量控制的核心逻辑,其中,getSortedRolesByWeight方法会返回一个以权重排序过后的角色列表,遍历返回的角色列表,符合条件就生成creep,其中角色为建筑者的creep还有额外的判断条件,本房间内存在建筑工地才生成。
所有的creep生成的数量都根据配置文件中的number字段决定,当该房间中的某一个角色的creep少于指定的值,就会生成一个creep,一直生成到指定数量。
比如这个房间内的upgrader(专门给控制器升级的creep)就需要3个
"upgrader": {role: UPGRADER,bodys: Array(7).fill(WORK).concat(Array(7).fill(CARRY)).concat(Array(7).fill(MOVE)),number: 3,weight: 2,func: upgraderRun,sourcesIndex: 1
}