Still Struggling with the D20 Repeats

Hello.

I am back again on this. Last time I thought I was able to get it to work. Turns out I was wrong. I was scrubbing through my game for final edits before releasing the full chapter one demo when I came across the repeating rolls again. No matter what I do it doesn’t work.

Unless I make it ugly. I have to put in a sentence or two in between the roll and the scene it needs to go to, which looks utterly stupid. I hate it, it’s awkward and is just jarring. But no matter what I try that is the ONLY thing that works. It makes me want to jump out of a plane.

What am I doing wrong?

Here is EVERY iteration of code I have used that has NOT worked followed by the single one that has. Straight from my story this time too. I apolgize in advance as some of this is VERY lengthy, but I don’t know what else to do other than paste it all in case something is wrong.

Fail 1:

Summary
#Investigate the sound. Someone could be trapped.
        You dash across the room, 
        *if (rrace = "human")
            vaulting over the flame licked surface of the bar
        *if (rrace = "elf")
            vaulting over the flame licked surface of the bar
        *if (rrace = "orc")
            vaulting over the flame licked surface of the bar
        *if (rrace = "halfling")
            skidding around the corner of the crumbling bar
        *if (rrace = "dwarf")
            skidding around the corner of the crumbling bar        
        and sprint to the kitchen (stuff about the maid you found.) The roof makes a loud creaking noise as you examine her. If you wish to help, you must do so before the roof caves in.
        *fake_choice
            #Attempt to remove the beam.
                *set DCrange "5"
                *rand d20 1 20
                *set strengthmodifier (strength/10)
                *set rollresult (d20 + strengthmodifier)
                *set rollsuccess false
                *set rollfail false
                *page_break
                *if (rollresult >= DCrange)
                    *set rollsuccess true
                    *page_break
                    *if (rollsuccess = true)
                        It doesn't take much effort to lift the beam from its position and toss aside with a dull thud. You grab the woman gently, hoisting her into your arms. You turn and swiftly make your exit.
                        *goto savemaid
                    
                *if (rollresult < DCrange)
                    *set rollfail true
                    *page_break
                    *if (rollsuccess = false)
                        You try to lift the beam, but it refuses to budge. The woman is unconcious now, so she is atleast spared the pain of your fumbling attempts. But try as you might, the scorched wood is simply too heavy. The ceiling groans ominously above you. Time is running out.
                    *fake_choice
                        *selectable_if ( Magic >= 25) #Levitate the beam.
                            You.........
                            *goto savemaid
                        #Leave
                            There is nothing more you can do for her. You leave the woman behind, returning to the commonroom.
                            *goto cont.1

Fail 2:

Summary
#Investigate the sound. Someone could be trapped.
        You dash across the room, 
        *if (rrace = "human")
            vaulting over the flame licked surface of the bar
        *if (rrace = "elf")
            vaulting over the flame licked surface of the bar
        *if (rrace = "orc")
            vaulting over the flame licked surface of the bar
        *if (rrace = "halfling")
            skidding around the corner of the crumbling bar
        *if (rrace = "dwarf")
            skidding around the corner of the crumbling bar        
        and sprint to the kitchen (stuff about the maid you found.) The roof makes a loud creaking noise as you examine her. If you wish to help, you must do so before the roof caves in.
        *fake_choice
            #Attempt to remove the beam.
                *set DCrange "5"
                *gosub_scene MISC strengthcheck
                *page_break
                You lift the beam with all your might.
                    *if (rollsuccess = true)
                           It doesn't take much effort to lift the beam from its position and toss aside with a dull thud. You grab the woman gently, hoisting her into your arms. You turn and swiftly make your exit.
                           *goto savemaid

                    *if (rollsuccess = false)
                           You try to lift the beam, but it refuses to budge. The woman is unconcious now, so she is atleast spared the pain of your fumbling attempts. But try as you might, the scorched wood is simply too heavy. The ceiling groans ominously above you. Time is running out.
                          *fake_choice
                              *selectable_if ( Magic >= 25) #Levitate the beam.
                                 You.........
                                 *goto savemaid

                              #Leave
                                 There is nothing more you can do for her. You leave the woman behind, returning to the commonroom.
                                 *goto cont.1

Fail 3- Infinity is adding *page_break between every single line with increasing frequency, at some point I even ended up with this and it did not work.

Summary
#Investigate the sound. Someone could be trapped.
        You dash across the room, 
        *if (rrace = "human")
            vaulting over the flame licked surface of the bar
        *if (rrace = "elf")
            vaulting over the flame licked surface of the bar
        *if (rrace = "orc")
            vaulting over the flame licked surface of the bar
        *if (rrace = "halfling")
            skidding around the corner of the crumbling bar
        *if (rrace = "dwarf")
            skidding around the corner of the crumbling bar        
        and sprint to the kitchen (stuff about the maid you found.) The roof makes a loud creaking noise as you examine her. If you wish to help, you must do so before the roof caves in.
        *fake_choice
            #Attempt to remove the beam.
                *page_break
                *set DCrange "5"
                *page_break
                *gosub_scene MISC strengthcheck
                *page_break
                *if (rollsuccess = true)
                    *page_break
                    It doesn't take much effort to lift the beam from its position and toss aside with a dull thud. You grab the woman gently, hoisting her into your arms. You turn and swiftly make your exit.
                    *goto savemaid

                *if (rollsuccess = false)
                    *page_break
                    You try to lift the beam, but it refuses to budge. The woman is unconcious now, so she is atleast spared the pain of your fumbling attempts. But try as you might, the scorched wood is simply too heavy. The ceiling groans ominously above you. Time is running out.
                    *fake_choice
                        *selectable_if ( Magic >= 25) #Levitate the beam.
                            You.........
                            *goto savemaid

                        #Leave
                            There is nothing more you can do for her. You leave the woman behind, returning to the commonroom.
                            *goto cont.1


What works do you ask? This awkward thing.

Summary
#Investigate the sound. Someone could be trapped.
        You dash across the room, 
        *if (rrace = "human")
            vaulting over the flame licked surface of the bar
        *if (rrace = "elf")
            vaulting over the flame licked surface of the bar
        *if (rrace = "orc")
            vaulting over the flame licked surface of the bar
        *if (rrace = "halfling")
            skidding around the corner of the crumbling bar
        *if (rrace = "dwarf")
            skidding around the corner of the crumbling bar        
        and sprint to the kitchen (stuff about the maid you found.) The roof makes a loud creaking noise as you examine her. If you wish to help, you must do so before the roof caves in.
        *fake_choice
            #Attempt to remove the beam.
                *set DCrange "5"
                *gosub_scene MISC strengthcheck
                *page_break
                You have the beam with all your might.
                *page_break
                *if (rollsuccess = true)
                    It doesn't take much effort to lift the beam from its position and toss aside with a dull thud. You grab the woman gently, hoisting her into your arms. You turn and swiftly make your exit.
                    *goto savemaid

                *if (rollsuccess = false)
                    You try to lift the beam, but it refuses to budge. The woman is unconcious now, so she is atleast spared the pain of your fumbling attempts. But try as you might, the scorched wood is simply too heavy. The ceiling groans ominously above you. Time is running out.
                    *fake_choice
                        *selectable_if ( Magic >= 25) #Levitate the beam.
                            You.........
                            *goto savemaid

                        #Leave
                            There is nothing more you can do for her. You leave the woman behind, returning to the commonroom.
                            *goto cont.1

Here is an example of the gosub scene as well, which I have also expiremented with putting a bunch of *page_breaks into at random intervals to no avail.

Summary
*label strengthcheck
*gosub skillconversion
*rand d20 1 20

*set rollresult (d20 + strengthmodifier)
*set rollsuccess false
*set rollfail false
*page_break
*if (rollresult >= DCrange)
    *set rollsuccess true
    *page_break
    
*if (rollresult < DCrange)
    *set rollfail true
    *page_break
