jarlyyn
发表于 2015-4-22 10:58:15
wait.lua是MUSH自带的一个协程建立工具而已。其核心是还是应用lua自身的协程函数 coroutine.create()来实现 ...
littleknife 发表于 2015-4-22 09:45 AM http://pkuxkx.com/forum/images/common/back.gif
感觉要做异步至少需要一个async那样的库。不然整个逻辑都会乱。
现在的想法是做一个类似现在前端框架(knockout.js/angular.js)那样做一个数据绑定。
触发器直接修改数据,数据直接影响触发。
写一个控制器程序根据状态判断需要进行的处理。
cmud
发表于 2015-4-22 11:08:55
我用python实现的协程方式,所有的函数都是一个独立的协程,可以随意拼接。
渡江过程就是这样:
while循环
渡江函数
渡江成功,跳出循环。
渡江失败
打坐函数
ltblue
发表于 2015-4-22 12:01:50
wait.lua是MUSH自带的一个协程建立工具而已。其核心是还是应用lua自身的协程函数 coroutine.create()来实现 ...
littleknife 发表于 2015-4-22 09:45 AM http://pkuxkx.com/forum/images/common/back.gif
local l,w=wait.regexp("^[> |]*船来了|^[> |]*设定环境变量 duchuan=='没来'")
if l~=nil and string.find(l,"没来") then 没来干什么事情 end
if l~=nil and string.find(l,"船来了") then 来船了干什么事情 end。
这个是判断船来没来的,但是只这一个无法判断打坐是否完成。
举例子:
船没来的情况下,我打坐的同时等船
如果出现船来的字样,打坐停止,上船
如果出现打坐完一次的字样,那么继续打坐
这是zmud的触发模式
用wait.regexp,就得用两个协程来处理这个过程,而由于游戏中内容复杂,比如这时候抢信的杀手来了,又或者有人pk你,又或者有捣乱的npc(比如夏雪宜之类)的来偷你东西,这些难道分别都用一个协程处理吗?
如果这样,相当于zmud里每有一个触发类,就有一个协程甚至多个协程对应?
不明白,为什么用wait写的东西会“变成了任务流程的代码罗列了。”
请教
ltblue
发表于 2015-4-22 14:14:45
本帖最后由 ltblue 于 2015-4-22 02:16 PM 编辑
wait.lua是MUSH自带的一个协程建立工具而已。其核心是还是应用lua自身的协程函数 coroutine.create()来实现 ...
littleknife 发表于 2015-4-22 09:45 AM http://pkuxkx.com/forum/images/common/back.gif
我尝试写一下你说的渡河的代码,你帮忙看看是不是这么个意思
boatcome=0
function duhe()
while true do
Send("yell boat")
Send("enter")
local l,w=wait.regexp("进入渡船了" | "江上传来等一等的声音")
if l and string.find(l,"进入渡船了") then
return "进入渡船"
end
if l and string.find(l,"江上传来等一等的声音") then
boatcome=0
wait.mark(
function()
dazuo()
end
)
wait.regexp("船来了")
boatcome=1
coroutine.yield
end
end
end
function dazuo()
while true do
if boatcomd=0 then
Send("dazuo 1000")
wait.regexp("打坐结束")
else
return coroutine.resume(duhe)--这里本身存在一个duhe协程,协程中调用了duhe函数
end
end
end
littleknife
发表于 2015-4-22 17:36:46
boatcome=0
function duhe()
wait.mark(function()
if boatcome==0 then do_dazuo() end-----等待过程中打坐开始。
while true do
Send("yell boat;enter;set duchuan notEnter")
local l,w=wait.regexp('^(> |).*渡船\\w*" |^(> |)设定环境变数:no_more = \"notEnter\"')
if l and string.find(l,"渡船") then
boatcome==1
local Here_DOC=[[
说明:这里可以空着。就是进入渡船。其实就是状态判定一下。(就是判定自己是不是在船上)
判断在船上,就返回一个状态参数。
]]
repeat
local l=wait.regexp("到地方了的触发",1)
until l
local outBoat=[[这里写到达地方了的动作代码,比如继续走等等。]]
return
end
if l and string.find(l,"notEnter") then
boatcome=0
local Here_DOC=[[
说明:这里也可以空着。就是确认了没在船上。其实就是状态判定一下。(就是判定自己是不是在船上)
判断不在船上,就返回一个状态参数。
]]
return
end
end
end)
end
function do_dazuo()
wait.mark(function()
while true do
if boatcomd==0 then
Send("dazuo 100")
wait.regexp("打坐结束")
else
break
end
end
end)
end
littleknife
发表于 2015-4-22 17:38:06
本帖最后由 littleknife 于 2015-4-22 05:55 PM 编辑
这里用到了两个协程。一个是主渡河函数的协程。一个是打坐的自己的协程。
其核心思路就是渡河过程中打坐独立于渡河,只是依据状态的分析来停止打坐。
所谓的流程代码罗列,就是在总配置文件里只有一个总的wait.make(function() ....end)框架。其他所有的任务函数,也就是机器人都是直接的写代码。流程到哪里里就写什么代码。
比如,一般任务流程可以这样参考:function DO_JOB()
ask npc about job
wait.time(1)-----这里因为总配置里有框架,所以都是可以通过的。
walkgo()
do_it()
goback()
finish_job()
end
也就是说,状态的判断是必不可少的。无论你做什么机器,除非你是单纯的触发--命令的zmud模式。当然zmud也能做状态的判定来编机器。
做成一个状态模块,也就是状态机来判断自身的状态是我认为较为合理的综合机器人的思路。
littleknife
发表于 2015-4-22 18:02:51
回复 92# cmud
个人认为最理想的机器,并不是协程的随意引用,因为那会造成大量的回调函数的使用,并不利于逻辑清晰,也不利于机器的更新和阅读整理。尊重任务流程的顺序,以程序代码基本的顺序逻辑执行反而显得清晰、易懂。需要协程的时候在不时的加入它来参入到主程序中即可。
比如,战斗模块。其中对自身状态的判定就可以独立形成一个协程,而战斗模块主程序却不需要独立的协程框架,而是直接融入到主机器模块中即可,因为主机器里是有框架的,可以继承它。
oolong
发表于 2015-4-22 19:47:36
完全听不懂{:7_275:}
ltblue
发表于 2015-4-23 14:14:09
littleknife 发表于 2015-4-22 05:36 PM http://pkuxkx.com/forum/images/common/back.gif
代码有几个问题不懂,请教一下哈
1.
if boatcome==0 then
do_dazuo()
end-----等待过程中打坐开始。
在没有叫船的情况下,直接就先打坐?又或者这个协程不会立即执行?
我理解渡江的过程应该是:
先叫船,船没到的前提下,再打坐等。这个逻辑我没看懂
2.
('^(> |).*渡船\\w*" |^(> |)设定环境变数:no_more = \"notEnter\"')
单引号套双引号的目的是什么呢?没懂两者的关系,如果我写,大概会写成
(”^(> |).*渡船\\w*|^(> |)设定环境变数:no_more = \"notEnter\“)
3.
local Here_DOC=和 local outBoat=
这里是改状态吗?如果是改状态,用local的话,这个函数结束了,变量不就释放了吗?不是很懂
4.
repeat
local l=wait.regexp("到地方了的触发",1)
until l
这里为什么要加repeat和until l呢?直接把1这个参数去掉不行吗?就是直接写
local l=wait.regexp("到地方了的触发")不行吗?
5.
if l and string.find(l,"notEnter") then
boatcome=0
local Here_DOC=--说明:这里也可以空着。就是确认了没在船上。其实就是状态判定一下。(就是判定自己是不是在船上)判断不在船上,就返回一个状态参数。
return
end
这里是指没进去船,然后等的情况吧?状态修改为什么用local的问题我刚才提了,为什么这里要return呢?没进去船,不是应该等船来吗?return之后整个函数不就结束了吗?
如果加的话,是不是应该写个wait.regexp(“船来了”)比较好呢?
还是不懂
littleknife
发表于 2015-4-23 16:56:05
本帖最后由 littleknife 于 2015-4-23 05:00 PM 编辑
代码有几个问题不懂,请教一下哈
1.
if boatcome==0 then
do_dazuo()
end-----等待过程中打坐开始。
在没有叫船的情况下,直接就先打坐?又或者这个协程不会立即执行?
我理解渡江的过程应该是:
先叫船,船没到的前提下,再打坐等。这个逻辑我没看懂
1. 因为do_dazuo()是独立协程,故此执行到这里程序不会停止,会继续向下执行主程序。
2. 至于是先叫船在打坐还是船到了打坐,这里可以用检查状态的模块来完成。我这里的意思是叫船开始的时候就反馈回去信息:可以打坐。
2.
('^(> |).*渡船\\w*" |^(> |)设定环境变数:no_more = \"notEnter\"')
单引号套双引号的目的是什么呢?没懂两者的关系,如果我写,大概会写成
(”^(> |).*渡船\\w*|^(> |)设定环境变数:no_more = \"notEnter\“)
单引号和双引号是一个意思。为什么用单引号因为环境变量的设定后面有个双引号,为了看清楚故此外边用的是单引号。
3.
local Here_DOC=和 local outBoat=
这里是改状态吗?如果是改状态,用local的话,这个函数结束了,变量不就释放了吗?不是很懂
这里的变量Here_DOC只是个说明变量,并没有意义。这里的意思是在这个位置写入你需要的代码。替换整个local Here_DOC部分的意思。
另外,local的作用范围是函数体范围,故若local写在哪里,就会作用到哪里。
4.
repeat
local l=wait.regexp("到地方了的触发",1)
until l
这里为什么要加repeat和until l呢?直接把1这个参数去掉不行吗?就是直接写
local l=wait.regexp("到地方了的触发")不行吗?
可以,但是若不触发,也就是服务端没有触发语句出现,程序将会停在那里而不执行下去,也就是wait的机制。这里1的意思是1秒后若没有触发文字则这个触发失效,继续执行下面的代码。
repeat ... until 和 while true do ... end都是循环,依据喜好写即可。
5.
if l and string.find(l,"notEnter") then
boatcome=0
local Here_DOC=--说明:这里也可以空着。就是确认了没在船上。其实就是状态判定一下。(就是判定自己是不是在船上)判断不在船上,就返回一个状态参数。
return
end
这里是指没进去船,然后等的情况吧?状态修改为什么用local的问题我刚才提了,为什么这里要return呢?没进去船,不是应该等船来吗?return之后整个函数不就结束了吗?
如果加的话,是不是应该写个wait.regexp(“船来了”)比较好呢?
还是不懂
这里的l指触发行,string.find(l,)就是触发行里出现了什么符号的意思。之所以用return的意思是退出循环,返回函数值。就是函数结束了的意思。
你的最后的话我理解为对wait.lua的机制还是没有理解透彻。应仔细阅读wait.lua文件。
注意:wait.regexp这个方法的意思是等待触发行出现,若没有对应触发文字,则程序会暂停在这里。若有失效时间设定,则过了失效时间后执行下面的程序代码。
页:
1
2
3
4
5
6
7
8
9
[10]
11
12