asacolips-projects / 13th-age

13th Age system for Foundry VTT
5 stars 2 forks source link

Proposal to change how triggers are implemented #119

Closed asacolips closed 7 months ago

asacolips commented 3 years ago

In GitLab by @luizbgomide on May 20, 2021, 13:16

Summary

Today we have a system that tries to parse words and numbers to detect triggers on the card rolls and highlight them for the user.

Since this is a simple detection of words like: even, odd, hit, miss and patterns like [number] or [number]+, it can fail when parsing: Natural 16+ if escalation die is 3+; otherwise natural 20. There is no way for the system to guess which number to use.

There is also the issue with word detection that doesn't work on translated text. Even if we managed to add support for other languages, those are still prone to error since simple words like even/odd are translated as par/impar in Spanish and Portuguese, which could be misinterpreted. Finally, even if we manage to detect text in translations, we would be limited to a single language (unless the logic gets a lot more complex), if we are running Toolkit113 in Spanish it wouldn't detect triggers written in English (and vice versa).

Natural language processing is very hard!!!

Proposal

Allow trigger tags to be added to the named hits (hit1, hit2, hit3, hit4, hit5) in the Action Template and the Trigger property from the Power Template. Those tags would be surronded by { }, like the following examples (all taken from system):

Natural 16+ if the escalation die is 3+; otherwise natural 20.{16+ ed3+|20}

Natural 5, 10, 15, or 20.{5,10,15,20}

Natural even hit{even hit}

List of flags and operators

Expression

The expression is a comma , separated list of following possible sub-expressions:

If any of the sub-expressions are validated the expression is considered true.

Changes in the current system

There are 3 major changes needed to be implemented in the following order:

How the flags could be processed in the card

  1. Get the list of flags from the HTML attribute
  2. Split the list by |, each of the substrings is a possible trigger and only fully matching one of them is needed.
  3. For each substring split the triggers by (space)
  4. Pop all triggers in the format (even|odd|\d+(-\d+)?) and use them to build a list of possible d20 values.
  5. Check if the d20 matches on the of the possible values, and then check every remaining trigger and they all must be true for the trigger to be considered valid. The ?? is always true, but if present the substring is at most a partial trigger.
  6. If on substrings produces a full trigger the processes is finished, if not and there is a partial trigger then it can be used (the highlight can be in a different color) and finally if no full or partial trigger is found no highlight is added.

Advantages

Since the syntax has a fixed list of keywords, in English this is very close to natural language, and for usage in other languages this is still very easy to use due to small number of keywords needed to construct complex triggers. By comparison it is much simpler than generating dice rolls in Foundry.

For translators it is just a matter of not touching the text between { } and eveything just works.

A dialog could be added to help construct triggers trying to recognize the words used in the trigger natural text to suggest what might be needed, but this is very close to natural language in english as the examples belows demonstrated.

Examples:

This is an example of a somewhat complex triggers that gets a bit more verbose:

The following are "problematic", but could be "fixed" in the future with more flags for conditions and maybe an operator to apply the flag to target (like > or something else), so staggered would trigger when the attacker staggered, and >staggered when the target is. But a partial trigger can be identified for all of them.

Note, natural language processing is so hard that the last trigger could be interpreted in 3 different ways...

asacolips commented 3 years ago

In GitLab by @luizbgomide on May 20, 2021, 17:47

Code in repository https://gitlab.com/luizbgomide/archmage

asacolips commented 3 years ago

In GitLab by @LegoFed3 on May 22, 2021, 04:53

If I undestand this right, the proposal is to eventually completely replace the current natural text processing with manually added tags. That is... annoying, since as a GM I'm hapy to have a bit of automation but frankly can't be bothered to manually code stuff that I can more quickly parse mentally those three times it comes up. I can see how this can be of interest to someone (you, for instance), but I'd recommend to leave the current natural text parsing in place, and before applying one or the other check for the presence of tags (i.e., stuff between {}). That way we can use the appropriate one without removing functionality for lazy GMs like me.

asacolips commented 3 years ago

In GitLab by @luizbgomide on May 22, 2021, 06:32

You mean existent functionality? My idea is to only replace the system once it does everything the current system does for all creatures and powers.

After the new system is implemented for English users it would be a matter of adding the criteria in pretty much natural language between brackets, since the keywords are English based and the shorthand are identical to what is used, and it can even be placed separated by triggers (also it can be at front, back, or in the middle of the text): Natural 16+{16+}; if you fight with a shield, also any natural even roll{shield even}.

In regards to keeping the natural system in place, my recommendation is that after someone fills text for action.hit[1-5].name and power.trigger (the only two custom trigger instances, the rest is all automatic) in the item settings and haven't filled up a trigger yet, detect which trigger he meant to use (now we can use translated natural language parsing) and show a popup (or something like it): "Do you to want detect "even hits" with that trigger?" And then the user can just confirm it. Since we would be dealing with a single line and can show a dialog asking for user confirmation, we can even construct multiple possible triggers and ask him what is the one he meant to use.

Yesterday I began tinkering with the system, so far I have the trigger processing complete, the trigger identification in the preprocessing of the chat card also complete (and I'm cleaning up a bit of code in that preprocessing that rely on hardcoded strings to work by default). After that the only remaining tasks are: adjusting the templates to hide the trigger text and adding the trigger information (I've already made two handlebar helpers that does just that), and go through the monsters srd hit1, hit2, hit3 to add trigger information and through the powers.trigger and all be ready for deployment. I think I can finish that by the end of the next week.