Help with Procedural Quest Generation

Announcements, support questions, and discussion for Quest Machine.
Post Reply
dylandev
Posts: 2
Joined: Sat Dec 15, 2018 1:44 pm

Help with Procedural Quest Generation

Post by dylandev »

Hi there,

I've been trying to wrap my head around this package for a little bit now and am confused about how to proceed. I think the sheer number of messages that need to be correctly addressed and different moving parts of the system is what is getting me. I've got some basic quests moving now and am looking into the procedural part. Although I appreciate the strength and flexibility of the way you are able to generate quests using it, I can't help but feel overwhelmed by the number of moving parts that need to be in play to generate some simple quests.

What I have right now is a simple Procedural Scout mission that is generated by an entity being in a domain. I made a custom script for the player to send a message to the messaging system that a new QuestEntity has been spotted. I'm using this if anyone is curious, it works quite well:

Code: Select all

QuestEntity qe = collision.GetComponent<QuestEntity>();
        if( qe!= null){
            if (DEBUG_LOGS) { Debug.Log("Player Scouted the QuestEntity: " + qe.name); }
            MessageSystem.SendMessage(transform.parent.gameObject, "Scouted", qe.name);

        }
My problem then is how do I control other procedural quests? What I would like to do is have a progression where a Monster is first Scouted (Quest1) then if that procedural quest is completed, a quest to go fight the monster is spawned. Now, I can use the GenerateQuest() command from a script in the QuestGeneratorEntity to generate a new script, but how would I take into account my previous Scout quest is already completed? Is that even possible? Also what is the preferred way to generate a new procedural quest once one has been completed? I was looking at using an Event Listener to listen to the EventCompleted message but that seems a bit hacky?

Also, is there a way to add more specificity to quest conditions for the Procedural Quests. Although sometimes using the faction relations and all that stuff is cool it would be nice if there was a simpler way to filter it. I'm thinking of like "RedPirate was Scouted" as a condition.

Although I see what you're doing with this package, and I really want to make it work, I am finding it very confusing to do simple things. There also seems to be a gap between quests that are linear and pre-built and quests that are totally procedural built up from entities internal states. Is there a way to make a quest template? Like "Scout one of three given options, when that is completed, go fight that monster chosen in step 1". Something that would allow me to use some quest structure but have more control over what is getting triggered?

Also, just as a way of feedback, I find the heavy reliance on the messaging system for simple things (eg collect a coin) to be somewhat error prone and difficult to debug,. It would also be nice to be able to set a DEBUG message flag for a single entity rather then the whole system at once.

Thanks in advance, I've been following the development of Love/Hate for a long time and am looking forward to this new package adding additional functionality!

Best

Dylan
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: Help with Procedural Quest Generation

Post by Tony Li »

Hi,

Thanks for using Love/Hate as well as Quest Machine! And thank you for the feedback, too. Quest Machine's procedural generation was in development for over three years, consulting with AI researchers who do this stuff at the university level, and this is about as simple as it gets to be able to provide this degree of flexibility. One simpler prototype was more like Mad Libs, with prewritten template structures (kind of like Skyrim's Radiant quest system), but it really limited the uniqueness of the quests.

That said, here are some pointers:

If you haven't watched the procedural generation tutorial video, you may find it helpful: Procedural Quest Generation.
dylandev wrote: Sat Dec 15, 2018 6:24 pmWhat I have right now is a simple Procedural Scout mission that is generated by an entity being in a domain. I made a custom script for the player to send a message to the messaging system that a new QuestEntity has been spotted. I'm using this if anyone is curious, it works quite well:

[snipped (thanks for sharing the code)]

My problem then is how do I control other procedural quests? What I would like to do is have a progression where a Monster is first Scouted (Quest1) then if that procedural quest is completed, a quest to go fight the monster is spawned. Now, I can use the GenerateQuest() command from a script in the QuestGeneratorEntity to generate a new script, but how would I take into account my previous Scout quest is already completed?
It's easier if you view the quest from the QuestGeneratorEntity's perspective. To reduce typing, I'll refer to the QuestGeneratorEntity as the "Questgiver."

