Loops and Arrays in AYA/YAYA

So what's the deal with arrays, and why do you need them? Simply put, arrays are a flexible list of values that you can add to, remove from, and generally manipulate however you want. Want to store a list of words that the user has input? Want to save a bunch of similar variables in a compact way? How about an inventory of items that can be easily tracked? Arrays have got you covered!

This guide will also include information about loops, since arrays and loops go hand in hand. If you can learn both of them, they'll open up a ton of options to you! You can achieve a lot with just if/else, but loops/arrays open up a whole new world. Also note: I'm covering AYA/YAYA syntax specifically, but the basic concepts apply to most modern programming languages.


Simple Arrays

First of all, AYA/YAYA have two different kinds of arrays: Simple Arrays and General Purpose Arrays. A simple array is not a true array, though they are very useful. A simple array is a string separated by commas. By attaching an index number, you can pull out the text between the commas. This is what it looks like to declare a simple array:

ColorArray = "Red,Green,Blue"

"%(ColorArray[0])" //This would display 'Red' in dialogue
"%(ColorArray[1])" //This would display 'Green' in dialogue
"%(ColorArray[2])" //This would display 'Blue' in dialogue

As you can see, a string separated by commas is stored in the variable ColorArray. Then, by calling ColorArray with an index number in brackets, you can pull out specific parts of the array. Index numbers start from 0, don't forget that! This is also how double envelopes work, if you're familiar with the GT Template.

One more note about simple arrays: you can actually use any delimiter, not just commas! That would look like this:

ColorArray = "Red|Green|Blue"

"%(ColorArray[0,'|'])" //This would display 'Red' in dialogue
"%(ColorArray[1,'|'])" //This would display 'Green' in dialogue
"%(ColorArray[2,'|'])" //This would display 'Blue' in dialogue

All you have to do is include the delimiter you want to use inside the brackets with the index number. You can use anything you want, | is just a personal preference of mine (it can't be used in file names, which is very handy if you're working with files).

A lot of SHIORI functions return values as simple arrays, so you should familiarize yourself with them! You can also convert a simple array to a general purpose array, but I'll cover that a bit further down.


General Purpose Arrays

Alright, so here's the deal. Simple arrays are fairly unique to AYA/YAYA, as far as I know. No other language treats comma-separated strings like an array. Most languages have something like general purpose arrays, and general purpose arrays are where the real magic happens! This is what it looks like to declare a general purpose array:

ColorArray = ("Red","Green","Blue")

"%(ColorArray[0])" //This would display 'Red' in dialogue
"%(ColorArray[1])" //This would display 'Green' in dialogue
"%(ColorArray[2])" //This would display 'Blue' in dialogue

This may look very similar to the simple array, but it's actually very different. As you can see, inside the () are three different values; three different strings separated by commas. You can still access them with index numbers, the same as a simple array, but you can do so much more!

Something important about general purpose arrays: since they're not just a string, you can store any type of variable you want in them (besides other arrays)! Here's an example with a string, an int, and a float/real number:

ExampleArray = ("String",42,3.14)

_sum = ExampleArray[1] + ExampleArray[1]
//Since ExampleArray[1] (42) is stored as an integer, adding them like this will give you a result of 84.

Mix and match types to your heart's content! Don't forget that you can use TOINT, TOSTR, and TOREAL to convert types if you need to. Now, on to dynamically adding/changing/removing values in arrays...

First of all, lets cover how to add new elements to an array. If you know what index number you want to store your value in, then you can just write it like so:

ColorArray[3] = "Yellow"
//The array now contains Red, Green, Blue, and Yellow

"%(ColorArray[3])" //This would display 'Yellow' in dialogue

You can use this to create a new element, or to change an existing element. Lets say I decided that I want orange instead of yellow. I can change it just like I would a normal variable, I just have to give it the index number of the element I want changed.

ColorArray[3] = "Orange"
//The array now contains Red, Green, Blue, and Orange

"%(ColorArray[3])" //This would display 'Orange' in dialogue

Great! But the thing is, when working with arrays, you often don't know what the index number of a particular value is, especially if you're creating dynamic lists. Thankfully, adding a new element to an array without knowing the index number is super easy:

ColorArray ,= "Purple"
//The array now contains Red, Green, Blue, Orange, and Purple

"%(ColorArray[4])" //This would display 'Purple' in dialogue

,= is a great operator that assigns a new element to an array, making it the last element in the list. You can add as much as you want to your array this way!

Alright, so what if I don't know what index number an element of my array is, but I want to change it? There's a function to help with that called ASEARCH. ASEARCH will search an array for a value, and return the index number. For example:

_i = ASEARCH("Blue",ColorArray)
//"Blue" is element 2 in the array (remember that the count starts from 0), so _i now contains the value 2
ColorArray[_i] = "Cyan" //You can use variables that contain numbers as the index! So this would change element 2

//The array now contains Red, Green, Cyan, Orange, and Purple

"%(ColorArray[2])" //This would display 'Cyan' in dialogue

ASEARCH is a bit advanced, but you should know it exists. It takes two arguments, the key, and the array. The key is the exact string you want to search for, and the array is the array you want to search in. Make sure you get the order of those two arguments correct, it's backwards from how most other functions work so it's easy to mix up. Also note: if ASEARCH does not find the element you searched for, it will return -1.

A note about ASEARCH: it will only return the first value that it finds. If you know there are more than 1 of the same value in your array, you'll want to use ASEARCHEX, which will return an array of index numbers. That's a bit advanced for this guide, though; if you want to know more you can read about it on the AYAYA wiki.

Alright, that's all well and good, but what if you want to remove a value from an array? This is also very easy! There is a handy function called IARRAY that will help. IARRAY is used to initialize empty arrays, and to delete an element of an array.

ColorArray[2] = IARRAY

//The array now contains Red, Green, Orange, and Purple

"%(ColorArray[2])" //This would display 'Orange' in dialogue

When you delete an element of an array with IARRAY, all the other elements of the array will shuffle back to fill in the gap. So, even though Orange was ColorArray[3] before, once you delete Cyan/ColorArray[2], Orange will now be ColorArray[2] and Purple will be ColorArray[3].

Note! This is different from setting an element to ""! Let me demonstrate with a new array:

FoodArray = ("Carrots","Celery","Tomatoes","Cucumbers")

//FoodArray contains Carrots, Celery, Tomatoes, and Cucumbers

FoodArray[2] = ""

//FoodArray contains Carrots, Celery, an empty string, and Cucumbers

"%(FoodArray[2])" //This would return an empty string
"%(FoodArray[3])" //This would display 'Cucumbers' in dialogue

As you can see, when you set an element of an array to "", it does not remove the element entirely, it simply sets it to an empty string. That means the other elements of the array will maintain their current positions, which is useful in some circumstances.

Ok, back to the IARRAY function. As I said before, it can create empty arrays, too. Why do you need this? It's important for initializing your variables properly. Lets start a new ColorArray to demonstrate:

ColorArray = ""
//ColorArray is now an empty string

ColorArray ,= "Gray"
ColorArray ,= "White"

//ColorArray now contains an empty string, Gray, and White

"%(ColorArray[0])" //This will return an empty string

As you can see, if you use ,= on an empty string, it leaves a blank element at the start of your array. That's frustrating! But the solution is simple. If you initialize ColorArray as an empty array rather than an empty string, it won't leave that empty element at the start.

ColorArray = IARRAY
//ColorArray is now an empty array

ColorArray ,= "Gray"
ColorArray ,= "White"

//ColorArray now contains Gray and White

"%(ColorArray[0])" //This will display 'Gray' in dialogue

No more empty element! So if you need an empty array to add values to later, always initialize it with IARRAY.

Alright, there's one more function for arrays that I want to show you before we move into loops, and that's ARRAYSIZE. ARRAYSIZE is just what it says on the tin; it tells you how many elements are in your array! Lets create a new array so I can demonstrate.

