I’ve worked at Microsoft for a long time; and by “long time,” I mean long enough to have been a developer on Microsoft Fortran Powerstation 90. Yeah, you kids today and your OOPs and your CLRs. In my day, code started on column 7 and by jove not one space more! (Or is that “by gum?” Damn, need to remember where I put my old-guy handbook.)
Anyway. That said, I basically grew up in the Xbox org, working on both Xbox and Xbox 360, where I was a part of the chaos (and intense fun) that was defining Xbox Live. So the value of the ‘metagame’ – the game surrounding the game – is pretty well ingrained in me. The shame I felt in playing King Kong on the 360 just to get those easy 1000 gamerpoints was washed away by the fact that I got 1000 gamerpoints.
After the Xbox org, I also spent time as the group program manager for MSN Games where 70% of our audience was basically Moms; and if there’s one thing we learned, it’s that they don’t have time to waste and playing a game is a waste of time. There, as well, the concept of metagame – through badges etc – is what made it okay for them to play. While improving or simply enjoying may be sufficient reason for you or I to play a game, for them a sense of progressing or earning towards a greater goal was necessary in order for it to not feel like a waste of time. A broad (ha!) generalization, but not an untrue one given the folks playing our games. So there as well, the value of the metagame was made abundantly clear to me.
And then there’s WoW, which I’ve played off and on since Beta (off, now). Although it’s a single game, to me it’s a quintessential metagame in that each quest – or at a broader level each zone – represents a mini-game, and completion moves you farther along in the metagame. There’s a ton of rat-tabs to feed out pellets in that game.
And finally, having kids has forced me out of a heavy gamer role and into a more casual gamer. I get up at 4AM (yeah, really), work until 4PM, play with the kids until 7PM, and by then I’ve got the time and energy to do one active thing; either play a game, or program while my wife watches TV. Easy choice most days (although I’ve got a pair of level 80’s that I can hear clearing their throats), but it does mean that there’s more value if there’s more to the game than just the game.
Now, contrast that with DCSS (as a proxy for most roguelikes). I love the game, even though like most roguelikes, it’s as close to a non-metagame as possible. Although you get enjoyment and a sense of discovery (neither a minor thing), the lack of save/restore points means that when you die you’ve “wasted” that time in terms of character advancement, etc. This is, of course, a primary draw of roguelikes – the constant threat of absolute obliteration delivers a very different gaming experience than the “meh, I’ll just save/restore until I get it right” gameplay that other titles deliver. I imagine that most folks on r.g.r.d would argue that that threat is a fundamental aspect of the “roguelike” genre, and I clearly don’t want to lose that in mine. Also: I want to target 10 hours of gameplay in my game – that’s incredibly hard to do if the player could die 9 hours in and is right back to square 1.
So how do I balance those seemingly irreconcilable gameplay models?
Answer: I cheat. My game will consist of a collection of “zones” (dungeons, cities, etc). Within each zone, death bumps you all the way back to the start of the dungeon, but your character doesn’t “permanently” die. In this way, the game itself is like a collection of distinct roguelikes that your character travels through (I could even eventually have each one play differently, which would be pretty awesome). The goal is that the player fears death as it means they’re back at the start of the dungeon, but I still get to have 10 hours of gameplay, the player doesn’t lose advancement between zones, and there’s more of a real phased story arc (compared to DCSS where there’s one arc; ideally you’d have a collection of sub-arcs and corresponding up-and-down of tension, leading up to the finale).
Here’s a screenshot from my earlier pass at this, showing a portion of the world map and the 16 zones I had on it. Per above, the player would start in Ordale, and couldn’t progress (and would start back at square 1) until they “won” that zone.
The hi-larious thing is that I’ve just rationalized a game model where the player only gets to save/restore at an incredibly coarse granularity. Take any non-roguelike game and tell the player that save points are 20-30 minutes apart and you’ll get laughed at. The only way this can work is if I make it infinitely clear that this is a roguelike. “Rogue II: The Roguening” or somesuch. And even then, I need to get out in front of anguish from non-roguelike players in some way. “Rogue II: The Roguening in which there is only a hardcore mode”. And on the other side I wonder if the rogue purists will roll their eyes at the idea of a rogue with what are essentially save/restore points at a very high level (but of course, I’ve already lost the true purists by eschewing ASCII :)). Ah well, time will tell.
Breaking the above ideas into a set of classes:
- The game consists of a set of Zones (Dungeons, Cities, etc). A Zone is comparable to a single roguelike (e.g. all of DCSS would be considered a single Zone).
- Each Zone consists of a set of Levels
- The Zone definition defines which types of Levels can appear at each depth.
- The Levels may be random “filler” levels, or they may be specific; e.g. if the goal of a zone is to kill a particular mob, then the bottom Level of that zone could be that mob’s “lair”. Similarly, there are Level sets from which levels may be randomly selected (e.g. the first two floors of a Cave level may select from a set of 20 different “Cave entry” Levels)
- A Zone can also contain sub-zones (e.g. the Orc Caves in DCSS)
- Note: Levels can be reused between different Zones.
- Each Level has:
- A layout definition – width/height, room styles, corridor styles, etc.
- A theme (dungeon, catacombs, castle, cave, …) that defines the look and feel of the Level – tileset, ambient sounds, etc. Although a Zone implies a theme, I want to support per-Level themes; imagine a Castle Zone that has an atrium level, a celler level, and an underground level – each Level has a very different look-and-feel.
- Note: Themes can be reused between different Levels
- A set of classes of monsters and items that can appear in the Level.
- Each monster and Item also specifies the ‘optimal’ levels for it to appear within; that way a “Spider Cave” Level could simply include the “AllSpiders” monster class, and the game will automatically select Spiders that are appropriate to the Level’s “depth”
- Monster classes are not fleshed out yet; e.g. whether they are hierachical or not, etc. But the concept of “include monsters from ‘this set'” will be present in the Level Definitions.
Longer term, I could imagine extensions such as:
- Random selection of Zones rather than preset Zones
- Sets of Quests that a Level can contain (random or otherwise)
- The ability for other developers to create Zones, Levels, and LevelThemes. Tons of challenges with that idea, but huge payoff if possible.
The Xml Definitions
Here’s xml definitions for sample LevelThemes, LevelDefinitions, and Zones. While I won’t support multiple Zones or Levels for a bit, I wanted to implement this now so that anything I add (e.g. Monsters) will be reflected appropriately here as well.
<LevelThemes> <LevelTheme Id="Dungeon" AmbientSounds="DungeonSounds"> <MonsterClasses RefIds="MonsterClass3" /> <CellAdornments RefIds="TortRack1, TortRack2, Lamp1, Lamp2" /> <CellDefaults DefaultFloor="StoneFloor1" DefaultWall="StoneWall1" /> </LevelTheme> <LevelTheme Id="Cave" AmbientSounds="CaveSounds"> <MonsterClasses RefIds="MonstClass8, AllSpiders" /> <CellAdornments RefIds="SpiderWeb3, SpiderWeb2" /> <CellDefaults DefaultFloor="DirtFloor1" DefaultWall="StoneWall1" /> </LevelTheme> <LevelTheme Id="CastleEntry" AmbientSounds="CastleSounds"> <MonsterClasses RefIds="LowLevelGuards, Ambassadors" /> <CellAdornments RefIds="TortRack1, TortRack2, Lamp1, Lamp2" /> <CellDefaults DefaultFloor="CastleTile" DefaultWall="CastleWall" /> </LevelTheme> </LevelThemes>
<LevelDefinitions> <!-- Castle and Keep related Levels --> <LevelDefinition ID="LargeEntryWay" LevelTheme="Castle" Width="120" Height="120"> <RoomGeneration RoomGenerator="SquareRoomGenerator" SmallestPartitionSize = ".25f" MaxPartitionSizeRatio = "1.75" PercentOfSmallRoomsToNotSplit = ".3f" HomogeneityFactor = "0.25f"/> <CooridorGeneration CorridorGenerator="Default"/> </LevelDefinition> <LevelDefinition ID="SmallEntryWay" Theme="Castle" Width="80" Height="80"> <RoomGeneration RoomGenerator="SquareRoomGenerator" SmallestPartitionSize = ".15f" MaxPartitionSizeRatio = "1.5" PercentOfSmallRoomsToNotSplit = ".1f" HomogeneityFactor = "0.25f"/> <CooridorGeneration CorridorGenerator="Default"/> </LevelDefinition> <LevelDefinition ID="CastleFiller" Theme="Castle" Width="100" Height="100"> <RoomGeneration RoomGenerator="SquareRoomGenerator" SmallestPartitionSize = ".125f" MaxPartitionSizeRatio = ".8" PercentOfSmallRoomsToNotSplit = ".25f" HomogeneityFactor = "0.25f"/> <CoordidorGeneration CorridorGenerator="Default"/> </LevelDefinition>
And finally, Zones:
<Zones> <Zone Name="Abandoned Mine" NumberOfFloors="20" Description="Kill the evil spider Tslith"> <Levels> <Level RefId="CaveFiller" Appears="Filler" LevelDepth="1-Bottom"/> <Level RefId="Tslith's Lair" Appears="1" LevelDepth="Bottom" /> </Levels> </Zone> <Zone Name="City of Ordale" NumberOfFloors="14-16" Description="A group of Ordale townsfolk approach you, pleading for help. An Orc Lord has moved into a nearby cave and has been terrorizing the town for months. Will you help them?"> <Levels> <Level RefId="LargeThroneRoom" Appears="1" LevelDepth="1" /> <Level RefId="GardenAtrium" Appears="AtMostOnce" LevelDepth="3-6" /> <Level RefId="Library" Appears="AtMostOnce" LevelDepth="3-6"/> <Level RefId="AdministrativeOffices" Appears="0-4" LevelDepth="3-6" /> <Level RefId="CastleFillerFloor" Appears="Filler" LevelDepth="2-6" /> <Level RefId="LargeEntryWay" Appears="1" LevelDepth="7" /> <Level RefId="UndergroundFillerFloor" Appears="Filler" LevelDepth="8-Bottom" /> <Level RefId="Cellar" Appears="AtMostOnce" LevelDepth="8" /> <Level RefId="LargeDungeon" Appears="1" LevelDepth="11-Bottom" /> <Level RefId="UndergroundLair" Appears="AtMostOnce" LevelDepth="Bottom" /> </Levels> </Zone> </Zones>
I haven’t had a chance to code up the parsers for that, so it may change as that coalesces. I’m hoping to get to that code tonight (at which time I’ll also update the DungeonTheme (etc) classes to reflect the above).