[screeps]room孵化队列的设计

在房间Coltroller等级达到7级和8级的时候,每个房间将解锁第二个/第三个Spawn,这时候就要考虑代码怎么能多兵营(spawn)同时造兵,而不是让spawn成为一个巨大的Extension

image.png

孵化任务列表

设想有一个孵化任务列表,来让spawn们自己来认领自己的孵化任务,当spawn可以孵化时,那我就领下这个任务。当spawn正在孵化时,那就不领。
现在要考虑的问题就是:

  1. 生成孵化任务列表
  2. spawn认领任务

生成孵化任务列表

在教程中,教给我们的是,使用数量来判断是否需要孵化更多的role,我也没有研究出更好的方法,也是用数量判断。
设定一个limit值表示房间内规划的数量,例如limit = 2,那当我在房间内数creep数小于limit值时,就要向孵化列表中push孵化任务了。
接下来的问题时那这个房间内数量的值,怎么获取呢?
使用memory存储,在孵化creep时除了role还定义了1个额外的值room 来标识这个creep出生的房间。
循环Game.creeps时,就能从memory中获得各个room中的role数量了
但这样还不够,有可能出现这种情况无法完成全部孵化任务
1.energy不够,spawn无法完成孵化任务
2.spawn在孵化中无法完成孵化任务
那在本tick结束后,队列中的指标还是没有完成,下一tick就会继续push孵化任务。
所以在计算数量的时候,还要算上queue中预孵化的这一部分creep

spawn认领任务

在创建好孵化任务列表后,认领任务就简单多了,只要循环Game.spawns判断spawnCreep的返回值,如果成功,那就删除第一个任务就好了。
有一点要注意的是,教程里为creep命名时,用的时Game.time,但实际上,有可能是同一tick时多个spawn一起孵化,而creep的名字不能重复,就要给creep一个绝对不能重复的名字。
我翻了下lodash文档,还真有_.uniqueId([prefix=''])

多兵营出兵

这样设计,spawn孵化资源就能利用上了,附几个代码参考

  • 数量检测Env.js
module.exports = function () {
  // 清除死去creep的memory
  const creepsName = Object.keys(Game.creeps)
  Object.keys(Memory.creeps).forEach(name => {
    if (!creepsName.includes(name)) {
      delete Memory.creeps[name]
    }
  })
  // 统计每个房间creeps数
  global.roomCreeps = {}
  Object.values(Game.creeps).forEach(creep => {
    const { room, role } = creep.memory
    if (!global.roomCreeps[room]) {
      global.roomCreeps[room] = {
        [role]: 1
      }
    } else if (!global.roomCreeps[room][role]) {
      global.roomCreeps[room][role] = 1
    } else {
      global.roomCreeps[room][role]++
    }
  })
}
  • room控制器
module.exports = function (room) {
  roomSpawnCreeps(room)
}

/**
 * 检查creep数量 room数+queue数
 */
function roomSpawnCreeps(room) {
  const { harvester = 0 } = global.roomCreeps[room.name] || {}
  const queue = room.memory.queue || []
  const queueNum = {}

  queue.forEach(role => {
    queueNum[role]
      ? queueNum[role]++
      : queueNum[role] = 1
  })

  if (harvester + (queueNum['harvester'] || 0) < 2) {
    queue.push('harvester')
  }
  room.memory.queue = queue
}
  • spawn控制器
module.exports = function (spawn) {
  getSpawnFromQueue(spawn)
}

// 从队列种选取孵化任务,领取后,shift掉
function getSpawnFromQueue(spawn) {
  const queue = spawn.room.memory.queue
  // 是否可以孵化?
  if (queue.length > 0 && !spawn.spawning) {
    const role = queue[0] // 孵化队列第一位
    const bodys = getBodys(role)
    const result = bodys && spawn.spawnCreep(bodys, _.uniqueId('harvester_'), {
      memory: {
        role: 'harvester',
        room: spawn.room.name
      }
    })
    if (result === OK) {
      queue.shift()
      spawn.room.memory.queue = queue
    }
  }
}

function getBodys(role) {
  if (role === 'harvester') {
    return [WORK, MOVE, CARRY]
  }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 为了不让自己下线时出现 creep 都凉了的情况,你的代码里或多或少都有一个用于控制他们数量的模块。在教程中,官方...
    HoPGoldy阅读 9,062评论 9 28
  • 前言 本文来讨论一下 Screeps 中最重要的 角色系统 的设计方案以及一些基本原则。注意,本文中讨论的内容可能...
    HoPGoldy阅读 14,237评论 3 13
  • 简介 在设计自己的角色系统的时候,很多人都会被角色越来越多的问题所困扰,本文不讨论如何去削减角色的数量,而是从“发...
    HoPGoldy阅读 10,369评论 7 21
  • 简介 作为新手玩家在游戏进程中遇到的第一个”BOSS“,很多人会对如何拓展自己的疆域感到无从下手,那么本文就简单介...
    HoPGoldy阅读 11,336评论 4 12
  • 作为一个多人在线沙盒游戏,和别的玩家发生冲突可以说是不可避免的事情。本文简单介绍一下在 Screeps 中的防御方...
    HoPGoldy阅读 5,909评论 0 7