Fake Arrays

Ask and answer questions about making games and related topics. Unrelated topics go in that other forum.

Moderators: marionline, SDHawk

Post Reply
User avatar
kylekrack
Liquid Metal Slime
Posts: 1243
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Fake Arrays

Post by kylekrack »

I'm just checking that the OHR still does not in fact support arrays. I'm building a fake array now and wondering if that's been added since the last time I've built one (it was a long time ago). If not, is there an estimate on when arrays will be supported, if ever?

EDIT: I knew I'd have follow-up questions on this. Can global variables only store numerical data or is it possible to store slice lookup codes? If not, is there a way to attach a global variable to a lookup code in some way?
Last edited by kylekrack on Tue Aug 11, 2015 10:49 am, edited 1 time in total.
My pronouns are they/them
Ps. I love my wife
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7660
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

Slice lookup codes are numerical values, so yes, you can store them in globals.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1243
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

Ok, that's great, but it means I don't know what I'm doing wrong. I have a slice collection which displays a row of 10 "item" sprites across the top. I am attempting to use an array to cycle through tags attached to each item and setting the sprite visible if the item is "owned." For example, if tag 3 is on, then the player has item 1, and the sprite for item1 should be set to visible.

I didn't know how to use a for loop to append lookup codes to global variables, so I repeated the subscript manually to append each item.

Code: Select all

define constant(100, array:items) # creating an array for the item icons onscreen

script, append items, begin
	variable(length)
	length := 0
	
	subscript, append this, sl, begin
		write global(array:items + length, lookup slice(sl))
		length += 1
	end
	
	append this(sli:item0)
	append this(sli:item1)
	append this(sli:item2)
	append this(sli:item3)
	append this(sli:item4)
	append this(sli:item5)
	append this(sli:item6)
	append this(sli:item7)
	append this(sli:item8)
	append this(sli:item9)
end

global variable(0,inv)

script, draw inventory, begin
	inv := load slice collection(1)

	variable(i) #this reads the items array and checks the tags to make the item "had"
	for(i,0,9) do(
		if(check tag(i + 2)) then(
			set slice visible(read global(array:items + i),true)
		)
		else(
			set slice visible(read global(array:items + i),false)
		)
	)
	
end
My pronouns are they/them
Ps. I love my wife
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7660
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

Some day we will have real arrays, but for now, there are two different ways that I like to do fake arrays.

The first method is probably easiest, but it requires that you set an upper limit on the size of your array. For example, suppose you are confident that you will never need more than 100 elements in the array.

Code: Select all

global variable(1000, myarray)
# Globals 1000 to 1999 are reserved for the array

script, read my array, index, begin
  exit returning(read global(@myarray + index))
end

script, write my array, index, value, begin
  write global(@my array + index, value)
end
This is pretty simple, but also I think it is not what you want, since you are talking about appending items. Instead, you want a fake array where you don't need to know how many items it will have in advance. For this, you can use the children of a hidden slice.

Code: Select all

script, create fake array, begin
  # This returns a slice handle that you can use as an empty fake array.
  # You can store the handle in a global or local variable, and when you
  # are done with it you can delete it with "free slice"
  variable(a)
  a := create container(0, 0)
  set slice visible(a, false)
end

script, append to fake array, a, val, begin
  # Append a new number to the end of an array
  variable(e)
  e := create container(0, 0)
  set slice extra(e, 0, val)
  set parent(e, a)
end

script, read fake array, a, index, begin
  # Return the number at the given index of the array, if it exists.
  variable(e)
  e := slice child(a, index)
  if(e) then(
    exit returning(get slice extra(e, 0))
  )else(
    script error(string sprintf(0, $1="Array index %d out of bounds", index))
  )
end

script, write fake array, a, index, value, begin
  # Write a new number into the given index of an array, if it exists.
  variable(e)
  e := slice child(a, index)
  if(e) then(
    set slice extra(e, 0, value)
  )else(
    script error(string sprintf(0, $1="Array index %d out of bounds", index))
  )
end
This method is a little more complicated, and uses a little more memory, but it is probably much better for your purposes.

It can be used for temporary arrays stored in local variables in just one script (don't forget to "free slice" at the end!) or it can be used for global arrays that are set up in your "new game" script (don't forget to turn on the option to save slice handles in savegames, and don't forget to think about what happens if you change your mind about how the array should be organized and then you load an old .rsav file)
User avatar
kylekrack
Liquid Metal Slime
Posts: 1243
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

Thank you very much. I will attempt the slice method instead this time.
My pronouns are they/them
Ps. I love my wife
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7660
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

Another cool thing about the slice method is that you can press F8, open up the slice editor, and inspect your array :)
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

I wrote a wiki article about fake arrays last time someone asked.

http://rpg.hamsterrepublic.com/ohrrpgce ... ake_arrays

Arrays of global variables are easier to inspect, using the script debugger (press V a few times until it shows global variables), although you can't see where the array ends.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1243
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

TMC wrote:I wrote a wiki article about fake arrays last time someone asked.

http://rpg.hamsterrepublic.com/ohrrpgce ... ake_arrays

Arrays of global variables are easier to inspect, using the script debugger (press V a few times until it shows global variables), although you can't see where the array ends.
I used this article for help when I started making it, actually! Thank you for creating it, I found it very useful. The script debugger worked fine, I started at 100 instead of 1000, but I was able to infer/had an idea of where it ended, so that wasn't an issue.
My pronouns are they/them
Ps. I love my wife
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

If you do use global variables for a variable length array, it's convenient to store the length in a global immediately before the array so that you can see it in the script debugger:

Code: Select all

define constant(99, array:items length)
define constant(100, array:items)
After all, you probably want to have the length of the array actually stored somewhere, and update the length as you append to it:

Code: Select all

   # array is the global id of the start of the array, and the length is stored in the global immediately before it.
   script, append, array, item, begin
      write global(array + read global(array -- 1), item)  #array[length] := item
      write global(array -- 1, read global(array -- 1) + 1)  # length += 1
   end 

...
   append(array:items, lookup slice(sli:item0))
   append(array:items, lookup slice(sli:item1))
   append(array:items, lookup slice(sli:item2))
   append(array:items, lookup slice(sli:item3))
   append(array:items, lookup slice(sli:item4))
   append(array:items, lookup slice(sli:item5))
   append(array:items, lookup slice(sli:item6))
   append(array:items, lookup slice(sli:item7))
   append(array:items, lookup slice(sli:item8))
   append(array:items, lookup slice(sli:item9))
Also, neat, someone actually using 'subscript' :)
Last edited by TMC on Thu Aug 13, 2015 8:57 am, edited 1 time in total.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1243
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

TMC wrote:Also, neat, someone actually using 'subscript' :)
I believe I stubbed my toe on my desk when I discovered it. I got a little bit too excited. It's super useful though, especially for expanding the usability of local variables in many circumstances.
My pronouns are they/them
Ps. I love my wife
User avatar
Gizmog
Metal King Slime
Posts: 2622
Joined: Tue Feb 19, 2008 5:41 am

Post by Gizmog »

I'm still not sure I understand the significance. What's the difference in creating a subscript and calling a seperate, regular script? Not having to initialize new variables? Getting to reuse the first arguments?
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7660
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

The subscript has access to the local variables of the parent script

Also, the name of the subscript only has to be unique within the parent script, so you could have five different scripts that all have their own versions of the "append" subscript.
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

That includes the ability to modify the local variables of the parent script (which you can't do with a separate script), so you can deduplicate repeated code by moving it into a subscript.
Last edited by TMC on Fri Aug 14, 2015 6:21 am, edited 1 time in total.
Post Reply