Open Stendarpaval opened 3 years ago
I'll try to get to this sometime, but I really can't promise anything. I'm a programmer, but also a new(ish) father and barely have time to play D&D with my wife and friends, let alone code in my spare time. :( However, I can suggest an alternate approach you could use if I can't get to it. Can't promise it'll work better, but it's what I'd try first. Here's some dirty psuedocode:
function parseMultiattack(actor)
if actor does not have multiattack then return
multiattack_items = []
for each of the actor's items, item
if actor.multiattack.text.lowercase() contains item.name.lowercase()
num = parseMultiattackForItem(actor.multiattack, item)
if num === undefined
num = 1 // To cover cases like "The dragon can use it's Frightful Presence"
if num > 0:
multiattack_items.append({num, item})
if multiattack_items is empty: // couldn't find specific matches for any of the actor's items
// use a regex to look for matches of "makes <num> <melee|ranged> attacks", like the Eryinyes and Lizardfolk entries.
// Then just add one match for every attack item that the actor has, filtering on the "melee|ranged" group if it was found.
function parseMultiattackForItem(ma, item)
itemName = item.name.lowercase()
// This extracts any number that appears between one and three words before the itemName.
// This matches strings like "one with its bite" or "two with its claws"
// Note using "a" and "an" as aliases for 1 should catch the Veteran's "a shortsword attack".
regex = new Regex("(an?|one|two|three|...)\W+(?:\w+\W+){0,2}?" + itemName)
if regex.match(ma.text.lowercase())
return stringToNum[regex.group(1)]
How well it works will really depend on how consistent the multiattack text is with using the exact name of the features it uses. You might need to also search for optional pluralizations or whatever.
For the Bandit Captain, you might want to split the string on ". Or" before running each section through the algorithm, and then you could show each section with an line between them or something. I'm not a UX guy. :P
What's wrong with the Erinyes entry, by the way? It just says she makes three attacks, presumably with any weapon, right?
Oh, if you're new to regex, here's what I used to mock out my example: regexr.com/5vv4k - just change the item name in the expression at the top (the last word) to try it with different items. Then mouse over the highlighted matches to see that group 1 equals the number part of the match.
Hey! I'm happy to have someone help me out with this, even if it's just brainstorming. Thanks for already taking a look! Edit: almost forgot, congratz on becoming a father! I totally understand that you don't have as much time to code. My available coding time is also reduced due to resuming DM duties as well as school projects. (Which is why this message is pretty long, because just like code it takes more time to write a compact message.)
I'm going to step through your pseudocode and give my thoughts on your input. You can read that below, but it's mostly a stream of my consciousness rather than an in-depth review.
So it's great that you suggest to use regex, since you're likely more knowledgeable about them than I am! That RegExr website is a great tool, btw, which I'll look into deeper.
How well it works will really depend on how consistent the multiattack text is with using the exact name of the features it uses.
Unfortunately, there is not perfect consistency between names that the multiattack text uses for weapons, spells, and features and the names that the actual weapon, spell, and feature names on actor and NPC sheets. The lycanthropes are an example of this mismatch, because the item names are appended with usage limitations.
You might need to also search for optional pluralizations or whatever.
Thankfully the English language is fairly simple when it comes to plural versions of nouns: just add an s (most of the time). The current implementation accounts for that.
For the Bandit Captain, you might want to split the string on ". Or" before running each section through the algorithm, and then you could show each section with an line between them or something. I'm not a UX guy. :P
Good that you bring up the question of how to display different multiattack options. One reason I decided to add Multiattack descriptions inside Mob Attack Tool was as a stopgap measure to allow users to know what the alternative option is, if any. For the Bandit Captain, stopping the analysis at ". Or" would work, but there are other creatures (like the Tarrasque) that only discuss some weapon options after starting a new phrase that includes "instead of", or "in place of" (like the Wight). These will cause similar issues.
For now I think it's fine if the first described multiattack option (let's call that the "default" multiattack option) is selected correctly. That brings me to your next sentence:
What's wrong with the Erinyes entry, by the way? It just says she makes three attacks, presumably with any weapon, right?
The Erinyes makes three attacks, so if she used a single weapon type than than the number to the left of the weapon icon should be 3. I suspect that all her weapon options have "1" as the number of attacks, because the current implementation will set them to "1" if the number of weapons in their inventory matches the number of attacks they get with their multiattack ability. Specifically, this probably only happens if the multiattack only says how many attacks they can make in general, without being more specific. The "correct" way should have been to have the strongest weapon used 3 times, or to check all the checkboxes on the right to ensure that 3 attacks are made.
Interestingly enough, the Lizardfolk has the opposite problem. :)
Once again, thanks for looking into this! I'm definitely interested in using regex to solve this. I'd enjoy it if you could provide more tips or examples on how to use them for this.
One of Mob Attack Tool's features is to automatically interpret how the multiattack ability works of monsters. I wrote an algorithm to accomplish this, which you can find in multiattack.js.
The algorithm currently doesn't always parse the correct number of weapons, or it selects only some of the weapons that are part of the multiattack. In some cases it even selects the wrong weapons. This is currently the case for lycanthrope monsters (so werewolves, wererats, werebears, wereboars and weretigers), veteran, bandit captain, the erinyes, and so on.
There are 142 monsters in the SRD with the multiattack ability and I have not systematically checked which ones the algorithm works for and for which ones it doesn't. I suspect there to be at least a dozen, possibly several dozen multiattack descriptions that the algorithm interprets incorrectly. You might wonder why I don't just add a big table of monsters and check by name. The reason is that many DMs change or make their own monsters, and I want Mob Attack Tool to correctly interpret the multiattack descriptions in these cases too.
To state the goal clearly: I would like to improve the accuracy of the algorithm, especially for monsters with a lower Challenge Rating (CR). I welcome pull requests that make the algorithm interpret more multiattack descriptions correctly, without it becoming worse at interpreting the descriptions it currently is good at interpreting. (Edit: Please note that it doesn't need to be perfect. I'm already really happy if 2 or 3 of the "Bad" examples from the examples below are interpreted correctly.)
I don't have specific style guides to follow, since I barely know of their existence. I'm not a professional programmer, after all. As long as I can generally interpret what your code is doing, I'll be more than content. In fact, I'll probably learn more from you than the other way around!
Examples
Click on the expandable section below to see some examples. In the "Good" examples, the algorithm worked as intended. In the "Bad" examples, the algorithm got something wrong.
Table of examples
Multiattack description data
The "training data" I used to design the current algorithm is based on the multiattack descriptions of all the monsters in Systems Reference Document (SRD) of D&D5e. The dnd5e system for Foundry VTT contains a compendium of these monsters.
You can specifically extract these descriptions using this macro in a Foundry VTT game world that uses the dnd5e system:
The macro above creates a new item called "Multiattack data". Right-click the item and select "Export Data" to obtain a JSON file. You'll find the multiattack descriptions in that JSON file.
For the sake of convenience, I'll also add a txt-file with the descriptions: dnd5eSRDmultiattackDescriptions.txt