[SOLVED] Trying to create a simple math minigame. Strange list index out of range error?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Message
Author
User avatar
LiveTurkey
Regular
Posts: 109
Joined: Tue Dec 27, 2016 10:50 pm
Location: Brooklyn
Contact:

[SOLVED] Trying to create a simple math minigame. Strange list index out of range error?

#1 Post by LiveTurkey »

Hey guys. I came back to working on my game after taking a year long hiatus so I'm super rusty on how everything works from screens to variable and so on.

I'm trying to create a simple chess inspired math minigame. The minigame works by showing the player a few random chess pieces with math equations in between and the player has to solve it using the point values of chess. For example, it could show Queen Plus Rook Times knight which would translate to 9 + 5 x 3 which equals 24.

I'm still stuck at the beginning. Here is what I have so far.

Code: Select all


label chessMinigame:
    
    $ get_chess_piece()
    jump expression location

init 2 python:

    def get_chess_piece():

        chess_pieces_list = [
            "King"
            "Queen"
            "Rook"
            "Bishop"
            "Knight"
            "Pawn"
        ]

        r1 = renpy.random.randint(0, 5)

        x = ("tempItems/" + chess_pieces_list[r1] + ".png")

        Show(x);


    def get_math_sign():

        math_signs_list = [
            "x"
            "/"
            "+"
            "-"
        ]

        r2 = renpy.random.randint(0, 3)

        x = ("tempItems/" + math_signs_list[r1] + ".png")

It is giving me a list index out of range error which doesn't make a lot of sense to me.
Last edited by LiveTurkey on Fri Jul 13, 2018 11:43 am, edited 2 times in total.

User avatar
MaydohMaydoh
Regular
Posts: 165
Joined: Mon Jul 09, 2018 5:49 am
Projects: Fuwa Fuwa Panic
Tumblr: maydohmaydoh
Location: The Satellite of Love
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#2 Post by MaydohMaydoh »

You need to put a comma between each item in the lists to separate them like,

Code: Select all

math_signs_list = [
	"x",
	"/",
	"+",
	"-"
]

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#3 Post by Remix »

Might also suggest

var = renpy.random.choice( the_list_var ) or renpy.random.choice( [ 'x', '-', '+', '/' ] ) rather than randint used as index
Frameworks & Scriptlets:

User avatar
LiveTurkey
Regular
Posts: 109
Joined: Tue Dec 27, 2016 10:50 pm
Location: Brooklyn
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#4 Post by LiveTurkey »

MaydohMaydoh wrote: Thu Jul 12, 2018 1:54 pm You need to put a comma between each item in the lists to separate them like,

Code: Select all

math_signs_list = [
	"x",
	"/",
	"+",
	"-"
]
Remix wrote: Thu Jul 12, 2018 3:19 pm Might also suggest

var = renpy.random.choice( the_list_var ) or renpy.random.choice( [ 'x', '-', '+', '/' ] ) rather than randint used as index

Thanks for all the help guys.

Here is the updated code

Code: Select all

init 2 python:

    def get_chess_piece():

        chess_pieces_list = [
            "King",
            "Queen",
            "Rook",
            "Bishop",
            "Knight",
            "Pawn"
        ]

        math_signs_list = [
            "Multiply",
            "Divide",
            "Add",
            "Subtract",
            "Equals",
            "Question"
        ]

        renpy.show (renpy.random.choice(chess_pieces_list), at_list=[Position(xpos = .1, ypos = .5 )])
        renpy.show (renpy.random.choice(math_signs_list), at_list=[Position(xpos = .2, ypos = .5 )])
        renpy.show (renpy.random.choice(chess_pieces_list), at_list=[Position(xpos = .3, ypos = .5 )])
        renpy.show (renpy.random.choice(math_signs_list), at_list=[Position(xpos = .4, ypos = .5 )])
        renpy.show (renpy.random.choice(chess_pieces_list), at_list=[Position(xpos = .5, ypos = .5 )])
        renpy.show (math_signs_list[4], at_list=[Position(xpos = .6, ypos = .5 )])
        renpy.show (math_signs_list[5], at_list=[Position(xpos = .7, ypos = .5 )])

It almost works. 90% of the time it works perfectly but 10% of the time for some reason either a math sign is missing or a chess piece is missing. I'll attach an image.

My hypothesis is that pieces go missing when the game tries to use the same piece twice like rook plus rook or king plus queen plus rook. Notice either the two rooks or the two additions. The reason I think this is because it has never shows me two of the same pieces or math signs in the same equation. So I'm assuming that when it tries to do that, thats how I get the blanks. It's like it removes the element from the list after using it which is very strange since absolutley nothing in the code implies that. Does anyone know why this is happening?

Image



Also, is there any way to retrieve what the random.choice was since I need to know to calculate what the correct answer is? Should I go back to using the ints as a way to index it since I would know which piece/math sign was used by checking what the int number is.

User avatar
MaydohMaydoh
Regular
Posts: 165
Joined: Mon Jul 09, 2018 5:49 am
Projects: Fuwa Fuwa Panic
Tumblr: maydohmaydoh
Location: The Satellite of Love
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#5 Post by MaydohMaydoh »

Might be an idea like in Remix's example to put each renpy.random.choice into a variable before showing it. As for displaying the same image twice, you need to give them a tag to allow for it to be shown more than once, so it should look something like the following.

Code: Select all

chess1 = renpy.random.choice(chess_pieces_list)
math1 = renpy.random.choice(math_signs_list)
chess2 = renpy.random.choice(chess_pieces_list)
math2 = renpy.random.choice(math_signs_list)
chess3 = renpy.random.choice(chess_pieces_list)

renpy.show (chess1, at_list=[Position(xpos = .1, ypos = .5 )], tag="chess1")
renpy.show (math1, at_list=[Position(xpos = .2, ypos = .5 )], tag="math1")
renpy.show (chess2, at_list=[Position(xpos = .3, ypos = .5 )], tag="chess2")
renpy.show (math2, at_list=[Position(xpos = .4, ypos = .5 )], tag="math2")
renpy.show (chess3, at_list=[Position(xpos = .5, ypos = .5 )], tag="chess3")
At least I think that's how it's supposed to work..

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#6 Post by Remix »

var = renpy.random.choice( the_list_var ) sets the choice to the variable var

Your image problem is basically due to using renpy.show with the same image... it's just moving it rather than showing two.

I would suggest using a screen and build the equation just in a hbox or layed out however (gets around the tag issue too as it is not using show)

Code: Select all

screen math_test():
    default pieces = [ renpy.random.choice(chess_pieces_list) for k in range(3) ]
    default signs = [ renpy.random.choice(math_signs_list) for k in range(2) ] 
    hbox:
        add pieces[0]
        add signs[0]
        add pieces[1]
        add signs[1]
        add pieces[2]
        add "Equals"
Frameworks & Scriptlets:

User avatar
LiveTurkey
Regular
Posts: 109
Joined: Tue Dec 27, 2016 10:50 pm
Location: Brooklyn
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#7 Post by LiveTurkey »

Here is what I have now

Code: Select all

label playChessBoard:
    $ speaker = "bethany"
    $ hideScreens()
    p "Let's D-D-D-Duel"
    jump chessMinigame

screen math_test():

    $ chess_pieces_list = ["King","Queen","Rook","Bishop","Knight","Pawn"]
    
    $ chess_pieces_values = ["10","9","5","3","3","1"]
    
    $ math_signs_list = ["Multiply","Divide","Add","Subtract","Equals","Question"]

    $ math_signs = [ '*', '/', '+', '-' ]

    default pieces = [ renpy.random.choice(chess_pieces_list) for k in range(3) ]
    default signs = [ renpy.random.choice(math_signs_list) for k in range(2) ]

    hbox:
        add pieces[0]
        add signs[0]
        add pieces[1]
        add signs[1]
        add pieces[2]
        add "Equals"

    $ import parser

    $ formula = "" + pieces[0] + signs[0] + pieces[1] + signs[1] + pieces[2]

    $ answer = parser.expr(formula).compile()

    $ chess_answer_list = []

    $ chess_answer_list.append(answer, True)
    $ chess_answer_list.append(answer + renpy.random.randint(0, 5), False)
    $ chess_answer_list.append(answer - renpy.random.randint(0, 5), False)
    $ chess_answer_list.append(answer + renpy.random.randint(0, 5), False)
    $ chess_answer_list.append(answer - renpy.random.randint(0, 5), False)

    $ user_chess_answer = menu(chess_answer_list)

