28 Jul, 2012, Hades_Kane wrote in the 1st comment:
Votes: 0
There was a system that was written probably about 9 or 10 years ago by the original coder of End of Time back before it was called such. It's very much a hack of the mobprog system… They are called Guardian Forces, upon killing one then you "gain" it, and during combat there is a chance for it to randomly appear to your aid, executing a "GF prog". The gf prog is really where the hack of the mobprog system is. It's been on our "todo list" forever, as far as getting the actual GFs written and plugged in, and we are working on that and doing some testing on the issue, and there's one issue I'm just not knowledgeable enough to figure out.

For reference, here is one of the GF progs:

1. *onearn
2. mob echoaroun $n $I gives $n a hurt look.
3. mob echoat $n $I gives you a hurt look.
4. You really hurt me! And my feelings even more. To make this up to me, you're gonna let me team up with you!
5. mob echoat $n [You will now occasionally summon $I in battle!]
6. mob goto 8
7. *end
8. *timer
9. 5
10. *end
11. *onload
12. mob echo $I appears in a gout of flame, wielding her six deadly weapons.
13. bow $n
14. say Let the blood-letting begin!
15. mob kill $t
16. mob elemdam $t 100 red slash
17. mob echo $I slashes $t with her right hand weapons[$z]
18. mob elemdam $t 100 red slash
19. mob echo $I slashes $t with her left hand weapons[$z]
20. *end
21. *onunload
22. mob echoaround $n $I crosses her six weapons and bows before $n.
23. mob echoat $n $I crosses her six weapons and bows before you.
24. mob echo $I disappears in a burst of flame that fades as quickly as it appeared.
25. *end
26. *onkilled
27. mob echo $I slumps to the ground, weapons dropped. A single tear drips down her face as she bursts into pyreflies and fades away.
28. mob goto 8
29. *end
30. *onkill
31. mob echo Brandishing her deadly weapons, $I grins fiercely with a shine to her eyes.
32. say You sure know how to show a girl a good time!
33. giggle
34. *end


Everything is pretty much working right, but where I'm running into trouble is when the *timer is a double digit number, as it seems to only be reading the first digit and ignoring the second.

bool run_gf_prog(CHAR_DATA *gf, int prog )
{
char *line = 0;
char *end;
char code[MSL];
size_t len;
int n;
CHAR_DATA *target;

if ( gf == NULL
|| !IS_NPC( gf )
|| !IS_SET( gf->act, ACT_GUARDIANFORCE )
|| gf->brkmsg[0] == '\0' )
return( FALSE );

if (gf->master == NULL)
return(FALSE);

if ( ( target = gf->master->fighting ) == NULL )
if ( ( target = gf->fighting ) == NULL )
if ( ( target = gf->mprog_target ) == NULL ) // maybe bad idea?
return(FALSE);

if ( (line = strstr( gf->brkmsg, gfprog[prog].head ) ) == NULL )
return( FALSE );

line += strlen( gfprog[prog].head );

if ( *line == 0 )
{
bug("Found NULL after prog header on GF %d", gf->pIndexData->vnum);
return( FALSE );
}

if ( (end = strstr( line, gfprog[prog].tail ) ) == NULL )
{
bug("prog terminator not found looking after prog on mob %d",
gf->pIndexData->vnum);
return( FALSE );
}

if ( (len = end - line) <= 0 )
{
bug("len <= 0 for gfprog on mob %d", gf->pIndexData->vnum);
return( FALSE );
}

strncpy(code, line, len);
code[len] = 0;

for ( n = 0; *gfprog[n].head != 0; n++ )
{
if ( strstr( gfprog[n].head, code ) != NULL )
{
bug("GFProg head found before *end on mob %d", gf->pIndexData->vnum);
*code = 0;
return( FALSE );
}
}

if ( prog == GF_TIMER )
{
int timer;
char *code1 = code;
while ( *code1 == ' ' || *code1 == '\n' || *code1 == '\r' ) code1++;
code[(index(code1, '\n') - code1)] = '\0';
if ( (timer = atoi( code1 )) <= 0 )
{
bug("GF timer <= 0 on mob %d", gf->pIndexData->vnum);
return( 0 );
}
bug("timer: %d", timer);
return(timer);
}

program_flow(gf->pIndexData->vnum,code,gf,NULL,NULL,gf->master,NULL,target);
return( TRUE );
}


Setting the timer in the GF Prog to 20, for example, will have that bug call show "2", etc.

I have some guesses as to where the problem is, but I've done very, very little code work that deals with string stuff like this, so I'm really at a loss. I do suspect all of the relevant code to the issue is contained in this function, though.

Any help would be greatly appreciated.
28 Jul, 2012, Hades_Kane wrote in the 2nd comment:
Votes: 0
I've managed to work out that if I put a " " after the double digit, it reads the full number. Sloppy solution, but that will work if nothing else will, so I'm thinking that line 66 is truncating the last "character" of the line… would still appreciate if someone can spot what isn't doing what it's supposed to there, though :)
28 Jul, 2012, plamzi wrote in the 3rd comment:
Votes: 0
Hades_Kane said:
I've managed to work out that if I put a " " after the double digit, it reads the full number. Sloppy solution, but that will work if nothing else will, so I'm thinking that line 66 is truncating the last "character" of the line… would still appreciate if someone can spot what isn't doing what it's supposed to there, though :)


If you care to debug this fully, I would just find out what char(s) your number line actually ends with (depending on what created the mobprog file, it could be "\r\n" or just "\n" or even "\n\r"…) and then make sure line 66 terminates the string where it should.
28 Jul, 2012, Hades_Kane wrote in the 4th comment:
Votes: 0
Looking through it all, it looks like it just goes through the string_append and whatnot, using the string_add function… at the bottom it has this, which is what looks to me to be what is determined the return/newline:

strcpy( buf, *ch->desc->pString );

/*
* Truncate strings to MAX_STRING_LENGTH.
* ————————————–
*/
if ( strlen( buf ) + strlen( argument ) >= ( MAX_STRING_LENGTH - 4 ) )
{
send_to_char( "String too long, last line skipped.\r\n", ch );

/* Force character out of editing mode. */
ch->desc->pString = NULL;
return;
}

/*
* Ensure no tilde's inside string.
* ——————————–
*/
smash_tilde( argument );

strcat( buf, argument );
strcat( buf, "\r\n" );
free_string( *ch->desc->pString );
*ch->desc->pString = str_dup( buf );
return;
}


Do I seem to be on the right path?
28 Jul, 2012, Runter wrote in the 5th comment:
Votes: 0
Can you show your index function?
28 Jul, 2012, Runter wrote in the 6th comment:
Votes: 0
while ( *code1 == ' ' || *code1 == '\n' || *code1 == '\r' ) code1++;
code[(index(code1, '\n') - code1)] = '\0';



I think these two lines are the problem. I think it's an off-by-one logic error. Try:

while ( *code1 == ' ' || *code1 == '\n' || *code1 == '\r' ) code1++;
*strstr(code1, "\n") = '\0';


Or the better way:

strtok(code1, "\n");
timer = atoi(strtok(NULL, "\n"));


The whole function could be cleaned up/simplified a lot using strtok. Something to think about.

http://codepad.org/ftDNmI0o
http://www.elook.org/programming/c/strto...
28 Jul, 2012, Hades_Kane wrote in the 7th comment:
Votes: 0
Thanks Runter, that did it!

I'll take a look into the links provided too, a lot of the string manipulation is still outside of my current grasp, but something I definitely need/want to brush up on.
29 Jul, 2012, Davion wrote in the 8th comment:
Votes: 0
For what it's worth, I've spent a lot of time with c string manipulation and this is the first I've heard of strtok… woulda saved me so much time :S. Are there any pitfalls to it? gotchas, that you know of?
29 Jul, 2012, Rarva.Riendf wrote in the 9th comment:
Votes: 0
No pitfall, just a little harder to 'naturally' read. I suck at C string manipulation and still used it cause it was still better than anything else.
29 Jul, 2012, plamzi wrote in the 10th comment:
Votes: 0
Davion said:
For what it's worth, I've spent a lot of time with c string manipulation and this is the first I've heard of strtok… woulda saved me so much time :S. Are there any pitfalls to it? gotchas, that you know of?


The only gotcha is to remember that it modifies the original string. So if you need it at the end of processing, remember to make a copy first.
29 Jul, 2012, Lyanic wrote in the 11th comment:
Votes: 0
It's fairly trivial to switch from using C-style strings to C++ std::string…just saying…

Also, inb4 quix with "C++ STRINGS NOT PRIMITIVES! THEY GOTS OVERHEAD! DUR!"
29 Jul, 2012, Runter wrote in the 12th comment:
Votes: 0
Lyanic said:
It's fairly trivial to switch from using C-style strings to C++ std::string…just saying…

Also, inb4 quix with "C++ STRINGS NOT PRIMITIVES! THEY GOTS OVERHEAD! DUR!"


Heh, I've only ever heard quix support switching to C++ strings.
30 Jul, 2012, Lyanic wrote in the 13th comment:
Votes: 0
Runter said:
Lyanic said:
It's fairly trivial to switch from using C-style strings to C++ std::string…just saying…

Also, inb4 quix with "C++ STRINGS NOT PRIMITIVES! THEY GOTS OVERHEAD! DUR!"


Heh, I've only ever heard quix support switching to C++ strings.

Either you're remembering incorrectly or Quix is trolling one/both of us. I've had numerous arguments, with him taking a very anti-C++ strings stance.
30 Jul, 2012, Runter wrote in the 14th comment:
Votes: 0
Lyanic said:
Runter said:
Lyanic said:
It's fairly trivial to switch from using C-style strings to C++ std::string…just saying…

