游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4124|回复: 5

一个AI设计的思考过程(继续1 )

[复制链接]

38

主题

96

帖子

148

积分

注册会员

Rank: 2

积分
148
发表于 2004-6-10 14:29:00 | 显示全部楼层 |阅读模式
所有的事都很简单
----- 从原始状态开始
       
        我看过很多别人的文章,有些可以看懂,有些则不能,但我每次看懂时都会觉得很简单的,其实我浪费了很多心思去了解作者的习惯和一些基础但将数不清楚的内容上,这是一个讨论AI的文章,不便在此对其他更基础的东西进行讨论,但是介绍一些与所要讨论的主题有关的内容是必要的,以免浪费讨论主题的时间。我假设你已经是一个能够写Windows程序,并能独立完成一个能够控制小人在地板上走动的人。如果还不能最好去学好那些基础,否则看着些代码将会很头痛。


        我们将在AiTestApp.cpp 里面开始我们的介绍。
HRESULT CAiTestApp::Init() 用于初始化一些对象数据 如果调用失败就返回一个E_FAIL; 如果调用成功就返回S_OK;
HRESULT CAiTestApp::Release() 用于是放在 Init 中初始化的对象。最后返回S_OK;
LRESULT CAiTestApp::OnMessage( UINT message, WPARAM wParam, LPARAM lParam ) 用于接收消息,这里一半用于接收windows消息,如键盘鼠标等响应消息。
void CAiTestApp:rocess() 系统每隔 33 毫秒就调用一次,我们把这个作为主处理函数。

HRESULT CAiTestApp::Render() 每次调用了Process render就会被请求调用,基本可以跟上显示更新速度。

一般来说我们建立每一个要在系统中运行的对象都有以上几个处理函数。都很象。
class CObject
{
    bool Init();
    void Release();
         OnMessage(UINT message, WPARAM wParam, LPARAM lParam );
    Void Process();
    Void Render();
};
事物 { 初始化,释放,消息响应,处理,渲染 } 我在考虑这个对象的内容时就不必考虑别的对象。

CStageScene, CCharacter 这两个都属于AI的环境(一切都是AIWorker的环境) CCharacter 语义上说过的 有行为对象相对应。
// 游戏中有行为的对象
class IActionObject : public IObject
这个对象有两个状态和一个行为, {空闲(eaIdle) 行走(esWalk)} 和 { 向哪个方向移动(MoveTo( dir)) }

CStageScene 给出了人物行走的空间参照坐标。人物的移动都是参照这个坐标系的。

有行为的对象必须理解:基本上是,做事情依赖于状态机和指令作相应的动作,
例如我发出 MoveTo 指令 那他一定听话去做移动一步。

接下来是虚拟机,前面提出过要建立一套AI语言才能更好的表达。写出更可自定义的AI。关于这部分的代码不便说明,
CMD_BEGIN( Move )

    virtual bool Create( const char *szParam )
    {
        m_iDir = atoi( szParam );
        return true;
    }
    virtual int Execute( const int IP )
    {
        theApp.m_Char.MoveTo((CCharacter::enumDir)m_iDir);
        theApp.m_VM.m_Status.Pause();
        return (IP+1);
    }

CMD_PARAM

    int m_iDir;

CMD_END

以上是一个完整的指令定义 只要在VMSCommand.cpp中 用 CMD_BEGIN( 命令名 ) 来定义一个命令. Create中进行参数提取, 把提取出来的参数付给 CMD_PARAM处定义的参数。在Execute里就可以写你的功能,如这里调用了主角的MoveTo。

为了实现我前面提到的AI实现想法,我做了这些测试环境。以上是对各部分的功能简单介绍一下。如果有兴趣继续讨论下面的实现方法,请尽快理解一下这部分代码。这样才好有个可以交流的环境。

sf_2004610142933.zip

36.56 KB, 下载次数:

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
发表于 2004-6-10 15:41:00 | 显示全部楼层

Re:一个AI设计的思考过程(继续1 )

看了楼主的代码了,这个想法吊。。。。
大概看了一下,有几点我不明白:
1,如何在指令里面修改或者更新玩家的状态?
2,如何在保存一个指令产生的临时状态,可能有一些指令是链式的,一个指令的执行会影响另外一个指令,这个状态保存在什么地方呢?
3,这样的写法实际上还是基于编译的啊,修改了脚本以后,需要重新编译之后才能生效?

总的来说,这个。。。。吊。


38

主题

96

帖子

148

积分

注册会员

Rank: 2

积分
148
 楼主| 发表于 2004-6-10 17:01:00 | 显示全部楼层

Re:一个AI设计的思考过程(继续1 )

er...

1. 如何在指令里面修改或者更新玩家的状态?
   玩家的状态或NPC的状态与脚本无关,脚本只依赖当前的环境法除想要做的任务。
2. 如何在保存一个指令产生的临时状态,可能有一些指令是链式的,一个指令的执行会影响另外一个指令,这个状态保存在什么地方呢?
   请问,什么样的指令产生了临时状态? 什么时候会出现指令时连式的? 那一条指令会影响到别的指令?这个指令的状态为什么要保存? 如果你只能给出我对一个概念的问题,我将无法回答,因为,在我的知识体系中,程序只有,顺序和分支(可以向前,也可以向后分支) 只有在进行IF 语句时进行目标分析。
         
      本人又一条原则:不为或许又的事情多想,尽量少想,尽快实现。真正的问题时做的过程中遇到的,而不是想出来的。

3,这样的写法实际上还是基于编译的啊,修改了脚本以后,需要重新编译之后才能生效?
  这种脚本暂时应用在游戏中,基本上是在启动游戏时及时编译,启动之后就可以用了。

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
发表于 2004-6-11 09:10:00 | 显示全部楼层

Re:一个AI设计的思考过程(继续1 )

恩,举个例子吧,NPC逃跑过程中,受到袭击,那么这个之后NPC如果需要改变逃跑的方向。

这里的流程是,首先,NPC被迫逃跑,这个过程应该是一个指令吧,然后再遭受袭击的这个判断指令中,是否应该判断当前是否在逃跑呢?然后再修改逃跑的方向?

因为有些动作是无法一下子完成的,还比如说NPC在追一个玩家。然后发现另一个玩家要也需要去追,那么他是否需要之前的一个决策产生的状态呢?这样来描叙:
NPC->Chase(Player_A);
这个过程并不是一次能完成的,这个时候会产生一个临时状态:NPC_Chasing_Player_A
然后这个状态可能会被Chase这个指令再一次用到,比如说在:
NPC->Chase(Player_B);的这个过程中,NPC_Chasing_Player_A
这个状态可能会影响到是否去追B的决策,那么这个状态如何传递呢?

38

主题

96

帖子

148

积分

注册会员

Rank: 2

积分
148
 楼主| 发表于 2004-6-11 10:46:00 | 显示全部楼层

Re:一个AI设计的思考过程(继续1 )

er...

IntendThinking 这里有一点要说明,在这个过程中只是完成 环境分析,发出任务,

也就是说
if( a ) than (b) else (c)
if( a ) than (b) else (c)
if( a ) than (b) else (c)
if( a ) than (b) else (c)
if( a ) than (b) else (c)
if( a ) than (b) else (c)

很多的这种东西 他们发送个这个 NPC 任务, 相当于大脑,只是会想事情发出指令,并不会去管理是否作了,是否做完,他不会亲自去监视行为是否被执行,他只知道环境是否改变了,是否有新的指令发出。任何的行为都会改变环境的状态, 所以,IntendThinking 是一个简单部件,非常多的简单处理可以完成复杂的事情,有点像二极管,三极管组成电器。这是一部分,是基础思考 或 环境反射 这些简单的判断会影响环境 既然这些简单的判定可以把思考变为简单的环境,那么就把无限复杂的IF 嵌套判定变为只有一级的判定, 这样把一个阶梯形复杂变为了线性复杂。

每一个任务,都应该有一个优先级 发出时间本身就是一种优先级 只有后面的优先级高过了前面的才会改变当前正在处理的事情。

关于决策方法 这里要说每一个问题,  判断一个事情的优先级时 不应当有完全强制最高优先级和最低优先级, 因为在判断时,我们将采用模糊判定:

A Task  P = 100;
B Task  P = 30;

  {
     两个中的优先权总值 T =  100 + 30 = 130 ;
   AP = 100;
   BP = 30;
   }

IA = 0;
IB = 0;
for( int i= 0 ;   i< 10; i++ )
{
  if( rand()%130 < AP )
  {
      IA ++;
  }
  if( rand()%130 < BP )
  {
      IB++;
  }
}

if( IA > IB )
{
           A 大于 B
}

循环次数越多可能与准确,所以为了有比较疯狂的表现,最好不要太多次循环。这是两件事情有影响时的处理想法和做法。

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
发表于 2004-6-11 11:49:00 | 显示全部楼层

Re:一个AI设计的思考过程(继续1 )

:) 我可能想得太多了。。。

其实还有一种可能的,就是简单的A + A 不一定等于 2 * A;
而可能A + A 等于 B;
比如说一个NPC正在追玩家A,但是同时又发现了玩家B,按道理发现玩家就应该去追。
但是如果想实现,发现了一堆玩家,觉得他们的实力要高过自己,然后就会选择逃跑。
也就是说,有些时候不仅仅是决策的优先问题,可能会改变决策。

其实我有个想法,完全可以设置一个状态机来保存各种临时的中间状态。
而每个指令可以产生很多临时状态,而在做其他决策的时候,是否考虑这个状态是
那个决策的问题了,就好象:
在Chase这个命令里面,比较智能的写法可以这样写:
if (previous_target = me->get_condition("Chasing"))
{
     if(current_target->power() + previous_target->power() > me->power())
        me->escape();
}

我是这样想的,一起讨论讨论。。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-7-1 18:15

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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