newtonerdai 发表于 2020-7-2 21:14:26

[UP1.5] 利用AI检测玩家/游戏暂停了多长时间

本帖最后由 newtonerdai 于 2020-7-2 22:11 编辑

祖安前言

哦?你问我为什么闲的蛋疼,要检测帝国游戏暂停了多久?!

因为!TM的!老是有玩家不仔细看战役任务栏里的信息,一顿乱操作下来一脸懵逼,回来怒骂作者一通。


所以劳资必须要让这些盲人玩家,先仔细看完任务栏,再给继续操作!

(咳,或者也可以给予一些醒目的提示,让玩家在热血正酣的战斗期间查看新出的任务。)


祖传过渡段
现在Userpatch 1.5的AI已经完全可以做到检测游戏暂停了多久!且看我的慢慢道来↓↓↓


原理讲解
我们需要的语句:up-get-precise-time(直译:获取精确时间)精确到ms。


设计思路:
0、时间戳是什么?
日常生活使用Unix时间戳,如 1593682976434 (ms) = 2020-07-02 17:42:56.434。你可以理解为现实世界的时间转化为一串数字,就是时间戳。不过帝国里时间戳的0点与现实世界里的不是相同的,但时间流速是相同的,大家理解这个概念就行。
(注:下图是用简单的代码获取到的决定版时间戳,具体代码就不放出来了,大家看看效果即可)


1、【核心原理】
我们让AI检测这一瞬间的时间戳,储存为time-1;再在下一瞬间检测时间戳,储存为time-2。
二者之差不就是现实世界经过的时间了吗?其代表的含义不就是【在连续两次AI检测之间,现实世界经过的时间】了吗?
那么,如果玩家暂停了5秒,那么时间戳之差必然>5,因为游戏暂停期间AI的语句也是直接暂停的。

(核心原理示意图。上图中,5175ms = 5000ms + 350ms÷2)

依照上面这个思路,我写了段简单的减法代码,其运行效果如下↓↓↓

(当然,这段代码即使不放出来,也不影响各位的理解。不妨先按捺住好奇心,继续看下去↓↓)

2、不过,倒是也不需要我们再自己做一次减法,因为up-get-precise-time这个语句是自带减法的,就很方便。

3、所以我们只需不断获取上一瞬间的时间戳,然后在下一瞬间用这个语句获取现实时间差,把时间差逐个累加起来,最后判断累计暂停时间是否满足需求即可。


那么,上菜!让我把详细做法端上来吧!
完整做法
触发部分:


触发0||初始开启不循环
    效果0||发送AI触发器(旧称事件/信号) 10号
    效果1||显示指南99999秒“请认真阅读任务栏……输入99可跳过”

触发1||初始开启不循环
    条件0||收到AI信号10号
    效果0||显示指南“看来你已了解信息,现在正式开始游戏吧!”
    效果1||应答AI信号10号

触发2||初始开启不循环
    条件0||收到AI信号11号
    效果0||显示指南“看来你已了解信息,现在正式开始游戏吧!”
    效果1||应答AI信号11号


当然,触发1 & 触发2、AI信号10号 & 11号的功能相同,是可以合并的。具体你们可以自己设计。

AI部分:


;///////////////////////////////////////////////////////////
;//                   暂停时长检测模块                  //
;///////////////////////////////////////////////////////////

(defconst time-1 100)       ;用于目标变量编号。储存前一次检测的时间戳。
(defconst time-2 101)       ;用于目标变量编号。储存两次检测的现实时间差。
(defconst time-sum 102)   ;用于目标变量编号。储存累计暂停时长。
(defconst cheak-switch 103) ;用于目标变量编号。储存模块的开关状态。
(defconst ON 1)         ;用于常数。代表模块开启。
(defconst OFF 0)      ;用于常数。代表模块关闭。

;———————— 模块的激活与初始化 ————————
;收到10号事件后,初始化模块。
(defrule
;↓↓ 收到触发的10号事件后,模块激活,并初始化。(注意,这条规则有自锁,并不会持续执行)
    (event-detected trigger 10)
=>
;↓↓ 模块开始时,获取当前时间戳作为time-1。
;   如果不这么做,那么接下来第一次得到的 time-2 将为:(时间戳+1),显然太大了,会被误判为暂停的。
    (up-get-precise-time 0 time-1)
    ;(up-chat-data-to-all "当前时间戳 = %d" g: time-1)
;↓↓ 启动“暂停时长检测”模块。
    (set-goal cheak-switch ON)
;↓↓ 启动模块时,将累计暂停时长归零。
    (set-goal time-sum 0)
;↓↓ 注销10号事件,使其可以重复使用。
    (acknowledge-event trigger 10)
)

