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
ReportManager
instance.
EachReportManager
needs to have areportManagerFor
property indicating the object or class it manages reports for. - Add
ReportSummary
instances to theReportManager
.
EachReportSummary
needs to have a declaredaction
it applies to and asummarize()
method to construct the actual summary.
Thesummarize()
method takes a single argument, aReportSummaryData
instance, and returns a single-quoted string (the report summary text). - The
ReportSummaryData
includes the properties:
vec
a vector containing the reports being summarized
objs
a vector containing the (direct) objects in the reports
count
the integer number of objects being summarized
dobj
a “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
Resource
subclass - Declare a
ResourceFactory
for 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/plural
becomes the single or plural name of the resource depending on the number in the reportcount
becomes the spelled-out number of items in a resource reporta/count
becomes 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/they
becomes “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 CollectiveGroup
s and ListGroupEquivalent
s. 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.