• Search is back up, but the index is being rebuilt, there may still be some minor problems until this is complete.

Ren'Py Problem: RevertableList object has no attribute 'image'

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,692
Hi,

I'm having a problem adding an object to the inventory; the object is added correctly but I get this error when I want to access the inventory:
'RevertableList' object has no attribute 'image'

This is my inventory code:
NOTE: Error occurs when processing the instruction: $ pic = item.image
Code:
screen inventory_screen:   
    add "gui/inventory.png"
    modal True
    imagebutton auto "nav/exit_inv_%s.webp" xpos 930 ypos 10 xalign 1.0 focus_mask True action [ Hide("inventory_screen")]


    $ x = 515
    $ y = 0
    $ i = 0
    $ sorted_items = sorted(inventory.items)
    $ next_inv_page = inv_page + 1           
    if next_inv_page > int(len(inventory.items)/9):
        $ next_inv_page = 0
    for item in sorted_items:
        if i+1 <= (inv_page+1)*9 and i+1>inv_page*9:
            $ x += 270
            if i%3==0:
                $ y += 235
                $ x = 515
            $ pic = item.image
            imagebutton idle pic hover pic xpos x+300 ypos y+110 action [Hide("gui_tooltip"), SetVariable("item", item), selectItem(item)] hovered [ Play ("sound", "sfx/click.wav") ] unhovered [Hide("gui_tooltip")] at inv_eff
            if item.selected:
                add "gui/selected.png" xpos x+200 ypos y+70 anchor(.5,.5)
                $ selitem = (item_use)
           
        $ i += 1
        if len(inventory.items)>9:
            textbutton _("Next Page") action [SetVariable('inv_page', next_inv_page), Show("inventory_screen")] xpos .475 ypos .83
It's an object (clothes) that has been added in the new update; and I do it with the following line:
Code:
default sportdress_2 = Item("sportdress_2", element="sportdress_2", image="shopfashion/items/sportdress_2_small_idle.png")
The image is defined but for some reason it gives me error :confused:

Do you know what this mistake can be due to and how to solve it?
Thanks in advance.


BTW, I remember that in another update I found that problem when I added a new object that was not present before... I solved it but right now I can't remember how :oops:
 
Last edited:

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,692
Ok, after some testing I have to say that the previous post code is correct.

The problem is the following...
The item (clothing) is purchased (added to the inventory) according to the player's selection. For that I use this code...
Define the variable:
Code:
default fashion_actual_dress = ""
The part where that variable changes according to the object (clothing) chosen:
Code:
imagebutton auto "shopfashion/items/sportdress_2_small_%s.png" focus_mask True action SetVariable("fashion_actual_dress", "sportdress_2"), SetVariable("fashion_actual_dress_price", 40), Show("fashion_big_dress_screen")
The instruction to add it to the inventory:
Code:
$ inventory.add([fashion_actual_dress])    ### This fails
If instead of using this instruction that adds the object to the inventory using the variable "fashion_actual_dress" I do it directly with the object works well...
Like:
Code:
$ inventory.add(sportdress_2)   ### This works
I think it may be the typical problem of adding or removing some character like "", () or [].

Any suggestions?
Thank you!
 

the66

beware, the germans are cumming
Modder
Donor
Respected User
Jan 27, 2017
7,667
23,782
these are not just some characters. o_O
you might want to check the Python documentation about data structures.


and your problem, you probably should create an item class and add your needed attributes and methods (name, prize, thumbnail or whatever and some methods to set or change these attributes).
create items that inherit from this class. these items can you add to your inventory and access their attributes or methods.
 
  • Like
Reactions: Porcus Dev

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,692
these are not just some characters. o_O
you might want to check the Python documentation about data structures.


and your problem, you probably should create an item class and add your needed attributes and methods (name, prize, thumbnail or whatever and some methods to set or change these attributes).
create items that inherit from this class. these items can you add to your inventory and access their attributes or methods.
Thanks!

