Separating numbers and letters in a string.

Discuss macro implementations, ask for macro help (to share your creations, see User Creations, probably either Campaign Frameworks or Drop-in Resources).

Moderators: dorpond, trevor, Azhrei, giliath, jay, Mr.Ice

Post Reply
User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Separating numbers and letters in a string.

Post by Xaelvaen »

I'm looking for a way to extract information from a single string. In example, if I wanted to take 1d8 and extract the information (1 dice roll, with 8 combinations), how would I go about this? I found 'endsWith' and 'startsWith' for simple things (1d8), but I have no idea where to look for more complex things, such as 10d8 and 8d10, since ends/starts only gets one character, or so I assume.

Even a point into the right part of the wiki would be greatly appreciated - an example even moreso. Thanks in advance.
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

User avatar
aliasmask
RPTools Team
Posts: 9023
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Separating numbers and letters in a string.

Post by aliasmask »

There's a bunch of ways to do it. The best way is probably using regex, but if the format is xdy then you can use listGet.

Code: Select all

[H: dice = "10d6"]
[H: x = listGet(dice,0,"d")]
[H: y = listGet(dice,1,"d")]

User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Re: Separating numbers and letters in a string.

Post by Xaelvaen »

I've seen 'regex' thrown around the forums, but I have no clue what that is.

As far as listGet, that's a nifty trick - will it work for other things? In example, if I just wanted a simple string that said '5d6 Fire', would I need regex to separate entire words like that?
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

User avatar
aliasmask
RPTools Team
Posts: 9023
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Separating numbers and letters in a string.

Post by aliasmask »

This should probably go in to the wiki.

Code: Select all

<!--
   (?i) - case insensative
   (d+) - number of dice (not optional)
   d - dice expression separator, upper or lower case
   (d+) - die sides (not optional)
   Optional:
      space* - space before modifier
      ([+-]*d+)* - roll modifier
      space* - space after modifier
      (w+)* - single word for damage type
      
   Example Groups: "(3)d(6)(+2) (Fire)"
-->
[H: regex = "(?i)(\\d+)d(\\d+) *([+-]*\\d+)* *(\\w+)*"]
[H, while(1), code: {
   <!-- cancel input to break out of loop -->
   [H: abort(input("diceExp|3d6+2 Fire|Enter Dice Expression|TEXT"))]
   [H: id = strfind(diceExp,regex)]
   [H: valid = getFindCount(id)]
   [H, if(valid), code: {
      [H: numDice = getGroup(id,1,1)]
      [H: numSides = getGroup(id,1,2)]
      [H: dieMod = getGroup(id,1,3)]
      [H: dmgType = getGroup(id,1,4)]
      
      [H: output = strformat("Original: %{diceExp}<br>Dice Expression: %{numDice}d%{numSides}")]
      [H, if(! json.isEmpty(dieMod)): output = json.append(output,strformat("Modifier: %{dieMod}"))]
      [H, if(! json.isEmpty(dmgType)): output = json.append(output,strformat("Damage Type: %{dmgType}"))]
   };{
      [H: output = strformat("Invalid Dice Expression: [%{diceExp}]")]
   }]
   [H: broadcast(json.toList(output,"<br>"))]
}] 
Example Output:

Code: Select all

Original: 3d6+2 Fire 
Dice Expression: 3d6 
Modifier: 2 
Damage Type: Fire
Also, check out this post for more regex info: http://forums.rptools.net/viewtopic.php ... 46#p259546

amsave regex dice expression


User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Re: Separating numbers and letters in a string.

Post by Xaelvaen »

Thanks for the example, and the link - looks really complex (and honestly a bit fun), so will be poking around at it. For now, I'm just packing the data separately in a json, but I'd love to eventually be able to pull this off.

A question for your listGet example, Alias - can you use listContains() in a similar way, like to find out if the sent variable -is- a dice roll?

Example:

Code: Select all

[h: dice=macro.args]
[h: "<!------- Let's say the dice expression received is 1d8 ---->"]

[h: isDiceExpression=listContains(dice,"d")]
Would that be able to pick up the d in the expression like your example above does? I've been looking for a way to have my attack information be variable; you can enter whole numbers (like averaged numbers in 5E), or the dice expression if you'd just rather roll it, so being able to determine if the information sent was dice would be helpful.

Even then, would it be better off to just do the opposite? Use isNumber() to see if it is -not- a dice expression?
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

User avatar
aliasmask
RPTools Team
Posts: 9023
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Separating numbers and letters in a string.

Post by aliasmask »

Here's a snippet of what I use in the 3.5/PF framework.

Code: Select all

<!-- Base Weapon Damage -->
[H, if(isNumber(Damage)), code: {
   [H: Damage.value = max(1,Damage)]
   [H: damageTipOutput = json.set(damageTipOutput,"Base Damage",Damage)]
};{
   [H: Damage.value = max(1,eval(Damage))]
   [H: damageTipOutput = json.set(damageTipOutput,"Base Damage",strformat("%{Damage} = %{Damage.value}"))]
}]  
The eval will ignore any text after a dice expression and return the rolled value.

User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Re: Separating numbers and letters in a string.

Post by Xaelvaen »

That's exactly what I was thinking, using the 'else' from isNumber(). Thanks for that info. Final question on the theme of this thread then, if you don't mind - is there a way to get the average of a dice expression, instead of rolling it? In example, 2d6 is 7. I was considering using your listGet() as follows:

Code: Select all

[h: dice="2d6"]
[h: x=listGet(dice,0,"d")]
[h: y=listGet(dice,1,"d")]
[h: avDice=add(floor(y/2),0.5)]

[h: total=floor(x*avDice)]
Not sure if there's an easier way or not, but that's what I came up with.
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

User avatar
aliasmask
RPTools Team
Posts: 9023
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Separating numbers and letters in a string.

Post by aliasmask »

floor(y/2*x) is what I would do

User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Re: Separating numbers and letters in a string.

Post by Xaelvaen »

That's smart - for some reason I just expected the floor to round where it wouldn't - I overcomplicate everything :P Haha, thanks again Alias =)
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

Post Reply

Return to “Macros”