Thursday, June 24, 2021

Painting Massive Darkness: Warrior Priests vs. the Spearmaiden Cyclops

It was a rough academic year. Even knowing that material goods cannot bring true happiness, I found myself excited to see that some Massive Darkness expansions showed up at Miniature Market. One that I picked up was Warrior Priests vs. the Spearmaiden Cyclops, and that is the set I just finished painting. I was in one of my periodic painting droughts, and this was a fun set for getting back into the swing of things.

Interested readers are welcome to check out my other Massive Darkness painting posts:

This set, then, contains the first Monster that I have painted: the Spearmaiden Cyclops. All those unpainted monsters in the Lightbringer box are going to be quite jealous!

First, the three heroes.

Moira

Moira

The first one I painted was this sorceress. It is the one I was most excited to paint due to the evocative character art. If I recall correctly, her artwork was used not only for the original Massive Darkness, but also in some of the promotional material or updates for Massive Darkness 2. I was disappointed to unpack the figure and see that she has a really strange pose. Rather than standing powerfully with her flaming staff, she is sort of leaning forward from the hips. It does not look heroic or menacing, but like she's getting ready for yoga. The face was also pretty badly cast. Despite my initial disappointment, I had fun painting her, and I like the warm purples, reds, and magentas. I opted against doing OSL with the flame.

Malleus

Malleus

Here's Malleus. He was a pretty straightforward paint job, and I used the opportunity to tinker with some of the inks-and-metallics techniques that Dr. Faust recently discussed. None of the techniques in his video were new to me, but sometimes it's good to be reminded of fundamentals. One significant difference I found, though, is that where he says he is just thinning the inks with water, I had a hard time getting a useful consistency with just tap water. I doped mine with matte medium, and that made it behave better on the brush and the miniature.

There are two different tones used on Malleus, following the subtle distinction in the card art. You can see it most prominently in his left leg, where the top of the knee is the toned down, greyer color and the rest is a more silver, more metallic. It's easier to see the difference in person since the light reflects differently off of the more matte parts vs. specular metallics. It adds a nice contrast.

Also, he was a reminder that all the Massive Darkness gang is addicted to fanny pack chains. 

Ostara

Ostara

I puzzled over Ostara for a bit. The cart art makes the armor look more yellow than gold, and so that's what I decided to do. I remember at the time being very happy with my mix of paints and mediums that I used to get this color... I wish I had written down what it was. I'll give you my best guess later on. The result, though, is nice: a bright yellow armor in contrast with vibrant purple cloth. I'm glad I spent some time putting a little extra dark lining around the armor panels, because that really makes it pop whereas originally it was too starkly yellow.

And here's the Monster, which is really monstrous.

Spearmaiden Cyclops

Spearmaiden Cyclops

Spearmaiden Cyclops

This is a big, heavy miniature.

I started with the flesh tone, but my first approach was too Caucasian compared to her card art, which has a similar purple tone to Moira. I spent a lot of time on the skin since, clearly, she is mostly skin. My first reaction was excitement, and when I looked at it the next day, I worried that I had taken the contrast too far. I suspected that this fear would diminish as I painted the rest of the figure, but it actually got worse. Looking at it now, I'm happy with it as an exercise in contrast. I don't think I took it too far, but it definitely has a kind of cartooniness. Incidentally, if I recall correctly, the base flesh tone is a mix of Vallejo's Flat Flesh, Buff, Magenta, and Neutral Grey, which I am jotting down in case I need to reference it should I get to painting the Stonebreaker Cyclops monster. The hair is Sorastro's famous blend of Vallejo Dark Sea Blue and Black. I was worried it might be too blue, but with the purplish skin tone, I think it's a good fit.

When I got to the yellow features on her pauldron and shield, I figured I could approach it as I did Ostara. Unfortunately, by this point, I had forgotten what I had done. I mixed up some test batches of metallics and inks, and the one that looked the best was a mix of Vallejo Lemon Yellow, White, and Vallejo Metal Medium. There's a very good chance that this is what I used on Ostara as well. Once again, I used inks to add some depth to the metallic parts.

Here's the whole crew:


I had a lot of fun painting this, although now I have to figure out where to store one painted Massive Darkness monster. As I mentioned above, the unpainted ones are happily jostling around in a cardboard box, but I don't think I can do that with the Spearmaiden Cyclops. That's a problem for another day.

