Inform - Support - Patches

About Patches  


DM4 Errata  

Issue L60802

TAKE ALL takes too much
Submitted by: Torbjörn Andersson     Appeared in: Library 6/8     Fixed in: Library 6/10

The TAKE ALL command is much more greedy in 6/8 than it ever was in 6/7. It will include every objects in every container in the room, including the player object. In 6/7, it would only include all objects in the player's environment.


The culprit seems to be in ReviseMulti() in Parserm.h. Towards the end of the function, it will determine which of the parsed objects TAKE ALL should include. 6/8 will do

  if (take_all_rule==2 || low>0)
  {   for (i=1, low=0:i<=multiple_object-->0:i++)
      {   if (ScopeCeiling(multiple_object-->i)==ScopeCeiling(actor))
          {   low++; multiple_object-->low = multiple_object-->i;
      multiple_object-->0 = low;

This loop appears in 6/7 as well, but the condition for keeping objects in the multiple_object array is simpler:

  {   if (parent(multiple_object-->i)==parent(actor))

Changing it back should give you the old behaviour, which might very well be sufficient. Another idea is to let it take all objects in scope, except for objects in your inventory, i.e. something like this:

  {   if (ScopeCeiling(multiple_object-->i)==ScopeCeiling(actor)
          && IndirectlyContains(actor,multiple_object-->i)==0)

But this re-introduces a slight misfeature. Consider the following case:

  You can see a box (in which are a fork and a spoon) here.

  box: Taken
  fork: Taken.
  spoon: Taken.

By the time TakeSub() is called, it's too late to stop it from taking the fork and spoon, because the parser will already have printed "fork: " and "spoon: ". I haven't really tested this enough, but something like this might work: Locate the part of Parserm.h where the actions are generated. It should be around line 3775, and part of the code reads:

  l = multiple_object-->k;
  print (name) l, ": ";

Before the call to PronounNotice(), insert the following:

  ! During "take all", an object has moved so that the
  ! object to take is now indirectly contained by the
  ! player. This should have produced a message (e.g.
  ! "sack: Taken.") so it should be safe to silently
  ! exclude these objects.
  if (action==##Take && take_all_rule==2
   && IndirectlyContains(player,l)) continue;

In the above example, "take all" will now take the box but leave the fork and spoon alone. Of course, I may have horribly broken other things without realizing. Use at your own risk.

Last updated 17 April 2013. This web site has not been fully supported since April 2008. Information may be out of date. This page was originally managed by Roger Firth.