Array help

Hi! I’ve been reading the array documentation and trying to code an inventory system.

Could I check if the following is correct?

Intention #1: Store, modify, and display information about various barrels in a tavern (and allow players to add barrels).

Step 1: Create the arrays for each attribute

First, create a variable to track the number of barrels

*create num_of_barrels 3

Create arrays to store each barrel’s contents, days, and quality

*create_array barrel_contents num_of_barrels "empty"
*create_array barrel_days num_of_barrels 0
*create_array barrel_quality num_of_barrels "average"
  • barrel_contents: This stores what is in each barrel (e.g., water, wine, oil). Default is “empty.”
  • barrel_days: This tracks how many days each barrel has been stored. Default is 0.
  • barrel_quality: This stores the quality of the contents (e.g., good, poor, excellent). Default is “average.”

Step 2: Display or manipulate the barrel attributes

Access or change the attributes of any barrel using either barrel_contents[index], barrel_days[index], or barrel_quality[index] syntax.

Example of displaying the status of a specific barrel:

*temp current_barrel 2

The contents of barrel ${current_barrel} are ${barrel_contents[current_barrel]}.
It has been stored for ${barrel_days[current_barrel]} days, and the quality is ${barrel_quality[current_barrel]}.

Example of setting a barrel’s attributes:

*set barrel_contents[1] "wine"
*set barrel_days[1] 10
*set barrel_quality[1] "excellent"

*set barrel_contents[2] "water"
*set barrel_days[2] 5
*set barrel_quality[2] "good"

Step 3: Adding or managing barrels

To increase or change the number of barrels and create new arrays accordingly, the num_of_barrels can be edited:

Example: Adding a new barrel

*set num_of_barrels + 1
*create_array barrel_contents num_of_barrels "empty"
*create_array barrel_days num_of_barrels 0
*create_array barrel_quality num_of_barrels "average"

This will increase the number of barrels by 1 and create a new set of attributes for the new barrel, with default values.

Step 4: Looping through the barrels for an inventory page

To loop through all barrels and display their information or make adjustments, a *temp index variable can be used

Example: Displaying all barrels’ contents, days, and quality

*temp I 1
*label loop_barrels
Barrel ${I}:
  Contents: ${barrel_contents[I]}
  Days stored: ${barrel_days[I]}
  Quality: ${barrel_quality[I]}

*set i + 1
*if (i <= num_of_barrels)
  *goto loop_barrels

Intention #2: Moving contents of barrel to a different container

Let’s say I want to move the contents of the barrel to a different kind of container. Note: If I want to make sure any barrel can be transferred to a container so long as the container is empty.

Step 1: Moving contents from Barrel 1 to Container 1

To copy the information from a barrel to a container, use *set to copy the values from the barrel arrays to the container arrays.

Example: Copy the contents, days, and quality from Barrel 1 to Container 1.

*set container_contents[1] barrel_contents[1]
*set container_days[1] barrel_days[1]
*set container_quality[1] barrel_quality[1]

Step 2: After copying the data to the container, reset the barrel attributes to their default values.

Example: Resetting Barrel 1

*set barrel_contents[1] "empty"
*set barrel_days[1] 0
*set barrel_quality[1] "average"

Step 3: Add a condition to check if the container is empty

Before transferring the contents of a barrel to a container, check if the container is empty. If it’s empty, the transfer proceeds.

Example: Emptying a specific barrel into a specific container with a check

*temp chosen_barrel 2
*temp chosen_container 3

*if (container_contents[chosen_container] = "empty")
    *comment Proceed with the transfer if the container is empty
    *set container_contents[chosen_container] barrel_contents[chosen_barrel]
    *set container_days[chosen_container] barrel_days[chosen_barrel]
    *set container_quality[chosen_container] barrel_quality[chosen_barrel]

    *comment Reset the chosen barrel after transfer
    *set barrel_contents[chosen_barrel] "empty"
    *set barrel_days[chosen_barrel] 0
    *set barrel_quality[chosen_barrel] "average"

    The contents of Barrel ${chosen_barrel} have been successfully transferred to Container ${chosen_container}.
*else
    The container is not empty! Please select an empty container before transferring.

Step 4: Set up a reusable function

If you’re using a function-like structure (via *label), you can add this logic into the label to make it reusable for any barrel and container. The transfer will only happen if the chosen container is empty.

Example: A function-like label with a check for an empty container

*label transfer_barrel_to_container
*params barrel_num container_num

*if (container_contents[container_num] = "empty")
    *comment Proceed with the transfer if the container is empty
    *set container_contents[container_num] barrel_contents[barrel_num]
    *set container_days[container_num] barrel_days[barrel_num]
    *set container_quality[container_num] barrel_quality[barrel_num]

    *comment Reset the chosen barrel after transfer
    *set barrel_contents[barrel_num] "empty"
    *set barrel_days[barrel_num] 0
    *set barrel_quality[barrel_num] "average"

    The contents of Barrel ${barrel_num} have been successfully transferred to Container ${container_num}.