label chessMinigame:
    
    show countdown at Position(xalign=.1, yalign=.1)
    
    $ ui.timer(5.0, ui.jumps("slow"))
    
    show math_test()
    $ renpy.pause()

    if user_chess_answer:
        show expression ( speaker + " happy")
        $ renpy.say(getattr(store, speaker[0]), "Right answer")
    else:
        show expression ( speaker + " disgusted")
        $ renpy.say (getattr(store, speaker[0]), "Wrong answer")

    $ speaker = "noOne"
    jump expression location

label slow:
        hide countdown
        "You're too slow."

init:
    python:

        def countdown(st, at, length=0.0):

            remaining = length - st

            if remaining > 2.0:
                return Text("%.1f" % remaining, color="#fff", size=72), .1
            elif remaining > 0.0:
                return Text("%.1f" % remaining, color="#f00", size=72), .1
            else:
                return anim.Blink(Text("0.0", color="#f00", size=72)), None

    image countdown = DynamicDisplayable(countdown, length=5.0)
I think it is almost done. The math_test screen doesn't show. It shows not found girl outline again.

Is the rest of my code right? I can't really test it since the screen is not showing. I want the player to have X amount of seconds to choose an answer.

I used this link https://stackoverflow.com/questions/594 ... -in-pythonfor the conversion of math equation into number. Will it work with renpy?

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#8 Post by Remix »

It likely isn't finding the images if they are not defined

image king = Image( 'images/king.png' ) should allow a screen to use something like "add king" or "add expression somefunc()"

I've not got any similar images to play with for testing so, unless you want to zip/attach yours, you might have to just experiment getting one of them to show.

I'd personally (as you are compiling the calculation yourself) just use eval on the built string rather than importing parser...
$ result = renpy.python.py_eval( "9+3*5" ) ## >> 24

Note: Random logic dictates you will sometimes get decimal results 9+3/5 >> 9.6 though you should not get division by zero at least. Just do not expect all results to be integers.
Frameworks & Scriptlets:

User avatar
LiveTurkey
Regular
Posts: 109
Joined: Tue Dec 27, 2016 10:50 pm
Location: Brooklyn
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#9 Post by LiveTurkey »

Remix wrote: Thu Jul 12, 2018 6:31 pm It likely isn't finding the images if they are not defined

image king = Image( 'images/king.png' ) should allow a screen to use something like "add king" or "add expression somefunc()"

I've not got any similar images to play with for testing so, unless you want to zip/attach yours, you might have to just experiment getting one of them to show.

I'd personally (as you are compiling the calculation yourself) just use eval on the built string rather than importing parser...
$ result = renpy.python.py_eval( "9+3*5" ) ## >> 24

Note: Random logic dictates you will sometimes get decimal results 9+3/5 >> 9.6 though you should not get division by zero at least. Just do not expect all results to be integers.

I figure out the problem, at least one of them lol.

I was writing

Code: Select all

    show math_test() 
Where I need to write

Code: Select all

 show screen math_test()
Also append only takes one variable but that was an easy fix.

Now I get this error message which I can't parse at all.

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/minigames.rpy", line 28, in script
    p "Let's D-D-D-Duel"
  File "game/screens.rpy", line 219, in execute
    screen choice(items):
  File "game/screens.rpy", line 219, in execute
    screen choice(items):
  File "game/screens.rpy", line 223, in execute
    window:
  File "game/screens.rpy", line 229, in execute
    vbox:
  File "game/screens.rpy", line 233, in execute
    for i in items:
  File "game/screens.rpy", line 234, in execute
    textbutton i.caption action i.action xalign 0.5
