Advertisement
Maruno

AI vs AI tester

Jun 25th, 2023
1,809
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 22.34 KB | None | 0 0
  1. # TODO: Be much more relevant with the choosing of held items. For example,
  2. #       only give a weather-boosting item to a Pokémon that can create the
  3. #       corresponding weather.
  4.  
  5. AI_MOVE_TESTING_THRESHOLD    = 1500
  6. AI_ABILITY_TESTING_THRESHOLD = 500
  7. AI_ITEM_TESTING_THRESHOLD    = 500
  8.  
  9. #===============================================================================
  10. #
  11. #===============================================================================
  12. # There are some duplicate effects in here (e.g. Power Weight/Bracer/etc.), but
  13. # whatever.
  14. ITEMS_WITH_HELD_EFFECTS = [
  15.   :AIRBALLOON, :BRIGHTPOWDER, :EVIOLITE, :FLOATSTONE, :DESTINYKNOT,
  16.   :ROCKYHELMET, :ASSAULTVEST, :SAFETYGOGGLES, :PROTECTIVEPADS, :HEAVYDUTYBOOTS,
  17.   :UTILITYUMBRELLA, :EJECTBUTTON, :EJECTPACK, :REDCARD, :SHEDSHELL, :CHOICEBAND,
  18.   :CHOICESPECS, :CHOICESCARF, :HEATROCK, :DAMPROCK, :SMOOTHROCK, :ICYROCK,
  19.   :TERRAINEXTENDER, :LIGHTCLAY, :GRIPCLAW, :BINDINGBAND, :BIGROOT, :BLACKSLUDGE,
  20.   :LEFTOVERS, :SHELLBELL, :MENTALHERB, :WHITEHERB, :POWERHERB, :ABSORBBULB,
  21.   :CELLBATTERY, :LUMINOUSMOSS, :SNOWBALL, :WEAKNESSPOLICY, :BLUNDERPOLICY,
  22.   :THROATSPRAY, :ADRENALINEORB, :ROOMSERVICE, :ELECTRICSEED, :GRASSYSEED,
  23.   :MISTYSEED, :PSYCHICSEED, :LIFEORB, :EXPERTBELT, :METRONOME, :MUSCLEBAND,
  24.   :WISEGLASSES, :RAZORCLAW, :SCOPELENS, :WIDELENS, :ZOOMLENS, :KINGSROCK,
  25.   :RAZORFANG, :LAGGINGTAIL, :QUICKCLAW, :FOCUSBAND, :FOCUSSASH, :FLAMEORB,
  26.   :TOXICORB, :STICKYBARB, :IRONBALL, :RINGTARGET, :MACHOBRACE, :POWERWEIGHT,
  27.   :POWERBRACER, :POWERBELT, :POWERLENS, :POWERBAND, :POWERANKLET, :LAXINCENSE,
  28.   :FULLINCENSE, :SEAINCENSE, :WAVEINCENSE, :ROSEINCENSE, :ODDINCENSE,
  29.   :ROCKINCENSE, :CHARCOAL, :MYSTICWATER, :MAGNET, :MIRACLESEED, :NEVERMELTICE,
  30.   :BLACKBELT, :POISONBARB, :SOFTSAND, :SHARPBEAK, :TWISTEDSPOON, :SILVERPOWDER,
  31.   :HARDSTONE, :SPELLTAG, :DRAGONFANG, :BLACKGLASSES, :METALCOAT, :SILKSCARF,
  32.   :FIREGEM, :WATERGEM, :ELECTRICGEM, :GRASSGEM, :ICEGEM, :FIGHTINGGEM,
  33.   :POISONGEM, :GROUNDGEM, :FLYINGGEM, :PSYCHICGEM, :BUGGEM, :ROCKGEM, :GHOSTGEM,
  34.   :DRAGONGEM, :DARKGEM, :STEELGEM, :FAIRYGEM, :NORMALGEM, :CHERIBERRY,
  35.   :CHESTOBERRY, :PECHABERRY, :RAWSTBERRY, :ASPEARBERRY, :LEPPABERRY, :ORANBERRY,
  36.   :PERSIMBERRY, :LUMBERRY, :SITRUSBERRY, :FIGYBERRY, :WIKIBERRY, :MAGOBERRY,
  37.   :AGUAVBERRY, :IAPAPABERRY, :OCCABERRY, :PASSHOBERRY, :WACANBERRY, :RINDOBERRY,
  38.   :YACHEBERRY, :CHOPLEBERRY, :KEBIABERRY, :SHUCABERRY, :COBABERRY, :PAYAPABERRY,
  39.   :TANGABERRY, :CHARTIBERRY, :KASIBBERRY, :HABANBERRY, :COLBURBERRY,
  40.   :BABIRIBERRY, :ROSELIBERRY, :CHILANBERRY, :LIECHIBERRY, :GANLONBERRY,
  41.   :SALACBERRY, :PETAYABERRY, :APICOTBERRY, :LANSATBERRY, :STARFBERRY,
  42.   :ENIGMABERRY, :MICLEBERRY, :CUSTAPBERRY, :JABOCABERRY, :ROWAPBERRY, :KEEBERRY,
  43.   :MARANGABERRY
  44. ]
  45. # These items have no effect if held by other species. Includes the Plates
  46. # because other items also have the type-boosting effect and we don't need to
  47. # test that effect of Plates.
  48. SIGNATURE_ITEMS = {
  49.   :PIKACHU   => :LIGHTBALL,
  50.   :CHANSEY   => :LUCKYPUNCH,
  51.   :DITTO     => [:METALPOWDER, :QUICKPOWDER],
  52.   :CUBONE    => :THICKCLUB,
  53.   :MAROWAK   => :THICKCLUB,
  54.   :FARFETCHD => :LEEK,
  55.   :SIRFETCHD => :LEEK,
  56.   :LATIOS    => :SOULDEW,
  57.   :LATIAS    => :SOULDEW,
  58.   :CLAMPERL  => [:DEEPSEATOOTH, :DEEPSEASCALE],
  59.   :DIALGA    => :ADAMANTORB,
  60.   :PALKIA    => :LUSTROUSORB,
  61.   :ARCEUS    => [:FLAMEPLATE, :SPLASHPLATE, :ZAPPLATE, :MEADOWPLATE,
  62.                  :ICICLEPLATE, :FISTPLATE, :TOXICPLATE, :EARTHPLATE, :SKYPLATE,
  63.                  :MINDPLATE, :INSECTPLATE, :STONEPLATE, :SPOOKYPLATE,
  64.                  :DRACOPLATE, :DREADPLATE, :IRONPLATE, :PIXIEPLATE],
  65.   :GENESECT  => [:DOUSEDRIVE, :SHOCKDRIVE, :BURNDRIVE, :CHILLDRIVE],
  66.   :SILVALLY  => [:FIREMEMORY, :WATERMEMORY, :ELECTRICMEMORY, :GRASSMEMORY,
  67.                  :ICEMEMORY, :FIGHTINGMEMORY, :POISONMEMORY, :GROUNDMEMORY,
  68.                  :FLYINGMEMORY, :PSYCHICMEMORY, :BUGMEMORY, :ROCKMEMORY,
  69.                  :GHOSTMEMORY, :DRAGONMEMORY, :DARKMEMORY, :STEELMEMORY,
  70.                  :FAIRYMEMORY],
  71.   :GROUDON   => :REDORB,        # Form-changing item
  72.   :KYOGRE    => :BLUEORB,       # Form-changing item
  73.   :GIRATINA  => :GRISEOUSORB,   # Form-changing item
  74.   :ZACIAN    => :RUSTEDSWORD,   # Form-changing item
  75.   :ZAMAZENTA => :RUSTEDSHIELD   # Form-changing item
  76. }
  77. MEGA_STONES = [
  78.   :VENUSAURITE, :CHARIZARDITEX, :CHARIZARDITEY, :BLASTOISINITE, :BEEDRILLITE,
  79.   :PIDGEOTITE, :ALAKAZITE, :SLOWBRONITE, :GENGARITE, :KANGASKHANITE, :PINSIRITE,
  80.   :GYARADOSITE, :AERODACTYLITE, :MEWTWONITEX, :MEWTWONITEY, :AMPHAROSITE,
  81.   :STEELIXITE, :SCIZORITE, :HERACRONITE, :HOUNDOOMINITE, :TYRANITARITE,
  82.   :SCEPTILITE, :BLAZIKENITE, :SWAMPERTITE, :GARDEVOIRITE, :SABLENITE, :MAWILITE,
  83.   :AGGRONITE, :MEDICHAMITE, :MANECTITE, :SHARPEDONITE, :CAMERUPTITE,
  84.   :ALTARIANITE, :BANETTITE, :ABSOLITE, :GLALITITE, :SALAMENCITE, :METAGROSSITE,
  85.   :LATIASITE, :LATIOSITE, :LOPUNNITE, :GARCHOMPITE, :LUCARIONITE, :ABOMASITE,
  86.   :GALLADITE, :AUDINITE, :DIANCITE
  87. ]
  88.  
  89. #===============================================================================
  90. #
  91. #===============================================================================
  92. class Battle::AI
  93.   alias _ai_testing__pbGetMoveScores pbGetMoveScores
  94.  
  95.   def pbGetMoveScores
  96.     if $tested_abilities && @user.ability_id
  97.       $tested_abilities[@user.ability_id] ||= 0
  98.       $tested_abilities[@user.ability_id] += 1
  99.     end
  100.     if $tested_items && @user.item_id
  101.       $tested_items[@user.item_id] ||= 0
  102.       $tested_items[@user.item_id] += 1
  103.     end
  104.     @user.battler.eachMoveWithIndex do |orig_move, idxMove|
  105.       if $tested_moves
  106.         $tested_moves[orig_move.id] ||= 0
  107.         $tested_moves[orig_move.id] += 1
  108.       end
  109.     end
  110.     return _ai_testing__pbGetMoveScores
  111.   end
  112. end
  113.  
  114. #===============================================================================
  115. #
  116. #===============================================================================
  117. def debug_set_up_trainer
  118.   # Values to return
  119.   trainer_array = []
  120.   foe_items     = []   # Items can't be used except in internal battles
  121.   pokemon_array = []
  122.   party_starts  = [0]
  123.  
  124.   # Choose random trainer type and trainer name
  125.   trainer_type = :CHAMPION   # GameData::TrainerType.keys.sample
  126.   trainer_name = ["Alpha", "Bravo", "Charlie", "Delta", "Echo",
  127.                   "Foxtrot", "Golf", "Hotel", "India", "Juliette",
  128.                   "Kilo", "Lima", "Mike", "November", "Oscar",
  129.                   "Papa", "Quebec", "Romeo", "Sierra", "Tango",
  130.                   "Uniform", "Victor", "Whiskey", "X-ray", "Yankee", "Zulu"].sample
  131.  
  132.   # Generate trainer
  133.   trainer = NPCTrainer.new(trainer_name, trainer_type)
  134.   trainer.id        = $player.make_foreign_ID
  135.   trainer.lose_text = "I lost."
  136.   trainer.items.push(:MEGARING)
  137.   # [:MAXPOTION, :FULLHEAL, :MAXREVIVE, :REVIVE].each do |item|
  138.   #   trainer.items.push(item)
  139.   # end
  140.   # foe_items.push(trainer.items)
  141.   trainer_array.push(trainer)
  142.  
  143.   # Generate party
  144.   valid_species = []
  145.   GameData::Species.each_species { |sp| valid_species.push(sp.species) }
  146.   Settings::MAX_PARTY_SIZE.times do |i|
  147.     this_species = valid_species.sample
  148.     this_level = 100   # rand(1, Settings::MAXIMUM_LEVEL)
  149.     pkmn = Pokemon.new(this_species, this_level, trainer, false)
  150.     # Set form for certain species
  151.     case pkmn.species
  152.     when :GRENINJA, :SLOWKING, :GEODUDE, :GRAVELER, :GOLEM, :PONYTA, :RAPIDASH,
  153.          :GRIMER, :MUK, :SLOWBRO, :RAICHU, :DIGLETT, :DUGTRIO, :STUNFISK
  154.       pkmn.form_simple = 1
  155.     when :DARMANITAN
  156.       pkmn.form_simple = 2
  157.     when :CALYREX
  158.       pkmn.form_simple = [1, 2].sample   # So we test both versions of As One
  159.     when :NECROZMA
  160.       pkmn.form_simple = 3   # Ultra form
  161.     end
  162.     # Generate moveset for pkmn (from level-up moves first, then from tutor
  163.     # moves + egg moves, then from all moves)
  164.     all_moves = pkmn.getMoveList.map { |m| m[1] }
  165.     all_moves.uniq!
  166.     if !$shown_all_moves_tested_message
  167.       all_moves.reject! { |m| $tested_moves[m] && $tested_moves[m] > AI_MOVE_TESTING_THRESHOLD }
  168.       if all_moves.length == 0
  169.         all_moves = pkmn.species_data.tutor_moves.clone + pkmn.species_data.get_egg_moves.clone
  170.         all_moves.reject! { |m| $tested_moves[m] && $tested_moves[m] > AI_MOVE_TESTING_THRESHOLD }
  171.         if all_moves.length == 0
  172.           all_moves = GameData::Move.keys.clone
  173.           all_moves.reject! { |m| $tested_moves[m] && $tested_moves[m] > AI_MOVE_TESTING_THRESHOLD }
  174.         end
  175.       end
  176.       if all_moves.length == 0 && !$shown_all_moves_tested_message
  177.         echoln "All moves have been tested at least #{AI_MOVE_TESTING_THRESHOLD} times!"
  178.         $shown_all_moves_tested_message = true
  179.       end
  180.     end
  181.     moves = all_moves.sample(4)
  182.     moves.each { |m| pkmn.learn_move(m) }
  183.     # Generate held item for pkmn (compatible Mega Stone first, then compatible
  184.     # signature item, then any item with a held effect)
  185.     all_items = []   # Find all compatible Mega Stones
  186.     GameData::Species.each do |sp|
  187.       next if sp.species != pkmn.species || sp.unmega_form != pkmn.form
  188.       all_items.push(sp.mega_stone) if sp.mega_stone
  189.     end
  190.     all_items.reject! { |i| $tested_items[i] && $tested_items[i] > AI_ITEM_TESTING_THRESHOLD }
  191.     if all_items.length > 0 && rand(100) < 50
  192.       pkmn.item = all_items.sample
  193.     elsif SIGNATURE_ITEMS.keys.include?(pkmn.species) && rand(100) < 75
  194.       all_items = SIGNATURE_ITEMS[pkmn.species].clone
  195.       if all_items.is_a?(Array)
  196.         all_items.reject! { |i| $tested_items[i] && $tested_items[i] > AI_ITEM_TESTING_THRESHOLD }
  197.         pkmn.item = all_items.sample if all_items.length > 0
  198.       else
  199.         pkmn.item = all_items if !$tested_items[all_items] || $tested_items[all_items] <= AI_ITEM_TESTING_THRESHOLD
  200.       end
  201.     end
  202.     if !pkmn.hasItem? && rand(100) < 75
  203.       all_items = ITEMS_WITH_HELD_EFFECTS.clone
  204.       all_items.reject! { |i| $tested_items[i] && $tested_items[i] > AI_ITEM_TESTING_THRESHOLD }
  205.       all_items = ITEMS_WITH_HELD_EFFECTS.clone if all_items.length == 0
  206.       pkmn.item = all_items.sample
  207.     end
  208.     # Generate ability for pkmn (any available to that species/form)
  209.     abil = pkmn.ability_id
  210.     if $tested_abilities[abil] && $tested_abilities[abil] > AI_ABILITY_TESTING_THRESHOLD
  211.       abils = pkmn.getAbilityList
  212.       abils.reject! { |a| $tested_abilities[a[0]] && $tested_abilities[a[0]] > AI_ABILITY_TESTING_THRESHOLD }
  213.       if abils.length > 0
  214.         pkmn.ability_index = abils.sample[1]
  215.       else
  216.         pkmn.ability = GameData::Ability.keys.sample
  217.       end
  218.     end
  219.     trainer.party.push(pkmn)
  220.     pokemon_array.push(pkmn)
  221.   end
  222.  
  223.   # Return values
  224.   return trainer_array, foe_items, pokemon_array, party_starts
  225. end
  226.  
  227. #===============================================================================
  228. #
  229. #===============================================================================
  230. def debug_test_auto_battle(logging = false, console_messages = true)
  231.   mar_load_tested_data_record
  232.  
  233.   old_internal = $INTERNAL
  234.   $INTERNAL = logging
  235.   if console_messages
  236.     echoln "Start of testing auto-battle."
  237.     echoln "" if !$INTERNAL
  238.   end
  239.   PBDebug.log("")
  240.   PBDebug.log("================================================================")
  241.   PBDebug.log("")
  242.   # Generate information for the foes
  243.   foe_trainers, foe_items, foe_party, foe_party_starts = debug_set_up_trainer
  244.   # Generate information for the player and partner trainer(s)
  245.   player_trainers, ally_items, player_party, player_party_starts = debug_set_up_trainer
  246.   # Log the combatants
  247.   echo_participant = lambda do |trainer, party, index|
  248.     trainer_txt = "[Trainer #{index}] #{trainer.full_name} [skill: #{trainer.skill_level}]"
  249.     ($INTERNAL) ? PBDebug.log_header(trainer_txt) : echoln(trainer_txt)
  250.     party.each do |pkmn|
  251.       pkmn_txt = "#{pkmn.name}, Lv.#{pkmn.level}"
  252.       pkmn_txt += " [Ability: #{pkmn.ability&.name || "---"}]"
  253.       pkmn_txt += " [Item: #{pkmn.item&.name || "---"}]"
  254.       ($INTERNAL) ? PBDebug.log(pkmn_txt) : echoln(pkmn_txt)
  255.       moves_msg = "    Moves: "
  256.       pkmn.moves.each_with_index do |move, i|
  257.         moves_msg += ", " if i > 0
  258.         moves_msg += move.name
  259.       end
  260.       ($INTERNAL) ? PBDebug.log(moves_msg) : echoln(moves_msg)
  261.     end
  262.   end
  263.   echo_participant.call(player_trainers[0], player_party, 1) if console_messages
  264.   PBDebug.log("")
  265.   if console_messages
  266.     echoln "" if !$INTERNAL
  267.     echo_participant.call(foe_trainers[0], foe_party, 2)
  268.     echoln "" if !$INTERNAL
  269.   end
  270.   # Create the battle scene (the visual side of it)
  271.   scene = Battle::DebugSceneNoVisuals.new(logging)
  272.   # Create the battle class (the mechanics side of it)
  273.   battle = Battle.new(scene, player_party, foe_party, player_trainers, foe_trainers)
  274.   battle.party1starts   = player_party_starts
  275.   battle.party2starts   = foe_party_starts
  276.   battle.ally_items     = ally_items
  277.   battle.items          = foe_items
  278.  
  279.   battle.debug          = true
  280.   battle.internalBattle = false
  281.   battle.controlPlayer  = true
  282.   # Set various other properties in the battle class
  283.   BattleCreationHelperMethods.prepare_battle(battle)
  284.   # Perform the battle itself
  285.   outcome = battle.pbStartBattle
  286.   # End
  287.   if console_messages
  288.     text = ["Undecided",
  289.             "Trainer 1 #{player_trainers[0].name} won",
  290.             "Trainer 2 #{foe_trainers[0].name} won",
  291.             "Ran/forfeited",
  292.             "Wild Pokémon caught",
  293.             "Draw"][outcome]
  294.     echoln sprintf("%s after %d rounds", text, battle.turnCount + 1)
  295.     echoln ""
  296.   end
  297.   $INTERNAL = old_internal
  298.  
  299.   mar_save_tested_data_record
  300. end
  301.  
  302. def mar_load_tested_data_record
  303.   if !$tested_moves
  304.     pbRgssOpen("tested_moves.dat", "rb") { |f| $tested_moves = Marshal.load(f) }
  305.   end
  306.   if !$tested_abilities
  307.     pbRgssOpen("tested_abilities.dat", "rb") { |f| $tested_abilities = Marshal.load(f) }
  308.   end
  309.   if !$tested_items
  310.     pbRgssOpen("tested_items.dat", "rb") { |f| $tested_items = Marshal.load(f) }
  311.   end
  312. end
  313.  
  314. def mar_save_tested_data_record
  315.   $tested_moves ||= {}
  316.   $tested_abilities ||= {}
  317.   $tested_items ||= {}
  318.   File.open("tested_moves.dat", "wb") { |f| Marshal.dump($tested_moves, f) }
  319.   File.open("tested_abilities.dat", "wb") { |f| Marshal.dump($tested_abilities, f) }
  320.   File.open("tested_items.dat", "wb") { |f| Marshal.dump($tested_items, f) }
  321. end
  322.  
  323. #===============================================================================
  324. # Add to Debug menu.
  325. #===============================================================================
  326. MenuHandlers.add(:debug_menu, :ai_testing_menu, {
  327.   "name"        => "AI Testing...",
  328.   "parent"      => :main,
  329.   "description" => "Functions that help to test the AI.",
  330.   "always_show" => false
  331. })
  332.  
  333. MenuHandlers.add(:debug_menu, :generate_test_data, {
  334.   "name"        => "Generate new test data",
  335.   "parent"      => :ai_testing_menu,
  336.   "description" => "Save current tested moves/abilities/items data. If none, generates it from scratch.",
  337.   "always_show" => false,
  338.   "effect"      => proc {
  339.     mar_save_tested_data_record
  340.   }
  341. })
  342.  
  343. MenuHandlers.add(:debug_menu, :test_auto_battle, {
  344.   "name"        => "Test Auto Battle",
  345.   "parent"      => :ai_testing_menu,
  346.   "description" => "Runs an AI-controlled battle with no visuals.",
  347.   "always_show" => false,
  348.   "effect"      => proc {
  349.     debug_test_auto_battle
  350.   }
  351. })
  352.  
  353. MenuHandlers.add(:debug_menu, :test_auto_battle_logging, {
  354.   "name"        => "Test Auto Battle with logging",
  355.   "parent"      => :ai_testing_menu,
  356.   "description" => "Runs an AI-controlled battle with no visuals. Logs messages.",
  357.   "always_show" => false,
  358.   "effect"      => proc {
  359.     debug_test_auto_battle(true)
  360.     pbMessage("Battle transcript was logged in Data/debuglog.txt.")
  361.   }
  362. })
  363.  
  364. MenuHandlers.add(:debug_menu, :bulk_test_auto_battle, {
  365.   "name"        => "Bulk test Auto Battle",
  366.   "parent"      => :ai_testing_menu,
  367.   "description" => "Runs 50 AI-controlled battles with no visuals.",
  368.   "always_show" => false,
  369.   "effect"      => proc {
  370.     echoln "Running 50 battles.."
  371.     50.times do |i|
  372.       echoln "#{i + 1}..."
  373.       debug_test_auto_battle(false, false)
  374.     end
  375.     echoln "Done!"
  376.   }
  377. })
  378.  
  379. #===============================================================================
  380. #
  381. #===============================================================================
  382. MenuHandlers.add(:debug_menu, :review_tested_data, {
  383.   "name"        => "Review tested moves/abilities/items",
  384.   "parent"      => :ai_testing_menu,
  385.   "description" => "List how much all moves/abilities/items have been tested.",
  386.   "always_show" => false,
  387.   "effect"      => proc {
  388.     mar_load_tested_data_record
  389.  
  390.     max_move_length = 0
  391.     GameData::Move.keys.each { |m| max_move_length = [m.to_s.length, max_move_length].max }
  392.     thresholded_moves = []
  393.     ($tested_moves || {}).each_pair do |move, count|
  394.       next if !count || count < AI_MOVE_TESTING_THRESHOLD
  395.       thresholded_moves.push([move, count])
  396.     end
  397.     thresholded_moves.sort! { |a, b| a[0].to_s <=> b[0].to_s }
  398.     remaining_moves = GameData::Move.keys.clone
  399.     thresholded_moves.each { |m| remaining_moves.delete(m[0]) }
  400.     remaining_moves.sort! { |a, b| a.to_s <=> b.to_s }
  401.  
  402.     File.open("tested moves summary.txt", "wb") do |f|
  403.       f.write(0xEF.chr)
  404.       f.write(0xBB.chr)
  405.       f.write(0xBF.chr)
  406.       f.write("================================================\r\n")
  407.       f.write("Met threshold of #{AI_MOVE_TESTING_THRESHOLD}: #{thresholded_moves.length}\r\n")
  408.       f.write("================================================\r\n")
  409.       thresholded_moves.each do |m|
  410.         f.write(m[0].to_s)
  411.         f.write(" " * (5 + max_move_length - m[0].to_s.length))
  412.         f.write(m[1].to_s)
  413.         f.write("\r\n")
  414.       end
  415.       f.write("\r\n")
  416.       f.write("\r\n")
  417.       f.write("\r\n")
  418.       f.write("================================================\r\n")
  419.       f.write("Remaining moves: #{remaining_moves.length}\r\n")
  420.       f.write("================================================\r\n")
  421.       remaining_moves.each do |m|
  422.         f.write(m.to_s)
  423.         if $tested_moves && $tested_moves[m]
  424.           f.write(" " * (5 + max_move_length - m.to_s.length))
  425.           f.write($tested_moves[m].to_s)
  426.         end
  427.         f.write("\r\n")
  428.       end
  429.     end
  430.     echoln "Moves: #{thresholded_moves.length} tested at least #{AI_MOVE_TESTING_THRESHOLD} times."
  431.     echoln "       #{remaining_moves.length} moves need more testing."
  432.  
  433.     #---------------------------------------------------------------------------
  434.  
  435.     max_ability_length = 0
  436.     GameData::Ability.keys.each { |a| max_ability_length = [a.to_s.length, max_ability_length].max }
  437.     thresholded_abilities = []
  438.     ($tested_abilities || {}).each_pair do |abil, count|
  439.       next if !count || count < AI_ABILITY_TESTING_THRESHOLD
  440.       thresholded_abilities.push([abil, count])
  441.     end
  442.     thresholded_abilities.sort! { |a, b| a[0].to_s <=> b[0].to_s }
  443.     remaining_abilities = GameData::Ability.keys.clone
  444.     thresholded_abilities.each { |a| remaining_abilities.delete(a[0]) }
  445.     remaining_abilities.sort! { |a, b| a.to_s <=> b.to_s }
  446.  
  447.     File.open("tested abilities summary.txt", "wb") do |f|
  448.       f.write(0xEF.chr)
  449.       f.write(0xBB.chr)
  450.       f.write(0xBF.chr)
  451.       f.write("================================================\r\n")
  452.       f.write("Met threshold of #{AI_ABILITY_TESTING_THRESHOLD}: #{thresholded_abilities.length}\r\n")
  453.       f.write("================================================\r\n")
  454.       thresholded_abilities.each do |a|
  455.         f.write(a[0].to_s)
  456.         f.write(" " * (5 + max_ability_length - a[0].to_s.length))
  457.         f.write(a[1].to_s)
  458.         f.write("\r\n")
  459.       end
  460.       f.write("\r\n")
  461.       f.write("\r\n")
  462.       f.write("\r\n")
  463.       f.write("================================================\r\n")
  464.       f.write("Remaining abilities: #{remaining_abilities.length}\r\n")
  465.       f.write("================================================\r\n")
  466.       remaining_abilities.each do |a|
  467.         f.write(a.to_s)
  468.         if $tested_abilities && $tested_abilities[a]
  469.           f.write(" " * (5 + max_ability_length - a.to_s.length))
  470.           f.write($tested_abilities[a].to_s)
  471.         end
  472.         f.write("\r\n")
  473.       end
  474.     end
  475.     echoln "Abilities: #{thresholded_abilities.length} tested at least #{AI_ABILITY_TESTING_THRESHOLD} times."
  476.     echoln "           #{remaining_abilities.length} abilities need more testing."
  477.  
  478.     #---------------------------------------------------------------------------
  479.  
  480.     max_item_length = 0
  481.     ITEMS_WITH_HELD_EFFECTS.each { |i| max_item_length = [i.to_s.length, max_item_length].max }
  482.     thresholded_items = []
  483.     ($tested_items || {}).each_pair do |item, count|
  484.       next if !count || count < AI_ITEM_TESTING_THRESHOLD
  485.       thresholded_items.push([item, count])
  486.     end
  487.     thresholded_items.sort! { |a, b| a[0].to_s <=> b[0].to_s }
  488.     remaining_items = ITEMS_WITH_HELD_EFFECTS.clone
  489.     remaining_items += MEGA_STONES.clone
  490.     SIGNATURE_ITEMS.each_pair do |species, items|
  491.       if items.is_a?(Array)
  492.         remaining_items += items
  493.       else
  494.         remaining_items.push(items)
  495.       end
  496.     end
  497.     remaining_items.uniq!
  498.     thresholded_items.each { |i| remaining_items.delete(i[0]) }
  499.     remaining_items.sort! { |a, b| a.to_s <=> b.to_s }
  500.  
  501.     File.open("tested items summary.txt", "wb") do |f|
  502.       f.write(0xEF.chr)
  503.       f.write(0xBB.chr)
  504.       f.write(0xBF.chr)
  505.       f.write("================================================\r\n")
  506.       f.write("Met threshold of #{AI_ITEM_TESTING_THRESHOLD}: #{thresholded_items.length}\r\n")
  507.       f.write("================================================\r\n")
  508.       thresholded_items.each do |i|
  509.         f.write(i[0].to_s)
  510.         f.write(" " * (5 + max_item_length - i[0].to_s.length))
  511.         f.write(i[1].to_s)
  512.         f.write("\r\n")
  513.       end
  514.       f.write("\r\n")
  515.       f.write("\r\n")
  516.       f.write("\r\n")
  517.       f.write("================================================\r\n")
  518.       f.write("Remaining items: #{remaining_items.length}\r\n")
  519.       f.write("================================================\r\n")
  520.       remaining_items.each do |i|
  521.         f.write(i.to_s)
  522.         if $tested_items && $tested_items[i]
  523.           f.write(" " * (5 + max_item_length - i.to_s.length))
  524.           f.write($tested_items[i].to_s)
  525.         end
  526.         f.write("\r\n")
  527.       end
  528.     end
  529.     echoln "Items: #{thresholded_items.length} tested at least #{AI_ITEM_TESTING_THRESHOLD} times."
  530.     echoln "       #{remaining_items.length} items need more testing."
  531.   }
  532. })
  533.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement