脚本AI与脚本引擎

来源:互联网 发布:mac怎么下载office2016 编辑:程序博客网 时间:2024/05/16 02:52

 

 

 

 

Scripted AI and ScriptingEngines

脚本AI与脚本引擎

This chapterdiscusses some of the techniques you can use to apply a scripting system to theproblem of game AI, and the benefits you can reap from doing this. At its mostbasic level, you can think of scripting as a very simple programming languagetailored to a specific task related to the game in enables the game designersrather than the game programmers to write and refine much of the gamemechanics. Players also can use scripting to create or modify their own gameworlds or levels. Taken a step further, you can use a scripting system in amassively multiplayer online role-playing game (MMORPG) to alter the gamebehavior while the game is actually being played.

 

这一章讨论一些如何应用脚本系统到游戏AI问题中去的技术,以及这样做你 能获得哪些好处。在最基础的层次上,你可以认为脚本是一种非常简单的为游戏中特殊的任务描述而定制的编程语言,它可以让游戏设计者而不是游戏程序员编写和精制大部分的游戏结构。玩家同样可以使用脚本来创建或修改他们自己的游戏世界和等级。进一步说,当游戏实际上正在运行着的时候,你可以在一个MMORPG 中使用脚本来改变游戏的行为。

 

You can takeseveral approaches when implementing a scripting system. A sophisticatedscripting system might interface an already existing scripting language, suchas Lua or Python, for example, with the actual game engine. Some games create aproprietary scripting language designed for the needs of the individual game.Although it's sometimes beneficial to use those methods, it's easier to havethe game parse standard text files containing the scripting commands. Employingthis approach, you can create scripts using any standard text editor. In a realgame, the scripts can be read in and parsed when the game first starts, or atsome other specified time. For example, scripts that control creatures orevents in a dungeon can be read in and parsed when the player actually entersthe dungeon area.

 

实现一个脚本系统时,你可以使用几种方法。实际的游戏引擎中一个复杂完善的脚本系统可以使用一种已经存在的脚本语言,例如Lua或者Python。一些游 戏为了特殊需要创建自己的脚本语言。有时候它不仅有利于使用那些方法(?),还可以方便的让游戏解析含有脚本命令的标准文本文件。采用这种方法,你可以使用任何标准的文本编辑器来创建脚本。在真正的游戏中,这些脚本可以在游戏开始时或者其他特定的时间读取进来并被解析。例如,当玩家进入地牢的区域时控制地牢中人和事件的脚本被读取并解析。

 

In the scope ofgame AI, you can use scripting to alter opponent attributes, behavior,responses, and game events. This chapter looks at all these uses.

 

在游戏AI中,你可以使用脚本来修改对手的属性、行为、反应以及游戏事件。这一章将着眼于所有这些应用。

 

Scripting Techniques

脚本技术

The actualscripting language used in a game is ultimately up to the game designers andprogrammers. It can resemble preexisting languages such as C or C++, or it cantake a totally approach; perhaps even a graphical rather than a text-basedapproach. Deciding how the scripting system looks and works depends primarilyon who will be using the scripting system. If your target is the end player, amore natural language or graphical approach might be beneficial. If the systemis primarily for the designers and programmers, it might not be beneficial tospend your development time on a complex and time-consuming natural languageparsing system. A quick and dirty approach might be better.

 

一个真正应用于游戏的脚本语言是从根本上服务于游戏设计者和程序员的。它可以类似于先前存在的语言像CC++,或者完全与之相同;或许甚至是图形上的而不 是文字上的相似。脚本系统看上去像什么和怎样工作从根本上取决于谁将要使用它。如果你的目标是一个最终的玩家,那么一个更类似于自然语言或者图形化的方法也许不错。如果这个系统是针对于设计者和程序员的,那么浪费你宝贵的开发时间在一个复杂的耗时的(译者认为是指运行效率)自然语言解析系统上是不明智的。一个快的脏的(?!dirty怎么翻译)方法会好一点。

 

You also shouldconsider other factors when developing a scripting system. Perhaps you want thescript to be easy to read and write for the game designers, but not necessarilyfor the game player. In this case, you might want to use a form of encryption.You also could develop a script compiler so that the end result is lessreadable to humans.

 

在开发一个脚本系统时你还应当考虑其他一些因素。或许你希望对于设计者来说脚本是易于读和写的,而对于玩家却不是必需的。因此,你可能想要使用一种形式的加密。你同样可以开发一个脚本的编译器,那样最终的结果对(旁)人来说就不是那么容易读懂了。

 

In this chapterwe create simple scripting commands and save them in standard text files. Wewant to avoid the need for a complex language parser, but at the same time wehave been careful to choose a vocabulary that makes it relatively easy forhumans to read and write the scripts. In other words, we use words thataccurately reflect the aspect of the game that the script is altering.

 

在这一章我们将要创建简单的脚本命令并把它们存储在标准的文本文件里。我们希望避免对一个复杂语言分析器的需求,与此同时我们还要小心地选取一个词汇集来使人们读写脚本相对的简单些。换句话说,我们在脚本中使用正确的词汇来精确地反映游戏的样子。

 

Scripting Opponent Attributes

脚本控制的对手的属性

 

It's common andbeneficial to specify all the basic attributes of each AI opponent by usingsome type of scripting. This makes it easy to tweak the AI opponents throughoutthe development and testing process. If all the vital data were hardcoded intothe program, you would have to recompile for even the most basic change.

 

通过使用一些类型的脚本可以方便的指定每一个AI对手(由AI控制的对手)所有的基本属性。这使得在整个开发和测试过程中调整AI对手(的属性)变得容易。如果所有重要的数据是被硬编码在程序中的,你将不得不重新编译哪怕是最基本的变动。

 

In general, youcan script opponent attributes such as intelligence, speed, strength, courage,and magical ability. In really comes down to the type of game you'redeveloping. Of course, the game engine ultimately will use these attributeswhenever a computer-controlled friend or foe interacts with the player. Forexample, an opponent that has a higher intelligence attribute would be expectedto behave differently from one of lower intelligence. Perhaps a moreintelligent opponent would use a more sophisticated pathfinding algorithm totrack down a player, while a less intelligent opponent might become easilyconfused when trying to reach the player.

 

一般而言,你可以把对手的属性诸如智慧、速度、力量、精神以及不可思议的能力编写进脚本里。但这到底包括哪些就要依你所开发的游戏类型而定了。当然,无论何时,只要玩家与电脑控制的朋友或敌人相遇,游戏引擎最终都会使用到这些属性。例如,一个有着较高智慧属性的对手与那些较低智慧的对手的预期行为不同。也许,一个有着更高智慧的对手会使用一个更加高级、完善、狡猾的寻路算法追捕到玩家,而一个低智慧的对手试图接近玩家的方法是那样的简单并且缺乏智慧。

 

Example 8-1shows a basic script you can use to set game attributes.

8-1展示了一个你能用来设置游戏属性的基础的脚本

Example 8-1.Basic script to set attributes

CREATURE=1;

INTELLIGENCE=20;

STRENGTH=75;

SPEED=50;

END

 

In this example,our script parser has to interpret five commands. The first, CREATURE,indicates which AI opponent is being set. The next three, INTELLIGENCE,STRENGTH, and SPEED, are the actual attributes being set. The final command,END, tells the script parser that we are finished with that creature. Anythingthat follows comprises a new and separate block of commands.

 

在这个例子中,我们的脚本解释器需要解释5条命令。第一条,CREATURE 出哪一个AI对手将要被设置。接下来的三条INTELLIGENCESTRENGTHSPEED是实际被设置的属性。最后的一个命令END告诉脚本解 释器对这个AI对手的设置结束了。之后的任何东西都是由新的独立的命令块组成的。

 

It would be justas easy to include the numbers 1,20,75,50 in a file and thus avoid any need for parsing thescript text. That approach works and developers use it frequently, but it doeshave some disadvantages. First, you lose quite a bit of readability. Second,and most important, your scripting system can increase in complexity to thepoint where specifying attributes by just including their numerical values in afile becomes impractical. Example 8-2 shows how a script can become morecomplicated by using a conditional statement.

 

你可以简单的在文件中包含1207550这样的数字,从而避免对解析脚本的需求。这 种方法很奏效并且开发者经常使用它,但是它存在一些缺点。首先,你损失了相当的可读性。其次,也是最重要的,你的脚本系统可能增长,复杂到仅仅通过在文件中包含它们的数值来指定属性变得不切实际的地步。例8-2展示了如何通过使用一个条件语句来使脚本变得复杂。

 

Example 8-2.Conditional script to set attributes

CREATURE=1;

 If (LEVEL<5)

BEGIN

INTELLIGENCE=20;

STRENGTH=75;

SPEED=50;

END

ELSE

BEGIN

INTELLIGENCE=40;

STRENGTH=150;

SPEED=100;

END

 

As shown inExample 8-2, we now have conditional statements that initialize the creatureattributes to different values depending on the current game level.

正如例8-2所示,我们使用条件语句来根据当前的游戏等级来初始化人的属性。

 

Basic Script Parsing

基本的脚本解析

 

Now that we'veshown what a basic attribute script looks like, we're going to explore how agame reads and parses a script. As an example, we will use a basic script toset some of the attributes for a troll. We will create a text file called TrollSettings.txt. Example 8-3 shows the contents of the troll settings file.

troll--<北欧神话>居住在洞穴或山中的巨人

 

然我们已经知道了基本的属性脚本是什么样子的,下面我们就来研究一个游戏是如何读取和解析脚本的。作为一个例子,我们将使用一个基本的脚本来设置一个巨人的部分属性。我们将创建一个叫做Troll Settings.txt的文本文件。例8-3展示了巨人设置文件的内容。

Example 8-3.Basic script to set attributes

INTELLIGENCE=20;

STRENGTH=75;

SPEED=50;

 

Example 8-3 is asimple example that sets only three creature attributes. However, we will setup our code so that we can easily add more attributes with very little changeto our script parser. Basically, we are going to set up our parser so that itwill search a given file for a specified keyword and then return the valueassociated with the keyword. Example 8-4 shows how this might look in an actualgame.

 

8-3是一个简单的实例,它只设置了人的三个属性。无论如何,我们要建立起我们的代码这样不用对我们的脚本解释器做很大的改动就可以添加更多的属性。最主要的,我们应建立我们的解释器,它将会在给定的文件中搜索指定的关键词并返回与之关联的值。例8-4展示了这个在真正游戏中的样子。

Example 8-4.Basic script to set attributes

