(12-21-2012, 11:25 AM)Kain Nobel Wrote: I found an interesting little tidbit today! Actually I've found it before and forgot about it, but since I've been reminded...
Game_Battler#add_state
Notice
how in the definition of add_state, the definition calls itself?
This is from the default script, but I'm curious why it doesn't throw a
Stack Level Too Deep or something.
Code:
#--------------------------------------------------------------------------
# * Add State
# state_id : state ID
# force : forcefully added flag (used to deal with auto state)
#--------------------------------------------------------------------------
def add_state(state_id, force = false)
# For an ineffective state
if $data_states[state_id] == nil
# End Method
return
end
# If not forcefully added
unless force
# A state loop already in existance
for i in @states
# If a new state is included in the state change (-) of an existing
# state, and that state is not included in the state change (-) of
# a new state (example: an attempt to add poison during dead)
if $data_states[i].minus_state_set.include?(state_id) and
not $data_states[state_id].minus_state_set.include?(i)
# End Method
return
end
end
end
# If this state is not added
unless state?(state_id)
# Add state ID to @states array
@states.push(state_id)
# If option [regarded as HP 0]is effective
if $data_states[state_id].zero_hp
# Change HP to 0
@hp = 0
end
# All state loops
for i in 1...$data_states.size
# Dealing with a state change (+)
if $data_states[state_id].plus_state_set.include?(i)
add_state(i)
end
# Dealing with a state change (-)
if $data_states[state_id].minus_state_set.include?(i)
remove_state(i)
end
end
# line change to a large rating order (if value is the same, then a
# strong restriction order)
@states.sort! do |a, b|
state_a = $data_states[a]
state_b = $data_states[b]
if state_a.rating > state_b.rating
-1
elsif state_a.rating < state_b.rating
+1
elsif state_a.restriction > state_b.restriction
-1
elsif state_a.restriction < state_b.restriction
+1
else
a <=> b
end
end
end
# If added forcefully
if force
# Set the natural removal's lowest number of turns to -1
@states_turn[state_id] = -1
end
# If not added forcefully
unless @states_turn[state_id] == -1
# Set the natural removal's lowest number of turns
@states_turn[state_id] = $data_states[state_id].hold_turn
end
# If unable to move
unless movable?
# Clear action
@current_action.clear
end
# Check the maximum value of HP and SP
@hp = [@hp, self.maxhp].min
@sp = [@sp, self.maxsp].min
end
There is a way for a method to call itself within its own definition,
but that is via the use of alias or alias_method. A child
method can call the definition of a parent's method by using a super, a parent method can call other methods defined by it's
child class even if its not defined within its own class, but a method calling itself
just seems odd to me.
A freshly defined method shouldn't be able to call itself within it's own definition, should it?
That is actually a misconception. In RGSS, you can indeed have a method call itself recursively, just as you can in regular old Ruby. You only get the "stack level too deep" error if you actually make a stack that is too deep. Unfortunately for RGSS I remember this stack being really small (200 something if I remember correctly) and so recursive calls are not very useful when scripting. In this case, it is VERY unlikely states will be nested in a way to exceed the stack so this is an okay thing to do.