Thanks for reading, and happy painting!

Wednesday, June 23, 2021

Summer Course Revisions 2021: CS315 Game Programming

The first of my summer course revisions is CS315: Game Programming. The online course plan can be found in the usual place. This was a fairly easy revision since I have recently revised a manuscript dedicated to the course. The paper has been accepted for publication in the Journal of Computing Sciences in Colleges, and I will be presenting it at the annual meeting of the Midwest chapter. Writing and revising that paper required me to carefully read through notes about the planning and execution of the course as well as my reflections, which are publicly available in a blog post. The paper includes some thoughts about what might be done in the future, so planning the course became a matter of following my own advice.

I decided to keep Godot Engine for Fall even though we will be back in the lab. I discussed this choice with my Spring game production studio course, which included students who had taken CS315 in Fall 2019 using UE4 and in Fall 2020 using Godot Engine. They unanimously agreed that using Godot Engine was a better choice and that focusing on 2D games in particular helped control project scope. 

I kept the overall course structure from Fall 2021, including the scaffolding of projects. The instructions are all based on Godot 3.x, and if 4.0 is released before the semester starts, I will have to think about which version to use in class. I removed the one-week 3D project from the course plan. Of all the work from Fall 2020, this was the least interesting. It will be interesting to see if students really care about this or not. It's not clear to me if 3D has the mystique to them that it once did for undergraduates. It's so common now that perhaps they will understand that it's fundamentally just like 2D, but with more asset work required and therefore slower cycle times.

Because we will be meeting in person, I have removed the requirement for web builds. I am a little sad to see this go because it's an interesting process, but it is no longer required when we can instead go back to showcase-style presentations. I can always add continuous integration as an option for the final project, which will be the first place where public dissemination becomes desirable.

I plan to have a one-week midsemester jam, potentially to be called the "Midsemester (Ex|J)am." This was a fun break for the students last year, to have a week to just make something that shows off specific technical skills. It should provide a useful transition to the final project. The descriptions of both of these are commented out of the course site right now since they will require a bit more revision. It does not seem worth that revision until I have a chance to get to know this crop of students, and Projects 0–2 should nicely fill up the first six weeks of the semester.

The schedule for the weeks will have students presenting their work on Tuesdays, and so in my plans, I have sketched in a few short tutorials for Thursdays. Some of the things I had in ad hoc videos last Fall I can do in class meetings, with the benefit of live Q&A. Without quizzes or attendance, there's a chance that students may decide to skip these meetings and just work by themselves. It certainly makes more sense for me to reuse the lengthy project descriptions I wrote for my asynchronous online semester rather than to write up shorter ones that are supplemented with ephemeral live demos. I intend to be open with the students here, to get a sense of what excites them and trying to use our time together most fruitfully, whether that means tutorials, Q&A, or philosophical discussions about the role of higher education in 21st century America.

One major addition I intend to make for the final project is the inclusion of development logs. I used design logs in Game Design in Fall 2020, where students had to log their efforts to earn a grade each week. Here, I would like to do something similar to make clear a distinction that some students seem to miss: the difference between "something is due in two weeks" vs "you are expected to make continuous progress on this over the next two weeks." It was the post-Thanksgiving, final iteration of the Fall 2020 game programming projects where I really became aware of this confusion. I hope that using development logs will help me get out in front of the problem. If nothing else, it will prompt me to have a discussion about this with the students, and perhaps I can even learn more about their experience through that.

Tuesday, June 22, 2021

Summer Flutter Development: Internationalizing the Thunderstone Quest Randomizer

Last week, I started laying down some of my Summer projects and began putting together course plans for Fall. I expected that, on Monday, I would jump in with both feet and get those new course sites up and ready. However, on Sunday, an unexpected thing happened on the GitHub page for my Thunderstone Quest Randomizer: a stranger posted a feature request to localize the app to French. 

I first wrote about this app about a year ago, when I described the reason for implementing a new randomizer in Flutter. Since then, I've released the odd improvement, including a significant internal improvement at the beginning of summer to allow the app to be built using null safety. That effort reignited my interest in the game, and so we've been playing a lot of it since then.

