Lookup Table
Now it's lookup(TABLE[x,y], x, COLUMN[y])
TABLE and COLUMN will be special types. Both are complicated types, meaning they will look something like:
- TABLE[NUMBER,STRING]
- or
- COLUMN[STRING]
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,y]... rather than just treating it as a String. Similar for the column names.
In that way, the first 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 a table that has formats like this:
- NUMBER,NUMBER,STRING
... will have multiple valid places it can be used, including:
- TABLE[NUMBER,NUMBER]
- TABLE[NUMBER,STRING]
This doesn't mean you can assign one TABLE format to another if the table happens to be compatible. I'm not even going to TRY to manage that one... and the use case is probably pretty narrow anyway.
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.
Tom
- 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 name. This must resolve in the formula system to a String that is a valid table name.
- Y is the lookup value in the table. It must match the format of the column in the table.
- Z is the target column name. This must resolve in the formula system to a String that is a valid table column name in the table named X
Thus max load calculation would be something like:
- lookup("Carrying Capacity",roundDown(StrScore),"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("Dice Step",BaseDamage,lookup("Step Column",CurrentSize-BaseSize,"Name"))
---
There are probably some nuances 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(DiceStepTable,BaseDamage,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...
SIDE COMMENT: This was regarding tables with no limits...
- [7:45 PM] Tom Parker: so the min one is fairly easy
- [7:45 PM] Tom Parker: if STR < 0, result is zero
- [7:45 PM] Tom Parker: that can be easily done with a MODIFY SET with a higher priority
- [7:45 PM] Tom Parker: the max one is trickier, but basically you can do something like:
- [7:46 PM] Tom Parker: mult = roundup ( (basestr - 29) % 10)
- [7:46 PM] Tom Parker: lookup then uses -> basestr - (mult * 10)