Coding into the Void

Coding into the Void

A blog that I’ll probably forget about after making thirty-five posts.

Champions of Shond Retrospective

Champions of Shond: Echoes of Faith has been at the top of my mind for a while. Working on Sanctuary's Grasp for the Dungeon Crawler Jam 2023 really got my brain hooked on the concept of making dungeon crawlers. After finishing that in April, I had three separate ideas for dungeon crawlers that I wanted to make. Two relatively conventional ones, and a more experimental one. This, of course, was one of the conventional ones.

This will discuss plot beats from the game and the novella, but honestly, there’s not all that much to spoil.

Inspirations

It ended up being an amalgam of ideas and tones that I pulled from three separate games.

The first Diablo game, atmospherically, is an incredibly evocative game. It’s an intimate setting, with it having a town that you can come back to to pick up side quests, heal, and talk to the NPCs. The later games are more expansive, but it’s to their detriment tonally. The idea of a whole game being centered around a corrupted holy site is such a strong premise, and I used it unabashedly in Champions of Shond.

Another series that nails a tone is the Ys games.1 They have a sense of adventure, with Adol dropping in (often with Dogi in tow), solving some problems, and then leaving for another expedition. You know that Adol is going to come in, solve some problems, and then leave, with only tales of his valor lying in his wake.

The third is Wizardry, which feels like a cheat to put on here, since I haven’t played even a half hour of all the Wizardry games combined. Clearly it’s a dungeon crawler like most Wizardry games are, but also it pulls monster stacks2 from it. The first Wizardry, like Diablo, has you descending deeper and deeper beneath the surface.

A Multi-Media Experience

I wanted to make a game that combined those two tones into a single dungeon crawler. However, I’d set a game development goal of six heavily writing focused games for the year, and I’d done, checks notes,3 one. So this had to be something writing focused for me to even pretend to be on track.

To ensure that there was a strong writing component, I decided I’d write a novella introducing my Adol-like character, Zel.4 I knew I wanted to experiment with having two playable characters in the party, so I decided to have the novella cover how they first met.

I sketched out a basic path for the story to go on, and it became more and more clear that the prequel was more about Mas, the other character, than it was about Zel. This is actually in line with the Ys games, where the focus is more on the character arcs of the other characters, as Adol serves a more passive role in the story, but I realized that Champions of Shond really felt like it was the two of them playing off of each other, not just Zel.

Zel was supposed to be the more introverted, nature-loving character, while Mas was the outgoing, but somewhat co-dependent, one. Mas gets some development along that path, often to the detriment of Zel’s development. I felt like I struggled at giving each character their own voice. I’d often write dialogue lines and think, “Well, really either one could be saying that.”

I used Ys IX’s prequel novella as a target for length,5 which was around fourteen thousand words. I sketched out a story structure with rough beats, although it was often just plot progression like “they face off against the villain and lose” and “they do something to help train for the next confrontation”. As I was writing it, mostly in sequence, where the plot would go slowly settled down. I ended up overshooting my word goal quite considerably, as it ending up being around 50% longer than my original goal of fourteen thousand words.

The novella was helpful in getting me a basis for the characters although, as I said, they didn’t have a strong identity. I intentionally made them have more camaraderie in the game than the prequel novella, as in this they’re hitting their stride as an adventuring group. They’ll tease each other, but it’s a friendly teasing.

Making the Game

Making the Levels

Champions of Shond was made for LOWREZJAM 2023, so it was locked into a two week period for game development. Since the game was hugely overscoped and I was long on vacation time, I ended up taking off the first week of the jam period.6 I’d decided to use two tools I hadn’t used in any released games before, ink and Tiled, and it let me get familiar with those workflows without the interruptions of work.

For previous games, I’d either used procgen,7 levels loaded from hand-coded XML,8, or built the levels directly in Unity.9 Tiled was a time saver for that. While it’s normally used to make tile maps, I used it to set up the terrain and the “theme” that each tile would render in, as well as objects on those tiles. After I had set up the bindings to import from Tiled to Unity10 and render it in my engine, it allowed for a speedy iteration time without requiring me to drop out of play mode.

For dialogue and interactions, I used ink. It has a Unity integration already written by inkle, the creators of ink, and using it is a very smooth experience. The documentation is good, and the scripting language is robust. I decided to go “all in” on ink, using it to manage all state and flags.

Since it provides an API to load and restore a JSON blob, it’s trivial to save and restore. The limitation it has is that all variables need to be declared in the ink files, so you can’t just inject flags willy-nilly to save. This would have been a problem if I wanted to save enemy death states in ink, but since I decided on random encounters, it was not an issue.

Previously for dialogue I’d used a connection of scriptable objects hooked up directly to game objects in unity. Since I was loading it from XML, it would have been clunky to set up those bindings, as I’d need to map each scriptable object to a key. Instead, I had Tiled objects with the “InkInteractable” class just use the corresponding ink knot. It made it less error-prone and easier to visualize and hunt down what object was connected to what ink dialogue.

Scripted battles, entrances, and exits were also hooked up to ink, and I was able to do most of what I wanted without any fiddling around. I’d already toyed around with ink in Fighter’s Guild, a game I planned to work more on this year, but it was in a simpler and much more narrative-focused manner. I wouldn’t be surprised if ink becomes a more frequently used tool in my arsenal in later games.

Similarly, I replaced scriptable objects declaring enemy stats with JSON. This ended up being somewhat unwieldy, as I couldn’t find a formatter that was relatively concise without being a nightmare, but it was easy to load and use in-game. It loaded on play, so I couldn’t tweak things mid-game, but that would have been trivial to add.

The worst fit I had for using ink as a save system was the map progress, which I just encoded and stuffed into the save file, dramatically increasing the size. I could have done some optimizations to lower the size of the maps, like not having all the tiled maps be 64x64 in size, but that felt like premature optimization for something that wasn’t a huge issue.

Making the Mechanics

Going into Champions of Shond, I knew I wanted random encounters, but I had no clue what the stats or battle mechanics would look like. I ended up going with a combination of seven stats: HP, MP, Strength, Magic, Defense, Dexterity, and Speed. HP was health points and MP mana points, clearly. Strength determined chance to hit and damage for physical attacks. Magic the equivalent for non-physical attacks. Defense was a modifier on chance to be hit and damage reduction for all attacks. Dexterity was a modifier on chance to hit and be hit. Speed determined how frequently the player would act.

Since I was tight on time and screen real estate (64x64 pixels), stats were allocated statically by level ups and item pickups. I’m not a fan of letting players lock themselves into bad stats, and I did not want to have to implement a respeccing system.

I’m not happy with how this system ended up working.

Magic ended up feeling underutilized, as it was only used for some of Zel’s specials, with it not mattering at all for Mas. If I wanted to make a character that was hard to hit, I either had to also make them hit often or weakly due to the combination of stats. This gave me fewer knobs to mess with for changing encounter difficulty.

Damage and magic increased sublinearly, which is bad for feeling like you’re making progress. A strength stat of 4 would roll between 2-4, averaging a 3. A strength stat of 8 would roll 4-8, averaging 6. So while the stat increased by 4, the average damage increased by 3. This made battles feel similar throughout the game, although each character got slightly more tools to play with.

The resolution limitation affected that as well, as the UI I had settled on didn’t allow for displaying many spells, so each character just got four to pick from in the end-game. Due to the attrition-based nature of the game (you have to return to the surface to heal, although there are shortcuts at floor 4 and 7), it discourages using magic, making fights boring slugfests. In fact, when you’re facing a boss, the best strategy is to just run past every encounter to end up there with max MP and HP, which isn’t fun.

I had considered adding a light and heavy attack in addition to the basic attack, but decided against it. The light attack would have halved the damage in exchange for advantage on the dex roll to hit, and the heavy attack would have done the opposite. It would have added complexity to the default attacks, but I’m not sure if it would have made all the trivial random encounters11 require too much thought.

I did one run through for balance and probably should have done more, but I ended up being very burnt out on playing the game, and by the Sunday before submission, I wanted nothing more than to never play the game.12

Making the Story

I had the novella to guide me through the characters and a setting that I wanted to explore—a tainted hellmouth of a temple. I’d referenced the Hopeseekers, the faction behind the events of this game, in the novella. They didn’t end up being the primary antagonists in the novella, but it did set the tone for how the two would react to them.

I tried to get a variety of side quests, establishing a goal of one side quest per floor. I had fun with them, and tried to make them not just be simple fetch quests. The most notable one of these is the one in which you have to find a girl that was kidnapped from the town. There is a twist to the quest, so players that don’t explore might find themselves with a less than optimal outcome.

In general, I’m proud of the quests. I think they have a nice variety in motivations, and they get reactions from the townspeople as necessary. I think my writing of the Hopeseeker motivations feels believable, as they are attempting to invoke a lesser evil to fight off a greater one.

Thoughts

The section on mechanics may make you think I don’t think much of this game, but I’m quite proud of it. Writing a twenty thousand word novella is no mean feat, and I accomplished a very broadly scoped game across a short period of time. I got more familiar with two different toolsets, and made some code that will streamline development in the future. While it is derivative, I enjoy the world that I created, and could see me coming back to it at some point.


  1. Most of them, anyway. Don’t get me started on Ys IX. ↩︎

  2. Albeit done mechanically different from it, I believe. ↩︎

  3. And that one’s a stretch. ↩︎

  4. He’s really nothing like Adol, but Adol’s the main character, so… ↩︎

  5. It inspired my novella, even though I didn’t find it particularly compelling. ↩︎

  6. Not quite, as the jam started on August 1st, a Tuesday, and I just took off that week entirely, but it was close. ↩︎

  7. Like Deeper and Deeper, a game I made for a previous LOWREZJAM. ↩︎

  8. Like ProtoBound. ↩︎

  9. Like Sanctuary’s Grasp and A Colossal Interruption. ↩︎

  10. Mostly through using the TiledCS library. ↩︎

  11. Of which there were too many, but lowering it would have affected the whole game’s leveling curve. ↩︎

  12. Which doesn’t mean the game is necessarily bad, since no game developer will have a clear-eyed evaluation of the game’s strengths and weaknesses. ↩︎