[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  SMAUG
. -> [Folder]  SMAUG coding
. . -> [Subject]  lower case parsing in exit desc -- need expert opinion

lower case parsing in exit desc -- need expert opinion

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1 2  

Posted by Klered   (24 posts)  [Biography] bio
Date Thu 20 Jan 2005 10:42 PM (UTC)
Message
Hi List -

Im looking for some guidance. Its not a big deal but it would be great if I could get Capital Letters to remain intact in my SMAUG exit descriptions.

What I know -

pexit->keyword is called in 'do_open'

act(AT_PLAIN, "$n opens the $d.", ch, NULL, pexit->keyword, TO_ROOM);
/* act(AT_PLAIN, "You open the $d.", ch, NULL, pexit->keyword, TO_CHAR);*/

my solution to keep the caps for CH was :
ch_printf(ch, "You open the %s.\n\r", pexit->keyword);

It seems like when 'pexit->keyword' is called from the "act()" string, the parse is in lower case. Im not sure how deep to go to fix it.

Can someone teach me how to tell the room about $n opens the $d and keep the Capital Letters from getting crushed?

I tried something like :
sprintf( buf, "%s opens the %s.\n\r", ch->name, pexit->keyword );

but that resulted in nothing.

Here is the first portion of the function for reference (see my comments):
----------------------------------------------------------
void do_open(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
EXIT_DATA *pexit;
int door;

one_argument(argument, arg);

if(arg[0] == '\0')
{
send_to_char("Open what?\n\r", ch);
return;
}

if((pexit = find_door(ch, arg, TRUE)) != NULL)
{
/* 'open door' */
EXIT_DATA *pexit_rev;
if( IS_SET(pexit->exit_info, EX_SECRET)
&& pexit->keyword && !nifty_is_name(arg, pexit->keyword))
{ ch_printf(ch, "You see no %s here.\n\r", arg); return; }
if(!IS_SET(pexit->exit_info, EX_ISDOOR))
{ send_to_char("You can't do that.\n\r", ch); return; }
if(!IS_SET(pexit->exit_info, EX_CLOSED))
{ send_to_char("It's already open.\n\r", ch); return; }
if(IS_SET(pexit->exit_info, EX_LOCKED)
&&IS_SET(pexit->exit_info, EX_BOLTED))
{ send_to_char("The bolts locked.\n\r", ch); return; }
if(IS_SET(pexit->exit_info, EX_BOLTED))
{ send_to_char("It's bolted.\n\r", ch); return; }
if( IS_SET(pexit->exit_info, EX_LOCKED))
{ send_to_char("It's locked.\n\r", ch); return; }

if(!IS_SET(pexit->exit_info, EX_SECRET)
|| (pexit->keyword && nifty_is_name(arg, pexit->keyword)))
{
/*questioning this area*/
act(AT_PLAIN, "$n opens the $d.", ch, NULL, pexit->keyword, TO_ROOM);

/*substitute next line for ch_print below as a test/*
/* act(AT_PLAIN, "You open the $d.", ch, NULL, pexit->keyword, TO_CHAR);*/

/*this works well and as expected */
ch_printf(ch, "You open the %s.\n\r", pexit->keyword);

/*this yields no results*/
sprintf( buf, "%s opens the %s.\n\r", ch->name, pexit->keyword );

/*end questioning*/

if((pexit_rev = pexit->rexit) != NULL
&& pexit_rev->to_room == ch->in_room)
{
CHAR_DATA *rch;

for(rch = pexit->to_room->first_person; rch; rch = rch->next_in_room)
act(AT_PLAIN, "The $d opens.", rch, NULL, pexit_rev->keyword, TO_CHAR);
}
remove_bexit_flag(pexit, EX_CLOSED);
if((door=pexit->vdir) >= 0 && door < 10)
check_room_for_traps(ch, trap_door[door]);
return;
}

<<SNIP>>

[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #1 on Thu 20 Jan 2005 10:59 PM (UTC)
Message
Quote:
sprintf( buf, "%s opens the %s.\n\r", ch->name, pexit->keyword );
This statement prints not to a character or anything, but to a buffer - but then you do nothing with the buffer. You need to do something with the buffer (e.g. send it to characters) for it to have an effect.

By the way, if you use the [code] tag for indents, it'll be a lot easier to read your code. :)

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Klered   (24 posts)  [Biography] bio
Date Reply #2 on Fri 21 Jan 2005 12:08 AM (UTC)
Message
Ksilyan,

Thanks alot- you really help alot of people here. I read your posts all the time. I have many many examples of the buf to player - I will see if I can dig something out of the existing code.

I still want to resolve the root of the problem - which is why I lose caps in the parsing in the cited example. Any ideas>?

Thanks in advance,

Mike
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #3 on Fri 21 Jan 2005 12:28 AM (UTC)
Message
I think the root of the problem is that the act() function makes sure that words are lowercase before inserting them. I think this is a "feature" which is useful most of the time - imagine the short desc is "A small goblin". You wouldn't want "You hit $N" to translate to: "You hit A small goblin", after all. So, since some people capitalize things that shouldn't be, act() simply makes them lowercase.

So, you'd have to prevent act() from doing that. However, you probably *do* want it to keep that "feature" for all other cases, or else you'll probably introduce more "features" into the code. :)
My solution would be to add a flag to act(), e.g. 'capitalize', that only capitalizes stuff if the flag is true. In C++ this would be easy; you could just add a default parameter. Since C doesn't have default parameters, you'd have to change every single place you use act(). Since that stinks, I would be tempted to just copy act and make a new function, act_nocaps, that doesn't lowercase the letters of the arguments.

(I could be wrong, this is from memory and I don't have the code to look at.)

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Frobozz   (75 posts)  [Biography] bio
Date Reply #4 on Fri 21 Jan 2005 04:00 PM (UTC)
Message

From mud.h, I tried to pull out all the parts you'll need to make an act2 function.



/* This is to tell if act uses uppercasestring or not --Shaddai */
bool DONT_UPPER;

down farther:

/*
 * TO types for act.
 */
typedef enum { TO_ROOM, TO_NOTVICT, TO_VICT, TO_CHAR, TO_CANSEE } to_types;



void act from comm.c



void act( sh_int AType, const char *format, CHAR_DATA *ch, void *arg1, void *arg2, int type )
{
    char *txt;
    CHAR_DATA *to;
    CHAR_DATA *vch = (CHAR_DATA *)arg2;

    /*
     * Discard null and zero-length messages.
     */
    if ( !format || format[0] == '\0' )
        return;

    if ( !ch )
    {
        bug( "Act: null ch. (%s)", format );
        return;
    }

    if ( !ch->in_room )
      to = NULL;
    else if ( type == TO_CHAR )
      to = ch;
    else
      to = ch->in_room->first_person;
    /*
     * ACT_SECRETIVE handling
     */
    if ( IS_NPC(ch) && xIS_SET(ch->act, ACT_SECRETIVE) && type != TO_CHAR )
        return;

    if ( type == TO_VICT )
    {
        if ( !vch )
        {
            bug( "Act: null vch with TO_VICT." );
            bug( "%s (%s)", ch->name, format );
            return;
        }
        if ( !vch->in_room )
        {
            bug( "Act: vch in NULL room!" );
            bug( "%s -> %s (%s)", ch->name, vch->name, format );
            return;
        }
        to = vch;
    }

    if ( MOBtrigger && type != TO_CHAR && type != TO_VICT && to )
    {
      OBJ_DATA *to_obj;

      txt = act_string(format, NULL, ch, arg1, arg2, STRING_IMM);
      if ( HAS_PROG(to->in_room, ACT_PROG) )
        rprog_act_trigger(txt, to->in_room, ch, (OBJ_DATA *)arg1, (void *)arg2);
      for ( to_obj = to->in_room->first_content; to_obj;
            to_obj = to_obj->next_content )
        if ( HAS_PROG(to_obj->pIndexData, ACT_PROG) )
          oprog_act_trigger(txt, to_obj, ch, (OBJ_DATA *)arg1, (void *)arg2);
    }

    /* Anyone feel like telling me the point of looping through the whole
       room when we're only sending to one char anyways..? -- Alty */
    for ( ; to; to = (type == TO_CHAR || type == TO_VICT)
                     ? NULL : to->next_in_room )
    {
        if ((!to->desc
        && (  IS_NPC(to) && !HAS_PROG(to->pIndexData, ACT_PROG) ))
        ||   !IS_AWAKE(to) )
            continue;

        if ( type == TO_CHAR && to != ch )
        if ( type == TO_CHAR && to != ch )
            continue;
        if ( type == TO_VICT && ( to != vch || to == ch ) )
            continue;
        if ( type == TO_ROOM && to == ch )
            continue;
        if ( type == TO_NOTVICT && (to == ch || to == vch) )
            continue;
        if ( type == TO_CANSEE && ( to == ch ||
            (!IS_IMMORTAL(to) && !IS_NPC(ch) && (xIS_SET(ch->act, PLR_WIZINVIS)
            && (get_trust(to) < (ch->pcdata ? ch->pcdata->wizinvis : 0) ) ) ) ) )
            continue;

        if ( IS_IMMORTAL(to) )
            txt = act_string (format, to, ch, arg1, arg2, STRING_IMM);
        else
            txt = act_string (format, to, ch, arg1, arg2, STRING_NONE);

        if (to->desc)
        {
        set_char_color(AType, to);
        send_to_char( txt, to );
        }
        if (MOBtrigger)
        {
          /* Note: use original string, not string with ANSI. -- Alty */
          mprog_act_trigger( txt, to, ch, (OBJ_DATA *)arg1, (void *)arg2 );
        }
    }
    MOBtrigger = TRUE;
    return;
}



There you go. I bet you can make it from there.


[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #5 on Fri 21 Jan 2005 04:10 PM (UTC)
Message
I think the 'lowercasing' takes place in act_string.

I didn't know that there was a global variable DONT_UPPER. I suppose setting that to false and then setting it back would do the trick. But man, is that evil and dangerous style...

FYI you'd do something like:
bool oldval = DONT_UPPER;
DONT_UPPER = false;
act( ... )
DONT_UPPER = oldval;
The reasoning is that you don't know what the oldvalue was; in case the old value was false, you don't want to set it to true when you're done with it here.

(This is, incidentally, a good example of why global variables like this are really not a good idea. Unfortunately, SMAUG is rife with them...)

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Klered   (24 posts)  [Biography] bio
Date Reply #6 on Sun 23 Jan 2005 01:18 AM (UTC)
Message
Thanks - I never considered how deep the rabbit hole would go. I was sure the act() was the culprit. I settled on doing it with this

       ch_printf(ch, "You open the %s.\n\r", pexit->keyword);
       sprintf( buf, "%s opens the %s.\n\r", ch->name, pexit->keyword );
       act( AT_ACTION, buf, ch, NULL, NULL, TO_ROOM );


I have also decided to visit each call to pexit->word and change accordingly
for things like door_bash - there are a handful of things to change that allows the support for Capital Letters in the exit descriptions without messing with the those Globals.

This all started because one of the builders ran into a problem using a color code in an Exit Description - Capital 'O' - which would get crushed into a lower case 'o' - needless to say it wasn't that big of a deal - but I thought how annoying - if you DO want a Capital Letter - you don't get one. This area is a special area that is going to break the color scheme of the game and installed into a fantasy/dream function.

Mike

[Go to top] top

Posted by Klered   (24 posts)  [Biography] bio
Date Reply #7 on Sun 23 Jan 2005 02:42 AM (UTC)
Message
The follow-up to making these changes for anyone interested in doing this - don't do it unless you want to comb through all of your areas and make sure that you have a proper exit description keyword =) on your doors. If you do not have an exit desc on a door - you will see the output string -

'You open the .'


Furthermore...

with the current code - if the Keyword is NULL (or doesn't exist) it reverts to the name 'door' - 'aka' -

'You open the door.'

I personally like the change because your keyword isn't limited to one word descriptions - with the stock code - My exit keyword was 'Immortal Room Trap Door - The open on the open action was -

'You open the immortal.'

My changes allow me to actually see the whole string - Keeping the caps intact - and doesn't truncate the exit desc keyword -

'You open the Immortal Room Trap Door.'


--maybe one of you smart guys can come up with a way so I won't have to go through all my areas.

Thanks in advance.

Mike
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #8 on Sun 23 Jan 2005 05:01 AM (UTC)
Message
Quote:
       ch_printf(ch, "You open the %s.\n\r", pexit->keyword);
       sprintf( buf, "%s opens the %s.\n\r", ch->name, pexit->keyword );
       act( AT_ACTION, buf, ch, NULL, NULL, TO_ROOM );
This is a good solution. It is quite smart to use existing functionality to avoid a for loop, and it accomplishes just what you wanted it to.

Quote:
maybe one of you smart guys can come up with a way so I won't have to go through all my areas.
Is your problem that it works for exits that *do* have keywords, but for exits that don't have keywords, it displays an empty string?

Here's something you can do: if the keyword text is not null and not empty (strlen > 0) then print out the whole text. If the keyword is null, or length == 0, then just print out 'door'.

Or have I misunderstood your problem?

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Meerclar   USA  (733 posts)  [Biography] bio
Date Reply #9 on Sun 23 Jan 2005 06:02 AM (UTC)
Message
Quote:
This all started because one of the builders ran into a problem using a color code in an Exit Description


From personal experience, using color codes in exit keywords is a horribly dangerous thing because to operate the exit, the codes must be matched *exactly*. Now if he wanted color in the visual room description, the color codes there should be escaped in the squash function anyway.

Meerclar - Lord of Cats
Coder, Builder, and Tormenter of Mortals
Stormbringer: Rebirth
storm-bringer.org:4500
www.storm-bringer.org
[Go to top] top

Posted by Klered   (24 posts)  [Biography] bio
Date Reply #10 on Sun 23 Jan 2005 11:50 PM (UTC)
Message
Yes Ksilyan, you understand my problem exactly.

Meerclar,

I totally see what your saying.

We are only trying this idea out - it is one area - so the work around is to use a system for your keywords.

If I use redit exname e {red}mahogany door -

The problem exists.

If I use redit exname e {red}a door mahogany -

The door can be opened with both 'door' and 'mahogany' - in the case of a room with multiple doors, 'mahogany' would suffice.

Thanks for the heads up tho - we will have to change the way we have made a few keywords!

Mike
Mike
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #11 on Mon 24 Jan 2005 12:25 AM (UTC)
Message
Alright. Let me know then if my suggestion works out - it should, although it might act funny for exits that aren't doors.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Klered   (24 posts)  [Biography] bio
Date Reply #12 on Mon 24 Jan 2005 08:08 PM (UTC)

Amended on Mon 24 Jan 2005 09:08 PM (UTC) by Klered

Message
Ksilyan - here is the finished solution - it basically solves the problem of the Keyword Desc being blank. This prototype can basically be added to all the calls to 'pexit->keyword' -- it works great - thanks for the idea.


I guess this is a Snippet - Enjoy

[Go to top] top

Posted by Klered   (24 posts)  [Biography] bio
Date Reply #13 on Mon 24 Jan 2005 09:07 PM (UTC)

Amended on Tue 25 Jan 2005 10:02 PM (UTC) by Klered

Message
((THIS IS A WORK IN PROGRESS)) REVIEW BUT DON'T USE YET!! I WILL POST
THE FINISHED PRODUCT SHORTLY))


To anyone using this Capital Letter Support and Multiple Word Descriptions in your exit keyword names. - This code is for exit keywords only - It works with color tags as well - just make sure to use the following convention when setting up your exit keywords with color and not colorize the actual keyword.

ex, when using COLOR in exit description keyword-

and in the case of multiple exits for your rooms, combined with color codes - your exits will open using either 'door' or 'mahogany'. 'Large' wouldn't really work well because it expects a color token in the argument.

ex, when using COLOR in exit description keyword-
redit exname <dir> <colorcode>Large Mahogany Door

>open mahogany
'You open the {red}Large Mahogany Door.'


Here is regular style...
ex, when using standard keywords in exit description keywords-
redit exname <dir> Large Mahogany Door

>open mahogany 
'You open the Large Mahogany Door.'


Compare it to the OLD way --> redit exname <dir> Door Mahogany

>open mahogany
'You open the door.'
>open door
'You open the door.'

-OR-
The OLD way again --> redit exname <dir> Mahogany Door

>open door
'You open the mahogany.'
>open mahogany
'You open the mahogany.'


Note -- You may need to proof all you existing exit description keywords after installing this code. Today I found an exit when I opened it - it said -
'You open the stone stones rock rocks' !!

To begin,

All you need to do is modify do_open and do_close in act_move.c -

In do_open - find the following at the top


    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    EXIT_DATA *pexit;
    int door;


- right below 'char arg[MAX_INPUT_LENGTH];' add this -


char buf[MAX_STRING_LENGTH];


- then locate the following -


 act(AT_PLAIN, "$n opens the $d.", ch, NULL, pexit->keyword, TO_ROOM);
 act(AT_PLAIN, "You open the $d.", ch, NULL, pexit->keyword, TO_CHAR);


- and replace with -


  /* New Support for Capital Letters in Exit Descriptions */
  /* Provided by Klered of Perished Lands Mud. */
  /* Special thanks to Gammon Software Solutions Forum. */ 
       ch_printf(ch, "You open the %s.\n\r", pexit->keyword[0] != '\0' ? pexit->keyword : "door");
       sprintf( buf, "%s opens the %s.\n\r", ch->name, pexit->keyword[0] != '\0' ? pexit->keyword : "door");
       act( AT_ACTION, buf, ch, NULL, NULL, TO_ROOM );
     /*end new support*/



In do_close - find the following at the top


    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    EXIT_DATA *pexit;
    int door;


- right below 'char arg[MAX_INPUT_LENGTH];' add this -


char buf[MAX_STRING_LENGTH];


- then locate the following -


 act(AT_PLAIN, "$n closes the $d.", ch, NULL, pexit->keyword, TO_ROOM);
 act(AT_PLAIN, "You close the $d.", ch, NULL, pexit->keyword, TO_CHAR);


- and replace with -


  /* New Support for Capital Letters in Exit Descriptions */
  /* Provided by Klered of Perished Lands Mud. */
  /* Special thanks to Gammon Software Solutions Forum. */ 
       ch_printf(ch, "You close the %s.\n\r", pexit->keyword[0] != '\0' ? pexit->keyword : "door");
       sprintf( buf, "%s closes the %s.\n\r", ch->name, pexit->keyword[0] != '\0' ? pexit->keyword : "door");
       act( AT_ACTION, buf, ch, NULL, NULL, TO_ROOM );
     /*end new support*/


-If you really want - this code can be applied to the MANY calls to pexit->keyword, for example, do_doorbash, do_picklock, etc. Good Luck.
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #14 on Mon 24 Jan 2005 09:09 PM (UTC)
Message
Haven't read it fully but there is in fact an edit post button in addition to a delete post button. :-) Maybe you should delete the first two posts since the third is correct.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


50,063 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]