Coding a dice game

I was coding a segment where two characters play a dice game. They have a book which contains questions corresponding to dice numbers, and they must answer the question they get.

BUT

A question can obviously not be repeated
(I haven’t written the *set donex true command in case there is a better way)

*label gaa
You nod, throwing the dice on the table.

*temp dice1 0
*temp dice2 0
*temp done1 false
*temp done2 false
*temp done3 false
*temp done4 false
*temp done5 false
*temp done6 false
*temp done7 false
*temp done8 false
*temp done9 false
*temp done10 false
*temp done11 false
*temp done12 false
*temp done13 false
*temp done14 false 
*temp done15 false
*temp done16 false
*temp done17 false
*temp done18 false
*temp done19 false
*temp done20 false
*temp done21 false
*temp done22 false
*temp done23 false
*temp done24 false
*temp done25 false
*temp done26 false
*temp done27 false
*temp done28 false
*temp done29 false
*temp done30 false
*temp done31 false
*temp done31 false
*temp done32 false 
*temp done33 false
*temp done34 false
*temp done35 false
*temp done36 false
*temp inside 0
*label redice
*fake_choice 
    #Throw dice
    #End game
*rand dice1 1 6
*rand dice2 1 6
The first rolls to ${dice1} and second to ${dice2}. You check the book.

*if dice1 = 1 
    *if (dice2 = 1) and (done1 = false)
        *set inside 1
    *elseif (dice2 = 2) and (done2 = false)
        *set inside 1
    *elseif (dice2 = 3) and (done3 = false)
        *set inside 1
    *elseif (dice2 = 4) and (done4 = false)
        *set inside 1
    *elseif (dice2 = 5) and (done5 = false)
        *set inside 1
    *elseif (dice2 = 6) and (done6 = false)
        *set inside 1
*elseif dice1 = 2
    *if (dice2 = 1) and (done7 = false)
        *set inside 1
    *elseif (dice2 = 2) and (done8 = false)
        *set inside 1
    *elseif (dice2 = 3) and (done9 = false) 
        *set inside 1
    *elseif (dice2 = 4) and (done10 = false)
        *set inside 1
    *elseif (dice2 = 5) and (done11 = false)
        *set inside 1
    *elseif (dice2 = 6) and (done12 = false)
        *set inside 1
*elseif dice1 = 3 
    *if (dice2 = 1) and (done13 = false)
        *set inside 1
    *elseif (dice2 = 2) and (done14 = false)
        *set inside 1
    *elseif (dice2 = 3) and (done15 = false)
        *set inside 1
    *elseif (dice2 = 4) and (done16 = false)
        *set inside 1
    *elseif (dice2 = 5) and (done17 = false)
        *set inside 1
    *elseif (dice2 = 6) and (done18 = false)
        *set inside 1
*elseif dice1 = 4 
    *if (dice2 = 1) and (done19 = false)
        *set inside 1
    *elseif (dice2 = 2) and (done20 = false)
        *set inside 1
    *elseif (dice2 = 3) and (done21 = false)
        *set inside 1
    *elseif (dice2 = 4) and (done22 = false)
        *set inside 1
    *elseif (dice2 = 5) and (done23 = false)
        *set inside 1
    *elseif (dice2 = 6) and (done24 = false)
        *set inside 1
*elseif dice1 = 5 
    *if (dice2 = 1) and (done25 = false)
        *set inside 1
    *elseif (dice2 = 2) and (done26 = false)
        *set inside 1
    *elseif (dice2 = 3) and (done27 = false)
        *set inside 1
    *elseif (dice2 = 4) and (done28 = false)
        *set inside 1
    *elseif (dice2 = 5) and (done29 = false)
        *set inside 1
    *elseif (dice2 = 6) and (done30 = false)
        *set inside 1
