Lookup & TABLE 6.08

From PCGen Wiki
Jump to: navigation, search


current as of Jan 20 2018

TABLE and COLUMN will be special types.  Both are complicated types, meaning they will look something like:

  TABLE[NUMBER]

or

  COLUMN[STRING]

The sub-format for TABLE is the format of the lookup (first) column of the table. The sub-format for COLUMN is the format of that column.

Note that a MODIFY doesn't look any different.  It's still:

  MODIFY:TABLENAME|SET|SomeTable

"SomeTable" is still a string to a naive reader, but what the system will do at that point is make sure that SomeTable can actually be interpreted as a TABLE[x]... rather than just treating it as a String.  Similar for the column names.

In that way, the sub variable will allow multiple tables to be swapped in, AS LONG AS they are the right format.  If the format is not compatible, then all bets are off and you'll get an error. 

Note that this still allows some runtime errors, but catches a lot of possible issues.  It is still possible to do a lookup on a Table that doesn't contain a specific column of the given name.  So if the third variable is COLUMN[NUMBER], we can check at load that the TABLEFORMAT has columns of FORMAT=NUMBER, but we can't guarantee the variable will resolve to a name actually in that table... that will have to wait for a runtime error.  That's life, but it does allow us to know the formats at load time, so we do get a lot of error checking in the context of the usage, if not the exact table and column names.


  STARTTABLE:Carrying Capacity,
  Strength,Capacity
  NUMBER,NUMBER
  1,10
  2,20
  ...
  29,1400
  ENDTABLE:Carrying Capacity,

Ignoring some of the diagnosis of bad inputs that will be necessary, this is the key logic: (1) This format of START and END allows more than one table per file (avoids sprawl) (2) Trailing commas are ignored (this allows the STARTTABLE and ENDTABLE lines to have blank cells where the rest are the table contents... we don't want to complain on minor things that may tools will do.) (3) Blank lines will be ignored.  This includes lines with commas but without content. (allows tables to be separated by blank lines or lines of all commas) (4) The column names (Strength,Capacity) are always the first line of the table.  The Formats are always the second line.  The rest of the lines are content of the table (5) Attempts to use embedded line breaks or embedded quotes may or may not be supported by the parsing system, but certainly aren't supported for purposes of PCGen. Optionally: (6) Lines that have the first cell starting with "#" are considered comment lines and will be ignored.  This will likely need to include if the first cell is escaped in quotes, just for protection from any tools that quote by default.

The dicestep then becomes more like:

  STARTTABLE:Dice Step,,,,,,,,,
  Dice,DOWN5,DOWN4,DOWN3,DOWN2,DOWN1,SELF,UP1,UP2,UP3,UP4,UP5,...
  DICE,DICE,DICE,DICE,DICE,DICE,DICE,DICE,DICE,DICE,DICE,DICE,...
  ...
  1d3,-,-,0,1,1d2,1d3,1d4,1d6,1d8,2d6,3d6,...
  ...
  ENDTABLE:Dice Step,,,,,,,,,

Note that "self" here is clearly defined, and it's a matter of pulling out of the correct column.  Since the CSV format ignores leading/trailing spaces, one can easily have a spaced out version that is a table in a text editor if folks don't want to edit in a spreadsheet.  (Having someone write a "PrettyTable" ... a trivial perl or python program to do that for the data team seems fairly easy)

I haven't fleshed it out, but there are some nuances here about what is "invalid" vs "empty" vs something else.  Lots of "-" used in various tables in rules and we'd need to decide what those mean so we don't just crash if it happens...


The second major issue is how to do the lookup in data.  We can borrow some inspiration from things like Excel and Google Docs:

  lookup(X,Y,Z)

X is a table.  This must resolve in the formula system to a valid table. For now, a get(...) function may be required. Y is the lookup value in the table.  It must match the format of the first column in the table. At this time, it does an EXACT match. Z is the target column.  This must resolve in the formula system to a valid table column. It must appear in the table named X

Thus max load calculation would be something like:

  lookup(get("TABLE[NUMBER]","Carrying Capacity"),roundDown(StrScore),get("COLUMN[NUMBER]","Capacity"))*SizeMult

In a formula - data controlled in a MODIFY. (This ignores the over 29 logic, as well as how SizeMult was initialized (presumably from the SIZE: object), but those are not difficult.)

To make the Dice Step example work, we would need something to find the correct column from the offset:

  STARTTABLE:Step Column,
  Steps,Name
  NUMBER,STRING
  -5,DOWN5
  -4,DOWN4
  ...
  0,SELF
  1,UP1
  ...
  ENDTABLE:Step Column,

The query would then look up the correct column name and use that column from Dice Step:

lookup(get("TABLE[NUMBER]","Dice Step"),BaseDamage,get("COLUMN[NUMBER]",lookup("Step Column",CurrentSize-BaseSize,"Name")))

There are potential future enhancements around things like range lookup (having it correctly deal with an input like 4.5 so the rounddown isn't necessary), but that is easy mechanics as part of the lookup function.


One neat item would be that we could alter the query above to extract the table name into the Global Modifier file:

  MODIFY:DiceStepTable|SET|"Dice Step"
  lookup(get("TABLE[NUMBER]",DiceStepTable),BaseDamage,get("COLUMN[NUMBER]",lookup("Step Column",CurrentSize-BaseSize,"Name")))

Now, if someone needs different dice steps for some reason... they can override the DiceStepTable variable and it will look up in a different table... so expansions could truly be expansions and not have to reach back into core PCC files in order to change key behaviors.

Another neat item is identical cast/known tables could be shared - the numbers would only need to be typed in once... :) ... since they are external to the Class file at that point... or if a subclass alters the default, just create a new table rather than having to BONUS/MODIFY all the numbers with adding and subtracting...

Additional Information on 'get()'

  get(<format>,<string representation>)

e.g.

  get("SKILL","Hide")
  get("TABLE[NUMBER]","Carrying")

etc.