ExampleArray = ("Element 0","Element 1","Element 2","Element 3","Element 4")

_size = ARRAYSIZE(ExampleArray)
//_size will now contain the integer 5

Notice that even though we have elements 0-4, ARRAYSIZE returned 5. Why is that? Well, index numbers start at 0, but ARRAYSIZE counts how many elements are in the array. If you only had element 0 and it said 0, that wouldn't be accurate! There are 5 elements total in this array, even though the index number starts counting from 0. Be aware of this, as it's an easy source of off-by-one errors.

One more useful function. You can use the RAND function to get a random element from an array, like so:

_rand = RAND(ARRAYSIZE(ColorArray))
//_rand now contains a random number, no higher than the last element of ColorArray

_color = ColorArray[_rand]
//_color is now a random element from ColorArray, based on the number stored in _rand

But there's a much easier way to write this if you just need a quick random selection. ANY will grab a random element from whatever array you give it.

_color = ANY(ColorArray)
//_color is now a random element from ColorArray

Function Arrays

There is actually one more type of array you need to know about before we continue. Functions can be set up to return arrays, like so:

ColorArray : array
{
	"Red"
	"Green"
	"Blue"
}

"%(ColorArray[0])" //This would display 'Red' in dialogue
"%(ColorArray[1])" //This would display 'Green' in dialogue
"%(ColorArray[2])" //This would display 'Blue' in dialogue

The thing about these arrays is that they are static. You cannot have the ghost modify anything about the actual array that's stored here. However, you can copy the contents of this array into a variable, and change that, if you want!

ColorArray : array
{
	"Red"
	"Green"
	"Blue"
}

_colors = ColorArray
//_colors now contains the values Red, Green, and Blue

_colors[1] = IARRAY
//_colors now contains the values Red and Blue

I have personally found this useful for things like pages in a book or changelog. I'll show off how this can be used at the end of this guide, with some examples.


for Loops

Alright, on to loops! This is where stuff starts to get really fun. I'll run through all the loop types that AYA/YAYA offer, but for the purposes of interacting with arrays, you'll mostly use for and foreach.

So, why would you want a loop? Loops are one of the most useful building blocks of programming. They let you execute the same code over and over as many times as you need! Want to display an inventory page where the number of items can change? Want to check if the user has guessed all the right letters in your hangman game? Want to read every line of a file to check for a specific string? Loops can do all that and so much more!

We'll start with for loops. Personally, I always thought that 'for' was kind of a weird label. Things like if/else make intuitive sense to me, since you can say 'if X happens, then do this, else, do this' and it makes sense. It took me a while to find a good way to think about 'for', but here's what I eventually came up with: 'for every time X is true, do this'. It'll make more sense in a minute, I promise. Here's the basic structure of a for loop:

for _i = 0; _i < 10; _i++
{
	//Some code
}

That may look a bit confusing, but I'll break it down. A for loop has 4 parts. After the word 'for' are 3 sections separated by semicolons. These are the initialization, the condition, and the incrementor.

The initialization in this loop is _i = 0. This will run one time before the loop starts, and is generally used to set up a variable to count how many loops have been done. So in this case, we create a new local variable called _i, and set it to 0.

The condition in this loop is _i < 10. The condition is checked every time the loop ends. In the case of a for loop, if the condition is true, it will run the code in the loop again. So, after the code in the loop runs, if _i is less than 10, the loop will run again.

The incrementor in this loop is _i++. The incrementor is run every time the loop ends and the condition is true. So, if _i is less than 10 in this loop, the incrementor will raise the value of _i by 1. The end result is that this loop will run 10 times and then stop!

Finally, there's the code inside the brackets. That's the code that will be run over and over until the condition is false.

Here's the thing though; all of the stuff I just mentioned is totally flexible. You can get really creative with your loops, you don't have to just do a simple count up like this! Here's an example of a for loop that would read every line in a file:

for _buff = FREAD(_file); _buff != -1; _buff = FREAD(_file)
{
	//Some code
}

I won't go into the specifics of reading files here, but for this loop, the initializer reads the first line of the file, the condition checks to make sure the end of the file has not been reached (FREAD will return -1 if the end of the file is reached), and the incrementor reads the next line of the file. You can do all kinds of creative loops like this!

Alright, so why do we need a loop like this, anyways? Well, lets go back to arrays for a moment. Lets say we have an array that contains items the user has given their ghost today, and you want to display those items in a list when the user opens a certain menu. Here's a really simple setup for that:

_display = "" //Initialize a local variable to hold the display

for _i = 0; _i < ARRAYSIZE(TodaysItems); _i++ //Loop through every element of the array
{
	_display += "%(TodaysItems[_i])\n" //Add the current element to a string, with a linebreak afterwards
}

"Here are the items you've given me today:\n\n%(_display)\e"

Just that small amount of code will display every item in the TodaysItems array, no matter how many items the user has given the ghost! And this is only scratching the surface of what's possible.

I briefly mentioned before that you can use variables as index numbers for arrays. Loops are where that's extremely useful! Since _i in this loop always has the number of the loop we're currently on, you can use _i to get each element of the array in order as the loop continues to execute.

One more thing before we move on. Beware of infinite loops! An infinite loop happens when the condition of the loop is never false. The loop will run forever, and it will crash SSP. Here's an example of an infinite loop:

for _i = 0; _i > -1; _i++
{
	//Some code
}

Since _i is counting up, it will always be greater than -1, and this loop will never stop running. Always test your loops thoroughly!


foreach loops

If all you need is a simple display like the item list above, you might be able to simplify your loop to a foreach loop! foreach loops are specifically for arrays, both simple and general purpose. They run once for every element of the array, and then stop. You can set up a foreach loop like this:

ColorArray = ("Red","Green","Blue")

foreach ColorArray; _color
{
	//Some code
}

This one is simple. There are two parts, the array you want to read, and the variable you want to store the current element in. So this loop means 'for every element in the array ColorArray, store the current element in _color, and run this code'. When the loop runs the first time, _color will be "Red". Then it'll run again, and _color will be "Green". Then it'll run one last time, and _color will be "Blue".

foreach loops are a great way to simplify a simple item display like the one we made above! Lets recreate it with a foreach loop.

_display = "" //Initialize a local variable to hold the display

foreach TodaysItems; _item //Loop through every element of the array, store the current item in _item
{
	_display += "%(_item)\n" //Add the current element to a string, with a linebreak afterwards
}

"Here are the items you've given me today:\n\n%(_display)\e"

That's a lot tidier! It's also safer than a for loop, since this will never result in an infinite loop. Sometimes it's more useful to have a for loop, though. A foreach loop like this can't read a file like the for loop I showed earlier. Also, sometimes you just really need that index number for things like dynamic menus!


while loops

There is one more type of loop, and it might be easier for you to grasp if you aren't so sure about for and foreach loops. The while loop is simple, you only need one thing: A condition.

_i = 0
while _i < 10
{
	//Some code
	_i++
}

When you set up a while loop, the only thing you need to give it is a condition. That while loop will run as long as the condition is true. while loops are a bit more dangerous than for loops, since it's much easier to get into an infinite loop! You must be very careful when setting up while loops. When I start a new while loop like this, the first thing I do is make sure that it will not run infinitely.

You may notice that this while loop does the exact same thing as the for loop I showed you. First I declare _i before the loop starts, then it checks if _i is less than 10, and if so it will run the code inside the brackets. Then I also added _i++ to increment _i every time the loop runs, so that it doesn't run forever. You could easily write this as a for loop instead! I usually do, since I think it keeps my code neater. It's really up to your personal preference, though. They say you're supposed to use for loops when you know the number of loops you need to run, and while loops when the number of loops is unknown, but for the purposes of ghost coding I don't think it matters that much. Write whatever loop you feel most comfortable with.

Alright, lets write that same example of a simple item display with a while loop.

_display = "" //Initialize a local variable to hold the display
_i = 0 //Start a variable to keep track of the index

while _i < ARRAYSIZE(TodaysItems) //Loop through every element of the array
{
	_display += "%(TodaysItems[_i])\n" //Add the current element to a string, with a linebreak afterwards
	_i++ //Increment _i so we don't make an infinite loop
}

"Here are the items you've given me today:\n\n%(_display)\e"

There you go! That's the basic logic behind loops.


Break and Continue

There are two more commands you need to know, and they can be used with any type of loop. Break is a command that will stop the currently running loop. This is good for preventing infinite loops, or for ending a loop once you've completed an objective, so that it doesn't need to waste time running the loop again (big loops can noticably impact performance, so this is very useful). Here's an example with a while loop:

_i = 0

while _i > 0
{
	if _i > 100
	{
		break
	}
	_i++
}

This loop is not set up properly. Since _i will always be greater than 0, the loop would run infinitely. However, we've included a break command to prevent that! Once _i is greater than 100, it will run the break command, and the loop will end. Note: if you have multiple loops nested in each other, the break command will only apply to the specific loop that it's in. So if you put your break command in the innermost loop, it will only break the innermost loop.

Similar to the break command is the continue command. This will skip the current loop, and go straight to the next iteration of the loop. For example, if you wanted to display a list of even numbers, you could do this:

_display = ""

for _i = 0; _i < 10; _i++
{
	if _i % 2 != 0 //This checks if the number is not even
	{
		continue
	}
	_display += "%(_i) "
}

"%(_display)"

The loop will run 10 times, but any time the number in _i is odd, it will go back to the top of the loop, run the incrementor, and start again. If you're writing a while loop, be careful! If your incrementor is at the bottom of the loop, you might end up skipping it, causing an infinite loop.

And that's that for simple loop logic! Now, how about some examples of loops and arrays together, where they really shine?


Dynamic Menus

You don't have to read the rest of this if you don't want to, some of it is pretty complex. This is just some examples of how I've used the concepts discussed above! If you're interested in seeing how these bits of code work, you should copy them into your own ghost and experiment with them.

I love dynamic menus, and if you've used any of my ghosts, you've probably noticed. So how do those work? Here's a simple example, a dynamic menu that will display all of the shells that a ghost has installed and allow the user to click the buttons to change to the various shells. If you want to see a menu like this in action, check out Hydrate!

On_installedshellname //This SHIORI event is notified when the ghost starts, and lists all the shells as reference values
{
	ShellList = IARRAY //Declare an empty array
	foreach reference; _shell //Each shell is in it's *own* reference value, but you can use a foreach loop like this to gather each one since reference is an array!
	{
		ShellList ,= _shell
	}
}

OnShellMenu //The actual menu displaying the shell names
{
	_display = ""
	foreach ShellList; _shell //Go through every element of the array we made earlier
	{
		if _shell == nowshell; _display += "\![*]" //If this is the current shell, add a choice marker to show that it's in use
		_display += "\q[%(_shell),OnSwitchShell,%(_shell)]\n" //Add a button for this shell. Note that the name of the shell is also the third argument here; this will be used to send it to the OnSwitchShell function as reference0
	}
	--
	"\0\*\_q\![set,autoscroll,0]" //Some starting tags before we get into the dynamic content. These set the character to the Sakura, prevent the balloon from timing out, display the menu instantly, and prevent the balloon from scrolling on its own (so the user sees the top of the menu first), respectively.
	--
	//These ARRAYSIZE checks here check how long the list is, and will choose bigger balloon sizes if the list is long. The biggest one will also add a back button at the top of the menu, so you don't have to scroll too long.
	if ARRAYSIZE(ShellList) > 16; "\b4\n\n[half]\![*]\q[Back to menu,OnMenuRun]"
	elseif ARRAYSIZE(ShellList) > 11; "\b4"
	else; "\b2"
	--
	"\_l[53]---Shells---"
	--
	"\n\n[half]%(_display)" //The actual dynamic content
	--
	"\n\n[half]\![*]\q[Back to menu,OnMenuRun]\n\![*]\q[Nevermind,Cancel]\e" //Back and cancel buttons at the end of the menu
}

