护镖:数据库版乱入算法
在之前首先感谢Maper提供了地名验证相关的算法,oolong提高721乱码处理的一些想法,Killunix提供了PKUXKX的地图数据库和地图转换的一些想法,本算法地图数据库来源于721自动生成的Map数据库加工而成,加工方法是通过Oracle的统计函数将邻居的竖列变成了Zmud 721的横列列表形式,方便将邻居使用Zmud 721的列表进行直接处理。本算法仅在测试环境进行功能测试,未做过完整任务,使用请谨慎。另外本算法用到了ADO,所以如果Zmud
721不支持Com的话,请安装Windows相关插件,具体安装办法请查找Zmud帮助
本人想法就是首先每次行走的时候都要验证地名和预定义的路线当前位置地名是否一致,如果不一致则进行重定位,第二种情况是只要乱入发生直接进
行位置重定位。
【可以通过本脚本对我之前发布的机器人进行升级,不过加工后的地图数据库,默认参数中的路线的ID定义hbnum_*,路线中地点的区域定义hbzone_*
需要自己根据自己的地图数据库添加,附件提供演示的加工后的地图数据库模板和通过ORACLE加工的加工语句:
select objectid,objectname,substr(relateobject,2,length(relateobject)-1) relateobject,objectdesc,zoneid,zonename
from (
select objectid, max(objectname) objectname,max(sys_connect_by_path(relateobjectid, '|')) relateobject,
max(objectdesc) objectdesc,max(zoneid) zoneid,max(zonename) zonename
from (select objectid, objectname,relateobjectid, objectdesc,zoneid,zonename,row_number() over(PARTITION BY objectid ORDER BY relateobjectid) l_robj
from world_map)
start with l_robj=1
connect by objectid = prior objectid and prior l_robj+1 = l_robj
group by objectid)
order by objectid
】
下面就是核心的重定位脚本:
//本批处理为行走出错重定位批处理,不管何种情况出错首先遍历整个任务路线地点和当前地点匹配,只要地名匹配成功并且方向匹配成功的
//情况下距离当前出错位置最近的一个地点为本任务正确地点,如果遍历任务路线未找到的情况,接下来根据乱入和非乱入有两种算法,如果
//是非乱入走到非路线定义地点则根据当前任务地点的邻居和本地地点匹配,只要地名匹配上则取反方向路径返回主线路,如果是乱入走到非
//路线定义地点则根据当地地点的邻居寻找在主线路上或者上一个乱入地点的匹配值,匹配上则返回到正确线路上(如果是二次乱入则下一次
//由于标志重置成REDIR-重定位不能使用乱入模式进行定位,这方面算法需要测试)
#if @error_path_flag!="ERROR" {#sa 护镖任务:发现位置错误,正确位置:@locate_vdesc与目前位置:@locate_desc不一致,请等待重定位}
#va loopb ""
#va MapRset %comcreate( "ADODB.Recordset")
#loop %numitems( @hbnum_runtime) {#if %i=1 {#va MapQuery %concat( "select objectname,direct,objectid from objectrelation where objectid in (", %item( @hbnum_runtime, %i))} {#va MapQuery %concat( %concat( @MapQuery, ","), %item( @hbnum_runtime, %i))}}
#va MapQuery %concat( @MapQuery, ")")
#CALL @MapRset.Open(@MapQuery,@MapConnStr,2)
#CALL @MapRset.MoveFirst
#WHILE (not @MapRset.eof) {
#if @MapRset.fields(0).value=%t1 {
#va locate_vdesc @MapRset.fields(1).value
#va loopa 0
#loop %numitems( @locate_directlist) {#if %ismember( %item( @locate_directlist, %i), @locate_vdesc)=0 {#va loopa 1}}
#if @loopa=0 {#va loopb %push( @MapRset.fields(2).value, @loopb)}
}
#CALL @MapRset.MoveNext
}
#call @MapRset.close
#va MapRset ""
#show @loopb
#if %numitems( @loopb)>=1 {
#if %numitems( @loopb)>1 {
#va loopa 0
#va loopc 0
#loop %numitems( @loopb) {
#if @loopa=0 {
#va loopa %abs( %ismember( %item( @loopb, %i), @hbnum_runtime)-@locate_pathid+1)
#va loopc %item( @loopb, %i)
} {
#if %abs( %ismember( %item( @loopb, %i), @hbnum_runtime)-@locate_pathid+1)<@loopa {
#va loopa %abs( %ismember( %item( @loopb, %i), @hbnum_runtime)-@locate_pathid+1)
#va loopc %item( @loopb, %i)
}
}
}
#va loopb @loopc
}
#va locate_pathid %eval( %ismember( @loopb, @hbnum_runtime) +1)
#sa 护镖任务:重定位成功
%item( @hbcmd_runtime, @locate_pathid)
#alarm check_locate {+2} {#sa 护镖任务:位置检查}
} {
#if @error_path_flag="ERROR" {
#va error_locate_buf ""
#va MapQuery %concat( %concat( "select objectname,objectid,relateobject,direct from objectrelation where zoneid in (", %item( @hbzone_runtime, %eval( @locate_pathid-1))), ")")
#va MapRset %comcreate( "ADODB.Recordset")
#CALL @MapRset.Open(@MapQuery,@MapConnStr,2)
#CALL @MapRset.MoveFirst
#va loopb ""
#WHILE (not @MapRset.eof) {
#if (@MapRset.Fields(0).value=%t1 and %abs( %len( @MapRset.Fields(0).value)-%len( %t1))<=1) {
#va loopa 0
#va loopc %numitems( @loopb)
#loop %numitems( @locate_directlist) {#if %ismember( %item( @locate_directlist, %i), @MapRset.Fields(3).value)=0 {#va loopa 1}}
#if @loopa=0 {
#loop %numitems( @MapRset.Fields(2).value) {#if %ismember( %item( @MapRset.Fields(2).value, %i), @hbnum_runtime)>0 {#va loopb %push( %item( @MapRset.Fields(3).value, %i), @loopb)}}
#if @loopb="" {#loop %numitems( @MapRset.Fields(2).value) {#if %ismember( %item( @MapRset.Fields(2).value, %i), @error_locate_list)>0 {#va loopb %push( %item( @MapRset.Fields(3).value, %i), @loopb)}}}
#if %numitems( @loopb)>@loopc {#va error_locate_buf %push( @MapRset.Fields(1).value, @error_locate_buf)}
}
}
#Call @MapRset.MoveNext
}
#Call @MapRset.close
#va MapRset ""
#if %numitems( @loopb)>=1 {
#exec gan che to %item( @loopb, 1)
#va error_locate_list %push( %item( @error_locate_buf, 1), @error_locate_list)
#if %numitems( @error_locate_buf)>1 {#echo 护镖任务:乱入返回路线识别可能有问题!查到多个地点符合要求}
#sa 护镖任务:乱入返回主线路
#va error_path_flag REDIR
}
} {
#va MapQuery %concat( "select relateobject,direct,relateobjname from objectrelation where objectid=", %item( @hbnum_runtime, %eval( @locate_pathid-1)))
#va MapRset %comcreate( "ADODB.Recordset")
#CALL @MapRset.Open(@MapQuery,@MapConnStr,2)
#CALL @MapRset.MoveFirst
#va locate_vdesc @MapRset.fields(0).value
#va loopb ""
#loop %numitems( @locate_vdesc) {#if %t1=%item( @MapRset.fields(2).value, %i) {#va loopb %push( %item( @MapRset.fields(1).value, %i), @loopb)}}
#sus check_locate
#if %numitems( @loopb)>=1 {
#exec gan che to %item( @mirror_direct_type, %ismember( %item( @loopb, 1), @direct_type))
#sa 护镖任务:返回主线路
} {
#sa 护镖任务:路线识别出错,请手工回到主线路然后重启机器人
#va error_path_flag ERROR
}
#call @MapRset.close
#va MapRset ""
}
}
算法相关的一些变量定义:
#CLASS {任务|护镖任务|公共变量|系统变量|运行参数}
#ALIAS hb_next {#t+ 行走;%item( @hbcmd_runtime, @locate_pathid)}
#VAR quest_minute {1162}
#VAR quest_num {13}
#VAR hb_path {yuewangmu}
#VAR owner {岳王墓墓前广场包打听}
#VAR target {墓前广场}
#VAR huoji {龚冕扈}
#VAR quest_id {19}
#VAR hb_target {墓前广场}
#VAR target_pathid {20}
#VAR hbdesc_runtime {福威镖局|西大街|西大街|中央广场|东大街|东大街|东大街|东门|大驿道|大驿道|山路|山路|嘉兴城|嘉兴南门|山路|小道|小道|墓前小道|墓前小道|墓前广场|岳飞墓|墓边小道|墓后U地}
#VAR hbcmd_runtime {gn|gn|ge|ge|ge|ge|ge|ge|ge|ge|gse|gs|ge|gs|gs|ge|gn|ge|gne|gn|gn|gnw|gne}
#VAR hbdesc_nums {23}
#VAR locate_pathid {6}
#VAR locate_desc {【闲聊】小希(Littlexi):刚发现是芸豆-}
#VAR locate_directlist {up|west}
#VAR error_path_flag {REDIR}
#VAR error_pathid {3}
#VAR locate_start_pathid {9}
#VAR loopa {4}
#VAR loopb {}
#VAR loopc {6}
#VAR check_directlist {east|northwest}
#VAR MapConnStr {Provider=Microsoft.Jet.OLEDB.4.0;Data Source=pkuxkx/WorldMap.mdb}
#VAR MapRset {}
#VAR MapQuery {select relateobject,direct,relateobjname from objectrelation where objectid=6}
#VAR hbnum_runtime {53|3|4|5|6|7|8|9|769|768|651|652|653|654|691|692|693|694|695|696|697|698|699}
#VAR locate_vdesc {5|7|70|71|72}
#VAR hbzone_runtime {1|1|1|1|1|1|1|1,10|1,10,52|10|10,16|10,18|10,18|18|18,19,22|18,19|19|19|19|19|19|19|19}
#VAR error_locate_buf {}
#VAR error_locate_list {}
#CLASS 0
[ 本帖最后由 seagate 于 2009-12-17 10:56 AM 编辑 ] 好想法,工作量挺大 我已经做完了,晚上对将算法更新到自己的机器人就好了,工作量没办法,基本上花了一周时间吧。我自己晚上整合以后测试一下有没有问题。主要是自己对地图函数不熟悉,而且个人感觉这些地图函数使用起来还不如自己用数据库直接折腾呢,反正就那些玩意也不复杂。下一步工作是解决区域搜索问题,这个算法实现上还没有很好的头绪,关键是在Zmud实现递归比较麻烦,否则能实现递归就很简单了,做一个5层递归就能解决所有问题。想想怎么实现递归比较好一点。 你搞得实在太复杂了。
巫师说不准公布超过5个房间以上的地图数据,你怎么把这个给放出来了
[ 本帖最后由 killunix 于 2009-12-17 10:26 AM 编辑 ] 呃。。。。。附件的数据库里有地图数据?清空吧
这里可以讨论思路,但禁止共享地图数据
我暂时把附件去掉了,清空了附件中的地图数据后再上传一个吧 上传一个1房间的地图吧,样本里面其实也没有几个房间,看着大是因为没有对数据库进行缩小,用的不熟,这把好了。上次上传的附件就是删节版,只是比5个房间多一点而已。 搞得复杂主要是因为乱入问题,乱入要考虑跨区域乱入所以设定比较多一点,如果区域递归搜索也要考虑边境问题,这都比较麻烦。【不过似乎现在交货点有几个存在边境问题的?嘉兴有可能跑到别的区域,桃源县的任务也有可能】 地图区域的问题我也纳闷,很多任务告诉的地点都不一样,比如说嘉兴的无名谷底,有时候就说是泉州的无名谷底,桃园县这一块也一样,伙计长跑到杀手帮那里去,都不知怎么分区域合理,可能需要经验多的玩家才能分的合理,有一次嘉兴钱庄的伙计居然跑到苏州南门去了,怎么也找不到。 这种情况就需要跨区域搜索了,局限在本区域肯定有问题。关键是要知道搜索几个区域,我想法是不预设路线,不用遍历算法,直接用数据库递归产生路径跑一边用多行触发,触发成功就OK了,但是有一个问题就是碰到伙计是名字会乱码还是不好解决,有一个办法是给任务的时候把伙计名字存到一个文本文件去,等到区域搜索的时候再从文本文件读出伙计名字和Trigger中的伙计名字进行匹配。
我发现Zmud 721最大的问题就是乱码,没有乱码很多代码都不需要那么复杂,问题简单很多,有了乱码会衍生无数问题,代码复杂度增加好几倍。 牛人处处有,北侠特别多