Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Entire forum
➜ SMAUG
➜ SMAUG coding
➜ Breaking stacked commands.
Breaking stacked commands.
|
It is now over 60 days since the last post. This thread is closed.
Refresh page
Pages: 1 2
Posted by
| Dace K
Canada (169 posts) Bio
|
Date
| Sun 09 Apr 2006 07:31 PM (UTC) |
Message
| Is there any way to add a stop command, like "stop", that would clear the command stack?
For example, if someone typed:
Kill zombie
punch
punch
punch
punch
punch
punch
punch
and the zombie ran away before the first punch, so the user typed in "stop", it would result in a clearing of all the un-executed commands? |
ASJ Games - .Dimension 2, Resident Evil, and snippets - oh my!
http://asj.mudmagic.com
Drop by the area archives and find something for your mud. http://areaarchives.servegame.com | Top |
|
Posted by
| Zeno
USA (2,871 posts) Bio
|
Date
| Reply #1 on Sun 09 Apr 2006 08:43 PM (UTC) |
Message
| There's a variable that is on the struct. It's the delay variable, but I'm not sure what it's called. wait_state maybe? You'll need to set that to 0, but also where commands are delayed (interp.c?) make an ifcheck where if the command is "stop" then ignore the wait. |
Zeno McDohl,
Owner of Bleached InuYasha Galaxy
http://www.biyg.org | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #2 on Sun 09 Apr 2006 09:10 PM (UTC) |
Message
| The problem is that the commands aren't really properly stacked. Rather the data is left on the socket buffer until wait_state goes to 0, then the next command is processed and interpreted.
What you'd actually need to do, then, would be to check the entire socket buffer for all of its commands, and if ever you find the clear command, then you would clear the entire buffer. It's unfortunately somewhat complicated.
But in C++, this would all be much easier. :-) You would just maintain a stack of commands, and as soon as input comes on the socket (whether or not the character has wait_state) you would stick it onto the stack. And if that command happened to be the clear command, you'd simply clear the stack. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Dace K
Canada (169 posts) Bio
|
Date
| Reply #3 on Sun 09 Apr 2006 09:55 PM (UTC) |
Message
| Ahh, that's kind of what I was thinking. It could get pretty laggy, and use up quite an unnecessary amount of CPU for the amount of use the players would get out of it.
As for switching to C++... eek. I can only imagine the number of problems I'd have with that :D.
Perhaps the best thing for me to do in C would be to replace wait_state with timers, and then simply discard all commands while the player has their timer on.
Of course, command stacking is useful in its own way...
Damn ;P. |
ASJ Games - .Dimension 2, Resident Evil, and snippets - oh my!
http://asj.mudmagic.com
Drop by the area archives and find something for your mud. http://areaarchives.servegame.com | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #4 on Sun 09 Apr 2006 11:01 PM (UTC) |
Message
| The CPU overhead is actually relatively minimal. In fact I think you'd hardly notice it. The update function is where the vast majority of CPU usage is, because it is not very smart about how it handles things. (For instance, it iterates over all mobs, not just mobs that have something to update.)
You actually don't need C++ to do the stack stuff, it's just easier because you don't have to get your own stack code. But I realize that most people probably don't want to switch to C++... but really, it's not all that hard. Heh, I had one person tell me once that they didn't want to switch to C++ because of the performance hit... that was pretty funny. :-)
The wait_state model is really quite poor. I'm not sure if timers would work; it would mean a fair amount of work since you would need multiple timers going on. But, it would probably work. I think it would be much easier to just write your own little linked list code that queues up commands, and is processed whenever wait_state hits 0. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Gohan_TheDragonball
USA (183 posts) Bio
|
Date
| Reply #5 on Mon 10 Apr 2006 12:01 PM (UTC) |
Message
| I have done what you are talking about, however I have a small drawback I have yet to fix as I am not good at manipulating strings.
void read_from_buffer( DESCRIPTOR_DATA *d )
{
// char log_buf[MAX_STRING_LENGTH];
int i, j, k;
/*
* Hold horses if pending command already.
*/
if ( d->incomm[0] != '\0' )
return;
if ( !str_infix_n( "forget", d->inbuf ) )
{
d->inbuf[0] = '\0';
stc( "You shake your head in a daze.....what was it you were trying to do again?\n\r", d->character );
return;
}
As for that str_infix_n() function I modified str_infix() because I needed to search for other things:
bool str_infix_n( const char *astr, const char *bstr )
{
int sstr1;
int sstr2;
int ichar;
char c0;
if ( ( c0 = LOWER(astr[0]) ) == '\0' )
return FALSE;
sstr1 = strlen(astr);
sstr2 = strlen(bstr);
for ( ichar = 0; ichar <= sstr2 - sstr1; ichar++ )
{
if ( c0 == LOWER(bstr[ichar]) && !str_prefix( astr, bstr + ichar ) )
{
if ( bstr[ichar+sstr1] == '\n' || bstr[ichar+sstr1] == '\r' )
return FALSE;
}
}
return TRUE;
}
The problem I am having is if someone types in anything that has the word forget at the end of their sentence the function kicks and and clears the command stack, not letting that sentence get though. if anyone can comment on how to fix that problem please do. | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #6 on Mon 10 Apr 2006 04:22 PM (UTC) |
Message
| You probably want to check for 'forget' being the only content of a command. To do that you would need to check if it is preceeded by a \n, \r or other whitespace, and followed by \n, \r with whitespace in between (potentially). Regular expressions would be incredibly useful here, but in the meantime you can write up your own fairly easily.
I am writing up a very quick example function and will provide it shortly. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #7 on Mon 10 Apr 2006 05:40 PM (UTC) Amended on Mon 10 Apr 2006 05:41 PM (UTC) by David Haley
|
Message
| Here is my code. I provide this with the disclaimer that I have only very briefly tested it and am not 100% sure that it is 100% correct. But it seems to do the job...
What this function is doing is checking if a buffer (buf, arg1) contains the single command (cmd, arg2).
This condition is considered satisfied when there is a newline, followed by some amount of whitespace, followed by the command, followed by some amount of whitespace, followed by a newline.
If there is enough demand, I will clean this up and release it as a proper snippet, perhaps in the general programming section.
Please give me your feedback. Enjoy. :)
EDIT:
Regarding implementation notes. The astute will notice that this is really just a very simple state machine. I use a trick to be able to have some arbitrarily large command, by having the command states after the fixed ones. If you want more details on how this works, it would probably be best to start a new thread. But the comments I provide might help at least a little bit...
// Does 'buf' contain the single command 'cmd'?
// Defined as: \n or \r then whitespace
// then: cmd
// finally: whitespace then \n or \r
bool str_has_command(const char * buf, const char * cmd)
{
int pos = 0;
int state = 0;
// States:
// 0: newline (\n or \r) (on success --> 1)
// 1: any whitespace (on success --> 3)
// 2: whitespace until newline (on success --> success)
// 3: cmd[0] (on success --> 4)
// 4: cmd[1] (on success --> 5)
// ...: ...
// 3+n: cmd[n] (on success --> 2)
char c;
while ( (c = buf[pos++]) != '\0' )
{
switch ( state )
{
// find initial newline
case 0:
if ( c == '\r' || c == '\n' )
state = 1;
break;
// munch whitespace
case 1:
if ( isspace(c) )
; // munch
else
{
state = 3;
pos--; // reconsider this character
}
break;
// whitespace; stop at newline.
// if we find a non-whitespace, go back to state 0
case 2:
if ( ! isspace(c) )
{
state = 0;
}
if ( c == '\r' || c == '\n' )
return true;
break;
// at state 3, we need to find cmd[0]
// at state 4, we need to find cmd[1]
// etc.
default:
// is this not what we wanted? then go back to zero
if ( c != cmd[state-3] )
{
state = 0;
}
else
{
state++;
// are we at the end of the cmd string?
// if so, move on to final whitespace search.
if ( cmd[state-3] == '\0' )
{
state = 2;
}
}
break;
}
}
return false;
}
|
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Dace K
Canada (169 posts) Bio
|
Date
| Reply #8 on Mon 10 Apr 2006 08:05 PM (UTC) |
Message
| That's a pretty nice little trick - definately wouldn't have thought of it myself.
Seems to work well, too - and I think you really should release it; I'm sure plenty of muds would get use out of it.
Just a quick thought - maybe the default case to look for a \n, \r, or whitespace after the cmd, just in case the mud decides to use a command for their stop cmd that has another similar command.
E.g. : Stop is used as stop cmd, whereas they have a command named.. er.. stopfighting, or something.
It's a little bit of a redundant check, but I'm sure will stop the inevitable question popping up. |
ASJ Games - .Dimension 2, Resident Evil, and snippets - oh my!
http://asj.mudmagic.com
Drop by the area archives and find something for your mud. http://areaarchives.servegame.com | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #9 on Mon 10 Apr 2006 08:27 PM (UTC) |
Message
| That's actually taken care of already. :) After completing the cmd match, it moves on to state 2, which only returns true if it hits a newline. It loops over whitespace, and aborts back to the beginning of the match if it ever finds something that is not whitespace.
So if the command we're looking for is 'stop', then 'stopfighting' will not match because 'f' is not whitespace.
Basically, the progression of states is:
0 --> 1 --> 3 --> 4 --> ... --> 3+n --> 2 --> successful termination
where n is the length of the cmd string. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Dace K
Canada (169 posts) Bio
|
Date
| Reply #10 on Tue 11 Apr 2006 12:16 AM (UTC) |
Message
| Ahh, missed that. Nice job :) |
ASJ Games - .Dimension 2, Resident Evil, and snippets - oh my!
http://asj.mudmagic.com
Drop by the area archives and find something for your mud. http://areaarchives.servegame.com | Top |
|
Posted by
| Gohan_TheDragonball
USA (183 posts) Bio
|
Date
| Reply #11 on Tue 11 Apr 2006 09:42 AM (UTC) |
Message
| just kind of wondering exactly how this is used, because i couldn't get it to work
if ( str_has_command( d->inbuf, "forget" ) ) | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #12 on Tue 11 Apr 2006 05:27 PM (UTC) |
Message
| That's correct. The function will return true if d->inbuf contains the command "forget", and false otherwise. What wasn't working for you? |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Gohan_TheDragonball
USA (183 posts) Bio
|
Date
| Reply #13 on Wed 12 Apr 2006 03:15 AM (UTC) |
Message
| beats me, but it doesn't work.
if ( str_has_command( d->inbuf, "forget" ) )
{
d->inbuf[0] = '\0';
stc( "You shake your head in a daze.....what was it you were trying to do again?\n\r", d->character );
return;
}
Thats how it looks in my code, but it does not work. Note, I simply replaced the line where my str_infix_n() function was, so I know its in the right place, and my str_infix_n() function worked before, so I know it should be working where it is, however it doesn't. | Top |
|
Posted by
| Gohan_TheDragonball
USA (183 posts) Bio
|
Date
| Reply #14 on Wed 12 Apr 2006 03:17 AM (UTC) |
Message
| I did however fix my previous problem with my str_infix_n() function, here is the working version of it where it doesn't cut off any sentence ending in forget:
bool str_infix_n( const char *astr, const char *bstr )
{
int sstr1;
int sstr2;
int ichar;
char c0;
if ( ( c0 = LOWER(astr[0]) ) == '\0' )
return FALSE;
sstr1 = strlen(astr);
sstr2 = strlen(bstr);
for ( ichar = 0; ichar <= sstr2 - sstr1; ichar++ )
{
if ( c0 == LOWER(bstr[ichar]) && !str_prefix( astr, bstr + ichar ) )
{
if ( bstr[ichar+sstr1] == '\n' || bstr[ichar+sstr1] == '\r' )
{
if ( ichar == 0 ) // No possibility of something coming before it
return FALSE;
else if ( bstr[ichar-1] == '\n' || bstr[ichar-1] == '\r' )
return FALSE;
else if ( bstr[ichar-1] == '\0' ) // just in case
return FALSE;
}
}
}
return TRUE;
}
usage:
if ( !str_infix_n( "forget", d->inbuf ) )
{
d->inbuf[0] = '\0';
stc( "You shake your head in a daze.....what was it you were trying to do again?\n\r", d->character );
return;
}
| 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.
47,973 views.
This is page 1, subject is 2 pages long: 1 2
It is now over 60 days since the last post. This thread is closed.
Refresh page
top