Exception: Cannot display <code object <module> at 04ADBF50, file "<syntax-tree>", line 1> as text.
I'm assuming it has something to do with the timer, specifically the

Code: Select all

    show countdown at Position(xalign=.1, yalign=.1)
line.

Also to get the answer I think I have to do something like this

Code: Select all

    $ answer = renpy.python.py_eval( chess_pieces_values[chess_pieces_list.index[pieces[0]]] + math_signs[math_signs_list.index[signs[0]]] + chess_pieces_values[chess_pieces_list.index[pieces[1]]] + math_signs[math_signs_list.index[signs[1]]] + chess_pieces_values[chess_pieces_list.index[pieces[2]]] )  ## >> 24
but it gives me an error

Code: Select all

TypeError: 'builtin_function_or_method' object has no attribute '__getitem__'


User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#10 Post by Remix »

Do not use
menu(chess_answer_list)
That would try to call a renpy menu which expects properly configured MenuItems which you'd best avoid until you know exactly what info each one holds.

I'd suggest just adding textbuttons to the screen and give each an action relative to their correctness

$ answer = renpy.python.py_eval( "".join( [
chess_pieces_values[chess_pieces_list.index[pieces[0]]],
math_signs[math_signs_list.index[signs[0]]],
chess_pieces_values[chess_pieces_list.index[pieces[1]]],
math_signs[math_signs_list.index[signs[1]]],
chess_pieces_values[chess_pieces_list.index[pieces[2]]] ] ) )
... maybe (got to make it a string for eval)
Frameworks & Scriptlets:

User avatar
LiveTurkey
Regular
Posts: 109
Joined: Tue Dec 27, 2016 10:50 pm
Location: Brooklyn
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#11 Post by LiveTurkey »

I think I almost got it

Code: Select all

default chess_answer_list =[]

default chess_pieces_list = ["King","Queen","Rook","Bishop","Knight","Pawn"]

default chess_pieces_values = ["10","9","5","3","3","1"]

default math_signs_list = ["Multiply","Divide","Add","Subtract","Equals","Question"]

default math_signs = [ '*', '/', '+', '-' ]

default pieces = []

default signs = []

screen chessBoardOptions:
    imagebutton:
        idle "backgrounds/transparent.png"
        action [Hide ("chessBoardOptions") ]
            
    imagebutton:                             
        idle "boxes/playChessG.png"
        hover "boxes/playChessH.png"
        action [Hide ("chessBoardOptions"), Jump("play"+itemClickedOn)]
        xpos 460
        ypos 890
        
    imagebutton:                             
        idle "boxes/investigateG.png"
        hover "boxes/investigateH.png"
        action [Hide ("chessBoardOptions"), Jump ("investigate" +itemClickedOn)]
        xpos 1060
        ypos 890

label investigateChessBoard:
    $ hideScreens()
    p "It's a board made of Chess."
    jump expression location

label playChessBoard:
    $ speaker = "bethany"
    p "Let's D-D-D-Duel"
    
    $ hideScreens()

    show countdown at Position(xalign=.1, yalign=.1)
    
    $ ui.timer(5.0, ui.jumps("slow"))

    show screen math_test()

    $ pieces = [ renpy.random.choice(chess_pieces_list) for k in range(3) ]
    
    $ signs = [ renpy.random.choice(math_signs_list) for k in range(2) ]

    $ chess_answer = 50
    #$ chess_answer = renpy.python.py_eval( "".join( [
    #    chess_pieces_values[chess_pieces_list.index[pieces[0]]],
    #    math_signs[math_signs_list.index[signs[0]]],
    #    chess_pieces_values[chess_pieces_list.index[pieces[1]]],
    #    math_signs[math_signs_list.index[signs[1]]],
    #    chess_pieces_values[chess_pieces_list.index[pieces[2]]] ] ) )

    $ generate_random_menu(chess_answer)
    $ user_answer = menu(chess_answer_list)
    
    $ renpy.hide_screen("math_test")

    if user_answer:
        show expression ( speaker + " happy")
        $ renpy.say(getattr(store, speaker[0]), "Right answer")
    else:
        show expression ( speaker + " disgusted")
        $ renpy.say (getattr(store, speaker[0]), "Wrong answer")
    
    $ speaker = "noOne"
    jump expression location


