"""Open and close commands for containers.""" from mudlib.commands import CommandDefinition, register from mudlib.container import Container from mudlib.player import Player from mudlib.targeting import find_in_inventory, find_thing_on_tile from mudlib.thing import Thing from mudlib.zone import Zone def _find_container(name: str, player: Player) -> Container | Thing | None: """Find a thing by name in inventory first, then on ground. Uses targeting module for prefix matching and ordinal support. Returns Thing if found (caller must check if it's a Container). Returns None if not found. """ # Check inventory first result = find_in_inventory(name, player) if result is not None: return result # Check ground at player's position zone = player.location if zone is None or not isinstance(zone, Zone): return None return find_thing_on_tile(name, zone, player.x, player.y) async def cmd_open(player: Player, args: str) -> None: """Open a container.""" if not args.strip(): await player.send("Open what?\r\n") return thing = _find_container(args.strip(), player) if thing is None: await player.send("You don't see that here.\r\n") return if not isinstance(thing, Container): await player.send("You can't open that.\r\n") return if not thing.closed: await player.send("It's already open.\r\n") return if thing.locked: await player.send("It's locked.\r\n") return thing.closed = False await player.send(f"You open the {thing.name}.\r\n") async def cmd_close(player: Player, args: str) -> None: """Close a container.""" if not args.strip(): await player.send("Close what?\r\n") return thing = _find_container(args.strip(), player) if thing is None: await player.send("You don't see that here.\r\n") return if not isinstance(thing, Container): await player.send("You can't close that.\r\n") return if thing.closed: await player.send("It's already closed.\r\n") return thing.closed = True await player.send(f"You close the {thing.name}.\r\n") async def cmd_put(player: Player, args: str) -> None: """Put an item into a container.""" if not args.strip() or " in " not in args: await player.send("Put what where? (put in )\r\n") return # Parse "thing in container" parts = args.strip().split(" in ", 1) if len(parts) != 2: await player.send("Put what where? (put in )\r\n") return thing_name = parts[0].strip() container_name = parts[1].strip() if not thing_name or not container_name: await player.send("Put what where? (put in )\r\n") return # Find thing in player's inventory thing = find_in_inventory(thing_name, player) if thing is None: await player.send("You're not carrying that.\r\n") return # Find container (on ground or in inventory) container_obj = _find_container(container_name, player) if container_obj is None: await player.send("You don't see that here.\r\n") return if not isinstance(container_obj, Container): await player.send("That's not a container.\r\n") return if thing is container_obj: await player.send("You can't put something inside itself.\r\n") return if container_obj.closed: await player.send(f"The {container_obj.name} is closed.\r\n") return if not container_obj.can_accept(thing): await player.send(f"The {container_obj.name} is full.\r\n") return thing.move_to(container_obj) await player.send(f"You put the {thing.name} in the {container_obj.name}.\r\n") register(CommandDefinition("open", cmd_open)) register(CommandDefinition("close", cmd_close)) register(CommandDefinition("put", cmd_put))