Multi-column access for tables is not part of the Standard Library.
It is possible to write an I6 routine (and accompanying I7 phrase) to enable this, but the catch is that there’s some special magic going on during compilation to keep track of whether or not a row in a table has been chosen at any given point in the code. If the compiler deems that the code is trying to access a row when no row has been chosen, a problem message results during compilation, such as:
Problem. You wrote 'say "[name entry] is [readiness entry] in bay [bay entry]."' : but no row seems to have been chosen at this point, so it doesn't make sense to talk about the entries within it...
The magic doesn’t recognize any added two-column version of the phrase as having chosen a row, so it’s necessary to first choose a row (using any method) to satisfy the compiler, then choose the row via the two-column method. Not great. (If anyone has any pointers on how to bypass this, I’d love to hear them. There doesn’t seem to even be any undocumented special template code to invoke to indicate a row has been chosen to the compiler – it just seems like something hardcoded as part of a validity check.)
EDIT: I belatedly realized that the ugliness of having to make a fake row choice can be wrapped up in the main phrase so that you don’t have to deal with it routinely as the author. The example has been modified accordingly.
EDIT 2: Oops. No, doing that doesn’t manage to fool the compiler; the row selection must occur within the same phrase as the entry access. I forgot to remove the fake row lookup in the when play begins
rule during the too-hurried testing of the new approach.
Here’s a (poorly) working example:
"Two Column Access"
Place is a room.
Status is a kind of value. The statuses are ready and not ready.
Table of StatusNameData
name readiness bay
"Alice" ready 2
"Bob" not ready 1
"Carl" ready 3
When play begins:
choose row 1 in the Table of StatusNameData; [fakes out compiler]
choose a row with a readiness of ready and a name of "Carl" in the Table of StatusNameData;
say "[name entry] is [readiness entry] in bay [bay entry]."
Include
(-
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! Tables.i6t: Table Row Corresponding (two-column access)
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
[ TwoColTableRowCorr tab col1 lu_val1 col2 lu_val2 cola1 cola2 i j f1 f2 v vf1 vf2;
if (col1 >= 100) col1=TableFindCol(tab, col1, true);
if (col2 >= 100) col2=TableFindCol(tab, col2, true);
if ((col1 == 0) || (col2 == 0)) rfalse;
cola1 = tab-->col1;
cola2 = tab-->col2;
j = TableRows(tab);
if (((tab-->col1)-->1) & TB_COLUMN_ALLOCATED) f1=1;
if (((tab-->col2)-->1) & TB_COLUMN_ALLOCATED) f2=1;
for (i=1:i<=j:i++) {
vf1 = false; vf2 = false;
if (f1) {
v = cola1-->(i+COL_HSIZE);
if ((~~((v == TABLE_NOVALUE) && (CheckTableEntryIsBlank(tab,col1,i)))) && (BlkValueCompare(v, lu_val1) == 0))
vf1 = true;
} else {
if ((~~((lu_val1 == TABLE_NOVALUE) && (CheckTableEntryIsBlank(tab,col1,i)))) && (cola1-->(i+COL_HSIZE) == lu_val1))
vf1 = true;
}
if (f2) {
v = cola2-->(i+COL_HSIZE);
if ((~~((v == TABLE_NOVALUE) && (CheckTableEntryIsBlank(tab,col2,i)))) && (BlkValueCompare(v, lu_val2) == 0))
vf2 = true;
} else {
if ((~~((lu_val2 == TABLE_NOVALUE) && (CheckTableEntryIsBlank(tab,col2,i)))) && (cola2-->(i+COL_HSIZE) == lu_val2))
vf2 = true;
}
if (vf1 && vf2) return i;
}
RunTimeProblem(RTP_TABLE_NOCORR, tab);
return false;
];
-) after "Table Row Corresponding" in "Tables.i6t".
To choose a/the/-- row with a/-- (C1 - K valued table column) of (V1 - value of kind K) and a/-- (C2 - L valued table column) of (V2 - value of kind L) in (TN - table name):
(- ct_0 = {TN}; ct_1 = TwoColTableRowCorr(ct_0, {C1}, {V1}, {C2}, {V2}); -).