Ruby Scripting
#17
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? Thinking

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

Happy with a sweat 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.

Thinking Is there another way to do the same?
Grinning 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. Laughing

Thinking 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. Laughing

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. Tongue sticking out

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. Angry

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 Dalek nil's it right away. Yeah, like a good old Dalek 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. Winking

Sad 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. Face Palm 

Incredible 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 Orson ruckus than what your code was supposed to solve in the first place. Laughing
"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.

[Image: SP1-Scripter.png]
[Image: SP1-Writer.png]
[Image: SP1-Poet.png]
[Image: SP1-PixelArtist.png]
[Image: SP1-Reporter.png]

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! Laughing + Tongue sticking out

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
Reply }


Messages In This Thread
Ruby Scripting - by kyonides - 08-29-2019, 04:51 AM
RE: Ruby Scripting - by kyonides - 08-30-2019, 05:47 AM
RE: Ruby Scripting - by kyonides - 09-03-2019, 07:24 AM
RE: Ruby Scripting - by kyonides - 09-06-2019, 05:46 AM
RE: Ruby Scripting - by kyonides - 09-09-2019, 05:00 AM
RE: Ruby Scripting - by kyonides - 06-05-2021, 08:20 PM
RE: Ruby Scripting - by kyonides - 11-28-2021, 03:31 AM
RE: Ruby Scripting - by kyonides - 05-02-2022, 02:43 AM
RE: Ruby Scripting - by kyonides - 01-27-2023, 08:01 AM
RE: Ruby Scripting - by kyonides - 02-03-2023, 02:42 AM
RE: Ruby Scripting - by DerVVulfman - 02-03-2023, 03:52 AM
RE: Ruby Scripting - by kyonides - 02-03-2023, 04:33 AM
RE: Ruby Scripting - by kyonides - 04-19-2023, 12:47 AM
RE: Ruby Scripting - by kyonides - 04-19-2023, 01:12 AM
RE: Ruby Scripting - by kyonides - 06-08-2023, 09:24 PM
RE: Ruby Scripting - by kyonides - 06-08-2023, 09:46 PM
RE: Ruby Scripting - by kyonides - 06-12-2023, 06:29 AM
RE: Ruby Scripting - by kyonides - 07-14-2023, 10:37 PM
RE: Ruby Scripting - by kyonides - 07-15-2023, 07:32 AM
RE: Ruby Scripting - by kyonides - 07-16-2023, 06:05 AM
RE: Ruby Scripting - by kyonides - 07-17-2023, 04:01 AM
RE: Ruby Scripting - by kyonides - 08-22-2023, 08:59 AM
RE: Ruby Scripting - by kyonides - 08-28-2023, 03:34 AM
RE: Ruby Scripting - by kyonides - 11-18-2023, 09:02 AM
RE: Ruby Scripting - by kyonides - 04-16-2024, 06:57 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
   Ruby - Behind the Scenes DerVVulfman 0 1,148 07-15-2023, 05:52 PM
Last Post: DerVVulfman
Information  Assorted Ruby chm documents. hanetzer 10 35,247 08-17-2020, 04:19 AM
Last Post: kyonides
Brick  Learn Ruby! greenraven 2 7,614 05-16-2014, 12:25 PM
Last Post: greenraven
   Creating Your Own Scripting System DerVVulfman 3 7,467 10-12-2009, 03:37 PM
Last Post: Alpha-Mad
   How to make interesting NPC's without scripting Third333Strike 0 3,846 12-06-2008, 04:59 PM
Last Post: Third333Strike



Users browsing this thread: 9 Guest(s)