When the Questgiver generates a quest, it doesn't look at what's actually in the world (i.e., the Unity scene). It works with an abstract representation called a world model. The world model has a list of entity types, which are abstract ideas of entities in the world. To generate the first quest, you want the Monster to be scoutable, so the world model should say that there's a scoutable monster in the domain. To generate the second quest, you want the questgiver to see the monster as attackable, so the world model should say that there's an attackable monster.

To implement this, define two EntityTypes: ScoutableMonster and AttackableMonster. ScoutableMonster should have a Scout action, and AttackableMonster should have an Attack action.

At design time, assign ScoutableMonster to the QuestEntity GameObject. When the player scouts the monster, change the QuestEntity's entity type to AttackableMonster. Do it in the same section of code you shared above. Example:

Code: Select all

qe.entityType = AttackableMonster; // Assumes you have a reference to the AttackableMonster EntityType asset.
What you're really doing is not changing the actual game world, but rather how the Questgiver perceives the world. That's the key to working with procedural generation.

dylandev wrote: Sat Dec 15, 2018 6:24 pmAlso what is the preferred way to generate a new procedural quest once one has been completed?
Start dialogue by calling the Questgiver's QuestGeneratorEntity.StartDialogueWithPlayer() method. It's like QuestGiver.StartDialogueWithPlayer() but generates a new quest first if needed.

dylandev wrote: Sat Dec 15, 2018 6:24 pmAlso, is there a way to add more specificity to quest conditions for the Procedural Quests. Although sometimes using the faction relations and all that stuff is cool it would be nice if there was a simpler way to filter it. I'm thinking of like "RedPirate was Scouted" as a condition.
Questgivers use two types of conditions.

First, they use urgency functions to choose which entity type to generate a quest about. The demo uses the Threat Urgency Function, which checks faction values. But you're welcome to use different urgency functions. Questgivers don't care how the functions work; just want a return value so they can choose the entity type with the highest value.

For example, another built-in urgency function is the Drive Alignment Urgency Function. Let's say you're making an art heist game. You could define drives such as Price, Impressionism, and Realism. Maybe one questgiver only cares about Price, while another loves Impressionism and hates Realism. If you assign drive values to the questgivers and the paintings to be stolen, the questgivers will choose different targets based on how well the drives align. Quest Machine's Templates folder has a starter template script if you want to define your own urgency functions.

The second type of condition questgivers use is checking whether certain entity types are in or out of the world model. This is defined in the Action asset's Requirements section. (Actions technically also support custom requirement code, too, but it's not exposed in the editor yet.) Going back to the art heist example, you could make the Steal Painting action require that the painting is in the museum domain -- or, better yet, not in the questgiver's personal domain -- since it wouldn't make sense for the questgiver to ask the player to steal a painting from the questgiver's own domain. But you can also define abstract domains to represent additional information in the world model. I'll skip the details because this wall of text is probably already visible from space.
dylandev wrote: Sat Dec 15, 2018 6:24 pmAlthough I see what you're doing with this package, and I really want to make it work, I am finding it very confusing to do simple things. There also seems to be a gap between quests that are linear and pre-built and quests that are totally procedural built up from entities internal states. Is there a way to make a quest template? Like "Scout one of three given options, when that is completed, go fight that monster chosen in step 1". Something that would allow me to use some quest structure but have more control over what is getting triggered?
That's actually on the roadmap. It's not available yet, though.
dylandev wrote: Sat Dec 15, 2018 6:24 pmAlso, just as a way of feedback, I find the heavy reliance on the messaging system for simple things (eg collect a coin) to be somewhat error prone and difficult to debug,. It would also be nice to be able to set a DEBUG message flag for a single entity rather then the whole system at once.
Great idea! I'll try to get that into the next release.
dylandev wrote: Sat Dec 15, 2018 6:24 pmThanks in advance, I've been following the development of Love/Hate for a long time and am looking forward to this new package adding additional functionality!
Hang in there. It takes a while to grok it all, but that's because it does something that no other commercial systems do right now.
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: Help with Procedural Quest Generation