*elseif dice1 = 6  
    *if (dice2 = 1) and (done31 = false)
        *set inside 1
    *elseif (dice2 = 2) and (done32 = false)
        *set inside 1
    *elseif (dice2 = 3) and (done33 = false)
        *set inside 1
    *elseif (dice2 = 4) and (done34 = false)
        *set inside 1
    *elseif (dice2 = 5) and (done35 = false)
        *set inside 1
    *elseif (dice2 = 6) and (done36 = false)
        *set inside 1

*if inside = 0
    "We have done this one. Re-roll."
*goto redice

Is there any better way to do this? I came up with this after a few minutes of thinking, but this is a lot of code.

1 Like

I’m not really sure what dice you’re using or how you’re combining them, so for this example I just used two 6-sided dice.

*comment Initialize temporary flags for each question (2 through 12)
*temp q2 true
*temp q3 true
*temp q4 true
*temp q5 true
*temp q6 true
*temp q7 true
*temp q8 true
*temp q9 true
*temp q10 true
*temp q11 true
*temp q12 true

*comment Dice values and control variables
*temp die1 0
*temp die2 0
*temp total 0
*temp turns 0

*label game_loop
*comment Roll two 6-sided dice
*rand die1 1 6
*rand die2 1 6

*comment Calculate the total of the two dice
*set total (die1 + die2)

*comment Show the dice results to the player
You rolled a ${die1} and a ${die2}, for a total of ${total}.

*comment Check if the corresponding question is still available; if so, mark it used and go to that question

*if (total = 2) and q2
  *set q2 false
  *set question_asked true
  *goto question2
*elseif (total = 3) and q3
  *set q3 false
  *set question_asked true
  *goto question3
*elseif (total = 4) and q4
  *set q4 false
  *set question_asked true
  *goto question4
*elseif (total = 5) and q5
  *set q5 false
  *set question_asked true
  *goto question5
*elseif (total = 6) and q6
  *set q6 false
  *set question_asked true
  *goto question6
*elseif (total = 7) and q7
  *set q7 false
  *set question_asked true
  *goto question7
*elseif (total = 8) and q8
  *set q8 false
  *set question_asked true
  *goto question8
*elseif (total = 9) and q9
  *set q9 false
  *set question_asked true
  *goto question9
*elseif (total = 10) and q10
  *set q10 false
  *set question_asked true
  *goto question10
*elseif (total = 11) and q11
  *set q11 false
  *set question_asked true
  *goto question11
*elseif (total = 12) and q12
  *set q12 false
  *set question_asked true
  *goto question12
*else
  *comment If the question was already used, reroll
  That question was already asked, so you reroll.
  *goto game_loop

*comment Question labels follow; each asks a different question, then proceeds to end_turn

*label question2
"Question 2: What is your earliest memory?"
*goto end_turn

*label question3
"Question 3: What’s a talent you wish you had?"
*goto end_turn

*label question4
"Question 4: If you could travel anywhere, where would you go?"
*goto end_turn

*label question5
"Question 5: What’s your favorite time of day?"
*goto end_turn

*label question6
"Question 6: Have you ever had a supernatural experience?"
*goto end_turn

*label question7
"Question 7: What’s a book or movie that changed your perspective?"
*goto end_turn

*label question8
"Question 8: Describe a perfect weekend."
*goto end_turn

*label question9
"Question 9: What’s a habit you’d like to break?"
*goto end_turn

*label question10
"Question 10: Who do you admire most?"
*goto end_turn

*label question11
"Question 11: What’s something you’ve always wanted to try?"
*goto end_turn

*label question12
"Question 12: What would you do if you won a million dollars?"
*goto end_turn

*label end_turn
*comment Increment the turn counter
*set turns +1

*comment End game after 11 unique questions (maximum possible with 2d6)
*if (turns = 11)
  All questions have been asked. The game is over!
  *finish
*else
  *comment Otherwise, continue to the next turn
  *page_break Next Turn
  *goto game_loop

1 Like

How does this dice game work? What is it supposed to do?

The first dice stands for set number, and second for question number. Suppose first dice rolls 2 and second rolls 6, so you have the 6th question of the 2nd set (because each set has a theme).

