From 1c22530be74d1e7644718ea40efd9505db15d7b3 Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Sat, 14 Feb 2026 16:45:06 -0500 Subject: [PATCH] Add character creation flow with description prompt --- src/mudlib/creation.py | 36 ++++++++++++++++ tests/test_creation.py | 96 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/mudlib/creation.py create mode 100644 tests/test_creation.py diff --git a/src/mudlib/creation.py b/src/mudlib/creation.py new file mode 100644 index 0000000..73243aa --- /dev/null +++ b/src/mudlib/creation.py @@ -0,0 +1,36 @@ +"""Character creation flow for new players.""" + + +async def character_creation( + name: str, + read_func, + write_func, +) -> dict: + """Run character creation prompts for a new player. + + Args: + name: Player name + read_func: Async function to read a line of input (returns str or None) + write_func: Async function to write output + + Returns: + Dict with creation data: {"description": str} + """ + await write_func("\r\n--- Character Creation ---\r\n\r\n") + await write_func( + "Describe yourself in a short sentence or two.\r\n" + "(This is what others see when they look at you.)\r\n\r\n" + ) + await write_func("Description: ") + + desc_input = await read_func() + description = "" + if desc_input is not None: + description = desc_input.strip() + + if description: + await write_func(f'\r\nYou will be known as: "{description}"\r\n') + else: + await write_func("\r\nNo description set. You can change it later.\r\n") + + return {"description": description} diff --git a/tests/test_creation.py b/tests/test_creation.py new file mode 100644 index 0000000..f46ba1f --- /dev/null +++ b/tests/test_creation.py @@ -0,0 +1,96 @@ +"""Tests for character creation flow.""" + +from collections import deque + +import pytest + +from mudlib.creation import character_creation + + +async def make_io(inputs): + """Create mock read/write functions.""" + input_queue = deque(inputs) + output = [] + + async def read_func(): + if input_queue: + return input_queue.popleft() + return None + + async def write_func(msg): + output.append(msg) + + return read_func, write_func, output + + +@pytest.mark.asyncio +async def test_character_creation_with_description(): + """Test providing a description returns it.""" + read_func, write_func, output = await make_io( + ["A wandering swordsman with a mysterious past."] + ) + + result = await character_creation("TestPlayer", read_func, write_func) + + assert result["description"] == "A wandering swordsman with a mysterious past." + assert any("Character Creation" in msg for msg in output) + assert any("Description:" in msg for msg in output) + assert any("A wandering swordsman with a mysterious past." in msg for msg in output) + + +@pytest.mark.asyncio +async def test_character_creation_empty_input(): + """Test empty input returns empty string.""" + read_func, write_func, output = await make_io([""]) + + result = await character_creation("TestPlayer", read_func, write_func) + + assert result["description"] == "" + assert any("No description set" in msg for msg in output) + + +@pytest.mark.asyncio +async def test_character_creation_none_input(): + """Test None input (disconnect) returns empty string.""" + read_func, write_func, output = await make_io([None]) + + result = await character_creation("TestPlayer", read_func, write_func) + + assert result["description"] == "" + assert any("No description set" in msg for msg in output) + + +@pytest.mark.asyncio +async def test_character_creation_prompts(): + """Test the output includes the prompts.""" + read_func, write_func, output = await make_io(["Test description"]) + + await character_creation("TestPlayer", read_func, write_func) + + output_text = "".join(output) + assert "Character Creation" in output_text + assert "Describe yourself" in output_text + assert "This is what others see when they look at you" in output_text + assert "Description:" in output_text + + +@pytest.mark.asyncio +async def test_character_creation_confirmation(): + """Test the confirmation message includes the description.""" + read_func, write_func, output = await make_io(["A fierce warrior"]) + + await character_creation("TestPlayer", read_func, write_func) + + output_text = "".join(output) + assert "You will be known as:" in output_text + assert "A fierce warrior" in output_text + + +@pytest.mark.asyncio +async def test_character_creation_strips_whitespace(): + """Test that leading/trailing whitespace is stripped.""" + read_func, write_func, output = await make_io([" A nimble thief "]) + + result = await character_creation("TestPlayer", read_func, write_func) + + assert result["description"] == "A nimble thief"