[MUD-Dev] Re: Why did it take years?

Cynbe ru Taren cynbe at muq.org
Tue Oct 27 00:58:27 New Zealand Daylight Time 1998

Ola Fosheim <olag at ifi.uio.no> asks:

| "Bruce Mitchener, Jr." wrote:
| > Many of the people associated with these projects have a strong sense of
| > what the problems with the current (and previous) implementations are, and
| > how they would do things if they were to start from scratch.  In some cases,
| > there are _years_ of work invested in those systems, getting them to where
| > they are today.
| Yes, and that leads to another question, why did it take years?

Which is a very fair question.

One quick answer:

 * Muq proper is 100,000 lines of code.

 * Industry estimates are that checking a 100,000 line for Y2K
   compliance is enough to keep one programmer busy for one year.

 * A typical industry estimate seems to be 20 lines of code per
   day per programmer:
       100,000 lines / 20 lines/day == 5000 days
         5,000 days/ 364 days/year  == 13.7 years.
   (I'm presuming the progammer gets Christmas Day off work. :)

Naturally, this raises the question:  Why does Muq need 100,000
lines of code?  Is Cynbe just throwing too much stupid stuff in?

Here's the C-server breakdown:

    -----   -----       --------
    asm.t   3397	Binary encoding of bytecodes, including arity deduction.
    blk.t    339        Blocks of arguments on stack.
    bnm.t   5140        Big integers.
    bot.t    332        Special bottom-of-stack guard class.
    cdf.t    546        Class definition class.
    cdt.t    622        Condition class.
    cfg.t   1507        In-db Muq configuration display
    cfn.t    798        Compiled-function class
    chr.t    350        Character class
    clo.t    690        Generic objects
    dil.t   1017        B-tree support
    ecn.t    464        Stack-allocated Lists.
    err.t    143        Error logging 
    est.t    611        Stack-allocated structures.
    evc.t    562        Stack-allocated vectors.
    flt.t    332        Floating point numbers.
    fun.t    785        Function source code objects.
    int.t    338        Short integers.
    jbs.t    558        Job sets, for internal job control.
    job.t  33893        Implementations of various bytecodes.
jobbuild.t  3572        Generate opcode lookup tables & various functions.
    jobd.t   580        Crypto primitive.
jobpass.t    429        Probes host and generates configuration header file.
    joq.t   1341        Job queues.
    key.t   1401        Keywords (much like UniqueStrings).
    lbd.t    483        Lambda expressions (function all argument handling)
    lib.t    495        Misc functions.
    lok.t    461        Binary semaphores
    lst.t    479        Lisp lists.
    mod.t    304        Module list.
    mss.t   1843        Message queues for interthread communication
    mtd.t    496        Methods.
    muf.t   7052        Bootstrap Multi-User-Forth compiler.
    muq.t   1825        Display interpreter state to in-db code.
    obj.t   5167        Generic object support.
    pkg.t    581        Packages.
    prx.t    469        Proxies, for transparent networking.
    rdt.t    394        Readtables for lisp compiler.
    rex.t    873        Regular expression support.
    sdf.t    863        Structure definitions. 
    sha.t    688        Secure Hash Algorithm code.
    sil.t    950        B-trees for properties on objects.
    skt.t   5830        Network interface code for UDP and TCP.
    spc.t    352        Special values like objectNotFound.
    ssn.t    601        Sessions, for internal job control.
    stc.t    700        Structures.
    stg.t   1130        Strings.
    stk.t   1053        Stacks.
    stm.t    836        Generic streams.
    sym.t    997        Symbols (package variables, essentially).
    sys.t   1086        Display host system state to in-db code.
    usq.t    640        User queues, part of job scheduling.
    usr.t   2590        User objects.
    vec.t    715        Vectors (fixed-length one-dimensional arrays).
    vm.t    5418        Persistent heap manager.
    z-muq.t 1025        Main(): arg parsing, startup and shutdown.

As Fred Brooks comments in the Mythical Man Month, it's the tarpit
that gets to you:  It's not that any one part is hard, but that you
have to do -all- of them...

If you peer at the above list (or the source code itself), I think
you'll find almost all of it is pretty basic, generic functionality.

No multi-media support, unicode font support or anything exotic and
arguably easy to do without like that.

In addition to the 100,000 lines of hardcode, Muq currently has
40,000 lines of softcode:

    FILE                   LINES  FUNCTION
    ------------------     ------ -------
    000-C-version.t           48  Library version number
    010-C-condition.t        654  Standard conditions/exceptions
    020-C-mos.t             1105  Muq Object System core
    030-C-struct.t           669  Structures
    060-C-lispread.t         453  Reader for lisp compiler.
    070-C-lispprint.t        227  Printer for lisp compiler. 
    070-C-telnet.t           811  Per-user telnet daemon.
    090-C-lisp.t             169  Lisp compiler core.
    095-C-diffiehellman.t    145  Diffie-Hellman constants.
    100-C-lists.t           1281  Softcoded List functions.
    100-C-utils.t           2211  Random utility functions like 'ps'.
    110-C-compile.t          339  State record for softcode Forth compiler.
    120-C-muf.t              877  Core of softcode Forth compiler.
    130-C-muf-syntax.t      2296  Additional syntax functions for Forth compiler.
    140-C-defstruct.t        251  Defstruct syntax for Forth compiler.
    140-C-init-shell.t       242  User shell for interactive Forth execution.
    140-C-muf-shell.t        345  Ditto.   
    150-C-defclass.t        1313  Defclass syntax for Forth compiler.
    155-C-stdconditions.t    228  Standard conditions/exceptions part II.
    160-C-defgeneric.t       490  Defgeneric syntax for Forth compiler.
    170-C-defmethod.t        440  Defmethod syntax for Forth compiler.
    175-C-rex.t             1545  Regular expression syntax for Forth compiler.
    180-C-make-instance.t    196  Creating class instances in Forth.
    190-C-muqnet.t          3292  Muqnet daemon supporting transparent networking.
    195-C-io.t               121  More transparent networking support.
    200-O-edit.t             270  Trivial line editor in Forth.
    250-C-debugger.t         655  Trivial exception handler ("debugger") in Forth.
    280-O-vt100.t            225  vt100 cursor control in Forth.
    300-X-nanomud.t          884  Demo extremely small mudserver in MUF.
    310-X-nanomsh.t          644  Demo extremely small user shell for above.
    330-W-oldmud.t           997  Core of the Micronesia mudserver.
    335-W-oldop.t            123  Inter-daemon communication protocol definitions.
    337-W-oldpub.t           425  String publishing for per-user daemons.
    340-W-oldlive.t          175  Mixin for 'live' objects (mud-user-visible objs).
    342-W-oldnop.t           171  NOP message handler for daemon protocol.
    345-W-oldtask.t          726  Basic task support for daemon-daemon communication.
    347-W-oldrequest.t       916  Usershell/Userdaemon API support.
    350-W-olddaemon.t        608  Core daemon animating users objects.
    360-W-oldping.t          139  Handler for PING protocol msg to an object.
    363-W-oldlist-serv.t     516  Handler exporting lists of properties.
    363-W-oldprop-serv.t     304  Handler exporting individual properties.
    365-W-oldisle-list.t    1180  Handler exporting list of known isles. (Servers.)
    365-W-oldnative-list.t   409  Handler exporting online users.
    365-W-oldroom-host.t     249  Base class for rooms.
    365-W-oldwho-list.t      395  Isle mixin supporting export of active-users.
    365-W-oldwho-user.t      178  Avatar mixin supporting listing on who-list.
    370-W-oldisle.t          530  Core class for Micronesia worlds/isles.
    375-W-oldview.t          243  Base class for visible objects.
    380-W-oldholder.t        777  Mixin for objects which can contain/be contained.
    385-W-oldcanonical-room-name.t          120  Procedural building support.
    385-W-oldecho-complete-string.t         153  User shell support.
    385-W-oldhas-been-ejected.t             112  Handler for ejection messages.
    385-W-oldhas-come.t      112  Procotol handler for avatar-arrival messages.
    385-W-oldhas-left.t      112  Protocol handler for avatar-exit messages.
    385-W-oldhear-page.t     111  Protocol handler recieving incoming pages.
    385-W-oldhear-say.t      118  Protocol handler recieving incoming say/poses.
    385-W-oldhear-whisper.t  111  Protocol handler recieving incoming whispers.
    385-W-oldsubstring.t     147  Fetch a substring of a published string.
    390-W-oldshell-host.t    117  State record for user shell.
    395-W-oldthing.t         193  Basic holdable/visible mud object class.
    400-W-oldexit.t          234  Basic exit class.
    400-W-oldroom.t          257  Basic room class.
    401-W-oldroom-cache.t    488  User-shell cache of objects in current room.
    402-W-oldroom-cache2.t   546  API support code for above.
    403-W-oldsay.t           155  Support code sending string to everyone in room.
    405-W-oldavatar-view.t   269  Support code computing avatars description.
    410-W-oldavatar.t        442  Basic avatar class.
    420-W-badweight.t        177  Preliminary procedural-building support.
    421-W-badset.t           157  Ditto.
    422-W-badexit.t          141  Ditto.
    423-W-badroom.t          229  Ditto.
    425-W-badlands.t         244  Ditto.
    465-W-oldsdb.t           131  Build sample isle.
    470-W-oldmsh.t           186  Core defs for usershell.
    475-W-oldmsh-ban.t       293  Class implementing @ban shell command.
    475-W-oldmsh-boot.t      181  Class implementing @boot shell command.
    475-W-oldmsh-dig.t       361  Class implementing @dig shell command.
    475-W-oldmsh-doing.t     191  Class implementing @doing shell command.
    475-W-oldmsh-eject.t     227  Class implementing @eject shell command.
    475-W-oldmsh-gag.t       266  Class implementing @gag shell command.
    475-W-oldmsh-go.t        243  Class implementing 'go' shell command.
    475-W-oldmsh-help.t      195  Class implementing 'help' shell command. 
    475-W-oldmsh-hide.t      210  Class implementing @hide shell command.
    475-W-oldmsh-home.t      174  Class implementing @home shell command.
    475-W-oldmsh-inside.t    198  Class implementing @inside shell command.
    475-W-oldmsh-look.t      470  Class implementing look shell command.
    475-W-oldmsh-muf.t       186  Class implementing @muf shell command.
    475-W-oldmsh-outside.t   198  Class implementing @outside shell command.
    475-W-oldmsh-page.t      283  Class implementing @page shell command.
    475-W-oldmsh-ping.t      204  Class implementing @ping shell command.
    475-W-oldmsh-pose.t      204  Class implementing @pose shell command.
    475-W-oldmsh-quit.t      259  Class implementing @quit shell command.
    475-W-oldmsh-repeat.t    265  Class implementing @repeat shell command.
    475-W-oldmsh-restart.t   184  Class implementing @restart shell command.
    475-W-oldmsh-say.t       220  Class implementing @say shell command.
    475-W-oldmsh-short.t     199  Class implementing @short shell command.
    475-W-oldmsh-state.t     222  Class implementing @state shell command.
    475-W-oldmsh-tunnel.t    355  Class implementing @tunnel shell command.
    475-W-oldmsh-undig.t     224  Class implementing @undig shell command.
    475-W-oldmsh-untunnel.t  224  Class implementing @untunnel shell command.
    475-W-oldmsh-whisper.t   279  Class implementing 'whisper' shell command.
    475-W-oldmsh-who.t       350  Class implementing @who shell command.
    480-W-oldmsh-shell.t     545  Core driver for usershell.
    490-W-root-oldmud.t      503  Root-privileged  startup/shutdown/etc fns.

The above listing doesn't include:

    softcode regression-suite code      10,000 lines
    hardcode regression-suite code       3,000 lines
    documentation source                40,000 lines

Those don't directly benefit the end-user, so they don't really
count, of course.  :)  But they still somehow wind up taking 
time to write.