OnSwitchShell //When one of the buttons in the menu is clicked, this function will be called. Since the shell name is sent as reference0, all this needs is a single command!
{
	"\![change,shell,%(reference0)]"
}

Pretty neat, right? No matter how many shells the user installs for this ghost, they'll always show in this menu. Even if they're shells you don't know about and didn't plan for!

Where I think arrays are most useful is dealing with user content. Lets say you have a game of hangman, and you want the user to be able to put in their own words to guess. Here's a little set of functions that would let you add, edit, and remove words from the list.

OnHangmanWords
{
	_display = ""
	for _i = 0; _i < ARRAYSIZE(HangmanWords); _i++ //Gets each word that is stored in the HangmanWords array. Note that I'm using a for loop and not a foreach loop, because I need the number in _i!
	{
		_display += "\q[(x),OnRemoveWord,%(_i)] \q[%(HangmanWords[_i]),OnEditWord,%(_i)]\n"
	}
	
	"\0\*\_q\![set,autoscroll,disable]List of hangman words:"
	--
	"\n\n\![*]\q[Add a word,OnAddWord]"
	--
	"\n\n%(_display)"
	--
	"\n\n\![*]\q[Back to menu,OnMenuRun]\e"
}

//---Adding a word---
OnAddWord
{
	"Type a word to add to the list."
	--
	"\![open,inputbox,OnWordAdded,-1]\e" //Opens an input box
}

OnWordAdded
{
	HangmanWords ,= reference0 //Adds the word to the array
	"\![raise,OnHangmanWords]" //Goes back to the word menu
}

//---Editing a word---
OnEditWord
{
	Temp = TOINT(reference0) //Stores the index number in a temporary variable. Have to do this because you can't send references through input boxes. Also note that reference0 will be a string because it was sent from a sakurascript!
	
	"Editing: %(HangmanWords[reference0])."
	--
	"\![open,inputbox,OnWordEdited,-1,%(HangmanWords[reference0])]\e" //Opens an input box. Note the argument after the -1, that makes it so that the word that's being edited will already be in the inputbox when it opens, so the user can edit it more easily.
}

OnWordEdited
{
	HangmanWords[Temp] = reference0 //Change the specific word that was being edited
	ERASEVAR("Temp") //Erase the temp var because we don't need it now
	"\![raise,OnHangmanWords]" //Goes back to the word menu
}

//---Removing a word---
OnRemoveWord
{
	HangmanWords[reference0] = IARRAY //Removes the chosen word
	"\![raise,OnHangmanWords]" //Goes back to the word menu
}

//When you start a game of hangman, you can pick a random word from the list with _word = ANY(HangmanWords). Make sure you check that the array isn't empty, first!

You can do all kinds of stuff with lists like this! Go crazy with it! You might want to add some checks to make sure the user doesn't put in anything dangerous, like sakurascript tags, but there's a lot of potential here as long as you're careful!

Alright, so what about those function arrays I mentioned earlier? How are those helpful? Let me show you a simplified version of a shop system I set up for one of my ghosts. I wanted to be able to easily add new items to the shop, without having to hardcode a bunch of menus. So, I made a big array of items, and a menu that decodes that array to figure out what to display!

ShopItems : array
{
	//Name,Category,Price,Unlock condition(1 for always unlocked),Sold out condition (-1 for never sold out)
	//Important note: If you have an envelope like %(hour < 5), it will display 1 if the hour is less than 5 and 0 if the hour is 5 or more. This is really useful for making items only available when certain conditions are met!
	
	//Also notice the local variables here. If I decided I wanted to change the price of all cheap items to 15, I'd only have to change the value here and it would automatically apply to every item that's using %(_pricecheap)
	_pricecheap = 20
	_pricemid = 50
	_priceexpensive = 100
	
	"Sweater,Clothing,%(_priceexpensive),1,%(ASEARCH('Sweater',Inventory))" //These two will always be available, since their unlock condition is just 1. They will not appear in the shop if already purchased, thanks to an ASEARCH command checking if they're already in your inventory
	"Hoodie,Clothing,%(_priceexpensive),1,%(ASEARCH('Hoodie',Inventory))"
	
	"Juice,Consumables,%(_pricecheap),%(timeslot == 'earlymorning' || timeslot == 'morning'),-1" //Is only available in the morning, never sells out
	"Water,Consumables,%(_pricecheap),1,-1" //Always available, never sells out
}

OnShopMenu
{
	_items = ShopItems //Store the items in a temp array
	if reference0 == ""; reference0 = "Consumables" //Sets it to the consumable page if reference0 is empty
	_display = ""
	
	for _i = 0; _i < ARRAYSIZE(_items); _i++
	{
		_current = _items[_i] //Get the current element of the array
		//Here's where simple arrays come in handy! Now that _current has the whole array entry, which is separated by commas, I can easily pick out individual values!
		_name = _current[0]
		_category = _current[1]
		_price = _current[2]
		_unlock = _current[3]
		_soldout = _current[4]
		
		if _unlock == "1" //If the item is unlocked
		{
			if reference0 == _category //Checks to make sure we're looking at the right category. You'll only see consumables on the consumables page, and you'll only see clothing on the clothing page
			{
				if _soldout != -1 //If the item is sold out. The reason I have this check for -1 is that ASEARCH returns -1 if it does not find anything, and I use ASEARCH to check if items already exist in the inventory.
				{
					_display += "\f[color,150,150,150]%(_name) (Sold out)\f[default]\n" //Adds the name of the item, but grayed out
				}
				else
				{
					_display += "\q[%(_name),OnBuyItem,%(reference0),%(_i)] ($%(_price))\n" //Adds the item as a clickable button. Note that clicking this sends the value that already exists in reference0 as reference0. This keeps us on the same menu page!
				}
			}
		}
	}
	
	"\0\b2\_q\*\![set,autoscroll,disable]"
	--
	"\![*]\q[Clothing,OnShopMenu,Clothing]  \![*]\q[Consumables,OnShopMenu,Consumables]\n\n" //These buttons let you change what page you're on by calling this function again with a different value in reference0
	--
	"%(reference0):" //The title of the current category we're in
	--
	"\n\n%(_display)" //The dynamic content
	--
	"\n\n\![*]\q[Back to menu,OnMenuRun]\e"
}

OnBuyItem
{
	_current = ShopItems[reference1] //Get the array entry the user clicked on
	_name = _current[0]
	_category = _current[1]
	_price = _current[2]
	
	if _category == "Clothing"
	{
		Inventory ,= _name //Add the clothing that was purchased to the inventory
	}
	
	money -= TOINT(_price) //Make the price an integer and subtract it from the user's money
	
	"You bought the %(_name)!\x\![raise,OnShopMenu,%(reference0)]"
}

This is an extremely simplified example, you'd have to add checks to make sure the user actually has enough money and such, but you can see what sorts of potential there is here! You could add hundreds of items just by adding new entries to the array, and the menu would just handle it! You could add more pages, lots of different unlock conditions, special dialogue for every item, whatever you want to do. And all of it would be super flexible and easy to change.

This is all just a small sample of what is possible with arrays and loops. Go forth and make something awesome! The AYAYA Wiki has a page with all of the functions in AYA/YAYA, and it includes a section for functions that manipulate arrays. Give those a read if you're interested in more stuff you can do with arrays! If you have any questions about the information in this guide, feel free to contact me at the links below, or on the Ukagaka Dream Team Discord Server. I love talking about this stuff, and there are some other folks on the discord who are also knowledgable about arrays and loops and can help you with them!