intfiction.org

The Interactive Fiction Community Forum
It is currently Sun May 19, 2013 8:34 pm

All times are UTC - 6 hours [ DST ]




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Wed May 04, 2011 9:47 pm 
Offline

Joined: Sun Jan 30, 2011 10:20 pm
Posts: 32
Hi again.

I’m trying to stick as much repetitive code as possible into custom classes, but I hit a snag as to how to, or whether it is possible, to make small modifications to relatively long objects. I know how to use Inherited() to add something to the end of a pre-existing method, but not how to mess with chunks from the middle.

For instance, here is Slime’s behaviour, represented by the agenda item slimeAttackAgenda:
Code:
+slimeAttackAgenda: AgendaItem
    isReady = (inherited() && player.location == slime.location)
    initiallyActive = true
    invokeItem()
    {
        local roll = rand(100);
        if (roll >= 50)
            "The Slime stares blankly and loses its turn. ";
        else
        {
            local roll = rand(100);
            local hitChance = 100 - player.SPD;
            if (hitChance >= roll)
            {
                "The Slime charges at you! ";
                player.LoseHP(slime.ATK);
            }
            else
                "The Slime charges at you, but its attack missed! ";
        }
    }
;


Suppose I want a lot of this to work much the same for other monsters, more or less like this:

Code:
class MonsterAttackAgenda: AgendaItem
    isReady = (inherited() && player.location == slime.location)
    initiallyActive = true
    invokeItem()
    {
        local roll = rand(100);
        local hitChance = 100 - player.SPD;
        if (hitChance >= roll)
        {
            "Monster attacks you message. ";
            player.LoseHP(slime.ATK);
        }
        else
            "Monster missed message. ";
    }
;


This would be generic monster behaviour. From here, I would want to customize the two double quoted strings for each monster, as well as the “slime” in
Code:
player.LoseHP(slime.ATK);

since I would need to change that to point to each respective monster, else all of them would be using slime’s ATK property to calculate damage.

Additionally Slime has another random 50/50 chance of just staring blankly and doing nothing instead of following with all the hitChance and attack behaviour. That’s there just as a placeholder for some other customized behaviour I might want to implement.

Basically, the point of this exercise is that I want to keep a block of code in a class definition and freely mess with chunks of the content on individual instances. Is this doable?


Top
 Profile Send private message  
 
PostPosted: Wed May 04, 2011 11:57 pm 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
You have the right idea. The trick is to keep the core logic the same for all members of the class, and limit the differences to properties that can be easily modified.

Mostly this means factoring out any strings, and being careful with the way you reference properties.

Code:
class MonsterAttackAgenda: AgendaItem
   isReady = (inherited() && gPlayerChar.location == owner.location)
   initiallyActive = true
   invokeItem()
   {
      local roll = rand(100);
      local hitChance = 100 - gPlayerChar.SPD;
      if (hitChance >= roll)
      {
         hitMsg();
         gPlayerChar.LoseHP(owner.ATK);
      }
      else
         missMsg();
   }

   hitMsg  { "The <<owner.name>> charges at you! "; }
   missMsg { "The <<owner.name>> charges at you, but its attack missed! "; }
   owner = location
;

yellowSlime: Monster 'yellow slime' 'YELLOW SLIME' @Redroom
   ATK = 100
   SPD = 100
;

+ MonsterAttackAgenda
   invokeItem()
   {
      local roll = rand(100);
      if (roll < dazeChance)
         dazeMsg();
      else
         inherited();
   }

   dazeChance = 50
   dazeMsg { "The <<owner.name>> stares blankly and loses its turn. "; }
;

purpleSlime: Monster 'purple slime' 'PURPLE SLIME' @Redroom
   ATK = 1000
   SPD = 100
;

+ MonsterAttackAgenda   
   hitMsg  { "The <<owner.name>> slimes you! "; }
   missMsg { "The <<owner.name>> quivers with rage! "; }
;


Top
 Profile Send private message  
 
PostPosted: Sat May 07, 2011 8:18 pm 
Offline

Joined: Sun Jan 30, 2011 10:20 pm
Posts: 32
That worked. I ended up fragmenting the more of the processes into methods so that I could override them individually if necessary or just have inherited() let it all carry as default.

I have a question that has absolutely nothing to do with this but doesn't really warrant a new thread: how do I override a preCond in an item? thing.t tells me this can be overriden on an individual basis but doesn't bother to tell me how, and simply leaving it off from the custom dobjFor(Drink) doesn't seem to do it. For instance, I made a fountain and set everything up to be able to drink from it, but I can't seem to get rid of the preCond = [objHeld] check, which of course always fails since the object is a Fixture.

Code:
+fountain: Fixture 'water/fountain/pool' 'Water fountain'
    "A fountain. "
    dobjFor(Drink)
    {
        verify() {}
        action()
        {
            "You took a sip" ;
        }
    }
;


Top
 Profile Send private message  
 
PostPosted: Sun May 08, 2011 12:06 am 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
You override the list of PreCondition objects with an empty list.

Code:
preCond = []


That should do the trick.


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

All times are UTC - 6 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 2 guests


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