Well, there is more code for all inventory control, but I have written the one I thought necessary, maybe I have forgotten something... but... doing tests, I see that the problem is that the variable "fashion_actual_dress" was text and not an object, so it was impossible for it to work.

I also use that variable to show one image or another according to the selection, so I need it... so I've tried the following...
Add a new variable for the inventory (an object) but linked to the variable that changes according to the selection of the player:
Code:
default fashion_actual_dress_inv = Item("[fashion_actual_dress]", element="[fashion_actual_dress]", image="shopfashion/items/[fashion_actual_dress]_small_idle.png")
Make it change as soon as the player selects one item of clothing or another:
Code:
imagebutton auto "shopfashion/items/sportdress_2_small_%s.png" focus_mask True action SetVariable('fashion_actual_dress_inv', sportdress_2), SetVariable("fashion_actual_dress", "sportdress_2"), SetVariable("fashion_actual_dress_price", 40), Show("fashion_big_dress_screen")
Doing that I can see that the new variable "fashion_actual_dress_inv" is now effectively an object, but it still gives me an error anyway... I guess the assigned characteristics (Item, element and image) don't change as they should.


Thanks in advance!
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,692
Iep!!! SOLVED :D:D:D:D:D

What I have commented just above worked... the only problem is that due to the many tests I had made, the part of the code in charge of adding the object to the inventory has wrong; I've only had to correct the following...

Change this:
Code:
$ inventory.add([fashion_actual_dress_inv])
To this:
Code:
$ inventory.add(fashion_actual_dress_inv)
Thanks for all ;)
 

the66

beware, the germans are cumming
Modder
Donor
Respected User
Jan 27, 2017
7,667
23,782
[fashion_actual_dress_inv] is a list with the object fashion_actual_dress_inv as sole member and ofc this list has no attribute image, only the actual object has it.
you might mix up a list definition a = [1, 2, 3] with Ren'Py's variable substitution text "[name]".
 
  • Like
Reactions: Porcus Dev

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,692
[fashion_actual_dress_inv] is a list with the object fashion_actual_dress_inv as sole member and ofc this list has no attribute image, only the actual object has it.
you might mix up a list definition a = [1, 2, 3] with Ren'Py's variable substitution text "[name]".
Could you give an example?

My previous solution is not practical because what is stored in the inventory is "fashion_actual_dress_inv"; and when I buy a second dress that variable changes, and in the inventory I will have two identical dresses, the first one that has changed the image when I buy the second one, and the second one o_O:ROFLMAO:

I was looking for a way to reduce code, but as I urgently need it to work to publish the new version... for now I will have to use something that works:
Code:
if fashion_actual_dress == "sportdress_1":
     $ inventory.add(sportdress_1)
if fashion_actual_dress == "sportdress_2":
     $ inventory.add(sportdress_2)
Evidently it's not the best option because this list will get bigger... but at the moment that's what I'm going to use :confused:

Thanks.
 

the66

beware, the germans are cumming
Modder
Donor
Respected User
Jan 27, 2017
7,667
23,782
i don't know your code for the items and the inventory but this here is an absolute minimalistic approach to have items, a list of them and an inventory:
Python:
init python:
    class Item(object):
        def __init__(self, name='', prize=0, image=''):
            self._name = name
            self._prize = prize
            self._image = '/images/items/' + image + '_%s.png'

    class Items(object):
        def __init__(self):
            self._list = []

        def add(self, item):
            self._list.append(item)

        def get(self):
            return self._list

    class Inventory(object):
        def __init__(self):
            self._list = []

        def add(self, item):
            self._list.append(item)

        def has(self, item):
            return item in self._list

        def get(self):
            return self._list

    class BuyItem(Action):
        def __init__(self, inv, item):
            self._inv = inv
            self._item = item

        def __call__(self):
            self._inv.add(self._item)
            renpy.restart_interaction()