*return


(so on and so forth with the other stats)



*label skillconversion
*set strengthmodifier (Strength/10)
*set dexmodifier (Dexterity/10)
*set intmodifier (Intelligence/10)
*set conmodifier (Constitution/10)
*set pmodifier (Perception/10)
*set stealthmodifier (Stealth/10)

*set steelmodifier (Steel/10)
*set archerymodifier (Archery/10)
*set brawlingmodifier (Brawling/10)
*set magicmodifier (Magic/10)

*set medmodifier (Medicine/10)
*set survmodifier (Survival/10)
*set leadmodifier (Leadership/10)
*set craftmodifier (Crafting/10)
*set thievemodifier (Thievery/10)
*return


So, unless there is something wrong with my compiler itself, since its been like 8 years since I updated it, I am unsure why is refuses to take ANYTHING but the single success I listed.

I goin crazy here lol.

If I understand this correctly, you want a method where the rand rolls don’t get called when moving in and out of the stats page?

Correct.

You can make all the rolls you need before the page loads so you won’t need to add articificial page_breaks.

Could you give an example?

In this example I’m using only one stat, though I suppose with this one I could do that. But when I’m doing a multi choice between all say, 4 combat options, then I can’t call one specific one no? If I wanted to do Steel, Archery, Magic, and Brawling and have a roll for each I couldn’t do them all at the beginning unless the system knows to save a separate roll for each variable and then carry it over.

Unless I’m misunderstanding?

I also must keep in mind every roll is changed by a modifier that is determined by the percentage divided by 2.

So if strength is 20% it will have a +2 to the roll, which needs to be done somewhere and then applied. And if I introduce 5 other stats each on has to modify the roll in some way, either on their own or sometimes even together.

Here is a short example highlighting the concept. You can paste this in a new project and see that the roll is always the same.

*temp roll 0

This is a place in the story where the player does not know that th roll is made

*rand roll 1 200

*page_break

Try as you might. Everytime you visit the stats page, the roll will still be ${roll}, you naughty cheater.

*fake_choice
# Ok 

Ok.


In this case, where you don’t know which stat roll you need, you make all of them before showing the player choices that depend on those rolls.

Each roll has a different DC though, so how do I determine fails/passes before the DC is declared?

Like say, lifting the beam is a DC 16.

That means I need a roll for that with strength and another for magic to levitate it.

The next choice is you save the maid and now you have to heal, that’s a DC 10.

Am I then using my gosub after every scene is declared? And does the game store each individual roll that needs to be modified.

D20+2 for strength.

And

D20+4 for magic.

I’m sorry, but I don’t understand what the issue is. As long as you make the roll before you show the options to the player, you can make any comparisons and additions you want with that roll.

EDIT: Can you provide a short code snipped with just the logic (no narrative text), so I can better understand your issue?

You might want to consider making all the rolls for the whole game when you first boot up the game’s startup file, through the use of an array.

In your startup.txt you could do something like this.

*create ArraySweeper 1
*create current_d20Roll 1
*comment The next part will generate 100 rolls stored under the d20 varable. By default we'll set all the values to 1 and then randomize them with the code below.
*create_array d20 100 1
*create_array d10 100 1
...
*comment After you've made all your variables, we can create a loop to assign a random roll to.
*label FrootLoops
*comment these [ ] brackets around ArraySweeper below are important as they are the roll you're currently viewing. If ArraySweeper is set to 7, then it is looking at the seventh d20 roll for your game.
*rand d20[ArraySweeper] 1 20
*if ArraySweeper <= 100
 *comment This will have it repeat assigning a value to all 100 rolls by sending it back to the beginning of the loop, until it is done with the 100th roll.
 *set ArraySweeper +1
 *goto FrootLoops
*set ArraySweeper 1

Then, during your code, you’d use the array value; you just need to check if you’re at the end of the array. You’d call for the array value by use of current_d20Roll in this example.

#Attempt to remove the beam.
 *set DC 15 
 *set strengthmodifier (strength/10)
 *comment once more, the [ ] brackets are needed to know which roll we're looking at.
 *set RollResult (d20[current_d20Roll] + strengthmodifier)
 *comment Then we'll lift the value to be ready to look to the next roll, you could also do this before hand, but I like doing it afterwards.
 *set current_d20Roll +1
 *comment then we check to see if we have reached the end of the prerolls, if so, we start it back at the beginning.
 *if current_d20Roll >= 100
  *set current_d20Roll 1
 *if DC > RollResult 
  *set rollsuccess false
 *else
  *set rollsuccess true

Since the randomizing is only done at start up, this makes it so it doesn’t randomize when going in and out of the stats screen, except maybe on that very first page.

I see, this is a little more in line with what I was thinking. Is there a way for me to combine it with my MISC scene to make the conversions there so I don’t have to do it every single choice?

How does the array work exactly? In theory it makes sense but I’ve never used an array before, how does it choose which “roll” to use when I do the choice itself. Is it still random or is it a predetermined roll?

In my example, it is randomized at the very start of the game, so both?

Could you give me an example of what you mean?

That’s complicated to explain.

Basically an array allows you to store multiple values in a single Variable, by partitioning it into a bunch of what I’ll call sub vaibles (I don’t know the actual term). The [ ] brackets tells the system which sub variable to look at. In my example current_d20Roll is a variable that points the system to which roll to look at. That’s why current_d20Roll is increased afterwards, so the next roll the system looks at will be a different roll. If you don’t use [ ] then you will get an error when trying to use the Array.

There is further reading on them here and here.

With all due respect, @quartz’ suggestion is a lot more sensible than rolling all dice at startup, even because as the game develop you may add more rolls and would need to always go back to startup to adjust that. Also, @quartz’ suggestion is how every other author does “dice” (or randomization) in ChoiceScript, no need to reinvent the wheel.

Something interesting happens here and the player makes a choice. Roll the dice here, even if they go to the stat screen and come back and the dice gets re-rolled, it doesn't matter because they haven't seen the outcome yet and doesn't know the value they rolled in the dice. 

*rand d20 1 20

*choice
   # Use Strength
      Here you you make any comparisons to DC and add other modifiers, since they are static, the result will always be the same and even if the player visits the stat page the dice has already been rolled and won't change.
   # Use Dexterity
. 
. 
. 

It’s that simple.

2 Likes

I should be writing for NaNo right now, but my mind is stuck on this.

Something you can also do is have a catch-all d20 roll check subroutine.

So you can create a file called d20Check.txt and put in this code

*set PassCheck false
*set RollResult d20[current_d20Roll]
*set RollResult + Modifier
*set RollResult + Bonus
*set RollResult - Penalty
*comment While I could do all of that in a single line, breaking it down into steps makes troubleshooting easier, and it also allows you to modify it more easily.
*if RollResult  >= DC
 *set PassCheck true
*set Modifier 0
*set Bonus 0
*set Penalty 0
*set current_d20Roll +1
*if current_d20Roll > 100
 *set current_d20Roll 1
*return

By the end of the code, I set everything back to 0 that needs to be and advance the code to look at the next die roll. This allows you to add rolls and modifiers when needed.

Then whenever you want to make a roll, you can do the following.

Example of simple Strength Check
# [Strength Check] Break down the door.
 *set DC 14
 *set Modifier (strength/10)
 *gosub_scene d20Check
 *if PassCheck
  *goto PassText
 *goto FailedText
Example of Adding Penalties

In this example, let’s assume the player is human, but the target doesn’t like humans.

# [Charima Check] Charm your way out.
 *set DC 16
 *set Modifier (Charisma /10)
 *if (Race = "human")
  *set Penalty 3
 *gosub_scene d20Check
 *if PassCheck
  *goto PassText
 *goto FailedText
Example for a d20 Flat check

This would also allow for flat checks by adding nothing to the roll.

