Dice Pool Assignment and Total Assistance

Hey all, new poster. I'm a very intelligent computer user with a broad knowledge base but I am not a programmer.

I need assistance with a random NPC generator that I'm trying to get to work. I'm starting with a human and the racial mins/maxs to get the algorithm correct. After that, I'll adjust for different races.

I have a points pool of 54. Racial minimums will use 6 points over six attributes, for a total of 36. This leaves 18. All 36 + 18 must be used.

I want to take that remaining 18 and randomly assign from 0-6 points across the six attributes while counting down from the 18. I must use all 18 points. I understand a 1d7-1 roll for the random 0-6. I have a code to count down from 18 that I'll post below.

My problems are that it doesn't stop counting at 0, and for some reason, on occasion, I get a total of 55 points and/or a dice code below the racial minimum of 6.
Set: att1 = 18
set: att1a = {1d7 - 1}
set: att1b = {!{$att1} - {$att1a}}

set: att2a = {1d7 - 1}
set: att2b = {!{$att1b} - {$att2a}}

set: att3a = [when] {$att2b} > 6 [do] {1d7 - 1} [else] {1d{$att2b}} [end]
set: att3b = {!{$att2b} - {$att3a}}

set: att4a = [when] {$att3b} > 6 [do] {1d7 - 1} [else] {1d{$att3b}} [end]
set: att4b = {!{$att3b} - {$att4a}}

set: att5a = [when] {$att4b} > 6 [do] {1d7 - 1} [else] {1d{$att4b}} [end]
set: att5b = {!{$att4b} - {$att5a}}

set: att6a = [when] {$att5b} > 0 [do] {$att5b} [else] 0 [end]

Set: Str = {6 + {$att1a}}
Set: Kno = {6 + {$att2a}}
Set: Mec = {6 + {$att3a}}
Set: Per = {6 + {$att4a}}
Set: Dex = {6 + {$att5a}}
Set: Tec = {6 + {$att6a}}

# The following is just so I could total up the point usage and see it at a glance during my trials and errors.

Set: att2 = {!{$att1} - {$att1a}}
Set: att3 = {!{$att2} - {$att2a}}
Set: att4 = {!{$att3} - {$att3a}}
Set: att5 = {!{$att4} - {$att4a}}
Set: att6 = {!{$att5} - {$att5a}}

I saw the post on hash tables located here, and am wondering if that's how I need to go...but again, not a programmer and not sure how to implement if so.

Comments

  • Hi Eddie, welcome to the forum!

    You've got some pretty impressive code there; I think mostly you're getting stymied by the peculiarities of IPP, particularly that 1d0 does not equal zero. For some reason, it always equals one (for what it's worth, I only just now discovered this). Worse, after the 1d0 = 1 happens, your next $attXb will be negative. And 1d-1 is taken as 1d6-1!

    I couldn't replicate the situation where one attribute was below minimum.

    There is one logical error in your code. In the event that the first five rolls were low, $att6a -- which gets the final remainder -- could be quite a bit higher than than 6.

    All that said, I've found that when doing semi-complex stuff like this, the best thing to do is to work the way IPP wants you to work, i.e. using tables. This code does what you're looking for:
    Set: Str = 6
    Set: Kno = 6
    Set: Mec = 6
    Set: Per = 6
    Set: Dex = 6
    Set: Tec = 6
    
    table: Start
    [@18 IncrementAStat]&
    [@ShowStats&;#93;
    
    table: IncrementAStat
    {Str=={{Str}+1}}
    {Kno=={{Kno}+1}}
    {Mec=={{Mec}+1}}
    {Per=={{Per}+1}}
    {Dex=={{Dex}+1}}
    {Tec=={{Tec}+1}}
    
    
    table: ShowStats
    Str {Str}\n&
    Kno {Kno}\n&
    Mec {Mec}\n&
    Per {Per}\n&
    Dex {Dex}\n&
    Tec {Tec}\n&
    \n&
    Sum {{Str}+{Kno}+{Mec}+{Per}+{Dex}+{Tec}}
    
    Hope that helps!
  • Thanks, largando!

    My logic error wasn't the remainder on that final variable, I knew I didn't have a way to cap it. My logic error was that I thought I would be able to come up with an answer on my own! :D

    My problem is that I don't know what IPP can and can't really do, yet. I've had it for a few years, messed around with it pretty heavily for about six months (and got fair at using it), then life interrupted all of my gaming/hobby activities and I stepped away. Now that life has stabilized, I'm getting back into gaming and the prep work for it. So I'm having to relearn to the point I was at, and with any luck exceed it this time around. The help file is decent for doing the basics, but sometimes I'm kind of clueless what it's trying to say so trial and error has been my main tutor.

    Again, thanks so much for the code!
  • In fact, would you mind talking me through the code so I can verify I understand what is going on?
    Set: Str = 6
    Set: Kno = 6
    Set: Mec = 6
    Set: Per = 6
    Set: Dex = 6
    Set: Tec = 6
    

    This I understand. It sets my initial variables at 6.If I need to adjust for different racial mins/maxs I start with this and then modify the 18 below.
    table: Start
    [@18 IncrementAStat]&
    [@ShowStats&;#93;
    
    table: IncrementAStat
    {Str=={{Str}+1}}
    {Kno=={{Kno}+1}}
    {Mec=={{Mec}+1}}
    {Per=={{Per}+1}}
    {Dex=={{Dex}+1}}
    {Tec=={{Tec}+1}}
    

    So the first table call out is for 18 times to increment a stat. They're random pulls and each one increments by 1 and doesn't display it (the ==), correct? It just does the internal math and holds it in place. What does the [@showstats] table call out do? And say I want a race that is typically smarter/stronger/technical/etc., I can weight the different items on the IncrementAStat table, right?

    What part of this stops the progression at 6 for an individual attribute? How does it cap it?

    And could you talk me through the actual syntax of {XXX=={{XXX}+1}}?

    1 --- {Str=={{Str}+1}} --- is saying create/change some variable and do something on the right of the == but just hold it in place and not display it. I understand that from the help file but what does the "not display it" really mean. I don't understand that concept fully. If you don't want to display it, you just don't show it in a different table like ShowStats below, right?
    2 --- {Str=={{Str}+1}} --- is the math expression or do something that is about to happen
    3 --- {Str=={{Str}+1}} --- is the variable or table or item that you're doing whatever it is to to get the overal result in line 1.

    Am I understanding that stuff correctly?
    table: ShowStats
    Str {Str}\n&
    Kno {Kno}\n&
    Mec {Mec}\n&
    Per {Per}\n&
    Dex {Dex}\n&
    Tec {Tec}\n&
    \n&
    Sum {{Str}+{Kno}+{Mec}+{Per}+{Dex}+{Tec}}
    

    I understand this part, this displays the final results and gives me my sum total so I can rapidly verify.

    One last observation, what happened to table: endtable:? I assume that it's what one of the other posts was talking about due to the IPP3 upgrade being more free with the language? So in this case, if there is a break in the rows the program assumes that the table is finished. That's why you put the \n& between Tec and Sum, right?
  • Eddie wrote:
    In fact, would you mind talking me through the code so I can verify I understand what is going on?
    No problem! It can get a little tricky.
    Eddie wrote:
    So the first table call out is for 18 times to increment a stat. They're random pulls and each one increments by 1 and doesn't display it (the ==), correct?
    Right on. A single "=" would display the new value of the variable.
    Eddie wrote:
    What does the [@showstats] table call out do?
    Just calls ShowStats, so I could verify that the code was working correctly.
    Eddie wrote:
    And say I want a race that is typically smarter/stronger/technical/etc., I can weight the different items on the IncrementAStat table, right?
    That would work, although setting up a different IncrementAStat table for each race sounds really tedious. I'll be happy to help you look for alternative methods if you want to familiarize me with the system you're using.
    Eddie wrote:
    What part of this stops the progression at 6 for an individual attribute? How does it cap it?
    Whoops! No part does; I completely forgot about that restriction. This code deals with that, although I suspect it will raise a few more questions:
    Set: Str = 6
    Set: Kno = 6
    Set: Mec = 6
    Set: Per = 6
    Set: Dex = 6
    Set: Tec = 6
    
    table: Start
    [@18 IncrementAStat]&
    [@ShowStats&;#93;
    
    table: GetStat
    Str
    Kno
    Mec
    Per
    Dex
    Tec
    
    table: IncrementAStat
    {stat=='[@GetStat&;#93;'}&
    [when]{{stat}}=12&
    [do]{stat=='[@GetStat&;#93;'}[@IncrementAStat&;#93;&
    [else]{{stat}=={{{stat}}+1}}&
    [end]
    
    
    table: ShowStats
    Str {Str}\n&
    Kno {Kno}\n&
    Mec {Mec}\n&
    Per {Per}\n&
    Dex {Dex}\n&
    Tec {Tec}\n&
    \n&
    Sum {{Str}+{Kno}+{Mec}+{Per}+{Dex}+{Tec}}
    
    Eddie wrote:
    1 --- {Str=={{Str}+1}} --- is saying create/change some variable and do something on the right of the == but just hold it in place and not display it. I understand that from the help file but what does the "not display it" really mean. I don't understand that concept fully. If you don't want to display it, you just don't show it in a different table like ShowStats below, right?
    2 --- {Str=={{Str}+1}} --- is the math expression or do something that is about to happen
    3 --- {Str=={{Str}+1}} --- is the variable or table or item that you're doing whatever it is to to get the overal result in line 1.

    Am I understanding that stuff correctly?
    Looks like you understand it perfectly!
    Eddie wrote:
    One last observation, what happened to table: endtable:? I assume that it's what one of the other posts was talking about due to the IPP3 upgrade being more free with the language? So in this case, if there is a break in the rows the program assumes that the table is finished. That's why you put the \n& between Tec and Sum, right?
    You got it! I very rarely use EndTable anymore; it's handy when the stuff following a table isn't another table, which happens in my files during the creation process, but in the final product I don't think I use it at all.
  • largando wrote:
    Whoops! No part does; I completely forgot about that restriction. This code deals with that, although I suspect it will raise a few more questions:

    I hate you. In a completely grateful, mind-blown way. I struggled for three days with that convoluted mess I initially posted.
    table: GetStat
    Str
    Kno
    Mec
    Per
    Dex
    Tec
    

    Okay, I see where this is getting used in the next table.
    table: IncrementAStat
    {stat=='[@GetStat&;#93;'}&
    [when]{{stat}}=12&
    [do]{stat=='[@GetStat&;#93;'}[@IncrementAStat&;#93;&
    [else]{{stat}=={{{stat}}+1}}&
    [end]
    

    Okay...I see the when/do/else/end...I understand that. Talk me through the rest, please.

    We're creating an inline variable of stat (which is starting as a constant of the set:) and assigning a table call for one of the attributes and at the same time applying a conditional with the & symbol, correct?

    It's checking if that inline variable already is equal to 12. If it is, then it's picking a different attribute from the GetStat table. Because of the earlier 18 calls of IncrementAStat, it's going to do this 18 times, giving me my total of 54 points spent.

    Okay, most important question I'm going to ask. Where is a document that tells me how to do all of these combinations and shortcuts?!
    largando wrote:
    Eddie wrote:
    1 --- {Str=={{Str}+1}} --- is saying create/change some variable and do something on the right of the == but just hold it in place and not display it. I understand that from the help file but what does the "not display it" really mean. I don't understand that concept fully. If you don't want to display it, you just don't show it in a different table like ShowStats below, right?
    2 --- {Str=={{Str}+1}} --- is the math expression or do something that is about to happen
    3 --- {Str=={{Str}+1}} --- is the variable or table or item that you're doing whatever it is to to get the overal result in line 1.

    Am I understanding that stuff correctly?
    Looks like you understand it perfectly!

    Okay, please explain the "not display" part of the function. I understand the English of what it means, but what does it mean in IPP-language? I'm lost.
  • edited March 2016
    Eddie wrote:
    Okay...I see the when/do/else/end...I understand that. Talk me through the rest, please.

    We're creating an inline variable of stat (which is starting as a constant of the set:) and assigning a table call for one of the attributes and at the same time applying a conditional with the & symbol, correct?

    It's checking if that inline variable already is equal to 12. If it is, then it's picking a different attribute from the GetStat table. Because of the earlier 18 calls of IncrementAStat, it's going to do this 18 times, giving me my total of 54 points spent.
    Initially I wasn't going to explain the code, because the above makes me think you understand it pretty well. Then I saw something worth clarifying and decided to write a simple explanation. Now I'm thinking, what the heck, I might as well break it down step-by-step so that casual readers can understand it too. So here goes:
    table: IncrementAStat
    {stat=='[@GetStat&;#93;'}&
    [when]{{stat}}=12&
    [do]{stat=='[@GetStat&;#93;'}[@IncrementAStat&;#93;&
    [else]{{stat}=={{{stat}}+1}}&
    [end]
    
    It may not be obvious at first blush, but IncrementAStat only has one selectable row in it. The "&"s let me break up that single row into several lines of text to improve readability.

    Looking at each line:
    {stat=='[@GetStat&;#93;'}
    
    • Assigns a value to the variable "stat". Note that I didn't need to declare "stat" before this point; with IPP I can create at the same time I assign it.
    • Is an instance of "inline variable assignment". That is, it assigns a value to a variable outside of the standard "Set:" syntax, and, more importantly, does so when a particular row of a table is selected.
    • The basic syntax of inline variable assignment (with extra spaces that really don't belong, for readability) is: { variable == 'value' }
      Many parts of this syntax are worth noting:
      • The curly braces, "{" and "}" tell IPP that inline variable assignment is happening. Confusingly, curly braces can also indicate other important things, such as "do some math", "roll dice", and "pull out the value from a variable" (also called "variable interpolation").
      • "variable" at one time had to begin with "$", a dollar sign. That is no longer the case, although if you like to use it you can.
      • "==" this is that part that actually assigns "value" to "variable". The double-equals means "don't display the resulting value", which is almost always what I want. If you do want to display the variable as you assign it, just use one equal sign.
      • The single quotes around "value". If "value" is not numeric, forgetting the single quotes will cause errors. If "value" is numeric, the single quotes are not needed, but it doesn't hurt to use them anyway.
      • "value" itself. This can be just a string, or a table result (as in the example code), or pretty much anything else that can be expressed as a long string.
    [when] condition [do] stuff [else] do other stuff [end]
    
    • This is just standard logic branching. IPP also uses "if", but I haven't found it to be reliable (although it's certainly possible that I'm just using it wrong).
    [when]{{stat}}=12
    
    • Remember above, when I said curly braces are confusingly overused? Here's an instance where it matters. Working from the inside out, we have:
      • stat. The variable assigned above.
      • Inner braces. These interpolate stat to bring out its value, so if earlier I assigned the value "Str" to stat, IPP now sees this:
        [when]{Str}=12&
      • Outer braces. These interpolate Str to bring out its value. Say for whatever reason I earlier assigned the value of 10 to Str. Now IPP sees this:
        [when]10=12&
    • So if stat is "Str", and Str is "10", then " [when]{{stat}}=12 " is false, meaning we'll go on to the "else" branch. If somehow {{stat}} did equal 12 (either because Str had a value of 12, or because stat had a different value (say, Kno) and that value was a variable with a value of 12) the we'd go on to the "do" branch.
    [else]{{stat}=={{{stat}}+1}}&
    
    (Note that I'm skipping the "do" branch for a second, because the "else" is far more likely to occur)
    • Here curly braces have taken on a life of their own. Let's break down {{stat}=={{{stat}}+1}}.
      • First, interpolate all cases of {stat}. If stat were "Str", then IPP would see this line as
        {Str=={{Str}+1}}
      • Now the innermost curly braces are {Str}. If the value of variable Str were 10, we now have
        {Str=={10+1}}
      • The new innermost curly braces are of the "do some math" variety. Since 10+1 = 11, we have
        {Str==11}
        ... which is just standard inline variable assignment.
    • So it all comes down to, "whichever attribute stat indicates (Str, Kno, Tec or whatever), increment it by 1".
    EDIT
    Well I'll be! Within just hours of writing this, I reread the documentation and learned that I'm seriously over-bracing. Color-coding the line of code {{stat}=={{{stat}}+1}}:
    • I can get rid of {} because when doing inline variable assignment, IPP will automatically look for and interpolate variables when evaluating formulas.
    • I can get rid of {}, my "do some math" braces, because the possibility of doing math is assumed on the right side of an inline variable assignment, so long as the value isn't in single quotes.
    • That leaves me with the embarrassingly simple {{stat}=={stat}+1} which probably didn't need explaining at all. Oh well.
    [do]{stat=='[@GetStat&;#93;'}[@IncrementAStat&;#93;&
    
    • This is what we do in the event that " [when]{{stat}}=12 " is true. In it, two different commands are performed.
      First is {stat=='[@GetStat]'}, which is identical to the first line of IncrementAStat.
      Next comes [@IncrementAStat], which just says "call IncrementAStat again".
    • What's going on here:
      • The requirements of this character-creation system are, for now, "no stat can go above 12".
      • So, if, say, Str is equal to 12, we don't what to bump it up to 13 (which is what the "else" branch would do). Instead find a new stat, and use it for a new call to IncrementAStat.
      • As you may have noticed, this means that, theoretically, this could loop infinitely, if the value of Str was 12 and we keep choosing "Str" as the new stat. I haven't found a good way to deal with that in IPP, so I let probability work for me.

        (an aside on probability) If Str were 12, and IPP chose "Str" as the stat 10 times, the loop would still complete faster than humans can notice. And the chance of IPP choosing the same 1 out of 6 stats 10 times in a row is 1/6^10, a.k.a. "1 in 60,466,176", a.k.a "pretty unlikely".
    [end]
    
    I'll let this part speak for itself.

    Whew, ok, that got a little long, and sorry for boring the experts out there. Hopefully coders new to IPP will find some value in it.
  • Just realized I didn't answer your other questions.
    Eddie wrote:
    Okay, most important question I'm going to ask. Where is a document that tells me how to do all of these combinations and shortcuts?!
    Sadly, nowhere that I know of. The pdf that comes with IPP is handy, and has some surprisingly useful nuggets hidden here and there. But much of what I've learned comes from trial and error.
    Eddie wrote:
    Okay, please explain the "not display" part of the function. I understand the English of what it means, but what does it mean in IPP-language? I'm lost.
    Possibly you found your answer in my previous post. If not, consider this sample code:
    table: Start
    {roll=={1d3}}&
    [#{roll} Animals]
    
    table: Animals
    cat
    dog
    mouse
    
    This code assigns a value of 1 to 3 to variable roll, then uses roll as the die roll on the Animals table. Because the value of roll was assigned with double-equals, you don't see the value, so the results might look like:

    mouse
    cat
    cat
    dog
    ...

    But! If you chose to just use a single equal sign, the new value of roll would be displayed immediately, right before the call to Animals. And you'd see results like this:

    3mouse
    2cat
    2cat
    1dog
    ...

    As I maybe mentioned earlier, I almost never want this kind of result, and therefore almost never use single-equals for inline variable assignment.
  • I appreciate it! That's the added clarity I needed. Like I said, I've combed through the help file and understand most of the mechanics of how to structure things, but the nuances and why's of it and when to use it all really elude me. Of course, I took C++ about 13 years ago for a semester and a half...I dropped the first semester and passed the second with a D. Coding isn't exactly my strong point but I still try to learn it when I can.
    largando wrote:
    This code assigns a value of 1 to 3 to variable roll, then uses roll as the die roll on the Animals table. Because the value of roll was assigned with double-equals, you don't see the value, so the results might look like:

    mouse
    cat
    cat
    dog
    ...

    But! If you chose to just use a single equal sign, the new value of roll would be displayed immediately, right before the call to Animals. And you'd see results like this:

    3mouse
    2cat
    2cat
    1dog
    ...

    As I maybe mentioned earlier, I almost never want this kind of result, and therefore almost never use single-equals for inline variable assignment.

    Exactly what I needed. Now it's a "duh" moment for me. Crystal clear.

    If we ever meet, I owe you a few beers!

Leave a Comment