Gamebook: Going between random pages?

makarr
17 Apr 2022, 21:47Hello! alrighty, here's the situation: I'm working in a gamebook for the first time, since it'll suit my current relatively simple project, and the main hurdle is one initial script.
I suppose the easiest way to visualize it is something like tinder; you are presented a profile; matching would lead down a path of scenes, but the 'pass' script would switch the page to a different profile, randomly chosen out of the pool of pages. I suppose it could be easiest to be a function recalled every time, since it's the same command no matter which profile you're on
I don't need it to exclude pages visited before and don't care if the same profile is randomly visited twice in a row, so hopefully that makes it easier! :)
mrangel
17 Apr 2022, 22:40I think the simplest option would be to have a 'randomiser' script page, that sends you to a random profile whenever you visit it.
Off the top of my head, something like:
profiles = Split("some page;another page;a different page;more of these")
number = GetRandomInt(1, ListCount (profiles)) - 1
player.parent = GetObject (ListItem (profiles, number))
Where the string some page;another page;a different page;more of these
is a list of page names that it could send you to.
If you wanted it to avoid duplicates, that would be:
if (not HasAttribute (this, "profiles")) {
// This line initialises the list of possibilities the first time we get here
this.profiles = Split("some page;another page;a different page;more of these")
}
number = GetRandomInt(1, ListCount (profiles)) - 1
next_profile = GetObject (ListItem (profiles, number))
list remove (this.profiles, next_profile)
if (ListCount (this, "profiles") = 0) {
// This block runs if this is the last profile the player hasn't seen.
// Here we reset the list and start again; if you want to do something else when the last one is visited, do it here
this.profiles = Split("some page;another page;a different page;more of these")
}
player.parent = next_profile

makarr
18 Apr 2022, 00:24Like, this as a page script?
profiles = Split("Test1;Test2;Test3")
number = GetRandomInt(1, ListCount (profiles)) - 1
player.parent = GetObject (ListItem (profiles, number))
mrangel
18 Apr 2022, 08:25I think that should work :)

makarr
18 Apr 2022, 16:43Putting that as a script page and trying to go to that page results in this:
Error running script: Error compiling expression 'GetObject (ListItem (profiles, number))': FunctionCallElement: Could find not function 'GetObject(Object)'
Which is odd for the function itself to not be recognized.
mrangel
18 Apr 2022, 19:02Ugh… type checking in Quest is weird. Sorry I missed that; was on my phone so it wasn't easy to test it.
Try changing ListItem
to StringListItem
.

makarr
19 Apr 2022, 13:02That's not it; I think it's the GetObject function that's causing trouble...
mrangel
19 Apr 2022, 17:24That's not it; I think it's the GetObject function that's causing trouble...
That is it. I made a test game, and can confirm that changing ListItem
to StringListItem
fixes that error.
You'll still get an error if one of the page names is spelled wrong in your list, but it would say Error running script: Error evaluating expression 'GetBoolean(player.parent, "runscript") or GetBoolean(player.parent, "runscriptonly")': GetBoolean function expected object parameter but was passed 'null'
.
The issue is because GetObject
and ListItem
are both built-in functions. This means that Quest will attempt to save processing time by checking whether they have the right types before attempting to run them. ListItem
can return either an object or a string, depending what type of data is in the list – so before allowing the line to run, the engine checks for the existence of typed functions GetObject(string)
(which exists) and GetObject(object)
(which doesn't). Even though we know in this case that the list's items are all strings, the error is based on the types that the ListItem
function is hypothetically capable of returning. So it's necessary to explicitly use StringListItem
or ObjectListItem
if you put it inside another built-in function.

makarr
20 Apr 2022, 00:50You're right! Sorry about that doubt-- and thank you so so much for working with me!