Skip to content

TASK: Add Inventory system (#65)#71

Open
ilmyang wants to merge 1 commit intoTheGittyPerson:mainfrom
ilmyang:feature/inventory-system
Open

TASK: Add Inventory system (#65)#71
ilmyang wants to merge 1 commit intoTheGittyPerson:mainfrom
ilmyang:feature/inventory-system

Conversation

@ilmyang
Copy link
Contributor

@ilmyang ilmyang commented Mar 24, 2026

Summary

This PR adds an inventory system to theperson .

Changes

Inventory system

  • Added a new inventory.py module with an Inventory class in theperson/
  • Added support for:
    • add_item
    • remove_item
    • clear
    • list_items
    • is_empty
  • Added extra inventory utilities:
    • has_item
    • get_quantity
    • is_full
    • remove_all
    • filter_items
    • sort_items
    • total_value

Inventory state/configuration

  • Added item_count as a state property
  • Added unique_item_types as an additional state property
  • Added max_capacity as a configuration value

Item module

  • Added a new item.py module with an Item base class in theperson/
  • Shared item attributes include:
    • name
    • value
    • stackable
  • Implemented the required item subclasses:
    • Food includes calories, cooked, and brand
    • Electronic includes brand and battery
    • Valuable
    • Weapon

Others

  • Person now initializes with an Inventory instance by default
  • Kept type hints and docstrings consistent with the existing codebase

Testing

Manually tested:

  • adding items
  • removing items
  • clearing the inventory
  • capacity limits
  • stackable vs non-stackable behavior
  • filtering and sorting
  • total value calculation

Test code can be provided if needed.

Notes

This implementation uses a hybrid inventory structure:

  • stackable items are stored with quantity tracking
  • non-stackable items are stored as individual instances

At this stage, I did not add extra methods for inventory operations, as the functionality is already accessible via person.inventory. This does not prevent such methods from being added later if needed.

For the same reason, person.py does not import Item directly, since it is not used there yet. I avoided adding an unused import or formality, especially to keep the code clean and pylint-compliant.

The current design is intentionally kept simple. Further improvements or more advanced features can be explored in future updates or separate issues.

Closes #65

@TheGittyPerson TheGittyPerson added enhancement New feature or request task This is a task issue / PR completing a task labels Mar 25, 2026
@TheGittyPerson TheGittyPerson self-requested a review March 25, 2026 12:07
Copy link
Owner

@TheGittyPerson TheGittyPerson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your PR! These are very well-written modules and I see no immediate errors or formatting issues. However here are just some small changes to error messages I recommend before I start analysing the code in more detail with some testing, which will take more time, so here are the minor fixes for now. (I didn't add comments in item.py as it's the same fixes)

Before we continue though, add a new Person object the_town.py (you can name it after yourself if you wish) that uses the Inventory class. In other words, create a Person instance and write some example code that shows how the Inventory methods and features are used in practice. I’ll also add some examples later, but since you’re currently more familiar with this new feature, I’d like you to create the initial demonstration first.

Thanks! Please do ask if you have any questions

ValueError: If max_capacity is negative.
"""
if not isinstance(max_capacity, int):
raise TypeError("max_capacity must be an integer.")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using periods in error messages (to stay consistent with the rest of the code). You should also put quotes around varibale names. So this could be:

f"'max_capacity' must be an integer, got type '{type(max_capacity)}' instead"

if not isinstance(max_capacity, int):
raise TypeError("max_capacity must be an integer.")
if max_capacity < 0:
raise ValueError("max_capacity must be non-negative.")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here — this could be:

f"'max_capacity' must be non-negative'"

ValueError: If adding the item exceeds max capacity.
"""
if not isinstance(item, Item):
raise TypeError("item must be an Item.")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"'item' must be an 'Item' object"

if not isinstance(item, Item):
raise TypeError("item must be an Item.")
if not isinstance(quantity, int):
raise TypeError("quantity must be an integer.")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"'quantity' must be an integer"

if not isinstance(quantity, int):
raise TypeError("quantity must be an integer.")
if quantity <= 0:
raise ValueError("Quantity must be positive.")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"'quantity' must be positive"

if quantity <= 0:
raise ValueError("Quantity must be positive.")
if self.item_count + quantity > self.max_capacity:
raise ValueError("Inventory capacity exceeded.")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just remove the period here

Comment on lines +87 to +97
raise TypeError("item must be an Item.")
if not isinstance(quantity, int):
raise TypeError("quantity must be an integer.")
if quantity <= 0:
raise ValueError("Quantity must be positive.")

if item.stackable:
if item not in self.stackable_items:
raise ValueError("Item not found in inventory.")
if self.stackable_items[item] < quantity:
raise ValueError("Not enough quantity to remove.")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here for these error messages

def __init__(
self,
name: str,
calories: int,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this could be optional?

self,
name: str,
calories: int,
cooked: bool = False,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allow None, as some food aren't meant to be cooked (like potato chips or coffee)

self.stackable_items.clear()
self.unique_items.clear()

def list_items(self) -> str:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say rename this to get_items, then make another method to print the list:

def list_items(self) -> None:
    print(self.get_items())

@ilmyang ilmyang force-pushed the feature/inventory-system branch from f64ccc2 to 93b5914 Compare March 26, 2026 03:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request task This is a task issue / PR completing a task

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TASK: Add Inventory system

2 participants