Accepting the Exceptions

Wow, a month has slipped by since the last time I published something to the site. That isn’t what I had in mind for an update schedule. I was hoping to do something every two weeks at a minimum. I will try to better honor that going forward. I want to keep this site from going stale, and taking an hour or two every few weeks to write something should be perfectly doable. Anyway, on to the meat of the entry!

Update on the NPC Generator

As I’ve talked about previously, what makes this project such a pain to produce (and why there isn’t one quite like this to my knowledge), is that the rules are full of exceptions and modifications. It’s built on it. It’s also built on making a lot of decisions that offer situational advantages. Things like getting bonuses for using a certain weapon, fighting a certain monster, or favoring a certain school of magic.

These little situational advantages aren’t a problem when they’re spelled out and are the same for every character of that class or race or what have you. A good example is characters that are smaller races (dwarves, gnomes, halflings) get a bonus to armor class against large opponents. This is easy; if the character is a gnome, add the power to the character sheet and leave it to the GM to remember to account for it (a large part of games like Pathfinder is remembering all the situational stuff when the time comes; a skill I’m terrible at). The trouble comes when these situational advantages are combined with character specific choices. Now I need to combine a power with logic that accounts for the character’s other powers and abilities to make a coherent choice.

A good example to demonstrate this is Fighters’ Weapon Training and Weapon Mastery. It may surprise you to hear that Fighters are good at fighting. They get a lot of bonus feats based around being good at fighting as well as some powers that boost their offensive and defensive capabilities. The first of these powers is Weapon Training, which basically gives the fighter combat bonuses when using a weapon category of their choosing (say Heavy Blades or Polearms). The trouble comes from the fact that a very common feat choice is Weapon Focus, and then Weapon Specialization. If a Fighter has taken the Weapon Focus feat, then when they get Weapon Training, they should pick the weapon group that their focused weapon comes from. And of course they can take Weapon Focus for multiple weapons, and get to pick multiple groups for Weapon Training as they gain levels. Then, the whole thing caps off at level 20 with Weapon Mastery which gives them advantages when using a single weapon (a rapier, say), and of course this decision should be based on picking the weapon that the fighter is already the most effective with based on the feats and Weapon Mastery decisions that have been made to this point.

This alone is kind of a mess, and there’s something like this for each of the classes, more or less. And very little of it is the same kind of mess. The big challenge then was how to write a program to go through and make all of these decisions without just writing a separate logic tree for each of the character classes that would handle all of the decisions but also repeat a lot of the things that are similar.

At first I was going to use an abstract base class, and have a module for each of the character classes derive from that. Then the things that tended to be the same for each class could be grouped into the base class, and the children could define the logic specific to being a Barbarian or a Rogue or whatever. The trouble with that, to me, was two-fold.

First, there are a lot of classes in this game. Paizo has published a lot of content for Pathfinder, and many of the books add new classes, each one requiring it’s own module. Every time a new book comes out with new classes I’ll have to write a new module that is largely the same as the others, and so I’d be updating the code all of the time. I really didn’t want to do this. Rather, what I want is to be able to create a logic engine that can create an NPC of any character class, existing or yet to be defined, without requiring me to go and change the code.

The second problem was just that the whole thing felt like a mess. A lot of logic seemed to be relatively generic to each class, but had to be tied into the parts that weren’t generic. It also meant I was defining a lot of things in code that should have been in the database. This last part wasn’t necessarily emergent from the design so much as just something stupid I was doing at the same time. However, once I realized I should move all that stuff into the database and out of the code, it made it pretty obvious to me that once that’s done I should be able to create a logic engine that is agnostic to the character class being created.

A Bespoke Language

So the solution finally came to me, courtesy of past experience and having read The Pragmatic Programmer: Write a Domain Specific Language. This would allow me to embed commands into the database model that could inform the logic engine of decisions it would need to make based on recently acquired powers, what would need to be added, what would need to be excluded, and so forth.

When I was first introduced to this idea, I was finishing up my degree and taking a programming languages course. It seemed kind of crazy to me to write a whole new programming language to solve one specific task. But that was mostly because I was taking an academic course that was focusing on defining general purpose tools and aspiring to creating the platonic ideal of a programming language (which was apparently Ada). But that’s not what a DSL is. At least not when I make one.

No my friend, my DSL was quick and dirty. It’s case sensitive, has almost no expressiveness, and a syntax bad enough to make even the most tolerant programmer want to barf. It’s not quite Ook, but it’s closer to that than, say, C#. But it has one thing going for it: It works. It’s allowing me to write one module that contains all of the logic to create a randomly generated NPC. There’s no fluff, or crust. I have a specification for it that outlines the commands and their syntax, and any time I run into something I hadn’t yet accounted for I can just update my spec, write the logic for my parser and move on. The nice thing is, once I can embed commands like this, the logic does become pretty generic, and so there are only a handful of specific carve-outs in the code. I’ve posted the specification (as of this writing) in the project section of the site here.

The Other Big Pieces

So, all in all things are looking up. I’ve figured out how to make things generic and am closing in on getting this damned thing up and running so we can hook a front end to it and open our doors for business. But there are a few pieces left I haven’t really turned to yet, chiefly animal companions and inventory. I don’t anticipate either of those things being too demanding, but who knows what nightmare awaits me once I dig in. Just now I remembered that Summoners get companions that work completely differently to what’s in the core rules, so I’m sure that’s going to be a blast when I add in the Advanced Player’s Guide. Bringing the content of that book in will also mean adding in archetypes, but I’ve made provisions for those already, and don’t anticipate that being too painful. Fortunately, adding that book in is a task for post launch. Minimum viable product and all that!

What Else is Going On

If that’s all I’d gotten done in the past month, I would be pretty disappointed, but thankfully it isn’t. I’ve put together a development kit that will let me prototype some electronics projects and I’ve started doing the education work to learn game development. For now all I’ll say is that my embedded development is going to involve ST Micro’s ARM microcontrollers and Visual Studio and game development is going to start out with the Godot engine. I’m sure I’ll find time to talk about some of this stuff in the days ahead.

If you made it this far, then thanks for reading.

 

Leave a Reply

Your email address will not be published.