Structs, recycling, iteration

Narks

Vastly intelligent whale-like being from the stars
Reaction score
90
Okay, so I have a few questions regarding structs:

- when I allocate a new struct, will it recycle unused indexes (like I create a struct using index 1, 2, 3, destroy 2, will the next struct by created using 2 or 4?)
- how can I iterate through all struct instances?
- say my struct has an X and Y coordinate stored in it, and I have an ability that looks for all struct instances in range of the ability being used - what is the most efficient way to handle this (speed is main focus here, as this ability can be spammed...)
 

dudeim

New Member
Reaction score
22
About the first question I'm pretty sure the indexes are recycled so in this case index 2 will be choosen.
The second question I have no idea if it's possible never heard of it though
The third well there may be another way of doing this by using hashtables or any kind of unit indexing system in which you can attach values to a specific unit (the structs instance).
 

tooltiperror

Super Moderator
Reaction score
231
>recycling
If you create a struct (1) then another (2), then delete the first, the next one you create will be (1), I'm pretty sure.

>iteration
You mean looping through a list? This is a bit limited but does what you want.
JASS:
//! zinc

library List
{
  struct Data
  {
    thistype next;
    
      static method IterateAndDisplay()
      {
        thistype this = thistype(0);
          while (true)
          {
              this = this.next;
              if (this == 0){ break; }
              BJDebugMsg(I2S(this));
          }
      }
    
      static method create() -> thistype
      {
        thistype this = thistype.allocate();
          this.next = thistype(0).next;
          thistype(0).next = this;
          return this;
      }
  }
  
  function onInit()
  {
    Data data = Data.create();
    Data data1 = Data.create();
    Data data2 = Data.create();
    Data data3 = Data.create();
    Data.IterateAndDisplay();
  }
}
//! endzinc


>X and Y
I think you'd have to iterate and do a check.
 

Sevion

The DIY Ninja
Reaction score
413
Doing a quick test, I found that JASSHelper does indeed recycle instances.

This code:
JASS:
scope test initializer init
    struct a
        method test takes nothing returns nothing
            call BJDebugMsg(I2S(this))
        endmethod
    endstruct
    private function init takes nothing returns nothing
        local a s1 = a.create()
        local a s2 = a.create()
        local a s3 = a.create()
        local a s4 = a.create()
        call BJDebugMsg("Initial Structs:")
        call s1.test()
        call s2.test()
        call s3.test()
        call s4.test()
        call s2.destroy()
        set s2 = a.create()
        call BJDebugMsg("Final Structs:")
        call s1.test()
        call s2.test()
        call s3.test()
        call s4.test()
    endfunction
endscope


Outputs:

1
2
3
4

1
2
3
4

However, if you're using structs, I suggest Alloc and struct arrays as they create less overhead.

For iteration through your instances, you'd have to have a dequeue. A doublely-linked list.

A basic one (using Alloc):

JASS:
struct myStruct extends array
    // OnDestroy must be spelled "OnDestroy" and placed above implement Alloc
    private method OnDestroy takes nothing returns nothing
        // Delink this node
        set thistype(0).next = this.next
        set this.next.prev = thistype(0)
    endmethod
    
    implement Alloc
    
    // Our node references
    private thistype next
    private thistype prev
    
    // Your X and Y coordinates set as privates for some intuitive stuff later
    private real x
    private real y

    // Some intuitive wrappers so you don't have to worry about remember to
    // square your values or square root your values when you want to change
    // their values
    public method operator X= takes real X returns nothing
        set this.x = X * X
    endmethod

    public method operator Y= takes real Y returns nothing
        set this.y = Y * Y
    endmethod
    
    public method operator X takes nothing returns real
        return SquareRoot(this.x)
    endmethod
    
    public method operator Y takes nothing returns real
        return SquareRoot(this.y)
    endmethod
    
    public static method create takes real X, real Y returns thistype
        local thistype this = thistype.allocate()
        
        // Add a node using thistype(0) as the head
        set thistype(0).next.prev = this
        set this.next = thistype(0).next
        set thistype(0).next = this
        set this.prev = thistype(0)
        
        // If these coordinate are not used for anything else, we can quickly sqare them
        // So we don't have to worry about them in the distance formula
        
        set this.x = X * X
        set this.y = Y * Y
        
        return this
    endmethod
    
    public static method iterate takes real cX, real cY, real range returns nothing
        local thistype this = thistype(0)
        set cX = cX * cX
        set cY = cY * cY
        set range = range * range
        loop
            set this = this.next
            exitwhen (this == 0)
            // Check distance
            if ( (this.x - cX) + (this.y - cY) <= range ) then
                // It's in range, do something
            endif
        endloop
    endmethod
endstruct


The above is also AFAIK the most efficient way of handling your last question.

There's no way to do it otherwise. You have to check distance every time. This method cuts down on the amount of math needed (As soon as you create it, it does the squaring required so that you won't have to do it again in the formula.)

It's also pretty intuitive with its wrappers.

You can easily do something like:

JASS:
scope ABCD initializer Init
    private function Init takes nothing returns nothing
        local myStruct a = myStruct.create(0 ,0)
        call myStruct.iterate(3, 4, 5)
        // It would do something because in a 3, 4 triangle, 5 is the length of the hypotnuse (distance)
       set myStruct.X = myStruct.X - 1
       call myStruct.iterate(3, 4, 5)
       // It would NOT do something because the distance is now greater than 5 (5.65685)
    endmethod
endscope
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top