Flatten commits
This commit is contained in:
commit
d3e719f743
19 changed files with 700 additions and 0 deletions
30
examples/EvaluationBotData/README.md
Normal file
30
examples/EvaluationBotData/README.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Evaluation Bots
|
||||
Bots and their usage
|
||||
|
||||
# Input
|
||||
- `DCStatDifficultyBot` - Evaluates the stat required and difficulty of an action (returns hard/medium/easy difficulty)
|
||||
- `InputDCattributeBot` - Evaluate the attribute and difficulty of an action (returns numeric difficulty)
|
||||
|
||||
# Input Special Usage
|
||||
- `SimplePossibilityBot` - Evalutes two possible actions, PossibleAction1 and PossibleAction2.
|
||||
- Special Usage: When `state.inputBot='SimplePossibilityBot'` you need to provide a character description in `state.contextualString`. This can be up to 75 characters (additional length will be truncated). `SimplePossiblityBot` will use the character description with the actions to provide information on what the character can do in the situation. Useful for enforcing limitations such as missing limbs or weapons.
|
||||
|
||||
# Output
|
||||
The following bots are best used on output.
|
||||
|
||||
## Multipurpose Evaluation Bots
|
||||
|
||||
- `GoblinBot` - Evaluates whether it detected any Goblins killed, health was lost, and loot gained
|
||||
- `KittenBot` - Evaluates whether rapport was gained or a kitten got hungrier
|
||||
- `SpaceLootBot` - Evaluates whether loot would be found (on a spaceship)
|
||||
- `HungerBot` - Evaluates whether the player would get hungrier or not
|
||||
- `RestDetectBot` - Evaluates whether or not the user got rest
|
||||
|
||||
## Simple Evaluation Bots
|
||||
There are several evaluation score bots. These bots can be used on either input or output to score different text. They all return a `reason` and a `score` which is roughly along the below descriptions.
|
||||
- `KillBot` - Evaluates whether the player is killing things
|
||||
- `JudgeBot` - Evaluates whether an action was just
|
||||
- `EmpathyBot` - Evaluates whether an action showed empathy
|
||||
- `SuccessBot` - Evaluates whether an action succeeded
|
||||
- `SantaBot` - Evaluates whether an action showed christmas spirit (An overly judgemental SantaBot also exists but is not currently available)
|
||||
|
13
examples/addSimpleInventory.js
Normal file
13
examples/addSimpleInventory.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
// Checkout the repo examples to get an idea of other ways you can use scripting
|
||||
// https://github.com/latitudegames/Scripting/blob/master/examples
|
||||
|
||||
const modifier = (text) => {
|
||||
|
||||
state.inventory = [{name: 'candy', quantity: 1}, {name: 'Turtles', quantity: 240}]
|
||||
|
||||
return { text }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
40
examples/authorsNote.js
Normal file
40
examples/authorsNote.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
const themes = [
|
||||
{
|
||||
text: 'ghost story',
|
||||
matcher: /ghost|halloween|spooky/i,
|
||||
},
|
||||
{
|
||||
text: 'trick-or-treat',
|
||||
matcher: /trick.or.treat|halloween|spooky/i,
|
||||
},
|
||||
{
|
||||
text: 'spooky',
|
||||
matcher: /halloween|spooky/i,
|
||||
},
|
||||
]
|
||||
|
||||
const modifier = (text) => {
|
||||
if (!state.setup) {
|
||||
state.theme = Math.floor(Math.random() * themes.length)
|
||||
state.setup = true
|
||||
state.matched = false
|
||||
}
|
||||
|
||||
const theme = themes[state.theme]
|
||||
|
||||
if (!state.matched && text.match(theme.matcher)) {
|
||||
state.matched = true
|
||||
}
|
||||
|
||||
if (state.matched) {
|
||||
state.memory = {}
|
||||
} else {
|
||||
const halloween = ` It involves Halloween and has a ${theme.text} theme.`
|
||||
state.memory = { authorsNote: `the rest of this story is silly & playful.${halloween}` }
|
||||
}
|
||||
|
||||
return {text}
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
27
examples/commandParser.js
Normal file
27
examples/commandParser.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
// This is an example Input Modifier that looks for commands from the user.
|
||||
|
||||
const modifier = (text) => {
|
||||
let stop = false
|
||||
|
||||
// This matches when the user types in ":something arg1 arg2" in any of the three input formats. For example, they could
|
||||
// type ":status" and then command would be "status" and args would be [], or they could type ":walk north" and command
|
||||
// would be "walk" and args would be ["north"].
|
||||
const commandMatcher = text.match(/\n? ?(?:> You |> You say "|):(\w+?)( [\w ]+)?[".]?\n?$/i)
|
||||
if (commandMatcher) {
|
||||
const command = commandMatcher[1]
|
||||
const args = commandMatcher[2] ? commandMatcher[2].trim().split(' ') : []
|
||||
state.message = `Got command '${command}' with args ${JSON.stringify(args)}`
|
||||
stop = true
|
||||
text = null
|
||||
} else {
|
||||
delete state.message
|
||||
}
|
||||
|
||||
// You must return an object with the text property defined.
|
||||
// If you include { stop: true } when inside of an input modifier, processing will be stopped and nothing will be
|
||||
// sent to the AI.
|
||||
return { text, stop }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
7
examples/contextModifiers/dontBeNegative.js
Normal file
7
examples/contextModifiers/dontBeNegative.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
const modifier = (text) => {
|
||||
// This will always result in a shorter string, so no need to truncate it.
|
||||
return { text: text.replace(/ not /gi, ' ') }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
72
examples/contextModifiers/notes.md
Normal file
72
examples/contextModifiers/notes.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Notes
|
||||
|
||||
## Input Modifier
|
||||
|
||||
```js
|
||||
const modifier = (text) => {
|
||||
state.notes = state.notes || []
|
||||
|
||||
if (text.match(/> You note:/i)) {
|
||||
const note = text.replace(/> You note: ?/i, '').trim()
|
||||
state.notes.push({
|
||||
pattern: history.map(({text}) => text).join('').split("\n").pop(),
|
||||
note,
|
||||
actionCount: info.actionCount,
|
||||
})
|
||||
state.message = `Noted: ${note}`
|
||||
text = ''
|
||||
} else {
|
||||
delete state.message
|
||||
}
|
||||
|
||||
return {text}
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
||||
```
|
||||
|
||||
Set a note by typing `note: ` when in Do mode. It will be tagged to whatever the most recent line of text is, appearing below it to the AI, but not visible to the user.
|
||||
|
||||
## Context Modifier
|
||||
|
||||
```js
|
||||
// info.memoryLength is the length of the memory section of text. text.slice(0, info.memoryLength) will be the memory.
|
||||
// info.maxChars is the maximum length that text can be. The server will truncate text to this length.
|
||||
// info.actionCount is the number of actions in this adventure.
|
||||
|
||||
const modifier = (text) => {
|
||||
state.notes = state.notes || []
|
||||
|
||||
const contextMemory = info.memoryLength ? text.slice(0, info.memoryLength) : ''
|
||||
let context = info.memoryLength ? text.slice(info.memoryLength) : text
|
||||
|
||||
// Assumes that the notes are sorted from oldest to newest.
|
||||
state.notes = state.notes.filter(({ pattern, note, actionCount }) => {
|
||||
if (actionCount > info.actionCount) {
|
||||
// The user must have hit undo, removing this note.
|
||||
return false
|
||||
}
|
||||
|
||||
const index = context.indexOf(pattern)
|
||||
|
||||
if (index >- 1) {
|
||||
context = [context.slice(0, index + pattern.length), "\n", note, context.slice(index + pattern.length)].join('')
|
||||
return true
|
||||
} else {
|
||||
// Only keep ones that were found, otherwise they must have moved out of the history window.
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
// Make sure the new context isn't too long, or it will get truncated by the server.
|
||||
context = context.slice(-(info.maxChars - info.memoryLength))
|
||||
const finalText = [contextMemory, context].join("\n")
|
||||
return { text: finalText }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
||||
```
|
||||
|
||||
You can debug this by viewing what the model received in the Scenario Script page. It's the little brain icon in the upper-right.
|
23
examples/contextModifiers/reimplementAuthorsNote.js
Normal file
23
examples/contextModifiers/reimplementAuthorsNote.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Checkout the repo examples to get an idea of other ways you can use scripting
|
||||
// https://github.com/AIDungeon/Scripting/blob/master/examples
|
||||
|
||||
// info.memoryLength is the length of the memory section of text.
|
||||
// info.maxChars is the maximum length that text can be. The server will truncate the text you return to this length.
|
||||
|
||||
// This modifier re-implements Author's Note as an example.
|
||||
const modifier = (text) => {
|
||||
const contextMemory = info.memoryLength ? text.slice(0, info.memoryLength) : ''
|
||||
const context = info.memoryLength ? text.slice(info.memoryLength) : text
|
||||
const lines = context.split("\n")
|
||||
if (lines.length > 2) {
|
||||
const authorsNote = "Everyone in this story is an AI programmer."
|
||||
lines.splice(-3, 0, `[Author's note: ${authorsNote}]`)
|
||||
}
|
||||
// Make sure the new context isn't too long, or it will get truncated by the server.
|
||||
const combinedLines = lines.join("\n").slice(-(info.maxChars - info.memoryLength))
|
||||
const finalText = [contextMemory, combinedLines].join("")
|
||||
return { text: finalText }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
62
examples/deathIsland.js
Normal file
62
examples/deathIsland.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
|
||||
// Checkout the repo examples to get an idea of other ways you can use scripting
|
||||
// https://github.com/AIDungeon/Scripting/blob/master/examples
|
||||
|
||||
const modifier = (text) => {
|
||||
let modifiedText = text
|
||||
|
||||
if(!state.events){
|
||||
state.turn = 0
|
||||
state.events = [
|
||||
'You hear a rustling in the bushes near you. Suddenly',
|
||||
'An ear splitting scream suddenly echoes',
|
||||
'You feel a cold chill go up your spine. You look up and see',
|
||||
'You suddenly get hit by',
|
||||
'Before you can do that you hear a loud crash. You look towards the sound and see a dark demonic looking creature',
|
||||
'You discover a horrifying',
|
||||
'You hear a terrifying sound',
|
||||
'You wake up and realize you were dreaming. You look down and see that your arms are in shackles',
|
||||
'A hand grabs your leg and you trip hitting your head on a stone. You wake up in a cage',
|
||||
'An uneasy feeling begins to settle in your stomach as',
|
||||
'You remember a dark feeling from last night',
|
||||
'Suddenly a bloody head rolls toward you from out of the bushes',
|
||||
'You see a massive creature',
|
||||
'A band of cannibals',
|
||||
'You see a band of cannibals',
|
||||
'A dark creature',
|
||||
'You feel a sharp pain in your side and realize'
|
||||
]
|
||||
}
|
||||
else{
|
||||
modifiedText = "\n> You try to " + text.substring(7)
|
||||
}
|
||||
|
||||
state.turn = state.turn + 1
|
||||
|
||||
if(state.turn > 2){
|
||||
state.memory = {context: "You're probably going to die."}
|
||||
}
|
||||
if(state.turn > 6){
|
||||
state.memory = {context: "You're about to die."}
|
||||
}
|
||||
else if(state.turn > 10){
|
||||
state.memory = {context: "You have no hope. There are minutes left till you die."}
|
||||
}
|
||||
|
||||
const nTurn = Math.floor((Math.random() * 2)) + 3
|
||||
|
||||
if(state.turn % nTurn === 0){
|
||||
const eventInd = Math.floor((Math.random() * state.events.length));
|
||||
if(eventInd < state.events.length){
|
||||
modifiedText = modifiedText + '\n' + state.events[eventInd]
|
||||
state.events.splice(eventInd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// You must return an object with the text property defined.
|
||||
return {text: modifiedText}
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
35
examples/evaluationBots.js
Normal file
35
examples/evaluationBots.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
|
||||
// Checkout the repo examples to get an idea of other ways you can use scripting
|
||||
// https://github.com/latitudegames/Scripting/blob/master/examples
|
||||
|
||||
//CONTEXT MODIFIER
|
||||
const modifier = (text) => {
|
||||
state.evaluationBot = 'JudgeBot'
|
||||
return { text }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
||||
|
||||
|
||||
// OUTPUT MODIFIER
|
||||
const modifier = (text) => {
|
||||
console.log(info)
|
||||
return { text }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
AVAILABLE BOTS
|
||||
['KillBot', 'JudgeBot', 'EmpathyBot', 'SuccessBot', 'SantaBot'] -> Score
|
||||
['GoblinBot'] -> Goblins killed, health lost, loot gained
|
||||
['KittenBot'] -> Rapport gained, hunger
|
||||
['SpaceLootBot'] -> Loot
|
||||
['DCStatDifficultyBot'] -> Stat, Difficulty
|
||||
['HungerBot'] -> Fullness
|
||||
['SimplePossiblityBot'] -> PossibleAction1, PossibleAction2
|
||||
*/
|
39
examples/guessOrDie.js
Normal file
39
examples/guessOrDie.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Input Modifier
|
||||
const modifier = (text) => {
|
||||
if(!state.initialized) {
|
||||
state.initialized = true;
|
||||
state.randomNumber = Math.round(Math.random()*9999+1);
|
||||
state.remainingGuesses = 13;
|
||||
}
|
||||
|
||||
var match = text.match(/(\d+)/)
|
||||
if(match && match[1]) {
|
||||
state.remainingGuesses--;
|
||||
var number = parseInt(match[1]);
|
||||
|
||||
var output = "You have "+state.remainingGuesses+" guesses remaining. ";
|
||||
|
||||
if(number == state.randomNumber) {
|
||||
output += "You guessed the number! Congratulations, you win!";
|
||||
} else if (state.remainingGuesses <= 0) {
|
||||
output += "You ran out of guesses! You are dead. You lose!";
|
||||
} else if (number > state.randomNumber) {
|
||||
output += "Your guess is too high!";
|
||||
} else if (number < state.randomNumber) {
|
||||
output += "Your guess is too low!";
|
||||
}
|
||||
state.nextOutput = output;
|
||||
return {text}
|
||||
}
|
||||
state.nextOutput = "Please enter a number!";
|
||||
return {text};
|
||||
}
|
||||
|
||||
modifier(text)
|
||||
|
||||
// Output Modifer
|
||||
const modifier = (text) => {
|
||||
return {text: state.nextOutput ? state.nextOutput : ""};
|
||||
}
|
||||
|
||||
modifier(text)
|
22
examples/inputBot.js
Normal file
22
examples/inputBot.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
// Checkout the repo examples to get an idea of other ways you can use scripting
|
||||
// https://github.com/latitudegames/Scripting/blob/master/examples
|
||||
|
||||
//INPUT MODIFIER
|
||||
const modifier = (text) => {
|
||||
state.inputBot = 'DCStatDifficultyBot'
|
||||
return { text }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
||||
|
||||
|
||||
// CONTEXT MODIFIEr
|
||||
const modifier = (text) => {
|
||||
console.log(info?.inputEvaluation)
|
||||
return { text }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
37
examples/magic.js
Normal file
37
examples/magic.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Here's a fun scripting example where players have to learn these magic spells to have cool effects.
|
||||
// The world info has entries that should hopefully lead people to these spells and so that they can find and cast them.
|
||||
// Can find the scenario at https://play.aidungeon.io/scenario/e982a8f0-a473-11ea-af38-d1932fa9d9e0
|
||||
// I changed the spell names so it doesn't ruin the discovery if you play the adventure.
|
||||
|
||||
const modifier = (text) => {
|
||||
|
||||
let modifiedText = text
|
||||
state.message = ''
|
||||
|
||||
if(!state.spells){
|
||||
state.spells = []
|
||||
}
|
||||
|
||||
const spells = {
|
||||
'SPELL1': 'a deathly fire ball spell that',
|
||||
'SPELL2': 'turning yourself into a cloud allowing you to move at will',
|
||||
'SPELL3': 'a dark spell that summons an evil demon. You hear a dark rumbling and see a cloud of black smoke appear. Out of it appears a large horned demon'
|
||||
}
|
||||
|
||||
const lowered = text.toLowerCase()
|
||||
for(spellName in spells){
|
||||
if(lowered.includes('cast ' + spellName)){
|
||||
if(!state.spells.includes(spellName)){
|
||||
state.spells.push(spellName)
|
||||
state.message = "Congrats you've learned the " + spellName + " spell!"
|
||||
}
|
||||
modifiedText = text + '\n' + 'You cast ' + spellName + ', ' + spells[spellName]
|
||||
}
|
||||
}
|
||||
|
||||
return {text: modifiedText}
|
||||
}
|
||||
|
||||
modifier(text)
|
||||
|
||||
|
15
examples/showTextLength.js
Normal file
15
examples/showTextLength.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
// Checkout the repo examples to get an idea of other ways you can use scripting
|
||||
// https://github.com/latitudegames/Scripting/blob/master/examples
|
||||
|
||||
|
||||
// OUTPUT MODIFIER
|
||||
const modifier = (text) => {
|
||||
|
||||
state.displayStats = [{key:'Text Length', value: text.length, color: 'red'}]
|
||||
|
||||
return { text }
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
13
examples/skills.js
Normal file
13
examples/skills.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
//input modifiers to set up skills
|
||||
|
||||
//creates skills with 5 skill points (for input modifier)
|
||||
const modifier = (text) => {
|
||||
state.skills = {'turtle':1}
|
||||
state.skillPoints = 5
|
||||
state.disableRandomSkill = true
|
||||
return ({text})
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
||||
|
11
examples/stats.js
Normal file
11
examples/stats.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
//input modifiers to set up stats
|
||||
|
||||
// creates stats to open up the stats overlay
|
||||
const modifier = (text) => {
|
||||
state.stats = {stats:{strength:{level: 4, cost:2}, agility:{level: 1, cost:5},}, statPoints:50}
|
||||
return ({text})
|
||||
}
|
||||
|
||||
// Don't modify this part
|
||||
modifier(text)
|
||||
|
122
examples/sundale.js
Normal file
122
examples/sundale.js
Normal file
|
@ -0,0 +1,122 @@
|
|||
// An example of how scripting can be used to manipulate quests, as well as how messages and the state variable can be used to store and show information
|
||||
// The code can be given basic changes using the state.configuration object, without needing to deal with the rest of the code
|
||||
// The scenario this was made for can be seen at https://play.aidungeon.io/scenario/71bab1a0-9d70-11ea-8733-c15678a0b129
|
||||
|
||||
// INPUT MODIFIER
|
||||
|
||||
const modifier = (text) => {
|
||||
state.configuration = {
|
||||
enableSelectionOnCompletedQuest: false, // Whether quest selection should be restricted until a specific quest is completed
|
||||
enableSelectionOnQuest: 0, // The line number of the quest in the list of quests (e.g. quest on second line = 2) on the Edit Scenario page. Only used when the above is true.
|
||||
initialQuests: 0, // The amount of quests inputted into the Edit Scenario page
|
||||
quests: [ // The quests that will become available to the player either after the above quest is completed or at the start of the scenario.
|
||||
{
|
||||
name: "quit your job", // The quest's name, shown in the selection message
|
||||
objectives: ["resign from your job"], // The objectives that are part of the quest
|
||||
nextQuests: [ // The quests that should be assigned after the player completes this one
|
||||
{
|
||||
name: "find a new job",
|
||||
objectives: ["get a job"],
|
||||
nextQuests: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if (state.initialised != true) {
|
||||
state.finishedScenario = false
|
||||
state.initialised = true
|
||||
if (!state.configuration.enableSelectionOnCompletedQuest) {
|
||||
state.availableQuests = JSON.parse(JSON.stringify(state.configuration.quests))
|
||||
} else {
|
||||
state.availableQuests = []
|
||||
}
|
||||
state.assignedQuest = ""
|
||||
state.nextOutput = ""
|
||||
}
|
||||
|
||||
state.nextOutput = ""
|
||||
|
||||
if (text.toLowerCase().startsWith("\n> you take up quest ")) {
|
||||
state.assignedQuest = JSON.parse(JSON.stringify(state.availableQuests[text.toLowerCase().substring(21) - 1]))
|
||||
quests.push({
|
||||
quest: state.assignedQuest.objectives.shift()
|
||||
})
|
||||
state.nextOutput = "You decide that the next thing you want to do with your life is " + state.assignedQuest.name.toLowerCase() + "."
|
||||
} else if (text.toLowerCase().includes("\n> you give up on your quest.")) {
|
||||
state.nextOutput = "You give up on your quest to " + state.assignedQuest.name.toLowerCase() + "."
|
||||
state.assignedQuest = ""
|
||||
quests.splice(state.configuration.initialQuests)
|
||||
}
|
||||
|
||||
return {
|
||||
text: text
|
||||
}
|
||||
}
|
||||
|
||||
modifier(text)
|
||||
|
||||
|
||||
// OUTPUT MODIFIER
|
||||
|
||||
const modifier = (text) => {
|
||||
|
||||
let modifiedText = text
|
||||
|
||||
if (!state.finishedScenario || !state.configuration.enableSelectionOnCompletedQuest) state.message = ""
|
||||
|
||||
if ((state.finishedScenario || !state.configuration.enableSelectionOnCompletedQuest) && state.assignedQuest == "") {
|
||||
questNames = []
|
||||
for (quest of state.availableQuests) {
|
||||
questNames.push(quest.name)
|
||||
}
|
||||
state.message = "Available Quests: " + questNames.join(", ") + ". To take up a quest, type 'take up quest <quest number in list>'."
|
||||
} else if (state.assignedQuest != "") {
|
||||
if (!quests[state.configuration.initialQuests].completed) {
|
||||
state.message = "Current Objective: " + quests[state.configuration.initialQuests].quest + ". To quit, type 'give up on my quest'."
|
||||
} else {
|
||||
nextObjective = state.assignedQuest.objectives.shift()
|
||||
if (nextObjective == undefined) {
|
||||
quests.splice(state.configuration.initialQuests)
|
||||
state.availableQuests = state.availableQuests.filter(e => e.name !== state.assignedQuest.name)
|
||||
for (nextQuest of state.assignedQuest.nextQuests) {
|
||||
state.availableQuests.push(nextQuest)
|
||||
}
|
||||
state.assignedQuest = ""
|
||||
questNames = []
|
||||
for (quest of state.availableQuests) {
|
||||
questNames.push(quest.name)
|
||||
}
|
||||
state.message = "Available Quests: " + questNames.join(", ") + ". To take up a quest, type 'take up quest <quest number in list>'."
|
||||
} else {
|
||||
quests.splice(state.configuration.initialQuests)
|
||||
quests.push({
|
||||
quest: nextObjective
|
||||
})
|
||||
state.message = "Objective completed! New objective: " + quests[state.configuration.initialQuests].quest + ". To quit, type 'give up on my quest'."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state.configuration.enableSelectionOnCompletedQuest) {
|
||||
if (quests[state.configuration.enableSelectionOnQuest - 1].completed == true && !state.finishedScenario) {
|
||||
state.message = "Quests have been assigned and will be accessible next turn."
|
||||
state.finishedScenario = true
|
||||
state.availableQuests = JSON.parse(JSON.stringify(state.configuration.quests))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (state.nextOutput !== "") {
|
||||
return {
|
||||
text: state.nextOutput
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
text: modifiedText
|
||||
};
|
||||
}
|
||||
|
||||
modifier(text)
|
Reference in a new issue