Post by Tony Li »

Version 1.1.2 is available on the Pixel Crushers customer download site (PM me your Unity Asset Store invoice number if you'd like access) and should be available on the Asset Store in 3-7 business days.

This version has a Message System Logger component that you can add to a GameObject to log Message System activity that's specific to that GameObject.

I forgot to mention in my post above that the Message System isn't the only way to handle conditions and actions. It's useful as a general-purpose tool. But for things like collecting coins you'll probably want to use custom actions specific to your inventory system. For example, if you're using the Inventory Engine integration, you'd use the custom actions to check or modify the amount of items in Inventory Engine, without having to fiddle with the Message System at all. This applies to hand-written quests. I'd like to be able to handle custom actions in procedurally-generated quests, but that will have to come in a future update.
fbit
Posts: 30
Joined: Fri Nov 30, 2018 9:30 am

Re: Help with Procedural Quest Generation

Post by fbit »

Hello everyone,
Tony Li wrote: Sat Dec 15, 2018 9:55 pm
dylandev wrote: Sat Dec 15, 2018 6:24 pmAlthough I see what you're doing with this package, and I really want to make it work, I am finding it very confusing to do simple things. There also seems to be a gap between quests that are linear and pre-built and quests that are totally procedural built up from entities internal states. Is there a way to make a quest template? Like "Scout one of three given options, when that is completed, go fight that monster chosen in step 1". Something that would allow me to use some quest structure but have more control over what is getting triggered?
That's actually on the roadmap. It's not available yet, though.
That would be great! I was looking for a feature like this as well, because I had the same problems.

I noticed that you can create more complex quests (with more than just one node) if the quest giver decides to set a specific task first in order to complete his main goal.

But it would be nicely if you could setup branches for quest nodes like you can do with hand-written quests.

Best regards,

Franca
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: Help with Procedural Quest Generation

Post by Tony Li »

fbit wrote: Mon Dec 17, 2018 8:46 amI noticed that you can create more complex quests (with more than just one node) if the quest giver decides to set a specific task first in order to complete his main goal.

But it would be nicely if you could setup branches for quest nodes like you can do with hand-written quests.
That's a tall order, but I'll give it some thought. Currently, while procedural quests don't have diverging branches, they can generate a sequence of any number of tasks, which still makes them interesting. For example, the tasks could be something like: [Find the Wizard] --> [Answer the Riddle] --> [Get the Magic Sword] --> [Slay the Dragon] --> [Escort the Prince Home] --> [Talk to King].

The pirate in the demo scene typically generates a multi-step quest like this: [Get Wand from Barrel] --> [Polymorph Target] --> [Talk to Pirate].
dylandev
Posts: 2
Joined: Sat Dec 15, 2018 1:44 pm

Re: Help with Procedural Quest Generation

Post by dylandev »

Hi Tony,

Thanks for the extensive response! I definitely understand that building something as comprehensive as this is not going to be simple, and I think you are doing a good job managing it. I also really appreciate the rapid support responses! You helped put some things in order for me and I'm going to keep working at it. I'm being critical in the spirit of providing you with good feedback and dialogue about how it could be improved. As I am figuring out how the system works I am seeing how components work together I see some of the reasons you have done things the way you have.

My main beef with the messaging setup is it makes it hard to trace the execution. One wrong letter in the message format means it doesn't get sent or received. You also need to have the whole quest planned out quite clearly in advance. What about a Quest Template form (even just a pdf)? Something to assist with planning? I find having to enter all the ID's and message codes one of the more confusing parts.

I think you are right about implementing a custom counters, that also helps with the issue of having multiple agents that can each complete a quest (eg. If I collect a rabbit, and the rabbit sends the collection message, I have to assume the player collected it. With a custom script tracking this I can tell which entity did which action. )

I also wonder about some of the condition type stuff (ie adding a Scoutable entity to an NPC. Whether its Scoutable or not may depend on the perspective of who would want to scout it? How do you filter for that without including something like Love/Hate as well? How do you handle simpler conditions for quests? Like if I wanted to have a quest spawn every time there is more then 3 rabbits, rather then dealing with the Security motivation etc?). Sorry if some of this is covered in the Docs already.

I'm going to keep plowing into this and trying to figure it out. Thanks for the quick and extensive support! :)

Dylan
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: Help with Procedural Quest Generation

Post by Tony Li »

Hi Dylan,
dylandev wrote: Sun Dec 23, 2018 12:35 pmI'm being critical in the spirit of providing you with good feedback and dialogue about how it could be improved.
Thank you! Your feedback will help make Quest Machine better for everyone.
dylandev wrote: Sun Dec 23, 2018 12:35 pmMy main beef with the messaging setup is it makes it hard to trace the execution. One wrong letter in the message format means it doesn't get sent or received.
Wherever you can manually type a string, you can assign a String Asset or Text Table instead. String Assets exist precisely to address this concern. You can define a string once, as an asset file, and then use that reference everywhere instead of manually typing the string again and again. Text Tables can serve the same purpose, plus they can handle language localization and be imported from spreadsheet applications.
dylandev wrote: Sun Dec 23, 2018 12:35 pmYou also need to have the whole quest planned out quite clearly in advance. What about a Quest Template form (even just a pdf)? Something to assist with planning? I find having to enter all the ID's and message codes one of the more confusing parts.
This is on the roadmap. The high level concept is that you'll create a quest structure, such as a kill quest. Then you'll be able to combine that quest structure with a target and a count, and it will pop out a quest asset to kill the specified number of the target.

Also on the roadmap is the ability to add custom message codes to the Quest Reference window. This way you'll be able to click on the message code button and then paste it into your quest without having to type it manually.
dylandev wrote: Sun Dec 23, 2018 12:35 pmI think you are right about implementing a custom counters, that also helps with the issue of having multiple agents that can each complete a quest (eg. If I collect a rabbit, and the rabbit sends the collection message, I have to assume the player collected it. With a custom script tracking this I can tell which entity did which action. )
Agreed that messages, being a general purpose tool, aren't as easy to work with as custom integrations for inventory counts. However, you can set your counter to only increment if the message has a specific sender, such as the quester assigned to the quest. The AI Questers tutorial does this so it can tell which AI picked up each item and update the correct counter.
dylandev wrote: Sun Dec 23, 2018 12:35 pmI also wonder about some of the condition type stuff (ie adding a Scoutable entity to an NPC. Whether its Scoutable or not may depend on the perspective of who would want to scout it? How do you filter for that without including something like Love/Hate as well?
In that case, I think this is where exposing custom requirement functions in the editor will be helpful. You could define a requirement function for the Monster's Attack action that requires that the questgiver has scouted the Monster first.

I realize many of these things aren't available yet. I'm mentioning them in case you or any other readers have thoughts on how they would work best for you. It's easier to adjust designs before they're implemented than after. Your feedback also helps me prioritize roadmap items.
dylandev wrote: Sun Dec 23, 2018 12:35 pmHow do you handle simpler conditions for quests? Like if I wanted to have a quest spawn every time there is more then 3 rabbits, rather then dealing with the Security motivation etc?).
If you're talking about procedurally-generated quests, you're always going to use urgency functions.

However, this sounds more like a specific hand-written quest. Set the quest's Offer Conditions to require that there are at least 3 rabbits in the scene. The actual setup will depend on how you keep track of the number of rabbits. If you use Quest Domains, you could write a custom QuestCondition that counts the rabbits in the questgiver's domains. Or you could define a counter that listens for messages when rabbits are added or removed.
Post Reply