Thursday, February 16, 2012

Procedurally generated puzzles

Just jotting down some informal thoughts on types of puzzles and how to proceduraly generate them. Each puzzle is really a barrier that you must overcome to get to the other side. Place a puzzle when you need a barrier to seperate zones, protect treasure, or just to keep things interesting.


Minigames. Reminds me of the Wii party games where whichever team gets the best overall score after 5 events wins the tournament. Slider puzzles, tower of hanoi, checkers, gambling, etc. It would take time to code each one but it would also break up the monotony. You could also make the real game a metagame of the minigames. Imagine everyone in the game is obsessed with a collectable card game. By finding new cards in the game world you improve your chances of winning the card minigame, which could lead to rewards that improve your chances of the real game. Done right it would be interesting and fun diversion; done wrongly it would be a tedious and required waste of time.

(days later) I just remembered that Star Wars: Knights Of The Old Republic had this with Pazaak! I was thinking more along the lines of a Magic The Gathering type minigame, but a poker-blackjack hybrid is a good idea too. Neat! Proof that my idea works!


Logic mazes. Reminds me of many games where you have to move like a knight on a giant chess board or slide across the ice in just the right pattern to make it to the other side. For these puzzles you must go from here to there but you must follow a certain way of moving. I think these would be easier to make in reverse. For example, start with an impassible expanse of ice. Start at the end point. Pick a direction and place a block in that neighboring cell. Move the opposite direction a few spaces. Repeat several times, making sure not to place blocks in areas the player will need to later pass through, and you end up with an end point, a start point, and at least one way to move from the start to the end. There are many more examples of logic mazes at http://www.mazelog.com/.


Inventory based. Reminds me of Metroidvania games. You must have a certain item or ability in order to pass. A locked door requires a key, a hall of spikes requires the spike armor, cracked walls require bombs. Basically there's some sort of "lock" and some sort of inventory "key" is required to pass. To place an inventory based puzzle, simply pick something from a preset table of a "lock" and item "key" and place the key somewhere before the lock. Or pick a random item from the world as the key: "The burly guard won't let you pass until you give him A HAM SANDWICH."


Knowledge based. Reminds me of Myst. You must answer a question or enter the correct sequence to pass. A combination lock where the randomized combination is written down elsewhere or a guard who asks you questions that you would only know from reading books in the game or talking to people in the game. Like the inventory puzzles, simply pick something from a preset table of a "lock" and an information "key" and place the randomly generated key somewhere before the lock.


Environment based. Reminds me of many sub puzzles in modern Zelda games. You must change the environment to a certain state before you can pass. Pull the lever to open a door, push all 4 buttons to lower the bridge, set all 6 torches on fire to open the treasure chest, redirect the laser to destroy the statue. This could be a superset of sokoban puzzles which are really just "push the blocks into the marked places". If you look at it a certain way, the requirements or triggers could even involve other people or groups: the king must be dead, the mages guild must be at war with the fighters guild, the price of milk must be low, the senate must be mostly of the Merchant's Alliance, etc.



These puzzles can be combined to form larger and more intricate puzzles:

To get the treasure chest you must push all four buttons
  • to push button 1 you just walk over and push it
  • to push button 2 you must cross a bottomless pit
    • to cross the pit you must purchace Flying Boots or know how to teleport
  • to push button 3 you must open the giant door
    • to open the door you must find and reassemble the 2 gears to the door machinery
      • gear 1 is on the other side of a giant randomized sokoban puzzle
      • gear 2 is buried at a random location
        • shovels can be purchaced at stores
        • the location is on a map you find in the dungeon
      • reassembling the gears is a slider puzzle
  • to push button 4 you must defeat the guardian with a special sword and a special shield 
    • to get the special sword you must help the dying king
      • the king will give you the sword if you give him an elixer of life that no one knows how to make
        • the recipe is randomly generated but written in a recipie book - or you could just start mixing things and get lucky
    • to get the special shield you must play the specific melody on the piano
      • the notes of the randomized melody are written on the wall of another room
