Blog Post #10


We Did It!!

Milestone 5 ended with a fully functioning Intelligent NPC prototype!

This project has been both exciting and challenging in all the best ways. I set out to build something rooted in a newer concept (one that very few people in the game industry are doing yet) while navigating it with limited programming experience and essentially no step-by-step guide to follow.

Despite all of that, I’m incredibly proud of the progress I’ve made and the fact that I reached my end goal: creating a fully functioning prototype of an Intelligent NPC.


The Final Pieces

To recap how I made it to my end goal, we need to begin where I left off last week. The midpoint of Milestone 5 left me with two items left on my list:

  1. Fixing the chat-history memory issue
  2. Tightening up Jenny Applebaum’s persona for the prototype.

I chose to tackle the chat-history issue first. It was the more complex of the two, and solving it would make it much easier to properly test any refinements I made to Jenny’s persona seed afterward.

Persistently Forgetful

For the LLM to hold a proper conversation with the player, it needed a way to simulate memory, something that would let it remember what had already been said. After some quick research into different data-handling options (I had a strong hunch it would involve an array), I came across persistent arrays.

Persistent arrays are a type of data structure that preserve their contents over time and through changes. In other words, the system remembers what’s been added as the array grows, and it can access previous entries or states whenever it needs to.

This felt like the perfect antidote to Jenny’s forgetfulness, so I charged ahead with this solution.

Where to Put You?

I decided to name my new array ChatHistory (straight to the point!) and then immediately found myself staring at my Blueprint, unsure where it actually belonged. Should it go at the start? The middle? The end?

My first attempt was adding the array at the very beginning. Not only did this change nothing, it also felt a little ridiculous: the JSON objects I needed later in the pipeline hadn’t even been created yet! How could I add entries to an array using objects that technically didn’t exist when the code ran?

Once that clicked, it became clear that the best place to build the ChatHistory was right after the three JSON objects were created the same spot where I had previously placed my simple, one-time array.

I swapped out the old nodes and added two Add Array nodes to ChatHistory: One for the NPC Seed and one for the Player Input. I then wired them into the Set Object Array Field node like before and, voilà, they were in.

I hit Play to test and… nothing changed. Jenny was still operating with a one-sentence recall.

Then it hit me: ChatHistory had no way of capturing Jenny’s parsed response from the LLM. She couldn’t remember what she herself said. So I took a guess and added an entry to the array at the end of the Blueprint, right around where the parsed response is handled.

Playtest again… and suddenly she seemed able to remember. However, I discovered a catch: this isn’t easy to test. You have to be very deliberate with your prompts to coax out whether she’s genuinely continuing a conversation and not just staying in character. And Jenny, as it turns out, is exceptionally good at staying in character!

To verify the array for sure, I decided to bring in the old reliable Print String node. I printed the array length after every LLM output, and it worked beautifully. The array grew by three entries with every exchange (one per object), confirming that ChatHistory was properly building.

Attitude Adjustment

Feeling pretty pleased that I’d conquered the more difficult task, I happily skipped over to the last (and much more entertaining) piece of Milestone 5: adjusting Jenny’s persona seed.

Through testing, I realized she wasn’t nearly as protective of her apples as I wanted. She sold them far too easily and was a little too warm and friendly. In my original vision, Jenny was a slightly grumpy older woman, utterly obsessed with apples, who only warmed up to true apple enthusiasts.

I needed her to only sell her apples to someone who could genuinely convince her. This condition is absolutely necessary to gamify the prototype. Without those boundaries, players aren’t interacting with an NPC they’re just chatting with an LLM.

As I tweaked the persona seed again and again, I found unexpected delight in discovering just how many subtle qualities go into binding the LLM correctly.

You need to be specific about what you want it to do: clear, concise, and firm, without being overbearing or drowning the model in prompt length. The LLM isn’t human; it mimics human interaction, and it has to be treated with that awareness in mind. It felt like trying to hold a slippery fish, carefully making sure there were no loopholes it could slip through to break character.

You also have to think creatively from multiple perspectives: the LLM’s, the NPC’s, and the player’s. The persona seed required a human (me) at the helm to shape, direct, and refine it.

I found the process to be surprisingly endearing. This step reinforced a hypothesis of mine that humans must be part of this process. The LLM can’t assume what you want; like a puppy, it needs clear, structured guidance.


The Market is Open!

Jenny was built from scratch. She began as a lighthouse keeper who could only say one line and couldn’t take input. Then she slowly transformed into a shadowy likeness of the apple loving NPC she would eventually become.

This intelligent NPC spoke to me, then stubbornly refused to speak at all. She broke, got fixed, and broke again. The development path became hopelessly cluttered, then suddenly illuminated in the right direction.

I spent countless hours hacking and slashing together an uncertain idea of development with no formal training to guide me. I created more functions than I could keep track of or logically explain. I ran victory laps around my living room when things worked and practiced rubberducking with my cat when they didn’t.

It has been an absolute joy working on this project.


What is Next for Jenny?

Now that Jenny is finally functioning as intended, I’m excited to showcase the prototype to others for testing. I’ve submitted for a table at the Clark IGDA Game Expo and also hope to present the prototype to my MFA peers at the end of the semester.

I plan to continue this Intelligent NPC work and experiment with other LLMs, SLMs, game engines, and approaches. Jenny may be the first, but she certainly won’t be the last. I hope to build many more intelligent NPCs as this technology continues to redefine the gaming industry in the coming years.

Until next time,

~Lauren


Leave a Comment

Your email address will not be published. Required fields are marked *