#Let the fates decide.
 *set DC 10
 *gosub_scene d20Check
 *if PassCheck
  *goto PassText
 *goto FailedText
Here is alt code for the d20Check.txt if you plan on using DnD's Advantage and Disadvantage
*set PassCheck false
*set RollResult d20[current_d20Roll]
*if Advantage
 *set current_d20Roll + 1
 *set RollResult2 d20[current_d20Roll]
 *if RollResult2 > RollResult
  *set RollResult RollResult2
*if Disadvantage
 *set current_d20Roll + 1
 *set RollResult2 d20[current_d20Roll]
 *if RollResult2 < RollResult
  *set RollResult RollResult2
*set RollResult + Modifier
*set RollResult + Bonus
*set RollResult - Penalty
*comment While I could do all of that in a single line, breaking it down into steps makes troubleshooting easier, and it also allows you to modify it more easily.
*if RollResult  >= DC
 *set PassCheck true
*set Modifier 0
*set Bonus 0
*set Penalty 0
*comment I then turn off Advantage when done so you only need to set it before the roll.
*set Advantage false
*set Disadvantage false
*set current_d20Roll +1
*if current_d20Roll > 100
 *set current_d20Roll 1
*return

This will let you set advantage to true right before calling the roll.

Using Advantage

This example uses a conditional advantage, checking if the character has the high ground before giving the advantage.

#Attack with bow.
 *set DC 21
 *set Modifier ( Dexerity /10)
 *if HighGround
  *set Advantage true
 *gosub_scene d20Check
 *if PassCheck
  *goto PassText
 *goto FailedText

I just spotted this. This is true, I am overcomplicating it and that looks to be a much simpler method.

Because I love Subroutines, I could take that method and still standardize it into a subroutine.

Alt d20Check.txt file (includes Advantage and Disadvantage)

With this example you don’t need to put *rand d20 1 20 every time and instead just use *gosub_scene d20Check instead. The subroutine will roll dice and add modifiers and the like as you input before calling the subroutine.

*set PassCheck false
*set RollResult d20
*if Advantage and (2d20 > d20)
 *set RollResult 2d20
*if Disadvantage and (2d20 < d20)
 *set RollResult 2d20
*set RollResult + Modifier
*set RollResult + Bonus
*set RollResult - Penalty
*comment While I could do all of that in a single line, breaking it down into steps makes troubleshooting easier, and it also allows you to modify it more easily.
*if RollResult  >= DC
 *set PassCheck true
*set Modifier 0
*set Bonus 0
*set Penalty 0
*comment I then turn off Advantage and Disadvantage since the check is over when done so you only need to set it before the roll.
*set Advantage false
*set Disadvantage false
*comment now, I'll roll two new dice for the next check.
*rand d20 1 20
*rand 2d20 1 20
*return

You would call it like this.

# Choice here
 *comment add modifiers, penalties, bonuses, advantage, and disadvantage here, only when applicable. Use examples from above on how to do that.
 *gosub_scene d20Check
 *if PassCheck 
  *goto GoodStuff
 *goto BadStuff
2 Likes

What I’d suggest is just move

*rand d20 1 20

to just before the *fake_choice

#Investigate the sound. Someone could be trapped.
        You dash across the room, 
        *if (rrace = "human")
            vaulting over the flame licked surface of the bar
        *if (rrace = "elf")
            vaulting over the flame licked surface of the bar
        *if (rrace = "orc")
            vaulting over the flame licked surface of the bar
        *if (rrace = "halfling")
            skidding around the corner of the crumbling bar
        *if (rrace = "dwarf")
            skidding around the corner of the crumbling bar        
        and sprint to the kitchen (stuff about the maid you found.) The roof makes a loud creaking noise as you examine her. If you wish to help, you must do so before the roof caves in.
        *rand d20 1 20
        *fake_choice
            #Attempt to remove the beam.

I understand it looks simpler, but how do I get the DC to properly be done after the fact?

Because adding the modifier means a pass or fail, not necessarily the dice roll itself.