Sunday's request for localization support intrigued me for a few reasons. First, it showed that someone besides me actually looked at the open source code and cared that it was hosted up on GitHub. Second, the person who made the request is involved in proof-reading the actual French translation of the game, and it's neat to have "insiders" taking a look at a hobby project. Third, I talk about internationalization a bit in my classes, but I have never actually tried to internationalize a nontrivial application before. A quick look at Flutter's internationalization documentation intrigued me enough to make me want to get my hands dirty.

There were two major problems to solve regarding internationalizing the app: the app interface and the card database. It was pretty clear from early in my analysis that I could not easily use the same approach for both. I will address each in turn.

Internationalizing the app interface was mostly a matter of following the Flutter documentation. I brought in the Intl package and did the requisite configuration. I extracted all the user-facing strings into an application resource bundle file, which is a format I had not seen before. Authoring this JSON file involved a lot of tedious typing, and though I was on the verge of looking for tool support, I ended up just powering through it. I wrote descriptions for each string key, and I documented the parameters for each template string (which they call "placeholder resources"). Something that was not obvious to me from reading the documentation was that, while the intl tool converts regular string resources into dart literals, it converts placeholder resources into functions. This is quite convenient but it was not what I expected.

I used Visual Studio Code for all of my development, and it's worth noting that there's a slight hiccup in the toolchain when building internationalized applications this way. The arb file is transformed into dart code during the build process, but that build process is not triggered by saving the arb file. Writing UI code that uses the generated dart files then will give false-negative compiler errors until the whole application is reloaded. Fortunately, this can be done with the hot-reload tool. It's a workflow I got used to, but it seems like it would be convenient to hook the arb file's saving into a regeneration of the dart code.

Adding localization support to the card database was a more interesting technical challenge. The cards are all specified in a large YAML file that is loaded during application initialization. My original plan was to load only the localized names into memory, which would work fine if one only ever wanted the cards in their platform's default locale. However, when I got into it, I realized that I needed an easier way to change languages for testing. I had assumed there would be a toggle in Chrome that would simply change locale, but all the documentation I found said that it requires restarting the browser as well. That's too fiddly. I also ran into a synchonrization problem: the rest of the application assumed that the YAML would be parsed only once, but if changing the language required re-parsing, then the app architecture needed adjustment to account for the time this takes. 

After having written an almost complete solution using this approach, I abandoned it in favor of a  simpler one. Now, the YAML file is parsed only once, but all the localized strings are stored in memory in simple string maps. This certainly uses more memory than the alternative approach, but it is much easier to swap languages: using Flutter's simple state management tools of Providers and Consumers, the UI can watch for the language key to change and then alter which localized text is shown on the screen. I have not done any profiling to see what the actual memory costs are, and so I'm just banking on contemporary environments having memory to spare.

As of this writing, the app does not have French language support exposed because I only have the two resources localized that the original GitHub feature request gave as examples. However, it is set up so that uncommenting a single line in the settings view will expose language selection options. When someone wishes to localize the data into any language, then, it should be an easy matter to incorporate it into the app.

It was fun to spend a few days learning about Flutter's internationalization support and adding that to my app, even if right now, there's no difference to the user. I learned a few new tricks, and importantly, I gained some experience that I will be able to share with my students in the future. No more hand-waving about internationalization: I can show them an example of exactly how I've done it.

Wednesday, May 19, 2021

Family Adventures with Dungeon Crawl Classics, Part 2: Reflection, Critique, and Future Directions

(This post is part 2 in a series about playing Dungeon Crawl Classics RPG with my family. Read Part 1 here.)

Playing through "The Old God's Return" was the longest RPG series that my family has played to date. As I mentioned above, this is partly due to the two-hour cap on session duration, which I think worked well for us. There were certainly some points where I was willing to go a bit further, but given the range of age and experience, I will call this a successful move. It helped that it was one continuous module, with a coherent beginning, middle, and end. This took a lot of pressure off of me compared to my experience with other games like ICRPG, Fate, and PDQ, where I had to do the additional prep work of making a story. 

One concrete lesson I learned is neither original nor particularly insightful, but I will record it here. I really should have copied essential material from the module into my little notebook, such as the tontuu's stat blocks. This advice is given by basically every RPG pundit on YouTube, but the truth is that I haven't run someone else's module in a long time. The sometimes month-long gap between sessions would have also meant that my notes would have been a good refresher of the essentials, rather than having to re-read the module as prep each time.

