Author Topic: Is one of array  (Read 6523 times)

0 Members and 1 Guest are viewing this topic.

Offline Cloudee1

Is one of array
« on: December 29, 2015, 01:48:25 PM »
I am trying to check to see if a number is in an array.

I have a local variable set up in a region script:
Code: [Select]
localRoomCheck[12] = (77 97 79 82 85 80 83 86 81 84 87 93)
In the same region script, I want to see if the current room number is part of that array, kind of a region inside of a region scenario.
Code: [Select]
(if(IsOneOf(gRoomNumber @localRoomCheck))
But the few different variations I have tried have not seemed to work, where as not using the array does
Code: [Select]
(if(IsOneOf(gRoomNumber 77 97 79 82 85 80 83 86 81 84 87 93))
Does anyone here know the proper syntax for doing this?


Halloween Competition Brass Lantern Prop Competition Groundhog Day Competition

Offline lskovlun

Re: Is one of array
« Reply #1 on: December 29, 2015, 02:18:49 PM »
I am trying to check to see if a number is in an array.
This is indeed not possible using OneOf. You'll have to code something up yourself.

Offline Cloudee1

Re: Is one of array
« Reply #2 on: December 29, 2015, 02:49:40 PM »
Alrighty, Going about this another way then, this seems to be working now

* Apparently I am a liar, this is in fact junk and doesn't work after all...

I have two local room variables...

Code: [Select]
doAsteroid = FALSE
localAsteroid[12] = (77 97 79 82 85 80 83 86 81 84 87 93)

and in the main script a CheckArray Procedure

Code: [Select]
(procedure public (CheckArray needle haystack)
(var i, size, inArray)
   = inArray FALSE
   = size Memory(memPEEK haystack)
   (for (= i 1) (<= i size) (++i)
       (if(== haystack[i] needle)
       = inArray TRUE   // indicate that we found it
       )
   )
   return inArray
)

and then in the rooms init method, a call to the procedure to set the other local variable

Code: [Select]
  = doAsteroid CheckArray(gRoomNumber localAsteroid)

Then anywhere in the room, I just check the local variable rather than remaking the procedure call over and over again.

Code: [Select]
     (if(doAsteroid)

Previously I had went a different route and had placed the procedure call in a doit method, and included the size as part of the procedure parameters... either or both of which may have been causing me problems.


« Last Edit: December 30, 2015, 09:59:18 AM by Cloudee1 »
Halloween Competition Brass Lantern Prop Competition Groundhog Day Competition

Offline lskovlun

Re: Is one of array
« Reply #3 on: December 29, 2015, 03:12:52 PM »
Code: [Select]
   (for (= i 1) (<= i size) (++i)

Two things:
  • Arrays are zero-based, so you'll have to start from zero for the math to work out.
  • You can't dereference a pointer using primitive ops in SCI. You can use the Memory kernel call to do that - basically, instead of array lookup, you do:
Code: [Select]
(if (== needle (Memory memPEEK (+ haystack (* i 2)))) /* found it */)
The gotcha here is the multiplication by two, which is needed because i counts array indices, and we need a byte count for this.

and phpBB messes with my list. Looks like it can't handle a code block inside a list. :(
« Last Edit: December 29, 2015, 03:19:11 PM by Cloudee1 »

Offline troflip

Re: Is one of array
« Reply #4 on: December 29, 2015, 03:24:23 PM »
You could also use a collection I think.

Code: [Select]
(instance localAsteroidRooms of Collect
)

Then in your region's init (presumably this is just called once?):

Code: [Select]
(localAsteroidRooms:add(77 97 79 82 85 80 83 86 81 84 87 93))


Code: [Select]
(if (localAsteroidRooms:contains(gRoomNumber))
    // do stuff
)


(haven't tested this code)
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline lskovlun

Re: Is one of array
« Reply #5 on: December 29, 2015, 03:29:08 PM »
Then in your region's init (presumably this is just called once?):
region inits are called on every room change as long as you are in the region and once more when you leave it (a room is in fact just a special case of a region).
The Collection/List idea is neat, and probably makes for the most readable code. But since a Collection/List is internally a linked list, careful management is needed so that the heap is not fragmented.
« Last Edit: December 29, 2015, 03:31:11 PM by lskovlun »

Offline Cloudee1

Re: Is one of array
« Reply #6 on: December 29, 2015, 03:39:42 PM »
In my case it would probably work as I am not using the region quite like it should be.

I am making a room part of the region in the room scripts init method

Code: [Select]
(self:setRegions(33))
Rather than defining the region elsewhere so that it is recognized more dynamically. Thus, I lose variable values between rooms (at least I presume that I do) so by extension, I would lose the collection as well. At least until it was rebuilt by the next room that set itself as part of the region.

Oddly though Lars, in regards to your last post, what I have seems to be working without the * 2 bit... rooms that aren't in the list don't seem to be triggering the death, and rooms that are, are.
Halloween Competition Brass Lantern Prop Competition Groundhog Day Competition

Offline troflip

Re: Is one of array
« Reply #7 on: December 29, 2015, 03:41:03 PM »
Yeah, it's a heavier weight operation (uses more heap), but more readable code.

So because of the init thing, you'd need to also check that the collection was isEmpty() before adding the rooms. I think heap fragmentation wouldn't be a problem if you just add these things once and never touch the list again (I guess that's the careful management you're talking about).


In actual original Sierra syntax, you could use a define:

Code: [Select]
(define ASTEROID_ROOMS 77 97 79 82 85 80 83 86 81 84 87 93)

Then you could use IsOneOf(gRoomNumber ASTEROID_ROOMS), and presumably do the other operations you need with that define too.

Unfortunately Companion doesn't support that, since defines are implemented as a lower level thing (since they could only be single value in SCI Studio), not a text substitution pre-processor.
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline Cloudee1

Re: Is one of array
« Reply #8 on: December 30, 2015, 09:58:13 AM »
Ok, final run through, yes the collections bit works and works fine.

Turns out my CheckArray procedure is in fact junk and I wasn't ever able to get it sorted out.

As the final alternative, I simply removed the whole local array variables attempt and just coded the single line statements which listed each room number which set a local Boolean flag.

Code: [Select]
 
  (if(IsOneOf(gRoomNumber 77 97 79 82 85 80 83 86 81 84 87 93)) = doAsteroid TRUE)
  (if(IsOneOf(gRoomNumber 77 97 82 85 80 83 86 93 81 84 87)) = doSpiderLanding TRUE)
  (if(IsOneOf(gRoomNumber 77 97 82 85 80 83 86 93 81 84 87)) = spiderInRoom TRUE)

As it has the smallest impact on heap, still leaves me listing the rooms in a single statement, just not in a local variable declaration. In the end it was easier to do this. The only drawback is that I don't get a new public procedure for checking an array... oh well
Halloween Competition Brass Lantern Prop Competition Groundhog Day Competition

Offline lskovlun

Re: Is one of array
« Reply #9 on: December 31, 2015, 03:17:42 AM »
Another funny thing about the kernel API for lists is that it is perfectly possible to use it for associative arrays. This feature was just never exposed in a class.

Offline Kawa

Re: Is one of array
« Reply #10 on: December 31, 2015, 05:17:22 AM »
Another funny thing about the kernel API for lists is that it is perfectly possible to use it for associative arrays. This feature was just never exposed in a class.
Could you elaborate on that?

Offline lskovlun

Re: Is one of array
« Reply #11 on: December 31, 2015, 05:39:07 AM »
Another funny thing about the kernel API for lists is that it is perfectly possible to use it for associative arrays. This feature was just never exposed in a class.
Could you elaborate on that?
NewNode takes two arguments, one is a search key and the other is the value. If the basic classes allowed the programmer to utilize this, you'd have the foundation for an AA implementation. They don't; they simply pass the same value for both. The return value of the contains method is effectively a boolean given the choice not to allow this, but in fact it is a pointer and could be passed to NodeValue to map a key to its value.

I haven't tried any of this, but I did implement some of it in ScummVM :)
EDIT: Note to self: Before I suggest such things, I might do well to check that there are no related bugs that might be easy but risky to fix...
« Last Edit: December 31, 2015, 06:22:05 AM by lskovlun »


SMF 2.0.19 | SMF © 2021, Simple Machines
Simple Audio Video Embedder

Page created in 0.034 seconds with 22 queries.