Mugen是由美国的Elebyte于1999年制作并发布的一款格斗游戏编辑器

3. 语法、运算符与表达式

---------------------------------------------------------------------------

写AI之前先说说语法之类跟计算机编程之类相关的东西。不过请放心,内容挺简单的。

因为Mugen本来就是给广大FTG爱好者一起玩的游戏引擎,所以其编写也是相当简单的。

另外学过计算机编程的同学这章可以看得快一点,毕竟很多都是学过的东西,注意一下某些跟C语言的区别就行了。




===========================================================================

3.1语法

===========================================================================


---------------------------------------------------------------------------

首先,分号;后面的是注释,也就是说;后面的东西是读不了的...


例子:


;例如这一句就是读不了的

;这一句也是...好神奇啊^ ^

分号前还是读得了 ; 分号后面就读不了了...T T

这句整句能读XD...好了不卖萌了


上面的例子计算机能读得到的就是“分号前还是读得了”和“这句整句能读XD...好了不卖萌了”,其他都读不到。

";"的用途主要是给自己/别人写注释,养成写注释的好习惯方便自己阅读,要不日后拿起来都不知道写了什么...

当然,有些不知道以后是否需要的代码,可以用";"把他们先屏蔽掉,以后有用再拿出来(这点很实用...)。



然后,要看一段语句是否运行,就要看里面的条件是否满足,也就是真或假。

与C语言相似,你的输入的值非0是真,0是假;系统返回值1是真,0是假。

呃,输入值和返回值是什么?

输入值是你告诉计算机的数值,而返回值是计算机处理一段代码后得到的结果,反过来告诉你。举些例子吧:

你告诉系统-1,不是0,系统就知道你说的是真,同理输入233也是真;

你告诉系统0,系统就知道你说的是假。

1+2=3,运算后系统发现这个是真,所以最后你得到一个1;

1+2=233,运算后系统发现这个是假,所以最后你得到一个0。



---------------------------------------------------------------------------

紧接着就是讲状态控制器(state controller或sctrl)和触发器(trigger)的格式了。

Cmd、St和Stcommon三种文件里都经常看到一种写法:


例子,Cmd里KFM的站轻拳(因为详细的trigger还没看过所以右边有文字注释):


;Stand Light Punch

[State -1, Stand Light Punch]

type = ChangeState;改变状态

value = 200;改变状态的值为200

triggerall = command = "x";按x键

triggerall = command != "holddown";没有按着↓键

trigger1 = statetype = S;站姿

trigger1 = ctrl;处于可控状态

trigger2 = stateno = 200;状态号为200

trigger2 = time > 6;时间大于6


其模板为:


[State XX, ...]

type = XXX

value = XXX

triggerall = ...

trigger1 = ...

trigger1 = ...

trigger2 = ...

trigger2 = ...

...

triggerN = ...


而这个模板就是sctrl的模板。


[State XX, ...]是整段的开始,其实没啥用途,但是你不能去掉...囧

XX其实可以随便填的,不过通常写在[Statedef XX]里就填XX,方便日后debug,例子中Cmd是[Statedef -1]。

中括号里逗号后面的省略号是文字注释,不影响运行。

type是你要做的事件类型,比如说例子里面ChangeState(即改变状态),

value是你要赋予的值,比如说例子里面就是200,

例子中结合type和value来看,就是改变状态到200号动作,即变为站轻拳。


紧接着就是一大串的trigger,即触发器,满足条件就触发这个状态控制器的事件,

学过编程的朋友可以理解为if语句。

trigger是按数字排序,编号为数字从1到N,按顺序从小到大检测是否满足,

一旦满足同编号trigger马上执行同数字的trigger要同时全部满足才算满足(当然同数字的只有一个的话只看那个就行了)。

如例子中trigger2就是状态号是200而且时间大于6两个条件同时满足才触发trigger2。

不过有一个特例,triggerall,是所有情况都需要满足的trigger,否则就不执行。

例子当中triggerall为你按x而且你没有按着向下方向键↓,否则下面的trigger1和trigger2满足了也没用。

如果从逻辑角度上来说,trigger的运作就是:


满足triggerall 而且 (       满足全部trigger1

                       或者  满足全部trigger2

                       或者  ......

                       或者  满足全部triggerN)


另外trigger在Winmugen里有长度限制,太长会报错,但是貌似Mugen1.0里面没有。

