4

我正在尝试构建 MUD(多人互动小说游戏)

我处于设计/概念化阶段,遇到了一个我无法提出解决方案的问题。我希望一些更有经验的程序员能给一些建议。

这是我能解释的最好的问题。当玩家决定执行一个动作时,他会向服务器发送一个命令。然后服务器处理命令,确定是否可以执行该操作,然后执行该操作或以无法执行的原因进行响应。一个动作可能失败的一个原因是玩家正忙于做其他事情。例如,如果一个玩家在战斗中刚刚挥动了一把巨大的阔剑,他可能需要 3 秒才能重复这个动作。如果玩家很快再次尝试挥杆,游戏将响应指示他必须等待 x 秒才能这样做。现在,我可能可以毫不费力地设计这个。我遇到的问题是如何从 AI 生物中复制这种行为。服务器自行执行的所有事件,也不是对玩家所做的事情的立即反应,必须是时间敏感的。一些邪恶的怪物对你施了咒语,但必须等待 30 秒才能再次施法……我想我可能会将所有这些事件添加到某种事件队列中,但我怎样才能使该事件队列对时间敏感?

4

7 回答 7

4

MUD 动作通常在“滴答”上执行,而不是立即执行 - 这允许有限的延迟影响,并允许将怪物的命令插入队列并公平处理。

就个人而言,我不喜欢这种方法,但几乎 99% 的 MUD 都使用它。您需要设计一个强大的命令队列和事件队列,可以同时处理 AI 和用户命令。然后,您可以将“虚拟延迟”添加到 AI 命令中,这些命令可能是预定义的或所有用户延迟的平均值,或者您喜欢的任何内容。

于 2010-04-30T22:43:14.973 回答
3

人工智能是客户。

它们仅在最远的视图中是“服务器的一部分”。它们实际上在主游戏引擎之外。他们是没有人的专业客户。

AI 客户端与服务器的接口与人类客户端的接口相同。

于 2010-05-01T11:57:41.843 回答
2

好吧,你的 AI 控制的实体有某种“我接下来要做什么?” 方法对不对?当另一个动作正在进行时,只需让该方法返回“我很忙,继续做我正在做的事情”结果。

例如

class ToughGuy(AI):
   Action_Idle, Action_BroadswordSwing, Action_CastingMagic = range(3)

   MagicRange = 10
   MagicTime = 8
   MeleeRange = 4
   MeleeTime = 2

   def __init__(self):
      self.action = ToughGuy.Action_Idle
      self.actiontimer = 0

   def Update(self, timestep):
      if self.actiontimer <= 0:
         self.action = ToughGuy.ActionIdle
      else
         self.actiontimer -= timestep

      if self.action == ToughGuy.Action_Idle:
         global player # don't do this
         if self.AmIFacing(player):
            distance = DistanceBetween(self, player)
            if distance < ToughGuy.MeleeRange:
               self.action = ToughGuy.Action_BroadswordSwing
               self.actiontimer = ToughGuy.MeleeTime
            elif distance < ToughGuy.MagicRange:
               self.action = ToughGuy.Action_CastingMagic
               self.actiontimer = ToughGuy.MagicTime

等等。对于可变编码标准感到抱歉... ;)

于 2010-04-30T23:18:52.117 回答
2

您可以使用线程来处理特定类型的 Mobs,并将所有实例放入某种数组中。然后,线程简单地通过列表重复应用逻辑。DelayTimeStart 和 Delay 可以是父 Mob 类的属性,并且当线程通过循环时,它可以推迟处理 Mob 的任何实例,其中有时间剩余延迟。

于 2010-11-16T02:46:01.593 回答
1

也许你会在这里找到实现的例子:

于 2010-11-29T08:35:08.453 回答
0

我将从 LPMud/LDMud 的角度为您提供答案。

MUD 中的每个玩家都是 player.c 的一个实例。Player.c 继承自 living.c。有生命的东西有心跳。对于泥浆上的每个活体(或任何具有 heartbeat() 函数的物体),heartbeat 函数每 2 秒处理一次。定时事件通常不是基于秒,而是基于通过对象内的计数器经过的心跳数。

适用于您的问题的好消息是怪物也继承自 living.c。这意味着,如果您的操作只能定期执行,则可以根据已发生的滴答数在心跳内进行管理。

于 2014-02-04T18:01:41.787 回答
0

一个基本的方法是拥有一个代表邪恶怪物的法术实例的数据结构,上面有一个冷却计时器。使用能量时,冷却时间被设置(大概是由法术的主定义定义的秒数);再次尝试使用它会像玩家能力一样失败。这可以通过让队列检查冷却时间与事件队列集成,如果它没有过期,则等待它过期,或中止操作,或重新安排操作,视情况而定。

于 2011-02-02T20:47:28.400 回答