v0.2
- method clean added
- method getRandom added
- add the set to 0 the Inc integer variable on top of functions in case of reach a limit op
- remove the uneeded local triggercondition in the forGroup method and remplace it by a global
- warning message to avoid desync with mac users with the method forGroup added
- removed an unused variable integer
- improved the methods copy and addGroup to avoid adding a null thing and return an integer instead of a boolean
- made a cleaner example
v0.1
- Initial release
//============================================================================== // ATGS -> Any Type Group System -- v0.2 //============================================================================== // // PURPOUSE: // * Use structs and methods for simulate an using of group for any type. // // // HOW TO USE: // * Check the test trigger and the last lines in this trigger. // // // PROS: // * Can easily use a "group" for any type (but you need to know vJass). // // * You can add the same thing many times in the group, but only if you really // want it of course, with the method altAdd. // // * Not as the natives functions, it return a boolean when you use the methods, // to know if it was done or not. // // // CONS: // * It's not very fast, if you really care about it, just use arrays ... // // * You need to remove yourself a thing in a group, not as in an unit group when // an unit is removed of the game. // // // DESCRIPTION OF THE METHODS: // * create : Just create a new group. // // * add : Add the thing to the group, if the thing is already in the group, // then it doesn't add it. Return true if add it and false if not. // It will be slower as the group is bigger. // // * altAdd : Add the thing to the group but it doesn't check if it is already // in group or not, so it is fast but not safe. It can be use too if // you want to add the same thing in the group. // // * remove : Remove the thing to the group. Return true if remove it and false if not. // It doesn't check if the thing is many times in group or not. // It will be slower as the group is bigger. // // * altRemove : Remove the thing of the group as many times as you want. // Use the argument 0 for remove totally the thing. // It return the how many times the thing was removed // It will be slower as the group is bigger. // // * clear : Just prepare the group for an other usage. it doesn't clear the memory, // as the clear natives. It just set an integer variable to 0, so it's fast // // * altClear : Prepare the group for an other usage and clean the memory. // It will be slower as the group is bigger. // // * isInGroup : Return true if the thing is in group and false if not. // It will be slower as the group is bigger. // // * forGroup : Just like the native ForGroup, but you need to use a textmacro // at the top of your function callback. Check the trigger test. // Like the native ForGroup it doesn't support TriggerSleepAction, // and so of course neither the PolledWait. // >>>> USE A FUNCTION WHICH RETURN A BOOLEAN TO AVOID DESYNC WITH MAC USERS <<<< // It will be slower as the source group is bigger. // // * copy : Copy a group. Return true if it was done and false if not. // It will be slower as the source group is bigger. // // * addGroup : Add a group to the source group. Return true if it was done and false if not. // It will be slower as the source group is bigger. // // * clean : Remove all null things on the group. It will be slower as the source group is bigger. // // * getRandom : Get a random thing in the group, return the null type if the group is empty // // // SPECIAL THANKS TO: // * Vexorian for the vJass. // // // HOW TO IMPORT: // * copy/paste this trigger. // //==============================================================================
//! textmacro Groups takes TYPE,NULL_TYPE,STRUCT_ARRAY,GROUP_ARRAY
struct s_$TYPE$Group[$STRUCT_ARRAY$]
publicinteger Index // I don't use private because you may want to read the value, but don't set it ... public $TYPE$ Enum // I don't use private to avoid a function call for the method forForce, but don't use it. publicstatic s_$TYPE$Group TB$TYPE$Group // I don't use private to avoid a function call for the method forForce, but don't use it privateintegerarray Copy[$GROUP_ARRAY$] private $TYPE$ array Group[$GROUP_ARRAY$] privatestatictrigger T= CreateTrigger() privatestaticinteger Inc= 0 privatestatictriggercondition Cond
staticmethod create takesnothingreturns s_$TYPE$Group local s_$TYPE$Group s= s_$TYPE$Group.allocate()
set s.Index=0
return s endmethod
method add takes $TYPE$ t returnsboolean localinteger i= .Index
if .Index== $GROUP_ARRAY$ then debugcall BJDebugMsg(s_$TYPE$Group.add.name+" the group is full, remove before add again") returnfalse elseif t== $NULL_TYPE$ then debugcall BJDebugMsg(s_$TYPE$Group.add.name+" $TYPE$ is $NULL_TYPE$") returnfalse endif
loop exitwhen i==0 set i=i-1
if .Group[i]== t then returnfalse endif
endloop
set .Group[.Index]=t set .Index= .Index+1
returntrue endmethod
privatemethod altAdd takes $TYPE$ t returnsboolean localinteger i= .Index
if .Index== $GROUP_ARRAY$ then debugcall BJDebugMsg(s_$TYPE$Group.altAdd.name+" the group is full, remove before add again") returnfalse elseif t== $NULL_TYPE$ then debugcall BJDebugMsg(s_$TYPE$Group.altAdd.name+" $TYPE$ is $NULL_TYPE$") returnfalse endif
set .Group[.Index]=t set .Index= .Index+1
returntrue endmethod
method remove takes $TYPE$ t returnsboolean localinteger i= .Index
if t== $NULL_TYPE$ then debugcall BJDebugMsg(s_$TYPE$Group.remove.name+" $TYPE$ is $NULL_TYPE$") returnfalse endif
loop exitwhen i==0 set i=i-1
if .Group[i]== t then set .Index= .Index-1 set .Group[i]=.Group[.Index] set .Group[.Index]= $NULL_TYPE$ returntrue endif
if t== $NULL_TYPE$ then debugcall BJDebugMsg(s_$TYPE$Group.remove.name+" $TYPE$ is $NULL_TYPE$") return 0 elseif nbr< 0 then
endif
if nbr== 0 then set nbr= i endif
set .Inc= 0
loop exitwhen i==0 or nbr==0 set i=i-1
if .Group[i]== t then set .Copy[.Inc]=i set .Inc= .Inc+1 set nbr= nbr-1 endif
endloop set i=.Inc
loop exitwhen .Inc== 0 set .Inc= .Inc-1
set .Index= .Index-1 set .Group[.Copy[.Inc]]=.Group[.Index] set .Group[.Index]= $NULL_TYPE$ set .Copy[.Inc]= 0
endloop
return i endmethod
method clear takesnothingreturnsnothing set .Index= 0 endmethod
method altClear takesnothingreturnsnothing
loop exitwhen .Index== 0 set .Index= .Index-1
set .Group[.Index]=$NULL_TYPE$
endloop
endmethod
method isInGroup takes $TYPE$ t returnsboolean localinteger i= .Index
if t== $NULL_TYPE$ then debugcall BJDebugMsg(s_$TYPE$Group.isInGroup.name+" $TYPE$ is $NULL_TYPE$") returnfalse endif
loop exitwhen i== 0 set i= i-1
if t== .Group[i]then returntrue endif
endloop
returnfalse endmethod
method forGroup takescode c returnsnothing localinteger i= .Index
set .Cond= TriggerAddCondition(.T,Condition(c)) loop exitwhen i== 0 set i =i-1
set .Enum= .Group[i] set .TB$TYPE$Group= this call TriggerEvaluate(.T)
endloop
set .Enum= $NULL_TYPE$ set .TB$TYPE$Group= 0 call TriggerRemoveCondition(.T,.Cond)
endmethod
method copy takes s_$TYPE$Group s returnsinteger localinteger i= .Index
set .Inc=0 if s== 0 then debugcall BJDebugMsg(s_$TYPE$Group.copy.name+ " the destGroup is an invalid struct") return 0 endif
loop exitwhen i==0 set i= i-1
if .Group[i]!= $NULL_TYPE$ then set s.Group[i]= .Group[i] set .Inc= .Inc+1 endif
endloop set s.Index= s.Index+.Inc
return .Inc endmethod
method addGroup takes s_$TYPE$Group s returnsinteger localinteger i= s.Index
if s== 0 then debugcall BJDebugMsg(s_$TYPE$Group.addGroup.name+ " the sourceGroup is an invalid struct") return 0 elseif s.Index== 0 then debugcall BJDebugMsg(s_$TYPE$Group.addGroup.name+ " the sourceGroup is empty") return 0 elseif s.Index+.Index > $GROUP_ARRAY$ then debugcall BJDebugMsg(s_$TYPE$Group.addGroup.name+ " to many things to add for the destgroup size") return 0 endif set .Inc=0
loop exitwhen i == 0 set i= i-1
if s.Group[i]!= $NULL_TYPE$ then set .Group[.Index+i]= s.Group[i] set .Inc= .Inc+1 endif
if .Group[i]== $NULL_TYPE$ then set .Index= .Index-1 set .Group[i]= .Group[.Index] set .Group[.Index]= $NULL_TYPE$ set .Inc= .Inc+1
endif
endloop return .Inc endmethod
method getRandom takesnothingreturns $TYPE$ if .Index==0 then return $NULL_TYPE$ debugcall BJDebugMsg(s_$TYPE$Group.getRandom.name+ " the group is empty") endif
loop exitwhen .Index== 0
set .Inc= GetRandomInt(0,.Index-1)
if .Group[.Inc]!= $NULL_TYPE$ then return .Group[.Inc] endif
set .Index= .Index-1
if .Index!= .Inc then set .Group[.Inc]= .Group[.Index] set .Group[.Index]= $NULL_TYPE$ endif
endloop return $NULL_TYPE$ endmethod
endstruct
//! endtextmacro
//! textmacro InitEnum takes STRUCT_VARIABLE_NAME,TYPE,ENUM_VARIABLE_NAME local s_$TYPE$Group $STRUCT_VARIABLE_NAME$= s_$TYPE$Group.TB$TYPE$Group local $TYPE$ $ENUM_VARIABLE_NAME$= $STRUCT_VARIABLE_NAME$.Enum //! endtextmacro
// to avoid a desynch with mac users use a fonction which return a boolean privatefunction LoopforGroup takesnothingreturnsboolean// use a function that takes nothing //! runtextmacro InitEnum("s","destructable","d")
Why aren't you using a function interface for ForGroup? Add a single integer parameter to make passing structs really, really easy. (pass an arbitrary int to forGroup, and its passed to the interface func on each iteration.)
__________________
Giving reputation is a nice way to say thank you to someone that helps you!
Why aren't you using a function interface for ForGroup? Add a single integer parameter to make passing structs really, really easy. (pass an arbitrary int to forGroup, and its passed to the interface func on each iteration.)
because i had never use that.
could you make an example plz ?
ok thx, i will change it.
i will be absent for one/two or three weeks.
Plz don't put it on graveyard, i will improve it when i will back, or let me post in it :p
functioninterface $GNAME$ForGroup takes $GNAME$ sourceGroup, $GTYPE$ value, integer tag returnsnothing
privatestruct $GNAME$Node $GNAME$Node next = 0 $GNAME$Node prev = 0
$GTYPE$ value endstruct
struct $GNAME$ $GNAME$Node first = 0 $GNAME$Node last = 0 integer nodeCount = 0
method add takes $GTYPE$ value returnsnothing local $GNAME$Node n = $GNAME$Node.create()
set n.value = value
set n.next = this.first set this.first.prev = n set this.first = n
set this.nodeCount = this.nodeCount + 1 endmethod
method addGroup takes $GNAME$ from returnsnothing local $GNAME$Node enum = from.first
loop exitwhen enum == 0
call this.add(enum.value)
set enum = enum.next endloop endmethod
method remove takes $GTYPE$ value returnsboolean local $GNAME$Node enum = this.first
loop exitwhen enum == 0
if enum.value == value then if this.first == enum then set this.first = enum.next endif
if this.last == enum then set this.last = enum.prev endif
if enum.prev != 0 then set enum.prev.next = enum.next endif
if enum.next != 0 then set enum.next.prev = enum.prev endif
call enum.destroy()
set this.nodeCount = this.nodeCount - 1
returntrue endif
set enum = enum.next endloop
returnfalse endmethod
method clear takesnothingreturnsnothing local $GNAME$Node enum = this.first
loop exitwhen enum == 0
if enum.next == 0 then call enum.destroy() exitwhentrue else set enum = enum.next call enum.prev.destroy() endif endloop
set this.first = 0 set this.last = 0
set this.nodeCount = 0 endmethod
method containsValue takes $GTYPE$ value returnsboolean local $GNAME$Node enum = this.first
loop exitwhen enum == 0
if enum.value == value then returntrue endif
set enum = enum.next endloop
returnfalse endmethod
method getRandom takesnothingreturns $GTYPE$ local $GNAME$Node enum = this.first localinteger goto = GetRandomInt(0, this.nodeCount - 1) localinteger i = 0
loop if i == goto then return enum.value endif
set i = i + 1 set enum = enum.next endloop
return $GNULL$ endmethod
method forGroup takes $GNAME$ForGroup func, integer tag returnsnothing local $GNAME$Node enum = this.first
loop exitwhen enum == 0
call func.evaluate(this, enum.value, tag)
set enum = enum.next endloop endmethod endstruct
endscope //! endtextmacro
endlibrary
(Stupid need for $GNULL$ >_>) Possible problem I have yet to remedy: calling .remove(value) from a forgroup callback can possibly fuck up iteration. (I'm just too lazy to solve that problem right now...)
__________________
Giving reputation is a nice way to say thank you to someone that helps you!
functioninterface $GNAME$ForGroup takes $GNAME$ sourceGroup, $GTYPE$ value, integer tag returnsnothing
privatestruct $GNAME$Node $GNAME$Node next = 0 $GNAME$Node prev = 0
$GTYPE$ value endstruct
struct $GNAME$ $GNAME$Node first = 0 $GNAME$Node last = 0 integer nodeCount = 0
method add takes $GTYPE$ value returnsnothing local $GNAME$Node n = $GNAME$Node.create()
set n.value = value
// Linked List operations: set n.prev = this.last set this.last.next = n set this.last = n
if this.first == 0 then set this.first = n endif
// Node Counting: set this.nodeCount = this.nodeCount + 1 endmethod
method addGroup takes $GNAME$ from returnsnothing local $GNAME$Node enum = from.first
loop exitwhen enum == 0
call this.add(enum.value)
set enum = enum.next endloop endmethod
method remove takes $GTYPE$ value returnsboolean local $GNAME$Node enum = this.first
loop exitwhen enum == 0
if enum.value == value then // Iteration: if enum == this.now then if this.now.next == 0 then set this.now = 0 elseif this.now.prev == 0 then set this.now = -1 else set this.now = this.now.prev endif endif // End Iteration
if this.first == enum then set this.first = enum.next else set enum.prev.next = enum.next endif
if this.last == enum then set this.last = enum.prev else set enum.next.prev = enum.prev endif
call enum.destroy()
set this.nodeCount = this.nodeCount - 1
returntrue endif
set enum = enum.next endloop
returnfalse endmethod
method clear takesnothingreturnsnothing local $GNAME$Node enum = this.first
loop exitwhen enum == 0
if enum.next == 0 then call enum.destroy() exitwhentrue else set enum = enum.next call enum.prev.destroy() endif endloop
set this.first = 0 set this.last = 0
set this.nodeCount = 0
// Iteration: set this.now = 0 endmethod
method containsValue takes $GTYPE$ value returnsboolean local $GNAME$Node enum = this.first