1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. We have recently started the 16th edition of the Mini Mapping Contest. The theme is mini RPG. Do check it out and have fun.
    Dismiss Notice
  4. Dismiss Notice
  5. The Highway to Hell has been laid open. Come along and participate in the 5th Special Effect Contest.
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[JASS] Linked list

Discussion in 'Triggers & Scripts' started by Risc, Jun 28, 2008.

  1. Risc

    Risc

    Joined:
    Jun 5, 2007
    Messages:
    81
    Resources:
    1
    Tools:
    1
    Resources:
    1
    EDIT: Revamped the old post.

    This is a new version of my linked list. It allows you to.... well, store structs in a linked-fashion :)
    It doesn't produce memory-leaks (if you use it right) and it's fast!

    Code (vJASS):

    //LinkedList for vJass
    //Copyright (c) 2008, E.Sandberg (Risc)
    //Free for public use.

    library LinkedList
       
        function H2I takes handle h returns integer
            return h
            return 0
        endfunction
       
        function H2N takes handle h returns Node
            return h
            return 0
        endfunction
       
        function N2H takes Node n returns handle
            return n
            return null
        endfunction
       
        //Modify this struct to anything you like.
        //Remember to modify the dispose-method to work with your struct (to prevent memory leaks)
        struct Data
            public string name
            public unit u
           
            public method dispose takes nothing returns nothing
                //this is just an example
                //change this to fit your fields
                call RemoveUnit(this.u)
                set this.u = null
                set this.name = null
            endmethod
        endstruct
       
        struct Node
            public handle next
            public Data data
            public boolean IsTail = false
           
            public method dispose takes nothing returns nothing
                call this.data.dispose()
                call this.data.destroy()
                set this.data = 0
                call this.destroy()
            endmethod
        endstruct

        struct List
            private Node head
            private Node tail
            private Node current
            public integer count
           
            static method create takes nothing returns List
                local List ldummy = List.allocate()
                set ldummy.head = Node.create()
                set ldummy.tail = Node.create()
                set ldummy.tail.IsTail = true
                set ldummy.head.next = N2H(ldummy.tail)
                return ldummy
            endmethod
           
            public method dispose takes nothing returns nothing
                //clear list
                call this.Clear()
                call this.head.destroy()
                call this.tail.destroy()
                call this.current.destroy()
                set this.head = 0
                set this.tail = 0
                set this.current = 0
                set this = 0
            endmethod
           
            public method First takes nothing returns Node
                return H2N(this.head.next)
            endmethod
           
            public method Add takes Data data returns Node
                local Node n = Node.create()
                local Node temp = this.head
                //find last node
                loop
                exitwhen H2N(temp.next) == this.tail
                    set temp = H2N(temp.next)
                endloop
               
                set n.data = data
                set n.next = N2H(this.tail)
                set temp.next = N2H(n)
                set this.count = this.count + 1
                //--- Debug ---
                //call BJDebugMsg("Handle to this object is " + I2S(H2I(N2H(n))))
                //call BJDebugMsg("Handle to previous object is " + I2S(H2I(N2H(temp))))
                return n
            endmethod
           
            public method RemoveAndEnumNext takes Node n returns Node
                local Node temp = this.head
               
                loop
                exitwhen temp.next == N2H(n)
                    set temp = H2N(temp.next)
                endloop
               
                set temp.next = n.next
                set this.current = H2N(this.current.next)
                set this.count = this.count - 1
                call n.dispose()
                return this.current
            endmethod
           
            public method Clear takes nothing returns nothing
                local Node temp = H2N(this.head.next)
                //find last node
                loop
                exitwhen temp.IsTail == true
                    call temp.data.dispose()
                    set temp = this.RemoveAndEnumNext(temp)
                endloop
                set this.head.next = N2H(this.tail)
                set this.count = 0
            endmethod
           
            public method Remove takes Node n returns nothing
                local Node temp = this.head
               
                loop
                exitwhen temp.next == N2H(n)
                    set temp = H2N(temp.next)
                endloop
               
                set temp.next = n.next
                if this.current == n then
                    set this.current = H2N(this.current.next)
                endif
                set this.count = this.count - 1
                call n.dispose()
            endmethod
           
            public method Enum takes nothing returns Node
                set this.current = H2N(this.head.next)
                return this.current
            endmethod
           
            public method EnumNext takes nothing returns Node
                set this.current = H2N(this.current.next)
                return this.current
            endmethod
        endstruct
    endlibrary
     
     
    Last edited: Jul 5, 2008
  2. Risc

    Risc

    Joined:
    Jun 5, 2007
    Messages:
    81
    Resources:
    1
    Tools:
    1
    Resources:
    1
    Forgot to add an example...
     

    Attached Files:

  3. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    Plz copy/paste your example in this post.
     
  4. spiwn

    spiwn

    Joined:
    Apr 27, 2008
    Messages:
    1,228
    Resources:
    0
    Resources:
    0
    The example is in the first post ...
    What is in the second(the double post) is an example map.
     
  5. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    Sorry but not, the first post is the link list "system".
    This is an example an only in the example map :

    Code (vJASS):
    library listTest initializer init_list
        globals
            List l
        endglobals
       
        function DebugLog takes string s returns nothing
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, s)
        endfunction
       
        function init_list takes nothing returns nothing
            set l = List.create()
        endfunction
       
        function testClearList takes nothing returns nothing
            call l.Clear()
        endfunction
       
        //stress-test of list
        function testAddPeasants takes nothing returns nothing
            local Data d
            local integer i = 1
            local real posX = 500
            local real posY = 3000
            //create 100 peasants and put them in the list
            loop
            exitwhen i == 100
                set d = Data.create()
                set posX = -posX
                set posY = posY - 100
                set d.u = CreateUnit(GetLocalPlayer(), 'hpea', posX, posY, 0)
                set d.name = "peasant"
                call l.Add(d)
                set i = i + 1
            endloop
        endfunction
       
        function testCircleAttackFrenzy takes nothing returns nothing
            local Node last = l.Enum()
            local Node n = l.EnumNext()
            loop
            exitwhen n.IsTail == true
                //order peasant to attack next peasant in list
                call IssueTargetOrder(n.data.u, "attack", last.data.u)
                call DebugLog("Ordering " + I2S(H2I(n.data.u)) + " to attack " + I2S(H2I(last.data.u)))
                set last = n
                set n = l.EnumNext()
            endloop
            //order first peasant to attack last peasant
            call IssueTargetOrder(l.First().data.u, "attack", last.data.u)
        endfunction
       
        function testSuicideFrenzy takes nothing returns nothing
            local Node n = l.Enum()
            loop
            exitwhen n.IsTail == true
                //order peasant to kill himself
                call KillUnit(n.data.u)
                set n = l.EnumNext()
            endloop
        endfunction
       
        function testBuildFarmFrenzy takes nothing returns nothing
            local Node n = l.Enum()
            loop
            exitwhen n.IsTail == true
                //order peasant to build a farm
                call IssueBuildOrder(n.data.u, "farm", GetUnitX(n.data.u), GetUnitY(n.data.u))
                set n = l.EnumNext()
            endloop
        endfunction
    endlibrary


    And the test trigger named "yo" :

    Code (vJASS):
    function Trig_yo_Actions takes nothing returns nothing
        call SetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_GOLD, 40000)
        call SetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_LUMBER, 40000)
        call testAddPeasants()
        call testCircleAttackFrenzy()
    endfunction

    //===========================================================================
    function InitTrig_yo takes nothing returns nothing
        set gg_trg_yo = CreateTrigger(  )
        call TriggerRegisterPlayerChatEvent( gg_trg_yo, Player(0), "yo", true )
        call TriggerAddAction( gg_trg_yo, function Trig_yo_Actions )
    endfunction
     
  6. GhostWolf

    GhostWolf

    Joined:
    Jul 29, 2007
    Messages:
    4,840
    Resources:
    2
    Tools:
    1
    Tutorials:
    1
    Resources:
    2
    Didn't get what's the point of the Data struct, you only need the nodes.

    public handle next
    - Can't you make that
    public node next
    (never tried using this with Jass) ?

    public boolean IsTail = false
    - normally you just check if node->next (the next pointer) is null instead of putting a boolean.

    Instead of the "dispose" method, you can just put a onDestroy method (runs automatically when the struct is destroyed).

    You might also add some documentary as you hardly commented it at all (and add the fact that it requires JNGP).
     
  7. Captain Griffen

    Captain Griffen

    Joined:
    Nov 20, 2005
    Messages:
    1,001
    Resources:
    3
    Maps:
    3
    Resources:
    3
    Code (vJASS):
        function N2H takes Node n returns handle
            return n
            return null
        endfunction


    I2H is really asking for random errors and a nightmare situation.
     
  8. Risc

    Risc

    Joined:
    Jun 5, 2007
    Messages:
    81
    Resources:
    1
    Tools:
    1
    Resources:
    1
    Doesn't work since it's never null. If you look at the inner-workings of the vJass preprocessor, you'll understand that all it does it reference a value in an array, which is never null; closets you'll get is 0, and that might be a structure in the list. That's why I would say it's not safe enough.

    I might just do that if someone actually decides to use this.

    It doesn't require JNGP. It requires a vJass preprocessor (JassHelper). Which isn't really the same thing.
     
    Last edited: Jul 6, 2008
  9. Risc

    Risc

    Joined:
    Jun 5, 2007
    Messages:
    81
    Resources:
    1
    Tools:
    1
    Resources:
    1
    EDIT: It turns out it worked best using this method.
     
    Last edited: Jul 6, 2008