前言
将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
}