*else
    Container ${container_num} is not empty! Please select an empty container before transferring.

*return

Step 5: Call the function whenever I need to transfer contents

*gosub transfer_barrel_to_container 1 2

This will transfer the contents of Barrel 1 to Container 2, but only if Container 2 is empty.

3 Likes

I haven’t read through absolutely everything (there’s a lot there!). But you seem to have grasped the general gist.

One definite issue:

*set num_of_barrels + 1
*create_array barrel_contents num_of_barrels "empty"
*create_array barrel_days num_of_barrels 0
*create_array barrel_quality num_of_barrels "average"

You can’t use variable values in any of the create commands. Similarly you actually can’t call create again after your startup code is finished. You’ll have to hardcode a maximum value, that you know you won’t go over. E.g. 100 or 1000.

You can then keep track of how many you’ve actually used by having a separate used_barrels variable.

7 Likes

Got it!! Thank you! So I’d need to create another variable to reflect whether the container has been bought or not (since barrel_1 to barrel_100 would have had to be created at the start regardless of whether a player has bought them or not)?

How would I be able to quickly display only barrels that have been bought?

I’m also wondering if this portion on transferring the contents of a barrel to a container can be automatically done- meaning the player just clicks “transfer to a container” and the game loops through the checks for empty containers until it has found an empty one or has reached the end of the bought containers?

1 Like

If you’re feeling adventurous, it sounds like you might benefit from having a look at CSLIB.

It has an array module that solves some of these problems. There’s a technical article that goes into more detail.

At the very least you might find it a useful reference, even if you don’t want to use it as-is.

4 Likes

That was some gorgeous inventory management code you got there miss.

I really like it. Mind if I, shamelesly, copy part of it for myself?

Choicescript got no native dynamic allocation. (There are some workaround though, like the amazing twigger_fluff inventory system. But it gets really laggy as your inventory grows.). I know that, I once tried to create a work around that ended supper buggy! (It tends to round 1 to zero and still have a hard time identifiying and manipulating variables already declared inside a struct. Mostly because I failed to check my name_sort function…)

Though, truth be told, in Real Life, there is also a [spacial] limit for how many barrews one can store inside a building…

Unless your MC can build new warehouse to store more barrels?

In this case, how many barrels one need to purchase before drowing in micormanengement :stuck_out_tongue_closed_eyes: ?

About the empty containers. A label inside a scene to manage arrays (gosub_scene f_array?) would do the trick.

Like this example:

[on startup.txt]

*create return ""

Then during the game you can call the scene by type:

*comment Do I have empty barrels?

*temp my_barrels 99
*comment I brought 99 barrels.

*comment =======================
*comment ====================

*temp query "contents"

*comment in your code I notice the pattern
*comment for queries are "_contents", 
*comment "_days" and "_quality",
*comment hence the "query" variable

*temp empty_container_nun 0

*gosub get_empty_barrel (query) (my_barrels) 

*set empty_container_nun return


The get_empty_barrel will return the Index number of the next empty barrel in your inventory as a number.

*comment =======================
*comment =======================

*label get_empty_barrel 
*params this_query max_index

*comment it look for "empty" barrels duh!
*comment it uses concatenation to identify
*comment wich one of the 3 arrays you
*comment are looking for\!

*comment =======================
*comment =======================



*gosub_scene f_array get_index_of ("barrel_" & this_query) ("empty") (max_index)
*comment in this case, ("barrel_" & this_query) = "barrel_contents"

*if return = false
    "You have no empty barrels in your inventory, please buy more barrrels!"
    *return
*elseif return <= max_index
    Your barrel number ${return} is empty!
    *set empty_container_nun return
    *return
*else
    *Bug The return of this function is higer that your number of [brought] barrels!
    *return
[in f_array.txt]
*comment =======================
*comment =======================
*comment array function get_index_of. 
*comment It will sweep all your array while
*comment looking for a determined value,
*comment  then it return its index number.
*comment =======================
*comment =======================

*label get_index_of
*params key value index
*temp i 1

*comment foreach( i=1; i<=index; i++)
*label for_empty_loop
*if (i <= index)
    *if {((key & "_") & i)} = value
    *comment in this example, "key" = barrel_contents[index]!
        *set return i
    *else
        *set i (i + 1)
        *goto for_empty_loop
*else
    *set return  false
    *return


Also note that the function get_index_of (key, value, index) literally get you the index number of anything you want it to get. But in my example, I get it to look for the string: “empty” in the variable barrel_contents

edit:
LOL it was supposed to be “{((key & “_”) & i)}” not {key}. this is what you gain by writting rushed code… :sob: