FAQ Search Memberlist Usergroups
Jolt Country Forum Index
Register Profile Log in to check your private messages Log in
Log in Log in

Quick Code Samples

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Jolt Country Forum Index -> Hugo's House of Horrors
View previous topic :: View next topic  
Author Message
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Wed Jan 09, 2013 1:08 am    Post subject: Quick Code Samples Reply with quote

This is a new thread for code on how to do simple things that are not worthy of their own thread. Some of this will eventually end up on Hugo By Example, but I thought it'd be good to share it here first.
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Wed Jan 09, 2013 1:16 am    Post subject: Reply with quote

Anchorhead-style Object-Grabbing:

Somebody on the ifMUD the other day was reminiscing about how Anchorhead did this thing where if you take an object that hasn't been examined yet, you automatically examine it as you take it. She thought this was a neat effect.

I can see how it might be appealing, although I have to admit that I was more intrigued by the coding challenge. Here's what I came up with:

Code:
! I declare the attribute this way so the author has the option of declaring it
! earlier and aliasing it to something like "special" (if it isn't being used
! for anything)

#if undefined examined
attribute examined
#endif

player_character you "you"
{
   react_after
   {
      if verbroutine = &DoLook and object and word[1] ~= "undo"
      {
         if object is not examined
            object is examined
      }
      return false
   }
}

replace NewVMessages(r, num, a, b)
{
        select r

   case &DoGet
   {
      select num
      case 8
      {
         if object is not examined
         {
            print "You pick up "; The(object);".";
            if &object.long_desc
            {
               print " ";
               run object.long_desc
               object is examined
            }
            else
               ""
         }
         else
            print "Taken."
      }
      case else : return false
   }

        case else : return false

       return true ! this line is only reached if we replaced something
}


The weirdest thing about the code above is that I found out that after a successful UNDO, the verbroutine global is set to the verb being undone, which is why in the player.react_before property, I had to check to make sure word[1] wasn't "undo".

I'm thinking that in future releases of Roodylib, I'll have DoUndo clear verbroutine after a successful undo. We'll see.
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Wed Jan 09, 2013 1:27 am    Post subject: Reply with quote

Phoenix-style no-description games:

On the other end of the spectrum, there were the Phoenix mainframe games, which completely forsook the concept of object-examination. If anything important was to be known about an object, it'd be listed in its name or short_desc.

Being used to Infocom games, it takes a little bit to get used to these games, but I've found that the style does not always come at the cost of story and immersion. I'm interested in writing at least one new game in this style.

Here's the code:
Code:
! grammar before "verblib.g" is included
verb "look", "l", "examine", "x", "watch"
   *                                                       DoLookAround
   * "around"                  DoLookAround
   * "in"/"inside" (PhoenixRules)                               DoLookIn
   * "on" (PhoenixRules)                                       DoLookIn
   * "at"/"to" (PhoenixRules)                                    DoLook
   * "out"/"through" (PhoenixRules)                                DoLookThrough
   * "under"/"underneath"/"beneath"/"below" (PhoenixRules)       DoLookUnder
   * "beside"/"behind"/"around" (PhoenixRules)                    DoLookUnder
   * (PhoenixRules)                                               DoLook


! . . .

routine PhoenixRules
{
   "You don't need to examine or look around anything in this game."
}

Using the routine-as-grammar-token method makes it so the command is understood yet no turn passes when the player accidentally tries to look at something.


Last edited by Roody_Yogurt on Wed Jan 09, 2013 6:07 pm; edited 1 time in total
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Wed Jan 09, 2013 2:49 am    Post subject: Reply with quote

Oops, forgot I had another code sample all ready:

Skipping picking up for DoPutIn:

Now, normally, DoPutIn requires that the object be held. With the checkheld system, it'll automatically pick up a unheld object first which works great almost all of the time.

Still, there might be instances where there is some kind of object manipulation where you don't want to let it seem like the object was picked up or possibly you just want to save the player the extra turn.

Here is some code for that:
Code:
! before "verblib.g" is included
#set USE_CHECKHELD


! Then, code the special DoPutIn objects like this:
object coin "coin"
{
   noun "coin"
   article "a"
   in STARTLOCATION
   before
   {
      object DoPutIn_CheckHeld
      {
         if xobject = fountain
         {
            Perform(&DoPutIn, self, xobject)
         }
         else
            return false
      }
   }
}


There are still ways code like that could get you into trouble, though, so be careful with how you use it.


Last edited by Roody_Yogurt on Wed Jan 09, 2013 6:08 pm; edited 1 time in total
Back to top
View user's profile Send private message AIM Address
Tdarcos



Joined: 16 May 2008
Posts: 4441
Location: University Park, Maryland

PostPosted: Wed Jan 09, 2013 4:19 am    Post subject: Context switch Reply with quote

Fast Context Switch

I saw this one once in a game where you were playing against another player, and it was used for a context switch, to switch from one player to the next.

If you have two items where you need to fast switch between the one being used and the other one, this is the best way I've ever seen to do it.

Let's say you have Item[1] and Item[2], so you can just use this

Code:

    TheItem = 1  ! Start with this one
   
    Item[ TheItem ].Visited = True

! Here's the switch:

    TheItem = 3 - TheItem   


That's all of it. You take the count of the sum of both and subtract the current value from that. It works for any two different numbers. If you have 0 and 1, then 1 - item will switch 1 to 0 and 0 to 1. In this case, 3 - theitem switches 2 to 1 and 1 to 2.

Slickest thing I've ever seen.
_________________
The lessons of history teach us - if they teach us anything - that no one learns the lessons of history.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Ice Cream Jonsey



Joined: 27 Apr 2002
Posts: 20088
Location: Colorado

PostPosted: Wed Jan 09, 2013 8:06 am    Post subject: Reply with quote

That Anchorhead thing where you take and examine is great. I wish all my games now had that now!

Part of me wants to open every last Hugo game I've made, write some automated tests and start putting things like that in, and support in each game for the YouCanGo extension (for non Hugo-programmers, that is the one where you get directions on where you can go, if you try to go in a direction you can't).

Also, knowing what I know about proportional fonts, I could make the Health and Ree counters in Fallacy of Dawn line up perfectly. I don't have OCD but the method I used does bug me, with one bar just a bit longer than the other, when they are both full.

One one hand, I'm a big fan of completing a project and being through with it.

On the other, man, we've all done so much cool stuff since then. I could make every graphic in A Crimson Spring better. I could use the music engine I put together for it, so it doesn't do that awkward, "Enter a room, get a new song" thing.

Maybe after I finish Cyberganked I'll do that. Just give a 10 year refresh on all the old games.
_________________
the dark and gritty...Ice Cream Jonsey!
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Wed Jan 09, 2013 2:26 pm    Post subject: Reply with quote

Ice Cream Jonsey wrote:
One one hand, I'm a big fan of completing a project and being through with it.


It's weird because, logically, I think the IF Archive is meant to be continuously updated, but on the other hand, uploading something there kind of feels like laying down cement; you really don't want to disturb the foundation unless there are some serious problems.

Other than having a cool old date next to your game in the archive listing ("Oh yeah, THAT's what I did in 1999!"), I think that probably overall, updates are better. I admit that one feels oddly crummy about it, though.

Ice Cream Jonsey wrote:
Maybe after I finish Cyberganked I'll do that. Just give a 10 year refresh on all the old games.


I think that's a good idea.


Also, as far as Tdarcos' contribution to this thread goes, let us point out that his code would not actually work. "visited" is an attribute and cannot be used as a property like he does there. Still, I guess it could be used for a property that can be one of two values. If the two values are 0 and 1, though, you could also just do this:
Code:
x = not x
Back to top
View user's profile Send private message AIM Address
loafingcoyote



Joined: 04 Jan 2012
Posts: 89
Location: Texas

PostPosted: Wed Jan 09, 2013 7:15 pm    Post subject: Reply with quote

Roody_Yogurt wrote:

It's weird because, logically, I think the IF Archive is meant to be continuously updated, but on the other hand, uploading something there kind of feels like laying down cement; you really don't want to disturb the foundation unless there are some serious problems.


This is an issue I've been meaning to discuss for awhile now.

Right after "The Hugo Clock" was uploaded to the archive I noticed an awful bug, but didn't want to immediately update it, since I didn't want to be a nuisance to the archive maintainers. I was thinking that, you know, those guys have lives too and I'm sure they don't want to spend all their time re-uploading my stuff.

After some time had passed, however, I had moved on to other projects and lost the desire to work on it. My question is, how many updates within what span of time is reasonable? Is uploading stuff to the archive a burden for the maintainers or not? It would help me to know one way or the other, because I agree that works in the archive should be updated. I'm just not sure how often is too often.

-lc
Back to top
View user's profile Send private message
Ice Cream Jonsey



Joined: 27 Apr 2002
Posts: 20088
Location: Colorado

PostPosted: Wed Jan 09, 2013 7:54 pm    Post subject: Reply with quote

I've never felt that it was possible to annoy the IF Archive updaters. I think they probably go after the upload directory every few days, so if you really had a bunch of submissions, they'd just take the latest one.
_________________
the dark and gritty...Ice Cream Jonsey!
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
DavidK
Guest





PostPosted: Thu Jan 10, 2013 12:34 am    Post subject: Reply with quote

(I'm one of the Archive maintainers: Jonathan Blask asked me to comment.)

As ICJ says, generally the uploads get looked at every few days, so if there's a bunch of versions of the same thing, I'll just grab the last one. Also, putting a new version of a file into the Archive is really easy, as I'll just overwrite the old version and edit the index entry if needed.

So, in short, don't worry about it and upload. If you're uploading more than a dozen a day, that would be the point to consider slowing down ...
Back to top
Tdarcos



Joined: 16 May 2008
Posts: 4441
Location: University Park, Maryland

PostPosted: Thu Jan 10, 2013 9:33 am    Post subject: Reply with quote

Roody_Yogurt wrote:
Also, as far as Tdarcos' contribution to this thread goes, let us point out that his code would not actually work. "visited" is an attribute and cannot be used as a property like he does there.

Well, pick a different property or array or whatever; it's the context switch in one statement that was the point I was making.
Quote:
Still, I guess it could be used for a property that can be one of two values. If the two values are 0 and 1, though, you could also just do this:
Code:
x = not x

Well, that only works for 0 and 1. Some conditions might use 1 and 2, which was the example I saw. Sometimes you can't use 0 as an index because the language doesn't support 0 as an array subscript. Taking
Code:
ThisUser = 3 - ThisUser
switches between 1 and 2 very nicely. Or, any two different values, add the two and subtract the current value from that, and it automatically switches between the two values.
_________________
The lessons of history teach us - if they teach us anything - that no one learns the lessons of history.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Flack



Joined: 18 Nov 2008
Posts: 4953
Location: Oklahoma

PostPosted: Thu Jan 10, 2013 9:53 am    Post subject: Reply with quote

Roody, I think you might be able to alleviate some of TDarcos's confusion by changing the thread topic from "Quick Code Samples" to "Quick Hugo Code Samples that Work".
_________________
[] Jonathan "Jack" Flack []
Back to top
View user's profile Send private message Visit poster's website
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Thu Jan 10, 2013 11:31 am    Post subject: Reply with quote

DavidK wrote:
(I'm one of the Archive maintainers: Jonathan Blask asked me to comment.)

As ICJ says, generally the uploads get looked at every few days, so if there's a bunch of versions of the same thing, I'll just grab the last one. Also, putting a new version of a file into the Archive is really easy, as I'll just overwrite the old version and edit the index entry if needed.

So, in short, don't worry about it and upload. If you're uploading more than a dozen a day, that would be the point to consider slowing down ...


Thanks for chiming in! I think it'll make future update-or-not decisions a lot easier.

Also, authors, I was thinking last night that we could add a >HISTORY command to our games which would give a release history so new uploads don't necessarily feel like you are negating past work. It's an idea, anyway.
Back to top
View user's profile Send private message AIM Address
loafingcoyote



Joined: 04 Jan 2012
Posts: 89
Location: Texas

PostPosted: Thu Jan 10, 2013 3:30 pm    Post subject: Reply with quote

Thank you for the answers guys, I appreciate it. Mostly I just didn't want to violate any unwritten rules that the archive may have developed over the years. This makes me far more enthusiastic about updating my stuff in the future.

Thanks again!

-lc
Back to top
View user's profile Send private message
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Fri Feb 15, 2013 1:00 pm    Post subject: Reply with quote

"Turn-less" Looking

Now, this one is extremely easy to do, but I just want to list it here so authors remember that doing something like this is always an option. Some authors have decided that passive commands like looking should not take up a turn, so in turn-intensive scenes, players feel free to examine things as much as they want. To be honest, I think this is a good idea, but I have rarely added it to my games.

Of course, in Hugo, the way to do this is to just replace DoLook and have it not return true:
Code:
replace DoLook
{
   local i

   if not light_source
      VMessage(&DoLook, 1)     ! "It's too dark to see anything."
   else
   {
      if not object.long_desc
         ! "Looks just like you'd expect..."
         VMessage(&DoLook, 2)

!      if object is living, transparent, not quiet
      if ((object is living, transparent) or
         object is platform or
         (object is container and (object is open or object is not openable))) and
         object is not quiet and object is not already_listed
      {
         for i in object
         {
            if i is not hidden
               break
         }
         if i and object ~= player
         {
            local tempformat
            tempformat = FORMAT
            FORMAT = FORMAT | NOINDENT_F
            list_nest = 0
            print ""
            WhatsIn(object)
            FORMAT = tempformat
         }
      }

      run object.after
!      return true   ! commented out
   }
}


You can do the same for DoLookAround, DoLookIn, and DoLookUnder, if you'd like. Hmm, maybe Roodylib should have a flag for easily turning look-turns on and off. Something to think about.
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Sat Feb 23, 2013 4:19 pm    Post subject: Reply with quote

Roody_Yogurt wrote:
"Turn-less" Looking

You can do the same for DoLookAround, DoLookIn, and DoLookUnder, if you'd like. Hmm, maybe Roodylib should have a flag for easily turning look-turns on and off. Something to think about.


Ok, I added it to Roodylib version 2.9, officially uploaded today:
http://hugo.gerynarsabode.org/index.php?title=Roodylib
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Tue Apr 30, 2013 12:25 pm    Post subject: Reply with quote

In Hugo, characters default to being transparent (allowing you to see what they are carrying). The tricky thing is, unless the the character is set to unfriendly, the player can grab whatever the character is holding, and there isn't even any special acknowledgement that the character allows it or anything.

In case you have friendly characters in your game, you might want to have something like the following:

Code:
replace character
{
   type character
   pronouns "he", "him", "his", "himself"
   capacity 50
   holding 0
   is living, transparent, static
   exclude_from_all true
   before
   {
      parent(object) DoGet
      {
         local l
         l = string(_temp_string, self.name)
         l--
         print "Nah, that is "; The(self);
         if _temp_string[l] = 's'
         {
            "'."
         }
         else
            "'s."
      }
   }
}
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Thu Jun 06, 2013 1:37 am    Post subject: Reply with quote

Last year, I volunteered to betatest this guy's Inform implementation of the ICOM game, The Uninvited.

In the first room (a car), I was dismayed to get this response:
Quote:
>OPEN GLOVE COMPARTMENT
Opened.

(notice the lack of a content-listing)

Now, part of the problem was that the glove compartment was empty, but any suggestion that I have to LOOK IN a container right after opening it just sends me into a fury (I don't know why).

For a long while, I've been meaning to take a closer look at how Hugo handles it. It turns out that if the container has children, Hugo will list them if the container is not set quiet (so, not until you have LOOKed IN it).

Here is an alternative behavior, where the container lists its children (or lack thereof) on the first opening regardless- but does not list them again:
Code:
replace DoOpen
{
   if not CheckReach(object):  return false

   if object is not openable
   {
      VMessage(&DoOpen, 1)             ! "You can't open that."
      return
   }
   elseif object is open
      VMessage(&DoOpen, 2)             ! "It's already open."
   elseif object is locked
      VMessage(&DoOpen, 3)             ! "It's locked."
   else
   {
      object is open
      if not object.after
      {
         VMessage(&DoOpen, 4)     ! "Opened."

         FindLight(location)     ! in case the light source
                  ! has been revealed
         if object is not moved
         {
            ""
            Perform(&DoLookIn, object)
         }
      }
      object is moved
   }
   return true
}


Now, this code will only really work with non-takeable containers, as objects are also given the moved attribute when taken. Still, I think I am happier with this than the default, and I have not landed on anything that would work well for everything.
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Wed Jun 19, 2013 1:13 am    Post subject: Infocom-Style PrintStatusLine (With Correct Spacing) Reply with quote

It has long bothered me that, as far as I can tell, no system had a nice status-line-drawing example that spaced things out exactly like how Infocom did it, as I thought Infocom's method looks surprisingly good on different screen widths.

For the longest time, I figured their screenwidth-drawing routine must have a really clever algorithm. More recently, I decided that, no, the 5 or so spaces between "Moves: " and "Score: " just gives it a nice stretched-out look no matter where in the screen it is.

Long story short, I put together a routine to emulate the Infocom look as much as possible (although I complicate it a bit more than I really needed to). Since it has different spacing than my other PrintStatusLine code, instead of trying to get it to play nice with my modular system, I'm just releasing it as a standalone routine:

Code:
replace PrintStatusline
{
   local temp_it_obj, len, new_height

   ! since calling Art() might change our pronoun, we save it
   temp_it_obj = it_obj

   text to _temp_string
   if not light_source
      print "In the dark";
   else
   {
      print capital location.name;
      if player not in location
      {
         if parent(player).prep
            print ", "; parent(player).prep; " ";
         else
            print ", "; IN_WORD; " ";
         print Art(parent(player));
      }
   }
   text to 0
   len = StringLength(_temp_string)
   if (len + 21) > display.screenwidth
   {
      new_height = 2
   }
   else
      new_height = 1

   Font(BOLD_OFF | ITALIC_OFF | UNDERLINE_OFF | PROP_OFF)

   if new_height < display.statusline_height
   {
      window display.statusline_height
      {
         cls
      }
   }
   display.statusline_height = new_height
   window display.statusline_height
   {
      color SL_TEXTCOLOR, SL_BGCOLOR
      cls
      locate 1, 1
      print "\_";
      StringPrint(_temp_string)
      if display.statusline_height = 2
      {
         locate 2,2
      }
      elseif (display.screenwidth - (len + 30)) >= 10
         print to (display.screenwidth - 30);
      else
      {
         print to (display.screenwidth - 16);
      }
      if ((display.screenwidth - (len + 30)) >= 10) or
      (display.statusline_height = 2)
      {
         print "Score: "; number score;
         if display.statusline_height = 1
            print to (display.screenwidth - 14);
         else
            print to 17;
         print "Moves: "; number counter;
      }
      else
      {
          print "S: "; number score;
          print to (display.screenwidth - 9);
          print "M: "; number counter;
      }
   }
   color TEXTCOLOR, BGCOLOR
   Font(DEFAULT_FONT)
   it_obj = temp_it_obj
}
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Thu Jun 20, 2013 11:22 am    Post subject: "travel mode" Reply with quote

For Robb's WIP, the sheer amount of traveling made it sound to me like the game could use a quicker way to move around. I thought a keypress system would work best. This example is not complete- it only handles cardinal directions- but here is some code for doing such a system (as I imagine it- or a variation thereof- could be applied to the rare IF game, too).

Code:
#ifclear _SYSTEM_H
#include "system.h"
#endif

#if undefined PauseForkey
routine PauseForKey(p)   ! Where p is a prompt, if it ends up being used
{
   local key

   key = system(READ_KEY)
   if system_status or system(MINIMAL_INTERFACE)
   {
      ! If READ_KEY isn't available, we have to use the
      ! regular pause-with-cursor (and maybe a prompt)
      if p
      {
         if not system(MINIMAL_INTERFACE)
         ! If we give a prompt, it always goes at the bottom
            locate (display.screenwidth-20), display.screenheight
         Font(PROP_ON | ITALIC_ON | BOLD_OFF)
         print p;
         Font(DEFAULT_FONT | ITALIC_OFF)
      }
      pause
      key = word[0]
   }
   else
   {
      while true
      {
         key = system(READ_KEY)
         system(PAUSE_100TH_SECOND)
         if key:break
      }
   }

   return key
}
#endif  ! if undefined PauseForKey

routine DoTravelMode
{
   local a, r
   while true
   {
   print "[Travel mode. Press an arrow key to move in a cardinal direction
   or press ESC to go back to regular mode.]"
      r = 0
      a = PauseForKey
      select a
         case UP_ARROW: r = n_obj
         case DOWN_ARROW : r = s_obj
         case RIGHT_ARROW : r = e_obj
         case LEFT_ARROW : r = w_obj
         case ESCAPE_KEY
         {
            break
         }
      if r
      {
         if Perform(&DoGo, r)
         {
            main
         }
         ""
      }
   }
   "\n[Returning to normal mode...]"
}


The main thing to be aware of is that an >UNDO will take the player back to before "travel mode" was initiated, as long as memory allows it. Since memory probably won't allow it half of the time, you might want to disallow UNDO for a step after travel mode just for consistency.
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Jolt Country Forum Index -> Hugo's House of Horrors All times are GMT - 7 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001 phpBB Group

Theme by Kage Musha - RPG Garden

Copyrights and trademarks are all of the belonging company. No copyright Infringement intended