PDA

View Full Version : I am bad at Regex, trying to deal with "auto" roll name [MoreCore/REGEX]



Varsuuk
January 5th, 2021, 04:37
I HAVE looked at
https://www.lua.org/pil/20.2.html
https://lua-users.org/wiki/PatternsTutorial
https://www.lua.org/manual/5.3/manual.html#6.4.1

and I still *bleep* at anything beyond trivial.

I'd like to have this:
/swthac0
/swthac0 [ranged]
/swthac0 [ranged,magic]

I could not get ANYWHERE with [], so even (ranged,magic) would be OK - but really I JUST wanted what was INSIDE of them - so I switched to doing:
/swthac0 ranged,magic


In MoreCore, the cliroller thing has "Melee Attack" in top title and "/swthac0 ranged,magic" in Dice String

I hoped I could apply a regex to the incoming: "ranged,magic Melee Attack"

Where it would result in:
sAttributes = "ranged,magic"
sRollName = "Melee Attack"

The original start point to grab ostensibly the disc-string along with the AUTOMATICALLY appended to the disc string by the MoreCore caller of performAction() was:
local _, _, sAttributeParam, sRollName = string.find(sParams, "([^%s]+)%s*(.*)");

My skills fail when corner cases are looked at.
Passing: /swthac0 ranged,magic -> works
Passing: /swthac0 ranged -> works
Passing: /swthac0 -> Results in:
sAttributes = "Melee"
sRollName = "Attack"


I played around with using (%b[]) and (%b()) and while the latter (no love with []) matched, it of course returns the "(" and ")" as part of it too.
I have read that cannot make patterns optional so I realize why other things I tried failed.

How would I approach this?
The above split of Melee and Attack happens even in the default /thac0 handler because it later tries to see if it has an actual roll string (required in normal /thac0 like "1d20x19") and if it does not, it doesn't interpret the first argument - just concatenates them together. So it "works" :)

In my case, it would try to treat the first melee as an attrib.

There some ways I can theoretically imagine:

1) Require a () around the attributes, like "%(([^%s]+)%)" [Haven't tested that, would PREFER to use "[]" if I HAD to use a grouper.] then look for that first, if find it, continue from where leaves off to read the rest like "%s*(.*)" --- so 1 to 2 different finds.
2) Require the user to name rolls with a grouping delim (again can't use [] so far so would be "(Melee Attack)"). -- but this smells to HIGH HEAVEN!
3) Require a damn terminator whether or not there is anything to separate :( like:
/swthac0 |
/swthac0 ranged|
/swthac0 ranged,magic|

I will try #3 first as a starting point that looks like I might have success - I man posting already even before know if can get #3 to do what need because I am so bad at this, if I waited until knew if that was an option I might not post in time tonight to get feedback.



Assuming bracketing with [] is a pain, I would enter:

/swathac0
/swthac0 ranged
/swthac0 ranged,melee

and this regex would give me

"", "Melee Attack" or "Melee Attack", ""
"ranged" "Melee Attack"
"ranged,melee" "Melee Attack"

in the 2 results.

Varsuuk
January 5th, 2021, 05:29
OK - tested my "working solution", using a "terminator" for every /swthac0 string :(

Passing in, "/swthac0 xxx,ranged,magic| "
results in the attached file appearance. Which lets me continue. Still, I'd love to figure out HOW to pull out either one or two captures based on my with or without attires string.


Mind you, if anyone reads this - PLEASE point out any bad coding or Lua-isms used here since I will likely need to use this version unless someone shows me another way.




function createRoll(sParams)
Debug.console("== SW) createRoll")
local rRoll = {}
rRoll.sType = sCmd
rRoll.nMod = 0
rRoll.aDice = {"d20"} -- StringManager.convertStringToDice("1d20")

local aArgs = StringManager.split(sParams, "|", true)
local nArgs = #aArgs

if nArgs == 1 then
-- There were no attributes supplied.
-- The array entry represents the name of the roll.
rRoll.aAttributes = {}
rRoll.sDesc = aArgs[1]
elseif nArgs == 2 then
-- There were attributes supplied. There can be more than one comma-separated entry.
local sAttribArg = StringManager.trim(aArgs[1]:lower())
rRoll.aAttributes = StringManager.split(sAttribArg, ",", true)

local nNumAttribs = #rRoll.aAttributes

rRoll.sDesc = aArgs[2] .. " ["
for i, v in ipairs(rRoll.aAttributes) do
if i > 1 then
rRoll.sDesc = rRoll.sDesc .. "," .. v
else
rRoll.sDesc = rRoll.sDesc .. v
end
end
rRoll.sDesc = rRoll.sDesc .. "]"
else
rRoll.sDesc = "Parameters not in correct format. Should be in the format of \"optional-comma-separated-list-of-attributes|\" with EXACTLY one '|' terminator."
return rRoll
end


Debug.console("SW) rRoll.sDesc: ", rRoll.sDesc);

return rRoll;
end

damned
January 5th, 2021, 09:19
Hi Varsuuk

Firstly why do you care if its ranged or magic or melee for a thac0 roll?
Does the thac0 change if its magic?

Second - i believe that roll first splits things based on a space
everything before the space and everything after the space
I would probably brute force it
after the default split that gives you the dice string (now with extras) and the description
then start chopping the dicestring up
again the way that *I* would go is
there is only a finite number of possible strings and string combinations
something like
melee
melee,magic
ranged
ranged,magic
thrown
thrown,magic
and maybe
magic,melee
magic,ranged
magic,thrown
and then id deal with each of those cases...

Im not good at being efficient.

Varsuuk
January 5th, 2021, 20:58
The code I pasted above does the initial separation of "stuff" after the "/swthac0" and before the terminating "|" vs the MC-supplied "roll entry name"

After that initial split, it takes the pre "|" string and breaks it up on "," into a list of "attributes".

The intent on the attributes is that for any given part of the roll, it may affect the roll. For ToHit, there is only one "Official" modifier: Dexterity. If the attacker has Dex 13+, the attacker gets a +1. So, the roll, if it represents a missile attack, may look like "/swthac0 ranged|"

Later revisions, I will add the support for optional rules like: Fighters (and only fighters) get +1 to-hit/damage if Dex 13+.

The reason for my use of "magic" etc in the examples was just to get the mechanism down. Right now, the only thing is "ranged" - BUT, later I intended to add something like "magic" to a magic weapon's roll attack because when tohit or damage against a target comes into play - those may prevent or mitigate a hit or damage.