Ran into a problem which is sorta well known, but searching through the forum, I couldn't find exactly how to fix it.
I raised the top level of my mud from 60 to 210, and the integers went into the negatives. Something i expected, but not sure how to fix. Can someone gimme some advice?
Or make it an unsigned int which will take you to 4.2 million. If you need more than 4.2mil, go to unsigned long long and youll have more range than you should ever need.
recompiled and ran the mud, and exp still goes into the negative after reaching 2,100,000.
Test - level 122 - exp: 2,125,873,200
Test - level 123 - exp: -2,115,949,696
and for some reason, once your exp goes negative, your mental state takes a shot of around -90 points. Get this message, which is wierd, because the Test character is a mage:
Damn you heathen! Go forth and do evil or suffer the consequences!
You feel very unmotivated.
Somethin somewhere didnt get recast to unsigned. Youll need to be sure EVERY reference to that pointer gets recast to display and reference as unsigned int.
I've looked throughout handler.c and mud.h. Did a grep from all calls for exp, and I either can't find it or have overlooked it. Any ideas of what I'm overlooking?
It may even be in the function that calculates the xp. If you have one variable that is used, but is not of the same type, it will assign a negatinve number into the long int, which is still valid, and from there keep getting used.
Quote: (under class_type) int exp_base
(under race_type) int exp_multiplier
(under mob_index_data) int exp
(under char_data) int exp
For one, those want to be unsigned ints...
Basically, every time you see an integer in an exp calculation, make it an unsigned integer.
[addendum]If you can, compile with g++, even if you're coding in C. It'll give you a lot of freaky (to the coder not aware of the intricacies of C/C++) warnings and even errors, but it's much stricter and will help you find places where you mixed int and unsigned int.
Sorry if I confused you, but I guess I have that tendancy :0
All the things I posted in my last post I've already changed into unsigned ints. At the moment I'm going through each .c file search for the word "int" trying to track down each instance to make sure I'm not missing anything.
I don't really have any other compilers other then cygwin. How would I go about compiling in G++ in cygwin?
Well, be careful - you don't want to change ALL occurences of integers to uints. There are legitimate negative numbers, after all. :) If you change them all to uint, you'll just be breaking something the other way.
And yes, like Greven said I think that g++ comes with gcc and you just change the compiler executable, but it may be a separate package. And yes - have fun. :-)
There are other traps, like this. Take a simple example program, where someone's experience is decreased when they die:
#include <stdio.h>
int main (void)
{
int experience;
experience = 50; // new player's experience
experience -= 100; // loses experience when he dies
// ensure not negative after death
if (experience < 0)
experience = 0;
printf ("Experience now %i.\n", experience);
return 0;
}
Output
Experience now 0.
Now change it to use unsigned integers:
#include <stdio.h>
int main (void)
{
unsigned int experience;
experience = 50; // new player's experience
experience -= 100; // loses experience when he dies
// ensure not negative after death
if (experience < 0)
experience = 0;
printf ("Experience now %u.\n", experience);
return 0;
}
Output
Experience now 4294967246.
Notice how after dying they suddenly have heaps of experience? This is because of subtracting 100 from 50 using unsigned arithmetic.
ok, I decided to start fresh, and reverted all of the unsigned ints back into ints. Figured I'd use this g++ stuff you guys mentioned. So I altered the makefile, and ran smack-dab into some errors. Problem is I can't seem to find the problems.
$ make
make smaug
make[1]: Entering directory `/home/KK & LILI/smaug/dist/src'
g++ -c -O -g3 -Wall -Wuninitialized -DSMAUG -DTIMEFORMAT -DREGEX act_comm.c
In file included from act_comm.c:32:
mud.h:398: error: syntax error before `;' token
mud.h:452: error: syntax error before `new'
mud.h:973: error: syntax error before `;' token
mud.h:1025: error: syntax error before `;' token
mud.h:1894: error: syntax error before `;' token
mud.h:2000: error: syntax error before `;' token
act_comm.c: In function `char* translate(int, const char*, const char*)':
act_comm.c:165: error: syntax error before `new'
act_comm.c:196: error: syntax error before `new'
act_comm.c: In function `void do_group(CHAR_DATA*, char*)':
act_comm.c:2413: error: syntax error before `->' token
act_comm.c:2414: error: operands to ?: have different types
act_comm.c:2414: error: syntax error before `:' token
act_comm.c:2437: error: syntax error before `->' token
act_comm.c:2442: error: operands to ?: have different types
act_comm.c:2442: error: syntax error before `:' token
act_comm.c:2455: error: syntax error before numeric constant
act_comm.c: In function `void add_profane_word(char*)':
act_comm.c:3223: warning: comparison between signed and unsigned integer
expressions
make[1]: *** [act_comm.o] Error 1
make[1]: Leaving directory `/home/KK & LILI/smaug/dist/src'
make: *** [all] Error 2
So I attempted to find the errors, but I can't seem to find them. Like this for example. Mud.h, line 398-
int class; /* Classes not allowed to use this */
I'm not seeing any syntax errors. Same with this line, 452
You want to be careful here. You are doing a C++ compile, not a C compile, and words like "class" and "new" are reserved words for C++, thus the errors you are getting.
You might be better off using gcc rather than g++ and using -Wpedantic to get more warnings.
Indeed - g++ is probably defaulting to C++, because C++ is a stricter and hence better language. Ignore the silly myths you may have heard about C++ being slower. C++ is *exactly* the same as C in speed if you don't use any of the extra features.
In any case, just like Nick said it's not working because all those are reserved words in C++. It would be like writing:
char char;
in C. There are two ways to fix this:
- replace 'class' with 'Class' - making the first character uppercase tends to be enough
- put g++ into C mode (it's a command-line parameter, but I can't remember what)
- do what Nick said, use gcc, but step up the warning level considerably. The pedantic mode can be a PITA sometimes, but, well, it also helps you get your code right. :-)
[amendment] You can try adding '-x c' to your compiler options to tell it it's C code, but it should be automatically detecting that anyways.
quick question as I work my way through things. Ran into some calculations in fight.c I'm confused about. Sould I make these type of calculations into unsigned ints?
OK, 2 days of trying to chase down ints and here's where I am so far. After using grep to find all the calls I made, I'm altered all these calls so far:
Hmm, I remember when adding a new variable that was unsigned long long, I had to change fread_number to unsigned long long. Perhaps you have to change that to unsigned int?
You can assign signed/unsigned to each other as long as they have the same size. For example unsigned long long to long long is fine, but unsigned long long to long is not fine.
Toy, I noticed the following function, which should have return type uint I believe:
int level_exp( CHAR_DATA *ch, unsigned int exp )
Don't forget to check your printing functions as well, make sure they're printing unsigned ints and not normal ints.
After 2 days of trying to track down this issue, I'm realizing it's more trouble then it's worth. Decided to put the max levels down to 100. Fits in better with what I'm looking to do (level 50 hero, level 100 legend..) and it avoids the irrating neg. ints.
Yeah, it was fun attempting what you just tried, when I changed max level to 1015 on a Final Fantasy MUD I was coding for. Then I simply resorted to changing the level requirements, and ways of getting exp.
yea what zeno said.. you might wanna change the way smaug determines how much exp per level. at lvl 210 your talking...lvl * lvl * lvl * get_exp_base(ch).. or if your exp base is say 1000, 9,261,000,000, just a though. check you exp_level function in handler.c, i upped my mud to 210 levels and i had to change that. then again if you do that you might wanna redo the exp system a little keeping in mind that you get exp with every hit against a mob and when you kill it.