You could create a puzzle like this at each dungeon or important location or create one giant puzzle that includes all the major locations in the game world.

Ideas like this aren't worth much unless actually implemented though. I'll have to create some proof of concept or even a roguelike that has puzzles like this in it. One of these days.

Saturday, February 11, 2012

Problems, solutions, and sandwiches

Let's say you have a screwdriver and you happen upon a loose screw that needs to be tightened. Using the screwdriver to fix the loose screw seems like a pretty good idea - and it probably is.

Now you happen to have a loose nail that needs to be fixed. You know you should use a hammer, but if you're really lazy, don't have enough time to fetch a hammer, or if someone else insists on it, then you could probably bang the nail in with your screwdriver. Yes, it won't work as well as a hammer, you may damage the screwdriver, and you may hurt yourself, but at the end of the day you will have fixed the loose nail. You can then go home with a banged up screwdriver and sore hand and wish you could do it the right way. Not ideal, but it happens from time to time.

Now you happen to have an empty stomach. You really should eat a sandwich but instead you reach for your screwdriver. Why? Maybe everyone keeps talking about using a screwdriver so you go along. Maybe someone doesn't realize that even though sandwich and screwdriver have many letters in common, they're not the same. Or maybe you happen to have the screwdriver in your hand and really think it can help. For whatever reason, you, or someone else, decides that eating your screwdriver is a perfectly acceptable way to fix your empty stomach. Despite your best efforts and after several days or weeks, the best you can hope for is a broken screwdriver and several broken teeth. And you still have an empty stomach.



This may or may not be a thinly disguised allegory for certain events that may or may not happen when programming on projects that involve several other people and hard deadlines. This has been one of the most difficult things for me to deal with.

Friday, February 10, 2012

A possible algorithm for Zeldalike overworlds

The 2012 7DRL challenge is one month away!


I've been thinking about how to procedurally create a Zeldalike map for a roguelike. By Zeldalike I mean the important parts that I remember from playing the original Zelda game: it was broken into screen-sized chunks, everywhere was reachable (although sometimes you had to get an item first), there were different themed areas, it wasn't too dense or too sparse - it was interesting, charming, and fun.


Here's an algorithm that should come up with something interesting like Zelda's overworld Hyrule. It creates one array of tiles and one array with details about each screen-sized chunk of the world.

Since the world will be broken into screen sized chunks, we can start by determining how those screens will be connected. Let's start with a 16x5 array of screens that have no connections to any neighbors.

This is a high-level view of the world. If you were to print it out, it may look something like this where each screen is represented as a blank space and the walls between them are solid spaces.
#################################
# # # # # # # # # # # # # # # # #
#################################
# # # # # # # # # # # # # # # # #
#################################
# # # # # # # # # # # # # # # # #
#################################
# # # # # # # # # # # # # # # # #
#################################
# # # # # # # # # # # # # # # # #
#################################
With the array of screens, create a simple perfect maze.

When printing out how the screens are connected to make a big maze, it would look something like this. We can see that this time, the top left screen has an open path to the screen to the east. After traveling east a few screens, you can go south.
#################################
#       #                       #
####### ### ##### ###############
#       # #     #               #
# # ### # # ######### # ### ### #
# # #           #   # #   #   # #
# ### # # ####### ### # ##### # #
# #   # #           # #     # # #
# # # ##### # # ############# # #
# # #   #   # #             # # #
#################################
Remove some of the walls to connect screens. There are now loops and many ways to move around. Now when traveling east from the top left screen you can go south on the second screen or continue to the fourth screen and go south.
#################################
#       #                       #
### ### ### ##### # # ###########
#       #                       #
# # ### # # ######### # ### ### #
# # #           #   # #       # #
# ### # # ####### ### # ##### # #
# #   # #           # #     # # #
# # # ##### # # ############# # #
# # #   #   # #             # # #
#################################
Assign themes to some of the screens. I'm just using 1 through 5 as arbitrary themes. They could be like the original zelda: brown rock, green rock, brown forest, green forest, cemetary, etc or they could be your own themes.
#################################
#  1    #  2 3                  #
### ### ### ##### # # ###########
#      4#    4                  #
# # ### # # ######### # ### ### #
# # #           #  1# #       # #
# ### # # ####### ### # ##### # #
# #   #5#        3 5# #    2# # #
# # # ##### # # ############# # #
# # #   #   # #             # # #
#################################
Spread the themes to adjacent screens that are connected.
#################################
#1 1 1 4#2 2 3 3                #
### ### ### ##### # # ###########
#  1 4 4#  2 4 4                #
# # ### # # ######### # ### ### #
# # #  5        #3 1# #       # #
# ### # # ####### ### # ##### # #
# #   #5#      3 3 5# #  2 2# # #
# # # ##### # # ############# # #
# # #   #   # #             # # #
#################################
Continue spreading them until all screens have a theme. This ensures that the themes match the path that the player has to walk through and the user should feel like they spend some time in each theme before entering a different one.
#################################
#1 1 1 4#2 2 3 3 3 3 3 3 3 3 3 3#
### ### ### ##### # # ###########
#1 1 4 4#2 2 4 4 4 4 4 2 2 2 2 2#
# # ### # # ######### # ### ### #
#1#1#5 5 5 2 2 2#3 1#4#2 2 2 2#2#
# ### # # ####### ### # ##### # #
#1#5 5#5#5 3 3 3 3 5#4#2 2 2#2#2#
# # # ##### # # ############# # #
#1#5#5 5#3 3#3#3 3 3 3 3 3 3#2#2#
#################################
#####################&&&&&&&*********
#     ##     ##     #&     &*     ** 
#  1  ##  1  ##  1  #&  4  &*  2  ** 
#     ##     ##     #&     &*     ** 
#####################&&&&&&&*********
##############&&&&&&&&&&&&&&*********
#     ##     #&     &&     &*     ** 
#  1  ##  1  #&  4  &&  4  &*  2  ** 
#     ##     #&     &&     &*     ** 
##############&&&&&&&&&&&&&&*********
##############%%%%%%%%%%%%%%%%%%%%%%%
#     ##     #%     %%     %%     %% 
#  1  ##  1  #%  5  %%  5  %%  5  %% 
#     ##     #%     %%     %%     %% 
##############%%%%%%%%%%%%%%%%%%%%%%%
#######%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#     #%     %%     %%     %%     %% 
Now we can build the real world map based on the array of screens created in the earlier part. For each cell in the array of screens, plop down a screen sized chunk in the world array. For this example I'll make each screen 7x5 tiles large and just show the top left few screens but a real game would have much larger screens. I will also put the theme number and use different border tiles for each theme.
#####################&&&&&&&*********
#     ##     ##     #&     &*     ** 
#  1      1      1      4  &*  2     
#     ##     ##     #&     &*     ** 
########## ##########&&& &&&*********
########## ###&&&&&&&&&& &&&*********
#     ##     #&     &&     &*     ** 
#  1      1      4      4  &*  2     
#     ##     #&     &&     &*     ** 
### ###### ###&&&&&&&&&& &&&*** *****
### ###### ###%%%%%%%%%% %%%%%% %%%%%
#     ##     #%     %%     %%     %% 
#  1  ##  1  #%  5      5      5     
#     ##     #%     %%     %%     %% 
### ##########%%% %%%%%% %%%%%% %%%%%
### ###%%%%%%%%%% %%%%%% %%%%%% %%%%%
#     #%     %%     %%     %%     %% 
Then remove the walls for screens that should be connected. It would be easiest to always remove the one or two center blocks from a wall that separates connected screens but you could also make a wider path, a path at a different spot, or multiple paths between two screens. That would add variety but the screens are too small to do that here. After this, we have a themed maze to walk around in based on the array of screens.
#####################&&&&&&&*********
#     ##     ###   ##& & & &* $ $ ** 
#  $     # #               &*        
#     ##     ###   ##& & & &* $ $ ** 
########## ##########&&& &&&*********
########## ###&&&&&&&&&& &&&*********
########     #&     &&#   #&*     ** 
###             &&&     ?  &*        
### ####     #&     &&#   #&*     ** 
### ###### ###&&&&&&&&&& &&&*** *****
### ###### ###%%%%%%%%%% %%%%%% %%%%%
##   ####   ##%%   %%%     %%     %% 
#  #  ###   ##%        ***     !     
##   ####!$!##%%   %%%     %%     %% 
### ##########%%% %%%%%% %%%%%% %%%%%
### ###%%%%%%%%%% %%%%%% %%%%%% %%%%%
#%   %#%%%%%%%%     %%     %%     %% 
Randomly select different things to fill the screens with based on its theme: a center lake, small blocks of rock, rows of tree's, bordering trees, statues, etc. You could also have special things that only appear at dead ends: temples, towns, caves, treasure, bosses, puzzles, etc. Putting things at the dead ends makes it worth the time spent getting there - a good idea since most players hate dead ends and mazes in general. Secret areas and bad guys could also be placed now.
#####################&&&&&&&*********
#     ##     ###   ##& & & &* $ $ ** 
#  $     # #               &*        
#     ##     ###   ##& & ~~~~~~ $ ** 
########## ##########&&& ~~~~~~******
########## ###&&&&&&&&&& ~~~~~~******
########     #&     &&#  ~~~~~~   ** 
~~#             &&&     ?  &*        
~~# ####     #&     &&#   #&*     ** 
~~# ###### ###&&&&&&&&&& &&&*** *****
~~# ###### ###%%%%%%%%%% %%%%%% %%%%%
~~   ####   ##%%   %%%     %%     %% 
~~ #  ###   ##%        ***     !     
~~   ####!$!##%%   %%%     %%     %% 
~~# ##########%%% %%%%%% %%%%%% %%%%%
~~# ###%%%%%%%%%% %%%%%% %%%%%% %%%%%
~~   %#%%%%%%%%     %%     %%     %% 
Hyrule had shore lines along some the edges and small lakes at the corner of four screens. You can add those too.
#####################&&&&&&&*********
#     ##     ###   ##& & & &* $ $ ** 
#  $     # #               &*        
#     ##     ###   ##& & ~~~~~~ $ ** 
########## ##########&&& ~~~~~~******
########## ###&&&&&&&&&& ~~~~~~******
########     #&     &&#  ~~~~~~   ** 
~~#             &&&     ? ~&*        
~~# ####     #&     &&#   ~&*     ** 
~~# ###### ###&&&&&&&&&& &~&*** *****
~~# ###### ###%%%%%%%%%% %~%%%% %%%%%
~~~=~~~~~~=~~~~~~~~~~~~~=~~%%     %% 
~~    ###   ##%        * *     !     
~~   ####!$!##%%   %%%     %%     %% 
~~# ##########%%% %%%%%% %%%%%% %%%%%
~~# ###%%%%%%%%%% %%%%%% %%%%%% %%%%%
~~   %#%%%%%%%%     %%     %%     %% 
Rivers could connect some of the lakes to the edges. It would be necessary to place bridges if the river is cutting off a path that used to be passable.

