How Do I Use Class Objects As Dict Values?

Don’t laugh but I’m making an RPG and currently I have the character class set up like this… and keep in mind I’m just setting things up so this is just a debugging setup. You’ll see that I’m not very good at Python but also that I’m trying to use dictionaries inside of the e_roster class. And when I use e_w_ProgKnife I’m trying to use an instance of the armory class which has all the data for the e_w_ProgKnife. But whenever I debug this the console gives me like the memory ID or whatever and tells me that I list indices have to be ints not strings. Is it possible to setup my classes this way?

class e_roster:
    
    TP_multi = 1.6
    zeal_multi = 1.3
    mobility_multi = 1.3
    tactics_multi = 1.2
    e_initiative = 1
    e_activity = 3 
    
    
    def __init__(self, name = 'Hobo', level = 1, profession = 'Hobo', clout = 'I said Hobo', TP = 120, zeal = 4, mobility = 2, tactics = 1, gifts = ['Warm Blood'], curses = ['Poverty'], skills = ['Bum Rush'], equipment = {
'head' : 'Skull Cap',
'body' : 'Soiled Thermals',
'waist' : 'Oversized Synthetic Belt',
'legs' : 'Soiled Long Johns',
'feet' : 'Mismatched Boots',
'main hand' : e_w_ProgKnife,
'off hand' : 'Shiv',
'charm1' : 'Faith Ornament',
'charm2' : 'Ancient Phone',
'charm3' : 'Ketogenic Cookbook',
'charm4' : 'Empty Walnuts Can',
'pack' : 'Elementary Book Bag',
'main hand alt' : '1 Round Revolver[]2Handed',
'off hand alt' : 'Fist'
   
}, TPturn = {}, TPmods = {}, zealmods = {}, mobilitymods = {}, tacticsmods = {}, stealthbase = 0
):
        
        
        
        self.name = name
        self.level = level
        self.profession = profession
        self.clout = clout
        self.TP = TP
        self.zeal = zeal
        self.mobility = mobility
        self.tactics = tactics
        self.gifts = gifts
        self.curses = curses
        self.skills = skills
        self.equipment = equipment
        self.TPturn = TPturn      
        self.TPmods = TPmods      
        self.zealmods = zealmods      
        self.mobilitymods = mobilitymods      
        self.tacticsmods = tacticsmods
        self.stealthbase = stealthbase      
        
        
        
        
    def weapon_swap(self):
        print('Before: \n ' + str(self.equipment))
        swapper_list = []
        swapper_list.append(self.equipment['main hand'])    
        swapper_list.append(self.equipment['off hand'])
        self.equipment['main hand'] = self.equipment['main hand alt']    
        self.equipment['off hand'] = self.equipment['off hand alt']
        self.equipment['main hand alt'] = swapper_list[0]
        self.equipment['off hand alt'] = swapper_list[1]
        print('After: \n' + str(self.equipment))
    
    def e_proc(self, skill):
        print(self.name + ' uses ' + skill.name + ' with these Tags: ' + str(skill.tags) + '\n' + self.name + ' has the Gifts: ' + str(self.gifts) + '.\n' + skill.name + ' has Base Damage of ' + str(skill.base_damage) + '\n'  + self.name + ' is equipped with ' + str(self.equipment['main hand']) + ' which has a base damage of ' + 'not working')

you need thing() you create a new instant of class thing:

at which time thing.__init__() runs

i am also working on a RPG (on and off) and here is one of my test that tries to accomplice the same thing that your example is.

(this example use class inheritance)

#----------------------------------------------------
# license goes here
#----------------------------------------------------
#
# description goes here
# (c) whatever
#----------------------------------------------------
from random import *
import time, hashlib
import json
import base64

#----------------------------------------------------
# function description goes here
#----------------------------------------------------
def genhash(val="default"):
    gen = hashlib.md5(val.encode('utf-8'))
    return gen.hexdigest()

def genkey():
    combined = str( time.time() ) + str( randrange(1,10000) )
    generated_id = hashlib.md5(combined.encode('utf-8'))
    return generated_id.hexdigest()
#----------------------------------------------------
# function description goes here
#----------------------------------------------------
def encode(key, clear):
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc).encode()).decode()

def encrypt(data):
    key = encode(genkey(),"iMKjw5LCp8KewpXChMKPV1TCpMOVwpLDmMOWW2vCg8K0UsKYwprCl1fCnVZqYmddwoTChsOYwpHDhsKeVm7")[:42]
    return key+encode(key,data)