intelligence[kTroll]=fi_GetData("TrollSettings.txt,"INTELLIGENCE");

strength[kTroll]=fi_GetData("TrollSettings.txt,"STRENGTH");

speed[kTroll]=fi_GetData("TrollSettings.txt,"SPEED");

 

Example 8-4shows three hypothetical arrays that can store creature attributes. Rather thanhardcoding these values into the game, they are loaded from an external scriptfile called Troll Setting.txt. The function fi_GetData traverses the externalfile until it finds the specified keyword. It then returns the value associatedwith that keyword. The game designers are free to tweak the creature settingwithout the need to recompile the program code after each change.

 

8-4假设有3个数组来存放人的 属性。相对于把这些数值硬编码到游戏中,它们是从一个叫做Troll Setting.txt的外部脚本文件中加载的。函数fi_GetData遍历整个文件直到找到指定的关键词。然后,返回与之关联的值。这样游戏设计者就可以轻轻松松地调整人的设定,而不需要在每次改动之后重新编译程序代码。

 

Now that we haveseen how you can use the fi_GetData function to set the attributes for a troll,let's go a step further. Example 8-5 shows how the function accomplishes itstask.

 

既然我们已经知道如何使用fi_GetData函数来设定巨人的属性,那么不妨更进一步。例8-5展示了函数是如何完成它的任务的。

Example 8-5.Reading data from a script

// 代码段,译者修改了2处小错误,你可以直接使用

#definekStringLength 99

intfi_GetData(char filename[kStringLength], char searchFor[kStringLength])

{

FILE*dataStream;

charinStr[kStringLength];

charrinStr[kStringLength];

charvalue[kStringLength];

long ivalue;

int i;

int j;

dataStream=fopen(filename,"r");

if(dataStream!=NULL)

{

while(!feof(dataStream))

{

if(!fgets(rinStr,kStringLength, dataStream))

{

fclose(dataStream);

return (0);

}

j=0;

strcpy(inStr,"");

for(i=0; i

if(rinStr[i]!='')

{

inStr[j]=rinStr[i];

inStr[j+1]='/0';

j++;

}

 

if(strncmp(searchFor,inStr, strlen(searchFor))==0)

{

j=0;

for(i=strlen(searchFor)+1;i

{

if(inStr[i]==';')

break;

value[j]=inStr[i];

value[j+1]='/0';

j++;

}

//StringToNumber(value, &ivalue);

ivalue=atol(value);

fclose(dataStream);

return((int)ivalue);

}

}

fclose(dataStream);

return (0);

}

return (0);

}

// 代码结束

 

The function inExample 8-5 begins by accepting two string parameters. The first specifies thename of the script file to be searched and the second is the search term. Thefunction then opens the text file using the specified file name. Once the fileis opened, the function begins traversing the script file once text line at atime. Each line is read in as a string.

 

8-5中的函数从接受两个字符串变量开始。第一个指出将要搜索的脚本的名字,第二个是要搜索的项。接着函数会以文本方式打开指定的文件。一旦成功打开文件,函数便开始逐行遍历脚本,并把每一行都当作一个字符串读取进来。

 

Notice that eachline is read into the variable rinStr, and then it's copied immediately toinStr, but without the spaces. The spaces are eliminated to make the parsing abit more foolproof. This prevents our script parser from getting tripped up ifthe script writer adds one or more spaces before or after the search term orattributes. Once we have a script line stored in a string, sans spaces, we cansearch for the search term.

注意,读取进来的一行数据是存放在rinStr变量中的,紧接着它会被立即拷贝到inStr中,但是不包括其中 的空格。消除这些空格是为了让解析的过程变得简单一些。这可以预防当脚本的作者在准备搜索的项或属性前后添加了空格时我们的解释程序出错。一旦我们把脚本行存储在字符串中,并且其中没有空格,我们就可以开始搜索了。

 

As you recall,we passed our search term to the fi_GetData function by using the stringvariable searchFor. At this point in the function, we use the C functionstrncmp to search inStr for the search term.

 

正如你记得那样,我们通过字符串变量searchFor来把我们要查找的项传递给fi_GetData函数。这里我们使用C语言的strncmp函数在inStr中搜索查找项。

If the searchterm is not found, the function simply proceeds to read the next text line inthe script file . However, if it is found, we enter a new loop that copies intoa new string named value the part of inStr that contains the attribute value.The string value is converted to an integer value by calling the outsidefunction StringToNumber. The fi_GetData function then returns the value inivalue.

如果没有找到查找项的话,函数就会读取脚本中的下一个文本行。但是,如果找到了,那就会进入一个新的循环来把inStr中包含属性值的那部分拷贝到名字为value的字符串 中。这个字符串将通过外部函数StringToNumber转化成整形数值(存放在ivalue中)。最后fi_GetData函数会返回这个存放在 ivalue中的值。

This function iswritten in a very generic way. No search terms are hardcoded into the function.It simply searches the given file for a search term and then returns an integervalue associated with it. This makes it easy to add new attributes to ourprogram code.

 

此函数以一种很常见的方式书写。没有查找项是硬编码在函数中的。它仅仅是在给定的文件中搜索查找项并返回与之关联的整数值。这样做将为我们的程序代码增加新的属性变得很简单。

Also, note thatthis is one area of game development where it is important to check for errors.This is true particularly if you want players as well as game designers to usethe scripting system. You should never assume any of the scripts being parsed arevalid. For example, you shouldn't rely on the script writers to keep all thenumeric values within legal bounds.

同样应注意,这正是在游戏开发中着重检查错误的区域。如果你希望玩家能像游戏设计者一样使用脚本系统的话,这是十分重要的。你绝不能假设所有的脚本都正确的解释。例如,你不能依赖(保证)脚本作者把所有的数值都限定在合法的范围内。

Scripting Opponent Behavior

脚本控制的对手的行为

 

Directlyaffecting an opponent's behavior is one of the most common uses of scripting ingame AI. Some of the previous examples showed how scripting attributes can havean indirect effect on behavior. This included such examples as modifying a creature'sintelligence attribute, which presumably would alter its behavior in the game.

 

直接影响一个脚本对手的行为是游戏AI中脚本的一个最常见的用途。先前的部分实例说明使用脚本控制属性可以间接地影响到人的行为。最典型的例子就是修改人的智慧属性将会影响到他在游戏中对自己行为的推测。

 

Scriptingbehavior enables us to directly manipulate the actions of an AI opponent. Forthis to be useful, however, we need some way for our script to see into thegame world and check for conditions that might alter our AI behavior. Toaccomplish this we can add predefined global variables to our scripting system.The actual game engine, not our scripting language, will assign the values inthese variables. They are used simply as a way for the script to evaluate aparticular condition in the game world. We will use these global variables inconditional scripting statements. For example, in our scripting system we mighthave a global boolean variable called PlayerArmed which will direct a cowardlytroll to ambush only unarmed opponents. Example 8-6 shows how such a scriptmight look.

 

使用脚本控制行为可以让我们能够直接的控制AI对手的动作。这很有用,但是,我们还 需要一些方法让我们的脚本进入游戏世界并检查那些可能引起AI行为改变的条件。为了完成这些我们需要向脚本系统中添加预定义的全局变量。对这些变量的赋值 将会由真正的游戏引擎而不是我们的脚本语言完成。作为脚本估测(计算)游戏世界中一个特殊条件的通道,它们使用简单。我们将会在脚本的条件语句中使用这些全局变量。例如,在我们的脚本系统中有一个控制着胆怯的巨人只是埋伏徒手的敌人(译者注:也可能指的是玩家)的全局布尔型变量。例8-6展示了这个脚本的样子。

 

Example 8-6.Basic behavior script

If(PlayerArmed==TRUE)

BEGIN

DoFlee();

END

ELSE

BEGIN

DoAttack();

END

 

In Example 8-6,the script does not assign the value PlayerArmed. It represents a value withinthe game engine. The game engine will evaluate the script and link thisbehavior to the cowardly troll.

 

在例8-6中,脚本并没有对PlayerArmed赋值。它表示的是一个游戏引擎内部的值。游戏引擎将会计算这个脚本并把这个行为和胆怯的巨人相关联。

 

In this example,the value PlayerArmed is a simple boolean value that represents nothing morethan another boolean value within the game engine. There certainly is nothingwrong with this, but scripting is more useful when you use simple globalvariables which represent a more complex series of evaluations. For example, inthis sample script we checked whether the player was armed. Although that mightbe useful for an opponent to know, it doesn't necessarily represent howchallenging the opponent will be in a fight.

 

在这个例子中,PlayerArmed是一个简单的布尔值,它和游戏引擎中其它的布尔值没有什么分别。当然这一点问题都没有,但是当你使用好几个全局变量表示一个复杂的数值的序列时,脚本会更有用。例如,在这个例子中我们检测玩家是否持有武器。虽然让一个对手知道这些会很有用,但是对表示怎样才能引起打斗这是不必要的(?)。

 

Many factorscould contribute to how challenging a potential opponent will be. We can makeour scripting system even more powerful if we evaluate these conditions in thegame engine and then make the result available to the script as a single globalvariable. For example, we could use a Bayesian network to evaluate how tough anopponent the player is and then make the result available in a variable such asPlayerChallenge. The script shown in Example 8-7 is just as simple as the onein Example 8-6, but it can have a much more sophisticated effect on thegameplay.

 

challenge--困难程度,复杂程度,对手有多么的强大(?)

多因素影响一个潜在对手的挑战是多少(?)。如果我们在游戏引擎中计算这些条件并让脚本能像使用一个全局变量那样使用这个结果,我们的脚本系统会更加强 大。例如,我们可以使用贝叶斯网络估算玩家是一个如何强大的对手,然后把结果存放在像PlayerChallenge那样的变量中(这样在脚本中也可以使用了,嘿嘿)。例8-7中的脚本和例8-6中的一样简单,但它对游戏的运行有更大的影响。

Example 8-7.Behavior script

If (PlayerChallenge==DIFFICULT)

BEGIN

DoFlee();

END

ELSE

BEGIN

DoAttack();

END

 

In the case ofExample 8-7, PlayerChallenge could represent a series of complex evaluationsthat rank the player. Some of the factors could include whether the player isarmed, the type of armor being worn, the current player's health, whether anyother players in the area might come to his defense, and so on.

 

在例8-7中,PlayerChallenge可以表示一系列复杂的用来评定玩家实力的值。这些因素包含玩家是否持有武器,所穿的护甲是否是过时的,玩家当前的健康状况,是否有其他玩家进入他的防御区等等。

 

Another aspectof behavior that you can script is AI character movement. We can take aconcept, such as pattern movement from chapter 3, and implement it in ascripting system. For example, it might be useful for the game designer toestablish patrol patterns for AI characters. Chapter 3 showed some examples ofhardcoded pattern movement. Of course, hardcoding behavior has manydisadvantages. It's much more difficult to tweak a game's design if a recompileis needed after every minor change. Figure 8-1 shows an example of a movementpattern that a game designer can implement using a scripting system.

 

你能用脚本控制的行为的另一种形式AI角色的移动。我们可以提出一种像第3章的模式移动那样的概念并在脚本系统中实现它。例如,它可能对游戏设计者建立游戏角色的巡逻模式很有帮助。在第 3章中展示了一些硬编码的模式移动。当然,硬编码的行为有许多的不利之处。如果对于每一次小的改变都要重新编译的话,那么调整游戏设定就太麻烦了。图 8-1展示了游戏设计者可以用脚本系统实现的模式移动的实例。

 

Example 8-8shows how we can construct a script to achieve the desired behavior.

8-8展示了如何构造一个脚本来完成我们想要的行为。

Figure 8-1.Scripted pattern movement

Example 8-8.Pattern movement script

If(creature.state==kPatrol)

Begin

move(0,1);

move(0,1);

move(0,1);

move(0,1);

move(0,1);

move(-1,0);

move(-1,0);

move(0,-1);

move(0,-1);

move(0,-1);

move(0,-1);

move(0,-1);

move(1,0); // 书上写的是move(0,1),但是只要和图8-1对照一下就会发现,

move(1,0); // 此脚本是控制人物做逆时针的循环移动,所以我修改成了这样

end

 

Example 8-8gives a glimpse of finite state machines from Chapter 9. In the scriptingexample, if the AI creature is in the patrolling state, it uses the specifiedmovement pattern. Each move is shown as a single unit change from the previousposition. See Chapter 3 for a detailed explanation of pattern movementtechiniques.

 

8-8小窥了一下第9章的有限状态机。在此脚本实例中,如果AI人物(角色)正处于巡逻状态,那么它就会根据指定的模式移动。每一次移动都被看作是相对于前一个位置的改变。请参看第3章了解模式移动的相关技术。

 

Scripting Verbal Interaction

脚本控制的语言交互(不知道怎么翻译好了,大概是指用脚本控制人物的对白吧)

 

The benefits ofscripting go beyond just making an AI opponent more sophisticated andchallenging. Many types of games incorporate intelligent behavior in ways thataren't meant to be a direct challenge to the player. A role-playing game, forexample, might provide the player with a series of subtle hints meant to movethe story along. Scripting is an excellent way to enable the game designer tocreate a compelling story without the need to alter the actual game program.

 

使用脚本的好处远远超过了让一个AI对手更加狡猾更具挑战性。许多类型的游戏在不同的方式上组合智能的行为并没有打算给玩家一个直接的挑战。例如一个RPG 会向玩家提供一系列的线索来推动故事的发展。脚本就是一个不错的方式来让游戏设计者创建一个引人入胜的故事而不需要修改已经完成的游戏程序。

 

Intelligentbehavior can make a game more challenging, but verbal responses that areintelligent and appropriate to the situation can go even farther when creatingan immersive environment for the player. Verbal interaction can range fromhelpful hints from a friendly nonplayer character to taunts from an adversary.Verbal interaction seems most intelligent and immersive when it relates to thecurrent game situation. This means the game AI needs to check a given set ofgame parameters and then respond to them accordingly.

 

智能的行为可以让游戏更具挑战性,但是在为一个玩家创建immersive的环境时让语言响应做的智能且合乎形势需要更多的工作(?)。从一个友善的NPC的有用提示到对手的戏弄嘲笑都属 于语言交互的范畴。当语言交互涉及到当前游戏的状态时它就显得那么的智能和immersive。这就意味着游戏AI需要检查一个给定的游戏参数从而对它们 做出反应。

 

For example, howa player is armed might be one parameter that can be checked. We can then havean adversarial AI character comment on how ineffective that weapon will be oncecombat starts. This seems more intelligent and immersive because it's not justa random taunt. It applies to the current game situation. It makes it seem asthough the computer-controlled characters are aware of what's happening in thegame. A quick example of how this script might look is shown in Example 8-9.

 

例如,玩家是否持有武器就可以作为一个检测的参数。我们可以有一个AI的对手来评论,如果打起架来那个武器是多 么的没有用。这看起来更智能和immersive,因为它不仅仅是一个随机的嘲讽。它取决于当前的游戏状态。它让这一切看起来就好像这个电脑控制的角色知 道游戏里到底发生了什么一样。例8-9是关于此的一个简单实例。

 

Example 8-9.Verbal taunt script

 

If(PlayerArmed==Dagger) // 匕首

Say("What acute little knife.");

 

If(PlayerArmed==Bow) //

Say("Dropthe bow now and I'll let you live");

 

If(PlayerArmed==Sword) //

Say("Thatsword will fit nicely in my collection.");

 

If(PlayerArmed==BattleAxe) // 战斧

Say("You'retoo weak to wield that battle axe.");

 

As Example 8-9shows, knowing a bit about the current game situation can add an immersiveeffect to gameplay. This is much more effective than simply adding randomgeneral taunts.

 

如例8-9所示,知道一点游戏当前的状况就可以增加游戏的immersive。这比简单的增加普通的随机嘲讽要有效的多。

 

So, an importantaspect of a scripting system is to enable the script writer to see what'shappening inside the game engine. The more game elements the script can see,the better. Figure 8-2 shows a hypothetical game scenario in which an evilgiant is chasing the player. In this case, the game AI is able to use uniqueelements of the game state to supply a taunt appropriate to the situation. Inthis case, we know that the adversary is a giant, the player is a human, andthe player is armed with a staff.

 

因此,脚本系统的一个重要功能是让脚本作者能够看到游戏中发生了什么。脚本中能看到的游戏元素越多越好。图8-2展示了一个假想的关卡,里面邪恶的大力士在追赶玩家。既然这样,游戏AI就可以根据游戏状态的唯一元素来提 供适合当前状况的嘲讽。我们知道了对手是一个大力士,玩家是普通的人类并且拿着木棍。

 

Figure 8-2.Giant taunt

 

Giant大力士 taunt嘲笑

 

Example 8-10shows how the game AI might can be an appropriate taunt during a battle betweena computer-controlled giant and a player-controlled human. In a real game youprobably would want to add multiple responses for each given situation and thenrandomly select among them. This would help prevent the responses from becomingrepetitive and predictable.

 

8-10展示了在电脑控制的大力士和玩家控制的人的战斗中游戏AI如何做出适当的嘲讽。在真正的游戏中你可能会想为每一个给出的情况加入多重响应,然后随机的选择它们。这将有助于预防回应的重复性和可预知性。

 

Example 8-10.Giant taunt script

 

If(Creature==Giant)and(player==Human)

Begin

if(PlayerArmed==Staff)

Say("Youwill need more than a staff, puny human!");

if(PlayerArmed==Sword)

Say("Dropyour sword and I might not crush you!");

if(PlayerArmed==Dagger)

Say("Yourtiny dagger is no match for my club!");

End

 

Of course, thistype of scripting isn't limited to adversarial characters that are out to killthe players. Benevolent computer-controlled characters can use the sametechniques. This can help the script writer create an engaging and immersiveplot. Example 8-11 shows how a script helps construct a plot and guide theplayer actions toward the game goals.

 

当然,这种形式的脚本并不仅限于想要杀死玩家的敌人。友善的NPC也可以使用这项技术。这将有助于脚本作者完成动人的immersive的情节。例8-11展示了脚本如何构建剧情并引导玩家接近游戏的目标。

 

Example 8-11.Benevolent AI script

 

If(Creature==FriendlyWizard)

Begin

if(PlayerHas==RedAmulet)

Say("I seeyou found the Red Amulet.

 

Bring it to thestone temple

and you will berewizard.");

end

 

As Example 8-11shows, a vital piece of information concerning where the amulet should beplaced won't be revealed to the player until the amulet is found and the playerconfronts the friendly wizard.

 

正如例8-11展示的,如果玩家没有得到护身符或者没有见到友善的向导时一条重要的信息护身符应该放在哪里是不会被透漏给玩家的。

 

The previousscript examples show how game AI can respond in a given situation, but it'salso sometimes necessary for game characters to have some type of verbal interactionwith the player. This could be benevolent characters meant to provide theplayer with helpful information, or perhaps a less-than-honest character meantto intentionally mislead the player.

 

先前的脚本实例展示过游戏AI如何给定的状态做出反应,但有时候对于游戏角色来说有必要与玩家进行某种类型的语言交互。这可能是友善的NPC向玩家提供有用的信息,或者是一个不诚实的角色有意地误导玩家。

 

In this type ofscenario, the player needs some mechanism to input text into the game. The gameengine then makes the text strings available to the script system, whichanalyzes the text and provides an appropriate response. Figure 8-3 shows howthis might appear in an actual game.

 

在这种类型的关卡中,玩家需要某种机制来向游戏输入信息。然后游戏引擎让脚本系统可以使用这些文本,以便于分析文本并对此做出适当的响应。图8-3展示了这在真正游戏中的样子。

 

In the case ofFigure 8-3, the player would type in the text "What is your name?"and the scripting system would return the text "I am Merlin." Example8-12 shows a basic script that you could use to accomplish this.

 

在图8-3的情况中,玩家输入你的名字是什么?然后脚本系统会返回我叫梅林。8-12展示了一个可以完成这个任务的基本的脚本。

 

Example 8-12.Basic "What is your name?" script

 

IfAsk("What is your name?")

Begin

Say("I amMerlin.");

End

 

Figure 8-3.Merlin

 

Of course,Example 8-12 does have one serious flaw. It works only when the player types inthe exact text of the question as it appears in the script. In reality, you canform a question in many way. For example, what happens if the player enters oneof the lines of text shown in Example 8-13?

 

当然,例8-12存在严重的缺陷。只有当玩家键入了准确的问题,跟脚本中出现的一样的时候,他才能工作。实际上,你可以以许多方式提出这个问题。例如,如果玩家键入了例8-13中的一个会发生什么呢?

 

Example 8-13.Example player input

 

What's yourname?

Whats your name?// 能这么缩写?

What is yourname.

What is thyname?

What is yourname, Wizard?

Hello, what isyour name?

 

As you can see,the script in Example 8-12 would fail for all the questions shown in Example8-13, even though it's quite obvious what's being asked. Not only can you ask aquestion in many ways, but we also have to consider the possibility that theplayer might not form the question in a correct manner. In fact, you can seethat one of the example questions ends in a period rather than a question mark.We could have strict requirements for the player-entered text, but it wouldhave the effect of removing the player from the immersive effect of the gamewhenever he made the inevitable minor error.

 

正如你所看到的,8-12中的脚本对例8-13中的问题一点作用也不起,即使很明显是在问什么。因为你可以用很多方式问同一个问题,所以我们不得不考虑玩家可能组织一个意义上正确的问题。事实上,你可能注意到其中一个例句是以句号而不是问号结束的。我们可以严格的要求玩家输入的文本,但是一旦他犯了不可避免的小错误,这就会减弱游戏给玩家带来的immersive的效果。

 

One alternativeto checking each literal text string is to create a language parser to deciphereach sentence to determine exactly what is being asded. For some games asophisticated language parser might be appropriate; however, for most gamesthere is a simpler approach. As you saw in Example 8-13, you can form the samequestion in many ways, but if you'll notice, they all have something in common.They all contain the words "what" and "name". So, insteadof checking for each literal text string, we can simply search for and respondto particular keywords. In this case, the scripting engine simply checks forthe presence of given keywords within a text string.

 

一种选择是检测每一个文本串也就是创建一个语言解释器分析每一个句子来确定到底在问什么。对一些游戏来说可能一个复杂的语言解释器是合适的,但是对于大多数的游戏来说有一个简单的方法。正如你在例8-13中看到的,组织问题的方式可能不同,但是 你是否注意到,它们有一些相同之处。它们都包括单词"what""name"。因此,我们可以简单的搜索并响应特定的关键词来代替检测每一个文本串。既 然这样,脚本系统就可以简单的检测文本串中是否有关键词出现。

 

As Example 8-14shows, the script is checking for the presence of two keywords in theplayer-entered text. Using this approach, the script responds correctly toevery question in Example 8-13.

 

如例8-14所示,脚本检测玩家输入的文本中是否有这2个关键词出现。使用这个方法,脚本就可以正确的响应例8-13中的所有问题。

 

Example 8-14.Keyword scripting

If(Ask("What") and Ask("name"))

Begin

Say("I amMerlin.");

End

 

Now that we'veshown you how to write a typical script to check player input for a give set ofkeywords, let's look at how the actual game engine checks player input for agiven keyword. Example 8-15 shows how to do this.

 

既然我们已经向你展示了如何编写在一个典型的检测玩家的输入是否存在给定的关键词集,让我们看看真正的游戏引擎是如何检测玩家输入中的关键词的。例8-15展示了这怎么实现。

 

Example 8-15.Searching for keywords

 

// 代码段,这段代码写的可谓是相当的别扭

BooleanFoundKeyword(char inputText[kStringLength], char searchFor[kStringLength])
{

charinStr[kStringLength];

charsearchStr[kStringLength];

int i;

 

for(i=0;i<=strlen(inputText);i++)

{

inStr[i]=inputText[i];

if(((int)inStr[i]>65)&& ((int)inStr[i]<=90))

inStr[i]=(char)((int)inStr[i]+32);

}

 

for(i=0;i<=strlen(searchFor);i++)

{

searchStr[i]=searchFor[i];

if(((int)searchStr[i]>=65)&& ((int)searchStr[i]<=90))

searchStr[i]=(char)((int)searchStr[i]+32);

}

 

if(strstr(inStr,searchStr)!=NULL)

return (true);

 

return (false);

 

}

// 代码结束

 

Example 8-15shows the actual code in the game engine that is invoked whenever the"Ask" function is called from the game designer's script. Thisfunction takes two parameters: inputText, which is the line of text the playerentered, and searchFor, which is the keyword we want to search for. The firstthing we do in this function is to convert both strings to all lowercase. Likemany programming languages, C and C++ are case-sensitive. A string containingthe text "Name" is not equal to a string containing the text "name".(不知道为什么书上总是写成"name."We can't rely on the player alwaysusing capitalization consistently or properly. The simplest solution is toconvert all strings to lowercase. That way, it doesn't matter if the playerenters all uppercase, all lowercase, or some combination.

 

8-15展示了游戏引擎中的真正代码,无论何时游戏设计者的脚本调用了Ask(),也就是间接调用 了引擎中的代码(?)。这个函数take两个变量:inputText,这是玩家输入的文本行,和searchFor,这是我们想要搜索的关键词。在这个 函数中我们做的第一件事是将两个字符串转化成小写字母。就像许多编程语言一样,CC++是大小些敏感的。字符串"Name""name"是不等同的。 我们不能指望玩家总是以大写字母开头。最简单的解决办法就是把所有的字符串都转化成小写字母。这样,无论玩家输入的全是大写、全是小写还是大小写兼有都没有问题了。

 

Once we have twolowercase strings, we call the C function strstr to compare the text strings.The strstr function searches inStr for the first occurrence of searchStr. IfsearchStr is not found in inStr, a null pointer is returned.

 

一旦有了2个小写的字符串,我们就可以调用C语言的strstr函数来比较文本串了。strstr函数在inStr中搜索searchStr出现的第一个位置。如果没有找到,则返回一个空指针。

 

Scripting Events

脚本事件

 

Now let'sexamine some of the other ways scripting can make gameplay more immersive. Theprevious sections showed how scripts alter the behavior of AI characters.Scripting behavior goes a long way toward making games and AI characters seemmore real. However, you can use scripting to make games more entertaining andrealistic in other ways as well. In this section we examine how scripts triggerin-game events that might not be related directly to AI characters. Forexample, perhaps stepping on a particular location will trigger a trap. Example8-16 shows how this might look in a text-based scripting language.

 

现在让我们来分析一下脚本的其它形式来使游戏运行的更immersive。前一部分展示了脚本如何控制AI角色的行为。为了让游戏和AI角色看起来更真实脚本行为帮助很大。但是,在 其他方面脚本同样可以让游戏更有趣更真实。在这一部分,我们研究如何用脚本控制与AI角色直接相关的游戏事件的触发器。例如,走上一个特殊的位置也许将会触发一个陷阱。例8-16展示了这在基于文本的脚本语言中是个什么样子。

 

Example 8-16.Trap event script

 

8-16 陷阱脚本事件

 

If(PlayerLocation(120,76))

Trigger(kExposionTrap);

 

If(PlayerLocation(56,16)

Trigger(kPoisonTrap);

 

As Example 8-16shows, the scripting system can compare the player position to somepredetermined value and then trigger a trap if they are equal. Of course, youcan make this much more sophisticated by making the triggering mechanism morecomplex. Perhaps the trap is triggered only if the player is holding a certainitem or wearing a particular piece of armor.

 

如例8-16所示,脚本系统会拿玩家的位置和预先设定的值比较,当它们相等的时候陷阱就被触发了。当然,你也可以通过创建更复杂的触发机制来让这变得更复杂些。也许只有当玩家持有某一物品或者穿了一件特殊的护甲时陷阱才被触发。

 

Scripting alsocan be an effective way to add a sense of ambience to gameplay. For example,you can link certain situations or objects to particular sound effects. If theplayer walks on a dock, a seagull sound effect might be triggered. You coulduse an entire scripting file solely for linking sound effects to differentsituations.

 

脚本也可以是增加游戏气氛的有效途径。例如,你可以将某些情况或对象和特殊的音效相关联。当玩家走上码头时,海鸥的声音被触发。你可以一整个脚本文件来把音效和不同的情况连接。

 

Figure 8-4 showsthe player standing in a doorway. This would be an excellent situation to linkto a creaking-door sound effect.

 

8-4展示了玩家站在门口的画面。这是放置门吱吱作响的音效的极好位置。

 

Figure 8-4. DoorSound script

 

Example 8-17shows how the player location or game situation, such as the game time, cantrigger relevant sound effects.

 

8-17展示了如何通过玩家的位置或是游戏状态(像游戏的时间)来触发相关的音效。

 

Example 8-17.Triggered sound script

 

If(PlayerLocation(kDoorway))

PlaySound(kCreakingDoorSnd);

 

If(PlayerLocation(kDock))

PlaySound(kSeagullSnd);

 

If(PlayerLocation(kBoat))

PlaySound(kWavesSnd);

 

If(GameTime==kNight) // 晚上放蟋蟀的声音

PlaySound(kCricketsSnd);

 

If(GameTime==kDay) // 白天放鸟叫

PlaySound(kBirdsSnd);

 

Although thischapter differentiated between the types of AI scripting, in a real game it canbe beneficial to use them together. For example, instead of a player actiontriggering an effect such as a sound effect, perhaps it triggers a specificcreature AI patrolling pattern. We also showed examples of how AI creatures canrespond to text entered by the player; however, this also can be a very usefulway to trigger in-game events. For example, the player could recite a spellthat triggers some event.

 

虽然本章区分了AI脚本的不同类型,但是在真正的游戏中结合使用它们会很有好处。例如,用玩家的动作触发一个特殊AI人物的 巡逻模式来代替触发一个音效。我们同样展示了AI人物如何来响应玩家键入的文字,这同样会是触发游戏事件的有效途径。例如,玩家可以背出一段符咒来触发什么事件。

 

Further Information

更多信息

 

In this chapterwe showed you how to implement basic scripting that enables you to alter gameAI outside the main game program. Such scripting can be very effective. Indeed,we successfully implemented these techniques in an MMORPG to enable gamemasters to change the game AI and other game parameters in real time.Implementing a full-fledged scripting engine can be very challenging, and itinvolves additional concepts that we have not yet covered. These conceptsinclude finite state machines and rule-based systems, which we'll get to inChapters 9 and 11 of this book.

 

这一章向你介绍了如何实现基本的脚本系统来响应游戏主程序外的AI。这样的脚本非常奏效。Indeed,我们已经成功地将这些 技术应用于MMORPG中从而使游戏管理员能够实时地改变游戏AI及其他的游戏参数。实现一个功能完善的脚本系统是十分具有挑战性的,它还包含许多我们没有设计的概念。这包括有限状态机和规则集系统,你可以在本书的第911章获得这些知识。

 

If you decide topursue scripting even further than we do in this book, you might find thefollowing resources to be particularly helpful:

 

如果你决定继续研究本书所没有涉及的脚本知识,下面的资料可能对你有很大的帮助:

 

AI ApplicationProgramming by M.Tim Jones(Charles RiverMedia)

应用程序AI编程 M.Tim Jones(Charles River Media)

AI GameProgramming Wisdom by Steve Rabin, ed.(Charles RiverMedia)

游戏AI编程知识 SteveRabin等著(CharlesRiver Media)

 

In the firstreference, author Tim Jones shows how to implement a scripted rule-based systemfrom scratch. His approach combines we covered in this chapter and those wewill cover in Chapter 11. The second reference includes seven articles writtenby game programming veterans focusing specifically on issues related toimplementing scripting engines for games.

 

在第一本参考书中,作者Tim Jones展示了如何实现一个规则集脚本系统from scratch。他的方法包括了这一章和11章中涉及的内容。第二本参考书包括7篇由游戏编程老手写的文章,这些文章特别的聚焦于已经发布的涉及实现游戏脚本引擎(?)

 

 

后记:这篇译文来自第 8章,翻译的感觉是大部分段落简单易懂,部分语句需要推敲。至于知识,译者认为,平平无奇,没能学到什么知识。开始还想从中得到什么脚本分析之类的知识,现在看来我还是老老实实地去学习编译原理解释原理什么的吧。由于目前对UI的研究可能用到有限状态机的知识,或许会对第9章进行翻译,如果能找到别的资料 就不翻译了,对这本书没什么好感了。

 

这本书用处最大莫过于目录了,是个不错的参考,但是你自己找相关资料学习比较好。目录列表如下:

 

 

Preface

 

1.               Introduction to Game AI

DeterministicVersus Nondeterministic AI
Established Game AI
The Future of Game AI

 

2.               Chasing and Evading

Basic Chasingand Evading

Line-of-SightChasing

Line-of-SightChasing in Tiled Environments

Intercepting

 

3.               Pattern Movement

Standard Algorithm

Pattern Movement in Tiled Environments

Pattern Movement in Physically Simulated Environments

 

4.               Flocking

Classic Flocking

Flocking Example

Obstacle Avoidance

Follow the Leader

 

5.               Potential Function-BasedMovement

How Can You Use Potential Functions for Game AI?

Chasing/Evading

Obstacle Avoidance

Swarming

Optimization Suggestions

 

6.               Basic Pathfinding and Waypoints

Basic Pathfinding

Breadcrumb Pathfinding

Path Following

Wall Tracing

Waypoint Navigation

7.               A* Pathfinding

Defining the Search Area

Starting the Search

Scoring

Finding a Dead End

Terrain Cost

Influence Mapping

Further Information

8.               Scripted AI and ScriptingEngines

Scripting Techniques

Scripting Opponent Attribures

Basic Script Parsing

Scripting Opponent Behavior

Scripting Verbal Interaction

Scripting Events

Further Information

9.               Finite State Machines

Basic State Machine Model

Finite State Machine Design

Ant Example

Further Information

10.            Fuzzy Logic

How Can You Use Fuzzy Logic in Games?

Fuzzy Logic Basics

Control Example

Threat Assessment Example

 

11.            Rule-Based AI

Rule-Based System Basics

Fighting Game Strike Prediction

Further Information

 

12.            Basic Probability

How Do You Use Probability in Games?

What is Probability?

Probability Rules

Conditional Probability

 

13.            Decisions UnderUncertainty--Bayesian Techniques

What is a Bayesian Network?

Trapped?

Treasure?

By Air or Land

Kung Fu Fighting

Further Information

 

14.            Neural Networks

Dissecting Neural Networks

Training

Neural Network Source Code

Chasing and Evading with Brains

Further Information

 

15.            Genetic Algorithms

Evolutionary Process

Evolving Plant Life

Genetics in Game Development

Further Information

 

Appendix: VectorOperations

 

Index