define item1 = Item('Item1', 100, 'item1')
define item2 = Item('Item2', 50, 'item2')

default items = Items()
default inv = Inventory()

screen buy():
    vbox align (.5, .5):
        for item in items.get():
            imagebutton:
                auto item._image
                action BuyItem(inv, item)
                sensitive not inv.has(item)
        textbutton "Return":
            xalign .5
            action Return()

label start:
    python:
        items.add(item1)
        items.add(item2)
        renpy.call_screen('buy')
        for item in inv.get():
            renpy.say("", "[item._name]: [item._prize]€")
from here i would add other needed attributes like a counter for stackable items or methods like increase/decrease/remove items from the inventory.

the problem i see in your code is eg.
Python:
$ inventory.add([fashion_actual_dress_inv])
# the added inventory entry is a list
# you would have to access it with something like inventory.your_entry[0]

default fashion_actual_dress_inv = Item("[fashion_actual_dress]", element="[fashion_actual_dress]", image="shopfashion/items/[fashion_actual_dress]_small_idle.png")
imagebutton auto "shopfashion/items/sportdress_2_small_%s.png" focus_mask True action SetVariable('fashion_actual_dress_inv', sportdress_2), SetVariable("fashion_actual_dress", "sportdress_2"), SetVariable("fashion_actual_dress_price", 40), Show("fashion_big_dress_screen")
#1st you declare fashion_actual_dress_inv as an Item() object but later you overwrite it with the sportdress_2 object/variable
 
  • Love
Reactions: Porcus Dev

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,268
Code:
screen inventory_screen: 
    [...]
Since you found by yourself that you were adding a list containing the object, and not directly the object, I'll focus on the code you use to display the inventory :

Python:
screen inventory_screen: 
    [...]

    default startPos = 0
    $ y = 0
    $ x = 515

    # Only works with the [number of entries by page] entries starting at /startPos/.
    for item in sorted( inventory.items )[startPos:startPos+9]:
        if x >= 1055:  # 515 + ( 270 * 2 )
            $ y += 235
            $ x = 515
        else:
            $ x += 270

        $ pic = item.image
        imagebutton idle pic hover pic xpos x+300 ypos y+110 action [Hide("gui_tooltip"), SetVariable("item", item), selectItem(item)] hovered [ Play ("sound", "sfx/click.wav") ] unhovered [Hide("gui_tooltip")] at inv_eff
        if item.selected:
            add "gui/selected.png" xpos x+200 ypos y+70 anchor(.5,.5)
            #  What are you trying to do ?
            # "( variable, variable )" mean that you are creating a tuple.
            # But creating a tuple of only one value should be wrote
            # "( variable, )", else Ren'py will directly assign the value
            # without putting it in a tuple.
            #  Is it that you wanted to build a list of items to sell ?
            #  Anyway, what's the value of "item_use", it's define nowhere
            # in the screen, is it comming from /selectItem/ ? If yes, why
            # not doing this directly inside it ?
            $ selitem = (item_use)

    showif startPos > 0:
        # Starting pos, actual first entry - number of entries by page.
        textbutton _("Prev Page"):
             #  You don't need to show a screen already shown. Screens are automatically
             # updated by Ren'py.
             action SetScreenVariable('startPos', startPos - 9)
             # float ? You really want to place it as % of the actual size ?
             xpos .375 ypos .83    # arbitrary pos for x

    showif startPos < len( inventory.items ) + 9:
        # Starting pos, actual first entry + number of entries by page.
        textbutton _("Next Page")
             action SetScreenVariable('startPos', startPos + 9)
             xpos .475 ypos .83