A final step could involve looking at each screen or tile in the world and placing more treasure, creatures, or structures at interesting points.
I haven't implemented this yet so I'm not sure if this will really work or not. I'm also not sure how difficult this will be or how fun the results will be. It's something I haven't seen in any roguelike or non-Zelda game and if each screen has something interesting then it should avoid having long spans of time where all you do is walk around. I will probably use this for my entry into the 2012 7DRL challenge.

Wednesday, February 1, 2012

2011 7DRL re-retrospective

I'm really looking forward to the 2012 7DRL next month and I've got a lot of ideas I want to try out. I rechecked the scores I got for my entry last year to see when I should focus this time. I'm quite happy with the scores for my 2011 entry but I think I can do better this time.

Here's what my 2011 entry Twelve Hours got:

Completeness: Bug free, polished game with no features that feel like they are missing.
2.67 - My highest score. I've got a much better idea of what I want this time, some ways of reducing memory and CPU usage, and some time set aside to add polish so I expect to get a 2.67 or 3.00 this time.

Aesthetics: Good looking, excellent controls and UI.
2.33 - A pretty good score; probably from the clean UI, few commands, and standard ASCII visuals. Less garish colors and a few small animations should help improve the aesthetics.

Fun: If you try any 7DRLs, try this one.
2.33 - One reviewer said: "Would be nice to have better control over your companions."Yup. I want to avoid having total control but I agree that more influence and interaction with others could add much more fun. Adding some humor and a more heroic feel won't hurt either. A 3.00 would be nearly impossible but I hope I could get a 2.67.

