Appending a randomly generated number to a string to make an attribute

fvu109
22 Sept 2020, 17:15

Is 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:38

For 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:11

mrangel :)

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:40

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)?

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:46

Could 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 variable rnd.

  • var result = squiffy.get("description" + rnd);
    Sticks the string "description" and the value of rnd together to get a name like description2, and uses squiffy.get to get the value of the named attribute, which it puts in the javascript variable result.

  • result = squiffy.ui.processText(result);
    Does the text processor thing to the text in result, the same as is done with a section's description when visiting it. This changes {color} to the current value of the color attribute and similar things. The result is stored back in the javascript variable result.

  • squiffy.set("description", result);
    Sets the squiffy attribute description to the value of the javascript variable result. 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 attribute dargA 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:53

First 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:57

Ahh, 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:30

Of 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:18

I think squiffy.set("drag" + rnd + "_hatched", true); may be the line you're looking for.


mrangel
25 Sept 2020, 14:23

Also, 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:29

You 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:10

I'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:41

Yes 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:59

Nice :) I wasn't 100% sure that would work, but good to see it does :)