You can even get ride of the computations if you decide to place the items in a . And solve the problem of selected items with a displayable.
Python:
screen inventory_screen:
    [...]

    default startPos = 0
  
    # 3 columns of 3 rows.
    grid 3 3:
        # Only works with the [number of entries by page] entries starting at /startPos/.
        for item in sorted( inventory.items )[startPos:startPos+9]:
            $ pic = item.image
            imagebutton:
                idle pic
                hover pic
                #  Arbitrary example. Build the in the fly "selected image".
                #  You can also create the /LiveComposite/ object directly
                # in the item object and have something like /item.selectedImage/.
                selected_idle LiveComposite( ( 154, 200 ),
                        ( 0, 0 ), Frame( pic, size=( 154, 200 ) ),
                        ( 0, 0 ), store.Frame( "gui/selected.png", size=( 154, 200 ) )
                #  Why not changing /selitem/ directly here ?
                #  Each time a new object will be selected, the value will change.
                # And your code weren't reverting its value to a null one if nothing
                # was selected, so it will change nothing.
                #  Still don't know what /item_use/ have as value.
                action [Hide("gui_tooltip"), SetVariable("item", item), selectItem(item), SetVariable( "selitem", item_use)]
                hovered [ Play ("sound", "sfx/click.wav") ]
                # Really not sure of this one, what are you trying to achieve ?
                unhovered [Hide("gui_tooltip")] at inv_eff

                #  Alternate code if what you wanted was to build a list of
                # items to sell.
#                action [Hide("gui_tooltip"),
#                           SetVariable("item", item),
#                           selectItem(item),
                           #  If the item is on the list of item to sell, a click mean
                           # "remove it". Else a click mean "add it"
#                           If( item_use in selitem, RemoveFromSet( "selitem", item_use ), AddToSet( "selitem", item_use ) )]
                #  If the item is in the list of items to sell, then it's selected.
#                selected item in selitem


    showif startPos > 0:
        # Starting pos, actual first entry - number of entries by page
        textbutton _("Prev Page"):
             # You don't need to show a screen already shown. Screens are automatically
             # updated by Ren'py
             action SetScreenVariable('startPos', startPos - 9)
             # float ? You really want to place it as % of the actual size ?
             xpos .375 ypos .83    # arbitrary pos for x

    showif startPos < len( inventory.items ) + 9:
        # Starting pos, actual first entry + number of entries by page
        textbutton _("Next Page")
             action SetScreenVariable('startPos', startPos + 9)
             xpos .475 ypos .83
and , if you're interested in the alternate code.


My previous solution is not practical because what is stored in the inventory is "fashion_actual_dress_inv"; and when I buy a second dress that variable changes, and in the inventory I will have two identical dresses, the first one that has changed the image when I buy the second one, and the second one o_O:ROFLMAO:
If the list was of text, you could do something like this :
Python:
#  Iterate all the entries of /inventory/, and for each one, if it starts with
# the value passed as parameter, we add it to the list that we will return.
define inventoryHas = lambda x: [ i for i in inventory if i.startswith( x ) ]

label whatever:
    # If an entry match, then remove it from the list before...
    if inventoryHas( "sportdress" ):
        #  Note that /inventoryHas/ return a list. And the list can
        # only have one entry since the purpose is to prevent duplicated
        # entries. So, what you want to remove is the first entry of the
        # returned list.
        $ inventory.remove( inventoryHas( "sportdress" )[0] )
   # Add the new entry to the list.
   $ inventory.add( sportdress_1 )
But the list is a list of objects... Therefore you have to change a little your item object. Since I don't know your object, I'll present you the meta method, and make it return the name of the item, instead of the usual <class "whatever" object at 0x...>.
Here's a small example of use :
Code:
init python:
    class Item( object ):
        def __init__( self, what ):
            self.what = what
        def __repr__( self ):
            return self.what

default inventory = [ Item( "sportdress_1" ), Item( "something else" ), Item( "nothing" ) ]
#  Note: Now we works with the text representation of the object, not its direct value.
define inventoryHas = lambda x: [ i for i in inventory if str( i ).startswith( x ) ]

label start:

    if not inventoryHas( "sportdress" ):
        "do not have dress"
    else:
        "Already have dress"

    if not inventoryHas( "sportsuit" ):
        "do not have suit"
    else:
        "Already have suit"
Note that, by using this, you can have more generic substitutions. You can by example decide that there can be only one dress in the inventory, whatever the kind of dress :
Python:
init python:
    class Item( object ):
        def __init__( self, what, kind ):
            self.what = what
            self.kind = kind
# No need of __repr__ now that we have an attribute to directly address.

default inventory = [ Item( "sportdress_1", "dress" ), Item( "something else", "crap" ), Item( "nothing", "void" ) ]
#  Note: We have an attribute to rely on, we test it directly. 
# And like it's a dedicated value, we can test it's entire value.
define inventoryHas = lambda x: [ i for i in inventory if i.kind == x ]

label whatever:
    # Did it have a dress ?
    if inventoryHas( "dress" ):
        # Yes, a sport one, so we remove it before...
        $ inventory.remove( inventoryHas( "dress" )[0] )
   # Add the floral dress to the list.
   $ inventory.add( floraldress_2 )
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,692
i don't know your code for the items and the inventory but this here is an absolute minimalistic approach to have items, a list of them and an inventory:
Python:
init python:
    class Item(object):
        def __init__(self, name='', prize=0, image=''):
            self._name = name
            self._prize = prize
            self._image = '/images/items/' + image + '_%s.png'

    class Items(object):
        def __init__(self):
            self._list = []

        def add(self, item):
            self._list.append(item)

        def get(self):
            return self._list

    class Inventory(object):
        def __init__(self):
            self._list = []

        def add(self, item):
            self._list.append(item)

        def has(self, item):
            return item in self._list

        def get(self):
            return self._list

    class BuyItem(Action):
        def __init__(self, inv, item):
            self._inv = inv
            self._item = item

        def __call__(self):
            self._inv.add(self._item)
            renpy.restart_interaction()

define item1 = Item('Item1', 100, 'item1')
define item2 = Item('Item2', 50, 'item2')

default items = Items()
default inv = Inventory()

screen buy():
    vbox align (.5, .5):
        for item in items.get():
            imagebutton:
                auto item._image
                action BuyItem(inv, item)
                sensitive not inv.has(item)
        textbutton "Return":
            xalign .5
            action Return()

label start:
    python:
        items.add(item1)
        items.add(item2)
        renpy.call_screen('buy')
        for item in inv.get():
            renpy.say("", "[item._name]: [item._prize]€")
from here i would add other needed attributes like a counter for stackable items or methods like increase/decrease/remove items from the inventory.

the problem i see in your code is eg.
Python:
$ inventory.add([fashion_actual_dress_inv])
# the added inventory entry is a list
# you would have to access it with something like inventory.your_entry[0]

default fashion_actual_dress_inv = Item("[fashion_actual_dress]", element="[fashion_actual_dress]", image="shopfashion/items/[fashion_actual_dress]_small_idle.png")
imagebutton auto "shopfashion/items/sportdress_2_small_%s.png" focus_mask True action SetVariable('fashion_actual_dress_inv', sportdress_2), SetVariable("fashion_actual_dress", "sportdress_2"), SetVariable("fashion_actual_dress_price", 40), Show("fashion_big_dress_screen")
#1st you declare fashion_actual_dress_inv as an Item() object but later you overwrite it with the sportdress_2 object/variable
Thank you very much for the example, I will study it as soon as I can ... now, unfortunately, because I have to publish the new version as soon as possible, I am forced to use the code that works, so for now I will use this:
Code:
if fashion_actual_dress == "sportdress_1":
     $ inventory.add(sportdress_1)
if fashion_actual_dress == "sportdress_2":
     $ inventory.add(sportdress_2)
The complete code I use for inventory is here:
https://f95zone.to/threads/doubt-with-renpy-inventory-system.18518/page-2#post-2010081


Thanks a lot! ;)
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,692
Since you found by yourself that you were adding a list containing the object, and not directly the object, I'll focus on the code you use to display the inventory :

Python:
screen inventory_screen:
    [...]

    default startPos = 0
    $ y = 0
    $ x = 515

    # Only works with the [number of entries by page] entries starting at /startPos/.
    for item in sorted( inventory.items )[startPos:startPos+9]:
        if x >= 1055:  # 515 + ( 270 * 2 )
            $ y += 235
            $ x = 515
        else:
            $ x += 270

        $ pic = item.image
        imagebutton idle pic hover pic xpos x+300 ypos y+110 action [Hide("gui_tooltip"), SetVariable("item", item), selectItem(item)] hovered [ Play ("sound", "sfx/click.wav") ] unhovered [Hide("gui_tooltip")] at inv_eff
        if item.selected:
            add "gui/selected.png" xpos x+200 ypos y+70 anchor(.5,.5)
            #  What are you trying to do ?
            # "( variable, variable )" mean that you are creating a tuple.
            # But creating a tuple of only one value should be wrote
            # "( variable, )", else Ren'py will directly assign the value
            # without putting it in a tuple.
            #  Is it that you wanted to build a list of items to sell ?
            #  Anyway, what's the value of "item_use", it's define nowhere
            # in the screen, is it comming from /selectItem/ ? If yes, why
            # not doing this directly inside it ?
            $ selitem = (item_use)

    showif startPos > 0:
        # Starting pos, actual first entry - number of entries by page.
        textbutton _("Prev Page"):
             #  You don't need to show a screen already shown. Screens are automatically
             # updated by Ren'py.
             action SetScreenVariable('startPos', startPos - 9)
             # float ? You really want to place it as % of the actual size ?
             xpos .375 ypos .83    # arbitrary pos for x

    showif startPos < len( inventory.items ) + 9:
        # Starting pos, actual first entry + number of entries by page.
        textbutton _("Next Page")
             action SetScreenVariable('startPos', startPos + 9)
             xpos .475 ypos .83
You can even get ride of the computations if you decide to place the items in a . And solve the problem of selected items with a displayable.
Python:
screen inventory_screen:
    [...]

    default startPos = 0
 
    # 3 columns of 3 rows.
    grid 3 3:
        # Only works with the [number of entries by page] entries starting at /startPos/.
        for item in sorted( inventory.items )[startPos:startPos+9]:
            $ pic = item.image
            imagebutton:
                idle pic
                hover pic
                #  Arbitrary example. Build the in the fly "selected image".
                #  You can also create the /LiveComposite/ object directly
                # in the item object and have something like /item.selectedImage/.
                selected_idle LiveComposite( ( 154, 200 ),
                        ( 0, 0 ), Frame( pic, size=( 154, 200 ) ),
                        ( 0, 0 ), store.Frame( "gui/selected.png", size=( 154, 200 ) )
                #  Why not changing /selitem/ directly here ?
                #  Each time a new object will be selected, the value will change.
                # And your code weren't reverting its value to a null one if nothing
                # was selected, so it will change nothing.
                #  Still don't know what /item_use/ have as value.
                action [Hide("gui_tooltip"), SetVariable("item", item), selectItem(item), SetVariable( "selitem", item_use)]
                hovered [ Play ("sound", "sfx/click.wav") ]
                # Really not sure of this one, what are you trying to achieve ?
                unhovered [Hide("gui_tooltip")] at inv_eff

                #  Alternate code if what you wanted was to build a list of
                # items to sell.
#                action [Hide("gui_tooltip"),
#                           SetVariable("item", item),
#                           selectItem(item),
                           #  If the item is on the list of item to sell, a click mean
                           # "remove it". Else a click mean "add it"
#                           If( item_use in selitem, RemoveFromSet( "selitem", item_use ), AddToSet( "selitem", item_use ) )]
                #  If the item is in the list of items to sell, then it's selected.
#                selected item in selitem


    showif startPos > 0:
        # Starting pos, actual first entry - number of entries by page
        textbutton _("Prev Page"):
             # You don't need to show a screen already shown. Screens are automatically
             # updated by Ren'py
             action SetScreenVariable('startPos', startPos - 9)
             # float ? You really want to place it as % of the actual size ?
             xpos .375 ypos .83    # arbitrary pos for x

    showif startPos < len( inventory.items ) + 9:
        # Starting pos, actual first entry + number of entries by page
        textbutton _("Next Page")
             action SetScreenVariable('startPos', startPos + 9)
             xpos .475 ypos .83
and , if you're interested in the alternate code.




If the list was of text, you could do something like this :
Python:
#  Iterate all the entries of /inventory/, and for each one, if it starts with
# the value passed as parameter, we add it to the list that we will return.
define inventoryHas = lambda x: [ i for i in inventory if i.startswith( x ) ]

label whatever:
    # If an entry match, then remove it from the list before...
    if inventoryHas( "sportdress" ):
        #  Note that /inventoryHas/ return a list. And the list can
        # only have one entry since the purpose is to prevent duplicated
        # entries. So, what you want to remove is the first entry of the
        # returned list.
        $ inventory.remove( inventoryHas( "sportdress" )[0] )
   # Add the new entry to the list.
   $ inventory.add( sportdress_1 )
But the list is a list of objects... Therefore you have to change a little your item object. Since I don't know your object, I'll present you the meta method, and make it return the name of the item, instead of the usual <class "whatever" object at 0x...>.
Here's a small example of use :
Code:
init python:
    class Item( object ):
        def __init__( self, what ):
            self.what = what
        def __repr__( self ):
            return self.what

default inventory = [ Item( "sportdress_1" ), Item( "something else" ), Item( "nothing" ) ]
#  Note: Now we works with the text representation of the object, not its direct value.
define inventoryHas = lambda x: [ i for i in inventory if str( i ).startswith( x ) ]

label start:

    if not inventoryHas( "sportdress" ):
        "do not have dress"
    else:
        "Already have dress"

    if not inventoryHas( "sportsuit" ):
        "do not have suit"
    else:
        "Already have suit"
Note that, by using this, you can have more generic substitutions. You can by example decide that there can be only one dress in the inventory, whatever the kind of dress :
Python:
init python:
    class Item( object ):
        def __init__( self, what, kind ):
            self.what = what
            self.kind = kind
# No need of __repr__ now that we have an attribute to directly address.

default inventory = [ Item( "sportdress_1", "dress" ), Item( "something else", "crap" ), Item( "nothing", "void" ) ]
#  Note: We have an attribute to rely on, we test it directly.
# And like it's a dedicated value, we can test it's entire value.
define inventoryHas = lambda x: [ i for i in inventory if i.kind == x ]

label whatever:
    # Did it have a dress ?
    if inventoryHas( "dress" ):
        # Yes, a sport one, so we remove it before...
        $ inventory.remove( inventoryHas( "dress" )[0] )
   # Add the floral dress to the list.
   $ inventory.add( floraldress_2 )
Fuck! I will need a lot of time to read, understand and put all this into practice, LOL :ROFLMAO::ROFLMAO::ROFLMAO:;)(y)

As I said, I now need a system that works and I can't risk changing the code too much... but obviously I want to improve it, optimize it, and learn something along the way :p
So for now I will release the new version with a less optimized code but that works (I already checked) and I will take into account everything you say to make changes in the next version (although to be honest, it's not going to be easy to understand everything ... my only programming experience before starting to create the game was a course of BASIC many years ago, hahahaha)

Thanks a lot! ;)
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,268
(although to be honest, it's not going to be easy to understand everything ... my only programming experience before starting to create the game was a course of BASIC many years ago, hahahaha)
That's why I gave example totally unrelated to your own code. This way you can practice more easily with it, and take your time to understand it.
 
  • Like
Reactions: Porcus Dev