Question about Rom 2.4 pc_race_table[]
Posted by Baron Sengir
on Fri 06 Nov 2009 04:33 AM
— 18 posts, 71,875 views.
Rom 2.4 codebase (QuickMUD)
I've stumbled across a bit of a problem that I can't seem to narrow down involving interactions of races and classes. Perhaps someone has come across the same problem and might have suggestions as to either fixing, or working around it?
I've added/changed numerous races (to a total of 9 playable) with stock values, and it worked normally. I then added two new classes and set everything to generic stock values, and it worked as well. A third addition was the inclusion of a 6th attribute for stats, which I named appearance.
In const.c, I have changed all of my races to include the new stat, as well as the new classes.
{
"human", "Human", 0, {100, 100, 100, 100, 100, 100},
{""},
{10, 10, 10, 10, 10, 10}, {15, 15, 15, 15, 15, 15}, SIZE_MEDIUM
},
^^^^ The MUD works normally with this. The problem lies in the next portion. My MUD will be running on a system that uses lower stats than D&D, and starting characters will begin with "1" in each stat (to be increased immediately after creation with additional options), with a maximum defined between "5" and "10" (based upon race. Humans max at "5", vampires max at "10", and others in between).
I changed the race statistic line to this:
{1, 1, 1, 1, 1, 1}, {5, 5, 5, 5, 5, 5}, SIZE_MEDIUM
Upon compiling, I recieve no errors. If I create as a human mage, it creates as normal. However, if I create as a human cleric, the MUD crashes. After repeated tweaking, I have narrowed it down to apparently the MUD doesn't like the starting stats to be "1". Can anyone give me some info or suggestions? I have looked all over the code, and am unsure what to do next. Thanks in advance.
What does gdb say?
Alright, the newbie strikes yet again. I did not know anything about gdb, however I found references to it here on this site, as well as a link to a discussion on how to use it. After crossing my fingers, I checked and lo and behold, gdb is configured on my online server. I read over Nick's explanation of how to use gdb (and I believe I understood a good half of it), but the problem now seems to be in actually using gdb on my core.* file.
I managed to track down the core.* file in the ../area folder of Rom. To be certain I got the correct one, I removed the numerous ones that were there (through multiple crashes while testing) and then intentionally crashed the MUD again to get a fresh core.* file, labelled as:
core.7183
I have tried using the commands listed but gdb simply loads up and tells me that : No such file or directory.
I have tried a few permutations, to no avail. Perhaps I am misreading the syntax?
gdb (pathname) (core.*)
In my case:
gdb DALSQuickMUD/area core.7183
I even thought that perhaps the obj files path was what is needed, and tried that as well, to no avail.
gdb DALSQuickMUD/src/obj core.7183
I also experimented with a few other pathnames/combinations, but it continuously gives me the same readout. Perhaps because I am on an online server/provider that my pathname needs to be more inclusive? Thanks again for any input.
Not pathname, but the MUD exec. The file that runs the MUD.
Thanks for clearing that up. I tried running gdb again using the startup file, which is this:
gdb ../area/startup core.7183
The error message it is giving me now is-
"...(serverhost)/DALSQuickMUD/area/startup": not in executable format: File format not recognized
'startup' is my executable, so it should work, right? Thanks again for input.
No, that is a script file. You want the rom file (the output from the compiler). It should be in the src directory.
In any case, you should be able to start like this:
cd ../area
gdb ../src/rom
That changes you to the area directory (where you need to be to run the MUD), and then runs gdb with the executable as the argument.
Doh! Alright, well that explains a lot about why I couldn't get gdb to recognize the format. Filing this information away for future use, slowly I'm learning what exactly each is used for. I changed back to the area file and managed to run gdb as you stated. This is what I received:
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
warning: exec file is newer than core file.
warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libcrypt.so.1...done.
Loaded symbols for /lib/libcrypt.so.1
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
Reading symbols from /lib/libnss_dns.so.2...done.
Loaded symbols for /lib/libnss_dns.so.2
Reading symbols from /lib/libresolv.so.2...done.
Loaded symbols for /lib/libresolv.so.2
Core was generated by `rom 3000 copyover 5 -1'.
Program terminated with signal 11, Segmentation fault.
[New process 7183]
#0 obj_to_room (obj=0xb7dfa7a4, pRoomIndex=0x0) at handler.c:1956
1956 obj->next_content = pRoomIndex->contents;
So if I'm reading this right, in "handler.c" down at line 1956 is where it is hanging up and crashing? Here is a list of my current code around this line (brought up by using 'list' in gdb):
1951 /*
1952 * Move an obj into a room.
1953 */
1954 void obj_to_room (OBJ_DATA * obj, ROOM_INDEX_DATA * pRoomIndex)
1955 {
1956 obj->next_content = pRoomIndex->contents;
1957 pRoomIndex->contents = obj;
1958 obj->in_room = pRoomIndex;
1959 obj->carried_by = NULL;
1960 obj->in_obj = NULL;
Doesn't this function take an object that is loaded into the virtual memory (forgive me if I'm mixing terms and wrong context) and sets it as 'in the room', removing it as being 'in the inventory' from a player ?
That would infer a problem with the items, wouldn't it? But if that was the case, why would it work when I have different statistics set?
Quote:
warning: exec file is newer than core file.
Fix this first. You need to make sure you don't gdb a core created from an older compile.
Compile, crash it and use that core. Don't compile after the crash or the backtrace may not match up.
Or compile, and then run it the way I suggested, so it crashes when running gdb. Make sure you have the -g3 (from memory) option on the compile as mentioned on my gdb page so you get the symbols.
Once you get the crash, make sure you type "bt" (backtrace) so you can see the calling sequence.
If this is indeed the offending line:
obj->next_content = pRoomIndex->contents;
In gdb, type "p obj" and "p pRoomIndex". If either of them is NULL (zero) then that is a clue.
Gah, get rid of the static arrays. That would be my suggestion. Yea, I know, not helpful.
Zeno said:
What does gdb say?
IT'S OVER 9000!
I haven't posted anything worthless in awhile.
I think I am getting the hang of navigating and getting information from gdb. Many thanks again Nick for your post on gdb, it has been massively instrumental in my learning. Now, however, I have another newbie-ish question. I am not as up to speed on how variables look from within the memory itself as I once was about 10 years ago. To clarify that:
p pRoomIndex gives me:
$2 = (ROOM_INDEX_DATA *) 0x0
Is the 0x0 the same as 0 or NULL ? If so, I think I have an idea of why it might be doing what I think it is doing. I'm researching it more while I post this, and hopefully will get more insight (or even better, have it resolved). Thanks again for the help and tips!
Yes, 0x0 is their way of representing hex. For example, 0x16 is hex 16 not decimal 16 (so that would be 22 in decimal).
Of course, hex 0x0 is the same as zero.
And on this processor at least, a pointer of zero is a NULL pointer.
Many thanks to all who helped me track this down (and contributed to helping me learn how to use gdb and a better way of debugging). I will still need to toy with it a bit more, but I at least understand a lot of the fundamentals. In any case, I seem to have tracked down the problem and have fixed it.
Simple enough, really. I'll keep this short so I don't bore everyone too badly, but posting in case someone else comes across this problem and could track it down easier.
By changing the starting values of the attributes to "1", I massively lowered the capabilities of starting characters to carry and wield anything of weight (I forgot about the modifiers for carry and wield that are in tables as the applies). When the new character created, it tried to equip a weapon that weighed more than it could handle, and so the mud attempted to make the player 'drop' the item into the room. Since this was a new character, the ch->in_room was still NULL. Therefore, it cannot move an obj from the character to a NULL room. I edited the tables to reflect the lower stats being able to carry and wield weight.
Thanks once again, you guys rock!
Well done for spotting the problem! Now you have the techniques for finding other things, when they go wrong. Gdb is very useful for that.
As for the bug, that was subtle, wasn't it? Hopefully you also put in a check in the drop function to make sure a room exists before you try to drop something into it.
Thanks for the encouragement! It's always satisfying when you get to the bottom of a problem, especially a bug that is getting in the way of progress for a MU*. I am hoping that with more usage of gdb that it will allow me to become more familiarized, and help me track down the bugs much quicker. I suppose it is like anything, I just need to use it more and use your guide as a reference, then ask questions for the really sticky parts, eh?
As for the bug itself, yes it was quite subtle. And it was even more confusing as I changed the values a few times to get varying results (although that should have clued me in to the applies in the first place, live and learn). I didn't put a check in there yet, but I will admit that I thought about it last night as I was fixing it. However, I was debating the best way to handle dropping if it was a NULL room for the character. The only time the room should be NULL and the possibility of dropping the item will be during creation, I think.
I was toying with the idea of setting the ifcheck to check "CON_STATE", and if it is less than CON_PLAYING to drop the offending item in the creation room, because if you are set as CON_PLAYING you would have to be in a room already. Of course I could always put the extra ifcheck that if CON_PLAYING, and room is NULL, drop the item at the recall room. Any suggestions or tweaks as to which may be the best way to go about this?
Well, you don't really want the creation room to be littered with dozens of items, one for each character that is created.
Perhaps just don't drop it, and log the event, so you can look into it.
Or somewhat more preferably, have a better mechanism - rather than giving something to someone and then immediately dropping it because they can't carry it, don't give it to them in the first place.
Nick Gammon said:
Well, you don't really want the creation room to be littered with dozens of items, one for each character that is created.
I wholeheartedly agree with that. To avoid this problem, I changed my apply tables to have the values for "1" to be roughly equivalent of stock ROM "10" statistic for strength. I then worked my way upwards for weight allocation from there (managing to keep it almost spot on for the system I am basing everything off of).
As for logging the event in case it does happen again... Brilliant!!! Ok, sorry, had to get that out. Seriously though, I probably wouldn't have thought to write a little bit to log it as a bug in the log in case it -does- happen again. I'm looking into logfile writing now.
I was actually trying to avoid 'taking away' the item completely, as it is intended to be the starting weapon you create with. But it -does- beg the question of having some form of control over giving the item during creation -just in case-. Perhaps not giving the item, then notifying the player that they must acquire one. Gonna brainstorm more on that one too.