Issues with dynamic list


#1

So Fiogan and I stumbled into a coding problem recently and we are trying to figure it out; I was wondering if anybody had any suggestions?

Here is the situation:

The MC is in a pet shop and can visit four different kinds of animals. After each visit, we want to be able to list the animals that have not been visited yet.

The choice looks like this:

*choice
  #Watch the dragon breath fire.
  #Make fish faces with the decapus.
  #Pet the jackalope.
  #Let one of the phantom kitties chase the dot from your laser pen.
  #Actually, I'll come back a little later.

When it loops to the choice to visit to a pet, we want to have a sentence that displays the pets still remaining to visit. We want the list of animals remaining to be in one sentence with the correct use of ‘and’ and (Oxford) commas:

'You only have X left to visit.'
'You still have X and Y left to see.'
'You haven't seen X, Y, or Z.'
'You haven't visited any of the pets yet! Would you like to see X, Y, Z, or W?'

For instance, if the player has only visited the dragon, once the loop returns to the *choice shown above, this would be displayed:

You haven't seen the aquatic decapus, the little jackalope, or the phantom kitties.

The player can visit the pets in any order and can leave at any time and come back later. When the player returns later, we would want to display the list of pets still left to visit again.


#2

Here’s a first draft solution.
You may still need to find a way to insert any appropriate punctuation between pets.

*temp pet1 0
*temp pet2 0
*temp pet3 0
*temp pet4 0
*temp pet5 0
*temp petw "the dragon"
*temp petx "the decapus"
*temp pety "the jackalope"
*temp petz "the phantom kitties"

*label petloop
*set pet5 0
*set pet5 +pet1
*set pet5 +pet2
*set pet5 +pet3
*set pet5 +pet4

*if pet5 = 0
 You haven't visited any of the pets yet! Would you like to see ${petw}, ${petx}, ${pety} or ${petz}?

*if pet5 = 1
 You haven't seen: 
 *if pet1 = 0
  ${petw}
 *if pet2 = 0
  ${petx}
 *if pet3 = 0
  ${pety}
 *if pet4 = 0
  ${petz}

*if pet5 = 2
 You still have these two to see: 
 *if pet1 = 0
  ${petw}
 *if pet2 = 0
  ${petx}
 *if pet3 = 0
  ${pety}
 *if pet4 = 0
  ${petz}

*if pet5 = 3
 You only have
 *if pet1 = 0
  ${petw} 
 *if pet2 = 0
  ${petx} 
 *if pet3 = 0
  ${pety} 
 *if pet4 = 0
  ${petz} 
 left to visit.

Where do you want to go?

*choice
 *selectable_if (pet1 = 0) #Watch the dragon breath fire.
  *set pet1 1
  *goto petdragon
 *selectable_if (pet2 = 0) #Make fish faces with the decapus.
  *set pet2 1
  *goto petfish
 *selectable_if (pet3 = 0) #Pet the jackalope.
  *set pet3 1
  *goto petjackalope
 *selectable_if (pet4 = 0) #Let one of the phantom kitties chase the dot from your laser pen.
  *set pet4 1
  *goto petkitties
 #Actually, I'll come back a little later.

#3

From Vampire’s language list, with modification:

*label languages
*temp number_of_languages 0
*if ethnicity = "choctaw"
	*set number_of_languages +1
*if speaks_english
	*set number_of_languages +1
*if speaks_french
	*set number_of_languages +1
*if speaks_german
	*set number_of_languages +1
*if speaks_latin
	*set number_of_languages +1
*if speaks_spanish
	*set number_of_languages +1

*if ethnicity = "choctaw"
	*set languages &"Choctaw"
	*set comma true
*if speaks_english
	*gosub comma_check
	*set languages &"English"
	*set comma true
*if speaks_french
	*gosub comma_check
	*set languages &"French"
	*set comma true
*if speaks_german
	*gosub comma_check
	*set languages &"German"
	*set comma true
*if speaks_latin
	*gosub comma_check
	*set languages &"Latin"
	*set comma true
*if speaks_spanish
	*gosub comma_check
	*set languages &"Spanish"
	*set comma true
Language(s): ${languages}.

*label comma_check
*if comma
	*set languages &", "
	*if number_of_languages = 1
		*set languages &"and "
	*set number_of_languages -1

(Didn’t test it, there may be a bug in there somewhere, but still, you get the idea).


#4

For oxford comma, you’d need to decrement the counter; as-is I think you just get commas with no final and/or with more than two.

You’d need separate total and remaining counts to have a special case for two; otherwise just one counter should be fine.


#5

You can, but it’s not necessary. It’s not incorrect to use a serial comma in a list of two items, and a serial comma may even be necessary for longer lists of two items.


#6

Here’s my take on the problem. It’s actually a lot simpler then it seems due to how the sentence changes depending on how many pets are left. The main trick I used here was array index swapping.

*label list_demo

*temp visits 0
*temp pet_0 "dragon"
*temp pet_1 "aquatic decapus"
*temp pet_2 "little jackalope"
*temp pet_3 "phantom kitties"
*temp swap ""

*label start

*if (visits = 0)
    You haven't visited any of the pets yet! Would you like to see the ${pet[0]}, the ${pet[1]}, the ${pet[2]}, or the ${pet[3]}?
