Revisiting the Array Class: Special Iterators
It is quite normal to go through a short or large Array to find something very specific that does NOT involved an index aka position at all, but how do you do that?
Two of the most common iterators are the for loop and the each iterator.
I am leaving some examples of how they would let you return a Game_Actor that matches a very specific criterion or nil if that never happens.
The For Loop
XP Version
Code:
class Game_Party
def find_aluxes
for actor in @actors
return actor if actor.id == 1
end
end
end
VX & VX Ace Version
Code:
class Game_Party
def find_ralph_or_eric
for actor_id in @actors
return $game_actors[actor] if actor_id == 1
end
end
end
The Each Iterator
This is how an each iterator would look for Aluxes aka Alexis aka Alex in RMXP.
Code:
class Game_Party
def find_aluxes
@actors.each {|actor| return actor if actor.id == 1 }
end
end
Of course, I could also have used a do plus some end keywords instead of curly braces there. Normally, you would use the keywords for iterators spanning 2+ lines of code on screen.
Is there another way to do the same?
Yes, there is just another method to accomplish the same goal. It is called the find iterator.
Code:
class Game_Party
def find_aluxes
@actors.find {|actor| actor.id == 1 }
end
end
Once again, you got to be careful because it could also return a nil value if Aluxes was away having fun with some cat girl at that moment.
What if you need to return a non nil value at the end of the iterator?
You could just add a return true or return false or return 0 line of code outside that block and it would work fine. Keep in mind you can put there whatever you need as its "failed test" return value. Let us take a look at some RMXP's code to make my point clear here.
Code:
class Game_Party
def all_dead?
# If number of party members is 0
if $game_party.actors.size == 0
return false
end
# If an actor is in the party with 0 or more HP
for actor in @actors
if actor.hp > 0
return false
end
end
# All members dead
return true
end
As you can see above, it is supposed to return false IF any actor is still alive but true otherwise.
Array's collect and map methods
The first thing I got to tell you here is that they are one and the same. map is nothing but collect's alias.
This is what collect does:
Code:
class Game_Party
def actors_names
@actors.map {|actor| actor.name }
end
end
Code:
class Game_Party
def members_names
@actors.map {|actor_id| $game_actors[actor_id].name }
end
end
What that code does is to retrieve all of the actors' names and keep them in a new Array object.
If you don't assign it to any variable, you lose the data and have to start all over again.
Array's select and reject methods
select simply does the same job collect does WITH an exception. It only cares about those values that matched the given criteria.
Code:
class Game_Party
def alive_actors
@actors.select {|actor| !actor.hidden and actor.hp > 0 }
end
end
Code:
class Game_Party
def alive_actors
members.select {|actor| !actor.hidden and actor.hp > 0 }
end
end
reject's purpose is the exact opposite as its name obviously implies.
A Real Life Situation & Application
Here is a piece of code I had found online that made me slightly sick for make the code look more convoluted that it ever should have in the first place.
Code:
class Window_CardSelect < Window_SkillList
def make_item_list
@data = @cards
@data.each_with_index do |card, i|
if card.exclude_extra
@data[i] = nil
end
end
@data.compact!
end
end
As you can see above, there is a make_item_list method that retrieves the existing @cards in a deck but for reason it needs to get rid of some of them before displaying them on the Card Selection Window.
I find it problematic indeed.
First, it creates not a copy but a link or reference to the @cards Array.
Then it iterates through that list looking for an exclusion criterion using a variant of the each iterator we have discused already.
If the test passes, it nil's it right away. Yeah, like a good old Dalek would do it!
At the end of the process, the array calls its compact! method to get rid of all those nil values in a blink of an eye.
Why is this terrible?
The reason is simple. You made a huge effort to get rid of all of those so called extra cards... only to later find out that you actually made them disappear forever and ever AND there is a high potential for it to return a dreadful nil value instead if the array had no nil values at all.
What should we do now?
The solution is even more simple than you could ever foresee as an amateur scripter. Just take a look at this curious snippet that applies some of the knowledge we have acquired today while reading this post.
Code:
class Window_CardSelect < Window_SkillList
def make_item_list
@data = @cards.reject{|card| card.exclude_extra }
end
end
That is ALL we needed to do to prevent it from destroying our deck for eternity or pretend it did while keeping it hidden from sight.
Now you know just another reason why you better pick the right method for your issue from the very beginning. Or else you will be causing more ruckus than what your code was supposed to solve in the first place.
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
My Original Stories (available in English and Spanish)
List of Compiled Binary Executables I have published...
HiddenChest & Roole
Give me a free copy of your completed game if you include at least 3 of my scripts!
Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
My Original Stories (available in English and Spanish)
List of Compiled Binary Executables I have published...
HiddenChest & Roole
Give me a free copy of your completed game if you include at least 3 of my scripts!
Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE