Things we did not build: Prerequisite Expressions

All posts, RSS Feed

For a while now, we have been wanting to write a series of blog posts on the things we did not build.

What you do not build is as telling as what you did build. And the reason something is not build often illuminates the process behind the building. A lot of this has to do with the trade-offs between complexity and customization — which we wrote about earlier in The Eternal Battle and How Much?

In this blog post I want to highlight the concept of “Prerequisite Expressions”, which are a thing we did not build.

Trees and Expressions

Feats, in Pathfinder, have prerequisites that state when the feat can be picked by a player of character. For example the Power Attack feat can only be picked if the character has ‘Str 13, base attack bonus +1’. This prerequisites indicates that to pick Power Attack — and this will sound rather obvious — the character must have both Strength 13, and a base attack bonus of +1 or higher. I will add an image of this here, for comparison later on:

Power Attack

This diagram depicts what computer scientists call a “Tree”. A tree is read from top to bottom, starting with the “root” — a tree is an abstract data structure so computer scientists and programmers are happy to declare the top-most part of the tree the root without any regard for how trees grow in the real world.

To make it easier to talk about the tree we will make a distinction between the circles and the boxes in the diagram. The official terminology sticks with the upside-down tree metaphor so we’ll do the same: we will call the circles “branch nodes” or “branches”, and the boxes “leaf nodes” or “leaves”.

We expressed the prerequisites of power attack as a tree: the root of the tree, which is a branch node itself, links to the two prerequisites, indicating that both must be satisfied before Power Attack can be picked. The leaf nodes, which are the two prerequisites themselves, are satisfied if what they test is true for the character: Str 13 test if the character’s Strength is 13 or better, and bab +1 tests if the character’s base attack bonus is +1 or higher.

If we write the tree in text, we get the prerequisite expression for Power Attack:

Power Attack = [ Str 13, bab +1 ]

The [ and ] indicate that we have a branch, and the nodes linked to the branch are written in between them.

Complex Prerequisites

Some feats, such as Improvised Weapon Mastery have prerequisites that are more involved: ‘Catch Off-Guard or Throw Anything, base attack bonus +8’. The increased complexity of this prerequisite is best expressed in an image again:

Improvised Weapon Mastery

The prerequisite tree of Improvised Weapon mastery contains two branch nodes that have a different meaning. From here on we will have to label the branch nodes to indicate the difference.

The prerequisite expression for this tree is:

Improvised Weapon Mastery = All [
    bab +8,
    Any [
        Catch Off-Guard,
        Throw Anything

As can be read from the prerequisite expression: to qualify for the feat, a character must satisfy All checks directly under the root: they must have both bab +8, and have Any of Catch Off-Guard or Throw Anything.

And there are feats such as Critical Mastery, which have prerequisites that allow for even more freedom when attempting to satisfy them: ‘Critical Focus, Any two critical feats, 14th-level Fighter’. Once again, this is interesting to see as an image:

Critical Mastery

Note that both branch nodes require All. For us, not being computers, it is still really simple to check if a character qualifies. To qualify for the Critical Mastery feat, a character needs to have Critical Focus, be a 14th-level Fighter, and have two other critical feats.

The prerequisite expression for Critical Mastery is:

Critical Mastery = All [
    Critical Focus,
    14th-level Fighter,
    All [
        Any critical feat,
        Any critical feat

(Of course, the second All branch does not need to be a branch. An expression of the form All [ a, b, ALL [ c, d ] ] is equal to All [ a, b, c, d ]. But we’ll leave it like this because this way it closer matches the prerequisite as written in the core rulebook.)

Why we did not build Prerequisite Expressions

To see where the first complexity comes from, lets have a look at Groknar. Groknar just levelled up to be a 16th-level Fighter. He has Critical Focus and Bleeding Critical. We hand Groknar and the prerequisite expression for Critical Mastery to a computer and ask “Does Groknar satisfy the prerequisite expression?” The computer takes almost no time to decide, and answers: “Yes, he does.”

To understand how the computer reaches this conclusion, let us do as the computer does:

  1. Check if Groknar has Critical Focus.
    He does.
  2. Check if Groknar is a 14th-level (or higher) Fighter.
    He is: 16 ≥ 14.
  3. Check if Groknar has any critical feat.
    He does: Bleeding Critical.
  4. Check if Groknar has any critical feat.
    He does: Bleeding Critical.
  5. With all prerequisites satisfied, we conclude that Groknar does indeed satisfy the prerequisite expression.

The issue here is that we understand ‘Any two critical feats’ as meaning ‘Any two different critical feats’. But this is not what we told the computer to check. We told it to test two times for Any critical feat… Which it did, and both times it found one.

So, we have to ask it to find two different critical feats. We could, for example, do something like this:

All [
    Any critical feat = A,
    Any critical feat = B,
    A ≠ B

Here, we want to find two critical feats, A and B, and make sure that once we find them that they are not the same. This is still perfectly doable. ‘Any three metamagic feats’ is slightly more complex, because none of the three feats may be the same, but still doable. But when we get to more complicated prerequisites such as ‘Any three metamagic or item creation feats’, we start running into the interesting problems because some feats might be both Metamagic and Item Creation.

And there are whole categories of other problems we would need to fix when we get to feats like Greater Weapon Specialization with ‘Proficiency with selected weapon, Greater Weapon Focus with selected weapon, Weapon Focus with selected weapon, Weapon Specialization with selected weapon, 12th-level fighter.’ Because now it no longer is just about finding the right feat, but finding the right set of feats that matches the selected weapon.

As described in our previous post How much?, part of the problem is that need RPGpad to be able to handle every possible prerequisite — within reason, there is simply no way to handle ‘Must have had contact with a powerful outsider’ — and that means that we need RPGpad to generically handle ‘Any two (somethings)’ and ‘Feat A with choice X, Feat B with the same choice X’. To do that, we would need to implement Unification.

To me, these are very interesting problems to solve. But they also come with a lot of complexity. Enough that we cannot even begin to imagine what the configuration interface for such prerequisites would look like. And while the solution to the problem would undoubtedly by awesome to build, it is also unnecessary for 80% of the feats.

So, we opted instead to only support a smaller subset of every possible prerequisite. This means that we can automatically check 80% of feat prerequisites. And we have added an “escape hatch” in the form of the Manual Prerequisites, which adds a “Please check” note to the quick sheet checks.

The exact prerequisites we implemented along with this week’s other changes can, as always, be found in the changelog! If you have any questions, feedback, or ideas do let us know in the community forum.