fly me to the moon

ADVANCED CODING

This section will cover more advanced programming concepts, which provide several useful tools. We'll dive in a bit more closely to arrays and temporary entries, and cover different kinds of loops.

Learning more advanced coding techniques can allow you to expand your Ghosts' capabilities in new and exciting ways. This is how you will be able to implement new, deeper features. Such as shops, inventories, or more complex games.

Data Types

Arrays

An array, in Kawari, is an entry that holds multiple definitions. Each separate definition is called an 'element'. An element can be accessed at its position, called an 'index'.

Writing an array in Kawari is easy. Commas can be used as delimiters, or you can write an additional definition on a separate line.
example_array : dog, cat, bear

example_array : otter
Using example_array with a normal entry call will randomly pick from 'dog', 'cat', 'bear', and 'otter'. An entry array call can be used to pick a specific element in the array. Array indexes are base 0, meaning they begin counting at 0 instead of 1. To pick 'otter', we'll use index 3.
sentence : "Take a look at that "$example_array[3]"!"
When that example is called, it'll print 'Take a look at that otter!', assuming that we are using our example_array and haven't modified it.

Let's say that you have a Ghost that uses an inventory system. Instead of having multiple entries that keep track of this, you could use an array instead. For a system that keeps track of "has" or "doesn't have", we could simply use an entry that stores the name of each item in inventory.

To start off, say our inventory entry currently looks like this:
inventory : butter, manhole cover, kerrek belt
Anytime you need to check if the user has something, you can use 'find' to get the first position of it in the entry. If 'find' returns -1, you can know the user does not have it, too.

You can add items to the inventory using commands like 'adddict', 'push', 'insert', and 'unshift'. You can also remove them with commands such as 'pop', 'shift', and 'clear'. Use the KIS reference to see which suits your purposes best.

Putting it all together:
OnTradeItem : $(
 # Assume OnTradeItem has a reference where the user chose what they were trading.
 setstr @tradeAway ${system.reference0};

 # If the user does not have the item in their inventory, exit OnTradeItem with fail response.
 if $[ $(find inventory ${@tradeAway}) == -1 ] $(
  return "\0\s[0]You can't trade something you don't have.";
 );

 # If the user chose to trade butter. Takes away "butter", adds "bread".
 if $[ ${@tradeAway} == "butter" ] $(
  # Grabs the index of the item and then uses @i to delete it with 'clear'.
  set @i $(find inventory ${@tradeAway});
  clear inventory[${@i}];
  # Adds the new item and exits with trade response.
  adddict inventory "bread";
  return "\0\s[0]Thanks for the butter. Here's the extra bread, like you asked.";
 );
)
You can also simply set the item at the index to something different:
if $[ ${@tradeAway} == "butter" ] $(
 set @i $(find inventory ${@tradeAway});
 set inventory[${@i}] "bread";
 return "\0\s[0]Thanks for the butter. Here's the extra bread, like you asked.";
);
Arrays can be used for many purposes, this is only one of them.

Temporary Entries

A temporary entry is an entry that is inaccessible outside of its code block and is removed after use. An entry, by default, is a global entry. That means it can be accessed anywhere, anytime.

Generally, in programming, you are supposed to keep your global variables tidy. This is part of optimization, security, and readability. Temporary entries are used when you only need an entry to hold some data that will be discarded later. They can only be accessed within the scope of the code block.

Up above, in the code examples for inventory management, you've actually seen examples of temporary entries already. Temporary entries are prefixed with '@'. This is how temporary is distinguished from global.
setstr @tradeAway ${system.reference0};

if $[ $(find inventory ${@tradeAway}) == -1 ] $(
 return "\0\s[0]You can't trade something you don't have.";
);
There's one temporary entry here, '@tradeAway'. @tradeAway's purpose is to hold the name of the item the user is attempting to trade for something else. This isn't information we need to know outside of the context of the current trade. So, a temporary entry is used.

The other entry used is 'inventory'. inventory is something we need to keep track of consistently. Users don't really like having their collected items deleted, or so I've heard. With this in mind, inventory is a global entry.

It should be fairly easy to recognize if an entry needs to be global or temporary. Unless the information is needed elsewhere and can't be passed as a reference, a temporary entry will most likely work fine.

Loops

Loops are functions that will repeat through a given code block. How many times they repeat depends on the type of loop. Loops are used commonly when code needs to be executed repeatedly, like for each element in an array, for a specific number of times, or while a condition is true.

Basic Loops

Basic loops are loops that repeat a given number of times. These loops are useful for simple repeated tasks, such as choosing sets of random numbers.

Say you want to implement a game of (American) bingo. Knowing the rules, we can randomly create a bingo card. Bingo numbers are limited by 5 columns:

B, 1-15
I, 16-30
N, 31-45
G, 46-60
O, 61-75

A bingo card has 5 rows, so each column needs 5 numbers. Additionally, the N column has one free space. So, N actually has 4 numbers.

To convert this into data, we know we need to generate exactly 24 numbers. That transfers well into a basic loop, as we know we can loop it 24 times. We can create an array that generates 24 random numbers, following the column restrictions.

OnBingoSetup : $(
 # Create the initial bingo card entry, starting with column B.
 set bingoCard $(rand 16);

 loop 24 $(
   # If there are 4 or less elements in bingoCard, add a number from 1-15. Remember, rand can pick 0 as well.
  if $[ $(size bingoCard) <= 4 ] adddict bingoCard $[ $(rand 16) + 1]
  # If there are between 5 and 9 elements in bingoCard, add a number from 16-30
  elseif $[ $(size bingoCard) <= 9 && $(size bingoCard) >= 5 ] adddict bingoCard $[ $(rand 16) + 16 ]
   # N needs one less number, so lower the size check accordingly.
  elseif $[ $(size bingoCard) <= 13 && $(size bingoCard) >= 10 ] adddict bingoCard $[ $(rand 16) + 31 ]
  # And so on.
  elseif $[ $(size bingoCard) <= 18 && $(size bingoCard) >= 14 ] adddict bingoCard $[ $(rand 16) + 46 ]
  elseif $[ $(size bingoCard) <= 23 && $(size bingoCard) >= 19 ] adddict bingoCard $[ $(rand 16) + 61 ]
 );
);

We now should have a set of randomly generated numbers that may be able to transfer into a legal bingo card. Each index number of the array corrosponds to a cell in the bingo grid (excluding the free space). This doesn't account for duplicate numbers, for simplicity's sake. But it is just one example of how to use a basic loop.

Foreach Loops

foreach is a loop command that can be used to execute code on every element in an array. When you need to iterate over each element, this is one of the tools to use.

Since we've been talking about inventory systems, we'll use that as an example. For reference, here is an example of elements in the inventory entry:
inventory : bread, manhole cover, kerrek belt
Having a place for viewing your inventory is something users will need. But, we need to be able to manage it regardless of its size. This is where foreach comes in. foreach will loop until every element in the array has been worked over. This is perfect for our inventory system, as we might not necessarily know how many items the user has.

The syntax used by foreach is $(foreach element array). To make a simple inventory display, we'll just print the name and a new line.

OnViewInventory : $(
 foreach @item inventory $(
  echo ${@item}"\n"
 )
 echo "\n\q[Exit,dummyClose]"
)
This should output:
bread
manhole cover
kerrek belt

Exit
This work, in terms of functionality. It's not extremely pretty. There are adjustments that could be made to improve it. Such as: capitalizing each item, creating pages that can be flipped through, and/or giving a description when clicked on. But it does what we set out to. Think about what suits your Ghost when making menus.

While Loops

While loops are a type of loop that repeat while a condition is true. The syntax for the until loop command is $(while condition). This type of loop is very common, and used for numerous tasks.

One example of using a while loop is to iterate with finer control than a basic loop.
while $[ ${i} < 100 ] $(
 inc i 10;
 echo "Looping timer at "${i}".\n"
)
This will output:
Looping timer at 10.
Looping timer at 20.
Looping timer at 30.
Looping timer at 40.
Looping timer at 50.
Looping timer at 60.
Looping timer at 70.
Looping timer at 80.
Looping timer at 90.
It won't output "Looping timer at 100." because of the condition. When it reaches 100, the condition is no longer met, so it won't print any more lines.

Until Loops

Until loops are a type of loop command that repeats until a condition is met. The syntax for the until loop command is $(until condition). This types of loop is the opposite of while loops.

There are many situations where an until loop would execute the same, so long as the condition is inverted.
until $[ ${i} > 100 ] $(
 inc i 10;
 echo "Looping timer at "${i}".\n"
)
This will output:
Looping timer at 10.
Looping timer at 20.
Looping timer at 30.
Looping timer at 40.
Looping timer at 50.
Looping timer at 60.
Looping timer at 70.
Looping timer at 80.
Looping timer at 90.

jump

Index
Introduction
Glossary
Writing
Writing in Kawari
Writing with SakuraScript
Shells
Shell Overview
Coding
SHIORI Event Overview Basic Coding
Advanced Coding

credit

walkthrough by Okuajub
design by almost sweet - resources