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!
  • Hey folks, resurrecting this because I need some assistance with it. I've moved on to more advanced interaction with different species in this generator. I've reached out to largando but someone else might have a solution also.

    The problem I'm trying to solve is ultimately to put a variable cap on an attribute, based on both species and stat name.

    As such, I have a prompt to specify species on the generator. For now, I have two to get it working, then I'll add more - human and wookiee. Select the species, it looks up a dictionary table to call a subtable roll for the species stats/sex/name/etc.

    I have the minimums for each attribute working perfectly using largando's code above as part of this subtable roll.

    The actual increment a stat portion I left separate and standalone of the species subtables (I'd like to move the species to external generators ultimately).

    The capping portion of the code is the '12' in this code:

    table: IncrementAStat
    {stat=='[@GetStat&;#93;'}&
    [when]{{stat}}=12&
    [do]{stat=='[@GetStat&;#93;'}[@IncrementAStat&;#93;&
    [else]{{stat}=={{{stat}}+1}}&
    [end]
    

    I need to turn the 12 into the two factor based variable I mentioned. I have two subtables in the Start table that run and don't display to set the variables through the rest of it - [@allnames][@{poolvar} IncrementAStat], this part seems to be the only way to get them to set if I keep them external to the generator.

    maxreps: 1
    Use: nbos\Star Wars NPC Name, Race, and Sex.ipt
    Use: nbos\Colors.ipt
    
    Prompt: Species {Human|Wookiee} Human
    Prompt: {Novice|Regular|Veteran|Elite|Special} Regular
    
    Set: Wilddie = {1d6}
    
    set: MALEHEIGHT = [@manheight]
    set: FEMALEHEIGHT = [@ladyheight]
    
    table: Start
    [@allnames][@{poolvar} IncrementAStat]<font face = "Times New Roman" size = "3"><B>{Name}</B><br><br>Pool: {pool}<br>Pool Variable: {poolvar}<BR><br><br>[@showstats]<br><br> [@stats]<BR><B>Weapon(s):</B><BR>[!{1d4} rangedweapons >> sort][!{1d4} meleeweapons >> sort]<BR><BR><B>NPC Items Carried:</B>[@items]<BR><B>NPC Notes:</B><BR>[@notes2]<BR></font>
    
    EndTable:
    
    table: stats
    1:<br><b>Species:</b> {$RACE}<BR>&
    <b>Gender:</b> {$GENDER}<BR>&
    <b>Physical Description:</b> {$Appearance}<BR><BR>&
    <b>Dexterity: [#{$Dex} diecodes]</b><br>&
    [!{1d18-1} dexskills >> sort >> implode]<br>&
    <br>&
    <b>Knowledge: [#{$Kno} diecodes]</b><br>&
    [!{1d15-1} knoskills >> sort >> implode]<br>&
    <br>&
    <b>Mechanical: [#{$Mec} diecodes]</b><br>&
    [!{1d19-1} mecskills >> sort >> implode]<br>&
    <br>&
    <b>Perception: [#{$Per} diecodes]</b><br>&
    [!{1d11-1} perskills >> sort >> implode]<br>&
    <br>&
    <b>Strength: [#{$Str} diecodes]</b><br>&
    [!{1d6-1} strskills >> sort >> implode]<br>&
    <br>&
    <b>Technical: [#{$Tec} diecodes]</b><br>&
    [!{1d19-1} tecskills >> sort >> implode]<br>&
    <br>&
    
    
    table: GetStat
    Str
    Kno
    Mec
    Per
    Dex
    Tec
    
    table: IncrementAStat
    {stat=='[@GetStat]'}[when]{{stat}}=12[do]{stat=='[@GetStat]'}[@IncrementAStat][else]{{stat}=={{{stat}}+1}}[end]
    
    
    table: ShowStats
    Str [#{Str} diecodes]\n&
    Kno [#{Kno} diecodes]\n&
    Mec [#{Mec} diecodes]\n&
    Per [#{Per} diecodes]\n&
    Dex [#{Dex} diecodes]\n&
    Tec [#{Tec} diecodes]\n&
    \n&
    Sum {{Str}+{Kno}+{Mec}+{Per}+{Dex}+{Tec}}
    
    table: diecodes
    +1
    +2
    1D
    1D+1
    1D+2
    2D
    2D+1
    2D+2
    3D
    3D+1
    3D+2
    4D
    4D+1
    4D+2
    5D
    5D+1
    5D+2
    6D
    6D+1
    6D+2
    7D
    7D+1
    7D+2
    8D
    8D+1
    8D+2
    9D
    9D+1
    9D+2
    10D
    10D+1
    10D+2
    11D
    11D+1
    11D+2
    12D
    12D+1
    12D+2
    13D
    13D+1
    13D+2
    14D
    14D+1
    14D+2
    15D
    15D+1
    15D+2
    16D
    16D+1
    16D+2
    17D
    17D+1
    17D+2
    18D
    
    Table: AllNames
    [#{$Prompt1} charnames]
    
    table: charnames
    Type: Dictionary
    Human:[@[|swhumanmale|swhumanfemale]]
    Wookiee: [@[|swwookieemale|swwookieefemale]]
    
    
    Table: swhumanmale
    set: attdice = 11
    set: Str = 6 
    set: Kno = 6 
    set: Mec = 6 
    set: Per = 6 
    set: Dex = 6 
    set: Tec = 6 
    set: pool = {{attdice} * 3 + 18}
    set: poolvar = {{pool} - {{STR}+{KNO}+{MEC}+{PER}+{DEX}+{TEC}}}
    set: RACE =Human
    set: GENDER =Male
    set: Appearance=[@Race_And_MaleGender]
    set: Name = [@SWHumanMaleNames] [@SWHumanSurnames]
    
    
    Table: swhumanfemale
    set: attdice = 11
    set: Str = 6 
    set: Kno = 6 
    set: Mec = 6 
    set: Per = 6 
    set: Dex = 6 
    set: Tec = 6 
    set: pool = {{attdice} * 3 + 18}
    set: poolvar = {{pool} - {{STR}+{KNO}+{MEC}+{PER}+{DEX}+{TEC}}}
    set: RACE =Human
    set: GENDER =Female
    set: Appearance=[@Race_And_FemaleGender]
    set: Name = [@SWHumanFemaleNames] [@SWHumanSurnames]
    
    
    Table: swwookieemale
    set: attdice = 12
    set: Str = 8 
    set: Kno = 3 
    set: Mec = 3 
    set: Per = 3 
    set: Dex = 3 
    set: Tec = 3 
    set: pool = {{attdice} * 3 + 18}
    set: poolvar = {{pool} - {{STR}+{KNO}+{MEC}+{PER}+{DEX}+{TEC}}}
    set: RACE =Human
    set: GENDER =Male
    set: Appearance=[@Race_And_MaleGender]
    set: Name = [@SWWookieMaleNames] [@SWWookieSurnames]
    
    
    Table: swwookieefemale
    set: attdice = 12
    set: Str = 8 
    set: Kno = 3 
    set: Mec = 3 
    set: Per = 3 
    set: Dex = 3 
    set: Tec = 3 
    set: pool = {{attdice} * 3 + 18}
    set: poolvar = {{pool} - {{STR}+{KNO}+{MEC}+{PER}+{DEX}+{TEC}}}
    set: RACE =Human
    set: GENDER =Female
    set: Appearance=[@Race_And_FemaleGender]
    set: Name = [@SWWookieFemaleNames] [@SWWookieSurnames]
    

    For humans, the cap for an attribute is 12 points always. That was simple (hence the 12 in largando's original code). When you get into alien species, it can vary widely from as little as 7 in some cases to 18, in the same species. For instance, wookies have a max Str of 18 (6D) and Per of 7 (2D+1).

  • I don't know that I follow exactly haw you are calculating your values, but let's assume that you have calculated values for each attribute and they meet or exceed the racial minimum values. I'd have a table (for instance Table: StrMax) setup for each attribute and call it like this:

    {Str={min({$Str},{[#{@Race} StrMax with {@Gender}})}}

    I haven't run it to check the brackets, @'s, and $'s... but what it's doing is this: assuming you have already calculated and stored a value for Str, it is resetting Str to the lower value of either what you have calculated, or the maximin allowed value for the race-gender combination. To have it lookup that race-gender combo max Strength value, have a table for each attribute that looks something like this (and you can easily add more races to the table as time goes on):

    Table: StrMax
    Type: Dictionary
    Human: 12
    Wookie: [when] {$1}="male" [do] 18 [else] 16 [end]

    So here, we're looking up Race in the dictionary table AND passing the value Gender into the table as {$1}. This is in case, for instance, a male wookie is allowed up to an 18 Str, but a female wookie is only allowed a 16 Str as a max value.

    (Ha! I'm assuming that wookies have binary gender and females are less strong than males. How boomer of me!)

    So, for instance, if you calculated the female wookie's strength as 22 (somehow... with you other bits of complicated code above), then it would compare the lookup max of 16 with the calculated 22 and set Str to the lowest of the two: 16. If the calculated value is 13, then it would set it to lowest of 13 or 16: 13.

    Hope I understand the question correctly and that this helps a bit.

  • Thanks for replying levendor.

    I'll try to help you understand the calculations. The old West End Games Star Wars uses d6 dice codes for all attributes and skills. Most species have 12D to divide amongst 6 attributes as a NPC and then "special" NPCs (or if the species gets picked by a player for a PC) get to add 6D for a total of 18D divided amongst the six attributes. Each 1D breaks down into 3 pips (+1, +1, +1 or +1, +2). A +3 would just go to the next full die, example 3D+3 is just 4D.

    IPP and numbercrunchers like Excel don't exactly like 2D+1 and 3D+2, etc. So I made the math easy. So I took the 3 pips/dice and just renamed them "points"/"steps". It's essentially a point-buy character system. Now IPP can math it's heart out. Multiply 12D and 6D by 3 each and we get 54 points total for character generation. Then I just take whatever number gets mathed and do a [#{mathednumber} table call] for the dice code to look pretty.

    Largando's code randomly increments the attributes for me to a maximum of 54 points. Hard-coded in is a second, individual attribute cap of 12 points (4D), which is the maximum for all humans. Like I said, now I want to go further with it and have different maximums for different species.

    table: IncrementAStat
    {stat=='[@GetStat]'}[when]{{stat}}=12[do]{stat=='[@GetStat]'}[@IncrementAStat][else]{{stat}=={{{stat}}+1}}[end]
    

    So that's what I'm trying to accomplish - 54 points get used total, but different attributes don't exceed their specific maximums also. The 12 in the quoted code needs to be a variable based on whatever gets passed to {stat}. I created the attribute max dictionary tables and tried to merge your two codes -

    table: IncrementAStat
    {stat=='[@GetStat]'}[when]{{stat}}={{stat}={min({${stat}},{[#{@Race} {stat}Max])}}[do]{stat=='[@GetStat]'}[@IncrementAStat][else]{{stat}=={{{stat}}+1}}[end]
    

    It hasn't worked for me yet and I think it's because I changed your code from StrMax to {stat}Max to try and get whatever is being set from the stat==GetStat call at the start of the line. If I don't do that though, I can't figure out how to increment correctly. Maybe I need to create six individual Increment tables and have them called separately, IncrementStr, IncrementDex, etc.

    Sidenote:
    As I've thought about it the last couple of days, I don't think I need to concern myself with an external generator for racial attributes. I've been on a big external generator kick lately for commonality across NPCs from different settings (but I really use the GURPS system for them all), mainly so I'm not opening up 15 different files and adding whatever new additions/changes I'm making. But this system is unique so I think I'm going to stop worrying about that aspect.

  • Maybe a bit closer now. I don't think I changed too much in this version. Biggest change - of course - is that call in Table: IncrementAStat. But before we get there:

    I added a Set: KnowMax = 5 to swwookiemale (and =6 to female wookie). This is arbitrary for testing, of course. You should go to each table and set all 6 attribute max values in the same way (unless there are no limits for a particular stat). I also moved set race and set gender to the top of the table (wanted those set immediately, but later realized there was no reason to move them).

    So back to Table: IncrementAStat... simply put, every time you enter this table, it selects a random stat (as you know... you wrote that part). Then a pretty simple [when] [do]. I'll write it here in simple syntax, and let's assume that [@getstat] returned 'Kno' for our random stat.

    [when] {Kno} < {$KnoMax} [do] {Kno={{$Kno}+1}}[else] [@IncrementAStat] [end]

    So, as long as the knowledge max has not yet been reached, it adds 1 to knowledge. If not it runs the increment routine again, selecting a new random attribute at the start of the rerun. Now the rerun doesn't count against your point pool because the rerun is being called by IncrementAStat itself, and it loops until it adds a point to some attribute that is not maxed out. Only then does it do another draw from [@{poolvar} IncrementAStat] command in Table:Start. (at least that's what I think... that may be the next thing we work on if I'm wrong.)

    And the real code below just replaces the three characters Kno with the six characters {stat} so that it works for every attribute.

    Here's the code:

    ; SWStat54.ipt
    ; using Eddie's code to modify. 1/4/2021 4:09:27 PM
    maxreps: 1
    Use: nbos\Star Wars NPC Name, Race, and Sex.ipt
    Use: nbos\Colors.ipt
    
    Prompt: Species {Human|Wookiee} Human
    Prompt: {Novice|Regular|Veteran|Elite|Special} Regular
    
    Set: Wilddie = {1d6}
    
    set: MALEHEIGHT = [@manheight]
    set: FEMALEHEIGHT = [@ladyheight]
    
    table: Start
    [@allnames][@{poolvar} IncrementAStat]<font face = "Times New Roman" size = "3"><B>{Name}</B><br><br>Pool: {pool}<br>Pool Variable: {poolvar}<BR><br><br>[@showstats]<br><br> [@stats]<BR><B>Weapon(s):</B><BR>[!{1d4} rangedweapons >> sort][!{1d4} meleeweapons >> sort]<BR><BR><B>NPC Items Carried:</B>[@items]<BR><B>NPC Notes:</B><BR>[@notes2]<BR></font>
    
    EndTable:
    
    table: stats
    1:<br><b>Species:</b> {$RACE}<BR>&
    <b>Gender:</b> {$GENDER}<BR>&
    <b>Physical Description:</b> {$Appearance}<BR><BR>&
    <b>Dexterity: [#{$Dex} diecodes]</b><br>&
    [!{1d18-1} dexskills >> sort >> implode]<br>&
    <br>&
    <b>Knowledge: [#{$Kno} diecodes]</b><br>&
    [!{1d15-1} knoskills >> sort >> implode]<br>&
    <br>&
    <b>Mechanical: [#{$Mec} diecodes]</b><br>&
    [!{1d19-1} mecskills >> sort >> implode]<br>&
    <br>&
    <b>Perception: [#{$Per} diecodes]</b><br>&
    [!{1d11-1} perskills >> sort >> implode]<br>&
    <br>&
    <b>Strength: [#{$Str} diecodes]</b><br>&
    [!{1d6-1} strskills >> sort >> implode]<br>&
    <br>&
    <b>Technical: [#{$Tec} diecodes]</b><br>&
    [!{1d19-1} tecskills >> sort >> implode]<br>&
    <br>&
    
    
    table: GetStat
    Str
    Kno
    Mec
    Per
    Dex
    Tec
    
    table: IncrementAStat
    {stat='[@GetStat]'}[when]{{stat}}<{${stat}Max}[do]{{stat}={{${stat}}+1}}[else][@IncrementAStat][end]
    
    
    table: ShowStats
    Str [#{Str} diecodes]\n&
    Kno [#{Kno} diecodes]\n&
    Mec [#{Mec} diecodes]\n&
    Per [#{Per} diecodes]\n&
    Dex [#{Dex} diecodes]\n&
    Tec [#{Tec} diecodes]\n&
    \n&
    Sum {{Str}+{Kno}+{Mec}+{Per}+{Dex}+{Tec}}
    
    table: diecodes
    +1
    +2
    1D
    1D+1
    1D+2
    2D
    2D+1
    2D+2
    3D
    3D+1
    3D+2
    4D
    4D+1
    4D+2
    5D
    5D+1
    5D+2
    6D
    6D+1
    6D+2
    7D
    7D+1
    7D+2
    8D
    8D+1
    8D+2
    9D
    9D+1
    9D+2
    10D
    10D+1
    10D+2
    11D
    11D+1
    11D+2
    12D
    12D+1
    12D+2
    13D
    13D+1
    13D+2
    14D
    14D+1
    14D+2
    15D
    15D+1
    15D+2
    16D
    16D+1
    16D+2
    17D
    17D+1
    17D+2
    18D
    
    Table: AllNames
    [#{$Prompt1} charnames]
    
    table: charnames
    Type: Dictionary
    Human:[@[|swhumanmale|swhumanfemale]]
    Wookiee: [@[|swwookieemale|swwookieefemale]]
    
    
    Table: swhumanmale
    set: RACE ={$prompt1}
    set: GENDER =Male
    set: attdice = 11
    set: Str = 6 
    set: Kno = 6 
    set: Mec = 6 
    set: Per = 6 
    set: Dex = 6 
    set: Tec = 6 
    set: pool = {{attdice} * 3 + 18}
    set: poolvar = {{pool} - {{STR}+{KNO}+{MEC}+{PER}+{DEX}+{TEC}}}
    set: Appearance=[@Race_And_MaleGender]
    set: Name = [@SWHumanMaleNames] [@SWHumanSurnames]
    
    
    Table: swhumanfemale
    set: RACE ={$prompt1}
    set: GENDER =Female
    set: attdice = 11
    set: Str = 6 
    set: Kno = 6 
    set: Mec = 6 
    set: Per = 6 
    set: Dex = 6 
    set: Tec = 6 
    set: pool = {{attdice} * 3 + 18}
    set: poolvar = {{pool} - {{STR}+{KNO}+{MEC}+{PER}+{DEX}+{TEC}}}
    set: Appearance=[@Race_And_FemaleGender]
    set: Name = [@SWHumanFemaleNames] [@SWHumanSurnames]
    
    
    Table: swwookieemale
    set: RACE ={$prompt1}
    set: GENDER =Male
    set: attdice = 12
    set: Str = 8 
    set: Kno = 3
    set: KnoMax=5 
    set: Mec = 3 
    set: Per = 3 
    set: Dex = 3 
    set: Tec = 3 
    set: pool = {{attdice} * 3 + 18}
    set: poolvar = {{pool} - {{STR}+{KNO}+{MEC}+{PER}+{DEX}+{TEC}}}
    set: Appearance=[@Race_And_MaleGender]
    set: Name = [@SWWookieMaleNames] [@SWWookieSurnames]
    
    
    Table: swwookieefemale
    set: RACE ={$prompt1}
    set: GENDER =Female
    set: attdice = 12
    set: Str = 8 
    set: Kno = 3
    set: KnoMax=6  
    set: Mec = 3 
    set: Per = 3 
    set: Dex = 3 
    set: Tec = 3 
    set: pool = {{attdice} * 3 + 18}
    set: poolvar = {{pool} - {{STR}+{KNO}+{MEC}+{PER}+{DEX}+{TEC}}}
    set: Appearance=[@Race_And_FemaleGender]
    set: Name = [@SWWookieFemaleNames] [@SWWookieSurnames]
    
  • Thanks, Levendor! I plugged it in and ran about 30 iterations. So far it seems like it's working. I think you solved my problem. Thank you!

Leave a Comment