Replacing a lib routine while being able to call original from replacement

I want to interfere with with the “(first taking the ___)” but only for certain objects: when a player tries to take a plant, they just get a sprig (a separate object) instead because I have a custom before::Take for the plant. However, if the player tries to “EAT PLANT”, it outputs a “(first taking the plant)” before my before::Eat or before::Take can prevent that.

I can fix this by turning off implicit actions in that room, which is ok. I suppose I could do it in a parse_name for the plant, by sneakily turning off implicit actions for that turn, but turning them back on at the end of a turn, but that feels dreadfully hacky.

It seems the best way might be to change ImplicitGrabIfNotHeld. This works great, but I don’t want to modify the library source. I can Replace that routine with one of my own, but it feels like a maintenance hassle to paste the body of the original routine into my source. I’d like my custom function to run first and still be able to call the original, from-library one if it’s not the plant.

I suspect this might be possible with the Replacedirective , but I can’t figure out how.

Any help or suggestions for a better way to fix this would be appreciated!

(I’m using PunyInform, btw)

Recent versions of the compiler (by which I mean 2014 onwards) have a new form of the Replace directive for exactly this situation:

Replace ImplicitGrabIfNotHeld OriginalImplicitGrab;

[ ImplicitGrabIfNotHeld arg1 arg2;
    Do_Stuff_Here();
    OriginalImplicitGrab(arg1, arg2);
    More_Stuff();
];
2 Likes

Thanks, @Draconis . I saw that in the notes, but I wasn’t able to figure out to to use it.

Here’s my code:

Replace ImplicitGrabIfNotHeld OriginalImplicitGrab;

! Replace ImplicitGrabIfNotHeld;

[ ImplicitGrabIfNotHeld arg1 arg2;
  print "MINE ", (object) arg1, arg2 == nothing, "^";
  if (arg1 ofclass Plant) { print "XXX"; rtrue; }
  return OriginalImplicitGrab(arg1, arg2);
];

When I use the one-argument Replace, it calls my replacement (once I comment out the call to OriginalImplicitGrab, of course).

When I tried using the new Replace X Y syntax, as above, it doesn’t call my function, and calls the library’s version. I can see that because it doesn’t print my debugging line in my version and it does print a debugging line I temporarily stuck in the original version.

Here’s a small-as-possible demonstration:

!% +../puny/lib
Constant INITIAL_LOCATION_VALUE = Room;

Include "globals.h";

Replace ImplicitGrabIfNotHeld OriginalImplicitGrab;

! Replace ImplicitGrabIfNotHeld;

[ ImplicitGrabIfNotHeld arg1 arg2;
    print "MINE ", (object) arg1, arg2 == nothing, "^";
    return OriginalImplicitGrab(arg1, arg2);
];

Include "puny.h";

Object Room "Room" has light;
Object -> Dinner "dinner" with name 'dinner' has edible;

[ Initialise ; ];

Are you putting your new definition before or after including the library? Replace X Y specifically means “make X refer to the latest-defined version, and Y refer to the earliest-defined version”.

1 Like

Thanks, @Draconis . Your questions prompted me to try a few other placements. The way that now works is to put the “Replace” statement before including the library, but put my replacement routine after including the library, a way I hadn’t tried.

This works:

!% +../puny/lib
Constant INITIAL_LOCATION_VALUE = Room;

Include “globals.h”;

Replace ImplicitGrabIfNotHeld OriginalImplicitGrab;

Include “puny.h”;

[ ImplicitGrabIfNotHeld arg1 arg2;
print "MINE ", (object) arg1, arg2 == nothing, “^”;
return OriginalImplicitGrab(arg1, arg2);
];

Object Room “Room” has light;
Object → Dinner “dinner” with name ‘dinner’ has edible;

[ Initialise ; ];
1 Like

I’m glad that worked! I admit the structuring of I6 files is still somewhat of a mystery to me.

(Also, to be clear, the arg1 arg2 stuff was a placeholder since I don’t know what arguments the original routine takes. I’ve never actually coded with PunyInform so I don’t know many of its routines.)

1 Like

The two-argument form of Replace is unintuitive at best. Sorry about that.

2 Likes