Source code for quest.contrib.inventory

from quest.contrib.removable import RemovableMixin
from quest.contrib.submodal import SubmodalMixin, CLOSE_SUBMODAL
from quest.modal import Modal
from collections import Counter
import arcade

[docs]class InventoryMixin(RemovableMixin): """A mixin for QuestGame which provides an inventory. Pick up and drop behavior can be implemented in a very simple way because `RemovableMixin` provides most of what we need. Also creates an `InventoryModal` and binds a key to open it (by default, 'i'). Attributes: inventory_shortcut: A key which should open the inventory. """ inventory_shortcut = arcade.key.I def __init__(self): super().__init__() self.inventory_modal = InventoryModal(self, self.inventory())
[docs] def inventory(self): "A helper to return the inventory" return self.removed_sprite_lists['inventory']
[docs] def pick_up(self, sprite): """Removes a sprite from the game and adds it to the inventory. """ self.remove_sprite_from_game(sprite, "inventory")
[docs] def drop(self, sprite): """Removes a sprite from the inventory and adds it to the game. Moves the sprite to the player's position and sets its `dropped_by` property to the player (to make sure it doesn't immediately get picked up). """ self.add_sprite_to_game(sprite) sprite.recently_dropped = True sprite.center_x = self.player.center_x sprite.center_y = self.player.center_y
[docs] def on_key_press(self, key, modifier): """Overrides `on_key_press` so that when the inventory shortcut key is pressed, opens the inventory. Otherwise, delegates to the parent `on_key_press` method. """ if key == self.inventory_shortcut: self.open_modal(self.inventory_modal) else: super().on_key_press(key, modifier)
[docs]class InventoryItemMixin: """A mixin for QuestSprite which allows it to behave as an inventory item. Attributes: detailed_description (str): A more detailed description. dropped_by (QuestSprite): Keeps track of whether the sprite was recently dropped. usable (bool): Indicates whether the item can be used. """ detailed_description = "An inventory item" recently_dropped = False usable = False droppable = True
[docs] def on_update(self, game): """When this sprite has recently been dropped, checks to see whether the dropped (probably the player) is still colliding. If not, sets `self.dropped_by` to None, indicating that the sprite can be picked up again. """ if self.recently_dropped: if not self.collides_with_sprite(game.player): self.recently_dropped = False
[docs] def on_collision(self, sprite, game): """Causes the sprite to be picked up, unless it was just dropped. """ if sprite == game.player and not self.recently_dropped: game.pick_up(self)
[docs] def use(self, game): """What should happen when used. By default, kills the item. """ self.kill()
[docs]class InventoryModal(SubmodalMixin, Modal): """An extension of Modal which interaacts with inventories. """ welcome_message = "Your inventory:" close_modal_option = "OK" def __init__(self, game, inventory): self.inventory = inventory super().__init__(game)
[docs] def text_label_contents(self): return [self.welcome_message]
[docs] def option_label_contents(self): labels = [] for description in self.unique_item_descriptions(): count = self.count_items_with_description(description) labels.append("{} ({})".format(description, count)) labels.append(self.close_modal_option) return labels
[docs] def choose_option(self, value): choice = self.option_label_contents()[value] if choice == self.close_modal_option: self.game.close_modal() else: description = self.unique_item_descriptions()[value] item = self.get_item_with_description(description) self.open_submodal(self.get_detail_modal(item))
def get_detail_modal(self, item): count = self.count_items_with_description(item.description) return InventoryItemModal(self.game, item, count) def get_item_with_description(self, description): for item in self.inventory: if item.description == description: return item def unique_item_descriptions(self): return sorted(set([item.description for item in self.inventory])) def count_items_with_description(self, description): return len([item for item in self.inventory if item.description == description])
[docs]class InventoryItemModal(SubmodalMixin, Modal): """A modal for interacting with an inventory item. """ name = "inventory item modal" use_option = "use" drop_option = "drop" close_modal_option = "back" def __init__(self, game, item, count): self.item = item self.count = count super().__init__(game)
[docs] def text_label_contents(self): return [ "{} ({})".format(self.item.description, self.count), self.item.detailed_description ]
[docs] def option_label_contents(self): verbs = [] if self.item.usable: verbs.append(self.use_option) if self.item.droppable: verbs.append(self.drop_option) verbs.append(self.close_modal_option) return verbs
[docs] def choose_option(self, value): verb = self.option_label_contents()[value] if verb == self.drop_option: self.game.drop(self.item) elif verb == self.use_option: self.item.use(self.game) self.close()