*elseif (visits = 1)
    You haven't seen the ${pet[0]}, the ${pet[1]}, or the ${pet[2]}.
*elseif (visits = 2)
    You still have the ${pet[0]} and the ${pet[1]} left to see.
*elseif (visits = 3)
    You only have the ${pet[0]} left to visit.
*else
    You have already visited all the pets.

*choice
    *hide_reuse #Watch the dragon breath fire.
        *gosub list_remove "dragon"
        The dragon breathes a lot of fire and generally stomps around making a giant amount of noise.
        *page_break
    *hide_reuse #Make fish faces with the decapus.
        *gosub list_remove "aquatic decapus"
        The decapus is quite unimpressed by your hideous human face.
        *page_break
    *hide_reuse #Pet the jackalope.
        *gosub list_remove "little jackalope"
        You stay to pet the little jackalope and it loves it, but at the end, it tires of your pawing and nips your hand.
        *page_break
    *hide_reuse #Let one of the phantom kitties chase the dot from your laser pen.
        *gosub list_remove "phantom kitties"
        The phantom kitties swarm the dot as soon as you press the button and you have hours of fun, but then the kittens grow bored and one of them barfs an invisible hairball on your lap.
        *page_break
    #Actually, I'll come back a little later.
        *goto come_back

*goto start

*label come_back

So, do you want to go back, or leave?

*choice
    #Go back to visit
        *goto start
    #I'm done here
        *ending

*label list_remove

*params value

*temp count 0

*label loop_start

*if (pet[count] = value)
    *set pet[count] pet[3 - visits]
    *set visits +1
    *return
*else
    *set count +1
    *goto loop_start

*return

… I feel like the *if statement can be streamlined a bit using multi-replace or the like, but I’m outta time!


#7

I’m pretty sure the current code would give you 1, 2, 3 rather than 1, 2, and 3. Just decrementing the variable you already have would get 1, 2, and 3; you’d only need a second variable if you specifically want 1 and 2 instead of 1, and 2.

So you’d want a

*set number_of_languages -1

In the comma check block


#8

I said there would be bugs :stuck_out_tongue: (but fixed I think).


#9

A great solution! Me and Fiogan actually came up with a very similar one to yours some time after we posted this. I thought it would be cool to see what other solutions others could come up with so I didn’t post it at the time; also wanted to see if there was another simpler method without using arrays.

Thanks for everyone that chimed in. Our solution is below; it’s fully functional so those interested can simply run this file as a project startup in CSIDE. If anyone wants to use a similar script for their game, feel free!

Click
*title Test
*author Mouse
*create implicit_control_flow true
*temp places 4
*temp place_1 "the decapus"
*temp place_2 "the phantom kitties"
*temp place_3 "the fire-breathing dragon"
*temp place_4 "the jackalope"
*temp donekitties false
*temp donedecapus false
*temp donedragon false
*temp donejackalope false
*temp search false
*temp used 1
Let's go to Penelope's Paranormal Pets and Rescue!
*label loop
*if (search)
  Which pet would you like to visit now?
*choice
  *if ((search) and (places < 1))
    *selectable_if (false) #You've visited all the pets!
  *if ((search) and (places > 0)) #Visit another pet.
    *gosub searches
    You@{places  only have| just have| have |'ve} @{places ${place[1]}|${place[1]} and ${place[2]}|${place[1]}, ${place[2]}, and ${place[3]}|${place[1]}, ${place[2]}, ${place[3]}, and ${place[4]}} @{places left.|still remaining.|left to see.|to visit.}
    *goto wheretosearch
  *if (search = false) #Visit one of the cute pets.
    *set search true
    Which pet would you like to visit?
    *label wheretosearch
    *choice
      *selectable_if (donedragon = false) #Watch the dragon breathe fire.
        *choice
          #They're busy making smoke signals; I'll come back later.
            You turn away from the dragon's massive glass enclosure.
            *goto loop
          #The dragon's breathing fire! Time to watch.
            *set places -1
            *set donedragon true
            The fire is all sorts of colours: peligin, jale, flange, and octarine.
            *goto loop
      *selectable_if (donedecapus = false) #Make fish faces with the decapus.
        *set places -1
        *set donedecapus true
        The decapus makes land-creature faces with you and seems to have a lovely time.
        *goto loop
      *selectable_if (donejackalope = false) #Pet the jackalope.
        *set places -1
        *set donejackalope true
        The jackalope loves to be patted on her shiny horns. You make sure to stay away from the sharp teeth, and she purr-hums happily.
        *goto loop
      *selectable_if (donekitties = false) #Let one of the phantom kitties chase the dot from my laser pen.
        *set places -1
        *set donekitties true
        The kitties fly across the room, their wings flapping steadily as they dart after the tiny green dot of light. Fly, kitties, fly!
        *goto loop
  #Leave the pet shop.
    Hwyl fawr!
    *ending
*label searches
*set used 1
*if (donekitties = false)
    *set place[used] "the wee phantom felines"
    *set used +1
*if (donejackalope = false)
    *set place[used] "the jackalope"
    *set used +1
*if (donedragon = false)
    *set place[used] "the enormous dragon"
    *set used +1
*if (donedecapus = false)
    *set place[used] "the tentacley decapus"
*return