Python Text RPG
-Inventory-
In today's sprint I was changing gears to let some ideas ruminate about the Maps and organization problem. So I started tackling items and an inventory system. You can see the use example at the bottom of the article.
Sprint method: For my sprints I set a block of time to work and when it expires that's what I have for the day.
class Item():
# class variable:gentype = "consumable"
subtype = "potion"
variant_type = "elixir"
name_ = "elixir of healing"
desc = "restores () health over () seconds"
value = 5 #recomended value; value assigned per shop
stack_size = 1
quantity = 1
weight_class = 0#, 1, 2, 3, 4 # none, light, medium, heavy, very heavy
visable = True
def __init__( self, name:str, qty:int, stack:int=1, **keywargs ):
# instance variable:
# Info
self.gentype = "general category".lower()
self.subtype = "local category".lower()
self.variant_type = "specific category".lower()
self.name_ = str( name ).lower()
self.description = "does things".lower()
# Inventory
self.stack_size = stack
self.quantity = qty if qty <= stack else stack
self.weight_class = 0#, 1, 2, 3, 4 # none, light, medium, heavy, very heavy
# Shop
self.value = 5 #recomended value; value assigned per shop
self.visable = True
def __str__( self ):
return f"{ self.name().title() }: { self.qty()[0] }/{ self.stack() }"
def __repr__( self ):
return f"{ self.name() }: { self.qty()[0] }/{ self.stack() }"
# Public facing calls to set and get object string variables.
def gen_type( self, new_gentype:str=None ) -> str:
return self._set_string( "gentype", new_gentype )
def sub_type( self, new_subtype:str=None ) -> str:
return self._set_string( "subtype", new_subtype )
def type( self, new_type:str=None ) -> str:
return self._set_string( "variant_type", new_type )
def name( self, new_name:str=None ) -> str:
return self._set_string( "name_", new_name )
def desc( self, new_desc:str=None ) -> str:
return self._set_string( "description", new_desc )
# The utility function for setting string variables
def _set_string( self, attr, string ):
if string:
setattr(self, attr, str( string ).lower() )
return getattr( self, attr )
# Public facing calls to set and get object boolean variables.
def show( self, new_state=None ):
return self._toggle_bool( "visable", new_state )
# The utility function for setting boolean variables
def _toggle_bool( self, attr, state ):
if None != state:
setattr( self, attr, state )
return getattr( self, attr )
# Public facing calls to set and get object numeric variables.
def price( self, new_price:int=None ) -> int:
return self._set_digit( "value", new_price )
def weight( self, new_weight:int=None ) -> int:
return self._set_digit( "weight_class", new_weight )
def stack( self, new_stack:int=None ) -> int:
return self._set_digit( "stack_size", new_stack )
def qty( self, new_qty:int=None ) -> ( int, int ):
remainder = 0
if not new_qty: pass
elif 1 < ( new_qty / self.stack() ):
remainder = new_qty - self.stack()
new_qty = self.stack()
return self._set_digit( "quantity", new_qty ), remainder
# The utility function for setting numeric variables
def _set_digit( self, attr:str, number:int ) -> int:
if str( number ).isdigit():
setattr( self, attr, number )
return getattr( self, attr )
# Get the current capacity for the item stack
def capacity( self ) -> int:
out = self.stack_size - self.quantity
return out if out <= self.stack_size else 0
class Container():
items = []
size = 3
# width x height ala diablo
def __init__( self, size:int ):
self.items = []
self.size = size
def item( self, item:Item=None ) -> Item or [ Item ]:
"""Takes in an item; If successful returns added item. If failed returns held items."""
out = self.items
if item:
self._add_item( item )
out = item
return out
def remove_item( self, item:Item ) -> bool:
out = False
if 1 not in self._validate_insert( item ):
self.items.pop( self.items.index( item ) )
out = True
return out
def _full( self ) -> int:
return self.size - len( self.items )
def _contains_obj( self, item:Item ) -> bool:
return item in self.items
def _contains_name( self, item:Item ) -> bool:
return item.name() in ''.join( str( self.items ) )
def _validate_insert( self, item:Item ) -> { int, str }:
"""returns a dictionary of { outcome_code : note, } "0, and -4 to -6" are invalid insertions. -2 to -3 denote the insertion is a duplicate. Return value of 1 indicates item is not present."""
out = { }
if not item:
out.update( { 0 : "empty argument" } )
if Item is not type(item):
out.update( { -6 : "not an item" } )
if 0 >= self._full():
out.update( { -5 : "inventory full" } )
if 0 >= item.stack():
out.update( { -4 : "empty item stack" } )
if self._contains_obj( item ):
out.update( { -3 : "item duplicate" } )
if self._contains_name( item ):
out.update( { -2 : "name duplicate" } )
else:
out.update( { 1 : 'valid insert' } )
return out
def _add_item( self, item:Item ) -> bool:
out = False
if 1 == list( self._validate_insert( item ) )[0]:
self.items.append( item )
out = True
return out
def _item_to_index( self, item:Item ) -> [ int ] or None:
out = None
catch = self._validate_insert( item )
if -3 in catch:
# Index of objects matches
out = self.items.index( i )
if -2 in catch:
# Index of Items with name matches
out = [self.items.index( i ) for i in self.items if item.name() == i.name() ]
return out
def _index_to_item( self, index:int) -> Item:
return self.items[ index ]
def _qty( self, item:Item, new_qty:int=None ) -> Item:
out = item
catch = self._validate_insert( item )
if -2 in catch:
# Case: item name exists in list
index = self._item_to_index( item )[0]
held_item = self._index_to_item(index)
# add the current qty to the new qty and return the remainder
updated_stock = held_item.qty( held_item.qty()[0] + item.qty()[0] )[1]
catch = item.qty( updated_stock )
out = item
return out
# USE EXAMPLE:
# Change the bag size to exclude items below
inv = Container( 6 )
# Try it yourself: Item( name, qty, stack_size )
# 'Pickup' various items until inventory is full
inv.item( Item( "health potion", 1 ) ) # 1
inv.item( Item( "raw steak flank", 1 ) ) # 2
inv.item( Item( "rusty sword", 1 ) ) # 3
inv.item( Item( "mirror shield", 1 ) ) # 4
inv.item( Item( "iron greaves", 1 ) ) # 5
ps = Item( "platinum sword", 1, 4 ) #6
inv.item( ps )
#---- Inventory at capacity
inv.item( Item( "obsidian helm", 1 ) ) #7
inv.item( Item( "golden armor", 1 ) ) #8
print( inv.item( ) )
print()
# Use Scenario: top off an item you already have from one in a locker
world_item = Item( "platinum sword", 4, 4 ) # Item in the locker
# world_item = inv._qty( world_item ) # finding similar item in inventory and stacking to full
print( inv._qty( world_item ) ) # show new qty for locker item
print( inv.item( ) )
No comments:
Post a Comment
Conduct: Be nice and don't advertise or plug without adding value to the conversation.