Ren'Py How to pick a specific item in the list?

iSleepZZZ

New Member
Aug 10, 2022
14
4
Hi guys, once again I'm back with more question as somewhat renpy noob.
As the title says, how do I pick a specific item in the list?

Here's the simplified version of my code:
Python:
init python:
    class item:
        def __init__(self, name, image):
            self.name = "{}".format(name)
            self.image = "images/{}.png".format(image)

default all_item = [item("Apple", "apple"), item("Orange", "orange")]
default backpack = []
default page = 1
# Basic set up for the item class

label AA_test: # Get the game running
    scene black
    $ backpack.append(all_item[0])
    $ backpack.append(all_item[0])
    $ backpack.append(all_item[1])
    $ backpack.append(all_item[1])
    $ backpack.append(all_item[1])
    # Get items

    $ d = 1

    show screen backpack_display
    while d > 0:
        "testing"

screen backpack_display:
    if page == 1:
        hbox:
            xalign 0.5
            yalign 0.5

            for backpack[0] in backpack: # The 1st item in backpack
            frame:
                imagebutton:
                    idle item.image
                    action SetVariable ("Something", "not important")
       
            for backpack[1] in backpack: # The 2nd item in backpack
            frame:
                imagebutton:
                    idle item.image
                    action SetVariable ("Something", "not important")
       
            for backpack[2] in backpack: # The 3rd item in backpack
            frame:
                imagebutton:
                    idle item.image
                    action SetVariable ("Something", "not important")
           
    elif page == 2:
        hbox:
            xalign 0.5
            yalign 0.5

            for backpack[3] in backpack: # The 4th item in backpack
            frame:
                imagebutton:
                    idle item.image
                    action SetVariable ("Something", "not important")
       
            for backpack[4] in backpack: #The 5th item in backpack
            frame:
                imagebutton:
                    idle item.image
                    action SetVariable ("Something", "not important")
       
            for backpack[5] in backpack: # The 6th item in backpack
            frame:
                imagebutton:
                    idle item.image
                    action SetVariable ("Something", "not important")
I set up other button to change pages so don't worry about it. The problem is the "for backpack[0] in backpack" doesn't work as I expected. It crashes the game, but somehow "$ backpack.append(all_item[0])" works:LOL:. Since the items are going to be added to the backpack in random order, how can I pick each item in order and put them in different page of the backpack_display?

Also, since I haven't got the first part to be working, I'm not sure if the game will crash when there's not enough item in the backpack to fill the space on the display screen.

Thank you very much.
 

Winterfire

Conversation Conqueror
Respected User
Game Developer
Sep 27, 2018
6,265
9,001
I woke up from a wild dream involving Count Morado to show you this video: which you may find useful (old but gold) to learn for loop.

When you have a list of items, and you need to find a specific item without knowing the order, you use a for loop to look for an element of said item. Typically that's an ID or the name of the item. Your items don't have an ID, so you'll probably want to compare the names instead (not ideal, also prone to error):

for i in inventory:
if "nameItem" == i.name - Return (function breaks here)
 
  • Like
Reactions: iSleepZZZ

iSleepZZZ

New Member
Aug 10, 2022
14
4
Thank you. I have studied the video but it's not the thing I'm looking for....
When you have a list of items, and you need to find a specific item without knowing the order....
It's quite the opposite, I know the order but I don't need to know what that item is. I want the item to be put in it's place by the order it's added to the backpack, not based on what the item is.

Edit:

The major problem I have is this:
Python:
for backpack[0] in backpack: # The 1st item in backpack
    frame:
        imagebutton:
        idle item.image
        action SetVariable ("Something", "not important")
      
for backpack[1] in backpack: # The 2nd item in backpack
    frame:
        imagebutton:
        idle item.image
        action SetVariable ("Something", "not important")
I'm not able to call the item out by it's order that is added to the backpack.
 

Winterfire

Conversation Conqueror
Respected User
Game Developer
Sep 27, 2018
6,265
9,001
Thank you. I have studied the video but it's not the thing I'm looking for....

It's quite the opposite, I know the order but I don't need to know what that item is. I want the item to be put in it's place by the order it's added to the backpack, not based on what the item is.

Edit:

The major problem I have is this:
Python:
for backpack[0] in backpack: # The 1st item in backpack
    frame:
        imagebutton:
        idle item.image
        action SetVariable ("Something", "not important")
     
for backpack[1] in backpack: # The 2nd item in backpack
    frame:
        imagebutton:
        idle item.image
        action SetVariable ("Something", "not important")
I'm not able to call the item out by it's order that is added to the backpack.
I am sorry, but I am not sure if I understood correctly. So, you want to put an item in a specific place in the list? In that case, instead of append(), you use insert(). That allows you to insert an item anywhere in the list without overwriting any item that may reside in that index.
 

