When we left off last time, I generated a tiny bit of NPC text.
The goal for this week is to push the system as far as we can and verify the direction will meet our needs.
To verify direction, its important to keep checking current position versus origin and destination.
I’m Old and I like World of Warcraft (Classic)
It’s been 13 years since I stopped playing WoW (it was Cataclysm). I have fond memories, so I decided to fire it up again and analyze their quest descriptions.
Why Wow?
If I polled for “Games with Best Quest Writing” I don’t think WoW will be top of anyone’s lists. I expect people will cite work from Bethesda, Bioware, CD Project Red, Obsidian, and Rockstar. So why look at WoW?
World of Warcraft writing has to achieve very specific goals which we share:
Appeal to Readers and Non-readers alike.
(Non readers rejoice: a recent mod uses AI to generate real-time Voice Over!)
Short and to the point. Low word count for the non-readers, but enough personality and flavor for readers (like me!)
Keep players playing! Give them something to do! Grinding through monsters for no reason can be boring. The quests are context and trappings to keep players fighting monsters in the zone. Quest are the most efficient way to level, but not mandatory.
Nudge the player to explore and interact with more of the world.
I was in a level 10-20 zone. The town mayor asked me to deliver a letter to a mayor of another town in a 15-25 zone. If not for this quest I wouldn’t know I had another place to level between level 15 and 20.
Very limited player verb set, basically fetch or kill quests. These are the verbs we are trying to start with.
Every WoW quest is hand crafted by a person. If we can generate text as good as WoW, we’ve achieved what we set out to do.
example WoW Kill Unique quest
Bounty on Garrick Padfoot
Bounty on Garrick Padfoot
Garrick Padfoot - a cutthroat who's plagued our farmers and merchants for weeks - was seen at a shack near the vineyards, which lies east of the Abbey and across the bridge. Bring me the villain's head, and earn his bounty!
But be wary, <name>. Garrick has gathered a gang of thugs around him. He will not be an easy man to reach.
Progress
Did you find Garrick's shack? Are we finally free of that villain?
Completion
Hah - you caught him! You've done Elwynn a great service, and earned a nice bounty!
Analysis
Dissecting the above we can identify these parts:
Unique monster name
Monster problem
Last seen location
Reason for task
Player advice
This could be put into a template like so:
[Unique monster name] [Monster problem] [Last seen location] [Reason for task]
[Player advice]
Iterating on our Text Generation
Continuing where we left off, we have an NPC with a goal and a problem (together called a Motivation) and they need to spit it out to the player so they know where to go and what to do.
(We already have a direction giving system built into the game, so we don’t need to worry about it here.)
World building is important. Our study of other games shows quest dialogue is where most world building is shared. We decided to test this by adding a Fact dictionary lookup to tell the player something about the skeletons. Nolan wrote up some text and we gave it a whirl. It’s important to know the system is easy to add to. I added the Fact part in < 5 mins.
Our first template looked like this:
(Template: [Greeting:Meet:Alignment] [Transition:Lead in] [problem] [Transition:One thing to do] [Goal:Eliminate] [Transition:To that end] [Quest Objective:objective] [Why not me:objective] [Opinion Context:feeling] [Fact:plotobject])
Good, you are here. We've got a problem An important [item] was taken by Skeleton. We must do something! We have to get rid of them. I have decided There's a [enemy] I'd like you to kill. I've hunted it for some time, but he always evades me. It makes me so angry that The skeleton warriors ended up destroying those who created them.
I don’t know other languages well enough to compare, but in English you can move the sequence of things around and it still makes sense but sounds different. I moved around chunks of the template and got this:
[Opinion Context:feeling] [problem]! [Why not me:objective] [Goal:Eliminate] [Quest Objective:objective] [Fact:plotobject] Oh. [Greeting:Meet:Alignment]
It makes me so angry that The Skeleton have been behaving strangely. I fear something is amiss.! I've searched everywhere. We have to get rid of them. We need to find [unique item]. I believe it will prove indispensable. The skeleton warriors ended up destroying those who created them. Oh. Good, you are here.
Just with these two different templates, I can't tell they were made by the same code gen because the structure of the language is so different!
Wait until we have 10 templates, and smaller chunks, and more variants. This is exciting!
Obviously the above text isn’t perfect and upon seeing the templates side by side it looks pretty obvious. But keep in mind the player is reading one of these every 5+ mins, not 5 times a minute. So there is a large mental break between outputs. This is in our favor.
We decided to keep going and see what we get.
Grinding it Out
As we iterated we discovered the kind of templates we need for the phases of the quest:
There is just one of each, for now, as we make sure each chunk is working.
The code detects when meeting the quest giver for the first time, providing context and overall objective to the quest first before then going into the actual task description. Then we use different templates on if you are returning to the same NPC or meeting a new one for the first time.
My first thought was the text replacement would require multiple passes. The above code shows I'm gluing the greeting template to a task template, and then doing the text replacement once. My gut says this will help us later doing everything in one pass.
I had to step away from work for a few days to deal with something, so Nolan took the time to really dig into the system and smooth out the language through lots of experimenting.
Example A
(Player: Do you have any work for me?)
Quest Giver: I believe we're going to need to kill the [enemy] named [enemy name].
(Player: Why?)
Quest Giver: The Skeleton have been proliferating again. We won't be safe until [enemy name] is dead. Just this morning my old master was shocked to learn the [enemies] have just up and vanished. It's not safe to venture forth until they're found. But I will not be intimidated by these creatures. If it's the last thing I do, I will have a [enemy] for a trophy. Can you help me?
(Player: Yes, I'll help you.)
Quest Giver: Now we'll get something done. The fact of the matter is he's far too strong for me, otherwise I'd face him myself. First, we need to gather support for our cause. With that in mind, we're going to need to earn the esteem of the people of [town].
Example B
(Player: Do you have any work for me?)
Quest Giver: It seems that The Skeleton have been behaving strangely. I fear something is amiss. I’ve thought long and hard about this and I have decided: They must be destroyed. Yesterday my niece learned what the [enemies] have in their keeping and decided to act. But I will not be intimidated by these creatures. If it’s the last thing I do, I will have a [enemy] for a trophy. To accomplish this, I believe we must clear this lair of [enemies]. Can you help me?
(Player: Yes, I'll help you.)
Quest Giver: Good. Narcedon wasn’t built in a day, though, so first talk to [NPC] at [location]. They may have some information for us. It’s embarrassing, but I haven’t been able to learn a thing.
We’re encouraged with these results!
Key Signs of Good Tech
Nolan and I met to assess where we are at:
System is easy to learn.
System is easy to extend.
It's fun, Nolan enjoys how easy it is to tweak on his end
Fast and easy to iterate on - Quick to adjust wording and regenerate
Nolan feels like he’s just scratching the surface of what can be done here
Good results
These are the signs of a good tech direction. If the system was great, but Nolan hated using it. Or Nolan loved it, but it was hard to extend with new features. Or Nolan said "uh... I think we've exhausted what we can do with this" that would be really bad. Those are signs we’re not there yet, or going the wrong way.
We feel the tech is 80% there. Another week to address some outstanding issues could be all we need.
Funny story: A Weird Test and Bug
Right after I left, Nolan started working with the system alone. Of course, he ran into a bug. It was a simple issue which I fixed quickly. But then I decided to add better error logging so he could see the error more clearly and know what to fix.
After adding much superior logging, it started spitting out results like this:
The Skeleton have been venturing dangerously close to our town. capture a [enemy]. We've got a problem. Here's what we're going to do: It seems that Can you help me? (Player: Yes, I'll help you.) Good. get to know me better. We need to be on better terms first. find somebody named [NPC]. I believe they may prove useful.
At first glance I thought it was working. But reading closer it was missing things, or at least putting them in the wrong order. I started digging into the problem for an hour+.
Then I found it! <facepalm>
I accidentally made the dialogue lines randomly return from all 475 in the database instead of the few contextual ones requested.
Basically it was completely random results. 100% broken.
Unbelievably, the results were almost good enough it fooled us into thinking there was a much more specific problem. Apophenia and expectations at work?
This was a funny test, and actually encouraged us!