shithub: pokecrystal

Download patch

ref: 810e20cc048f3418205adca744dc79c3c59098bc
parent: e0eb31df734fd89b979b48e0e86793c8b54dbbf4
author: Bryan Bishop <[email protected]>
date: Sat May 19 09:57:19 EDT 2012

use report_unreferenced_trainer_ids to show which ids are probably valid but unused

--- a/extras/crystal.py
+++ b/extras/crystal.py
@@ -3387,9 +3387,9 @@
         trainer_id = self.params[2].byte
 
         if not trainer_group in trainer_group_maximums.keys():
-            trainer_group_maximums[trainer_group] = [trainer_id]
+            trainer_group_maximums[trainer_group] = set([trainer_id])
         else:
-            trainer_group_maximums[trainer_group].append(trainer_id)
+            trainer_group_maximums[trainer_group].add(trainer_id)
 
     def to_asm(self):
         xspacing = ""
@@ -3440,6 +3440,7 @@
     This can be used with trainer_group_maximums to figure out the current number of
     trainers in each of the originating trainer groups.
     """
+    total_unreferenced_trainers = 0
 
     # look at each possibly relevant script
     for item in script_parse_table.items():
@@ -3447,6 +3448,54 @@
         if isinstance(object, Script):
             check_script_has_trainer_data(object)
 
+    # make a set of each list of trainer ids to avoid dupes
+    # this will be used later in TrainerGroupTable
+    for item in trainer_group_maximums.items():
+        key = item[0]
+        value = set(item[1])
+        trainer_group_maximums[key] = value
+
+def report_unreferenced_trainer_ids():
+    """ Reports on the number of unreferenced trainer ids in each group.
+
+    This should be called after find_trainer_ids_from_scripts.
+
+    These are trainer groups with "unused" trainer ids. The
+    "find_trainer_ids_from_scripts" function analyzes each script in the game,
+    and each map header in the game (because of code in TrainerFragment), and
+    finds all references to trainers. But, if there are any trainers that are
+    referenced in raw ASM, this method does not detect them. Each instance of a
+    trainer reference is added to a global table called
+    "trainer_group_maximums". Next, "find_trainer_ids_from_scripts" looks at
+    the trainer IDs referenced for each group and takes the minimum number and
+    the maximum number. To find whether or not there are any unused trainers,
+    it takes the minimum and maximum ids and then sees which intermediate
+    numbers are missing from the list of "referenced" trainer ids.
+    """
+    for item in trainer_group_maximums.items():
+        key = item[0]
+        value = item[1]
+
+        # i'm curious: are there any missing trainer ids in this group?
+        min_id = min(value)
+        max_id = max(value)
+        expectables = range(min_id, max_id+1)
+
+        unreferenced = set()
+
+        for expectable in expectables:
+            if not expectable in value:
+                unreferenced.add(expectable)
+
+        if len(unreferenced) > 0:
+            total_unreferenced_trainers += len(unreferenced)
+            output = "trainer group "+hex(key)+" (\""+trainer_group_names[key]["name"]+"\")"
+            output += " (min="+str(min_id)+", max="+str(max_id)+")"
+            output += " has "+str(len(unreferenced))+" unreferenced trainer ids"
+            output += ": " + str(unreferenced)
+            print output
+    print "total unreferenced trainers: " + str(total_unreferenced_trainers)
+
 def check_script_has_trainer_data(script):
     """ see find_trainer_ids_from_scripts
     """
@@ -3463,9 +3512,9 @@
 
         if trainer_group != None and trainer_id != None:
             if trainer_group in trainer_group_maximums.keys():
-                trainer_group_maximums[trainer_group].append(trainer_id)
+                trainer_group_maximums[trainer_group].add(trainer_id)
             else:
-                trainer_group_maximums[trainer_group] = [trainer_id]
+                trainer_group_maximums[trainer_group] = set([trainer_id])
 
 def trainer_name_from_group(group_id, trainer_id=0):
     """ This doesn't actually work for trainer_id > 0."""
@@ -7572,7 +7621,7 @@
     find_trainer_ids_from_scripts()
 
     # and parse the main TrainerGroupTable once we know the max number of trainers
-    gtable = TrainerGroupTable()
+    #gtable = TrainerGroupTable()
 
 #just a helpful alias
 main=run_main