DCC RPG manifests the OSR aesthetic. The world is dangerous, and the heroes are pressed up against it. I understand the appeal of such systems, and I could see myself really enjoying a continuous campaign with players who understand that they should not get too attached to their characters. Regardless, conversations with my wife between sessions made me realize that there is a gap in the design. When facing a dangerous world, good luck is needed, but one would hope that wit counts for something. However, there were almost no points in the game where cleverness was rewarded: more often, it was just a matter of rolling dice. 

I would like to explore that in a bit more detail, drawing upon our experience with "The Old God's Return." It was a good idea for Seth to scout the area around the top of the floating glacier, but he failed the roll, so it was fruitless. The players know that he failed the roll, and that there was nothing they could do except move forward and hope, which led to Seth's first fall. DCC RPG has no concept of failing forward as one finds in games like Dungeon World. Fail-forward strikes me as a much better way to reward players for cleverness and creativity, not to mention narrative-centered moves such as roleplaying a situation to the point of personal danger. Later, when facing the wall of rubble, Seth again decided to scout, but this time he made the rolls, and it led to that cinematic ambush. When the dice are with you, it works, but when they are not, it can feel like punishment.

One could say "That's just the OSR aesthetic" and be only partially right because of one particular and excellent rule: the fighter's Mighty Deed of Arms. Whereas the other classes have a laundry list of abilities, the fighter has essentially just this one, but it is a doozy. On any attack roll, the fighter can try to accomplish some mighty deed, such as tripping the opponent, knocking away a barbarian's axe, or grabbing the magic chalice out of the sorcerer's hands. It's a strangely narrative moment in an otherwise statistical game. This mechanism accomplishes the stated design goal of differentiating the fighter from the other classes, which I consider a great success over the earlier D&D distinction, which was basically that fighters have bigger numbers.

Mighty Deeds of Arms introduces a contrast that highlights the lack of robustness in the rest of the system. The fighter is the only one who can use the environment to his advantage in combat, and while it's fun to be the thief who finds the trap, that happens rarely, and there's a lot of time in combat. Put another way, it may be more consistent for the fighters to just have bigger numbers. DCC RPG has no concept of 5e-style advantage or ICRPG-style hero coins: there is no mechanical way to encourage players to do something contextually interesting, so it boils down to who rolls well. By way of comparison, it's worth looking at Phoenix Point: Dawn Command, which had the best environmental interaction system I have ever seen. For each scene, it provides a list of items from the description that can be used to the players' advantage, but each thing can only be used once, akin to boosts in Fate.

Playing games like DCC RPG and PbtA games, players are often choosing from a menu of options. With DCC RPG in particular, there is a sense that if it's not on the menu, it cannot be done. This is not technically true, of course, in that a good DM will come up with a reasonable, systemically-appropriate way to handle special cases, but keep in mind that I am playing with a broad range of ages. I already mentioned how Joe the Cleric's player was clearly overwhelmed by the number of things he could do, and enough time passed between each session that almost nobody could remember how to read their own character sheets. An anxiety manifests in my wife, who claims that the family "is not good at" these games; as I have written about before, I think this is a sort of UX problem, where the system does not present itself as learnable. This came up in the final battle with Tjaptar, for example. When Joe commanded the Old God to flee into the woods, my wife started looking for interesting things that her character could do... but the only thing she could do was go attack the Big Bad, which is a false choice since it's the only one. Indeed, it's slightly worse than that: the party had earlier learned that Tjaptar's power was centered in his antlers, and that they should attack those. This meant that every shot had to be a called shot at -4, which for the party meant a success only on a natural 20, or, with about a 7% chance and restricted only to fighters, a successful mighty deed. The choice becomes really less than meaningful then: do you shoot Tjaptar in the regular way and have nothing good happen, or do you take a crippling penalty? You can see why morale was low at the end of the penultimate session.

Now, of course, I could have put a mystical amulet on the altar in the back of the room that was a nexus for Tjaptar's powers, and foreshadowed its existence, and given her the option of getting Joe to cleanse the evil altar... but now I'm doing the work of writing a module rather than the much easier work of running a module. Once again, if a group wanted exactly this kind of OSR experience, then more power to them, but looking at it as a designers and as someone playing with my family, I am left hungry.

My family has been talking some about the experience, and no one is clamoring for more DCC RPG right now. My wife insists that she does not like dice, although as the session report indicates, she was certainly the most emotionally responsive to their fickleness, the first to moan at a 1 and the first to squeal on a 20. I suppose one does not have to like that feeling, but an outsider watching the game would think it was her favorite part. Regardless, our conversations brought us back to more narrative-first games, and Fate in particular. I played a fun ad hoc session of Fate with the older two boys which I think they were excited to continue, but for which I ran out of steam. The whole family played one session of Fate together with a setting that only resonated to a few of us. In both cases, I feel like I was an amateur at running the game, moving too slowly through things that could have been left on the cutting-room floor. I was also improvising without much direction, while trying to keep the needs of the family in mind.

I think our next move will be to try Fate again, but with a few specific constraints. One will be to limit the duration of the game, which will be good for all of us—maybe especially me, so that my creative juices do not run dry. I will need to have in front of me a copy of the players' character sheets, because I realized that it was too much to try to remember their aspects from across the table. Another constraint will be to use a familiar setting. Our previous family game of Fate was about exploring an unfamiliar planet with a B-grade sci fi aesthetic. However, because the genre and setting were unfamiliar, most of the players had little sense of what they could do in that environment. Instead of introducing a fantastic new environment, we will definitely be choosing settings that all the family can understand. Fortunately, they read a lot, and so there are a lot of options. Unfortunately, our conversations have not led us to one that everyone is equally excited about. Part of me wants to do a medieval fantasy setting just because I have all these excellent miniatures that could be used with zone rules, and I know the boys can draw on their experience watching classics like Hawk the Slayer or the MST3K riffing of Cave Dwellers. On the other hand, I find myself thinking about Sherlock Holmes' Victorian London or Indiana Jones and wondering whether these can be laced with some fantastic elements and secret societies. I think if we focus on a one-off, then there won't be pressure to saturate the world, and we can see where that takes us.

Family Adventures with Dungeon Crawl Classics, Part 1: The Session Report

My family went through a Dungeon Crawl Classics RPG funnel back in February, and we decided to continue their adventures as level 1 characters. One of the outcomes from the family debriefing was that short sessions were better than long ones, and so we decided to proceed in two-hour increments. After reviewing some of the appropriate first-level modules I picked up through Humble Bundle, I decided on "The Old God's Return," which is 2013 Holiday Module by Michael Curtis. The adventure starts off during a cold winter solstice celebration, which seemed appropriate in mid-March when we started this module that, from the prologue, "can be completed in a single session." It ended up taking us four, but I have no regrets about the timeboxed session duration: everyone was able to maintain their attention much better, and breaking in the middle of a fight meant we could come back for a cliffhanger. The only tenuous division was between the last two session, where the party had started the fight against the Big Bad, and it certainly looked like they were all going to perish... but I'm getting ahead of myself.

(This remainder of this post contains numerous spoilers from "The Old God's Return.")

Our heroes include: my wife as the fighter Chioggia and then, played by the boys and in descending age order: Mord, the Wizard; Seth, the Thief; Joe, the Cleric; and Luck, another Fighter. 

The party arrived as guests of honor to the Winter Solstice celebration as guests of honor, as it was the anniversary of their having cleansed the "The Portal Under the Stars." This gave some background for how they had gone their separate ways to learn their first-level skills and spent their treasure. The party was interrupted by an attack of tontuu—strange, ice-cold, dwarf-like creatures who are the emissaries of the titular Old God. Mord unleashed burning hands onto one of them, revealing in the process that his mercurial form of this spell summoned otherworldly attention. While the magic did its job of crisping up a tontuu or two, the whole party felt as if someone, or something, was watching them. This seemed to freak out my wife, who is generally uncomfortable in not knowing the line between rules and story in tabletop roleplaying games. Indeed, here is a case where the mercurial magic gives no specific indication of the rules, but I started hatching a plot around it.

Joe the Cleric, being Lawful, decided to turn the evil creatures. He rolled an astronomical result that scattered the remaining tontuu, which gave him a strong feeling of efficacy.

The party accepted the blessing of the town's priest, gaining points of "sovereign fire" to be used during the adventure. In retrospect, this was a strike against the module, since this introduced yet another thing for the novice players to have to manage. I'm sure it would not have been a problem for veteran players, but I should have noticed this complication when reviewing first-level dungeons.

The party borrowed horses and chased down the the source of evil that was plaguing the region: a floating glacier that, unknown to them, contained the ruins of an ancient temple. The temple was dedicated to Tjaptar, a long-forgotten god who was using the tontuu to capture the children's souls he needed to grow in power. Classic Old God stuff, that. In order to reach the floating structure, Luck burned half of his sovereign fire points to adopt a fiery form, charge the one tontuu guard he could see, and then lower a rope ladder for the others to climb up. The youngest son was very excited about being featured here, and he still sometimes talks about the time his character flew in the air and punched out a bad guy.

The party climbed to the flat surface at the top of the floating glacier, where they could see the lone structure in the center: the nearly-buried top level of a ziggurat. They wisely had Seth scout the area before heading in, but unfortunately, Seth's player rolled poorly, and he walked right into an ambush. Three tontuu hurled spears at him, taking him down. Seth already had a low stamina, and although Joe healed him before he died, he lost a precious stamina point, dropping his max HP even lower. The party survived the ambush, and this ended the first session.

The next session had them descending into the temple. There were a few exciting moments in this middle chapter of their adventure. At one point, facing a pile of rubble, Seth's player made a series of successful checks to climb over and scout the other side, which allowed the party to set up an ambush of their own. This was especially helpful since both Chioggia and Luck were much better with their bows than with their swords, so a round of free missile attacks was appreciated by the fighters. During the battle, Mord cast flaming hands again, and this time, an otherworldly eye opened upon his forehead, peering through him into the temple.

During a battle with a particularly nasty creature, my wife fumbled an attack, giving her a -2 to her next roll. She really does not like dice, and so this was extra disheartening. However, her next roll was an 18, which was exactly what she needed to hit the beast, and she did maximum damage to it. When the creature was down to one hit point remaining, Luck's player rolled a natural 20, critically punching it in the face, again to much fanfare.

Joe the Cleric was unable to complete a single spell or healing ability, and he ended the session with a disapproval rating of four. That means that, on any future attempt, he had a 20% chance of something like critical failure and, potentially, the loss of his abilities.

In the penultimate session, the party unwittingly unleashed a dangerous monster from its icy prison, an frozen insectoid creature animated by the power of a nearby sorcerer. Chioggia charged across the room to defend the rest of the party, rolled a natural 20, and knocked one of the thing's pincers clean off.

This was also the session that began the epic showdown against Tjaptar. It began with Seth climbing a tree (yes, the temple was filled with strange underground conifers) to see what was coming up. Tjaptar  was aware of his presence and cast his "wood wyrding" spell, in keeping with the module's tactical notes. Seth had only three hit points, and when the arrows in his quiver grew spikes that shot through his chest, he fell to the ground with none left. Joe once again got to him just in time, selflessly burning two Luck to cast a healing spell to keep Seth alive. This made Seth lose yet another Stamina, disappointing his player. All these holes in his chest make him look like a short-termer.

There were two other creatures in the room with Tjaptar, one being a tough tontuu that kept two party members occupied by the doorway. The other was turned by Joe, which was hit by a timely critical hit by Luck; the fleeing of this creature let the rest of the party focus on the Big Bad. However, Tjaptar had already destroyed Joe's mace—his only weapon—with his wood wyrding, and Chioggia and Luck had dropped their bows and arrows in fear that what happened to Seth would happen to them. Mord blasted the tontuu with flaming hands, expecting to fell it, but its extra hit points further dropped the morale of the party.  Seth leaped up and landed a critical hit on the creature, but a poor roll on the critical table, combined with his low luck score, meant that he actually missed, which was a catastrophic twist. As the timer rang indicating the end of our two-hour session, the party was left without much hope.

About a month later, we were able to finish the adventure. This was in the second week of May, so the wintery theme had long since lost its meteorological synergy. Despite fear of a TPK, the players were eager to see how the adventure would conclude.

Chioggia and Mord faced the tontuu while the others engaged Tjaptar. Mord let loose another flaming hands, and this time, he got the most fearful result from his mercurial magic: the extradimensional being appearing before him. I was as surprised as anyone, and I realized at that moment that I had a rough plan for what to do if this happened, but I had not done the legwork. It turned out that, in "The Portal Under the Stars," it was Mord who had picked up the horn of the serpent guardian, Ssissurag. He still carried it with him, though he knew not what he could do with it. I made Ssissurag itself appear and offer Mord a bargain: the power of venom to defeat the tontuu in exchange for doing the serpent's will. Mord, being chaotic and fearing the destruction of the party and the success of the Old god, agreed. Ssissurag struck out, biting the tontuu and defeating it. In truth, it only had a few hit points remaining, but this was an excellent conclusion to Mord's personal story.

Meanwhile, the Old God was blasting the rest of the party mercilessly with a freezing blast, which was his inversion of flaming hands. Joe tried to heal himself and failed, raising that disapproval rating to five, and in the following round, he was finally able to successfully heal himself. The player was excited to play a cleric, but it was never clear to me that he understood all of his options and their implications. Indeed, several times we had to hold up the action to review his various skills and abilities. With the party losing hit points faster than they could injure Tjaptar, and after reviewing all his options, Joe decided to cast Word of Command, despite a 25% chance of disapproval from his deity. The player rolled an amazing 19 and commanded the Old God to "run," while gesturing away from the party. Tjaptar failed his Will save, and so after Joe's repeated pleas to his deity for help, the divine power finally flowed through him, and Tjaptar turned tail and fled into the trees. The party took some free attacks of opportunity, including Luck's landing a mighty blow. 

Chioggia grabbed his bow off the ground, lined up the shot, burned a point of sovereign fire to imbue the arrow with fiery magic, and let fly. The roll was a natural 20, and the critical table indicated that the target moved into the blow, taking an extra 1d8 damage. Chioggia's explosive arrow destroyed the Old God!...

But of course, this triggered the collapse of the ancient temple. That's just how these things go. The party climbed out of the temple, to the top of the disintegrating glacier. At this point, everyone had the five remaining sovereign fire points required to fly down to the ground except Luck: he had used five to be the one to fly up, and he had used one in an earlier battle to imbue his sword with flame. Luck tried to climb down the side of the glacier, but he failed his roll. His last chance was to make a Reflex save to jump to a chunk of descending ice, and he made it. The party had survived and saved the region.

That completes the story of my family's adventure in "The Old God's Return." Part 2 includes a reflection on the experience, a critique of the system, and some ideas for where we may go next with our tabletop RPG journey. You can read Part 2 here.

Tuesday, May 18, 2021

Memories of Pathfinder Society, seven years later

I set myself to cleaning my home office this morning, and I came across a few interesting odds and ends. In one dusty pile was a folder containing my Pathfinder Society notes from a trio of sessions in 2014. The sessions were run by friends in the Indy area who have since moved out of state. I don't expect I would ever need the character sheets and logs. It was fun to see them again, though shocking to see how many years ago that was. The sheets are in the recycling bin now, but I thought I'd share a few memories about the experience here.

These three sessions have been my only experience playing Pathfinder RPG. I was and remain an outsider to "the scene." I decided to play a paladin because I had a fun idea for a character and I had never played one before. It was only afterward that I discovered that paladins had a reputation within PFS as being for powergamers, which you'll see is a bit ironic. I decided to play a paladin in his mid-50s, a farmer who received a calling to be a holy warrior after his family was killed in a raid. I named him Craddoc, which was a name I pulled from online references to Lloyd Alexander's Prydain Chronicles; I had read those in my youth and was inspired to search there for names, though I have no recollection of the namesake's role in the stories.

Craddoc's companion was Absalom*, his faithful border collie who was the only other survivor from his village. Absalom was just a dog, and Craddoc was very protective of him. This confused some of the other players at the table, including the DM, who thought I wanted a war dog that could charge into battle and take some hits. In my imagination, Craddoc would patiently tell Absalom to sit, stay, and be quiet, and then he would charge into battle. Afterward, he would return and pat the good boy on the head, perhaps giving him a treat. 

This leans into one of the curious phenomena around the game. I was interested in a heroic journey, exploring the adventures of Craddoc and his companions. Playing with this group, it was clear that some of the others had more of a CRPG interpretation of TRPG. Indeed, once it became clear, the DM and I had a great conversation about this: his interest was in making an environment like World of Warcraft, where players do missions to gain loot, whereas I was approaching it as one who wanted to engage in a story. Seeing how the sessions unfolded, I got to understand that PFS was not really designed for what I wanted to get out of it, but I still enjoyed it. One of the most memorable moments was when the rest of the party was sneaking into a warehouse, which of course the paladin refused to do. I volunteered to "take care of" the guards at the front door. I am sure the players and DM thought this meant I would go attack them, but instead, I explained to that I wanted to greet them, get to know them a bit, and then use some of my treasure earned in a previous session to buy them a round of beers at a nearby tavern. Craddoc made friends with the guards while the others did whatever the quest required, and I got to enjoy a memorable story moment.

There was another interesting conflict between the PFS experience and designed and the players at the table. One of the players brought a carefree gnome adventurer to the table. This character was ostensibly modeled after Indiana Jones but combined with the recklessness of Daffy Duck. A particular moment I recall involved the party being in an icy cave, at the top of a long, descending tunnel containing unknown perils. The gnome decided to run to the front of the group, leap forward, and slide down to the bottom of the tunnel on his belly. In a cartoonish campaign, this would be a great move, but in a deadly fantasy setting, it seemed unwise. I played Craddoc as completely flummoxed at it, treating the gnome like one of his children, which seemed appropriate at the time. At the same time that Craddoc (the character) was flummoxed, I (the player) was also a bit confused. Was this the other player's version of narrative-first gameplay, or did his character have a death wish? It was never really clear to me, and this was our last session together.

I don't think I ever shared here the miniatures I used for Craddoc and Absalom. The "dog" is a wolf miniature from a ranger-and-wolf set, but I was pleased to see that with the right paint job, it works as a border collie. I chose the miniature for the paladin in large part because I could paint the hair and beard to convey his age. The original had a shield attachment on his left arm, which Craddoc did not use, so I just filed down the peg and did not include the shield. I believe that, to date, these are the only metal miniatures I have painted since my teenage years.

Absalom and Craddoc

* In my papers, I actually found two different character sheets for the dog. They had identical stats, but one was named "Merlin" and the other, "Absalom." The second seemed to be the more recent. Reviewing my game notes, I noticed that one of the other characters was named "Myralin," so I think I changed the dog's name after the first session to prevent confusion between these two nearly-identical names.

Tuesday, May 11, 2021

The CS222 Optional Summer Enrichment Exercises

In my earlier post, as part of my reflection on the Spring 2021 CS222 experience, I mentioned an optional summer enrichment program that I assembled for the students. The full document is in the course GitHub organization, and it contains some fluff explaining the context and goals. I decided to also copy over the exercises here, in case they are of general interest. The version on GitHub will eventually be discarded along with the students' repositories, probably the next time I teach the course and need to repurpose that organization.

Without further ado, then, here are the exercises that I designed to help students build their knowledge of data structures in Java while also strengthening the skills they learned in CS222. 
  1. Watch my video about developing a linked list with TDD. In the video, I mention several areas in which the sample problem is underspecified, such as not handling exceptional cases and not supporting remove-by-value. Make a list of those, then work through a complete linked list example using TDD. This will strengthen your knowledge of Java, data structures, and Clean Code.
  2. Using what you learned in that previous video, write your own implementation of array list. Note that the task list will be almost identical. The special cases to add will be where the internal array needs to be resized. For example, you should set it up so that your ArrayList constructor takes an argument which is the original size of the backing array. Then, make sure you test a case where you add more elements than fit into that array, in which case your implementation should be allocating a larger array behind the scenes.
  3. To get practice with recursion, try the exercises above with recursive rather than iterative solutions. My video shows an iterative approach, but anything you can do iteratively you can do recursively.
  4. Write your own library of ADT wrappers. For example, make an interface Queue that defines the behavior of a queue, then use TDD to write a LinkedQueue implementation that uses Java's LinkedList as a backing data structure, or ArrayQueue that uses Java's ArrayList as a backing data structure. Try it with Stack as well.
Consider it CC BY-SA 4.0, which is how I've been licensing all my public educational resources lately. I think it was on the SIGCSE mailing list that I saw someone exhort the community to be explicit about their licenses, and being a fan of Free Culture, I think it's a great idea.