2

I'm trying to learn the Command design pattern and apply it to the game I'm working on. First I read about the general implementation, and I feel like I understand it pretty well. Now I want to know how to use it in games. I started reading this book about design patterns in games and in the section about the command pattern the author says:

We can use this same command pattern as the interface between the AI engine and the actors; the AI code simply emits Command objects.

I've programmed game AI before and I have trouble understanding how this pattern helps. Usually when programming AI you want the instructions to be executed instantly, I also can't see what other flexibility this pattern provides, since you won't be for example swapping out different commands (like in the input example).

The author mentions that :

The decoupling here between the AI that selects commands and the actor code that performs them gives us a lot of flexibility. We can use different AI modules for different actors.

Isn't this achievable with a simple interface between the game's AI and the actor? Could someone give me an example of a setup where the command design pattern is used as suggested in this book?

  • Why would you implement a different interface for the AI? The command-based interface you already have gives you those benefits for free. – Goyo Sep 28 '18 at 15:55
  • @Goyo The problem is that I don't know what the benefits are in case of AI. – Wojtek Wencel Sep 28 '18 at 16:07
  • "The decoupling here between the AI that selects commands and the actor code that performs them gives us a lot of flexibility. We can use different AI modules for different actors." And maybe more. – Goyo Sep 28 '18 at 16:40
  • @Goyo That's when I asked: Isn't this achievable with a simple interface between the game's AI and the actor? – Wojtek Wencel Sep 28 '18 at 16:45
  • 2
    I don't think that's clear in your question but I can give an answer to that. – Goyo Sep 28 '18 at 17:43
3

You are right in that its just another way to compartmentalise your code, not the only solution.

But consider that often you want your ai code to generate a list of commands for an actor to follow.

  1. move to x,
  2. pickup y,
  3. move to z,
  4. drop y

While the first actor is moving to x the ai can loop through other actors which are blocked or have completed their commands generating new instructions for them.

The command pattern is a good (but not the only) fit for this style of programming

  • Is there any use for this pattern if I don't want to use a command stream (if I understand correctly that's what your example does)? Most often I find myself writing AI that does something only when the previous action is finished. – Wojtek Wencel Sep 28 '18 at 16:02
  • 1
    @WojtekWencel: That's simply a matter of who is doing the waiting. In your system, the AI is sitting there asking, for each frame, "Have you moved to X yet?" If that returns true, then it says "pickup y". In the command stream way, the AI sends a list of commands, and then sits there. The command processor for the actor is the one who asks every frame "Have you moved to X yet?". – Nicol Bolas Sep 28 '18 at 16:06
  • you are still seperating the ai and the actor, but sure there are other ways of do that. I guess I would say take a look at your ai code and see if it doesnt make sense to generate mote than one command at the same time. after all, if its caculated that the actor shpuld move to x, presumably its worked out the reason to move to x at that point. you dont need to wait for the actor to move before saying, once command 1 is finished do this – Ewan Sep 28 '18 at 16:08
  • @NicolBolas Oh, okay. So I guess there is no simple benefit in this case, it's just another way of organizing things. – Wojtek Wencel Sep 28 '18 at 16:09
3

The Intent section for the Command pattern in the Go4 book reads:

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

Let's break some of that down, and look at it in context of game programming.

The Ability to Parameterize the Invoking Code

This allows you to dynamically configure the thing that invokes the command with an action to execute. This can also be achieved with callbacks. Command objects can serve as on OO replacement for callbacks in a language that doesn't support them in a way that you need (e.g., no support for higher-order functions, or no support for closures); but if you need to access or manipulate the state associated with the command later, or to support more complex interface then just Execute(), having a Command class can help.

In the book, the pattern in introduced in the context of developing a framework for application menus, where a menu item can be configured by a Command. The important bit is that the menu item has no idea what it does or what the target object is - it has no understanding of the operation it executes, it just knows that something should happen when it's clicked.

enter image description here

You can vary this basic structure; for example, the receiver my be referenced indirectly, via an ID of some kind (and fetched by some other component).

In games, and specifically in game AI, one rather similar scenario is when you want to support scripting - a command can encapsulate a user-provided script (and maybe carry some metadata along, and possibly a reference to the scripting engine). Here, the calling code knows when and under what circumstances to execute a script, but has no idea what to do and which entities to affect. (Of course, there are other ways to do it). This promotes separation of concerns between different systems involved (AI, Scripting).

But also, consider something less exotic. Keybindings. There could be multiple keys (or multiple triggers on different input devices) that invoke the same action, or actions can be context-dependent (same key does a different thing in different situations). Furthermore, the player can change these at any time. One way to handle this is to have a set of command objects that you can just plug into and out of the system that handles input, associating them with various triggers dynamically.

The Ability to Queue Requests

Once you have this infrastructure in place to map inputs to commands, you can leverage it in your AI system to control NPCs.

Now, you said:

Usually when programming AI you want the instructions to be executed instantly

Well, they don't have to be executed right at the moment the decisions are made - just within the current cycle in the game loop. Besides, if the game is using the ECS pattern, a command stream approach may be a good fit. Also, some games run their AI engines at a different update rate then the renderer and the rest of the game, and queuing AI output as commands may be a good way to approach this.

Support for Logging

This can mean literally logging, but let's think beyond that. A log is a recorded stream of events. That can potentially be (when constructed with some care), played back. Replay & demo support out of the box! Add in some timing metadata, and with some effort this can also support things like the time rewind mechanic, where the player can rewind time (up to a certain point) to try the same scenario again (something along the lines of what's possible in Braid, or in GRID 2).

Extra Goodies

The ability to support undo/redo is pretty self explanatory, so I won't go into it.

Another interesting thing you can do is combine this with the Composite pattern, which then enables you to have composite commands - which are made of subcommands. This may simply be treated as a convenience for you as a developer, but this could also provide support for building editors where users can build these composite commands in a GUI, or even enable you to incorporate this into gameplay, where the player can could build custom behaviors as a part of some mechanic - and have the game remember them (since you can serialize and deserialize commands, including composite commands).

Another benefit of treating commands as objects or data is that you can flexibly execute some of them in parallel (if the tasks are parallelizable), which may improve performance.

  • Wow, thanks for the extensive reply, I understand it much better now! – Wojtek Wencel Sep 29 '18 at 0:25
0

In the book, the main motivation for using the command pattern in the first place is explained some paragraphs before your quotes and it is about the user input, not the AI.

We can use this same command pattern as the interface between the AI engine and the actors; the AI code simply emits Command objects.

By the time when you "can use this same command pattern as the interface between the AI engine and the actors" you are supposed to be already using the commands as a way to translate user input to actions in the game. Otherwise the quote doesn't even have sense.

The decoupling here between the AI that selects commands and the actor code that performs them gives us a lot of flexibility. We can use different AI modules for different actors.

It may be true that you can achieve the same benefits by other means, but by using what you already have you get them for free.

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.