Login
User Name:

Password:



Register
Forgot your password?
Vote for Us!
tintin++ ogg sound player script for linux
Author: Robert Smith
Submitted by: Vladaar
6Dragons ogg Soundpack
Author: Vladaar
Submitted by: Vladaar
6Dragons 4.4
Author: Vladaar
Submitted by: Vladaar
LoP 1.46
Author: Remcon
Submitted by: Remcon
LOP 1.45
Author: Remcon
Submitted by: Remcon
Users Online
CommonCrawl, Yandex

Members: 0
Guests: 9
Stats
Files
Topics
Posts
Members
Newest Member
481
3,734
19,366
618
Micheal64X
Today's Birthdays
There are no member birthdays today.
Related Links
» SmaugMuds.org » Codebases » AFKMud Support & Development » Parsing cast arguments
Forum Rules | Mark all | Recent Posts

Parsing cast arguments
< Newer Topic :: Older Topic > need a little push

Pages:<< prev 1 next >>
Post is unread #1 Jun 9, 2004, 12:55 am   Last edited May 19, 2005, 7:03 pm by Samson
Go to the top of the page
Go to the bottom of the page

cynshard

GroupMembers
Posts95
JoinedNov 19, 2003

I'm working on a way to parse the arguments supplied to do_cast() so that spells do not have to be enclosed in apstrophes. I've gotten it to work mostly, but there are a few things going on, and I'm positive my function doesn't work in all cases. I know the site will be down for a while soon, but maybe I can get a nudge in the right direction before it goes down.

Here is what I'm doing...

In magic.c I am replacing a call to one_argument with my custom function like this:
target_name = spell_argument( ch, argument, arg1 );


And in interp.c I define spell_argument as follows:
char *spell_argument( CHAR_DATA *ch, char *target, char *spell )
{
	char test[MSL], test2[MSL];
	int  count, sn;
	
	count = 0;
	
	if( !target )
  return NULL;
	
	while( target && target[0] != '' )
	{
  target = one_argument( target, test );
  // If it's not a live player or mob...
  if( !get_char_world( ch, test )  )
  {
  	if( count > 0 )
    sprintf( test2, "%s %s", spell, test );
  	else
    sprintf( test2, "%s", test );
  }
  if( ( sn = skill_lookup( test2 ) ) < 0 )
  {
  	if( !strstr( target, test ) )
    return ( target = test );
  	else
    return NULL;
  }
  sprintf( spell, "%s", test2 );
  count++;
	}
  
	if( !strstr( target, test ) )
  return ( target = test );
	else
  return NULL;
}


Basically I check the arguments word by word to see if they are a char in the room and if they are they don't belong to the spell (this works so long as a spell isn't named after a mob... :/) and if it passes that test it checks to see if it's a spell in case there are no mobs in the room... I don't think that this way is going to work in the long run. Any suggestions?

Some of my known bugs:

- After you cast a spell on a mobile, if you type 'c' and hit enter it will repeat the previous spell. ( This is actually kinda neat, but I don't know why.. so it's a bug for now ) Also, if the mobile dies and you type 'c' and hit enter again the game crashes with the following gdb output:
0x0810ae4d in one_argument (argument=0x0, arg_first=0xbfffc7dc "hag";) at interp.c:1085
1085 argument++;


- If you attempt to cast a beneficial spell on yourself you have to specify 'self' as a target.
I.e. 'cast heal' will not cast heal, instead you receive the following message:
They aren't here


Thanks,
Cynshard
       
Post is unread #2 Jun 9, 2004, 6:41 pm   Last edited May 19, 2005, 7:03 pm by Samson
Go to the top of the page
Go to the bottom of the page

Odis

GroupMembers
Posts46
JoinedMar 8, 2005

In response to your bugs you could do this:

Check to make sure the target is in the room (you'll need to modify this):

char arg[MIL];
CHAR_DATA *target;

argument = one_argument( argument, arg );

if ( (target = get_char_room( ch, arg ) ) == NULL && str_cmp( arg, "self" ) )
{
  send_to_char( "Sorry, but that person is not here.\n\r", ch );
  return;
}
else if ( !str_cmp( arg, "self" ) )
  target = ch;

Also, since I'm not familiar with how the spells really work, if the code will not allow you to use an attack spell on yourself you could change it to look like this:

char arg[MIL];
CHAR_DATA *target;

argument = one_argument( argument, arg );

if ( (target = get_char_room( ch, arg ) ) == NULL && str_cmp( arg, "self" ) )
{
  send_to_char( "Sorry, but that person is not here.\n\r", ch );
  return;
}
else
  target = ch;

Thus making you the default target, fixing your other problem which is having to specify yourself as the target.

I'm not sure why it does the same thing when you hit 'c', so yeah, sorry!

Basically I check the arguments word by word to see if they are a char in the room

Well, you are using get_char_world, which is not if the char is in the room. Just thought I'd point that out
       
Post is unread #3 Jun 9, 2004, 11:12 pm
Go to the top of the page
Go to the bottom of the page

cynshard

GroupMembers
Posts95
JoinedNov 19, 2003

Here's some more explination.

The purpose of the function spell_argument is to parse arguments passed to the game after the do_cast function. This will make it so you don't have to quote everything.

I just want to locate the parts that aren't the target and separate them from the target.

This said, I WANT to use get_char_world, since it doesn't matter if the char is in the room or not. That part is handled later in the do_cast function. Also, some spells don't depend on the target being IN the room, farsight for example.

Just a little update...
Too tired to give much more at the moment.

Thanks,
Cynshard
       
Post is unread #4 Jun 11, 2004, 8:07 pm
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,643
JoinedJan 1, 2002

I'm not terribly good with strings, but it seems to me that in most cases the target of a spell is the last word in the line. Figure out how to grab the last word in the cast command sent, see if it's a valid mob/pc target. If the last word isn't a valid mob/pc, then treat the spell like it would normaly be treated.
       
Post is unread #5 Jun 13, 2004, 9:55 pm
Go to the top of the page
Go to the bottom of the page

cynshard

GroupMembers
Posts95
JoinedNov 19, 2003

Going on the hint that Samson gave me I cooked this up. It seems to work, but my implementation in skills.c isn't complete just yet.
--outdated--


After I fiddle with the way the actual input is handled in skills.c it should work fine. I may tweak the section in spell_argument that pulls out the first word of the inversed argument so that it double checks the remainder for a valid spell, in case there are multiple targets, but that's another day. Too bad the boards go down tomorrow...

Cynshard
       
Post is unread #6 Jun 18, 2004, 10:20 pm   Last edited May 19, 2005, 7:04 pm by Samson
Go to the top of the page
Go to the bottom of the page

cynshard

GroupMembers
Posts95
JoinedNov 19, 2003

First, I'd like to say that I'm glad my main support mechanism is back on-line.

Second, thanks to Greven for working with me a bit on this hack, even though we didn't get far.

I have managed to get this to work, using Samson's suggestion as a lead off point... here is what I've hacked together. I'm still having a few problems though.

I made this little function to invert the argument words so that I could read the string sorta backwards( this part works fine ):
char *invert_string( char *input )
{
	char test[MSL] = "", ret_string[MSL] = "", buffer[MSL] = "";
	static char moo[MSL];

	// I need to read the string semi-backwards...
	while( input && input[0] != '' )
	{
  input = one_argument( input, test );
  sprintf( buffer, "%s %s ", test, ret_string );
  mudstrlcpy( ret_string, buffer, MSL );
	}
	mudstrlcpy( moo, ret_string, MSL );

	return moo;

}


The problem is in my use of this function within magic.c, i seem to be getting unpredictable results. Here is my current snapshot of magic.c (working on it right now..)

---UPDATE---
Here is the current code, that appears to be working properly, i haven't cleaned it up/made it more elegant, it's just a hack after all...
// Parse cast arguments -----------------------
	// Hack! --Cynshard
	if( ( sn = skill_lookup( argument ) ) < 0 )
	{
  argument = invert_string( argument ); // turn it around
  mudstrlcpy( arg1, one_argument( argument, arg2 ), MIL ); 
  mudstrlcpy( arg1, rtrim(invert_string( arg1 )), MIL ); 
  target_name = arg2;
  DISPOSE( ranged_target_name );
  ranged_target_name = str_dup( target_name );
	}
	else
	{	
  sprintf( arg2, "'%s'", argument );  
  target_name = one_argument( rtrim(arg2), arg1 );
  sprintf( arg2, "%s", target_name );
  DISPOSE( ranged_target_name );
  ranged_target_name = str_dup( target_name );
	}
	
	// --------------------------------------------

If anyone has any suggestions on how to compact this code please lemme know.

Cynshard
       
Post is unread #7 Jul 24, 2004, 12:32 am
Go to the top of the page
Go to the bottom of the page

Txzeenath
Apprentice
GroupMembers
Posts86
JoinedJul 24, 2004

Hmm I am quite interested in this code(and good job).. I would like to implement it on my mud(with the quote by you still given of course) but I am kinda bad at installing other peoples code so I was curious if you would consider posting a "snippet" of this feature or direct me as to what changes I have to make and where.


Figures.. can make sex based classes, multiclassing(saving equipment over multiclass in progress), and tons of other changes and I cant do this
       
Post is unread #8 Jul 25, 2004, 8:05 pm
Go to the top of the page
Go to the bottom of the page

cynshard

GroupMembers
Posts95
JoinedNov 19, 2003

I went ahead and glued together a snippet of my current spell parsing code. If you install it and it doesn't work paste your error messages and gdb information into this thread and I'll modify the snippet.

Here is the snippet.

Cynshard
       
Post is unread #9 Jul 25, 2004, 9:19 pm
Go to the top of the page
Go to the bottom of the page

Txzeenath
Apprentice
GroupMembers
Posts86
JoinedJul 24, 2004

Only thing I get is this

magic.c:1410: too many arguments to function `strcpy'



I changed the mudstrlcpy to strcpy.. is there some other function I could use? I run a smaug codebase(modified quite a bit, but functions are the same pretty much)
       
Post is unread #10 Jul 25, 2004, 9:24 pm
Go to the top of the page
Go to the bottom of the page

Txzeenath
Apprentice
GroupMembers
Posts86
JoinedJul 24, 2004

I just changed the mudstrlcpy's to sprintf's and it works perfect.. only thing it wont cast is create fire.. while create food, and create water work fine....

Perhaps a error while trying to find something with more than one other match to arg1?


... new results.. now it wont work with "cure light" etc. either.. even when no second argument is given.. possibly because I used sprintf?
       
Post is unread #11 Jul 26, 2004, 12:30 pm
Go to the top of the page
Go to the bottom of the page

cynshard

GroupMembers
Posts95
JoinedNov 19, 2003

AFAIK mudstrlcpy and strcpy are the same function, so replacing one with the other should work fine.

Using sprintf should accomplish the same thing also. Try sticking a log_printf statement after the arguments pass through the new functions and print out all the variables so that you can see exactly what is being done.

Cynshard
       
Post is unread #12 Jul 26, 2004, 10:56 pm
Go to the top of the page
Go to the bottom of the page

Greven
Magician
GroupMembers
Posts204
JoinedMar 5, 2005

mudstrlcpy and strcpy are not the same. They are very similiar, but mudstrlcpy takes an additional argument, the size of the max that you want to copy. you can replace mudstrlcpy with strncpy without changing the rest of the call
       
Post is unread #13 Jul 27, 2004, 5:48 pm
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,643
JoinedJan 1, 2002

Just keep in mind that strncpy doesn't always properly NULL terminate and as a result can possibly cause overflows or corruption.

mudstrlcpy is simply strlcpy from the BSD libraries, but since not all systems have it, I needed to rename it to work wherever the code went, even if it's redundant.
       
Post is unread #14 Jul 27, 2004, 8:49 pm
Go to the top of the page
Go to the bottom of the page

Greven
Magician
GroupMembers
Posts204
JoinedMar 5, 2005

Speaking of this, does anyone happen to have the code available for slprintf? I beleive that it is also available through freebsd, as I think it does the same to snprintf as strlcpy does to strncpy.

Also, (I'm in the middle of converting to mudstrlcpy instead) How are you supposed to control the size when its nothing but pointers? IE, your copying into a pointer, and cannot track the size, its pointers all the way back.
       
Post is unread #15 May 19, 2005, 5:36 am   Last edited May 19, 2005, 1:27 pm by Txzeenath
Go to the top of the page
Go to the bottom of the page

Txzeenath
Apprentice
GroupMembers
Posts86
JoinedJul 24, 2004

-------------EDIT-------DELETE---------
       
Post is unread #16 May 19, 2005, 10:46 am   Last edited May 19, 2005, 1:29 pm by Txzeenath
Go to the top of the page
Go to the bottom of the page

Txzeenath
Apprentice
GroupMembers
Posts86
JoinedJul 24, 2004

Working on my own rtrim and invert_string codes.. if anyone wants them lemme know and i'll post them


-EDIT-
Man do I need to read before I post... nevermind on the invert.. cyn posted one.. but if you need a rtrim lemme know
       
Post is unread #17 May 19, 2005, 1:17 pm   Last edited May 19, 2005, 3:41 pm by Txzeenath
Go to the top of the page
Go to the bottom of the page

Txzeenath
Apprentice
GroupMembers
Posts86
JoinedJul 24, 2004

I found a problem with this, and when you use more than one word as the target, it puts the word into the spell name.. I found a way around this.

            /*
             * Godly "spell builder" spell casting with debugging messages
             */
 {
            while( (sn = skill_lookup( arg1 ) ) < 0 && argument[0] != '\0')
{
argument = one_argument(argument, arg2);
mudstrlcpy(arg2, arg2, MSL);
mudstrlcpy(arg1, invert_string(argument), MSL);
invert_string(arg2);
invert_string(argument);
}

            if( ( sn = skill_lookup(arg1) ) < 0 )
            {
               send_to_char( "We didn't create that yet...\n\r", ch );
               return;
            }


It should be pretty easy to see what to do... if not than find out hehe.

What it does is looks for a skill named arg1, if it doesn't find one than it strips off one word, than it checks again, and again, and again until "argument" is completely empty or it finds a skill, at which point it quits, returning the "We didn't create that yet" message like normal. ARG2 is the target's name.. if the first word entered matches than it will cast as normal, If the first keyword is wrong than it won't work... This is actually exactly the same as the normal code, so this "hack" as far as I can see, is completely working. I've tested this using well over 7 target keywords specified.. which is far over you should be using anyway.

The only things missing are these:

#1
[1188hp 307m 150mv] [1exp] cast cure lighter self

ARG1:cure lighter
ARG2:self
LEFTOVER:rethgil eruc

ARG1:cure
ARG2:lighter
LEFTOVER:eruc
They aren't here.


.. it will try and cast "cure" on "lighter" ... but this isn't much of a problem.. since they should be spelling the spells the right way.

#2
For players who have developed a habit of it, the old 'SPELLNAME' argument isn't supported anymore... this is easily fixed with a str_cmp.




--------------EDIT-----------

I fixed #2... #1 seems pointless to solve as they should be spelling the name right in the first place... I'll post the #2 fix within 24 hours when I get back online.
       
Post is unread #18 Jun 18, 2005, 2:28 am   Last edited Jun 18, 2005, 2:30 am by Xorith
Go to the top of the page
Go to the bottom of the page

Xorith
The Null Value
GroupAFKMud Team
Posts254
JoinedFeb 23, 2003

Curious about your invert_string function.

/* invert_string( original, inverted );
 * Author: Xorith
 * Date: 6-18-05
 */
void invert_string( const char *orig, char *inv )
{
   const char *o_ptr = orig;
   char *i_ptr = inv;

   if( orig == inv || orig == NULL || inv == NULL )
      return;

   for( o_ptr += strlen( orig ) - 1; o_ptr != orig - 1; o_ptr--, i_ptr++ )
      (*i_ptr) = (*o_ptr);
   (*i_ptr) = '\0';
   return;
}


You can build on that nicely. For a returning value, I'd just use a static string. The reason I don't have it returning anything is because I wanted to keep it as clean and quick as possible. Can't really get any quicker than that. :)

Since it uses strlen, you need to include <string.h>, but otherwise it's golden for any MUD distro.
       
Post is unread #19 Jun 18, 2005, 2:45 am
Go to the top of the page
Go to the bottom of the page

Xorith
The Null Value
GroupAFKMud Team
Posts254
JoinedFeb 23, 2003

*laugh* Too darn tired. Just realized you want to invert the string's words, not letters. Ah, for that it's a bit more difficult.

char *last_arg( const char *orig, char *arg )
{
   const char *o_ptr = orig;
   static char newarg[MSL] = "";
   char *i_ptr = arg;
   size_t start = strlen( orig );

   if( orig == NULL || orig[0] == '\0' )
      return NULL;

   for( o_ptr += start; o_ptr != orig - 1; o_ptr--, start-- )
      if( (*o_ptr) == ' ' )
         break;

   if( start == -1 )
      mudstrlcpy( arg, orig, MSL );
   else
      mudstrlcpy( arg, orig+start+1, MSL );
   mudstrlcpy( newarg, orig, MSL );
   newarg[start] = '\0';
   return newarg;
}


I tested it. It takes the last argument (only counting spaces). Returns orig less the argument it took off. Doesn't modify orig. Works pretty well.

If you can use it, great. If not, oh well. Provided me a minute or two of boredom-relief. :P
       
Pages:<< prev 1 next >>