Re: Circlemud design issues

From: James Turner (turnerjh@XTN.NET)
Date: 04/20/98

   George <greerga@CIRCLEMUD.ORG> writes:

> >It really is an excellent code base, but I think it, like any other large,
> >multi-generation project, has some questionable design issues that have
> >long since needed rennovation.
> Kind of like how the four global buffers absolutely kill multithreaded
> potential? :)

Definitely, though I don't know how necessary or useful multithreading
would be... like changing to C++, it isn't something we should do
midstream unless there is hugely compelling need.  But that horrid
global variable buf needs killing! :)

> >I'd like to see a discussion on these topics, which are
> >probably too drastic for changes in the 3.0 codebase (maybe 3.1, or
> >perhaps 4.0).
> I do occaisonally, don't get many responses except when people miss the
> point of the project.

Can you clear me up, and perhaps others at the same time?  What are
the design goals of the Circlemud project?  Have plans been made for
what version 4.0 will include, or 3.1?

> >1. The biggest issue in my opinion is the use of macros.  Macros
> >definitely have their place, but computer speed has increased so much
> >since the first circlemud that they become less and less of a speed
> >issue.
> Macros are nice for other reasons.  They can do cheap checking like I have
> done in the upcoming bpl13 code.  Everything that now references a player
> specific structure element will produce a warning when used on a mob.

Macros are hideous :)  We should replace them with functions.  I
wasn't suggesting we do things like ch->name; we should have

const char *getName(CHAR_DATA *ch);

To get the name of a mob or character.  (In my code, I've typedef'd
CHAR_DATA to struct char_data; similarly, I've done this to all other
global structures.  I have a sed script which converts all references
in the code to use these, if anyone is interested).

> >Moreover, their inherent nature makes it very difficult to
> >debug in some circumstances (particularly since you can't set
> >breakpoints in a macro, and because expansion can be different than
> >you would expect and there's no way to see the problem without running
> >the code through the preprocessor).
> You shouldn't do that much in a macro then.  The only real offender is
> REMOVE_FROM_LIST, which is there for obvious reasons.

There is very little that actually needs doing with a macro.
Particularly, the data access macros (GET_NAME, OBJ_FLAGS, etc) should
be functions, not macros.  That way we can add proper flow control, as
well as leaving room for later changes in the data structures.

> >Additionally, it would be nice if a higher level of data abstraction could
> >be reached; macros provide useful hooks to such things (replacement with
> >functions, then renamnig all occurances via sed), but they aren't enough.
> They are also there for structure variable abstraction, data checking, and
> readability.  GET_NAME(ch) or ch->  How about GET_SAVE(ch, i)
> versus ((ch)->char_specials.saved.apply_saving_throw[i])?

Again, I misspoke in my original posts.  getSave() and getName() would
be the replacements, not actually accessing the structures manually.

> >(Additionally, for speed issues, gcc allows for the inlining of
> >functions, even in C code.  Perhaps VC++ provides a similar facility,
> >but with the progression of Cygnus' gnuwin32 [which I am assuming
> >supports inlining like this], I see less and less need to explicitly
> >support such an alien compiler).
> GCC will automatically inline functions if you use -finline-functions or
> -O3.

As I mentioned in my response to another message, we need to be able
to explicitly dictate which functions get inline'd.  gcc is smart, but
it can't properly predict the flow graphs of code once it is actually
executed.  Also, it won't inline every function -- that would make a
HUGE executable.  It tried to pick and choose; we should help it.

> >2. Expandability.  Circlemud provides a great platform for newbie
> >admins who just want to start a mud.  But in some respects, it is
> >difficult to expand.  For instance, the skill code is rather
> >restrictive IMO.
> Already scheduled to be rewritten.

Excellent.  I've got some working code (in my rather non-stock
codebase) that allows not only for skill percentages, but also skill
levels.  This isn't the place to go into it here, but once I do more
testing, I would be willing to make it public for stock inclusion if
that would be of any help.

> >Similarly, I've done the same with ability scores (a smaller project, not
> >needed in many cases, but it has its uses to abstract them as well).
> Huh? Isn't GET_STR(ch) abstract enough?

int getAbility(ch, ABIL_STRENGTH);
int setAbility(ch, ABIL_STRENGTH, 15);
int getRealAbility(ch, ABIL_INTELLIGENCE);
const char *getAbilityName(ABIL_PERCEPTION);

Those kinds of things.  It makes it easy to add or remove abilities,
as well as using a uniform interface to fundamental abilities (ie the
ones stock has now) and derived abilities (say we want an ability
based partially on strength and endurance).

It does make the code a small bit wordier.  However, it abstracts the
underlying structures as well as providing range checking and so forth.

> >Guild code is something that Circle could use (by this I mean part of the
> >main distribution) which isn't trivial to add.
> It has guild code, see SPECIAL(guild)

I use the word guild for what most people call clans, I believe.
Groups that players can divide themselves into.  Allegiances, so to
speak.  Not the guilds that stock has (ie not the 4 basic clases).

> >3. Layout.  The code in circlemud is, to be honest, poorly laid out.
> It inherited from Diku.

We should repair it :)

> >The file divisions are usually fairly accurate, though there are many
> >contradictions and oddities in the code that make it hard to understand
> >what functions belong in which files.  I personally use Emacs and etags,
> >so this is much less of an issue, but it is still a design issue that
> >needs addressing.  Also, we need a single .h file;  having several is a
> >real problem.
> A single .h file would cause excessive recompilation.
> I can understand the argument with conf.h, sysdep.h, structs.h, and utils.h
> though, since everything already includs them.

The other .h files are small compared to those.  I excised them in my
distribution long ago.  Also, as I mentioned in another post,
compilers move over headers much more quickly since headers don't
(well, SHOULDN'T) contain functions/global variables.

> >home/P-T/saga/saga.alias
> >home/P-T/saga/saga.objs
> >home/P-T/saga/saga.skills
> Everyone has a different opinion, although I don't entirely disagree with
> that.

I didn't mean to imply mine was the only way, just that I personally
like it more than other methods :)

> >Yes, there is a tiny amount of redundancy in the name appearing twice,
> >but it makes backing up easier, as well as removing a single player's
> >files, renaming them, etc.  Further, it eliminates issues of having
> rm */*/player.*
> (Would erase 'P-T/saga/saga.*' in your example.)

'rm */*/player.*' won't work.  Unix shells don't glob like that.
Unless I misunderstand what you're saying?  To backup a single
player's data into a convenient location,

tar zfc home/backups/P-T/saga.tgz home/P-T/saga/*

will do the job nicely.  Makes putting them in cryo easier (though
cryo and rent code I've taken out and haven't dealth with, so I could
be mistaken).

(Again, I've had too much to say and crossed the 200 line boundary.
Continued next post :) )

James Turner     

     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     | |

This archive was generated by hypermail 2b30 : 12/15/00 PST