label slow:
    $ renpy.hide_screen("math_test")
    hide countdown
    "You're too slow."
    $ speaker = "noOne"
    jump expression location

screen math_test():

    hbox:
        add pieces[0]
        add signs[0]
        add pieces[1]
        add signs[1]
        add pieces[2]
        add "Equals"

init 2 python:

    def generate_random_menu(correct_value):

        global chess_answer_list

        chess_answer_list.append( (str(correct_value), True))
        chess_answer_list.append( (str(correct_value + renpy.random.randint(0, 5)), False))
        chess_answer_list.append( (str(correct_value - renpy.random.randint(0, 5)), False))
        chess_answer_list.append( (str(correct_value + renpy.random.randint(0, 5)), False))
        chess_answer_list.append( (str(correct_value - renpy.random.randint(0, 5)), False))

This works perfectly except for the line I commented out.

Code: Select all

$ chess_answer = renpy.python.py_eval( "".join( [
        chess_pieces_values[chess_pieces_list.index[pieces[0]]],
        math_signs[math_signs_list.index[signs[0]]],
        chess_pieces_values[chess_pieces_list.index[pieces[1]]],
        math_signs[math_signs_list.index[signs[1]]],
        chess_pieces_values[chess_pieces_list.index[pieces[2]]] ] ) )
That gives me the getItem error again.

I don't understand it should work. Let's say pieces[0] = "Rook". Then chess_pieces_list.index["Rook"] = 2. Then chess_pieces_values [2] = "9". Even if I wrap the correct parts with int(). It still doesn't work. I suspect the problem is chess_pieces_list.index["Rook"]

User avatar
MaydohMaydoh
Regular
Posts: 165
Joined: Mon Jul 09, 2018 5:49 am
Projects: Fuwa Fuwa Panic
Tumblr: maydohmaydoh
Location: The Satellite of Love
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#12 Post by MaydohMaydoh »

Think the index method for list should use parenthesis

Code: Select all

chess_pieces_values[ chess_pieces_list.index( pieces[ 0 ] ) ]

User avatar
LiveTurkey
Regular
Posts: 109
Joined: Tue Dec 27, 2016 10:50 pm
Location: Brooklyn
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#13 Post by LiveTurkey »

MaydohMaydoh wrote: Thu Jul 12, 2018 9:59 pm Think the index method for list should use parenthesis

Code: Select all

chess_pieces_values[ chess_pieces_list.index( pieces[ 0 ] ) ]
Yes!!!!!!!!!!!!! That fixed it.

User avatar
LiveTurkey
Regular
Posts: 109
Joined: Tue Dec 27, 2016 10:50 pm
Location: Brooklyn
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#14 Post by LiveTurkey »

I'm trying to make sure there are no repeat answers.

Code: Select all

chess_answer_list.append( (str(correct_value), True))

        while len(chess_answer_list) < 4:
            modifier = renpy.random.randint(1, 7)
            if ((correct_value + modifier) not in chess_answer_list): 
                chess_answer_list.append( (str(correct_value + modifier), False))
            modifier = renpy.random.randint(1, 7)
            if ((correct_value - modifier) not in chess_answer_list): 
                chess_answer_list.append( (str(correct_value - modifier), False))
It looks like it should work but it doesn't. What am I missing here?

Doing

Code: Select all

            if (str(correct_value + modifier)) not in chess_answer_list): 
Doesn't fix it either.

User avatar
MaydohMaydoh
Regular
Posts: 165
Joined: Mon Jul 09, 2018 5:49 am
Projects: Fuwa Fuwa Panic
Tumblr: maydohmaydoh
Location: The Satellite of Love
Contact:

Re: Trying to create a simple math minigame. Strange list index out of range error?

#15 Post by MaydohMaydoh »

Need add "False" to the if statement too as you're searching for a tuple in the list and not a single value.

Code: Select all

if ( ( (correct_value + modifier), False) not in chess_answer_list)

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot], Majestic-12 [Bot]