Appending a randomly generated number to a string to make an attribute
fvu109
22 Sept 2020, 17:15Is there a way to generate a random number and append it to an attribute, eg
@set description1 = The car was red
@set description2 = The bus was blue
[[next]]
[[next]]:
var randomnumber = function rng(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
set ("rnd", randomnumber(1,2));
...and then append the rnd result to description to make {description1} or {description2}, randomly displaying either 'The car was red' or 'The bus was blue' (without having to do if statements for each possible result of rnd)?
And somewhat related, is there a way to set an attribute with another attribute in it?
@set colour = red
@set description1 = The car was {colour}
...just produces The car was {colour} from {description1}
mrangel
22 Sept 2020, 19:38For the first, I think your javascript should be:
squiffy.set("result", squiffy.get("description" + randomnumber(1,2));
It's probably easier to do in javascript, because you can combine a string and a random number to get the parameter you need for squiffy.get
to get a Squiffy attribute.
If you want it to work with other attributes inside that string, you'd want to call processText. Something like this:
var rnd = randomnumber(1,2);
var result = squiffy.get("description" + rnd);
result = squiffy.ui.processText(result);
squiffy.set("result", result);
So you can then use {result}
in your text.
If you don't need to do anything else with the result before it's displayed, you can compress that down into a single line:
squiffy.set("result", squiffy.ui.processText(squiffy.get("description" + randomnumber(1,2))));
which is more efficient, but may be harder to read if you're not used to looking at code.
fvu109
22 Sept 2020, 21:11mrangel :)
var randomnumber = function rng(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
squiffy.set("result", squiffy.get("description" + randomnumber(1,2)));
{result}
works beautifully for me, thank you :)
Could you elaborate on the processText alternative? I can't get either to work in my demo, but I'd like to know more - could I use it to stick together (technical term!) different attributes and random results?
fvu109
22 Sept 2020, 21:40Also this is a real rookie question (but I still don't have my head around javascript). In this example from one of the other solutions you've helped me with, how would I append (or prepend) a string of drag to the pageNumber created by the rng so that I'd have an attribute of {dragA} {dragB} etc (dependent on what the rng generated)?
squiffy.set("pagesToVisit", "ABCDEFGHIJKLMNOPQRST")
var pages = get("pagesToVisit");
if (pages) {
var rnd = pages.charAt(Math.floor(Math.random() * pages.length)); // pick a random character from pages
squiffy.set("pageNumber", rnd);
squiffy.set("pagesToVisit", pages.replace(rnd, "")); // remove that page from the list so it won't be picked again
} else {
squiffy.story.go("leftStanding");
}
mrangel
23 Sept 2020, 20:46Could you elaborate on the processText alternative? I can't get either to work in my demo, but I'd like to know more
Here's what I've tried. It seems to work for me:
@title Dumb test game
[[first section]]:
window.randomnumber = function(min, max) {
return Math.floor(Math.random() * (1 + max - min) + min);
};
@set color1 = red
@set color2 = blue
@set color3 = green
@set description1 = The car is {color}
@set description2 = The truck is {color}
The initial attributes are set. Would you like to [[pick a color]] or [[pick a description]]?
[[pick a color]]:
var rnd = randomnumber(1,3);
var result = squiffy.get("color" + rnd);
result = squiffy.ui.processText(result);
squiffy.set("color", result);
Okay, so far we've picked a color. It was {color}.
Next, would you like to [[pick a color]] or [[pick a description]]?
[[pick a description]]:
var rnd = randomnumber(1,2);
var result = squiffy.get("description" + rnd);
result = squiffy.ui.processText(result);
squiffy.set("description", result);
You look at the traffic. {description}.
Next, would you like to [[pick a color]] or [[pick a description]]?
To summarise how it works:
-
var rnd = randomnumber(1,2);
Gets a random number from 1 to 2, and puts that in the javascript variablernd
. -
var result = squiffy.get("description" + rnd);
Sticks the string"description"
and the value ofrnd
together to get a name likedescription2
, and usessquiffy.get
to get the value of the named attribute, which it puts in the javascript variableresult
. -
result = squiffy.ui.processText(result);
Does the text processor thing to the text inresult
, the same as is done with a section's description when visiting it. This changes{color}
to the current value of thecolor
attribute and similar things. The result is stored back in the javascript variableresult
. -
squiffy.set("description", result);
Sets the squiffy attributedescription
to the value of the javascript variableresult
. This means that you can then use{description}
in your section text.
Also this is a real rookie question (but I still don't have my head around javascript). In this example from one of the other solutions you've helped me with, how would I append (or prepend) a string of drag to the pageNumber created by the rng so that I'd have an attribute of {dragA} {dragB} etc (dependent on what the rng generated)?
OK, I'm not sure exactly what you mean here.
This line:
squiffy.set("pageNumber", rnd);
sets the attribute pagenumber
to the randomly chosen letter. If you want to do something else, you'll want to put a different line either after or instead of that one. Different things you might want include:
-
Set an attribute (let's call it
pagename
) to a string like "dragA" or "dragB"
squiffy.set("pagename", "drag" + rnd);
-
Set an attribute (let's call it
dragrnd
to the contents of the attributedargA
etc, so you can use{dragrnd}
instead of{dragA}
,{dargB}
, etc.
squiffy.set("dragrnd", squiffy.get("drag" + rnd));
-
Go to the page
dragA
,dragB
, or so on.
squiffy.story.go("drag" + rnd);
Is one of these what you wanted, or am I missing something?
fvu109
23 Sept 2020, 21:53First thing - brilliant, that's exactly what I needed! I'm trying to construct unique passages using random choices for each part of the sentence, and that does it beautifully, thank you!
On the second one, I think what I'm after is your second example:
squiffy.set("dragrnd", squiffy.get("drag" + rnd));
...so that I can use {dragrnd} instead of having to specify dragA, dragB etc. However for me {dragrnd} is returning null if I use it like this:
var pages = get("pagesToVisit");
if (pages) {
var rnd = pages.charAt(Math.floor(Math.random() * pages.length)); // pick a random character from pages
squiffy.set("dragrnd", squiffy.get("drag" + rnd));
squiffy.set("pagesToVisit", pages.replace(rnd, "")); // remove that page from the list so it won't be picked again
} else {
squiffy.story.go("leftStanding");
}
{dragrnd}
A further thought (once it's not returning null!) - would I be able to stick a string on the beginning and the end of rnd, like
squiffy.set("dragcolour", squiffy.get("drag" + rnd + _colour));
to produce an attribute {dragcolour} that would return the value of dragA_colour, dragB_colour etc?
mrangel
24 Sept 2020, 09:00...so that I can use {dragrnd} instead of having to specify dragA, dragB etc. However for me {dragrnd} is returning null if I use it like this:
That looks like it should work. Are you sure that the attribute pagesToVisit
has been set before that point?
I can only see 'null' coming out of that in 3 situations:
pagesToVisit
hasn't been set yet- all the options have already been used
- one of the
dragA
,dragB
,dragC
attributes hasn't been set yet (if the one that gets picked is null, dragrnd will be null as well)
squiffy.set("dragcolour", squiffy.get("drag" + rnd + _colour));
Should be squiffy.set("dragcolour", squiffy.get("drag" + rnd + "_colour"));
, because _colour
is a string rather than the name of a javascript variable.
fvu109
25 Sept 2020, 11:57Ahh, that was what I hadn't done - defined dragA, dragB etc. Thank you!
That makes sense on the string, too. Honestly, I'm nearly there with this game (she says, after six months...)
fvu109
25 Sept 2020, 12:30Of course I have another question : )
So I have this:
@set dragA = Bob
@set dragB = Fred
@set dragA_hatched=false
@set dragB_hatched=false
squiffy.set("pagesToVisit", "AB")
var pages = get("pagesToVisit");
if (pages) {
var rnd = pages.charAt(Math.floor(Math.random() * pages.length)); // pick a random character from pages
squiffy.set("dragrnd", squiffy.get("drag" + rnd));
squiffy.set("pagesToVisit", pages.replace(rnd, "")); // remove that page from the list so it won't be picked again
} else {
squiffy.story.go("leftStanding");
}
{dragrnd} has hatched
Once a drag eg dragA has been randomly selected, dragA_hatched needs to change to 'true' (as that true/false is used elsewhere) - can that be done?
mrangel
25 Sept 2020, 14:18I think squiffy.set("drag" + rnd + "_hatched", true);
may be the line you're looking for.
mrangel
25 Sept 2020, 14:23Also, if you're pasting a whole bunch of code in the forum, rather than putting `
s on each line, you can put three of them before and three after, like this:
```
here is some code
as many lines as you want {
and we can see the spaces
at the start of the lines
so it's easier to read
}
```
fvu109
29 Sept 2020, 16:29You thought I'd gone away satisfied, didn't you? Ahahahahaha nope!
So the player randomly selected a dragon (eg dragA, dragB), and whatever drag they select additionally gets eg dragA_current=true
set for them to indicate that dragA is the one currently in focus. {dragCurrent}
returns a true/false based on dragA_current
.
@set dragA = Bob
@set dragB = Fred
@set dragA_hatched=false
@set dragB_hatched=false
@set dragA_current=false
@set dragB_current= false
squiffy.set("pagesToVisit", "AB")
var pages = get("pagesToVisit");
if (pages) {
var rnd = pages.charAt(Math.floor(Math.random() * pages.length)); // pick a random character from pages
squiffy.set("dragname", squiffy.get("drag" + rnd));
squiffy.set("drag" + rnd + "_current", "true");
squiffy.set("dragCurrent", squiffy.get("drag" + rnd + "_current"));
squiffy.set("pagesToVisit", pages.replace(rnd, "")); // remove that page from the list so it won't be picked again
} else {
squiffy.story.go("leftStanding");
}
{dragname} has hatched{if dragCurrent=true: and is the current dragonet}. But he doesn't seem interested in you.
[[Leave him alone and wait for another dragon to hatch]](Hatching)
[[Try harder]](Try harder)
However if (after other stuff happens in that section) dragA isn't interested in the player, dragA_current
needs to be set back to false so that the next dragon can be set to current. I tried this with:
[[Leave him alone and wait for another dragon to hatch]](Hatching,dragCurrent=false)
but that doesn't affect dragA_current
- it remains set to true.
Obviously by this point in the passage I can't set it using another line of javascript because the javascript always has to be the first thing in the section! Any advice?
mrangel
29 Sept 2020, 20:10I'd suggest setting an attribute to the chosen letter, so you can access it on other pages.
For example:
squiffy.set("chosenLetter", rnd);
Then you can have your link not modifying the variables yet:
[[Leave him alone and wait for another dragon to hatch]](Hatching)
And have the Hatching page set it to false as soon as the player gets there, before doing anything else:
[[Hatching]]:
if(squiffy.get("dragCurrent")) {
squiffy.set("dragCurrent", false);
squiffy.set("drag" + squiffy.get("chosenLetter") + "_current", false);
}
Does that make sense?
fvu109
29 Sept 2020, 20:41Yes it does - in fact the even more simple way I realised I could do, it based on your solution was
squiffy.set("chosenLetter", rnd);
[[Leave him alone and wait for another dragon to hatch]](Hatching, {chosenLetter}_current=false)
Thank you!
mrangel
29 Sept 2020, 20:59Nice :) I wasn't 100% sure that would work, but good to see it does :)