The broad problem: you have some objects that either are indistinguishable, interchangeable, or otherwise require some special handling to merge/combine/summarize action reports.
There are a number of easy half-solutions, this is an attempt to implement a more comprehensive solution. Specifically, here I’m presenting 1) a report manager framework for merging reports involving multiple related objects (as defined by their object type, i.e. a parent class), and 2) a framework for implementing “resource”-type objects—indistinguishable, interchangeable objects like coins or abstract resource-gathering resources (stone, wood, or whatever).
THE REPORT MANAGER
Basic usage is:
- Declare a
ReportManagerinstance.
EachReportManagerneeds to have areportManagerForproperty indicating the object or class it manages reports for. - Add
ReportSummaryinstances to theReportManager.
EachReportSummaryneeds to have a declaredactionit applies to and asummarize()method to construct the actual summary.
Thesummarize()method takes a single argument, aReportSummaryDatainstance, and returns a single-quoted string (the report summary text). - The
ReportSummaryDataincludes the properties:
veca vector containing the reports being summarized
objsa vector containing the (direct) objects in the reports
countthe integer number of objects being summarized
dobja “representative” object for the summary. By default this is the first object inobjs, butReportManager.getReportDobj()can be over-written to use a different object (including one that’s not in the reports at all, for example)
AN EXAMPLE
First, consider the gameworld:
class Pebble: Thing '(small) (round) pebble*pebbles' 'pebble'
"A small, round pebble. "
isEquivalent = true
;
startRoom: Room 'Void' "This is a featureless void.";
+me: Person;
++Pebble;
++Pebble;
+Pebble;
+Container '(wooden) box' 'box' "A wooden box. ";
++Pebble;
++Pebble;
++Pebble;
++Pebble;
+Pebble;
+Pebble;
+Thing '(ordinary) rock' 'rock' "An ordinary rock. ";
By default this gets us:
Void
This is a featureless void.
You see three pebbles, a box (which contains four pebbles), and a rock here.
>x all
your pebble: A small, round pebble.
your pebble: A small, round pebble.
the pebble on the floor: A small, round pebble.
box: A wooden box. It contains four pebbles.
the pebble in the box: A small, round pebble.
the pebble in the box: A small, round pebble.
the pebble in the box: A small, round pebble.
the pebble in the box: A small, round pebble.
the pebble on the floor: A small, round pebble.
the pebble on the floor: A small, round pebble.
rock: An ordinary rock.
>
Now we add:
pebbleReportManager: ReportManager
reportManagerFor = Pebble
;
+ReportSummary @ExamineAction
summarize(data) {
return('It\'s <<spellInt(data.count)>> small, round pebbles. ');
}
;
This gets us:
Void
This is a featureless void.
You see three pebbles, a box (which contains four pebbles), and a rock here.
>x all
box: A wooden box. It contains four pebbles.
rock: An ordinary rock.
your pebbles: It's two small, round pebbles.
pebbles on the floor: It's three small, round pebbles.
pebbles in the box: It's four small, round pebbles.
>
Note the wonky spacing around the container. That’s a TADS3/adv3 thing, not part of the report manager.
INTERCHANGEABLE OBJECTS
Everything above is just juggling the reports. This doesn’t fix things like commands with item counts and so on. That involves CollectiveGroup, listWith and so on. To make using all of that easier, here’s a “resource” model for intistinguishable/interchangeable objects.
The basic usage is simple:
- Declare a item type as a
Resourcesubclass - Declare a
ResourceFactoryfor the resource
In this case we re-define the pebble class:
class Pebble: Resource '(small) (round) pebble*pebbles' 'pebble'
"\^{A/Count resource} small, round {single/plural resource}. "
smellDesc = "\^{It/They resource} smell{s resource} like
{a/count resource} small, round {single/plural resource}. "
;
Note a couple of things here. One is that the desc uses a bunch of message parameter substitutions with the resource tag. These are specific to the resource module, and are:
singe/pluralbecomes the single or plural name of the resource depending on the number in the reportcountbecomes the spelled-out number of items in a resource reporta/countbecomes either “a” if there’s one in the report or the spelled out number (“two”, “twelve”, or whatever) if there’s more in the reportit/theybecomes “it” if there’s one, “they” if there’s more
We can use them directly (without having to declare any report summaries) because each Resource automagically gets a report manager and summary reports for each of the standard sense descriptions. So you can just declare desc, smellDesc, soundDesc, feelDesc, and tasteDesc and it’ll (hopefully) just work.
Continuing the example, the factory declaration is just:
pebbleFactory: ResourceFactory
resourceClass = Pebble
;
Then with the same gameworld used above, at preinit the ResourceFactory will take care of setting up all the CollectiveGroups and ListGroupEquivalents. That gets us:
Void
This is a featureless void.
You see a box (which contains two pebbles) and three pebbles here.
>i
You are carrying five pebbles and a rock.
>put 2 pebbles in the box
You put two pebbles in the box.
>x pebbles
pebbles in the box: Four small, round pebbles.
pebbles on the floor: Three small, round pebbles.
your pebbles: Three small, round pebbles.
If you want to define addtional report summaries for a Resource you can add them (via the +ReportSummary format) on the ResourceFactory declaration.
THE REPOS
The reportManager github repo.
The resources github repo.
I’ll probably bump with some discussion of the gotchas and dead ends I explored in hammering this out.
I’d also be surprised if this doesn’t require additional tweaking/bugfixes, because there are a lot of fiddly corner cases I’m sure I haven’t tested yet. So comments/bug reports welcome.