On the topic of other online discussions of D&D-centric theory, this was an interesting breakdown of styles or flavors of D&D, partially correlated to editions, that have come up over the years. Like all broad categorizations, there’s sure to be some over-generalization, and lots of fun things in the interstices. There’s undoubtedly some interesting examinations of the causes and effects between emerging and evolving styles of playing D&D, and changes to editions, though I’ll leave that to people who actually know something.
The internet has a long history of attempting to generate theories that encompass various aspects of role playing games. Since I never engaged in great depth with many, I won’t do them the injustice of a hack job recap. Recently, however, I encountered one that left me interested in engaging with it in the context of my own efforts. I’ll try to summarize, and maybe expand, on it a bit below, and then perform the embarrassing act of public thinking about what I have done, or need to do, to achieve my own aims. Read more
This week, I’m visiting Colorado with my dad and brother, to partake in ritual hurling oneself down a snow-covered mountain. The downhill portion rather requires one’s attentions (and will eventually punish you for your lapses), but lift rides to the top can be slow, and so leave plenty of time for other considerations. One of this week’s topics is what I should blog about. I have a few thoughts that are working their way through – emergent properties and optional rule systems as related to encumbrance, RPG theory and game categorization, as a couple of examples. In the meantime, I figure on settling for something simple and autobiographical.
Way back in grade school, my genre obsession was Mystery. I read every Encyclopedia Brown, owned a shelf full of Hardy Boys, had gone through all the Sherlock Holmes and Poirot stories I could find, and was getting new children’s mysteries via interlibrary loan, because I had gone through what the local library had on hand. I even wrote my own series of stories for the state’s Young Authors competitions, and won out in my school district and went to the state convention several times. In short, I had it bad.
Then in fifth grade, I got a boxed set of The Hobbit and The Lord of the Rings for Christmas. From there, I followed my old, familiar pattern: books, and lots of them. The Chronicles of Prydain, the Enchanted Forest Chronicles, Chronicles of the Shadow War… lots of chronicles, is the point I’m trying to make.
Then one day I was hanging out with a friend when he showed me this cool game that he was playing. It was called Magic: the Gathering, and it was at the very beginning of the Rath cycle, and for all the years I played at the card game, I was enthralled by the outlines of the story that came with each new expansion, and the hints and details about this enormous multiverse and the epic struggles that are continually reshaping it. I eventually found the comics and the novels, read through the Brothers’ War, the accidental unleashing of Phyrexia, the cosmic war and ultimate defeat of a hegemonizing evil. Airships, planeswalkers, slivers and other stranger monsters. O true apothecary, thy drugs are quick.
One day, hanging out at the local game shop, wasting time waiting to play Magic, I espied a group setting up a table with several large tomes, and some dice. They invited me to join them, and I received a crash course in playing Dungeons and Dragons. For over a year, this was my D&D group, and we played second edition during some of its final years. The only other game I played with this group was Villains and Vigilantes, but I heard the lore as well – strange coincidences worked by modern mages, surviving friend computer, and so on.
Then came high school, and third edition. I had two mostly separate gaming groups, elements of which I still game with today. For one group, I ran a years-long epic campaign spanning multiple planes of existence. There was even an airship, in case my influences weren’t showing. The other group traded off game mastering responsibilities and had a variety of adventures, several featuring a shared setting that we collaborated on. We dabbled very briefly in the Forgotten Realms (it didn’t take), and also played in Eberron. In my personal favorite, I ran a one-shot locked room murder mystery set on board a lightning rail – Murder on the Orien Express.
Come college, I eventually assembled a new gaming group. I never wrangled an invitation to the highly regarded local Vampire game, but some of its players went on to play a GURPS/In Nominee fantasy game, and I got myself in. The following year (with, bizarrely, inspiration that came from prolonged exposure to Japan), I reconvened several of that group, pulled in some new faces, and ran a Mage: the Awakening campaign set in World War II London during the Blitz. As an aside, I like to think that I was responsible for two weddings by running that game. The year after that, I ran a sequel game with a handful of returning faces and a few new additions (but no new weddings). Besides those long investments, I played Exalted, Cyberpunk 2020, and Dogs in the Vineyard, as well as running a DitV session myself, and a nWoD mortals game using a scenario from the Call of Cthulhu d20 sourcebook. They weren’t expecting that…
After college, I wound up getting back together with the old gang. This was the age of Fourth Edition and virtual tabletops. I also discovered Fate, and after long years of gazing from afar, wound up failing to sustain several games with it – a Fate dragons game, and a Mass Effect game, both with extra crunch of my own devising/adapting. I have also run Legends of the Wulin, and played Chuubo’s Marvelous Wish-Granting Engine. Now I’m designing, running, and playing my own D&D-lineage game.
Besides assembling a retinue of armed and optionally disagreeable men, another D&D tradition is obtaining a castle, keep, or other stronghold. Some variants (especially Adventurer, Conqueror, King) go a step further, and assume that the new home base comes with feudal obligations and large territories to manage. Obtaining an interesting home base has long been something I have wanted to do in a game. Rules for these, however, tend to delve into almost minute detail.
I’ll begin with a seeming digression – one of the things that I find fun and helpful in Fate is the “Fate fractal.” Officially called the Bronze rule, the idea is this: Fate has a small set of very simple components for a character – aspects, skills or approaches, stress, and consequences. These components represent all the mechanics of the game, and therefore anything that needs mechanical support is necessarily able to be modeled as a character (or part of one).
Thieves’ Guild? Obviously it has aspects. Will the guild be acting against characters or the interests of another guild? Now it has skills to model its ability to act. Will someone else be acting against them in turn? Stress and consequences.
Is the building on fire? Sure, there’s an aspect for that, but if the fire is so deadly that it “attacks” the characters, it has a skill for that, too. If the fire can be put out, it might also have a stress track.
This approach makes it both quick and easy to give something the mechanics it needs, when it needs them.
The past couple of days, I have started actually playing around with programming in Rust.
If you want to play along at home, here is how you can get set up.
The language updates periodically, and there are several features that currently live on the nightly branch. The tool offered to manage this is rustup, which is your “toolchain manager”. This means it’s responsible for pulling down different versions of your core dev stuff – compiler, package manager, and the rest.
Since I work in a .NET shop, I’m using the new Visual Studio Code, which has a rust extension. It provides syntax highlighting and some basic code completion, but it’s far, far short of what I get with Visual Studio and C#. This is one of the areas that’s expected to improve this year, but there’s plenty of room to improve.
Doing the work
Since this is just playing around, I decided to redo a small utility that I’ve already written in C#. It scans a directory for all executables, then outputs the path (relative to the starting directory) and its MD5 checksum either to the console or to a CSV file, depending on command line arguments. The C# application is quick-and-dirty, but I did try a few optimization tricks – arrays of structs, splitting the work across multiple workers to compute hashes in parallel.
For my Rust version, I decided to start simple and do a single-threaded application. Rust is not “batteries included”, so I had to pull in almost everything I’d use a standard library for elsewhere – the MD5 hasher, the glob library to search directories recursively, a library for handling timing how the application runs, and even command line argument parsing all come from “crates”, which are third-party (or in some cases first-party-but-still-in-trial-phase) libraries that are pulled in via the package manager.
The pain points
Contrary to popular wisdom, I have not had to struggle much with the borrow checker – the set of rules applied by the compiler to guarantee that I’m not going to share the same reference out several times and have one part of the code start tripping up another. For a project as linear as this one right now, that doesn’t surprise me. Adding parallelism later on will no doubt make it more interesting.
My problem has been dealing with types. First off, it’s good that Rust’s documentation is as good as it is (and that the crates are all open source), because it has made me keenly aware of how much I rely on my accumulated knowledge of the .NET framework as well as quick and accurate code completion. Most of my time has been spent groping around in the dark trying to figure out what type or function I even need.
The other hurdle I hit is, literally, types. For example: I wish to abstract over “write to console” and “write to file”. In C#, this is easy because I can just get a Stream from either the console or a file, and then write to it. Base classes and interfaces form a hierarchy that lets me abstract over the details. Rust doesn’t let me get away with that, and here’s why.
First, Rust doesn’t have object inheritance, so there’s no type hierarchy in the sense that I am used to. Second, instead of interfaces, it has a similar concept called Traits (probably closer to C++ Concepts, but I’m saying this as someone who has barely done C++). The trick is that while there is a useful Trait to abstract behavior (in this case std::io::Write), I can’t go about just saying that I have some instance of std::io::Write. That’s because I’m trying to hold onto some concrete type that Writes, and the console (std::io::Stdout) and a file (std::fs::File) are two different concrete types. I can’t have some space on the stack (or can I? More in a later paragraph!) and have it be one of the two, don’t care which, just pretend that it Writes. The quick way to fix this is to turn them into a Trait Object – stick the real thing on the heap (Box in Rust parlance, new or any kind of smart pointer in C++, reference objects in .NET), and keep the pointer type as the trait. Once I have a Box<std::io::Write>, I can put anything that implements the trait behind it, and through magic auto-dereferencing, pretend I have the original object at hand.
The other trick, which dummy me only thought of driving home, is to use rust’s enum. Rust enums are much smarter than the enums you’re used to, which are numbers given fancy names. Rust enums are also called “algebraic data types” or “sum types” and the reason is that each variant of an enum is not just a named alternative, but it can have its own data-carrying type. For example, Rust doesn’t allow null pointers – the way you signal that you may or may not have some object of type T is to use the enum Option<T>, where you either have Some(T) or None. There are no thrown exceptions, so operations that can fail are modeled as the enum Result<T, E> and the action was either Ok(T) or Err(E), where both the data type T and the error type E are defined in the operation itself.
What I could have done was define my own Output enum, and given it types like Console(std::io::Stdout) and CsvFile(std::fs::File). For added trickiness, I could then implement the Write trait on my new type, and just forward everything along to the thing I actually have. Bam, one more pointer indirection done away with.
As of this afternoon I have the basic program behavior done. The next thing will be trying to parallelize hashing files, and then seeing how I can do performance-wise against my .NET version.
Preview material for Pillars of Eternity 2 got me thinking about multi-class design in RPGs.
I picked up Pillars of Eternity on sale for cough totally legitimate research purposes. For some reason, the game just isn’t grabbing me.
Pillars is very reminiscent of Baldur’s Gate, with several things cleaned up from baseline D&D (ish, anyway) rules, and several things made more fiddly to reward system mastery. Unfortunately for me, one thing I don’t particularly enjoy is games rewarding system mastery for very fiddly systems. The other problem is that while the game has a lot of original lore, it hasn’t managed to convey it well enough to pull me in.
I’m through Act I so far. The opening tutorial is blessedly shorter than I remember running around Candlekeep in BG1 being, and includes an actual (though small) dungeon that’s far less annoying that Irenicus’ opening dungeon from BGII. There’s also a nice small dungeon in the first town, though a bit of it fell flat for me. There’s a door puzzle that I couldn’t find enough clues to solve, but since I also picked up the key that opened it anyway, I don’t quite understand the point of the puzzle.
One thing I notice is that every map feels very, very small. My memories of BGI are so old as to be unreliable (I haven’t played it since at high school), but I’ve started BGII a couple times in the past many years, and I know that the opening dungeon is sprawling – merely escaping it took about as much play as getting through Act I, with more compelling immediacy to the story’s stakes.
As for the totally legitimate research purposes…
Here’s some rambling about where I’m directing my thinking on topics of interest to this blog.
I’ve got a few things I intend to write about – quest mechanics, rule modularity so far. Are there any topics you would like to have me cover?