Innovation: Brings something fundamentally new to roguelikes.
2.00 - Reviewer: "Survive timer, goal other than finding the powerful artifact, inventory-less." My lowest score. I don't know about "fundamentally new" but I've got a few new ideas up my sleeve this year....

Scope: Beyond what you think could have been done in seven days.
2.33 - Fair enough. I was unfocused for the first few days so it was less than 7 days of useful work. I've got a long list of ideas in my head this time so I hope to have much more in the game this year.

Roguelike: 3 means Roguelike, 2 means Roguelike-like, 1 means Not Roguelike.
2.67 - "misses some points for tactical polish." Agreed. I've got some ideas and expect a 3.00 this time.

Average
2.39 - Not a bad score - not bad at all. I did better than I thought I would but this year I'd like at least a 2.50. By looking at last year's entries, this seems to be a very difficult and rare thing. On the other hand, if one reviewer had given me one more point my average would have been 2.59 so I think 2.50 is reasonable for 2012.


I think most of my posts for February and March will be about roguelikes. Ideas, implementations, and random musings and rants.

Java multimethods for a simple command handler

I came up with a simple way to have an event handler easily handle multiple types. It's basically a way to say a class implements Handle<DomainEvent1>, Handle<DomainEvent2>, which works fine in C# but doesn't work in java due to type erasure. My solution: reflection based multiple dispatch. I'm sure others have done this before so it's nothing new.

public abstract class Handler {

 public void handle(Object message) {
  multipleDispatch(message);
 }

 private void multipleDispatch(Object message) {
  try {
   this.getClass().getMethod("handle", message.getClass()).invoke(this, message);
  } catch (IllegalArgumentException e) {
   e.printStackTrace();
  } catch (SecurityException e) {
   e.printStackTrace();
  } catch (IllegalAccessException e) {
   e.printStackTrace();
  } catch (InvocationTargetException e) {
   e.printStackTrace();
  } catch (NoSuchMethodException e) {
   ;
  }
 }
}

Not a good idea for high-performance applications and possibly not a good idea for any app. When you send a message to a class that extends Handler then the correct method will get called if it is capable of handling it. If you use a specific type then the specific method is called like normal, otherwise this multiple dispatcher tries to call the correct method.

Friday, January 27, 2012

System.Collections.IEnumerable and collection initializer syntax

I'd like to make a post about something that I think is one of the least utilized aspects of C#: custom collection initializers. Implementing a custom collection initializer for your class can make your code much more declarative and concise.

It's common to have a collection of things that you set up at design time: drop down list items, configurations, items in a game, a list of mappings, all kinds of things. These are often stored in external xml files or in a sql table. If you're like me then you'd rather have this in code and have it as concise and easy to get right as possible. Here's how.

Look at this example of setting up a list of Armor types for a game:

public List<Armor> ArmorsWithListExample()
{
 List<Armor> armors = new List<Armor>();
 armors.Add(new Armor("leather armor",  1,  250, 10));
 armors.Add(new Armor("chain mail",     4,  500, 14));
 armors.Add(new Armor("splint mail",    7,  750, 16));
 armors.Add(new Armor("plate armor",   10, 1000, 18));
 return armors;
}

Here is the same thing using the collection initializer syntax:

public List<Armor> ArmorsWithInitializedListExample()
{
 return new List<Armor>() {
  new Armor("leather armor",  1,  250, 10),
  new Armor("chain mail",     4,  500, 14),
  new Armor("splint mail",    7,  750, 16),
  new Armor("plate armor",   10, 1000, 18),
 };
}

There are several advantages with the collection initializer syntax. You don't have to have the temporary variable, it's less code with fewer redundancies, and it's a nice declarative way to show that all you are doing is creating the collection. Small advantages, I admit, but they add up. But if you look at some C code, you see that the code can be even more concise by declaring the objects themselves inline. Here's an example from the game Brogue:

const itemTable armorTable[NUMBER_ARMOR_KINDS] = {
 {"leather armor", "", "", 10, 250,  10, {30,30,0},  true, false, "This lightweight armor offers basic protection."},
 {"scale mail",  "", "", 10, 350,  12, {40,40,0},  true, false, "Bronze scales cover the surface of treated leather, offering greater protection than plain leather with minimal additional weight."},
 {"chain mail",  "", "", 10, 500,  13, {50,50,0},  true, false, "Interlocking metal links make for a tough but flexible suit of armor."},
 {"banded mail",  "", "", 10, 800,  15, {70,70,0},  true, false, "Overlapping strips of metal horizontally encircle a chain mail base, offering an additional layer of protection at the cost of greater weight."},
 {"splint mail",  "", "", 10, 1000,  17, {90,90,0},  true, false, "Thick plates of metal are embedded into a chain mail base, providing the wearer with substantial protection."},
 {"plate armor",  "", "", 10, 1300,  19, {120,120,0}, true, false, "Emormous plates of metal are joined together into a suit that provides unmatched protection to any adventurer strong enough to bear its staggering weight."}
};


It's a small improvement but I want to do that in C# as well. With custom collection initializers, you can.

public List<Armor> ArmorsWithCustomInitializerExample()
{
 return new ArmorCollection() {
  { "leather armor",  1,  250, 10 },
  { "chain mail",     4,  500, 14 },
  { "splint mail",    7,  750, 16 },
  { "plate armor",   10, 1000, 18 },
 }.List;
}

Look at that! Concise and easy to get right. Here's the code for the ArmorCollection; notice that it's just a wrapper around a List. The only additional functionality it has is the Add method.

class ArmorCollection : IEnumerable
{
 public List<Armor> List { get; set; }
 
 public ArmorCollection()
 {
  List = new List<Armor>();
 }
  
 IEnumerator IEnumerable.GetEnumerator(){
  return List.GetEnumerator();
 }
  
 public void Add(string name, int weight, int cost, int ac)
 {
  List.Add(new Armor(name, weight, cost, ac));
 }
}

The Add method is what makes it work. According to section 7.6.10.3 of the C# specs, if a class implements the IEnumerable interface then the compiler converts the initializer syntax into a series of calls to the Add method, even though the Add method isn't part of the IEnumerable interface. The Add method can have any number of parameters and the compiler will make it work.

So when you have a collection of things that isn't going to change, instead of using a built-in collection with a series of Add calls, loading from an external xml file, or loading a sql table, consider creating an in memory collection by using a custom initializer: it may be easier, faster, and more concise than the alternatives.

Tuesday, January 24, 2012

My summary of CQRS and DDD

Recent epiphany: sagas are just ways to turn domain events into commands.

Here's my as-of-now summary of the concepts I see in many EventSourcing, CQRS, and DDD videos and blog posts.

Command: A simple message that represents a user's request to make something happen. Just data with no behavior and often named in the imperative tense.
class CloseAccount implements Command
{
  public AccountId accountId;
  public String reason;
 
  public CloseAccount(AccountId accountId, String reason){
    this.accountId = accountId;
    this.reason = reason;
  }
}

