Creep移动原理和对穿的应用 - Screep技术

在Screeps游戏中,寻路是最基本、最重要也最需要细致优化的事情。

在前期游戏中你可能会遇到两个Creep在对向寻路时,一个Creep会绕着另一个Creep移动,这样的事情看起来并不是很完美。

然而在Screep中,游戏是允许两个Creep相互“对穿”移动的,正如开头GIF中你看到的那样。

那么我们如何更好实现这样的移动,原理又是如何的呢?

首先你要注意以下几件事情

  • 避免单独或依赖使用自带的寻路
  • 重新定义物流/移动全局逻辑

实现简单对穿

找来两只creep,让他们紧靠,一个在左一个在右

//在控制台
let t1 = Game.creeps.t1;//在左边的creep
let t2 = Game.creeps.t2;//在右边的creep

t1.move(LEFT);
t2.move(RIGHT);

这样两个creep就相互对穿了。

在继续讲解对穿之前你需要知道几个基本原理逻辑,这里不再剖析源代码,我直接告诉你结果和过程。

首先你需要了解几个概念

纳入计划

在Screeps的文档中找到Creep的move方法返回值列表中,对返回值OK的描述是这个操作已经成功纳入计划。但您要记得,纳入计划并不代表creep本tick结束时一定会移动到那里,如果遇到预定冲突,被调用的creep可能是不会移动的。

预定

预定,creep在移动到一个坐标前会尝试去预定这个坐标,预定成功后,这个位置就是下一个tick该creep的位置,且永远不会被其他creep抢占,如果预定失败,那么该creep会预定原来自己的位置,下一tick也就在原来的位置。

预定冲突

当一个creep的move在被纳入计划后,即将被预定的位置上却有了其他creep的位置预定,那么这个creep的位置预定将会在它原来的位置。也就是说,谁先预定一个位置,谁就能移动到那个位置。


基本移动规律:

  • 调用api后,这个移动会被纳入计划表(也叫做intent)
  • 代码的先后调用顺序不能完全决定Creep在预定时遇到冲突的优先权
  • Creep在预定时会进行递归,递归判断对自己预定有直接或间接影响的Creep,从而判断自己的预定
  • 每个Creep在预定位置后,它将不再有其他的位置改变

具体流程如下(我用js写流程方便大家理解):

let intent = (...);//拿到本tick的计划表,这个表存放了这个tick所有的creep.move调用每个数据包括creep和direction,表中的每一个数据一旦取出(pop)就会消失,直到取完
let perPos = (...);//预定二维数组,每个数据包含了两个数据,pos和creep分别表示被预定了的位置和预定这个位置的creep

function reserve(creep){
  //从计划表中取出数据,这个操作会让计划表中该数据无法再次pop,既消失
  let data = intent.popByCreep(creep);

  //从data中获取要移动的方向
  let direction = data.direction

  //根据direction获取将要移动到的坐标
  let nextPos = getPos(creep.pos,direction);

  //判断这个坐标是否能够前往,如果是地图边缘或者不能踩creep的建筑就直接预定失败
  if(!isTouchable(nextPos)){
    //只能预定自己原来的位置
    perPos.set(creep.pos,creep);
    return false;//返回预定失败
  }

  //查询这个位置上有没有其他的预定
  if(perPos.exist(nextPos)){
    //如果有,只能待在原地,预定自己原来的位置
    perPos.set(creep.pos,creep);
    return false;//返回预定失败
  }
  //如果没有其他的预定

  //获取要移动到的位置上的Creep,注意,是获取本tick地图上某个位置的creep,并不是预定移动后的creep
  //并且也无法获取到此次迭代中的上级creep
  let nextCreep = getCreep(nextPos);

  if(!nextCreep){//如果那个位置上没有creep
    //直接预定
    perPos.set(nextPos,creep);
    return true;//返回预定成功
  }else{//如果那个位置上有creep
    //判断nextCreep是否已经成功预定了其他位置,且这个位置不是要移动的creep的nextPos
    if(perPos.exist(nextCreep)
    && perPos.getPos(nextCreep) != nextPos){
      //无法移动,因为这个creep已经有了预定且它预定的位置就是它原来的位置,要移动的creep不能移动到它的头上
      perPos.set(creep.pos,creep);
      return false;//返回预定失败
    }

    //判断该nextCreep该tick是否有移动计划
    if(!intent.exist(nextCreep)){//如果nextCreep没有移动计划
      //则要移动的creep无法移动只能预定原来自己的位置
      perPos.set(creep.pos,creep);
      return false;//返回预定失败
    }else{//如果nextCreep有移动的计划
        if(reserve(nextCreep)){//递归处理这个creep
          //如果nextCreep预定成功了,要移动的creep也能成功预定,因为那个位置已经被腾出来了
          perPos.set(nextPos,creep);
          return true;//返回预定成功
        }else{//如果nextCreep没能成功预定
          //要移动的creep只能待在原地
          perPos.set(creep.pos,creep);
          return false;//返回预定失败
        }
    }
  }
}

