Sunday, 22 April 2012

Group Contents

In the last post, I used the field name detail$ rather than description$ because it would have another purpose.

This purpose is the group contents, a list of which objects are members of the groups defined in the data file.
tool,-1:stone axe
resource,-2:tree,stone
device,-3
job,-4
process,-5
storage,-6
tree,7:Home to Birds and Monkeys
stone,8:Small hard piece of planet
stone axe,9:Primative chopping device
log,10:Rough tree part, might burn well
kindling,11:Basis of a good fire
spark,12:Warning - fire Hazard
flame,13:Fire's younger sibling
fire,14:Good source of heat and light
Again the colon is used to separate the list, which is a string of names separated by more commas.  These names must match exactly the names for the objects.

Initially we don't have much in our groups, but it is enough to start with and use for testing the routine.

Group memberships can't be assigned like the other fields and will require another loop after the array has been filled with objects.

For example, when processing the data for the "Tool" object (which is a group), the object listed as a member, "stone axe", has not yet been converted to the array, so the program doesn't know it exists yet.

This is not a problem, since we are already putting the string after the colon into the details field in it's source or "raw" form.

The membership pass will simply convert the "raw" string names stored in the detail$ field to the Base96 code which represents the object.

Yes, this is where the Base96 routines we did a long time ago, will come into play.

Once the convert for/next loop has finished, the membership routine starts a new for/next loop. The routine works in a number of nested structures.
// Group Memberships
for i=1 to topObject()
   if ObjectIsGroup( i ) > 0 and ObjectDetail( i ) <> ""
      thisString$ = ObjectDetail( i )
      thisLen = len( thisString$ )
      thisStart = 1
      while thisStart < thisLen

      endwhile
   endif
next i
Here's a brief rundown of these outer loops structures;
  • It does a full pass of the array using the for/next loop.
  • It then checks if the object is a group with members using the if condition.
  • It retrieves the raw string from the array and stores it in a local variable.
  • It retrieves the length of that string and stores this in a local variable.
  • It sets a start point of 1 using a local variable.
  • It then enters a while/endwhile loop.
I have outlined the outer structure this way as everything here should be familiar by now and so I can concentrate on the main part of the routine, which is inside the while/endwhile block.

I want to first cover, what it is we are going to do, using an example, this will be for the group resource.
resource,-2:tree,stone
Above is the data in the file.  When it gets to this routine, the files are set as follows.
  • name$ contains "resource"
  • detail$ contains "tree,stone"
  • icon contains 2
  • isGroup contains 1
When the program gets to the while/endwhile loop, it has the following local variables.
  • thisString contains "tree,stone"
  • thisLen contains 10
  • thisStart contains 1
So the while condition is met ( 1 is less than 10 ) and so it enters the block.
thisComma = FindSubString( thisString$ , "," , thisStart )
This looks for a comma, starting at the position in thisStart ( 1 ) storing the result ( 5 ) in thisComma.
if thisComma = 0 then thisComma = thisLen + 1
If no comma was found, then use the length of the string plus 1. In our case, a comma was found so this is not done and thisComma stays at 5.
thisObject$ = mid( thisString$ , thisStart , thisComma - thisStart )
This retrieves the portion of the string from the position in thisStart to the position before the comma.

Since the mid() command requires a start and a length, and we have a start and an end, we do a bit of maths to work the length out.

thisComma - thisStart = 5 - 1  = 4

So thisObject$ contains part of the string from position 1, length 4 which is "tree".

I'm going to leave the encode part for now, so you can follow the next step of this loop.  Just insert the comment line.
// Convert to Base96
And I'll pick this up next time.

The last instruction in the while/endwhile loop is.
thisStart = thisComma + 1
Which moves the start position ready for the next object.  thisStart becomes 6.

In the second pass of the loop, it does the search from position 6, but won't find the comma, so thisComma becomes thisLen + 1 or 11.

When it extracts the string, this time it uses.

thisComma - thisStart = 11 - 6  = 5

So it starts from position 6 and uses length 5, thisObject$ becomes "stone".

After the next encode bit, it sets thisStart to thisComma + 1, so it becomes 12.

Since 12 is greater than 10, it exits the while/endwhile loop.

The full loop structure now looks like this.
// Group Memberships
for i=1 to topObject()
   if ObjectIsGroup( i ) > 0 and ObjectDetail( i ) <> ""
      thisString$ = ObjectDetail( i )
      thisLen = len( thisString$ )
      thisStart = 1
      while thisStart < thisLen
         thisComma = FindSubString( thisString$ , "," , thisStart )
         if thisComma = 0 then thisComma = thisLen + 1
         thisObject$ = mid( thisString$ , thisStart , thisComma - thisStart + 1 )
         // convert to base96
         thisStart = thisComma + 1
      endwhile
   endif
next i
Next we will do the conversion to Base96, which will round off Week 2.

No comments:

Post a Comment