;—————————— 获取部分 ——————————
;在检测启动期间,不断获取两次检测之间经过的现实时间差。
(defrule
    (goal cheak-switch ON)
=>
;↓↓ 获取现实时间差,储存到time-2里。
    (up-get-precise-time time-1 time-2)
;↓↓ 完事后,储存本次检测的时间戳,用于下次检测。
    (up-get-precise-time 0 time-1)
;↓↓ 向所有人报告time-1的数值,用于检查。
    ;(up-chat-data-to-all "当前时间戳 = %d" g: time-1)
;↓↓ 向所有人报告time-2的数值,用于检查。
    ;(up-chat-data-to-all "距上次检测经过了 %d ms"g: time-2)
)

;—————————— 累加部分 ——————————
;为了防止AI遍历间隔的干扰,同时也考虑到玩家阅读任务应该会久一点,我们应该只累加2秒以上的暂停时长。
(defrule
    (goal cheak-switch ON)
    (up-compare-goal time-2 c:> 2000)
=>
;↓↓ 把time-2加到time-sum里。
    (up-modify-goal time-sum g:+ time-2)
)

;—————————— 模块的关闭 ——————————
;模块启动期间,如果time-sum > 5000 ms,就判定玩家暂停了5秒钟。告知触发,同时暂时关闭“暂停时长检测”模块。
(defrule
    (goal cheak-switch ON)
    (up-compare-goal time-sum c:> 5000)
=>
;↓↓ 向所有人报告,用于检查。
    (chat-to-all "【暂停了 5 秒以上】")
;↓↓ 发送10号AI信号,告知触发。(注:AI信号与AI事件是互相独立的)
    (set-signal 10)
;↓↓ 关闭“暂停时长检测”模块。
    (set-goal cheak-switch OFF)
)

;无论何时,只要玩家 1 发送数字“99”,都会关闭“暂停时长检测”模块。同时告知触发。输入99表示玩家很熟悉了,不想看任务栏而是直接跳过。
(defrule
    (taunt-detected 1 99)
=>
    (set-goal cheak-switch OFF)
;↓↓ 发送10号AI信号,告知触发。
    (set-signal 11)
;↓↓ 应答这个数字嘲弄,使其可循环使用。
    (acknowledge-taunt 1 99)
)



运行效果如下:
开局提示:


暂停累计5秒以上:


输入99跳过:



我顺便测了一下DE的AI遍历间隔:
游戏负荷极小(比如就几十行代码+一两个单位)的情况下,基本稳定在0.350~0.400现实秒,偶尔会低或高,无论是什么游戏速度。

另外,UP1.5的似乎也是这样。

troytroytroy 发表于 2020-7-2 23:17:12

Problem unsolved.
玩家在這種情況下有可能只是暫停10秒、打開外交選項10秒、打開遊戲設定10秒、打開科技樹10秒等。

就是沒有打開任務欄。{:164:}

要對付盲人玩家,你可以有100種方法,但他們會有200種盲法。

blazefires 发表于 2020-7-3 02:32:52

本帖最后由 blazefires 于 2020-7-3 02:35 编辑

多人游戏模式和延迟也都会影响结果
单机60FPS下都是约0.4秒一次

源六郎义经 发表于 2020-7-5 11:52:58

troytroytroy 发表于 2020-7-2 23:17
Problem unsolved.
玩家在這種情況下有可能只是暫停10秒、打開外交選項10秒、打開遊戲設定10秒、打開科技樹 ...

甚至可能不熟悉文明特性,现翻科技树。

期悦 发表于 2020-7-11 18:30:01

如果为了表现有配音的对话,让他们不因为游戏速度差异而导致配音交叠或间隔大的问题,这个东西能解决吗?

newtonerdai 发表于 2020-7-12 00:44:52

本帖最后由 newtonerdai 于 2020-7-12 00:46 编辑

HudsonLee 发表于 2020-7-11 18:30
如果为了表现有配音的对话,让他们不因为游戏速度差异而导致配音交叠或间隔大的问题,这个东西能解决吗? ...
检测游戏速度的方法,我记得论坛有一个贴子讲过。你可以去搜搜,我得先下线了。

其实AI是可以获取当前游戏时间的。

理论上,通过对比游戏时间差 和 现实时间差,是可以获知游戏速度的

期悦 发表于 2020-7-24 22:43:04

本帖最后由 HudsonLee 于 2020-7-24 22:48 编辑

测试了一下,检测暂停次数转换为变量
https://www.bilibili.com/video/bv1wz4y1Q7d3
页: [1]
查看完整版本: [UP1.5] 利用AI检测玩家/游戏暂停了多长时间