I get more combinations this way (36) instead of just 12.

2 Likes

The dice are supposed to select a set number and a question number. (it first checks if the question has already been used or not, and rerolls if it has been)

Suppose you roll first die, it gives 5

You enter the fifth set

And then you roll second die, it gives 4

The 4th question is now selected (and eliminated).

Well the process will be the same, more or less, just with 36 choices. You could have it set up so that only that second die gets rerolled if there are open options in the set still though, I suppose.

1 Like

Maybe use an array?

*create dice1 0
*create dice2 0
*create index 0
*create questions_asked 0
*create_array question_done 36 false

Welcome to the Dice Game!

*label redice
*if (questions_asked = 36)
    "All questions have been answered! Thanks for playing."
    *finish

Press to roll the dice.
*choice
    #Roll dice
        *rand dice1 1 6
        *rand dice2 1 6
        You rolled a ${dice1} and a ${dice2}.
        *set index ((dice1 - 1) * 6) + dice2

        *if question_done[index]
            You've already answered question ${index}. Rolling again...
            *goto redice
        *else
            *set question_done[index] true
            *set questions_asked +1
            *goto question_select

*label question_select
*gosub_scene questions question_${index}
*goto redice

and another scene containing the questions

*label question_1
Question 1: What is your earliest memory?
*return

*label question_2
Question 2: What's a talent you wish you had?
*return

*label question_3
Question 3: What is your favorite book and why?
*return

*label question_4
Question 4: What was your dream job as a kid?
*return
4 Likes

I second the use of array, but with d66 notation.

*temp dice1 0
*temp dice2 0

*temp_array done 66 false

//-----------
*label redice

*rand dice1 1 6
*rand dice2 1 6

*if (done[dice1 & dice2])
    "We have done this one. Re-roll."
    *goto redice
  1. Create an array to save the results. The array has 66 slots, but you’ll use only 36. That’s okay.
  2. Use the string concatenation syntax to “add” the two rolls together. You’re not adding them numerically, just aglutinating them, so 1 & 1 is 11 and not 2.
  3. Use array notation to access that slot in the array: done[dice1 & dice2].

I would suggest that instead of rerolling, to go to the next available option. Otherwise, the more questions they make the more likely to get stuck in a rerolling loop. The last question for example as 1 in 36 chances (less than 3%) of coming out.

1 Like

I will try to implement this and see.

Hm… Could we not force it to keep rerolling till it has an option? If we remove the “We have done this. Reroll.” and redirect it to just before it rolls the dice, will it not keep repeating till it encounters a number that is not done? At least that’s how I think it should work.

Yes, that should work, unless chances fall below 1%.

1 Like

You know, I’m really not sure what gave me the impression that arrays weren’t a thing in ChoiceScript

1 Like

They’re actually not. :joy: It’s just syntax sugar coating to create multiple variables with a prefix. But there’s no way to manipulate arrays natively or any type of property like “length”.

If you’re interested, in CSLIB there’s a module for working with ChoiceScript’s pseudo-arrays.

3 Likes

That’s insane! I was just trying to figure out how to do some string manipulation last month and had to do a weird workaround. I’ll definitely be digging deeper into that library!

2 Likes

Cool. If you come up with new solutions yourself, contributions are always welcome.

3 Likes

I believe the solution was “it isn’t worth my time to reinvent the wheel just for a little one-off bit of narrative, so I’m going to figure out an easier way to accomplish something similar” haha

2 Likes

CSIDE isn’t recognising this as a command for some reason?

I’m not sure which version you’re using, but the online version recognizes the command.

Should be the latest, but I will try it out in the online CSIDE

If you prefere to work offline, you can try VS Code with the ChoiceScript plugin.

If I do not add the underscore in the variable names in the *if statements below line 18, it gives an error saying no such variable exists, but if I do add it, it doesn’t recognise it in the statement on line 11. If I don’t add it in line 11 and add it in the statements below 18, it starts repeating because the done being set to true isn’t the same as the done being checked in the *ifs below line 18 (???)

