Coding is an (Infinite) Adventure

Jed Rembold

November 17, 2025

Announcements

  • I am deeply sorry, but getting Project 5 finalized over the weekend took up more hours than I’d expected, so Exam 2 is still not finished being graded
    • It is my top priority at the moment
  • Enigma Project due tonight!
    • I’ll be around after 4:30 for a while in addition to my usual office hour today
  • Project 5 guide is out now!
    • Introducing it later today
    • You already have what you need to get through the first few milestones
    • On Wednesday we’ll talk more in depth about API’s and the requests library
  • Graphics Contest submissions due in one week
  • Polling: polling.jedrembold.prof

Review Question

Suppose I had created the data structure to the right in order to keep track of class sizes over the years. How would I access the size of my Spring 2018 Mechanics (Phys 339) class?

  1. data[2018]['classes']['Phys339']
  2. data[1]['Phys339']
  3. data[1]['classes']['Phys339']
  4. data[2018]['Phys339']
data = [
    {   'year': 2017,
        'semester': 'Fall',
        'classes': {
            'Phys221': 38,
            'Phys110': 49
        }
    },
    {   'year': 2018,
        'semester': 'Spring',
        'classes': {
            'Phys339': 16,
            'Phys222': 35
        }
    },
    {   'year': 2018,
        'semester': 'Fall',
        'classes': {
            'CS151': 26,
            'Phys110': 45
        }
    }
]

Working with Compound Data

Compound Strategies

  • If working with data that is already heavily nested, you must stop and really understand the data structure before starting to write code
    • What parts might you be needing to loop over?
    • What parts might you want to extract for later use?
  • Break out smaller pieces that you are going to need to reuse into their own variables
    • This stops you from having to re-index everything out every single time
  • Pay close attention to what data type you get back from each indexing
    • Is it a list? A dictionary? A set?

Demo

  • We’ve seen an example of the nested structure holding information about a fireball spell already
  • I’ve gone and grabbed all 300+ D&D spells into a single data structure, where each spell has a similar internal structure to Fireball
  • Let’s use that structure to write some code to do the following:
    • Print out all spells from a chosen school below a certain level threshold
    • Print out all spells from a chosen class that have no verbal component
    • Determine which spell does the most cold damage at level 11

Adventure Time

Beginning the Adventure

  • One of the first computer games I ever played was Riven: The Sequel to Myst
  • This was but the latest addition in an already long line of adventure type games

Life among Wizards

  • The history of the early internet has been told in several books. One relates the following story:
   

A small circle of friends at BBN had gotten hooked on Dungeons and Dragons, an elaborate fantasy role-playing game in which one player invents a setting and populates it with monsters and puzzles, and the other players then make their way through that setting. The game exists only in the minds of the players.

Dave Walden got his introduction to the game one night when Eric Roberts, a student from a class he was teaching at Harvard, took him to a D&D session. Walden immediately rounded up a group of friends from the ARPANET team for continued sessions. Roberts created the Mirkwood Tales.

One of the regulars was Will Crowther.

Willie Crowther’s Adventure Game

A Brief History of Adventure

  • Eric Roberts begins the Mirkwood Tales in early 1975
    • Will Crowther creates Adventure later that year
  • Stanford graduate student Don Woods released an expanded version of Adventure in early 1977
  • Dave Lebling and others from MIT release the first version of Zork in 1977
  • Adventure is ported to wide variety of platforms by 1980
  • Eric Roberts creates an expanded version in 1984 and uses it as the basis for his first Adventure Project at Wellesley
  • The Adventure Project begins at Willamette University in 2022
  • The Adventure Project becomes infinite in 2025!

Why Infinite?

  • Older versions of Adventure were always limited in what options a player could choose to do
  • Many possibilities, but still always possible to try to do something reasonable that was denied by the game
  • What if we could change that?
  • With the advent of Large Language Models (LLMs), computers are now shockingly good at producing new content given a prompt
  • So in the Infinite Adventure, when a player tries to do something or go somewhere the game designer didn’t plan, it does not error or prevent them from doing so
    • Instead, the program uses an LLM to generate a new scene description on the fly

Building Blocks

Story JSON fileLLM Creation (ChatGPT)PregeneratedImages

The Story Structure

story plot scenes scenes scene_key 1 scene_key 2 scene_key 3 scene_key 1 text scene_summary choices choices 0 1 2 0 text scene_key

The Story JSON

Milestones

