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. The poll for Hive's 12th Concept Art Contest is up! Go cast your vote for your favourite genie!
    Dismiss Notice
  4. Travel to distant realms and encounter scenes unknown to the common folk. The Greatest of Adventures is upon us with the 8th Cinematic Contest. Join in on a fun ride.
    Dismiss Notice
  5. The 18th Icon Contest is ON! Choose any ingame unit and give him/her Hero abilities. Good luck to all.
    Dismiss Notice
  6. Contestants are to create a scene set in the Stone Age. Come and see what you can come up with. We wish you the best of luck!
    Dismiss Notice
  7. Colour outside the lines! Techtree Contest #13 is a go. The contest is optionally paired.
    Dismiss Notice
  8. Greetings cerebrates, our Swarm needs new spawners that will have numerous children. Join the HIVE's 31st Modeling Contest - Spawners and Spawned! The contest is optionally paired.
    Dismiss Notice
  9. 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.

[Snippet] IndexCarrier

Discussion in 'Graveyard' started by Krogoth, Jul 28, 2013.

  1. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    [Snippet] Indexer

    Reworked:
    Code (vJASS):
    //===============
    //=== Indexer ===
    //=== v1.050 ====

    /*************************************************************************
    * Functions
    *     function CreateIndexer takes integer n returns integer
    *          - Creates an indexer meant for n instances and returns its id
    *     function IndexCount takes integer CODE returns integer
    *          - Returns count of indexes used by indexer
    *           (In very deed this returns the largest index used currently)
    *     function Indexed takes integer CODE, integer index returns boolean
    *          - Is this index of an indexer currently occupied
    *     function Index takes integer CODE returns integer
    *          - Occupies free index of an indexer and returns it
    *     function Deindex takes integer CODE, integer index returns boolean
    *          - Frees an index of an indexer
    *
    * Array data
    *     bool: ... [Indexer N created]        ------------>    [0 indexed]   [1 indexed]   ... [Indexer N+1 created]     ...
    *     int:  ... [Indexer N index count] [Freeindex address] [Freeindex 0] [Freeindex 1] ... [Indexer N+1 index count] ...
    *************************************************************************/


    library Indexer
    //=== Settings ===
        globals
            private constant integer SIZE = 256
    //================
            private integer count = 0
            private boolean array b
            private integer array i
        endglobals
       
        function CreateIndexer takes integer n returns integer
            local integer temp = count
            set b[count] = true
            set i[count] = 0
            set i[count + 1] = 1
            set count = count + n
            return temp
        endfunction
       
        function IndexCount takes integer CODE returns integer
            return i[CODE]
        endfunction

        function Indexed takes integer CODE, integer index returns boolean
            return b[CODE + 1 + index]
        endfunction
       
        function Index takes integer CODE returns integer
            local integer j = CODE + 1
            local integer index
            if i[j] == 1 then
                set index = i[CODE]
                set i[CODE] = i[CODE] + 1
            else
                set index = i[i[j]]
                set i[j] = i[j] - 1
            endif
            set b[j + index] = true
            return index
        endfunction
       
        function Deindex takes integer CODE, integer index returns boolean
            local integer j = CODE + 1 + index
            if b[j] then
                set b[j] = false
                if i[CODE] == index + 1 then
                    set i[CODE] = index
                else
                    set CODE = CODE + 1
                    set i[CODE] = i[CODE] + 1
                    set i[i[CODE]] = index
                endif
                return true
            endif
            return false
        endfunction
    endlibrary

    Example of usage (old):
    Code (vJASS):
    //========================
    //=== SpellPoisonSting ===
    //======== v1.000 ========

    library SpellPoisonSting requires Cast, Indexed, SpellTypePoison
    //=== Settings ===
    globals
        private constant integer ABILCODE = 'X204'
        private constant integer BUFFCODE = 'W012'
        private constant integer SLOW_ABILITY = 'X206'
        private constant string SLOW_ORDER = "slow"
    //----------------
        private constant integer TICK_COUNT = 15
        private constant real TICK_TIME = 1
    endglobals
        struct SpellPoisonSting extends array
            private static real array TICK_DAMAGE
            private static method onInit takes nothing returns nothing
                set TICK_DAMAGE[1] = 4
                set TICK_DAMAGE[2] = 6
                set TICK_DAMAGE[3] = 9
                set TICK_DAMAGE[4] = 13
    //================
                set indexer = CreateIndexer()
            endmethod
            private static integer indexer
            private static unit array target
            private static unit array caster
            private static integer array level
            private static integer array tick_count
            private static timer array t
           
            private static method damage takes nothing returns nothing
                set Assist.workTimer = GetExpiredTimer()
                //! runtextmacro ObtainTimerIndex("t")
                //! runtextmacro DealPurePoisonDamage()
                if tick_count[Assist.workInteger] == 0 then
                    //! runtextmacro EndPoison("indexer")
                endif
            endmethod

            static method onUnitTakesDamage takes nothing returns nothing
                local integer level
                if GetUnitAbilityLevel(Damage.target, BUFFCODE) != 0 then
                    call UnitRemoveAbility(Damage.target, BUFFCODE)
                    set level = GetUnitAbilityLevel(Damage.source, ABILCODE)
                    call CastUnit(Damage.source, Damage.target, CASTER_DEFAULT_LIFETIME, SLOW_ABILITY, level, SLOW_ORDER)
                    if level != 0 then
                        //! runtextmacro BreakPoison("indexer")
                        //! runtextmacro SetPoison("indexer")
                        set tick_count[Assist.workInteger] = TICK_COUNT
                        call TimerStart(t[Assist.workInteger], TICK_TIME, true, function thistype.damage)
                    endif
                endif
            endmethod
        endstruct
    endlibrary

    SpellTypeIndexed:
    Code (vJASS):
    //===============
    //=== Indexed ===
    //=== v0.950 ====

    library Indexed requires Indexer
        //Timers
        //! textmacro ObtainTimerIndex takes t
            set Assist.workInteger = 0
            loop
                exitwhen $t$[Assist.workInteger] == Assist.workTimer
                set Assist.workInteger = Assist.workInteger + 1
            endloop
        //! endtextmacro

        //Units
        //! textmacro ObtainUnitIndex takes u
            set Assist.workInteger = 0
            loop
                exitwhen $u$[Assist.workInteger] == Assist.workUnit
                set Assist.workInteger = Assist.workInteger + 1
            endloop
        //! endtextmacro
       
        //! textmacro SeekUnit takes indexer, u
            set Assist.workBoolean = false
            set Assist.workInteger = 0
            loop
                exitwhen Assist.workInteger == IndexCount($indexer$) or Assist.workBoolean
                if $u$[Assist.workInteger] == Assist.workUnit then
                    set Assist.workBoolean = true
                endif
                set Assist.workInteger = Assist.workInteger + 1
            endloop
        //! endtextmacro
    endlibrary

    SpellTypePoison:
    Code (vJASS):
    //=======================
    //=== SpellTypePoison ===
    //======= v1.000 ========

    library SpellTypePoison requires Assist, Indexer, vGDC
        //-=- General -=-
        //! textmacro BreakPoison takes indexer
            set Assist.workInteger = 0
            loop
                exitwhen Assist.workInteger == IndexCount($indexer$)
                if target[Assist.workInteger] == Damage.target then
                    set tick_count[Assist.workInteger] = 1
                    set Assist.workInteger = IndexCount($indexer$)
                else
                    set Assist.workInteger = Assist.workInteger + 1
                endif
            endloop
        //! endtextmacro
       
        //! textmacro SetPoison takes indexer
            set Assist.workInteger = Index($indexer$)
            set target[Assist.workInteger] = Damage.target
            set caster[Assist.workInteger] = Damage.source
            set thistype.level[Assist.workInteger] = level
            if t[Assist.workInteger] == null then
                set t[Assist.workInteger] = CreateTimer()
            endif
        //! endtextmacro
       
        //! textmacro EndPoison takes indexer
            call Deindex($indexer$, Assist.workInteger)
            set target[Assist.workInteger] = null
            set caster[Assist.workInteger] = null
            call PauseTimer(t[Assist.workInteger])
        //! endtextmacro
       
        //-=- Pure poison -=-
        //! textmacro DealPurePoisonDamage
            set Assist.workReal = GetWidgetLife(target[Assist.workInteger])
            if Assist.workReal != 0 then
                if Assist.workReal < TICK_DAMAGE[level[Assist.workInteger]] then
                    call DealDamage(caster[Assist.workInteger], target[Assist.workInteger], ULTIMATE_DAMAGE, PURE, false)
                    set tick_count[Assist.workInteger] = 0
                else
                    call SetWidgetLife(target[Assist.workInteger], Assist.workReal - TICK_DAMAGE[level[Assist.workInteger]])
                    set tick_count[Assist.workInteger] = tick_count[Assist.workInteger] - 1
                endif
            endif
        //! endtextmacro
    endlibrary
     
    Last edited: Aug 7, 2013
  2. Almia

    Almia

    Joined:
    Apr 24, 2012
    Messages:
    4,860
    Resources:
    35
    Spells:
    30
    Tutorials:
    4
    JASS:
    1
    Resources:
    35
    Module? YEEEEEEEEEEEESSSSSSSSSSSSSSSSSS
     
    Last edited: Jul 28, 2013
  3. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    That's a function interface Almia.

    It's a cool way to have a function type. Not the _best_ solution however ;\

    By the way, would anyone really need 32768 instances of your indexCarrier? :p
    I mean, 8192 instances is already quite a lot
     
  4. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    Who knows :O
     
  5. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Actually, it seems that with the current configuration, you can only have 32 instances of the struct ;o

    The arrays of size 1024 each invalidate like 1023 indices while using 1 :eek:
     
  6. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    Np, we can make it larger!
    Though I have not tried to do it, I am using only 3 instances for now, and no one with unregister_func =D
    (Seems like struct of arrays or struct arrays aren't much different in executive code)
    ^^ Because ... unregister function is useful only when indexed objects are global, otherwise have evidently excessive methods
    (For example, global indexing of units / heroes / structures (because it sometimes seems useful to have separated global indexing) with attached data, though I still do not use this, just a possibility for someone maybe :])
     
  7. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    The code generated by this must be huge for larger values of TOTAL_SIZE_LIMIT :|
     
  8. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    Have I got right that non-struct version with 2D boolean array would be much better?
     
  9. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    You don't need to get rid of the struct.
    You can use Table instead of having the arrays.

    This will also allow you to get rid of the size in the struct and just leave it with the default 8192 max size.

    Doing this will increase capacity by 256 times
     
  10. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,016
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Basically you could use a struct to do this same thing. Scoping indices and abstracting arrays to use "." syntax is more important to me than using a central library just for the sake of unifying indices.

    Big arrays also compile into a mess.

    Scheduling for graveyard.
     
  11. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    Let's suppose I remade this into 2D private boolean array and struct with static public methods and static readonly fields (to use .[] syntax and others)
    This seems much more effective than having a lot of structures (~1 skill per hero = 100 indexes for kind of Dota map) with implemented indexing
    Spells are encapsulated in libraries, so what "." syntax do you want to use if ~90% of struct members used inside the library? (And ~9% of the rest is not connected with indexing)
    Seems like garbage in this case
    (Though I am thinking too much in my own way probably)
     
  12. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    Reworked
    (Take a look at example also)
     
    Last edited: Jul 31, 2013
  13. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    Replaced modules (^_^) with textmacro
     
  14. Almia

    Almia

    Joined:
    Apr 24, 2012
    Messages:
    4,860
    Resources:
    35
    Spells:
    30
    Tutorials:
    4
    JASS:
    1
    Resources:
    35
    API please.
     
  15. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    ^ Added
    By the way, this is very simple snippet and intuitive to work with, I think this does not need any public struct interface
     
  16. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    I don't think that trying to unify everything like this is a good idea for wc3
     
  17. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    Why?
    Coz my thoughts are quite the opposite for now :O
     
  18. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Well, unifying allows any resource to have a relation to any resource, like passing a linked list between two resources.

    There are a few problems with this in *wc3*

    1: memory is limited (will run into performance issues trying to make a bigger array, a hashtable will actually be faster)
    2: arrays of different types can't be easily related (once again, hashtable)
    3. performance (will have to result in a hashtable, best performing implementation)

    Now, while relating any resource to any other resource may be good, it's not very necessary

    Also

    when any two resources are related to each other, they typically use each other's structures specifically, not a generic structure. In cases where a generic structure is used, a specific implementation for the resource can usually be utilized (very rare when a generic global structure is better, sorting is one example)


    The 1 pro does not outweigh the 3 cons. In SC2, you can actually do a global memory space, and it's recommended that you do a global memory space too. Why? You can make gigantic arrays, you can use functionrefs to perform generic operations on an unknown set, and you can link sets of different types up with each other.

    If you want something like this, it's only really feasible in SC2.
     
  19. Krogoth

    Krogoth

    Joined:
    Apr 5, 2011
    Messages:
    247
    Resources:
    0
    Resources:
    0
    :[
    What's ~ size when these issues start?
     
  20. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    When u get into more than 1 array, u have the issue, so greater than 8k