CommandHandler: A domain service that turns a command into events by calling methods on an aggregate root, publishes the resulting events, and handles transactions and persistence. Stateless with just behavior; just a task based method and sort of procedural.
class AccountCommandHandler extends CommandHandler
{
  private AccountRepository _repository;
  private MessageBus _messageBus;
 
  public AccountCommandHandler(AccountRepository repository, MessageBus messageBus){
    this._repository = repository;
    this._messageBus = messageBus;
  }
 
  public void handle(CloseAccount command){
    Account account = _repository.get(command.accountId);

    account.close(command.reason);
  
    persistAndPublishEvents(account);
  }
}

Aggregate Root: A persistent domain object that turns method calls into domain events. May contain references to other domain objects as part of a parent/child relationship. Stateful and behaviorful and guaranteed to be internally consistent.
class Account extends Aggregate
{
  private AccountId id;

  public Account(AccountId id){
    this.id = id;
    super.storeEvent(new AccountCreated(this.id));
  }

  public void Close(CloseReason reason){
    super.storeEvent(new AccountClosed(this.id, reason));
  }
}

Domain Event: A simple message that represents a change to the state of an aggregate. Just data with no behavior and often named in the past tense.
class AccountClosed implements DomainEvent
{
  public AccountId accountId;
  public CloseReason reason;
 
  public AccountClosed(AccountId id, CloseReason reason){
    this.accountId = id;
    this.reason = reason;
  }
}

MessageBus: A mechanism for publishing commands and events and subscribing handlers to commands and events. May be a separate EventBus and CommandBus. The only behavior is publishing events and subscribing event and command handlers to events; the only state is what's required to track which services have subscribed to which events.
public class SimplestEventBus implements EventBus
{
  private List<Handler> handlers = new ArrayList<Handler>();
  
  public void subscribe(Handler handler)
  {
    handlers.add(handler);
  }
  
  public void publish(DomainEvent event)
  {
    for (Handler handler : handlers)
      handler.handle(event);
  }
}
Saga: A persistent object that turns domain events into commands. Stateful and behaviorful. The only state is what's required for knowing when to create the commands.
// Send a notice to the account's owner once the account is
// both paid off and closed. (ignore thread safety since this is a simple example)
class OwnerNotificationSaga implements Saga
{
  private AccountRepository _repository;
  private MessageBus _messageBus;
 
  private List<Account> closedAccounts = new ArrayList<Account>();
  private List<Account> paidOffAccounts = new ArrayList<Account>();
 
  public OwnerNotificationSaga(AccountRepository repository, MessageBus messageBus){
    this._repository = repository;
    this._messageBus = messageBus;
  }
 
  public void handle(AccountClosed event){
    Account account = _repository.get(event.accountId);
  
    if (closedAccounts.contains(account))
      return;
  
    if (paidOffAccounts.contains(account)){
      sendNotice(account);
      paidOffAccounts.remove(account);
    } else {
      closedAccounts.add(account);
    }
  }
 
  public void handle(AccountPaidOff event){
    Account account = _repository.get(event.accountId);
  
    if (paidOffAccounts.contains(account))
      return;
  
    if (closedAccounts.contains(account)){
      sendNotice(account);
      closedAccounts.remove(account);
    } else {
      paidOffAccounts.add(account);
    }
  }
 
  private void sendNotice(Account account){
    _messageBus.publish(new NotifyOwner(account.ownerId));
  }
}

So, for many of the examples I've seen, a user creates Commands that are handed to a MessageBus that dispatches it to a subscribed CommandHandler. The CommandHandler loads the relevant Aggregate and calls methods on it. The resulting events are gathered, persisted (if doing Event Sourcing), and passed to the MessageBus. The subscribers to that event will often update some read model (effectively turning domain events into updates on report tables) but they may be Sagas that track events and create related commands when necessary.

None of that is the essence of DDD or the essence of CQRS, but it's so common to the discussions and examples that this little glossary helps me to keep things straight.