Lab 10: Choose-Your-Own-Adventure with AI
Overview
You are going to write a Choose-Your-Own-Adventure game in Python. When the game is done, you will interact with it by seeing parts of the story and choosing the next step by entering a number on the keyboard. Each time this happens, a message with that step will be sent to a server, which will generate the next part of the story with a Large Language Model (LLM) and send it back to your program. You will be responsible for incorporating the next part of the story into the game state.
Setup
The starter code includes:
adventure_game.py
- Main game file with data structures and partial implementationrequirements.txt
- Required Python packagesREADME.md
- Instructions for running the game
Install the required packages:
pip install -r requirements.txt
Data Structures
The game uses two main data structures:
StoryChunk
@dataclass
class StoryChunk:
story: str # what happened in this part of the narrative
choices: List[str] # list of possible options of what to do next
GameWorld
@dataclass
class GameWorld:
story: List[StoryChunk] # the game's story (most recent first - REVERSE ORDER)
waiting: bool # whether we sent a choice and are waiting for response
Your Tasks
Task 1: Parse Server Messages (YOU DO THIS)
Complete the message_to_story_chunk
function that converts server responses into StoryChunk objects.
Function signature:
def message_to_story_chunk(message: List[str]) -> StoryChunk:
"""
Parse a message received from the server into a StoryChunk.
Args:
message: List where first element is story text, rest are choices
Returns:
StoryChunk object with the story and choices
"""
Test case:
# Should convert:
["The story begins at a large door...", "I open the door.", "I hide."]
# Into:
StoryChunk("The story begins at a large door...", ["I open the door.", "I hide."])
Task 2: Integrate New Story Parts (YOU DO THIS)
Complete the integrate_message
function that adds new story chunks to the game world.
Function signature:
def integrate_message(world: GameWorld, message: List[str]) -> GameWorld:
"""
Add a new StoryChunk to the FRONT of the story and set waiting to False.
Args:
world: Current game state
message: Server response to parse and integrate
Returns:
Updated GameWorld with new story chunk added to front
"""
Requirements:
- Add the new StoryChunk to the front of the story list (most recent first)
- Set
waiting
toFalse
since we received a response
Task 3: Handle User Choices (YOU DO THIS)
Complete the request_next_chunk
function that processes user input and prepares server requests.
Function signature:
def request_next_chunk(world: GameWorld, choice_num: int) -> Tuple[GameWorld, str]:
"""
Handle user's choice and prepare message for server.
Args:
world: Current game state
choice_num: Index of chosen option (0-based)
Returns:
Tuple of (updated_world, message_to_send)
- updated_world: GameWorld with choice added and waiting=True
- message_to_send: The choice text to send to server
"""
Requirements:
- Add a new StoryChunk with "You chose: [choice text]" and empty choices list
- Set
waiting
toTrue
- Return the choice text as the message to send
Task 4: Test Your Implementation
Run the provided tests to verify your functions work correctly:
python -m pytest test_adventure.py
Task 5: Play the Game
Once your functions pass the tests, you can play the game:
python adventure_game.py
Game Controls:
- Enter a number (0, 1, 2, etc.) to choose your next action
- Type 'quit' to exit
Task 6: Connect to Real AI Server (Optional)
To use real AI-generated stories, update the constants at the top of adventure_game.py
:
# Server Configuration (get these values from your TA)
SERVER_URL = "https://your-lab-server.com" # Base URL
API_KEY = "cs2000_lab10_key_alpha"
How the storytelling works:
- The initial story and first choice response are written by hand, so always start the same.
- All subsequent choices use the AI server for dynamic adventures that respond to your decisions
Provided Code
The starter code includes:
- Display functions:
story_to_string()
,format_choices()
for rendering text - Game loop: Main game loop that handles user input and server communication
- Server communication: Mock server for testing (real server URL provided by TAs)
Task 7: Privacy and Stakeholder Analysis (ANSWER THIS)
While using generative AI (LLMs) to create narrative games like this is interesting, as it allows an incredible amount of variety, it also raises important privacy and safety concerns. Your game sends user choices and receives AI-generated content through a server, creating data flows that affect multiple parties.
Part A: Stakeholder Analysis
Complete the following stakeholder matrix by identifying the interests/values for each stakeholder group affected by the game:
Stakeholders | Interests/Values |
---|---|
Game players (users) | [to be filled in] |
Game developers/companies | [to be filled in] |
AI/LLM service providers | [to be filled in] |
[Additional stakeholder to be identified] | [to be filled in] |
Part B: Privacy/Contextual Integrity Analysis
Now think, in particular, about information from the users of the game as they interact with it, and complete the following analysis.
Question | Answer |
---|---|
What type of information is shared? | [to be filled in] |
Who is the subject of the information? | [to be filled in] |
Who is the sender of the information? | [to be filled in] |
Who are the potential recipients of the information? | Intended: [to be filled in] Unintended: [to be filled in] |
What principles govern the collection and transmission of the information? | [to be filled in] |
Part C: Analysis Questions
-
Stakeholder Conflicts: Identify one conflict between stakeholder interests in your matrix. Which stakeholder's interest should take priority and why?
-
Privacy Risks: Based on your contextual integrity analysis, what is one significant privacy risk for users of AI-generated games?
-
Design Recommendation: Suggest one specific change to how the game handles data that would better protect user privacy while still allowing the AI functionality to work.
Write your answers as comments at the bottom of adventure_game.py
.