def decrypt(data):
    key = data[:42]
    return decode(key,data[42:])
#----------------------------------------------------
# function description goes here
#----------------------------------------------------
def decode(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc).decode()
    for i in range(len(enc)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)



#----------------------------------------------------
# class description goes here
#----------------------------------------------------
class basicContainer:
    
    def __init__(self):
        self.name = "container"
        self.items = {}
        
        super().__init__()
        
    
    def __getitem__(self, key):
        return getattr(self, key)
    
    def __setitem__(self, key, value):
        setattr(self, key, value)
    
    def __len__(self):
        return len(self.items)
    
    def __iter__(self):
        for key in self.items:
            yield self.items[key]
        return self
    
    def add(self,item):
        if hasattr(item,"key"):
            self.items[item["key"]] = item
        else:
            self.items[genkey()] = item

    def remove(self,item):
        if hasattr(item,"key"):
            if item["key"] in self.items:
                outobj = self.items[item["key"]]
                del self.items[item["key"]]
                return outobj
        else:
            for key in self.items.keys():
                if item == self.items[key]:
                    outobj = self.items[key]
                    del self.items[key]
                    return outobj
                
        if hasattr(item,"name"):
            print("ERROR :",item.name,"Not in",self.name)
        else:
            print("ERROR : Item Not in",self.name)
            
        return None



#----------------------------------------------------
# class description goes here
#----------------------------------------------------
class Characterlist(basicContainer):
    
    def __init__(self, **kw):
        super().__init__()
        
        for arg in kw:
            if arg in vars(self):
                self[arg] = kw[arg]
                
    def gettingOlder(self,value = 1):
        for character in self.items.values():
            character.stats["age"] += value



#----------------------------------------------------
# class description goes here
#----------------------------------------------------
class AI:

    def __init__(self):
        self.state = None
        
        super().__init__()
        
     
    def AI_update(self):
        return self.state



#----------------------------------------------------
# class description goes here
#----------------------------------------------------     
class Loot:
    def __init__(self):
        self.loot = {} #  {"Bone":{"stats":{"dmg":4,"attack":8}}}
        
        super().__init__()
        
    def genLootFromTable(self,count=2,table=None):
        if table:
            tmp = []
            out = []
            
            for item in table:
               itm = table[item]
               t = [ item ] * itm
               tmp += t
            
            for c in range(count):
                out += [choice(tmp)]
            
            return out

        
#----------------------------------------------------
# class description goes here
#----------------------------------------------------
class GameObject:

    def __init__(self):
        self.key = genkey()
        self.name = "noname"
                
        super().__init__()
        
        
    def __getitem__(self, key):
        return getattr(self, key)
    
    def __setitem__(self, key, value):
        setattr(self, key, value)



#----------------------------------------------------
# class description goes here
#----------------------------------------------------
class Stats:

    def __init__(self,**kw):
        self.stats ={}
        super().__init__()

            
#----------------------------------------------------
# class description goes here
#----------------------------------------------------
class Critter(GameObject,Stats,AI,Loot):
    
    default ={"age":1,
            "race":"unknown",
            "level":1,
            "mana":10,
            "health":10,
            "armor":10,
            "attack":10,
            "dmg":10,
            "strength":10,
            "demo":None}
    
    def __init__(self,**kw):
        super().__init__()
        
        self.stats.update(Critter.default)
        
        for arg in kw:
            if arg in vars(self):
                if type(kw[arg]) == dict:
                    self[arg].update(kw[arg])
                else:
                    self[arg] = kw[arg] 
    
    def update(self):
        print( self.stats["race"], self.name, self.AI_update() )
                
                

#----------------------------------------------------
#
# Default Data for Monsters
#
#----------------------------------------------------
critters = {}
critters["Orc"]    = {"loot":{"axe":{"stats":{"dmg":14,"attack":8}}},"stats":{"race":"Orc" , "health":50 , "attack":15 , "dmg":12 , "armor": 7 , "strength" :15 } }
critters["Kobold"] = {"stats":{"age":1 ,"race":"Kobold" , "health":30 , "attack":14 , "dmg":13 , "armor": 8 , "strength" : 8 } }
critters["Kitten"] = {"stats":{"age":1 ,"race":"Kitten" , "health":40 , "attack":18 , "dmg":15 , "armor":10 , "strength" :20 }, "state" : "sleeping"}
critters["Spider"] = {"stats":{"age":1 ,"race":"Spider" , "health":34 , "attack":12 , "dmg":15 , "armor":11 , "strength" :15 } }

namelist = ["bob","fred","carla","sofie","lars","boba fett","lisa","sonja"]

table = {"Bone":5,"Sword":10,"Rock":5,"Staff":15,"Gun":15,"Stick":15,"Cup":15,"Vase":3,"Pipe":15,"Pot":5}

defaultstats = {}
defaultstats["Bone"] = {"dmg":5,"durability":8,"speed":4}
defaultstats["Sword"] = {"dmg":15,"durability":8,"speed":4}
defaultstats["Rock"] = {"dmg":6,"durability":8,"speed":4}
defaultstats["Staff"] = {"dmg":7,"durability":8,"speed":4}
defaultstats["Gun"] = {"dmg":25,"durability":8,"speed":4}
defaultstats["Stick"] = {"dmg":5,"durability":8,"speed":4}
defaultstats["Cup"] = {"dmg":1,"durability":8,"speed":4}
defaultstats["Vase"] = {"dmg":2,"durability":8,"speed":4}
defaultstats["Pipe"] = {"dmg":16,"durability":8,"speed":4}
defaultstats["Pot"] = {"dmg":3,"durability":8,"speed":4}


#----------------------------------------------------
# start of execution
#----------------------------------------------------

critterlist = list(critters)

characterlist = Characterlist( name = "Characterlist" )

for name in namelist:
    data = critters[choice(critterlist)]
    data["name"] = name
    characterlist.add(Critter(**data))
   

print("number of characters in",characterlist.name,len(characterlist))
print("-----------------------------------------------\n")

characterlist.gettingOlder(99)


for character in characterlist:
    character.update()
    lootlist = character.genLootFromTable(4,table)
    
    for loot in lootlist:
        tmp = {}
        tmp[loot]={}
        tmp[loot]["stats"] = defaultstats[loot]
        
        character.loot.update(tmp)
        
    print( character.genLootFromTable(4,table) )


clist = {}
print("-----------------------------------------------\n")
for character in characterlist:
    clist[character["key"]] = vars(character)
    print(vars(character))
print("-----------------------------------------------\n")
print(encode(genhash("pass"),json.dumps(clist)),"\n-----------------------------------------------")

I already have that. I just didn’t show it because it’s a part of the armory class, not the e_roster class

Be careful with your default arguments:
https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments

Well I think my problem is that I am trying to pass class info from a separate Armory class into the separate Characters class. Instead, it would make better since to make the Characters class inherit weapon information from the Armory class. In other words instead of Characters reaching to the side for weapon info, the Weapons should send their info down to the Characters. Guess I gotta try it. Cuz there don’t seem to be any simple answers anywhere.

If you talking about doing something like

class Character(Armory):
    ...

Then I would say that this is not the best design approach.

When you inherit, you might ask yourself: “is a Character an Armory”?

In this case it sounds like the answer is: “no, a Character has different pieces of Armory”, which indicates composition.

Then maybe I just didn’t understand what you said, but I know that it is often better to favor composition rather than inheritance, unless applicable.

Yes a character is an armory.

Since hash (“dict”) keys, AFAIK, are only strings, a good strategy when you need to relate one thing to another using a hash is to create some kind of synthetic key, or “nonce.” In other words, an arbitrary random string. (A base-class’s constructor is a good place to do this.) Even a short random string will be good enough because you can be confident that it will never be duplicated.

Functionally, this is like a “primary key” in a database. Its value should “mean” nothing at all, but should uniquely identify the object.

Now, anywhere you need to put “a reference to the other thing” (although it is not “a reference” in the classical sense), you use its nonce. (If you like, you can use a single master dict to translate a nonce to a reference to the corresponding object, and the aforementioned base-class constructor/destructor can handle that chore, too.)

Because nonces aren’t true “references,” they can also make life easier for the memory-manager and avoid “leaks.” But you need to have to know what you’re doing and have code to clean-up the nonce uses, or be prepared to handle the case when a nonce has become stale.

I figured it out

Ok? Are you able to explain a bit more? :slight_smile:

What do you want to get in your class?

Do you want python objects you can directly work with, or do you want strings that can be used (e.g. as search criteria).?