|
首先,我要声明一下,虽然代码还没有写,不过我绝不是纸上谈兵的,以下算法都是可实现的,代码有空再完成呵呵~
以下算法包括了吃药,武功选择,走位以及最新的特殊状态和特殊武功等等的处理,只有文字,不知道各位代码狂人能否融入代码中,呵呵~
首先说说整个算法的基本价值判定,也就是AutoBattle中各种判断的基本流程
在我的代码中,AI的价值观为:
自保>杀人>加持>伤人>休息
自保,顾名思义就是保持自己不死,吃药,医疗,或者使用特殊武学治疗等都算,这是放在所有事情的第一位,相信这是没有什么悬念的,对了,还有逃跑,因为休息可以恢复一部分生命内力等,所以逃跑也算是自保,有一些特殊状况,后面再说
如果吃药医疗等判断为false,那么AI将会判断是否存在可以杀掉的敌人,然后杀之,解决敌人(我方?)的有生力量是自保之后的第二件事情,而战斗判断复杂,同样后面再说
加持,也就是对友军施加正面状态,相信这是一个让AI设计者头痛的东西,往往不知道放在哪里好,对吧?在判断不能减少敌人数量之后,加强自我属性状态往往是一个比纯粹伤害敌军更佳的选择
伤人,就是使用武功,可能你会发现,伤人跟杀人同样使用武功,那是否意味着要重复进行武功判断呢?看下面就知道
休息就不说了,直白点说,什么都做不成就会休息
有了这么一个大的方向,剩下的就是把判断不断地细分的一个过程了~AI说起来神秘,其实也就是处理一堆变量的假设和循环罢了
然后,如何才能做出一个比较聪明的AI呢?如果只是跟以前的一样,那这AI就没有必要写了
我的变革有如下几点:
1,使用药品对象从自我变为友军
这个在代码中是很好实现的,我刚接触复刻源码时就做出来了这么个系统,只是加几行代码罢了。就是改了一下case mode后面的~
procedure BattleMenuItem(bnum: integer);
var
i, rnum, inum, mode, step: integer;
str: widestring;
begin
if MenuItem then
begin
inum := CurItem;
rnum := brole[bnum].rnum;
mode := Ritem[inum].ItemType;
case mode of
3: //战场吃药系统强化,突破只给自己吃药的限制,药物可以作用于队友
begin
CalCanSelect(bnum,1);
step:=2;
if ( SelectAim(bnum, step) ) then //选定某个坐标的角色
begin
for i:=0 to (BRoleAmount-1) do //在战场上搜索所有人物对照
begin
if (BRole[i].X = Ax ) and (BRole[i].Y =Ay) and (BRole[i].Team=0) then //坐标上人物非空,为队友
begin
EatOneItem(BRole[i].rnum, inum);
instruct_32(inum, -1);
Brole[bnum].Acted := 1;
waitanykey;
end;
end;
end;
end;
4:
begin
UseHiddenWeapen(bnum, inum);
end;
end;
end;
end;
然后在AI中,我的建议是用等级判断,每个角色行动前,先判断可使用药品范围内(如果药品范围是离自身两格内,那就是移动格数+2),是否存在需要使用药品的角色,如果存在,并且角色等级比自身要高,则优先给等级高的角色使用药品
例如,一个小兵跟欧阳锋同时被打成红血,然后小兵会给欧阳锋用药,欧阳锋攻击,这改革意义就大了,小兵的存在也只不是充当经验值了
2,记录最高伤害数值和角色
在源码中,单场战斗的数据是不被记录在什么R,D,S之类的文件中的,也就是战斗数据不会影响文件结构,所以为战斗人物加几个变量是很简单的事情
有见及此,我提议为角色加入最高受伤和带来该伤害的攻击者记录,提升AI的智能
不明白怎么回事?
我也举个例子:
例如郭靖一个降龙打欧阳锋(又是他)500,那在欧阳锋的最高受伤纪录就会变成500,攻击者为郭靖的人物编号
如果欧阳锋的生命值少于500的双倍1000,他就会采取吃药等自保行动,而郭靖也成了他攻击的第一顺位目标,这样就不会再被“快马”拉着跑了吧?
同样地,如果他的最高受伤纪录才50,那有1000血的他就没必要神经兮兮地吃药了。
这设计的价值在于更符合效益的吃药和攻击等行为判断,是否好用还是要经过调试,不太好说。
3,对逃跑坐标的记录
所谓的逃跑坐标,就是当角色放弃攻击而选择逃跑(如吃药,休息等)时,的移动坐标
我的设计中,把这坐标放到了所有判断的最前面!
而不同于一般的设计中,当角色逃跑时,才来计算
为什么要如此设计呢?
因为逃跑坐标被应用到了更广的方面来,更聪明的AI走位的实现其实不难
首先说说逃跑坐标是如何决定的吧
对每一个可以移动的格子,判断该格坐标与所有非我方角色的坐标差值的和,最大的那一格的坐标就是逃跑坐标了
如,敌人A的坐标为(1,1),敌人B为(2,3),如果可选择的行动坐标分别为C(1,4)和D(2,5)
那么可得,C与A,B的总距离为0+3+1+1=5,D与A,B总距离为1+4+0+2=7
得到D为逃跑坐标
当然,实际中不可能只有两格可走,不过从这个例子我们可以看出,逃跑坐标简而言之就是离所有敌人相对最远的一格了
记录这一格的好处是很大的,除了吃药跑路等,应用是多方面的,也是例子说明吧~
例子1,假设欧阳锋(呃)的蛤蟆功范围为线5,移动为7,跟敌人的距离为3格,
那欧阳锋坐标为(10,10)的话,敌人坐标为(10,13)
因此,我们可以得到逃跑坐标应该为离敌人最近的一格(10,3),
利用了逃跑坐标后,在攻击时,欧阳锋的AI就不再是一味地接近敌人然后攻击了,他完全可以后退两步,找到一个离逃跑坐标最近,而又让武功触及到敌人的移动坐标(10,8)才进行攻击
也就是说,我们的AI懂得后退攻击了!怎样,比想象中的要简单对吧?
或许有人说,不记录逃跑坐标,临时计算也可以实现啊,这没错,
但是!
如果有10个武功判断呢?这临时计算就要走10次,先把坐标记录了,计算时可以直接代入轻松地找到最佳的走位点,那在效率方面就高了
当然,也有可能是接下来的流程中都没有用到这个坐标,白算了 = =!,不过这样的可能性较小
4,正面状态的判断
正如我上面说的,这玩意往往不知道怎么让AI处理好,因为特殊武功的判断复杂,总不可能一个个去判断吧?难道必须让敌人舍弃特殊武功吗?
这明显是不妥的,因为AI不止用在敌人身上,也要用于我方!
谁也不想见到一按“自动”,AI就瘫痪了不是?
其实说出来一文不值,就是增加武功类型数量,也就是,武功不在局限于拳剑刀特,看到这里,或许有人要喝乌鸦的倒彩了,先别急,看下去先~
我说增加武功类型,不是说要在拳剑刀特后面再加一个什么辅助武功类型,不是!所有武功归类在四基之中在很多mod之中都是必要的,创造一个辅助类那不是变相的束缚吗?
我的建议是,增加不如细化,把四基根据目标分化为对敌武功和对我武功变成8基,甚至再加上全体武功,变成12基
——拳敌,拳我,拳全,剑敌,剑我……
说出来工作量似乎很大,不过就是复制一下代码,然后改一下switch case函数,阵型变量改一下罢了~~我是这么认为的
对于辅助状态的存在,这样的改动是必要的,武功使用时,判断一下人物是否有对我方的武功(总不会有武功杀友军吧?),如果存在,而且我方附近存在不含某某状态的友军,则使用该武功,为友军加持正面状态。
这样很方便是吧?至少比输入特殊武功的编号,然后一个一个的判断来得简单
5,负面状态的选择
两个字,加权~
相比起正面状态,带负面状态的武功判定相对是比较简单的,因为这种武功完全可以看做是普通的伤害性武功,而负面状态则可看作是一个附加的伤害,多调试几次,设置好就结了
如武功A的威力是1000,无效果,武功B是800,但带麻痹,假设设定麻痹的价值等同300伤害
那攻击某敌人时,AI自然会选择武功B,如果敌人已经带有麻痹,则武功A更佳,这没有什么意见吧?
哦,对了,对复数敌人也是一样的,如存在3个敌人,都是正常状态,而且武功一次性可以含盖3个敌人
第一轮攻击,武功A的价值为1000*3=3000,武功B的价值为800*3+300*3=3300,选武功B攻击,两人麻痹
第二轮,武功A价值依然为3000,武功B为800*3+300=2700,则选武功A
这是AI的设计(上)的全部内容,下篇将呈现整个流程(或者我会直接写成代码?)
欢迎各位研究讨论,谢谢
[[i] 本帖最后由 winson7891 于 2009-7-14 08:23 编辑 [/i]] |
|