设计下一代基建脚本

第一代基建脚本

目前只有两个基建脚本:

二者共同特点是遵循特定的换班策略,排班表中只说明按照这个策略“换什么”,而没有“怎么换”的部分,据此将maa与mower称为第一代基建脚本。具体来说,maa的换班策略是“定时或手动触发若干次换班,每次换班按照排班表中的具体安排进行”,排班表中是每一班的时间和干员安排;mower的换班策略是“生成跑单和上下班任务,每次执行任务后根据基建的状态继续生成后续任务”,排班表中有主力、替换、宿管、心情设置、肥鸭充能等。

第一代基建脚本以特定的换班策略为核心。开发者将自身的基建认识抽象为一套换班策略,用户遵循换班策略编写排班表。这种做法有其优点:如果开发者自身的理解有先进之处,使用这套策略的用户也能从中获益,排班表的编写也相对简单。例如很多玩家可能“看到红脸就换”或者“随便换”,接触maa后开始思考一天要换几次、每次安排什么干员,慢慢地开始研究组合的安排;很多用户在接触mower后,才了解跑单、工作时间占比等概念。不过,这套“策略优先”的理念也有其缺点:

  1. 换班策略有缺陷。例如使用maa时,如果不同位置的干员工作、休息的周期不同,会导致排班表编写极为不便;mower“同组一起上下班”不适用于自动化,“提高主力的工作时间占比”不适用于鸿雪组;
  2. 可能出现超出设计者预期的情景。例如maa不支持跑单,mower难以处理跃跃、深海、冰酿/刺玫/摩根、少于4个宿舍、跟随鸿雪组切产物、半天跑单等;
  3. 换班策略固定,没有为自动优化留出空间。

第二代基建脚本

第一代基建脚本的根本问题是试图将一套特定的换班策略应用到基建全局。第二代基建脚本构建一套基建换班的框架,将基建中的位置划分为若干区域,允许在不同的区域内应用不同的换班策略,不受某个具体换班策略的限制。具体而言,第二代基建脚本具有以下特点:

通用的换班协议

第一代基建脚本的排班表与对应换班策略绑定,换班策略更新后,排班表也需要进行改动。第二代基建脚本分离了换班策略的实现与应用,用户在排班表中指明某个区域应使用的具体换班策略。这样,一方面,天然地保持了对以往排班表的兼容;另一方面,通过实现新的换班策略和优化已有的换班策略,留出了发展的空间。脚本适用的范围也更为广泛:用户在全部区域上选择定时换班策略,就能实现类似maa的效果;在全部区域上选择动态换班策略,就能实现类似mower的效果;在不同区域上选择不同的换班策略,通过组合实现单一策略无法达到的效果。

工作与休息分离

不同的换班策略对于心情恢复的要求是不一样的。例如,定时换班策略要求在指定时间前,将特定干员的心情恢复至特定值以上;动态换班策略的要求则是心情恢复越快越好。换班的时间与安排不再由单一因素主导,而是受多种因素共同影响。为解决这一问题,我们采取工作与休息相分离的设计,通过工作模块与休息模块间的协商,解决基建排班过程中的冲突。

工作模块负责安排干员上班,向休息模块提出休息的请求。休息模块对宿舍进行管理,处理工作模块提出的请求。如果能够满足请求,就根据两个模块各自的安排进行排班;否则休息模块拒绝工作模块,工作模块再进行新的安排。当干员休息完成时,休息模块通知工作模块,后者再改变排班。

虚拟的基建状态

工作模块与休息模块沟通时,难免出现反复协商的过程。然而,反复协商不意味着同步地操作基建。脚本需要摆脱对真实基建的依赖,基于虚拟的基建状态进行推演。这不仅有利于基建操作的提速,也方便对代码进行自动化的集成测试,而且是将排班功能接入基建模拟器的基础要求。

提升自动化水平

提升自动化水平,就是更少地添加具体约束,从直接指定“怎样做”变为提出“要怎样”的要求,由脚本自动地进行安排。

第一代基建脚本为了便于理解和实现,往往进行不必要、甚至错误的假设与约束,没有为自动决策留出空间。对全局生效的换班策略进行“放宽”,也难以控制整套换班策略的复杂程度。

在第二代基建脚本的框架下,提出具体的假设和约束的并不是框架本身,而是具体的功能逻辑,例如某个区域上换班协议,或者休息模块的逻辑。这样一来,提升整体的自动化水平就等于提升具体功能模块的自动化水平,框架本身不仅不会限制自动优化的空间,反而把笼统、模糊的全局优化转化为针对具体模块的功能改进,形成了一条目标清晰、切实可行的发展路线。

4 个赞