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....