iSleepZZZ

New Member
Aug 10, 2022
14
4
Well, the problem is when I run the game, it crashes and says:
Code:
File "game/test_script/AA_test.rpy", line 31: expected 'in' not found.
    for backpack[0] in backpack:
What I want to do is that: During the game, the player will get many random items, which will be added to the backpack list with use of append(). And then I use the backpack_display screen to show the item the player got.
Since the space to show items on the screen is limited, I need to put the items on different pages on the backpack_display screen.
Say the backpack is limited to 3 slot, My logic is: Item 1, 2, 3 goes to page 1, Item 4, 5, 6 goes to page 2, etc.
So it doesn't matter what item does the player get, the first item in the backpack list always goes to slot 1. And I need to know how to call the item by it's order on a screen as a imagebutton (for other actions)

Thank you for your patience, I know I'm bad at coding.:cry:
 

Winterfire

Conversation Conqueror
Respected User
Game Developer
Sep 27, 2018
6,265
9,001
The issue is that you're using for loop wrong. You cannot loop by using "backpack[0]", here's a written tutorial in case the video wasn't clear enough:
 
  • Like
Reactions: anne O'nymous

iSleepZZZ

New Member
Aug 10, 2022
14
4
So I guess I should not be using for loop in this situation. Thank you, I will look for another way to call the list item.
 

Winterfire

Conversation Conqueror
Respected User
Game Developer
Sep 27, 2018
6,265
9,001
So I guess I should not be using for loop in this situation. Thank you, I will look for another way to call the list item.
If you only need to call an item with a known index, then no, you don't need a for loop for that.
You could simply do print(backpack[index]) ex. print(backpack[0]) to get the first element in the list, 1 for the second, and 2 for the third.

If you need to loop a list, you need to use a temp int, example:
for i in backpack

which will loop from 0, all the way to the max value of backpack.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
12,510
20,246
The problem is the "for backpack[0] in backpack" doesn't work as I expected.
And this for a really good reason.

for variable in list: ask Python to loop for all values in the list, with each loop feeling the variable with the next value.

what you want is :
Python:
            frame:
                imagebutton:
                    idle backpack[0].image
                    action SetVariable ("Something", "not important")

            frame:
                imagebutton:
                    idle backpack[1].image
                    action SetVariable ("Something", "not important")
    [...]
You address the entry in the backpack list by it's index (the [x]), what will automatically give you access to the object stored a this index. This mean that you can also directly access to the attribute of this object.

Therefore, you can simplify your screen:

/!\ Wrote on the fly, there's possibly typos /!\
Python:
screen backpack_display():   # The () is important, it permit to optimize your screen.

    default page = 0

    vbox:
        hbox:
            xalign 0.5
            yalign 0.5

            #  /range(x, y)/ create a list staring by x and ending right before y
            # So here: [0, 1, 2] for the first page, then [3, 4, 5] for the second, and so on.
            for idx in range( 0 + ( page * 3),  3 + (page * 3) ) :
                #  You'll not always have a number of object that is a multiple of 3. So you
                # need to ensure that there's a value.
                if len( backpack ) > idx:
                    frame:
                        imagebutton:
                            idle backpack[idx].image
                            action SetVariable ("Something", "not important")
                # For a clean visual, fill with empty entries for the emply slots.
                else:
                    frame:
                        add "images/empty_slots.png"
     
        hbox:
            textbutton "prev":
                sensitive not page == 0  # Only sensitive if it's not the first page
                SetScreenVariable( "page", page - 1 )
            textbutton "newt":
                # Only sensitive if it's not the last page. Normally the computation is correct.
                sensitive not page == int( len( backpack ) /  3 ) if len( backpack ) % 3 else int( len( backpack ) /  3 ) - 1
                SetScreenVariable( "page", page + 1 )
 

iSleepZZZ

New Member
Aug 10, 2022
14
4
Thank you very much. I'm able print the elements in the list onto my screen now.

But... there's another problem now...
If the player gets fewer item than the total space inside the side, the game crash again with:

Code:
IndexError: list index out of range
I tried to fix it with a if statement but somehow the game just seen to ignore it:

Python:
# Say there's only two item in the backpack this time.

screen backpack_display:
    if page == 1:
        hbox:
            xalign 0.5
            yalign 0.5
            spacing 10
           
            #slot 1
            frame:
                imagebutton:
                    idle backpack[0].image
           
            #slot 2
            if len(backpack) > 1:
                imagebutton:
                    idle backpack[1].image
            #slot 3
            if len(backpack) > 2:
                imagebutton:
                    idle backpack[2].image
I use len(backpack) to count the total number of item in the backpack list. The game should've ignore the extra slot when there's not enough item, but still it tells me that the list index is out of range...

Edit:
Sorry anne O'nymous, I just saw your reply. I will try it out now.