Dan Egli wrote:
> void list_languages(struct char_data *ch)
> {
> char *tmp;
> int a = 0, i;
> sprintf(buf, "Languages:\r\n");
> for (i = MIN_LANGUAGES; i < MAX_SKILLS; i++) {
> if (SPEAKING(ch) == i) sprintf(buf, "*%s", buf);
> sprintf(buf, "%-20s %s\r\n", languages[a++], how_good...;
> sprintf(tmp, "Itteration: %d, Language: %s\r\n", a+1,...;
> send_to_char(tmp, ch);
> }
> sprintf(buf, "%s\r\n* denotes currently spoken language.\r\n", buf);
> send_to_char(buf, ch);
> }
Let's look at what you're doing really quickly by plugging in values
and simulating the loop, shall we? I call this little thing a "loop
iteration graph" (I don't know if there's a real name given to it, or
even if anyone else in the world bothers to do this),
Let MIN_LANGUAGES = 100 and MAX_SKILLS = 106
Let SPEAKING(ch) = 100 (Common)
Iteration 1: i = 100
if (100 == 100) buf = "*Languages:\r\n"; /* bug #1 */
buf = languages[0] + " " + how_good(GET_SKILL(ch, 100)); /* #2 */
a += 1; /* since we called a++ in previous sprintf(); a = 1 */
log("Iteration: " + (a+1) + ", " + language[1]);
a += 1; /* since we called a++ in previous sprintf(); a = 2 */
OUTPUT: "Iteration: 2, Troll"
Iteration 2: i = 101
buf = languages[2] + " " + how_good(GET_SKILL(ch, 101));
a += 1; /* a = 3 */
log(...);
a += 1; /* a = 4 */
OUTPUT: "Iteration: 3, Elvish"
Iteration 3: i = 102
buf = ...;
a += 1; /* a = 5 */
OUTPUT: "Iteration: 6, Dragon"
a += 1; /* a = 6 */
.
.
. (We have a significant sample size)
There are a variety of bugs here. First, we're causing a bug with
our attempt to discover a bug by having 'a' incremented after
both sprintf() statements. My suggestion would be to move the 'a'
stuff into the actual for(;;) portion, rather than have it in the
block. Hence,
for (a = 0, i = MIN_LANGUAGES; i < MAX_SKILL; a++, i++) {
if (GET_SKILL(ch) == i) ...;
sprintf(buf, "%-20s %s\r\n", languages[a], how_good...;
.
.
.
}
with 'a' not being incremented within the actual loop code (i.e.,
no 'a++' statements).
The next problem, denoted by "Bug #1" above, is that we call
sprintf() with "*%s" and the argument 'buf'. Assuming that our
string isn't mangled (it will almost certainly be because buf
will be modified before we incorperate it into the sprintf()
statement, meaning that we'll likely get "**") or we don't get
a crash, we'll at best have "*Languages:" which isn't what we
wanted. Rather,
if (GET_SKILL(ch) == i) strcat(buf, "*"); /* add * at end of buf */
Next, denoted by "Bug #2", we overwrite the contents of buf with
the new ones, rather than append them. What we want to do is,
sprintf(buf+strlen(buf), ...);
Which will put the new text at the end of buf. If you don't
understand how this works, I suggest reading a (good) book on C,
one that covers things such as pointer arithematic.
Also, with our sprintf(tmp...) thing: we are crashing because
tmp is a pointer to a random memory address, not an array. We want
"char tmp[MAX_STRING_LENGTH];" rather than "char * tmp;".
Recommendations:
1. Get a book covering pointers. There are a lot of mediocre
programmers out there that don't understand pointers. Until
they get a grasp of the idiosyncrasies of pointers, they'll
never take that next step.
2. Desk check your code -- that is, read it once or twice before
you even try to compile it. It can save you some time and
maybe a few headaches.
3. If you've read over your buggy code a thousand times and things
just aren't clicking together in your head, try simulating it
using something like a "loop iteration graph", or splitting it
up into groups to analyze certain blocks by what function they
are supposed to serve.
4. If you have other coders on your MUD, try to establish a "Peer
Review" method. In this, each coder would review the other's
code -- reading it and writing down (or maybe even fixing) the
potential problems. The only danger is if any of your coders
aren't mature enough to handle constructive criticism, or give
it.
As a side note, I would also suggest implementing something like a
"Peer Review" group with your builders, by asking them to set aside
some time to go through the new areas -- perhaps as three different
PC characters (since areas are typically developed for certain
level/power characters make it one below the target level range, one
of the average of the target level range, and one above the target
level range). I realize the quantity of areas produced will go
down since builders will have to set aside some time to review one
another's areas, but the quality will rise and provide a more
enjoyable experience for the players.
Note that this isn't necessarily a "quality control" program: you
should make it clear that builders aren't going to be ousted if
they're not producing high quality areas/descriptions/whatever. The
idea is to have each builder help one another. "No man is an
island."
-dak : Finally got his DVD-ROM to play DVD movies (It came with bad
drivers, originally).
+------------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
| http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
+------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/15/00 PST