📄 电脑游戏中的人工智能制作.htm
字号:
<HTML><HEAD><TITLE>电脑游戏中的人工智能制作</TITLE>
<BODY aLink=#990000 bottomMargin=0 leftMargin=0 rightMargin=0
topMargin=0 marginheight="0" marginwidth="0">
<CENTER>
<DIV align=center>
<DIV align=left class=fst>
<DIV class=fstdiv3
id=print2><BR><BR>电脑游戏随着硬件执行效率与显示解析度等大幅提升,以往很多不可能或非常难以实现的电脑游戏如此都得以顺利完成。虽然电脑游戏的呈现是那么地多样化,然而却与我们今日所要探讨的主题,人工智能几乎都有着密不可分的关系。
<BR> 在角色扮演游戏中,程序员与企划人员需要精确地在电脑上将一个个所谓的“怪物”在战门过程中栩栩如生地制作出来;所以半兽人受了重伤懂得逃跑,法师懂得施展攻性法术。
<BR> 目前能让人立刻想到与人工智能有密切关系的游戏有两种:
<BR> 一是所谓的战棋/策略模拟游戏,二则是棋弈游戏。人工智能的比重与深浅度,在不同的游戏类型中各有不一。有的电脑游戏非标榜着高人工智能不可,不然没有人买;有的则是几乎渺茫到让玩家无法感觉有任何人工智能的存在。
<BR><BR> 导向式思考
<BR><BR> ai最容易制作的的方式,同时也是早期游戏ai发展的主要方向就是规则导向或称之为假设导向。在一些比较简单的电脑游戏中,程序员可以好不困难地将游戏中的规则与设定转化成一条条的规则,然后将它们写成电脑程序。让我们以角色扮演游戏为例。决大多数的企画在设定所谓电脑怪物时,所设定的属性通常有以下几种:
<BR><BR> 生命值 攻击力 防御力 法力 属性
<BR><BR> 最后一个“属性”是我在设定时喜欢增加的项目之一。透过这项属性的设定,我可以把怪物设定成“贪生怕死的”,也可以把战士设定为“视死如归”。以目前我们所掌握的资料,在战门系统中的大纲如是诞生了:
<BR><BR>规则一 <BR><BR>if (生命值< 10) // 边临死亡了吗
<BR>{ if (属性== 贪生怕死)
<BR> 结果 = 试图逃跑
<BR> if (有任何恢复生命值的物品或法术可用)
<BR> 结果 = 使用或施展相关物品或法术
<BR>} <BR> <BR><BR>规则二
<BR> <BR>if (可施攻击性法术 && 有足够法力)
<BR>{
<BR> 结果 = 施展攻攻击性法术
<BR>}
<BR><BR> 由以上一连串的“如果--就--”规则设定,建立了最基本的ai。说这样的制方式只能建立基本ai其实并不当然正确。只要建立足够及精确的规则,这样的方式仍然有一定水准的表现。
<BR> 规则导向的最大优点就是易学易用。在没有深奥的理论概念的前提下,仍有广大的使用群。所以很多老道的玩家常常没两下就摸清楚敌人的攻击策略,移动方式等等。
<BR><BR> 推论式思考
<BR><BR> 相信曾经接触过电脑语言课程,或是自习过相关书籍的朋友们,都曾曾经听过一个著名的程序,那就是井字游戏。用井字游戏作为讨论ai的入门教材,我个人觉得是最适当的例子。或许有人还不知道井字游戏怎么玩。只要任何一方在三乘三的方格中先先成一线便胜利了。我们在前面谈过的规则导向,在这里也可以派得上用场。
<BR><BR> if任何一线已有我方两子&&另外一格仍空//我方即将成一线吗
<BR> 结果 = 该空格
<BR> if任何一线已有敌方两子&&另外一格仍空//防止敌方作成一线
<BR> 结果 = 该空格
<BR> if任何一线已有我方一子&&另外两格仍空//作成两子 <BR> 结果 = 该空格
<BR><BR> 有一次我在某本电脑书上,同样地也看到某些以井字游戏为介绍的范例。不同的是,我几乎看不到任何规则导向的影子。但在仔细分析该程序码后,我得到了极大的启发,原来ai是可以不用这么多规则来制作的。它用的方法正是在电脑ai课程中重要的概念:极大极小法。我在这里只说明这法则的概念。继续以井字游戏为例,电脑先在某处下子,接着会以假设的方式,替对方下子,当然,必须假设对方下的是最佳位置,否则一切则毫无意义。在假设对方下子的过程中,自然又需要假设我方的下一步回应,如此一来一往,直到下完整局游戏为止。
<BR><BR>底下是节录书中的程序片段: <BR>
<BR>bestmove(int p, int*v) <BR>{ int i;
<BR> int lasttie;
<BR> int lastmove;
<BR> int subv;
<BR>/*first, check for a tie*/
<BR> if (istie()) {
<BR> *v=0; <BR> return(0);
<BR> };
<BR>/*if not a tie, try each potential move*/
<BR> for (*v=-1, lasttie=lastmove=-1,i=0;i<9;i++)
<BR> {
<BR> /*if this isn't a possible, skip it*/
<BR> if (board[i]!=0) continue;
<BR> /* make the move. */ <BR> lastmove=i;
<BR> board[i]=p;
<BR> /* did it win? */
<BR> if (haswon(p)) *v=1;
<BR> else{
<BR> /*if not, find out how good the other side can do*/
<BR> bestmove(-p,&subv);
<BR> /* if they can only lose, this is still a win.*/
<BR> if (subv==-1) *v=1;
<BR> /* or, if it's a tie, remember it. */
<BR> else if (subv==0){
<BR> *v=0; <BR> lasttie=i;
<BR> };
<BR> };
<BR>/* take back the move. */
<BR> board[i]=0;
<BR>/*if we found a win, return immediately
<BR> (can't do any better than that)*/
<BR> if (*v==1) return(i);
<BR>/*if we didn't find any wins, return a tie move.*/
<BR> if (*v==0) return(lasttie);
<BR>/*if there weren't even any ties, return a loosing move.*/
<BR> else return(lastmove); <BR>};
<BR><BR> 国外的一些论坛曾举行过256字节的游戏设计比赛。作品非常多,其中有一件作品正巧也是井字游戏。作者用区区两百多行就写了与上述程序演算方式完全相同的作品,可见功力确实了的。另外,我也很希望类似的活动能在国内推展起来。对了,在这样的比赛条件限制下,除了汇编语言外,几乎没有其它的选择了。
<BR><BR> .386c
<BR> code segment byte public use16
<BR> assume cs:code, ds:code
<BR>
<BR> org 100h
<BR> <BR> tictac proc far
<BR> <BR> start:
<BR> push cs
<BR> pop ds
<BR> mov ax,0b800h ; 清除屏幕
<BR> mov es,ax ;
<BR> xor di,di ;
<BR> mov cx,7d0h ;
<BR> mov ax,0f20h ;
<BR> rep stosw ;
<BR> xor cx,cx ;
<BR> mov dl,5
<BR> loc_1:
<BR> call printboard
<BR> loc_2:
<BR> mov ah,8 ; 等待按键
<BR> int 21h <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -