• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[System] Iterator

Status
Not open for further replies.
Level 13
Joined
Sep 13, 2010
Messages
550
It's a pretty useless system, actually just a waste of performance. Allows you to make ForGroup, ForForce like iterations. I couldn't think out a demonstration code, so I gladly accept any ideas.

JASS:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                             //
//  Iterator v1.0 by Geries - Pretty shortened edition.                                                        //
//                                                                                                             //
//  Iterator does no really special stuff, it's just some eye-candy stuff with some loss of performance. It    //
//  allows to have calls like ForGroup or ForForce, etc.. Also it is vulnerable to DestroyTrigger( ) stuffs... //
//                                                                                                             //
//  Using optional modules:                                                                                    //
//       - Table by Bribe: Saves one hashtable for you.                                                        //
//                                                                                                             //
//  API:                                                                                                       //
//                                                                                                             //
//      Creates an iterator instance and sets up the code to be executed.                                      //
//          static method create takes code toRun returns Iterator                                             //
//                                                                                                             //
//      Destroys an iterator instance.                                                                         //
//          method destroy takes nothing returns nothing                                                       //
//                                                                                                             //
//      Starts iterating for a given amount of loops. OP limit safe. You can also set it self-destructing when //
//      finished.                                                                                              //
//          method iterate takes integer count , boolean doDestroy returns nothing                             //
//                                                                                                             //
//      Gets the current iterator instance.                                                                    //
//          static method getIterator takes nothing returns Iterator                                           //
//                                                                                                             //
//      Gets the iterator position.                                                                            //
//          method tellp takes nothing returns integer                                                         //
//                                                                                                             //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                             //
//  CONFIG                                                                                                     //
//                                                                                                             //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
globals
    // Allow Iterator to use the Table if it is available
    constant boolean ITERATOR_USES_TABLE = true
endglobals
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                             //
//  SCRIPTS                                                                                                    //
//                                                                                                             //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
library Iterator requires optional Table

    struct Iterator extends array
        
        static if ITERATOR_USES_TABLE and LIBRARY_Table then // Checks if Table available for the system
            // One for iterator IDs
            private static Table TData // ID to Trigger
            // An other one for holding data for Iterators
            private static Table DataA // Current Loop
            private static Table DataB // End of loop
        else
            // Or only one hashtable and more performance
            private static constant hashtable HT = InitHashtable( )
        endif

        private static integer Cu
        
        static method create takes code toRun returns thistype
            local trigger T = CreateTrigger( )
            local integer id = GetHandleId( T )
            static if ITERATOR_USES_TABLE and LIBRARY_Table then
                set thistype.TData.trigger[id] = T
            else
                call SaveTriggerHandle( thistype.HT , 0 , id , T )
            endif
            call TriggerAddCondition( T , Condition( toRun ) )
            set T = null
            return id
        endmethod
    
        method destroy takes nothing returns nothing
            static if ITERATOR_USES_TABLE and LIBRARY_Table then
                call DestroyTrigger( TData.trigger[this] )
                call thistype.TData.handle.remove( this )
                call thistype.DataA.remove( this )
                call thistype.DataB.remove( this )
            else
                call DestroyTrigger( LoadTriggerHandle( thistype.HT , 0 , this ) )
                call RemoveSavedHandle( thistype.HT , 0 , this )
                call RemoveSavedInteger( thistype.HT , this , 0 )
                call RemoveSavedInteger( thistype.HT , this , 1 )
            endif
        endmethod
        
        method iterate takes integer count , boolean doDestroy returns nothing
            static if ITERATOR_USES_TABLE and LIBRARY_Table then
                debug if thistype.TData.handle.has( this ) then
                    if not thistype.DataB.has( this ) then
                        if count > 0 then
                            set thistype.DataB[this] = count
                            set thistype.Cu = this
                            call ExecuteFunc( thistype.iterateLoop.name )
                            if doDestroy then
                                call this.destroy( )
                            endif
                        debug else
                            debug call BJDebugMsg( "|cffff0000[Iterator] - You shall give a number bigger than zero!|r" )
                        endif
                    debug else
                        debug call BJDebugMsg( "|cffff0000[Iterator] - You can't start an iteration before it didn't finish!|r" )
                    endif
                debug else
                    debug call BJDebugMsg( "|cffff0000[Iterator] - Not existing iterator ID, no iteration." )
                debug endif
            else
                debug if HaveSavedHandle( thistype.HT , 0 , this ) then
                    if not HaveSavedInteger( thistype.HT , this , 1 ) then
                        if count > 0 then
                            call SaveInteger( thistype.HT , this , 1 , count )
                            set thistype.Cu = this
                            call ExecuteFunc( thistype.iterateLoop.name )
                            if doDestroy then
                                call this.destroy( )
                            endif
                        debug else
                            debug call BJDebugMsg( "|cffff0000[Iterator] - You shall give a number greater than zero!|r" )
                        endif
                    debug else
                        debug call BJDebugMsg( "|cffff0000[Iterator] - You can't start an iteration on the same iterator instance before it would finish previous iterations!|r" )
                    endif
                debug else
                    debug call BJDebugMsg( "|cffff0000[Iterator] - Not existing iterator ID, no iteration." )
                debug endif
            endif
        endmethod
        
        static method getIterator takes nothing returns Iterator
            static if ITERATOR_USES_TABLE and LIBRARY_Table then
                if thistype.TData.handle.has( GetHandleId( GetTriggeringTrigger( ) ) ) then
                    return GetHandleId( GetTriggeringTrigger( ) )
                endif
            else
                if HaveSavedHandle( thistype.HT , 0 , GetHandleId( GetTriggeringTrigger( ) ) ) then
                    return GetHandleId( GetTriggeringTrigger( ) )
                endif
            endif
            debug call BJDebugMsg( "|cffff0000[Iterator] - Your script is not running under iterator, no return." )
            return 0
        endmethod
        
        method tellp takes nothing returns integer
            static if ITERATOR_USES_TABLE and LIBRARY_Table then
                debug if thistype.TData.handle.has( this ) then
                    return thistype.DataA[this]
                debug endif
            else
                debug if HaveSavedHandle( thistype.HT , 0 , this ) then
                    return LoadInteger( thistype.HT , GetHandleId( GetTriggeringTrigger( ) ) , 0 )
                debug endif
            endif
            debug call BJDebugMsg( "|cffff0000[Iterator] - Not existing iterator ID, no return." )
            debug return 0
        endmethod
        
        private static method iterateLoop takes nothing returns nothing
            local integer this = thistype.Cu
            static if ITERATOR_USES_TABLE and LIBRARY_Table then
                local integer max = thistype.DataB[this]
                local integer Curr = thistype.DataA[this]
            else
                local integer max = LoadInteger( thistype.HT , thistype.Cu , 1 )
                local integer Curr = LoadInteger( thistype.HT , thistype.Cu , 0 )
            endif
            local integer i = 0
            
            loop
                exitwhen i == 2000 or max <= Curr
                set i = i + 1
                set Curr = Curr + 1
                static if ITERATOR_USES_TABLE and LIBRARY_Table then
                    set thistype.DataA[this] = Curr
                    call TriggerEvaluate( thistype.TData.trigger[this] )
                else
                    call SaveInteger( thistype.HT , this , 0 , Curr )
                    call TriggerEvaluate( LoadTriggerHandle( thistype.HT , 0 , this ) )
                endif
            endloop
            
            if max > Curr then
                set thistype.Cu = this
                call ExecuteFunc( thistype.iterateLoop.name )
            else
                static if ITERATOR_USES_TABLE and LIBRARY_Table then
                    call thistype.DataA.remove( this )
                    call thistype.DataB.remove( this )
                else
                    call RemoveSavedInteger( thistype.HT , this , 0 )
                    call RemoveSavedInteger( thistype.HT , this , 1 )
                endif
            endif
        endmethod

        static if ITERATOR_USES_TABLE and LIBRARY_Table then        
            private static method onInit takes nothing returns nothing
                set thistype.TData = Table.create( )
                set thistype.DataA = Table.create( )
                set thistype.DataB = Table.create( )
            endmethod
        endif
        
    endstruct

endlibrary
I do accept constructive criticism as long as they are not like "Delete this nao" or "GTFO with this crap bro"( I know this will probably end up in the Graveyard :D ), but ideas how to make this even more faster( right now its 4 times slower than ForGroup ). I also appreciate bugs reported if there any.
 
Status
Not open for further replies.
Top