*temp dice1 0
*temp dice2 0
*temp_array done 66 false
*temp q_asked 0
*label gaa
You nod, throwing the dice on the table.

*label redice
*rand dice1 1 6
*rand dice2 1 6
*if (done[dice1 & dice2])
    *goto redice
*fake_choice 
    #Throw dice
    #End game
The first rolls to ${dice1} and second to ${dice2}. You check the book.

*if dice1 = 1 
    *if (dice2 = 1)
        *set q_asked +1
        *set done_1 true
    *elseif (dice2 = 2)
        *set q_asked +1
        *set done_2 true
    *elseif (dice2 = 3)
        *set q_asked +1
        *set done_3 true
    *elseif (dice2 = 4)
        *set q_asked +1
        *set done_4 true
    *elseif (dice2 = 5)
        *set q_asked +1
        *set done_5 true
    *elseif (dice2 = 6)
        *set q_asked +1
        *set done_6 true
*elseif dice1 = 2
    *if (dice2 = 1)
        *set done_7 true
        *set q_asked +1
    *elseif (dice2 = 2)
        *set done_8 true
        *set q_asked +1
    *elseif (dice2 = 3)
        *set done_9 true
        *set q_asked +1
    *elseif (dice2 = 4)
        *set done_10 true
        *set q_asked +1
    *elseif (dice2 = 5)
        *set done_11 true
        *set q_asked +1
    *elseif (dice2 = 6)
        *set done_12 true
        *set q_asked +1
*elseif dice1 = 3 
    *if (dice2 = 1)
        *set done_13 true
        *set q_asked +1
    *elseif (dice2 = 2)
        *set done_14 true
        *set q_asked +1
    *elseif (dice2 = 3)
        *set done_15 true
        *set q_asked +1
    *elseif (dice2 = 4)
        *set done_16 true
        *set q_asked +1
    *elseif (dice2 = 5)
        *set done_17 true
        *set q_asked +1
    *elseif (dice2 = 6)
        *set done_18 true
        *set q_asked +1
*elseif dice1 = 4 
    *if (dice2 = 1)
        *set done_19 true
        *set q_asked +1
    *elseif (dice2 = 2)
        *set done_20 true
        *set q_asked +1
    *elseif (dice2 = 3)
        *set done_21 true
        *set q_asked +1
    *elseif (dice2 = 4)
        *set done_22 true
        *set q_asked +1
    *elseif (dice2 = 5)
        *set done_23 true
        *set q_asked +1
    *elseif (dice2 = 6)
        *set done_24 true
        *set q_asked +1
*elseif dice1 = 5 
    *if (dice2 = 1)
        *set done_25 true
        *set q_asked +1
    *elseif (dice2 = 2)
        *set done_26 true
        *set q_asked +1
    *elseif (dice2 = 3)
        *set done_27 true
        *set q_asked +1
    *elseif (dice2 = 4)
        *set done_28 true
        *set q_asked +1
    *elseif (dice2 = 5)
        *set done_29 true
        *set q_asked +1
    *elseif (dice2 = 6)
        *set done_30 true
        *set q_asked +1
*elseif dice1 = 6  
    *if (dice2 = 1)
        *set done_31 true
        *set q_asked +1
    *elseif (dice2 = 2)
        *set done_32 true
        *set q_asked +1
    *elseif (dice2 = 3)
        *set done_33 true
        *set q_asked +1
    *elseif (dice2 = 4)
        *set done_34 true
        *set q_asked +1
    *elseif (dice2 = 5)
        *set done_35 true
        *set q_asked +1
    *elseif (dice2 = 6)
        *set done_36 true
        *set q_asked +1
*page_break
*if q_asked < 36
    *goto redice
*else 
    *ending

(Don’t mind the q_asked. I realise that it’s better to just write it as a single statement before page_break)