Also, inb4 quix with "C++ STRINGS NOT PRIMITIVES! THEY GOTS OVERHEAD! DUR!"


Heh, I've only ever heard quix support switching to C++ strings.

Either you're remembering incorrectly or Quix is trolling one/both of us. I've had numerous arguments, with him taking a very anti-C++ strings stance.


Possible im just remembering wrong then.
30 Jul, 2012, quixadhal wrote in the 15th comment:
Votes: 0
Just to clarify, while I like the *IDEA* of C++ strings, I don't much care for the half-arsed implementation of them in the standard library. One of my biggest gripes came from exploring how they worked when making my xterm-256 code.

As Lyanic remembers, I discovered that memory use is extremely high when doing things which are easy and quick in languages like ruby or perl (where strings are a native type). Namely, a std::map of std::strings takes a LOT of overhead. In addition, the C-nature of the underlying data shows through in ugly ways, such as there being no easy way to make comparisons be case-insensitive, short of overloading half the operators with code that creates temporary copies filtered to lower-case.

So, if your project is small, they are indeed slightly easier to work with than char *'s, but if you have a few hundred thousand of them, it gets pretty ugly.

If you run this perl script, it'll spit out both C and C++ code to do the same thing (along with perl and lpc). The C++ code is comparable if you use char *'s – but then why bother? If you use std::strings, it gets kinda big.
01 Aug, 2012, Lyanic wrote in the 16th comment:
Votes: 0
quixadhal said:
Just to clarify, while I like the *IDEA* of C++ strings, I don't much care for the half-arsed implementation of them in the standard library. One of my biggest gripes came from exploring how they worked when making my xterm-256 code.

As Lyanic remembers, I discovered that memory use is extremely high when doing things which are easy and quick in languages like ruby or perl (where strings are a native type). Namely, a std::map of std::strings takes a LOT of overhead. In addition, the C-nature of the underlying data shows through in ugly ways, such as there being no easy way to make comparisons be case-insensitive, short of overloading half the operators with code that creates temporary copies filtered to lower-case.

So, if your project is small, they are indeed slightly easier to work with than char *'s, but if you have a few hundred thousand of them, it gets pretty ugly.

If you run this perl script, it'll spit out both C and C++ code to do the same thing (along with perl and lpc). The C++ code is comparable if you use char *'s – but then why bother? If you use std::strings, it gets kinda big.

There you go with that example again, after it was already proven to you that the insane memory usage is due to poor programming practice on your part - not because C++ strings have the ridiculous overhead you try to claim. Give it a rest.
01 Aug, 2012, Ssolvarain wrote in the 17th comment:
Votes: 0
Pretty sure you're the one who called the argument back up…
01 Aug, 2012, Runter wrote in the 18th comment:
Votes: 0
I don't know about the reasons Quix mentions, but it's pretty widely accepted that std::string is poorly implemented and one of the worse classes in the standard template library. I think std::string is a confused implementation that didn't realize if it's supposed to be a string manipulation API, or jut a STL char container that duplicates logic and code of something like std::vector, or both. A lot of people are opting for other string libraries that are implemented much better, yet aren't standard. For me it's not even a performance thing. I've always felt STD::String was a mess since the first time I had to use it.
01 Aug, 2012, Kline wrote in the 19th comment:
Votes: 0
Runter said:
I've always felt STD::String was a mess since the first time I had to use it.


Mess it may be, I still prefer it over a char. Particularly in MUDs where working with strings is the primary concern. In many ways it's a much more "natural" way to interact with data, and the fact that you don't get into a big mess over pointers and memory leaking can't be beat. How many novice dev questions and problems could be avoided if the more popular bases were updated to primarily use string objects? A lot, I'd bet. Hardly a concern of fixed-length buffer overruns, almost no worries about lost pointers and memory leaking, etc. Yes, all of that could also be fixed with better technique and knowledge, but everyone is fallible. It's nice to have the "safety net" of features provided by strings.
01 Aug, 2012, Runter wrote in the 20th comment:
Votes: 0
Kline said:
Runter said:
I've always felt STD::String was a mess since the first time I had to use it.


Mess it may be, I still prefer it over a char. Particularly in MUDs where working with strings is the primary concern. In many ways it's a much more "natural" way to interact with data, and the fact that you don't get into a big mess over pointers and memory leaking can't be beat. How many novice dev questions and problems could be avoided if the more popular bases were updated to primarily use string objects? A lot, I'd bet. Hardly a concern of fixed-length buffer overruns, almost no worries about lost pointers and memory leaking, etc. Yes, all of that could also be fixed with better technique and knowledge, but everyone is fallible. It's nice to have the "safety net" of features provided by strings.


You're presenting a false dilemma. I never suggested using c strings is better. There's C++ string implementations out there that don't suck. The more an application uses strings, the more invested they should be in using a good string implementation. The milage will be high for a text game.
Random Picks
0.0/22