I’m not understanding how I would add the modifier later is what I mean, without running into the same issue? Are you saying to do this instead?


Something interesting happens here and the player makes a choice. Roll the dice here, even if they go to the stat screen and come back and the dice gets re-rolled, it doesn't matter because they haven't seen the outcome yet and doesn't know the value they rolled in the dice. 
*rand d20 1 20
*fake_choice
   # Use Strength
      *set DC “10”
      *gosub MISC strengthcheck
      *page_break
      *if (rollsuccess = true)
            XYZ happens
            *goto next
      *if (rollsuccess = false)
            XYZ happens.
            *goto next

       
     
   # Use Dexterity
      *set DC “10”
      *gosub MISC dexcheck 
      *page_break
      *if (rollsuccess = true)
            XYZ happens
            *goto next
      *if (rollsuccess = false)
            XYZ happens.
            *goto next

Then in my subroutine I just remove the Rand 1 D 20 roll from the beginning?

Summary

*label strengthcheck
*gosub skillconversion

*set rollresult (d20 + strengthmodifier)
*set rollsuccess false
*set rollfail false
*page_break
*if (rollresult >= DCrange)
    *set rollsuccess true
    *page_break
    
*if (rollresult < DCrange)
    *set rollfail true
    *page_break
*return


(so on and so forth with the other stats)



*label skillconversion
*set strengthmodifier (Strength/10)
*set dexmodifier (Dexterity/10)
*set intmodifier (Intelligence/10)
*set conmodifier (Constitution/10)
*set pmodifier (Perception/10)
*set stealthmodifier (Stealth/10)

*set steelmodifier (Steel/10)
*set archerymodifier (Archery/10)
*set brawlingmodifier (Brawling/10)
*set magicmodifier (Magic/10)

*set medmodifier (Medicine/10)
*set survmodifier (Survival/10)
*set leadmodifier (Leadership/10)
*set craftmodifier (Crafting/10)
*set thievemodifier (Thievery/10)
*return

I could also feasibly just have the stats modify at the beginning of every scene and then call to it with a label if the roll and conversions have to be done in the same scene for every choice like I had been doing.

I just don’t want to have to do the real time stat conversation every single choice. But if I HAVE to I can.

You could also combine all the stat checks into a single file, then use a new variable “stat_check” to save you from having to keep reusing the same code in every file.

Something interesting happens here and the player makes a choice. Roll the dice here, even if they go to the stat screen and come back and the dice gets re-rolled, it doesn't matter because they haven't seen the outcome yet and doesn't know the value they rolled in the dice. 
*rand d20 1 20
*fake_choice
   # Use Strength.
      *set DC “10”
      *set stat_check "strength"
      *gosub_scene roll_check strength
      *if (rollsuccess = true)
            XYZ happens
            *goto next
      *else
            XYZ happens.
            *goto next
   # Use Dexterity.
      *set DC “10”
      *set stat_check "dexerity"
      *gosub_scene roll_check dexterity
      *if (rollsuccess = true)
            XYZ happens
            *goto next
      *else
            XYZ happens.
            *goto next

***Then in the file named roll_check

*label strength
*set strengthmodifier (strength/10)
*set rollresult (d20 + strengthmodifier)
*set rollsuccess false
*if (rollresult >= DCrange)
    *set rollsuccess true
    *return
*else
    *set rollsuccess false
    *return

*label dexerity
*set dexeritymodifier (dexerity/10)
*set rollresult (d20 + dexeritymodifier)
*set rollsuccess false
*if (rollresult >= DCrange)
    *set rollsuccess true
    *return
*else
    *set rollsuccess false
    *return

Not what you’re asking about, but I’d check you’re not getting rerolls where you’ve put the *rand command. It might be ok, but I usually roll a pagebreak or choice earlier than this, as have had issues with rerolls happening when people go to the stats menu, which really messes the game up.

Yeah, I think I posted something similar above.

Do you think it’s better to keep the subroutine as is minus the Rand D20 or adopt the skill check one you posted?