Total:  About 200,000 lines of hand-generated files.

(Muq also has another 20,000 lines of source code not listed above,
which are automatically generated by its 'jobbuild' tool: Not writing
that code by hand avoided a fair amount of coding and debugging, and
made it enormously easier to reconfigure various things easily.
Possibly a point worth noting.)

I expect if you look at MOO or Cold or such you'll get a broadly
similar picture:  There are no really killer individual coding
problems, but by the time you get it all done, it's a lot of little

The tarpit.

DevMUD seems to me to be contemplating addressing a fair number of
difficult problems which Muq does not: With Muq, I've deliberately
tried to avoid doing anything terribly exotic, in favor of shipping
something solid relatively soon: If using Muq as an estimation base,
you may want to add (say) a *2 multiplier on for extra code required,
and another *2 for extra coding effort to break new ground rather than
following pretty familiar coding trails?  If so, that would put you at
about 24 person-years to completion, it would seem, assuming no time
lost to defections or bickering.

Everyone still eager to dive in and get started?  :) :) :)


(PS:  I did a quick count of the number of source lines in
Golgotha:  About 250,000.
  On a quick scan, I see very little overlap between what the Muq
server does and what Golgotha does, so if you want an all-out
programmable distributed multimedia virtual world server/client, a
good quick estimate come from summing them: About 350,000 lines of
hardcode source and 500,000 total lines by the time you have a really
impressive softcode layer on top of it.
  This is starting to approach the megaline barrier at which even
well-funded efforts run by experienced professionals start seeing
about a 50% failure rate, no...?  Time for a thoughtful pause. :)

More information about the MUD-Dev mailing list