intfiction.org

The Interactive Fiction Community Forum
It is currently Wed May 22, 2013 11:19 pm

All times are UTC - 6 hours [ DST ]




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Mon May 02, 2011 6:50 pm 
Offline

Joined: Thu Oct 07, 2010 3:10 pm
Posts: 19
I have been trying to code a global remapping such that a command of the form KISS X becomes GIVE KISS TO X. This is what I have so far:

Code:
kissToGiveKissTo: GlobalRemapping
    getRemapping(issuingActor, targetActor, action)
    {
        if (action.ofKind(KissAction))
        {
            local newAction = GiveToAction.createActionInstance();
            newAction.setOriginalAction(action);
            local dobj = 'kiss';
            local iobj = action.dobjMatch;
            newAction.setObjectMatches(dobj, iobj);
            return [targetActor, newAction];
        }
        return nil;
    }
;

I already have a kiss object that allows commands of the form GIVE KISS TO X to work. The string 'kiss' obviously needs to be replaced (it is just a placeholder here), but even after reading "Global Command Remapping" in the Technical Manual and "GrammarProd" in the System Manual I don't know what a viable substitution would be. PreResolvedProd is not an option here, because the kiss object is not directly used in an action (I have instead made it an object in the inventory of an off-stage actor from which other actors inherit). So what do I do? Also, this is the first time I have attempted global remapping, so any other suggested improvements would be appreciated.


Top
 Profile Send private message  
 
PostPosted: Tue May 03, 2011 12:28 am 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
Remapping any command to GiveTo seems to cause a nil reference error. I can get this code to work:

Rant: show
Code:
kissToGiveKissTo: GlobalRemapping
   getRemapping(issuingActor, targetActor, action)
   {
      if (action.ofKind(KissAction))
      {
         local newAction = LockWithAction.createActionInstance();
         newAction.setOriginalAction(action);
         local dobj = new PreResolvedProd(kiss);
         local iobj = action.dobjMatch;
         newAction.setObjectMatches(dobj,iobj);

         if (!(iobj.length() == 0))
            return [issuingActor, newAction];
      }
      
      return nil;
   }
;


But if I change the newAction instance to GiveToAction, it fails.

Could you use the more straightforward approach of replacing the action during resolution?

Rant: show
Code:
kiss: Thing 'kiss' 'KISS'
   "A kiss! "
;

modify Thing
   dobjFor(Kiss)
   {
      check()
      {
         replaceAction(GiveTo, kiss, self);
      }
   }
;


Top
 Profile Send private message  
 
PostPosted: Tue May 03, 2011 2:03 am 
Offline

Joined: Thu Oct 07, 2010 3:10 pm
Posts: 19
Thank you for the help.

bcressey wrote:
Could you use the more straightforward approach of replacing the action during resolution?

I had somehow forgotten about replaceAction(). This works well. It does not seem to matter that the kiss object is in the inventory of the object from which the actor inherits. The only problem for my purposes is that while commands of the form X, GIVE ME A KISS are remapped to ASK X FOR A KISS, commands of the form X, KISS ME are not. If nothing else works, there is always StringPreParser, but I was hoping for something a little more elegant.


Top
 Profile Send private message  
 
PostPosted: Tue May 03, 2011 4:16 pm 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
OK, I figured out why GlobalRemapping caused a nil error. It's because the kiss remap succeeds, but then transitions into the giveMeToAskFor remapping which fails for complicated reasons that I don't fully understand. The fix I came up with was to track whether or not the GiveTo action being considered was already the result of a remapping, and if so to avoid a second remapping.

Rant: show
Code:
kissToGiveKissTo: GlobalRemapping
   getRemapping(issuingActor, targetActor, action)
   {
      if (action.ofKind(KissAction))
      {
         local newAction = GiveToAction.createActionInstance();
         newAction.setOriginalAction(action);
         newAction.setRemapped();
         local dobj = new PreResolvedProd(kiss);
         local iobj = action.dobjMatch;
         newAction.setObjectMatches(dobj,iobj);
         return [targetActor, newAction];
      }
      
      return nil;
   }
;

modify giveMeToAskFor
   getRemapping(issuingActor, targetActor, action)
   {
      if (!(action.isRemapped()))
         return inherited(issuingActor, targetActor, action);
      else
         return nil;
   }
;

modify GiveToAction
   isRemapped() { return remapped_ != nil; }
   setRemapped() { remapped_ = true; }
   remapped_ = nil
;


This will remap all commands in the >KISS X form to the equivalent >GIVE KISS TO X form.

I'm not entirely sure if you want any remapping from >GIVE KISS TO X to >ASK X FOR KISS, however. That's a little more difficult to accomplish, because it only holds when X is an actor and the kiss has to be transformed into a topic. I have a partial start on this but will happily abandon it unless it's something you need.


Top
 Profile Send private message  
 
PostPosted: Tue May 03, 2011 5:00 pm 
Offline

Joined: Thu Oct 07, 2010 3:10 pm
Posts: 19
This resolves the problem wonderfully. I would still like to remap orders to commands of the form ASK X FOR KISS, if at all possible. But this certainly gets me past the obstacle I had kept running into. Thank you.


Top
 Profile Send private message  
 
PostPosted: Tue May 03, 2011 6:12 pm 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
Here's a version that will remap >KISS X to >ASK X FOR KISS, when X is an Actor. Commands in the form >X, KISS Y will be likewise transformed into >X, ASK Y FOR KISS.

Code:
kissToGiveKissTo: GlobalRemapping
   getRemapping(issuingActor, targetActor, action)
   {
      if (action.ofKind(KissAction))
      {
         local dobjActor = nil;
         local obj = firstObj();
         while (obj != nil)
         {
            if (obj.ofKind(Actor) && action.canDobjResolveTo(obj))
               dobjActor = true;
            obj = nextObj(obj);
         }

         local newAction, dobj, iobj;

         if (!dobjActor)
         {
            newAction = GiveToAction.createActionInstance();
            dobj = new PreResolvedProd(kiss);
            iobj = action.dobjMatch;
         }
         else
         {
            newAction = AskForAction.createActionInstance();
            dobj = action.dobjMatch;
            iobj = new ResolveInfo(kiss, 0);
         }
         
         newAction.setOriginalAction(action);
         newAction.setRemapped();
         newAction.setObjectMatches(dobj,iobj);
         return [targetActor, newAction];
      }
      
      return nil;
   }
;

modify giveMeToAskFor
   getRemapping(issuingActor, targetActor, action)
   {
      if (!(action.isRemapped()))
         return inherited(issuingActor, targetActor, action);
      else
         return nil;
   }
;

modify TAction
   isRemapped() { return remapped_ != nil; }
   setRemapped() { remapped_ = true; }
   remapped_ = nil
;


It's a bit clunky in performance terms because it has to iterate through every object in the game, check whether that object is an actor, and then check whether that actor could resolve as the direct object.

Transcript with results.

Rant: show
Quote:
> kiss me
Talking to yourself won’t accomplish anything.

> slime, kiss me
You do not respond.

> slime, ask me for a kiss
You do not respond.

> kiss slime
The RED SLIME does not respond.

> slime, give me a kiss
The RED SLIME does not respond.

> ask slime for a kiss
The RED SLIME does not respond.

> kiss widget
You cannot give anything to a WIDGET.

> slime, kiss widget
The RED SLIME cannot give anything to a WIDGET.


Top
 Profile Send private message  
 
PostPosted: Tue May 03, 2011 7:43 pm 
Offline

Joined: Thu Oct 07, 2010 3:10 pm
Posts: 19
This code worked pretty well, but it still did not transform commands in the form X, KISS ME into commands of the form ASK X FOR KISS. However, thanks to your code (especially your use of ResolveInfo(), which I was not familiar with), I was able to write this:

Rant: show
Code:
kissToGiveKissTo: GlobalRemapping
   getRemapping(issuingActor, targetActor, action)
   {
      if (action.ofKind(KissAction))
      {
         local newAction, dobj, iobj;
         if (action.canDobjResolveTo(issuingActor))
         {
            newAction = AskForAction.createActionInstance();
            newAction.setOriginalAction(action);
            newAction.setPronounOverride(PronounYou, targetActor);
            dobj = new PreResolvedProd(targetActor);
            iobj = new ResolveInfo(kiss, 0);
            newAction.setObjectMatches(dobj, iobj);
            return [issuingActor, newAction];
         }
         else
         {
            newAction = GiveToAction.createActionInstance();
            newAction.setOriginalAction(action);
            newAction.setRemapped();
            dobj = new PreResolvedProd(kiss);
            iobj = action.dobjMatch;
            newAction.setObjectMatches(dobj, iobj);
            return [targetActor, newAction];
         }
      }
      return nil;
   }
;


When I use this code, I get the responses I want from my NPC and no undesirable behavior (so far as I have seen).

Thank you so much! Without your help I would still be stuck in front of a number of obstacles.


Top
 Profile Send private message  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 6 hours [ DST ]


Who is online

Users browsing this forum: Google [Bot] and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group