Wednesday, March 28, 2012

Common uses for the State pattern

Of all the design patterns, I think the state pattern is one of the simplest and probably the one I use the most. It's easy to understand and easy to use but I still see many places where it could be used but isn't. Here's a few things that indicate when using state objects would be simpler.

If you have a variable that represents what 'mode' or 'state' something is in, or what the current behavior is, then you may want to use the state pattern. A common place for this is if you have a gui and the user can interact with one of many tools. Instead of:

public void onClick(int x, int y){
  if (currentTool == PAINT)
    canvas.paint(x, y);
  else if (currentTool == BLUR)
    canvas.blur(x, y);
  else if (currentTool == ERASE)
    canvas.erase(x, y);
  else if (currentTool == LINE && lineStart == null)
    lineStart = new Point(x, y);
  else if (currentTool == LINE && lineStart != null) {
    canvas.drawLine(lineStart.x, linesStart.y, x, y);
    lineStart = null;
  }
}

you could refactor to the state pattern:

public void onClick(int x, int y){
  currentTool.onClick(x, y);
}

class PaintTool extends GuiTool {
  @Override
  public void onClick(Canvas canvas, int x, int y){
    canvas.paint(x,y);
  }
}

This means that new tools could be added without having to change the gui code. The state pattern would also simplify the gui since it no longer needs to determine what clicking means. This is especially beneficial when multi-click operations are involved since the gui no longer needs extra variables to track that.

class LineTool implements GuiTool {

  private Point startPoint;

  @Override
  public void onClick(Canvas canvas, int x, int y){
    if (startPoint == null)
      startPoint = new Point(x, y);
    else {
      canvas.drawLine(startPoint.x, startPoint.y, x,y);
  }
}

That brings to another common case where the state pattern is useful: If you have variables that are used in some situations and ignored in others, then you may want to use the state pattern instead. For example, if you have a game or simulation where each agent either has a fixed home, another agent it follows, a group it considers "home", then instead of:

public void goHome(){
  if (homeLocation != null)
    goTo(homeLocation.x, homeLocation.y);
  else if (leader != null)
    follow(leader);
  else if (group != null)
    follow(group.getRandomMember());
  else
    wander();
}

you could refactor to the state pattern:

public void goHome(){
  home.goTo();
}

public class StationaryHome implements AgentHome {
  private Agent agent;
  private Point home;

  public StationaryHome(Agent agent, Point home){
    this.agent = agent;
    this.home = home;
  }

  @Override
  public void goTo(){
    agent.goTo(home);
  }
}

Once you have the different states, then the agent no longer needs all of those extra variables and is made much simpler. It also disallows states that don't make sense: what does it mean if an agent has a location it considers home and a group it considers home? If that's not a valid situation then you need to make sure you never end up with both. If it is a valid situation then you can just create a new state object that handles it.

You may have noticed something about these two examples: If you have a bunch of if/if else statements that compare variables to literal values (like enums!), then you may want to use the state pattern instead. Complex objects with complex logic can be greatly simplified by using the state pattern. In fact; it's possible to completely remove all branching and delegate behavior to multiple different state objects instead.

Since these scenarios are all cases where we want different behavior based on some runtime values, they're good candidates for the state pattern. So keep an eye out for chances to use the state pattern.

Monday, March 19, 2012

I rule, you rule, we all rule old-school Hyrule retrospective part 1

So the 2012 7DRLC has come and gone and I've finished my third and best entry. I've looked at some posts and announcements that others have made but have only tried a couple other entries so far. Without getting "official" feedback from this years judges and without comparing my entry to the others, I have to ask myself: what went right? What went wrong? What did I learn? And what can I do differently?

Right. I had a plan and stuck with it when it worked and dropped it when it didn't. I got a zeldalike overworld that was aesthetically pleasing and fairly interesting. I got a bunch of different items to use, most of which have a passive and active use. I also have fairly intelligent rivals that really push you forward and made the game much more fun. The random monsters were sometimes fun and I really liked the camouflage and calling for help. The code - while a bit on the spaghetti side - was mostly decent and did use events. In the end I had a game that was somewhat fun with a clear indication of progress and you could win by cautious exploration, reckless combat, or an opportunistic combination of both. I also had someone playtest and spot so many spelling errors.

Wrong. The overworld sometimes had inaccessible places. It's rare and not game breaking, unless you start on a tiny area and can't escape, but it happens. The evasion thing was pretty uninteresting and some of the items aren't as useful or interesting as others. I tried to make all items equally interesting and useful but that didn't work out as well as I thought. I ditched many of my ideas because they were just not fun. Sometimes the monsters were too overpowering or just uninteresting. The game was often to short to really get into it. I also had a hard time deploying as an applet and eventually just provided a download link. That really sucked since a big part of choosing java was being able to play it in the browser. The biggest problem was that I also spent the middle portion of my week flubbing around and spastically tweaking things left and right without a clear plan. It was chaotic and I moved sideways as much as I moved forward, if that makes any sense.

Learned. Worldgen shouldn't be all or nothing - if I could make one "room" or "screen", check it, and then accept or reject it on its own then I could avoid having inaccessible sections and unintentional dead ends. I don't think I could have done the items much better since I originally had detailed plans that just turned out to be uninteresting. That's not to say they couldn't be done better but I think that's one thing that you just have to get right through iteration and hands on playtesting. My weakness was probably the items and item balancing and I probably should have stuck with the the best parts: worldgen and rivals. Not that it matters that much - the game is so short that I often see only a small portion of it before the game ends. I think that the more randomness a game has and the more content it has to explore, the more chances you need to overcome the randomness and the more time you need to explore. I'll have to make a post on randomness and the number of choices required to rise above being slave to the RNG.

Next time. I tend to go overboard with my ideas; like having a zelda overworld, random monsters, evasion, 2 item max, rivals, and fame percent all in one seven day project. Although it's great having different options to explore, the items were probably my weakness. I should either focus on that and practice making item-based roguelikes or ditch it for the next 7DRL. The events were also a bit of a mixed blessing. When should I use events and when should I code things inline? It was also difficult to control the order of when messages appeared and deal with situations where one action would have similar events published and logged. I'll try dropping the event based thing and rely on explicitly sequenced overrides and callbacks as an alternative. Yeah, it's tightly coupled, but I also have the control I need. I also need to have specific goals for each session: worldgen, rivals, polish, etc and not have generic "content". That's how I end up with a bunch of items most people will never see and even fewer will like. Lastly, java isn't as cross platform and easy to deploy as I thought. I'll have to look more into Flash for my next roguelike.

So, have a plan but ditch it when it doess't work and focus on your strengths since your strong points will make your project a success and your weak points will, at best, be a waste of time, and, at worse, may overshadow your strengths. Also, if you can, have someone else playtest it. Once I get more feedback from the fine people at the roguetemple and other folks who review my game, I'll come up with a retrospective part 2.

Friday, March 16, 2012

I rule, you rule, we all rule old-school Hyrule

Here it is! My 2012 7DRL, I rule, you rule, we all rule old-school Hyrule. I no longer have it running from this page since so many people were having problems with it but you can still download it and run it localy.

Source:
  https://github.com/trystan/iryrwarosh

Download the iryrwarosh.jar:
  https://sites.google.com/site/trystansprojects/iryrwarosh.jar

Once you have the jar file, double click it or type "java -jar iryrwarosh.jar" from the command line.

Good luck!


2012-03-23 update: I made a minor bugfix that was causing an infinite loop when a monster tried to unhide but couldn't find an acceptable place. This doesn't change the gameplay except it's now theoretically possible to kill something that's hiding by blocking the only places it could enter again.

Tuesday, March 13, 2012

I rule, you rule, we all rule old-school Hyrule halfway milestone

So, I'm about halfway through this year's 7DRL and these are my thoughts.

I've made amazing progress on my 7DRL. Neat worldgen, unique items to choose from, limited but interesting inventory choices, challenging and interesting enemies, pleasant aesthetics - all good so far.

I've sort of but not explicitly abandoned the allies/followers idea. It turns out that it's not very fun to implement or play. If it was a city simulation or tactics game then it may be interesting, but it doesn't add much to the lone hero vs the world storyline we're all so familiar with. These are common game tropes but I'd say there's three reasons why that works so well: clear playability, clear progress, and clear obstacles.
  • Clear playability. You know what to do. Going down stairs is good. Getting new stuff is good. +5 is better than +3. A Black Dragon is scary, a Newt is not. The conventions and standards from high fantasy, AD&D, previous roguelikes, and numerous hero stories means that you have a general idea of what to do (go down the stairs) how to do it (find [>] and press [>]) and the common supporting ideas ([q]uaff, AC, DEX, [e]at, Potion of Stone Skin, etc).
  • Clear progress. You know how close you are to winning. You're on dungeon level 4 of 20. Or the sewer branch. Or you're at character level 8 and 11 is the highest you've been at before. Or you've got 1000 gold coins. Or you just got the Master Sword. Roguelikes, and possibly games in general, tend to have a clear way of seeing how close you are to the end - by a numeric success vs total (Mario Bros. world number) or success vs failure (chip pile during poker tournament).
  • Clear obstacles. You know how close you are to losing. You are low on hp. Or poisoned and starving. Or paralyzed and surrounded by ants. Whatever the situation is, you can clearly see that you are closer and closer to failing.
This means that in the best games you know what to do, and how close you are to winning, and how close you are to losing. Like knowing that you should be able to handle petrification as you turn to stone on level 18 of 20 while surrounded by demons. So close to winning (level 18/20), but you know you're going to fail (petrified and surrounded), but you know how to play it better next time (resist petrification). Possibly the roguelike ideal.

So, what other game mechanics contribute to showing what to do, how close you are to winning, and how close you are to losing? Do you know of any clear examples that support these ideas? Any that contradict?

Monday, March 5, 2012

My plan for the 2012 7DRL

I've been thinking a lot about what I want to do with this year's 7DRL. For 2011 I wanted to see what it was like to not be the hero but have to cooperate with other heroes and to try a survival goal rather than the tried-and-true "descend and return". Even though it wan't very fun, I'm happy that I did that and I consider it a success. I've posted some of my ideas before, but as March approaches, I've been narrowing down what I want to focus on.


Event based architecture. I've had a lot of fun and learned much while delving into simple event based programming and I think this will be a good test of how to apply it to an interesting application. Roguelikes tend to have very messy dependancies and have an unholy number of exceptions to the rules and complex interactions so this will be a good test of how well I can make events, commands, and sagas work.

Interesting overworld. I've gotten tired of playing games that have too much uninteresting space. Long corridors, huge outdoor fields, empty room after empty room after empty room. I want small and unique spaces. Moving is so boring that some roguelikes have it automated for you. Despite all the hours I played the original Zelda as a kid I never got tired of it. Each screen had its own unique charm and character, each fit within its own little neighborhood, and each area had it's own secrets to reveal. I want that.

Random monsters. Other than the Forgotten Beasts of Dwarf Fortress, I haven't seen this implemented. I don't think I'll have DF's giant vomit monsters, just a few species with three or four random advantages each game. This should add variety like identifying potions does, except perhaps with deadlier consequences.

Dynamic quests. The more I think about it the less intimidating this seems - but that may just be my own hubris. Since it's a 7DRL I will probably only have a few quests. Getting other people to follow commands and attempt the same quests would be interesting - and it should be possible if I'm right about the connection between commands and quests.


Focusing on these means I would de-emphasize other things. There will probably be just a few simple armors, weapons, and other items. I will most likely skip magic alltogether. The game itself may not even be fun or difficult. I'm not sure what the story will be either but it should involve quests and followers. I should probably think of something soon otherwise I'll end up with just a proof of concept: a bunch of neat ideas with no theme to tie them together.

My 7 day plan:

Day 1. Hyrulian Overworld: worldgen, player controlled @
Day 2. Basic gameplay: basic creatures, basic combat, basic stats, basic items
Day 3. Monsters: randomized monsters, better creature AI, a few status effects
Day 4. Society: people, victory, basic commands
Day 5. Dynamic quests
Day 6. More content and polish....
Day 7. More content and polish....

Tuesday, February 28, 2012

Followers, spoken commands, and quests


I think I've found something that hasn't been done that could add a lot to roguelikes: spoken commands. You type what you want your followers to do and they do it. Instead of having a complex AI that handles the entire english language, you could focus on a few things that could be combined in different ways. If you have many people following these commands then you and your rag-tag team of adventurers could really change the world.

Here's a simple command syntax that I have in mind:
  <target> <verb> [<objects>] [<preposition clauses>]

target is an optional person or group you are talking to: healer, fighters, Bob, Joe, etc.
verb is one of a dozen or so supported verbs: attack, defend, go, pickup, drop, help, etc.
objects are the people, places, or things directly involved with the verb: a sword, goblins, me, the desert, home, etc.
preposition clauses are optional clauses that constrain the verb: in <location>, with <item>, etc.

The prepositions are where the real flexibility and power come from since you can specify where something should happen, what should be used, or whatever else makes sense. The verbs, people, places, things, and prepositions would be whatever is appropriate to the game; resource gathering, squad maneuvers, mixing potions, social intrigue, whatever you can think of.

Turning the spoken words into commands would be three steps:
  1. Normalize the sentence, removing fluff words and changing synonyms (protect -> defend)
  2. Parse the sentence
  3. Correct the prepositions and objects if necessary

As an example, Miners, give the blacksmith ore from the mines would be normalized into
 miners give blacksmith ore from mines which would be parsed into this:
 target = miners
 verb = give
 objects = blacksmith, ore
 prepositions = from mines

The correction phase would be necessary in this example since the "give" verb requires the verb's object to be a thing and requires a "to <person>" prepositional clause. "blacksmith" is a person and "ore" is a thing so "blacksmith" should be the "to" prepositional clause and "ore" should remain as the verb's object. The corrected interpretation is:
 target = miners
 verb = give
 objects = ore
 prepositions = from mines, to blacksmith
or miners give ore from mines to blacksmith

So the miners who hear this would get ore from the mines and give it to the blacksmith.

Some other example commands:
 healer, help the villagers at home
 kill the goblins in the dark forest with spears
 Urist, craft a sword with steel at the master's forge
 guards, escort the prince from the castle to the fort


There seems to be a deep similarity between commands and quests. Even my example Lost Heirloom Quest could be seen as a command: player, give the McUrist family watch from the dark forest to Urist McUrist. Since the NPCs can follow commands, and commands and quests are the same, then they should be able to follow quests. Also; since the player can give commands, the player is also giving quests. Imagine a world with a few hundred NPCs running around trying to fulfill quests and giving quests to others when appropriate.

Wednesday, February 22, 2012

Procedural quests for a dynamic world

Interesting and procedurally generated quests are something of a holy grail for many roguelike developers. I've also given it some thought and here's a simple idea I came up with.

Basically, if you have a catalogue of possible quests and you have an event based architecture, then each quest type would have it's own saga. That saga would listen to domain events and when the preconditions were right, it would add the quest to a quest giver. By talking to a quest giver the player, or any other actor, could accept the quest. When the saga receives the right domain event, the quest is over and everyone undertaking the event is rewarded or notified as appropriate.

Here's a concrete example I'll call a Lost Heirloom quest.
  1. A LostHeirloomSaga subscribes to certain events like PersonMoved (while fleeing or confused) or ItemStolenFromPerson. As a response to those events, it may create a LoseItem command with a reference to the person and item.
  2. Some command handler causes the target of the LoseItem command to drop the item (if it wasn't already stolen) and create an ItemLost event with references to the person, the location, the time, the item, and the reason why.
  3. The LostHeirloomSaga listens to ItemLost events and when it handles the event, the person who dropped the item is given a LostHeirloomQuest and can ask others to accept it.
  4. When the player talks to that person they can accept that quest. The details from the LostItem event can be used to create the quest specific rewards and text. Imagine talking to URIST McURIST the WOODCUTTER when he says "TWO WEEKS ago I was CUTTING WOOD in the DARK FOREST and was attacked by a GIANT BEETLE. While fleeing for my life, I dropped my McURIST FAMLIY WATCH. If you find it and return it, I'll give you my spare WOODCUTTER'S AXE and a PASS TO THE WOODCUTTER'S GUILD."
  5. The LostHeirloomSaga also listens to ItemGiven events. When the item that was given matches a lost item and the person it was given to matches the person who lost it, the associated quest is completed and the person who gave the item is rewarded.
  6. If a CreatureDied event for the quest giver happened, an ItemDestroyed event for the lost item, or some other quest-canceling event happens, then the LostHeirloomSaga cancels that creature's quest and everything else is cleaned up appropriately.
  7. For extra awesomeness, when the saga notices other events related to the item (like ItemSold or ItemPickedUp), it could somehow add details to the world about it. Maybe the town's gossipmonger would tell you rumors about how the local blacksmith found a family watch in the dark forest. You could then talk to the blacksmith to find out what happened to it or you could sneak through his stuff when he's not looking.
Implementing this quest means adding a few classes: a LoseItem command, a method to handle that command, a ItemLost event, a LostHeirloomQuest, and a LostHeirloomSaga. The neat thing is that no existing classes need to be updated except for making sure the quest saga subscribes to the right events - all the logic is contained in the command handler and LostHeirloomSaga. The LostHeirloomSaga can use details of the quest giver to create dynamic and relevant details about what was lost, how it was lost, and when and where it was lost as well as a reward appropriate for the quest giver and the location and value of the lost item.


The real emergent behavior comes from quests that play off of events generated by other quests. If each quest can be ended two or three different ways, each quest directly or indirectly involves affecting the world, and there are multiple actors giving or accepting quests, then a complex chain of events could cause gathering firewood to lead to the downfall of a civilization.
  • Perhaps LostHeirloomQuestCompleted events please the god of compassion who may give the quest completer a Help The Townfolk quest.
  • Perhaps when a Rescue Princess quest is ended by the princess dying, her family creates a Kill Person quest targeting the killer and a Revenge quest against every group the killer was a member of. When a Rescue Princess quest is ended by the princess returning home, her family rewards whoever escorted her and every group the escort is a member of.
  • Perhaps 10 Expand Influence quests must be completed before a size 3 town can become size 4. Whenever an Expand Influence quest is completed, nearby paranoid town mayors become nervous and may create an Attack Town quest or Assassinate Ruler quest targeting their rival neighbors. When an Attack Town quest is completed, the targeted town's mayor can give Strengthen Defenses and retaliatory Attack Town quests. Undertaking either requires buying resources from the market and if a market trader's goods are running low then he could create Gather Resource quests. Of course gathering resources in your neighbor's territory will cause them to hand out quests to get you to stop; by bribery, trade, or sword and shield.
This, right now, is just idle speculation but I think this could be done. By relying on domain events and sagas, new quests can be implemented without muddying up the existing code since it doesn't even need to be touched. By relying on specific details of the people and places creating the events, compelling and believable quests can be generated. And by relying on quests that build on domain events raised as part of attempting other quests, an interdependent and dynamic history following simple laws of cause and effect can be created. I'll have to create a proof of concept some time.