//判断计划表是否为空来循环
while(!intent.isEmpty()){
  //越早调用api的creep越先进入递归
  reserve(intent.popEarliest().creep);
}

//通过预定数组,更新下一个tick的creep位置
updateGame(perPos);

注:上面的流程模型并不是最终模型,这个模型并没有得到源代码的印证和官方的认可,仅限于直白的了解移动机制。

为了检查你是否能意会这些概念,我们做一个情境练习。

这是一个线性坐标上Creep的分布

POS 1 2 3
Creep t1 t2 t3
t1.move(RIGHT);
t2.move(LEFT);
t3.move(LEFT);

当执行上面的代码时,creep的移动情况如何?

答案是

POS 1 2 3
Creep t2 t1 t3

这个过程是这样的

因为是t1最早进行的调用,所以递归从t1开始

t1预定位置2时发现上面有个t2,于是便进入递归对t2进行预定,结果在计划中发现t2是向位置1移动,而位置1没有被预定,所以t2预定了位置1

POS 1 2 3
Creep t1 t3
PER t2

因为t2的成功预定,所以t1也能够预定到它想去的位置---位置2,并结束了递归

POS 1 2 3
Creep t3
PER t2 t1

此时t1和t2都预定完成了,计划表中还剩t3,所以让t3开始递归
t3想预定位置2,发现位置2已经被t1预定了 ,此时发生了预定冲突,所以t3只能预定自己原来的位置即位置3

POS 1 2 3
Creep
PER t2 t1 t3

所以在下一个tick时,三个creep的位置就是

POS 1 2 3
Creep t2 t1 t3

还是同样的情况

POS 1 2 3
Creep t1 t2 t3

那接下来这段代码呢

t3.move(LEFT);
t2.move(LEFT);
t1.move(RIGHT);

结果是

POS 1 2 3
Creep t2 t1 t3

再来进行一次分析,这次递归会有点深度
首先还是对最先调用api的t3进行递归

t3想预定位置2,发现位置2上有t2,于是对t2进行递归

t2想预定位置1,发现位置1上有t1,于是对t1进行递归

t1想预定位置2,但虽然位置2上有t2,但t2是t1的上级递归,所以按照流程t1是看不见它的。t1就认为位置2上没有其他creep,且没有其他预定,所以t1成功预定了位置2

POS 1 2 3
Creep t2 t3
PER t1

因为t1的预定成功,所以t2也能预定成功,所以t2预定到了位置1

这里就解释了为什么creep能完成对穿

POS 1 2 3
Creep t3
PER t2 t1

由于t2的预定成功,所以t3本来也该预定成功,但t3想预定位置2时发现位置2已经被t1预定了,发生了预定冲突,所以t3只能预定自己原来的位置

POS 1 2 3
Creep
PER t2 t1 t3

所以在下一个tick时,三个creep的位置就是

POS 1 2 3
Creep t2 t1 t3

经过多次在sim中的验证,以上的流程逻辑是能够得到正确的结果的。你可以把它作为参考来定制和优化你的Creep移动/物流逻辑。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容

  • 文章图片上传不正常,如需文档,可联系微信:1017429387 目录 1 安装... 4 1.1 配置探针... ...
    Mrhappy_a7eb阅读 6,313评论 0 5
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,810评论 0 38
  • 日志管理1.1 错误日志1.1.1作用记录MySQL工作过程中,状态,警告,报错。。。。数据库启动后自动打开的,存...
    亮仔_c1b5阅读 205评论 0 0
  • 1.错误日志(log_error) 1.1 作用 记录启动\关闭\日常运行过程中,状态信息,警告,错误 1.2 错...
    醉舞经阁半卷书A阅读 395评论 0 0
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    迷月闪星情阅读 10,567评论 0 11