MS 0: Understanding

  • Milestone 0 is completed in the warmup.py file
  • Focuses in on reading in the JSON data and then:
    • Looping over all the scenes
    • Looping over all the choices for each scene
    • Looking at the resulting scene_key
    • Comparing that key back to all the available keys in the scenes dictionary
    • Printing out “dead-end” scene keys
  • The idea here is to ensure you understand the compound data structure and can work productively with it

MS 1: Printing a Room

  • Whenever the player “enters” a room or scene, a description needs to be printed to the terminal
    • Begins with the scene description text
    • Followed by a numbered list of all the possible choices
  • Formatting is important here, to keep things clean and readable!
  • Constantly printing room descriptions, so makes sense to package up in a helper function

MS2: Getting a Valid Choice

  • Writing a helper function to prompt the user to enter in their choice
  • Not all choices are valid!
    • Enter in something besides a number? Try again.
    • Enter in a number that isn’t a choice? Try again.
  • Need to keep prompting the player until they make a valid choice, then return that choice
  • If no characters are entered, should return None

MS3: Connecting the Flow

  • Now you have all the parts to connect things together!
  • Track what scene the player is currently in
  • Repeatedly:
    • Print out the current scene
    • Prompt the player for their valid choice
    • Look up the corresponding next scene_key for that choice
    • Update the current scene to the next scene_key
  • Should continue infinitely until None is returned by your valid choice function
  • Will error when encountering a dead-end room! This is expected!

MS4: Generating New Scenes

  • Here is where you’ll get to write a function to use ChatGPT to make a new scene!
  • First need to construct the prompt
    • A template is provided for you! You’ll just need to substitute in the correct bits for any new scene. Things like:
      • This scene’s scene_key
      • An example of how we format a scene
      • The overall plot of the story
      • What choice a user selected to arrive here
      • What the previous scene key was
    • f-strings will be very useful here!

MS4: The API Call

  • Once you have your prompt, you need to package it up and send it off to ChatGPT
  • Example code provided for how to do this
  • You’ll need to provide your NotOpenAI api key at the top of the program
  • After a moment, you’ll get back a string of JSON information
    • Use json.loads(|||your string response|||) to convert this to nested data structures
  • Then you can print it off like usual, and add it to the scenes dictionary!
  • We’ll play more with API calls on Wednesday

NotOpenAI

  • In general, while simpler models do not cost much, they still cost something to access through OpenAI’s API
  • We didn’t want you to have to pay anything though, so instead you connect through our custom NotOpenAI library
    • Acts as a sort of “middle-man”, receiving your request and then forwarding that request on to ChatGPT, but using our API key (which we are paying for)
    • The way you make a request to ChatGPT with the NotOpenAI library is identical to how you would do so with the official OpenAI library
    • Your NotOpenAI keys are allocated around 1.5 million tokens of usage, which should correspond to somewhere between 750 to 1500 generated scenes, which is a LOT! But it isn’t infinite, so don’t abuse it.

MS5: Visualizing

  • Text descriptions are nice, but images can really bring a story to life
  • For all the pre-generated rooms, I have also generated a corresponding image using DallE
  • All images follow the naming pattern of img/|||scene_key|||.jpg
  • When you display the text of a room, you also want to display the corresponding image if it exists
    • Display a black box if it does not exist
  • This is just using existing PGL functionality that you are already familiar with

MS6: Reflecting

  • When we use generative AI, we are, by design, giving up some control to the AI
  • How do we evaluate or measure if the AI is making “good choices”?
  • This milestone asks you to generate a handful of scenes from a new story: engineer_story
  • You want to pay particular attention to the names of your coworkers, and then answer several questions about if “good” decisions are being made.
  • These questions will be answered in infinite_ethics.txt and uploaded along with your code

Final Thoughts

First Time!

  • This is the first time this project has been done at Willamette!
  • All the section leaders have prepped by completing the project
  • Other tutors will likely be less familiar, though they have had access to the materials
    • By patient with them if it takes them a bit longer to get up to speed
    • You can always direct questions to me!
  • I’m very excited to see what fun extensions you can come up with and what your general feelings on the project are!

LLM Problems

  • Generative AI is very provocative atm, for good reason. It can do some amazing things, but at some real cost
  • I personally have strong concerns with both the environmental impacts of generative AI training and the seemingly wanton disregard for intellectual property, copyright, and attribution that big tech has shown in training most models.
  • But usage of and discussions around generative AI have become the norm in especially many tech fields
  • I don’t think this is something we can improve or help guide or regulate without engaging with the technology on more than a surface level
  • Please keep both the benefits, but also the costs in mind as you engage with the technology on this project
// reveal.js plugins