找回密码
 点一下
查看: 2597|回复: 1

随机属性系统(只有攻击部分)

[复制链接]
发表于 2012-1-13 17:53:54 | 显示全部楼层 |阅读模式
此系统和YDWE的系统存在冲突,我也不知道为什么....
请保证自己有一定的Jass基础
演示地图 Base.w3x (21 KB, 下载次数: 65)
由于暴雪没有提供取余运算符,我们来自己定义一个取余函数(好吧Blizzad.j有这个函数的声明)
我会乱扯的,我只给些思路好了,做完整比较麻烦.
[jass]
function ModuloInteger takes integer dividend, integer divisor returns integer
    local integer modulus = dividend - (dividend / divisor) * divisor
    if (modulus < 0) then
        set modulus = modulus + divisor
    endif
    return modulus
endfunction
[/jass]
对于那些对代码一窍不通的同学可能会认为上面的modulus会等于0,在整数的运算中/操作符会执行舍位,好吧,我得举几个列子
3 / 2 = 1  ,10 / 3 = 3 , 17 / 4 = 4
所以了 3 - ( 3 / 2 ) * 2 = 1  ,10 - ( 10 / 3 ) * 3 = 1, 17 - ( 17 / 4 ) * 4 = 1
事实上,这也是个二进制算法,可以用来做随机属性系统,简单提一下啊(感谢hanyant)
(乱猜的)在N年前,那个技能不能叠加的时代,我们想给单位加上一个0~999之间的任意数值的攻击,也就意味为我们得粘接攻击技能,复制999次,改动999次,用一个数组把这些技能记录下来,接着看看是那个随机数,加上对应的技能,到了技能可叠加的时代,有些地图作者学会了偷懒,他们采取了循环添加 + 1攻击技能给单位来达到自己的目的,但他们忽略了一个问题,这对玩家的电脑是个严峻的挑战,所以说,我们还是要避免叠加,而是通过不同数值的同类技能组合出期望数值.
第一个问题出现了:如何让计算机分析出不同的数值组合
好吧,你可能不明白这个问题,那我做个比方:
假设我们想给单位加6点攻击,那么我们可以给他添加 +2 和  + 4.(那些看过这些的可以跳了),但是............计算机怎么知道把+6 拆成 + 2 和 + 4 ,他又不拥有逻辑能力(尽管递归可以模拟)? ,我们得想把法让计算机知道啊
另外我们想在 + 6 的基础上再 + 2 了,那我们不能再添加 +2 给单位了,他已经有这个技能,
那我们只好删除掉先前的 + 2 和 +4 两个技能,进行重构.也就是说,我们得让计算机能够把一个0`999的随机数给拆开成几个数相加.
而魔兽的触发中从来没有创建一个临时技能的说法,这些+ 2 , +4我们需要预先定义这些基础技能,我们已经越来越接近问题的核心:我们如何预先定义一批作为基础的技能来组合出我们可能要求的任意目标数值
二进制闪亮登场了,不要说你不明白什么是二进制,自己百度去吧
二进制神奇的特性被用于计算机,比如说:
1)只有0和1两个值,便于计算机实现,也便于判断是否添加技能(true,false)
2)每一位代表的权值不同(权值什么的,百度),这也是要定义的基础技能
3)任何一个十进制整数都可以用二进制来表示!(小数是不可以的!)
我想大部分人都已经知道怎么做了
把十进制转成二进制
从低位读取到高位,那一位是1就添加相应的技能(权值)给单位
上面可能有点难懂,嗯哼,打个比方
12转化为2进制就是(1100),左边是最高为,右边是最低位.我们来从右边往左边读数
第一个是0,他对应的权是2的0次幂 1,0为false,所以 + 1的技能不添加给单位
第二个是0,他对应的权是2的1次幂 2,0为false,所以 + 2 的技能不添加给单位
第三个是0,他对应的权是2的2次幂 4 , 1为 true ,所以 + 4的技能添加给单位
第四个是0,他对应的权是2的3次幂 8 , 1为 true ,所以 + 8的技能添加给单位
这样,不就是给单位加了12点攻击力
所以说,我们需要一个转二进制的函数,转出的二进制我们用字符串(string)来表示,我们先来做些准备工作
这个系统将支持从-32767 ~ + 32767的数据,支持负数是有必要的!
我在这里使用的是一个16位的二进制数(我没有采用补码,那样对某些同学老说,有点难了,我自己也不会写求补码的函数)
在计算机中,一般都是最高位用作符号位,0表示是整数,1表示是负数,那么以12为例,他所求得的字符串(string)应该就是:"0000000000001100"函数等下给出,我们先做好预备工作!
我们先要定义基础技能(请使用能自定义物品ID的地图编辑器,或者是让+1的技能ID的最后为大写字母A,这样方便接下来的赋值,先做一个+1的基础技能(手动输入ID,或者让其自增)[连续粘贴]
在这里我使用'FNaA'作为+1的ID,那么依次内推:(依照下表)(好吧,我忘记表的Html写法了...)
(这个是怎么回事了,明明启动失败,却还可以用了....) failed.jpg
table1.jpg
我们还需要做准备,我们需要两个数组来储存这些ID值,ID值是整数,所以我们这样写
[jass]
globals
integer array AiId
integer array BiId
endglobals
[/jass]
我们还需要将这两个数组初始化,定义一个初始化函数
[jass]
function Init_Id_Array takes nothing returns nothing
local integer i = 0
set AiId[0] = 0
set BiId[0] = 0
loop
      exitwhen i > 15
      set AiId[i + 1 ] = 'FNaA' + i
      set BiId[i + 1 ] = 'FNbA' + i
      set  i = i + 1
      //为了某些同学,我的下标从1开始
endloop
endfunction
[/jass]
接下来的就是2进制转换函数!!最重要的部分来了啊!!!
[jass]
function D2B takes integer attack returns string//attack的取值为-32767 ~ + 32767
    local integer index = 15
    local string B = null
    local integer array temp
    if attack > 0 then
        set B = "0" //是正数,最高位置为0
    else
        set attack = 0 - attack
        set B = "1"
    endif
    if attack > 32767 then
        set attack = 32767 //越界修正
    endif
    loop
        exitwhen index < 1
        set temp[index] = attack - ( attack / 2 ) * 2
        set  attack = attack / 2
        set index = index - 1
    endloop
    loop
        exitwhen index > 14 //因为此时的index为0
            set B = B + I2S(temp[index + 1])
            set index = index + 1
    endloop
    return B
endfunction
[/jass]
此段代码经过本人测试有效(刚开始时,不记得写set index = index + 1,死循环了...),一下为这些代码执行结果的图片
[jass] call BJDebugMsg(D2B(32767) [/jass]
result_32767.jpg
[jass] call BJDebugMsg(D2B(77593) [/jass]
result_77593.jpg
接下来我们要做的是定义一个给单位增加任意攻击的函数,在此之前,我们有个问题需要解决,那就是这个单位已经有了加攻击的技能怎么办,我们需要将单位拥有的攻击值储存进HashTable,在这里我只给出一个设置攻击的函数,其他的函数大家可以照猫画虎自己做.首先先声明一个HashTable,和一些相关的ParentKey值(这个系统可以被扩充)
悲剧的自己在测试这个系统时发现没有作用,纠结了数分钟,发现自己没有运行初始化函数....(.....0)
唉,刚开始的初始化语句就错了......
[jass]
globals
integer array AiId
integer array BiId
endglobals
function Init_Id_Array takes nothing returns nothing
local integer i = 0
set AiId[0] = 0
set BiId[0] = 0
loop
      exitwhen i > 15
      set AiId[i + 1 ] = 'FNaA' + i
      set BiId[i + 1 ] = 'FNbA' + i
      set  i = i + 1
      //为了某些同学,我的下标从1开始
endloop
endfunction
function GetStringSub takes string char , integer where returns string
return SubString( char,( where - 1 ) ,where )
endfunction
function RemoveAttack takes unit whichunit returns nothing
local integer attack = HT_GetUnitAttack(whichunit)
local string B = null
local integer i = 1
set B = D2B(attack)
if GetStringSub(B,1) == "0" then
    loop
        exitwhen i > 15
        if GetStringSub(B,( 17 - i )) == "1" then
            call UnitRemoveAbility( whichunit ,AiId )
        endif
        set i = i + 1
    endloop
else
    loop
        exitwhen i > 15
        if GetStringSub(B,( 17 - i )) == "1" then
            call UnitRemoveAbility( whichunit ,BiId )
        endif
        set i = i + 1
    endloop
endif
endfunction
function SetUnitAttack takes unit whichunit , integer attack returns nothing
local string B = null
local integer i = 1
set B = D2B( attack )
call RemoveAttack(whichunit)
call HT_SetUnitAttack(whichunit,attack)
if GetStringSub(B,1) == "0" then
    loop
        exitwhen i > 15
        if GetStringSub(B,( 17 - i )) == "1" then
            call UnitAddAbility( whichunit ,AiId )
        endif
        set i = i + 1
    endloop
else
    loop
        exitwhen i > 15
        if GetStringSub(B,( 17 - i )) == "1" then
            call UnitAddAbility( whichunit ,BiId )
        endif
        set i = i + 1
    endloop
endif
endfunction
[/jass]
以上代码是我在WE中写的,通过了编译,并进行了大量数据测试
在数据比较大时,会有一秒左右的延迟.........
给图说明我这个系统的功能.....
+32767.jpg , -32767.jpg
事实上,这个系统有很多改进的地方,在我的演示地图中(演示地图在上面),我使用的是八进制和技能多等级.在大的数据方面要快了很多(除了第一次有点慢,你可以先给其加0点攻击让其初始化)
=============到此结束========================

评分

参与人数 1威望 +102 收起 理由
希瓦 + 102 不错的演示

查看全部评分

发表于 2012-1-15 13:30:52 | 显示全部楼层
很强大。看不懂算法。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-11-21 23:19 , Processed in 0.086983 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表