反正就是不要写太长(不过初学者应该不会写得很长的)。

还有要注意至少要有一个后缀为数字的trigger(也就是trigger1),只有triggerall的话会报错哦。


...什么还是看不懂?引用四娘语录:


type = 

吃饭

(干什么)


type = 

value = 

吃“一碗”饭

(量)


type = 

trigger1 = 

value =

“在中午”吃一碗饭

(什么时候)


果然四娘就是四娘简单暴力直接易懂的吃饭教学请允许在下跪拜OTL



---------------------------------------------------------------------------

语法例子若干:


继续使用上面的例子:

;Stand Light Punch

[State -1, Stand Light Punch]

type = ChangeState;改变状态

value = 200;改变状态的值为200

triggerall = command = "x";按x键

triggerall = command != "holddown";没有按着↓键

trigger1 = statetype = S;站姿

trigger1 = ctrl;处于可控状态

trigger2 = stateno = 200;状态号为200

trigger2 = time > 6;时间大于6



1.有按x键和↓键,站姿,处于可控状态,状态号不为200,时间大于6

满足command = "x",不满足command != "holddown",所以不满足triggerall,下面全部不满足trigger


2.有按x键,没有按着↓键,站姿,处于可控状态,状态号不为200,时间大于6

满足triggerall,满足所有trigger1,所以满足trigger,执行


3.有按x键,没有按着↓键,蹲姿,处于可控状态,状态号为200,时间大于6

满足triggerall,蹲姿不满足trigger1,满足trigger2,所以满足trigger,执行


4.有按x键,没有按着↓键,蹲姿,处于可控状态,状态号不为200,时间大于6

满足triggerall,但不满足trigger1和trigger2,不满足trigger,所以不执行



好,语法其实就是这么多,Cmd、St和Stcommon基本都是以这个格式写的。

其实前半部分是Sctrl,后半部分就是trigger。

做AI能用到的Sctrl的类型其实也只有ChangeState等为数不多的几种,

当然要做人物的话就要用到各种各样的type,不过在AI教程里面就不予赘述了。

trigger倒是需要多知道一些,毕竟写AI要考虑各种各样不同情况。

至于常用Sctrl与trigger,笔者会在下章讲。

想了解更多的建议多看看trigger表和Sctrl表,里面解释的挺清楚的。




===========================================================================

3.2运算符与表达式

===========================================================================


---------------------------------------------------------------------------

运算符就是各种各样的运算符号,跟数字之类的结合成为表达式。

毕竟mugen里面的AI还是与数学和计算机密切相关的,这些基础的东西还是要提及一下。


---------------------------------------------------------------------------

括号


( )     括号,括号内优先运行,跟数学里的意义基本一样,不多说了

        此外,有时在语句长、逻辑关系十分混乱或语句有歧义时,用括号分段会有很好的效果



---------------------------------------------------------------------------

算术运算符


+ - * / 加减乘除这四个就不解释了- -...不懂的朋友建议重新读小学XD...

%       取余,A % B,例如5 % 2余数就是1

**      乘方,A ** B,就是A的B次方,需要注意的是winmugen里面乘方运算有BUG,1.0被修复,使用时小心



---------------------------------------------------------------------------

逻辑运算符


!       NOT,非,表示否定,!A,真假颠倒,即真的变成假,假的变成真

&&      AND,并且,A && B,AB同时为真才为真,否则为假

||      OR,或者,A || B,AB同时为假才为假,否则为真

^^      XOR,异或,A ^^ B,AB只有一个为真才为真,否则为假



---------------------------------------------------------------------------

关系运算符


=       等于号,A = B,当AB同为整型或浮点型且相等的时候为真,否则为假。

!=      不等于号,A != B,当AB同为整型或浮点型且不相等的时候为真,否则为假。

<       小于号,A < B,当两边同为整型或浮点型且A小于B的时候为真,否则为假。

<=      不大于号,与小于号相似,A = B时亦为真

>       大于号,A > B,当两边同为整型或浮点型且A大于B的时候为真,否则为假。

>=      不小于号,与大于号相似,A = B时亦为真

以上判断大小关系运算符,若AB类型不同,系统会自动转化为浮点型再比较


=[,]    以下的都是A “=或!=” “[或(” B,C “]或)” 的形式,例如X=[Y,Z],表示区间

!=[,]   嘛,集合是高一数学的内容(我应该没记错吧...)

=[,)    =和!=我就不多说了,[]是闭区间,包含区间端点,()是开区间,不包含区间端点,另外B <= C

!=[,)另外请注意这八种区间的表达如果不是用在这行的末端,会造成语句歧义而报错

=(,]解决方法是加括号,例:Trigger1 = (Power = [1000,2000]) && Life < 300

!=(,]

=(,)

!=(,)



---------------------------------------------------------------------------

赋值运算符


:=      赋值号,用于赋予变量值,以后讲到变量Var和浮点变量FVar再提及



---------------------------------------------------------------------------

二进制运算符


没学过二进制的朋友可能会比较难理解,而且应用面不广,这部分选读即可(拓展内容www)。

我们平时生活中应用的数字是十进制,数字从0~9一个十个数字,每逢十个就进一位。

二进制就是只由0和1两个数字组成,每逢两个就进一位,在计算机当中有广泛运用(用0/1表示关/开非常方便)。

例如十进制的6 = (2^2)*1 + (2^1)*1 + (2^0)*0 -> 二进制的110(1个2的2次方 加 1个2的1次方 加 1个2的0次方)。

mugen里面的运用多数用于大量的布尔型数据(即真或假)的储存,

注意进行二进制计算请用整型


!       NOT,非,表示否定,!A,真假颠倒,即真的变成假,假的变成真

&       AND,并且,A & B,AB同时为真才为真,否则为假

|       OR,或者,A | B,AB同时为假才为假,否则为真

^       XOR,异或,A ^ B,AB只有一个为真才为真,否则为假


二进制的逻辑其实就是每个数位独立出来运算...

还是举个两个例子吧(下面的^符号代表数学运算中的乘方运算)...


6&5其实等价于((2^3)*0 + (2^2)*1 + (2^1)*1 + (2^0)*0) & ((2^3)*0 + (2^2)*1 + (2^1)*0 + (2^0)*1)

6|5其实等价于((2^3)*0 + (2^2)*1 + (2^1)*1 + (2^0)*0) | ((2^3)*0 + (2^2)*1 + (2^1)*0 + (2^0)*1)


  0110

& 0101

--------

  0100

一共四个字节,只有第三个字节是上下同为1,所以只有第三个字节是1,其他是0

返回((2^3)*0 + (2^2)*1 + (2^1)*0 + (2^0)*0) = 4


  0110

| 0101

--------

  0111

一共四个字节,只有第四个字节是上下同为0,所以只有第四个字节是0,其他是1

返回((2^3)*0 + (2^2)*1 + (2^1)*1 + (2^0)*1) = 7



---------------------------------------------------------------------------

运算符优先级


优先级从上到下排列,同一行的是同级运算。

如果同级的运算是按从左到右次序进行,多层括号由里向外。


! ~ -(负号)

**

* / %

+ -(减号)

> >= < <=

= !=

:=

&

^

|

&&

^^

||



---------------------------------------------------------------------------

表达式例子若干:


1.1

直接返回1,为真


2.1 && 0 || 1

根据运算符优先级可知,先考虑1 && 0,返回0;再考虑 0 || 1,返回1


3.1 + 1 = 2 && 1 + 2 != 3

根据运算符优先级可知,先考虑1 + 1 = 2,再考虑1 + 2 != 3,最后考虑两个的式子的关系

1 + 1 = 2为真,返回1;

1 + 2 != 3为假,返回0;

1 && 0为假,返回0




===========================================================================

课后作业:


1.

!((5 % 2) || (1 >= 2) && ((1 ** 233 + 2) * 3 != 10086) && (1 = [0,2)) && 0)

按步骤分析上述表达式并写出过程


2.

[State 233, 莫伸手]

type = 伸手党处理方法

triggerall = LZ伸手

trigger1 = 帖子问题与精品贴中某教程帖吻合

trigger1 = LZ没翻过置顶/精品贴

trigger2 = 借话题水

triggerX = YYY

value = ifelse(吧务心情不好, 删帖, 不删放着让大家水)

分别给以下两种情况,赋予YYY适合的触发条件

a). X = 2

b). X = 3


3.

如何利用二进制运算符有效地储存布尔型数据?理论上可以储存多少个布尔型数据?

附加题,难度较大,对二进制运算感兴趣的同学可以试试,不过对计算机专业的朋友来说应该是小菜一碟-w-


以上教程由口水轩撰写

你,确定要这么做吗?
正在处理中...