Index: ChangeLog =================================================================== RCS file: /home/circledb/.cvs/circle/ChangeLog,v retrieving revision 1.225 retrieving revision 1.234 diff -u -p -r1.225 -r1.234 --- ChangeLog 4 Oct 2002 07:18:16 -0000 1.225 +++ ChangeLog 19 Nov 2002 04:03:26 -0000 1.234 @@ -1,5 +1,6 @@ Release history: +Version 3.1 (yes, no beta pl): November 18, 2002 Version 3.00 beta pl22 release: October 4, 2002 Version 3.00 beta pl21 release: April 15, 2002 Version 3.00 beta pl20 release: January 15, 2002 @@ -4185,3 +4186,68 @@ change. of throwing it away. write_to_descriptor(): Return number of bytes written. process_output(): Keep data on socket write block. + +******** CircleMUD 3.1 *************************************************** + +11/15/2002 + +-- gg - comm.c: echo_on(), echo_off(): "%s" format strings, though not + necessary. + make_prompt(): Revert changeset #1.115. + process_output(): Cast 'result' to avoid unsigned warnings. + +-- gg - structs.h: Force 'byte' to signed char. Some platforms use + an unsigned char by default. + +-- gg - limits.c: gain_condition(): Cosmetic return -> break change. + +-- gg - lib/text/credits: Added Alex Fletcher, George Greer, and Daniel + Koepke. Changed jelson@ address to cdev@. + +-- gg - shop.h: Make it more obvious the WILL_* #define values are + bitvectors and not simply counting. + From: Carlton Colter + +-- gg - comm.c: process_output(): Correctly switch to large buffer + when text would just barely fit in the small buffer + then forget to change. + From: Yoram Harmelin + +-- gg - cnf/configure.in, cnf/aclocal.m4: Added -fno-builtin detection + to fix prototype testing. Functions such as bzero(), + printf(), and fprintf() were receiving false negatives. + configure: Regenerated. + +11/17/2002 + +-- gg - utils.h: Make TOGGLE_BIT "x^=y" instead of "x=x^y" to avoid + a VC++ warning. + +-- gg - house.c: House_delete_file(): Make 'vnum' a 'room_vnum' type. + +-- gg - castle.c: castle_mob_spec(): Use 'mob_vnum' type. + +-- ae - Updated docs, and added coding.tex/coding.pdf + +-- gg - autorun, autorun.cmd, autorun.pl, autorun.sh: Remove '3.0' + version number, to avoid needing to update it. + +-- gg - Makefile.lcc, constants.c, structs.h: bpl22 -> 3.1 + +-- gg - Makefile.amiga, Makefile.arc, Makefile.in, Makefile.lcc, Makefile.msvc, + Makefile.os2, Smakefile, magic.c, structs.h, Makefile.in: + Remove '3.0' version numbers to avoid updates. + +-- gg - util/Makefile.in: Remove '3.0' version numbers to avoid updates. + +-- gg - lib/world/README: Remove '3.0' version numbers to avoid updates. + +-- gg - lib/text/greetings, lib/text/imotd: Change 3.0 to 3.1. + +-- gg - doc/README-NOW: Deleted. + +-- gg - doc/README.AMIGA, doc/README.ARC, doc/README.BORLAND, doc/README.CYGWIN, + doc/README.MSVC4, doc/README.MSVC5, doc/README.MSVC6, + doc/README.OS2, doc/README.UNIX, doc/README.VMS, + doc/README.WATCOM, doc/README.WIN: Remove '3.0' version numbers + to avoid updates. Index: README =================================================================== RCS file: /home/circledb/.cvs/circle/README,v retrieving revision 1.14 retrieving revision 1.15 diff -u -p -r1.14 -r1.15 --- README 23 Aug 2001 15:32:28 -0000 1.14 +++ README 18 Nov 2002 15:15:01 -0000 1.15 @@ -2,7 +2,7 @@ CircleMUD README File --------------------- -Welcome to CircleMUD 3.0! I hope you enjoy your stay. +Welcome to CircleMUD 3.1! I hope you enjoy your stay. More information about CircleMUD can be found at the CircleMUD Home Page: http://www.circlemud.org. That site has the latest source distributions, @@ -33,7 +33,7 @@ jelson@circlemud.org Downloading CircleMUD --------------------- -You can find version 3.0 of CircleMUD at the following anonymous FTP sites: +You can find version 3.1 of CircleMUD at the following anonymous FTP sites: ftp.circlemud.org:/pub/CircleMUD/3.x ftp2.circlemud.org:/pub/CircleMUD/3.x @@ -98,7 +98,7 @@ doc/README.VMS - If you happen to be o If you are interested in porting CircleMUD to a new platform, see the file doc/porting.txt for some tips. -Version 3.0 source currently does NOT compile under DOS, Windows 3.x, or +Version 3.1 source currently does NOT compile under DOS, Windows 3.x, or Windows for Workgroups. Also, we currently do not distribute binaries, although the FTP site does have a very old Amiga binary of CircleMUD 2.20. @@ -115,25 +115,25 @@ Other Documentation If this information isn't enough to get you running, there's a lot more information available. All documentation (other than this file) is in -the "doc" directory and available on-line at http://www.circlemud.org. +the "doc" directory and available on-line at http://www.circlemud.org/. The README file in the doc directory describes each documentation file in detail, but there are several main files which should be of interest: -"The CircleMUD Administrator's Guide" (admin.txt, admin.ps) +"The CircleMUD Administrator's Guide" (admin.pdf) A good place to start after reading this README file, admin.txt gives an overall description of how Circle works, how to get it to compile and run for the first time, information about customizing and configuration options and command-line arguments, and tips on maintenance and day-to-day MUD administration. -"The CircleMUD Builder's Manual" (building.txt, building.ps) +"The CircleMUD Builder's Manual" (building.pdf) For the builders in your group, this documents the world-file format and describes how to create new rooms, objects, and monsters. Also, it describes how to add new areas to the MUD and gives some tips about game balance and world-file debugging. -"The CircleMUD Coder's Manual" (coding.txt, coding.ps) +"The CircleMUD Coder's Manual" (coding.pdf) For the coders in your group, a technical reference describing some of the more basic coding tasks such as how to add new commands, spells, skills, socials, and classes. Note that it assumes the reader already has @@ -143,6 +143,7 @@ an excellent knowledge of C; the manual A comprehensive list of all the possible SYSERR messages CircleMUD can generate, and a description of what can cause each problem and how to solve it. An excellent guide for troubleshooting and area debugging. +[NOTE: This document is not complete at this time] Getting Help Index: autorun =================================================================== RCS file: /home/circledb/.cvs/circle/autorun,v retrieving revision 1.6 retrieving revision 1.7 diff -u -p -r1.6 -r1.7 --- autorun 31 Jan 2002 18:05:29 -0000 1.6 +++ autorun 18 Nov 2002 17:18:24 -0000 1.7 @@ -1,6 +1,6 @@ #!/bin/sh # -# CircleMUD 3.0 autorun script +# CircleMUD autorun script # Contributions by Fred Merkel, Stuart Lamble, and Jeremy Elson # New log rotating code contributed by Peter Ajamian # Copyright (c) 1996 The Trustees of The Johns Hopkins University Index: autorun.cmd =================================================================== RCS file: /home/circledb/.cvs/circle/autorun.cmd,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 --- autorun.cmd 29 Oct 1997 05:15:32 -0000 1.1 +++ autorun.cmd 18 Nov 2002 22:43:48 -0000 1.3 @@ -1,10 +1,10 @@ /* REXX */ /* Note: This is an example Autorun REXX Script for use with OS/2 and - CircleMUD 3.0. You may use it as is, or as the basis for your own + CircleMUD. You may use it as is, or as the basis for your own script. April 18, 1996 - David A. Carver */ -/* CircleMUD 3.0 autorun script +/* CircleMUD autorun script * Originally by Fred C. Merkel * Copyright (c) 1993 The Trustees of The Johns Hopkins University * All Rights Reserved Index: autorun.pl =================================================================== RCS file: /home/circledb/.cvs/circle/autorun.pl,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- autorun.pl 29 Oct 1997 05:15:32 -0000 1.1 +++ autorun.pl 18 Nov 2002 17:18:24 -0000 1.2 @@ -1,5 +1,5 @@ #!/usr/bin/perl -# autorun -- maintain a Circle V3.0 mud server +# autorun -- maintain a Circle mud server # Copyright (c)1995 Vi'Rage Studios # This program is free software; you can redistribute it and/or modify Index: autorun.sh =================================================================== RCS file: /home/circledb/.cvs/circle/autorun.sh,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- autorun.sh 25 Jun 2001 18:28:38 -0000 1.1 +++ autorun.sh 18 Nov 2002 17:18:24 -0000 1.2 @@ -1,6 +1,6 @@ #!/bin/sh # -# CircleMUD 3.0 autorun script +# CircleMUD autorun script # Contributions by Fred Merkel, Stuart Lamble, and Jeremy Elson # Copyright (c) 1996 The Trustees of The Johns Hopkins University # All Rights Reserved Index: configure =================================================================== RCS file: /home/circledb/.cvs/circle/configure,v retrieving revision 1.16 retrieving revision 1.17 diff -u -p -r1.16 -r1.17 --- configure 16 Apr 2002 02:23:38 -0000 1.16 +++ configure 13 Nov 2002 20:17:00 -0000 1.17 @@ -1,7 +1,7 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.14.1 +# Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation @@ -333,7 +333,7 @@ EOF verbose=yes ;; -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.14.1" + echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) @@ -493,7 +493,7 @@ done if test -r "$cache_file"; then echo "loading cache $cache_file" - test -f "$cache_file" && . $cache_file + . $cache_file else echo "creating cache $cache_file" > $cache_file @@ -537,7 +537,7 @@ do set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:540: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_prog_MORE+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prog_MORE'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$MORE"; then @@ -570,7 +570,7 @@ done set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:573: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then @@ -600,7 +600,7 @@ if test -z "$CC"; then set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:603: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then @@ -646,12 +646,12 @@ fi if test -z "$CC"; then case "`uname -s`" in - *win32* | *WIN32* | *CYGWIN*) + *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:654: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then @@ -681,8 +681,8 @@ fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:686: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works" >&5 +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:686: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -723,14 +723,14 @@ echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:728: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:728: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo "configure:733: checking whether we are using GNU C" >&5 -if eval "test \"\${ac_cv_prog_gcc+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&6 echo "configure:761: checking whether ${CC-cc} accepts -g" >&5 -if eval "test \"\${ac_cv_prog_cc_g+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c @@ -793,7 +793,7 @@ if test $ac_cv_prog_gcc = yes; then echo $ac_n "checking whether ${CC-cc} -Wall also needs -Wno-char-subscripts""... $ac_c" 1>&6 echo "configure:796: checking whether ${CC-cc} -Wall also needs -Wno-char-subscripts" >&5 -if eval "test \"\${ac_cv_char_warn+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_char_warn'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -829,7 +829,7 @@ echo "$ac_t""$ac_cv_char_warn" 1>&6 echo $ac_n "checking whether ${CC-cc} accepts -Wno-char-subscripts""... $ac_c" 1>&6 echo "configure:832: checking whether ${CC-cc} accepts -Wno-char-subscripts" >&5 -if eval "test \"\${ac_cv_gcc_ncs+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_gcc_ncs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -859,6 +859,38 @@ fi echo "$ac_t""$ac_cv_gcc_ncs" 1>&6 + echo $ac_n "checking whether ${CC-cc} accepts -fno-builtin""... $ac_c" 1>&6 +echo "configure:864: checking whether ${CC-cc} accepts -fno-builtin" >&5 +if eval "test \"`echo '$''{'ac_cv_gcc_fnb'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_gcc_fnb=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_gcc_fnb=no +fi +rm -f conftest* + CFLAGS=$OLDCFLAGS + +fi + +echo "$ac_t""$ac_cv_gcc_fnb" 1>&6 + if test ${ac_cv_char_warn:-ERROR} = no; then MYFLAGS="-Wall" @@ -876,12 +908,12 @@ else fi echo $ac_n "checking for gethostbyaddr""... $ac_c" 1>&6 -echo "configure:880: checking for gethostbyaddr" >&5 -if eval "test \"\${ac_cv_func_gethostbyaddr+set}\" = set"; then +echo "configure:912: checking for gethostbyaddr" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gethostbyaddr'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostbyaddr=yes" else @@ -923,15 +954,15 @@ if eval "test \"`echo '$ac_cv_func_'geth else echo "$ac_t""no" 1>&6 echo $ac_n "checking for gethostbyaddr in -lnsl""... $ac_c" 1>&6 -echo "configure:927: checking for gethostbyaddr in -lnsl" >&5 +echo "configure:958: checking for gethostbyaddr in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyaddr | sed 'y%./+-%__p_%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:977: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -966,12 +997,12 @@ fi echo $ac_n "checking for socket""... $ac_c" 1>&6 -echo "configure:970: checking for socket" >&5 -if eval "test \"\${ac_cv_func_socket+set}\" = set"; then +echo "configure:1001: checking for socket" >&5 +if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1029: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_socket=yes" else @@ -1013,15 +1043,15 @@ if eval "test \"`echo '$ac_cv_func_'sock else echo "$ac_t""no" 1>&6 echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 -echo "configure:1017: checking for socket in -lsocket" >&5 +echo "configure:1047: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1066: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1056,12 +1086,12 @@ fi echo $ac_n "checking for malloc""... $ac_c" 1>&6 -echo "configure:1060: checking for malloc" >&5 -if eval "test \"\${ac_cv_func_malloc+set}\" = set"; then +echo "configure:1090: checking for malloc" >&5 +if eval "test \"`echo '$''{'ac_cv_func_malloc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1118: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_malloc=yes" else @@ -1103,15 +1132,15 @@ if eval "test \"`echo '$ac_cv_func_'mall else echo "$ac_t""no" 1>&6 echo $ac_n "checking for malloc in -lmalloc""... $ac_c" 1>&6 -echo "configure:1107: checking for malloc in -lmalloc" >&5 +echo "configure:1136: checking for malloc in -lmalloc" >&5 ac_lib_var=`echo malloc'_'malloc | sed 'y%./+-%__p_%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lmalloc $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1155: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1153,12 +1182,12 @@ fi echo $ac_n "checking for crypt""... $ac_c" 1>&6 -echo "configure:1157: checking for crypt" >&5 -if eval "test \"\${ac_cv_func_crypt+set}\" = set"; then +echo "configure:1186: checking for crypt" >&5 +if eval "test \"`echo '$''{'ac_cv_func_crypt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_crypt=yes" else @@ -1203,15 +1231,15 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 -echo "configure:1207: checking for crypt in -lcrypt" >&5 +echo "configure:1235: checking for crypt in -lcrypt" >&5 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lcrypt $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1254: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1250,13 +1278,13 @@ fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1254: checking how to run the C preprocessor" >&5 +echo "configure:1282: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then -if eval "test \"\${ac_cv_prog_CPP+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get @@ -1265,13 +1293,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1275: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1303: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1282,13 +1310,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1292: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1320: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1299,13 +1327,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1309: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1337: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1330,12 +1358,12 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1334: checking for ANSI C header files" >&5 -if eval "test \"\${ac_cv_header_stdc+set}\" = set"; then +echo "configure:1362: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1343,7 +1371,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1347: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1375: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1360,7 +1388,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1378,7 +1406,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1399,7 +1427,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1410,7 +1438,7 @@ if (XOR (islower (i), ISLOWER (i)) || to exit (0); } EOF -if { (eval echo configure:1414: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1442: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -1434,12 +1462,12 @@ EOF fi echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 -echo "configure:1438: checking for sys/wait.h that is POSIX.1 compatible" >&5 -if eval "test \"\${ac_cv_header_sys_wait_h+set}\" = set"; then +echo "configure:1466: checking for sys/wait.h that is POSIX.1 compatible" >&5 +if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1455,7 +1483,7 @@ wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF -if { (eval echo configure:1459: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1487: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -1479,21 +1507,17 @@ for ac_hdr in fcntl.h sys/fcntl.h errno. do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1483: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:1511: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < -#endif #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1497: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1521: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1523,21 +1547,17 @@ for ac_hdr in limits.h sys/time.h sys/se do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1527: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:1551: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < -#endif #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1541: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1561: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1567,21 +1587,17 @@ for ac_hdr in memory.h crypt.h assert.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1571: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:1591: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < -#endif #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1585: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1601: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1611,21 +1627,17 @@ for ac_hdr in sys/stat.h sys/socket.h sy do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1615: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:1631: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < -#endif #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1629: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1641: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1655,21 +1667,17 @@ for ac_hdr in signal.h sys/uio.h mcheck. do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1659: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:1671: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < -#endif #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1673: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1681: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1698,8 +1706,8 @@ done echo $ac_n "checking whether crypt needs over 10 characters""... $ac_c" 1>&6 -echo "configure:1702: checking whether crypt needs over 10 characters" >&5 -if eval "test \"\${ac_cv_unsafe_crypt+set}\" = set"; then +echo "configure:1710: checking whether crypt needs over 10 characters" >&5 +if eval "test \"`echo '$''{'ac_cv_unsafe_crypt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1714,7 +1722,7 @@ else ac_cv_unsafe_crypt=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1749: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_unsafe_crypt=yes else @@ -1764,12 +1772,12 @@ fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:1768: checking for working const" >&5 -if eval "test \"\${ac_cv_c_const+set}\" = set"; then +echo "configure:1776: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -1839,129 +1847,111 @@ EOF fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:1843: checking for pid_t" >&5 -if eval "test \"\${ac_cv_type_pid_t+set}\" = set"; then +echo "configure:1851: checking for pid_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS -#include #include #include #endif -#if HAVE_SYS_BITYPES_H -#include -#endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* - eval "ac_cv_type_pid_t=yes" + ac_cv_type_pid_t=yes else rm -rf conftest* - eval "ac_cv_type_pid_t=no" + ac_cv_type_pid_t=no fi rm -f conftest* fi -if eval "test \"`echo '$ac_cv_type_'pid_t`\" = yes"; then - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 - cat >> confdefs.h <&6 +if test $ac_cv_type_pid_t = no; then + cat >> confdefs.h <<\EOF #define pid_t int EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:1882: checking for size_t" >&5 -if eval "test \"\${ac_cv_type_size_t+set}\" = set"; then +echo "configure:1884: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS -#include #include #include #endif -#if HAVE_SYS_BITYPES_H -#include -#endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* - eval "ac_cv_type_size_t=yes" + ac_cv_type_size_t=yes else rm -rf conftest* - eval "ac_cv_type_size_t=no" + ac_cv_type_size_t=no fi rm -f conftest* fi -if eval "test \"`echo '$ac_cv_type_'size_t`\" = yes"; then - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 - cat >> confdefs.h <&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF #define size_t unsigned EOF fi echo $ac_n "checking for ssize_t""... $ac_c" 1>&6 -echo "configure:1921: checking for ssize_t" >&5 -if eval "test \"\${ac_cv_type_ssize_t+set}\" = set"; then +echo "configure:1917: checking for ssize_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS -#include #include #include #endif -#if HAVE_SYS_BITYPES_H -#include -#endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])ssize_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* - eval "ac_cv_type_ssize_t=yes" + ac_cv_type_ssize_t=yes else rm -rf conftest* - eval "ac_cv_type_ssize_t=no" + ac_cv_type_ssize_t=no fi rm -f conftest* fi -if eval "test \"`echo '$ac_cv_type_'ssize_t`\" = yes"; then - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 - cat >> confdefs.h <&6 +if test $ac_cv_type_ssize_t = no; then + cat >> confdefs.h <<\EOF #define ssize_t int EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:1960: checking whether time.h and sys/time.h may both be included" >&5 -if eval "test \"\${ac_cv_header_time+set}\" = set"; then +echo "configure:1950: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1970,7 +1960,7 @@ int main() { struct tm *tp; ; return 0; } EOF -if { (eval echo configure:1974: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1964: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -2005,19 +1995,19 @@ EOF fi echo $ac_n "checking for struct in_addr""... $ac_c" 1>&6 -echo "configure:2009: checking for struct in_addr" >&5 -if eval "test \"\${ac_cv_struct_in_addr+set}\" = set"; then +echo "configure:1999: checking for struct in_addr" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_in_addr'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2011: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_in_addr=yes else @@ -2044,19 +2034,19 @@ if test $ac_cv_header_sys_socket_h = no; ac_cv_socklen_t = no; else echo $ac_n "checking for typedef socklen_t""... $ac_c" 1>&6 -echo "configure:2048: checking for typedef socklen_t" >&5 -if eval "test \"\${ac_cv_socklen_t+set}\" = set"; then +echo "configure:2038: checking for typedef socklen_t" >&5 +if eval "test \"`echo '$''{'ac_cv_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { socklen_t sl; sl=0; ; return 0; } EOF -if { (eval echo configure:2060: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2050: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_socklen_t=yes else @@ -2080,12 +2070,12 @@ fi echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:2084: checking return type of signal handlers" >&5 -if eval "test \"\${ac_cv_type_signal+set}\" = set"; then +echo "configure:2074: checking return type of signal handlers" >&5 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2102,7 +2092,7 @@ int main() { int i; ; return 0; } EOF -if { (eval echo configure:2106: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2096: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -2121,12 +2111,12 @@ EOF echo $ac_n "checking for vprintf""... $ac_c" 1>&6 -echo "configure:2125: checking for vprintf" >&5 -if eval "test \"\${ac_cv_func_vprintf+set}\" = set"; then +echo "configure:2115: checking for vprintf" >&5 +if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2143: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" else @@ -2174,12 +2163,12 @@ fi if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 -echo "configure:2178: checking for _doprnt" >&5 -if eval "test \"\${ac_cv_func__doprnt+set}\" = set"; then +echo "configure:2167: checking for _doprnt" >&5 +if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2195: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" else @@ -2230,12 +2218,12 @@ fi for ac_func in gettimeofday select snprintf strcasecmp strdup strerror stricmp strlcpy strncasecmp strnicmp strstr vsnprintf do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2234: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:2222: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2289,12 +2276,12 @@ LIBS="$LIBS $NETLIB" for ac_func in inet_addr inet_aton do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2293: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:2280: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2348,13 +2334,17 @@ LIBS=$ORIGLIBS ac_safe=accept; echo $ac_n "checking if accept is prototyped""... $ac_c" 1>&6 -echo "configure:2352: checking if accept is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2338: checking if accept is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2364: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2380,6 +2370,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2398,13 +2391,17 @@ fi ac_safe=atoi; echo $ac_n "checking if atoi is prototyped""... $ac_c" 1>&6 -echo "configure:2402: checking if atoi is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2395: checking if atoi is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2421: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2430,6 +2427,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2449,12 +2449,16 @@ ac_safe=atol; echo $ac_n "checking if atol is prototyped""... $ac_c" 1>&6 echo "configure:2452: checking if atol is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2478: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2480,6 +2484,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2498,13 +2505,17 @@ fi ac_safe=bind; echo $ac_n "checking if bind is prototyped""... $ac_c" 1>&6 -echo "configure:2502: checking if bind is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2509: checking if bind is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2535: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2530,6 +2541,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2548,13 +2562,17 @@ fi ac_safe=bzero; echo $ac_n "checking if bzero is prototyped""... $ac_c" 1>&6 -echo "configure:2552: checking if bzero is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2566: checking if bzero is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2592: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2580,6 +2598,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2598,13 +2619,17 @@ fi ac_safe=chdir; echo $ac_n "checking if chdir is prototyped""... $ac_c" 1>&6 -echo "configure:2602: checking if chdir is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2623: checking if chdir is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2649: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2630,6 +2655,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2648,13 +2676,17 @@ fi ac_safe=close; echo $ac_n "checking if close is prototyped""... $ac_c" 1>&6 -echo "configure:2652: checking if close is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2680: checking if close is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2706: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2680,6 +2712,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2698,13 +2733,17 @@ fi ac_safe=crypt; echo $ac_n "checking if crypt is prototyped""... $ac_c" 1>&6 -echo "configure:2702: checking if crypt is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2737: checking if crypt is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2763: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2730,6 +2769,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2748,13 +2790,17 @@ fi ac_safe=fclose; echo $ac_n "checking if fclose is prototyped""... $ac_c" 1>&6 -echo "configure:2752: checking if fclose is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2794: checking if fclose is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2820: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2780,6 +2826,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2798,13 +2847,17 @@ fi ac_safe=fcntl; echo $ac_n "checking if fcntl is prototyped""... $ac_c" 1>&6 -echo "configure:2802: checking if fcntl is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2851: checking if fcntl is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2877: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2830,6 +2883,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2848,13 +2904,17 @@ fi ac_safe=fflush; echo $ac_n "checking if fflush is prototyped""... $ac_c" 1>&6 -echo "configure:2852: checking if fflush is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2908: checking if fflush is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2934: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2880,6 +2940,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2898,13 +2961,17 @@ fi ac_safe=fprintf; echo $ac_n "checking if fprintf is prototyped""... $ac_c" 1>&6 -echo "configure:2902: checking if fprintf is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:2965: checking if fprintf is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2991: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2930,6 +2997,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2948,13 +3018,17 @@ fi ac_safe=fputc; echo $ac_n "checking if fputc is prototyped""... $ac_c" 1>&6 -echo "configure:2952: checking if fputc is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3022: checking if fputc is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3048: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -2980,6 +3054,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -2998,13 +3075,17 @@ fi ac_safe=fputs; echo $ac_n "checking if fputs is prototyped""... $ac_c" 1>&6 -echo "configure:3002: checking if fputs is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3079: checking if fputs is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3105: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3030,6 +3111,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3048,13 +3132,17 @@ fi ac_safe=fread; echo $ac_n "checking if fread is prototyped""... $ac_c" 1>&6 -echo "configure:3052: checking if fread is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3136: checking if fread is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3162: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3080,6 +3168,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3098,13 +3189,17 @@ fi ac_safe=fscanf; echo $ac_n "checking if fscanf is prototyped""... $ac_c" 1>&6 -echo "configure:3102: checking if fscanf is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3193: checking if fscanf is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3219: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3130,6 +3225,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3148,13 +3246,17 @@ fi ac_safe=fseek; echo $ac_n "checking if fseek is prototyped""... $ac_c" 1>&6 -echo "configure:3152: checking if fseek is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3250: checking if fseek is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3276: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3180,6 +3282,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3198,13 +3303,17 @@ fi ac_safe=fwrite; echo $ac_n "checking if fwrite is prototyped""... $ac_c" 1>&6 -echo "configure:3202: checking if fwrite is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3307: checking if fwrite is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3333: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3230,6 +3339,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3248,13 +3360,17 @@ fi ac_safe=getpeername; echo $ac_n "checking if getpeername is prototyped""... $ac_c" 1>&6 -echo "configure:3252: checking if getpeername is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3364: checking if getpeername is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3390: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3280,6 +3396,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3298,13 +3417,17 @@ fi ac_safe=getpid; echo $ac_n "checking if getpid is prototyped""... $ac_c" 1>&6 -echo "configure:3302: checking if getpid is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3421: checking if getpid is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3447: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3330,6 +3453,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3348,13 +3474,17 @@ fi ac_safe=getrlimit; echo $ac_n "checking if getrlimit is prototyped""... $ac_c" 1>&6 -echo "configure:3352: checking if getrlimit is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3478: checking if getrlimit is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3504: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3380,6 +3510,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3398,13 +3531,17 @@ fi ac_safe=getsockname; echo $ac_n "checking if getsockname is prototyped""... $ac_c" 1>&6 -echo "configure:3402: checking if getsockname is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3535: checking if getsockname is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3561: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3430,6 +3567,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3448,13 +3588,17 @@ fi ac_safe=gettimeofday; echo $ac_n "checking if gettimeofday is prototyped""... $ac_c" 1>&6 -echo "configure:3452: checking if gettimeofday is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3592: checking if gettimeofday is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3618: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3480,6 +3624,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3498,13 +3645,17 @@ fi ac_safe=htonl; echo $ac_n "checking if htonl is prototyped""... $ac_c" 1>&6 -echo "configure:3502: checking if htonl is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3649: checking if htonl is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3675: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3530,6 +3681,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3548,13 +3702,17 @@ fi ac_safe=htons; echo $ac_n "checking if htons is prototyped""... $ac_c" 1>&6 -echo "configure:3552: checking if htons is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3706: checking if htons is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3732: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3580,6 +3738,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3598,13 +3759,17 @@ fi ac_safe=inet_addr; echo $ac_n "checking if inet_addr is prototyped""... $ac_c" 1>&6 -echo "configure:3602: checking if inet_addr is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3763: checking if inet_addr is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3789: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3630,6 +3795,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3648,13 +3816,17 @@ fi ac_safe=inet_aton; echo $ac_n "checking if inet_aton is prototyped""... $ac_c" 1>&6 -echo "configure:3652: checking if inet_aton is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3820: checking if inet_aton is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3846: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3680,6 +3852,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3698,13 +3873,17 @@ fi ac_safe=inet_ntoa; echo $ac_n "checking if inet_ntoa is prototyped""... $ac_c" 1>&6 -echo "configure:3702: checking if inet_ntoa is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3877: checking if inet_ntoa is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3903: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3730,6 +3909,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3748,13 +3930,17 @@ fi ac_safe=listen; echo $ac_n "checking if listen is prototyped""... $ac_c" 1>&6 -echo "configure:3752: checking if listen is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3934: checking if listen is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3960: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3780,6 +3966,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3798,13 +3987,17 @@ fi ac_safe=ntohl; echo $ac_n "checking if ntohl is prototyped""... $ac_c" 1>&6 -echo "configure:3802: checking if ntohl is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:3991: checking if ntohl is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4017: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3830,6 +4023,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3848,13 +4044,17 @@ fi ac_safe=perror; echo $ac_n "checking if perror is prototyped""... $ac_c" 1>&6 -echo "configure:3852: checking if perror is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4048: checking if perror is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4074: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3880,6 +4080,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3898,13 +4101,17 @@ fi ac_safe=printf; echo $ac_n "checking if printf is prototyped""... $ac_c" 1>&6 -echo "configure:3902: checking if printf is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4105: checking if printf is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4131: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3930,6 +4137,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3948,13 +4158,17 @@ fi ac_safe=qsort; echo $ac_n "checking if qsort is prototyped""... $ac_c" 1>&6 -echo "configure:3952: checking if qsort is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4162: checking if qsort is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4188: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -3980,6 +4194,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -3998,13 +4215,17 @@ fi ac_safe=read; echo $ac_n "checking if read is prototyped""... $ac_c" 1>&6 -echo "configure:4002: checking if read is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4219: checking if read is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4245: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4030,6 +4251,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4048,13 +4272,17 @@ fi ac_safe=remove; echo $ac_n "checking if remove is prototyped""... $ac_c" 1>&6 -echo "configure:4052: checking if remove is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4276: checking if remove is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4302: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4080,6 +4308,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4098,13 +4329,17 @@ fi ac_safe=rewind; echo $ac_n "checking if rewind is prototyped""... $ac_c" 1>&6 -echo "configure:4102: checking if rewind is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4333: checking if rewind is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4359: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4130,6 +4365,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4148,13 +4386,17 @@ fi ac_safe=select; echo $ac_n "checking if select is prototyped""... $ac_c" 1>&6 -echo "configure:4152: checking if select is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4390: checking if select is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4416: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4180,6 +4422,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4198,13 +4443,17 @@ fi ac_safe=setitimer; echo $ac_n "checking if setitimer is prototyped""... $ac_c" 1>&6 -echo "configure:4202: checking if setitimer is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4447: checking if setitimer is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4473: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4230,6 +4479,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4248,13 +4500,17 @@ fi ac_safe=setrlimit; echo $ac_n "checking if setrlimit is prototyped""... $ac_c" 1>&6 -echo "configure:4252: checking if setrlimit is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4504: checking if setrlimit is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4530: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4280,6 +4536,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4298,13 +4557,17 @@ fi ac_safe=setsockopt; echo $ac_n "checking if setsockopt is prototyped""... $ac_c" 1>&6 -echo "configure:4302: checking if setsockopt is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4561: checking if setsockopt is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4587: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4330,6 +4593,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4348,13 +4614,17 @@ fi ac_safe=snprintf; echo $ac_n "checking if snprintf is prototyped""... $ac_c" 1>&6 -echo "configure:4352: checking if snprintf is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4618: checking if snprintf is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4644: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4380,6 +4650,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4398,13 +4671,17 @@ fi ac_safe=socket; echo $ac_n "checking if socket is prototyped""... $ac_c" 1>&6 -echo "configure:4402: checking if socket is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4675: checking if socket is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4701: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4430,6 +4707,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4448,13 +4728,17 @@ fi ac_safe=sprintf; echo $ac_n "checking if sprintf is prototyped""... $ac_c" 1>&6 -echo "configure:4452: checking if sprintf is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4732: checking if sprintf is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4758: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4480,6 +4764,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4498,13 +4785,17 @@ fi ac_safe=sscanf; echo $ac_n "checking if sscanf is prototyped""... $ac_c" 1>&6 -echo "configure:4502: checking if sscanf is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4789: checking if sscanf is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4815: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4530,6 +4821,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4548,13 +4842,17 @@ fi ac_safe=strcasecmp; echo $ac_n "checking if strcasecmp is prototyped""... $ac_c" 1>&6 -echo "configure:4552: checking if strcasecmp is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4846: checking if strcasecmp is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4872: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4580,6 +4878,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4598,13 +4899,17 @@ fi ac_safe=strdup; echo $ac_n "checking if strdup is prototyped""... $ac_c" 1>&6 -echo "configure:4602: checking if strdup is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4903: checking if strdup is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4929: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4630,6 +4935,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4648,13 +4956,17 @@ fi ac_safe=strerror; echo $ac_n "checking if strerror is prototyped""... $ac_c" 1>&6 -echo "configure:4652: checking if strerror is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:4960: checking if strerror is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4986: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4680,6 +4992,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4698,13 +5013,17 @@ fi ac_safe=stricmp; echo $ac_n "checking if stricmp is prototyped""... $ac_c" 1>&6 -echo "configure:4702: checking if stricmp is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5017: checking if stricmp is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5043: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4730,6 +5049,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4748,13 +5070,17 @@ fi ac_safe=strlcpy; echo $ac_n "checking if strlcpy is prototyped""... $ac_c" 1>&6 -echo "configure:4752: checking if strlcpy is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5074: checking if strlcpy is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5100: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4780,6 +5106,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4798,13 +5127,17 @@ fi ac_safe=strncasecmp; echo $ac_n "checking if strncasecmp is prototyped""... $ac_c" 1>&6 -echo "configure:4802: checking if strncasecmp is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5131: checking if strncasecmp is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5157: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4830,6 +5163,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4848,13 +5184,17 @@ fi ac_safe=strnicmp; echo $ac_n "checking if strnicmp is prototyped""... $ac_c" 1>&6 -echo "configure:4852: checking if strnicmp is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5188: checking if strnicmp is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5214: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4880,6 +5220,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4898,13 +5241,17 @@ fi ac_safe=system; echo $ac_n "checking if system is prototyped""... $ac_c" 1>&6 -echo "configure:4902: checking if system is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5245: checking if system is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5271: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4930,6 +5277,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4948,13 +5298,17 @@ fi ac_safe=time; echo $ac_n "checking if time is prototyped""... $ac_c" 1>&6 -echo "configure:4952: checking if time is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5302: checking if time is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5328: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -4980,6 +5334,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -4998,13 +5355,17 @@ fi ac_safe=unlink; echo $ac_n "checking if unlink is prototyped""... $ac_c" 1>&6 -echo "configure:5002: checking if unlink is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5359: checking if unlink is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5385: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -5030,6 +5391,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -5048,13 +5412,17 @@ fi ac_safe=vsnprintf; echo $ac_n "checking if vsnprintf is prototyped""... $ac_c" 1>&6 -echo "configure:5052: checking if vsnprintf is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5416: checking if vsnprintf is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5442: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -5080,6 +5448,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -5098,13 +5469,17 @@ fi ac_safe=write; echo $ac_n "checking if write is prototyped""... $ac_c" 1>&6 -echo "configure:5102: checking if write is prototyped" >&5 -if eval "test \"\${ac_cv_prototype_$ac_safe+set}\" = set"; then +echo "configure:5473: checking if write is prototyped" >&5 +if eval "test \"`echo '$''{'ac_cv_prototype_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5499: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_prototype_$ac_safe=no" else @@ -5130,6 +5505,9 @@ else eval "ac_cv_prototype_$ac_safe=yes" fi rm -f conftest* + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi fi @@ -5235,7 +5613,7 @@ do echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.14.1" + echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; @@ -5495,7 +5873,7 @@ exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files -test "$no_create" = yes || $SHELL $CONFIG_STATUS || exit 1 +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 # echo "Configuration completed. To compile, type: cd src; make" Index: release_notes.3.1.txt =================================================================== RCS file: release_notes.3.1.txt diff -N release_notes.3.1.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ release_notes.3.1.txt 19 Nov 2002 01:58:55 -0000 1.3 @@ -0,0 +1,58 @@ +It's here. It's been a long time coming (9 years and a day in fact[1]), +but it has finally arrived. + +CircleMUD 3.1 is now made officially available for your consumption. + +This is the final[2] release that all of the beta patchlevels over the +last several years have been building towards. + +Some brief history on the CircleMUD 3.x releases: + +After the highly successful release of CircleMUD 2.20, steps were quickly +made towards overhauling the codebase from ground up, extending what could +be done, and removing bugs and loopholes all over the place. This +culminated in an "internal" release of CircleMUD 3.0, which over the +course of a few months led to a release of Patch Level 4 on September 24, +1994, a little less than a year after the 2.20 release. A mere 8+ years +later, many additions, 20 patchlevels, many new bugs, and something called +"documentation", the beta testing period is over, and we have made a full +and proper release! + +The changes are too numerous to list[3], but some highlights of +differences from CircleMUD 2.20[4] include an entirely new world, new shop +structure, several new core members for the development team, and coherent[5] +documentation on the world and core components of the source code. + +Work will begin shortly on the CircleMUD 4.x series, with a release +expected in late 2010[6]. + +Don't run with scissors, but make your way to: + ftp://ftp.circlemud.org/pub/CircleMUD/3.x/ + +Special thanks to all of those on the CircleMUD Mailing List and everyone +who submitted bug reports over the last decade, we couldn't have done it +without you.[7] + +Best Regards, + +The CircleMUD Development Team, 2002 + + Jeremy Elson Since Jul 16, 1993 + Chris Epler Since Late , 1994 + Alex Fletcher Since Feb 23, 1995 + George Greer Since Oct 14, 1997 + Daniel A. Koepke Since Jul 11, 1999 + + +[1] CircleMUD 2.20 was released on November 17, 1993. CircleMUD 3.1 was + released November 18, 2002. +[2] We, the CircleMUD Group, reserve the right to all and any future "final" + CircleMUD releases. +[3] But they're listed in the Changelog file anyhow, just in case you're + really curious. +[4] Everyone compares to their last full version, why can't we? +[5] Well, we'd like to think so at least. +[6] We're hoping to time it with the discovery of a monolith around Jupiter. +[7] And had you not submitted so many damned bug reports, we would have had + this finished almost a decade ago! + Index: cnf/aclocal.m4 =================================================================== RCS file: /home/circledb/.cvs/circle/cnf/aclocal.m4,v retrieving revision 1.6 retrieving revision 1.7 diff -u -p -r1.6 -r1.7 --- cnf/aclocal.m4 20 Mar 2002 22:23:11 -0000 1.6 +++ cnf/aclocal.m4 13 Nov 2002 20:17:05 -0000 1.7 @@ -4,6 +4,10 @@ ac_safe=translit($1, './+-', '__p_'); AC_MSG_CHECKING([if $1 is prototyped]) AC_CACHE_VAL(ac_cv_prototype_$ac_safe, [# + if test $ac_cv_gcc_fnb = yes; then + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + fi AC_TRY_COMPILE([ #define NO_LIBRARY_PROTOTYPES #define __COMM_C__ @@ -16,6 +20,9 @@ void $1(int a, char b, int c, char d, in ],dnl , eval "ac_cv_prototype_$ac_safe=no",eval "ac_cv_prototype_$ac_safe=yes") + if test $ac_cv_gcc_fnb = yes; then + CFLAGS=$OLDCFLAGS + fi ]) if eval "test \"`echo '$ac_cv_prototype_'$ac_safe`\" = yes"; then Index: cnf/configure.in =================================================================== RCS file: /home/circledb/.cvs/circle/cnf/configure.in,v retrieving revision 1.16 retrieving revision 1.17 diff -u -p -r1.16 -r1.17 --- cnf/configure.in 16 Apr 2002 02:23:06 -0000 1.16 +++ cnf/configure.in 13 Nov 2002 20:17:05 -0000 1.17 @@ -42,6 +42,15 @@ if test $ac_cv_prog_gcc = yes; then CFLAGS=$OLDCFLAGS ]) + dnl If Determine if gcc can accept -fno-builtin + AC_CACHE_CHECK(whether ${CC-cc} accepts -fno-builtin, ac_cv_gcc_fnb, + [ + OLDCFLAGS=$CFLAGS + CFLAGS="$CFLAGS -fno-builtin" + AC_TRY_COMPILE(, , ac_cv_gcc_fnb=yes, ac_cv_gcc_fnb=no) + CFLAGS=$OLDCFLAGS + ]) + dnl If gcc -Wall gives no warnings with isascii(), use "-Wall"; dnl Otherwise, if gcc -Wall gives isascii warnings: dnl If we can use -Wno-char-subscripts, use "-Wall -Wno-char-subscripts" Index: doc/FAQ.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/FAQ.pdf,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 Binary files /tmp/cvsmyx983 and /tmp/cvsqq8djD differ Index: doc/README-NOW =================================================================== RCS file: doc/README-NOW diff -N doc/README-NOW --- doc/README-NOW 6 Feb 1996 20:24:02 -0000 1.1.1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,9 +0,0 @@ -3/9/95 JE - -These files contain some of the PRELIMINARY DOCUMENTATION for CircleMUD 3.0. -They are not yet complete!! Do not write mail saying that your coding.doc -has been mysteriously truncated (believe me when I tell you I've gotten 50 -such letters already) -- it just hasn't all been written yet. - -running.doc and building.doc are both complete, however, so feel free to -send me any critiques you may have of it. Index: doc/README.AMIGA =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.AMIGA,v retrieving revision 1.3 retrieving revision 1.4 diff -u -p -r1.3 -r1.4 --- doc/README.AMIGA 6 Sep 2002 12:17:52 -0000 1.3 +++ doc/README.AMIGA 18 Nov 2002 22:12:25 -0000 1.4 @@ -1,4 +1,4 @@ - Compiling CircleMUD version 3.0 on the Amiga + Compiling CircleMUD on the Amiga Written by Damian Jurzysta Compiling CircleMUD on the Amiga is basically the same as compiling it using Index: doc/README.ARC =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.ARC,v retrieving revision 1.2 retrieving revision 1.3 diff -u -p -r1.2 -r1.3 --- doc/README.ARC 1 Jul 1998 01:04:27 -0000 1.2 +++ doc/README.ARC 18 Nov 2002 22:12:25 -0000 1.3 @@ -1,5 +1,4 @@ - Compiling CircleMUD Version 3.0 - under RiscOS + Compiling CircleMUD under RiscOS by Gareth Duncan (garethduncan@argonet.co.uk) You will need: Index: doc/README.BORLAND =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.BORLAND,v retrieving revision 1.3 retrieving revision 1.4 diff -u -p -r1.3 -r1.4 --- doc/README.BORLAND 24 May 2001 12:37:10 -0000 1.3 +++ doc/README.BORLAND 18 Nov 2002 22:12:25 -0000 1.4 @@ -1,4 +1,4 @@ - Compiling CircleMUD Version 3.0 + Compiling CircleMUD under Microsoft Windows 95 or Windows NT using Borland C++ Index: doc/README.CYGWIN =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.CYGWIN,v retrieving revision 1.7 retrieving revision 1.8 diff -u -p -r1.7 -r1.8 --- doc/README.CYGWIN 16 Jan 2002 03:11:09 -0000 1.7 +++ doc/README.CYGWIN 18 Nov 2002 22:12:25 -0000 1.8 @@ -1,9 +1,8 @@ - Compiling CircleMUD Version 3.0 - under Microsoft Windows 95 or Windows NT + Compiling CircleMUD under Microsoft Windows 95 or Windows NT using CygWin (formerly GNU-Win32) by David Goldstein (goldstei@cs.sunysb.edu) -CircleMUD 3.0 compiles under version b19 or later of Cygnus Solutions' +CircleMUD compiles under version b19 or later of Cygnus Solutions' GNU-Win32 environment without needing any special modifications. This free pseudo-Unix environment for Windows 95 and NT includes the "bash" shell, "gcc" family of compilers, and a full set of programs and libraries for Index: doc/README.MSVC4 =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.MSVC4,v retrieving revision 1.2 retrieving revision 1.3 diff -u -p -r1.2 -r1.3 --- doc/README.MSVC4 6 Sep 2002 12:17:52 -0000 1.2 +++ doc/README.MSVC4 18 Nov 2002 22:12:25 -0000 1.3 @@ -1,9 +1,8 @@ - Compiling CircleMUD Version 3.0 - using Microsoft Visual C++ v4.x + Compiling CircleMUD using Microsoft Visual C++ v4.x by Jeremy Elson (jelson@circlemud.org) For help, write to help@circlemud.org -CircleMUD 3.0 compiles relatively easily under Windows 95 and NT using +CircleMUD compiles relatively easily under Windows 95 and NT using the Microsoft Visual C++ compiler version 4.x. These instructions won't work for any compiler except for MSVC++ 4.0; if you have a different compiler, take a look at the main README.WIN file for instructions. Index: doc/README.MSVC5 =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.MSVC5,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/README.MSVC5 1 Jul 1998 19:06:20 -0000 1.1 +++ doc/README.MSVC5 18 Nov 2002 22:12:25 -0000 1.2 @@ -1,5 +1,4 @@ - Compiling CircleMUD Version 3.0 - under Microsoft Windows 95 or Windows NT + Compiling CircleMUD under Microsoft Windows 95 or Windows NT using Microsoft Visual C++ v5.x Index: doc/README.MSVC6 =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.MSVC6,v retrieving revision 1.2 retrieving revision 1.3 diff -u -p -r1.2 -r1.3 --- doc/README.MSVC6 12 Sep 1999 05:26:19 -0000 1.2 +++ doc/README.MSVC6 18 Nov 2002 22:12:25 -0000 1.3 @@ -1,5 +1,4 @@ - Compiling CircleMUD Version 3.0 - under Microsoft Windows 95 + Compiling CircleMUD under Microsoft Windows 95 using Microsoft Visual C++ 6.0 w/SP2 Index: doc/README.OS2 =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.OS2,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/README.OS2 29 Jun 1998 14:43:09 -0000 1.1 +++ doc/README.OS2 18 Nov 2002 22:12:25 -0000 1.2 @@ -1,70 +1,70 @@ - Compiling CircleMUD Version 3.0 - under OS/2 Warp Connect v3.0 or 2.1 - by David Carver - - -To compile CircleMUD 3.0 under OS/2, you must have the following: -All needed files can be found at the hobbes.nmsu.edu FTP site. - - -* OS/2 Warp Connect Version 3.0, or OS/2 Version 2.1 with TCP/IP installed. - You should have at least 8 megs of memory. (Circle runs quite well on an - 8 meg machine). - -* An HPFS formatted drive. CircleMUD needs to be uncompressed on an HPFS - drive because it uses long filenames. - -* The EMX09b runtime and compilation systems. These are free and - can be downloaded by anonymous FTP at hobbes.nmsu.edu in os2/unix/emx09b - -* The OS/2 port of GNU's GCC compiler. This can also be found at - hobbes.nmsu.edu in os2/unix/emx09b. Please make sure you have the most - recent version of the GCC compiler for OS/2, as files needed by CircleMUD - were not included in earlier versions of GCC for OS/2. The current version - is 2.7.0 - -* GNU's TAR and GZIP programs to decompress the necessary files. Again - these can be found at hobbes.nmsu.edu in os2/unix. - **** You only need this if you plan on getting some of the various - **** addons for Circle that others have coded. - -* A MAKE program. Either the GNU Make, or IBM's NMAKE should work. You - can obtain the NMAKE from either IBM's Developers kit or from - hobbes.nmsu.edu in os2/16dev. - - -Installation: - -*** IMPORTANT -*** -*** You must have EMX and GCC installed and the directories in your -*** PATH and LIBPATH statements in your CONFIG.SYS. Please read the -*** EMX installation instructions included with that package for more -*** information on how to install both EMX and GCC. - -Download the ZIP archive of Circle and use your favorite UNZip utility -to extract it. - -After you have uncompressed the files, switch to the directory that has -the CircleMUD files in it, and then to the SRC subdirectory. Rename -the following files: - -Rename 'conf.h.os2' to 'conf.h'. -Delete the old 'makefile', and rename 'makefile.os2' to 'makefile'. - -To compile the MUD type the following at an OS/2 command line: - -NMAKE /i - -CircleMUD will be compiled and the executable will be put in your current -directory. Copy the CIRCLE.EXE file to the circle30\bin directory. Then -follow the CircleMUD instructions in README on how to start up the MUD. - -NOTE: General questions about CircleMUD can be addressed to the author, -Jeremy Elson, at jelson@circlemud.org. However, all questions which -specifically deal with the OS/2 port of Circle should go to my address, -listed below. - -David Carver -dcarver@cougar.colstate.cc.oh.us -dcarver@iwaynet.net + Compiling CircleMUD + under OS/2 Warp Connect v3.0 or 2.1 + by David Carver + + +To compile CircleMUD under OS/2, you must have the following: +All needed files can be found at the hobbes.nmsu.edu FTP site. + + +* OS/2 Warp Connect Version 3.0, or OS/2 Version 2.1 with TCP/IP installed. + You should have at least 8 megs of memory. (Circle runs quite well on an + 8 meg machine). + +* An HPFS formatted drive. CircleMUD needs to be uncompressed on an HPFS + drive because it uses long filenames. + +* The EMX09b runtime and compilation systems. These are free and + can be downloaded by anonymous FTP at hobbes.nmsu.edu in os2/unix/emx09b + +* The OS/2 port of GNU's GCC compiler. This can also be found at + hobbes.nmsu.edu in os2/unix/emx09b. Please make sure you have the most + recent version of the GCC compiler for OS/2, as files needed by CircleMUD + were not included in earlier versions of GCC for OS/2. The current version + is 2.7.0 + +* GNU's TAR and GZIP programs to decompress the necessary files. Again + these can be found at hobbes.nmsu.edu in os2/unix. + **** You only need this if you plan on getting some of the various + **** addons for Circle that others have coded. + +* A MAKE program. Either the GNU Make, or IBM's NMAKE should work. You + can obtain the NMAKE from either IBM's Developers kit or from + hobbes.nmsu.edu in os2/16dev. + + +Installation: + +*** IMPORTANT +*** +*** You must have EMX and GCC installed and the directories in your +*** PATH and LIBPATH statements in your CONFIG.SYS. Please read the +*** EMX installation instructions included with that package for more +*** information on how to install both EMX and GCC. + +Download the ZIP archive of Circle and use your favorite UNZip utility +to extract it. + +After you have uncompressed the files, switch to the directory that has +the CircleMUD files in it, and then to the SRC subdirectory. Rename +the following files: + +Rename 'conf.h.os2' to 'conf.h'. +Delete the old 'makefile', and rename 'makefile.os2' to 'makefile'. + +To compile the MUD type the following at an OS/2 command line: + +NMAKE /i + +CircleMUD will be compiled and the executable will be put in your current +directory. Copy the CIRCLE.EXE file to the circle30\bin directory. Then +follow the CircleMUD instructions in README on how to start up the MUD. + +NOTE: General questions about CircleMUD can be addressed to the author, +Jeremy Elson, at jelson@circlemud.org. However, all questions which +specifically deal with the OS/2 port of Circle should go to my address, +listed below. + +David Carver +dcarver@cougar.colstate.cc.oh.us +dcarver@iwaynet.net Index: doc/README.UNIX =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.UNIX,v retrieving revision 1.3 retrieving revision 1.4 diff -u -p -r1.3 -r1.4 --- doc/README.UNIX 6 Sep 2002 12:17:52 -0000 1.3 +++ doc/README.UNIX 18 Nov 2002 22:12:25 -0000 1.4 @@ -1,4 +1,4 @@ - Compiling CircleMUD Version 3.0 under UNIX + Compiling CircleMUD under UNIX by Jeremy Elson (jelson@circlemud.org) For help, write to help@circlemud.org Index: doc/README.VMS =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.VMS,v retrieving revision 1.5 retrieving revision 1.6 diff -u -p -r1.5 -r1.6 --- doc/README.VMS 5 Mar 2001 12:45:29 -0000 1.5 +++ doc/README.VMS 18 Nov 2002 22:12:25 -0000 1.6 @@ -19,8 +19,7 @@ To build this, you need the following: emulation I would suggest getting a copy of Multinet though the OpenVMS hobbyist program at http://www.montagar.com/hobbyist. - .3) A copy of the CircleMUD v3.00 beta patch level 16 distribution file - or later. + .3) A copy of the CircleMUD distribution file. This can be found at ftp://ftp.circlemud.org/3.x/ Index: doc/README.WATCOM =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.WATCOM,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/README.WATCOM 1 Jul 1998 19:06:20 -0000 1.1 +++ doc/README.WATCOM 18 Nov 2002 22:12:25 -0000 1.2 @@ -1,4 +1,4 @@ - Compiling CircleMUD Version 3.0 + Compiling CircleMUD under Microsoft Windows 95 or Windows NT using Watcom v.11 Index: doc/README.WIN =================================================================== RCS file: /home/circledb/.cvs/circle/doc/README.WIN,v retrieving revision 1.7 retrieving revision 1.8 diff -u -p -r1.7 -r1.8 --- doc/README.WIN 9 May 2001 12:44:04 -0000 1.7 +++ doc/README.WIN 18 Nov 2002 22:12:25 -0000 1.8 @@ -1,4 +1,4 @@ - Compiling CircleMUD Version 3.0 + Compiling CircleMUD under Microsoft Windows 95 and NT by Jeremy Elson (jelson@circlemud.org) For help, write to help@circlemud.org Index: doc/act.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/act.pdf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 Binary files /tmp/cvsEkCP0n and /tmp/cvsPbO0cX differ Index: doc/admin.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/admin.pdf,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 Binary files /tmp/cvsgeykpw and /tmp/cvstNiJC5 differ Index: doc/building.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/building.pdf,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 Binary files /tmp/cvsyqHnQE and /tmp/cvstI6Y4d differ Index: doc/coding.doc =================================================================== RCS file: doc/coding.doc diff -N doc/coding.doc --- doc/coding.doc 4 Oct 2002 03:34:42 -0000 1.16 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,1999 +0,0 @@ -/* ************************************************************************ -* File: coding.doc Part of CircleMUD * -* * -* All rights reserved. See license.doc for complete information. * -* * -* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * -* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * -************************************************************************ */ - - HOW TO CONVERT YOUR IDEAS INTO REALITY - A CircleMUD Coding Manual by Jeremy Elson - and the rest of the CircleMUD Group - -Summary: - A guide to writing C code for use with CircleMUD. Includes a -description of commonly used functions, tips on how to add new commands and -spells, and other commonly asked coding questions. Good familiarity with -both C and UNIX is assumed, although system-level UNIX C programming skill -not required. - Area-building not covered (see building.doc). - -Intended Audience: - Coders only. - -Table of Contents ---------------------------------------------------------------------------- - -1. Introduction - -2. Overview and Coding Basics - 2.1. An Internet Server Tutorial - 2.2. The Way Things Work -- Overview - 2.3. CircleMUD's Global Variables - 2.4. Frequently Used Functions - -3. Adding Features - 3.1. Adding Commands - 3.2. Adding Socials - 3.3. Adding Spells - 3.4. Adding Skills - 3.5. Adding Classes - 3.6. Adding Levels - 3.7. Adding Color - -4. Writing Special Procedures - 4.1. Overview of Special Procedures - 4.2. Pulsed vs. Command-Drive Special Procedures - 4.3. Relating Special Procedures to Objects, Mobiles, and Rooms - 4.4. The Special Procedure Function Header - 4.5. The Special Procedure Return Value - -Note: Section 4 written by Luis Pedro Passos Carvalho - ---------------------------------------------------------------------------- - - -1. Introduction - - When DikuMUD was first released in 1990, the authors were rightly more -concerned with getting their product released than with little cosmetic -details. Between writing 25,000 lines of C code and building the entire -DikuMUD world, complete with objects, rooms, and monsters, it's understandable -that making the code portable or clean was not at the top of the list of their -priorities. Most DikuMUD distributions were not portable and had a number of -bad bugs and even syntax errors which prevented the code from compiling at -all. If a potential MUD implementor wanted to run a Diku, an excellent -knowledge of C was necessary, because the MUD simply wouldn't run otherwise. - - Now the situation is much different. With the proliferation of -user-friendly code bases such as Merc and Circle, any Average Joe can just -type "make" and inflict yet another MUD on the world. Therefore, the number -of truly unique MUDs as a fraction of the total is dropping drastically -because coding experience is no longer a prerequisite to being able to put a -MUD up on the 'Net. Some people may tell you that you don't need to know how -to code in order to run a MUD -- don't believe them. Those people are wrong. - - If you want your MUD to succeed and flourish, you'll have to know how -to code in C. Otherwise, your MUD will be exactly like every other MUD out -there. You're not the only person who knows how to type "make"! Although the -quality and originality of your areas is also very important, it's the code -that transforms the areas from lifeless text files into a living, breathing -virtual world. If you don't know how to code, you won't be able to add new -features, respond to requests of your players, add new world flags for your -area builders, or even fix the simplest of bugs. Running a MUD without -knowing how to code is certainly a recipe for disaster. If you're a great -game-player and have some terrific ideas about how a MUD should work, but -don't know how to code, you should either learn or find a good coder who can -join your team. Don't assume that you can get away with running a MUD without -knowing C -- you can't. Not for very long, anyway. - - This document won't teach you how to program in C; you'll have to learn -that on your own. Instead, it will try to familiarize you with the way -Circle's code is structured so that you can put your C skills to good use. -Even for the best programmers, it takes a while to "get into" a program and -feel comfortable enough with the way it works to start modifying it. -Hopefully, by reading this manual, your breaking-in period for getting to know -Circle will be minimized. - - Circle consists of close to 30,000 lines of moderately dense C code, so -you shouldn't expect familiarity to come overnight. The best way to learn is -to DO. Get your hands dirty! Don't be afraid to tinker with things. Start -small by modifying existing functions. Then, work your way up to creating new -functions by copying old ones. Eventually you'll be able to write completely -original functions, and even tear some of Circle's native functions out as you -realize completely new ways of implementing them! But you should learn to -walk before you try to run. - - Most of all, try to remember that coding for a MUD should be fun. It -can sometimes be easy to lose site of the ultimate goal of personal enjoyment -that MUDs are supposed to provide, particularly when they start to get crushed -under the weight of their own politics or the egos of their administrators. -If you enjoy coding, but find yourself spending more time on politics than you -are on code, don't be afraid to restructure your MUD or even remove yourself -as Imp to a lower wizard position which requires less politics. - - People often ask me why I do so much work on CircleMUD. They want to -know why I spend so much time writing code *only* for the purpose of letting -other people use it, since I don't actually run a MUD myself. After reading -the preceding paragraph, the answer to that question should be clear. I've -spent considerable time coding for on-line MUDs in the past, but after a while -it just wasn't fun any more. I eventually found myself doing nothing but -working politically and doing virtually no coding at all. Eventually, I even -lost the will to write code completely. By quitting from my various God -positions on every MUD I was of which I was a member, and concentrating on my -public Circle releases, I have the luxury of enjoying MUD coding in its purest -form: all code, no politics. Well, almost none, anyway -- my past still comes -back to haunt me now and then. :) - - A final thought: nothing will turn potential players away from your MUD -more than logging in and finding that it's exactly like half the other -CircleMUDs out there. Strive to show the world something new and unique. And -may the source be with you. - - - -2. Overview and Coding Basics - - Before getting down to the details of learning how to write code, we -will first examine generally what a MUD is and what it does, to give you an -overview of what type of program you're working with. - - The first section, "An Internet Server Tutorial", describes how Internet -servers such as CircleMUD work. It contains interesting background material -if you'd like a deeper understanding of how the MUD actually interacts with -the Internet and the computer on which it runs, but little practical coding -advice. So, if you're reading this document purely to learn how to write MUD -code, you should skip to the second section. - -2.1. An Internet Server Tutorial - - An Internet "server" is a program which provides some service to -Internet users (called "clients"). There are many different types of servers -on the Internet. FTP servers allow you to transfer files between a remote -computer and your own. Telnet servers allow you to connect to remote -machines. News servers allow you to read USENET news. Similarly, CircleMUD -is a server which allows you to play a game. - - However, MUDs such as CircleMUD differ from most Internet servers in -several very important ways. When ten different people connect to CircleMUD, -they can all interact with one another. CircleMUD -- a single program -- must -be aware of many users at the same time. On the other hand, most other -Internet servers such as FTP servers are written to only be aware of *one* -user at a time. If more than one user wants to use an FTP server -simultaneously, the operating system runs two copies of the server: one to -handle each user. Each individual copy of the FTP server is not aware of -anything but the single user it has been assigned to serve. - - This approach of making one copy of the program per user works quite -well with an FTP server because all the users of an FTP server do not need to -interact with one another. However, this approach does not work well at all -with MUDs, because it makes the task of allowing users to communicate and -interact with each other quite difficult. - - In addition, most simple Internet servers do not actually contain any -network code -- the Internet superserver (inetd) contains most of the code to -perform the network magic, allowing the individual servers such as FTP and -telnet to be network-unaware for the most part, simply reading from standard -input and writing to standard output as if a user at a normal terminal was -using the program. The Internet superserver is responsible for setting up -standard input and standard output so that they are actually network sockets -and not a text terminal. - - To sum up, a MUD such as CircleMUD does not have the luxury of being -able to handle multiple users by allowing the operating system to make many -copies of the MUD. The MUD itself must be capable of handling many users. -The MUD also doesn't have the luxury of allowing a pre-written program such -as inetd to set up its network connections. The MUD itself is responsible for -setting up and keeping track of all of its own network connections, as well -as splitting its time evenly among all of its players. The MUD cannot stop -and wait for a player to type something -- if it stops and waits for that -player, the MUD will appear to have frozen from the point of view of all the -other players! - - Let's make this idea more concrete with an example. Imagine that your -first programming assignment in a C class is to write a simple calculator that -gets two numbers from a user as input, multiplies them together, and then -prints the product on the screen as output. Your program would probably be -quite simple: it would prompt the user for the two numbers, then stop and wait -while the user types the numbers in. - - Now, imagine that your project is to write a program that lets 10 people -simultaneously connect to your calculator and multiply their own numbers -together. Forget for a moment the problem of how to write the network code -that allows people to connect to your program remotely. There is a more -fundamental problem here: your original strategy of stopping and waiting for -the user to type input won't work any more. With one user, that worked fine. -But what will happen with 10 users? - - Let's say your program stops and waits for the first user to type -something. Now, what happens if the second user types something in the -meantime? The program will not respond to the second user because it is still -waiting for a response from the first user. Your simple calculator has -suddenly become much more complex -- now, it must constantly cycle through all -users, asking the operating system if any one of them have typed something, -without ever stopping to wait for a single user. When input comes in from any -one of the users, your program must immediately process it and move on to the -next user. - - Let's say that you've written a program which does the cycling among -users described in the previous paragraph. Now, imagine that the operating -system tells you that User 4 has just typed the number 12. You might be able -to see the second problem: what does that 12 mean? Is 12 the first or second -multiplicand for your calculator? Should you immediately multiply the 12 with -some other number, or store it and wait for another number to multiply by 12? - - Your simple calculator has become more complicated again! Now, in -addition to cycling through all users to check if any have typed anything, you -must remember the STATE each user is in. In other words, each user might -start out in a state called "Waiting for First Number." If a user types a -number while she's in the "Waiting for First Number" state, you'd store her -number somewhere and move her into the "Waiting for Second Number" state. If -she types a number while in the "Waiting for Second Number" state, you'd -retrieve the first number from memory, multiply it by the number just typed, -and print the result. Of course, each user can be in a different state -- -there is no global state shared by all users. - - Now, you might be able to see how this calculator example relates to -CircleMUD. Let's say that the MUD receives the string, "Sleep" from a user. -What should Circle do with this string? Maybe the user is trying to log in, -typing her name which happens to be "Sleep". Maybe the user is typing in her -password. Maybe the user is already logged in, and is trying to go to sleep! -Just like with our calculator, the MUD knows how to interpret data it receives -from users by examining the users' state. - - You can see a list of all possible players' states in structs.h (they -all start with "CON_"). All users are put into the CON_GET_NAME state when -they first connect to the MUD. CON_GET_NAME simply means that the MUD is -waiting for the user to type her name, at the "By what name do you wish to be -known?" prompt. The normal state that most players are in most of the time -is the CON_PLAYING state, which indicates that they have already logged in and -are playing normally. - - Now, let's go back to our previous example and trace exactly what -happens when you type "Sleep". First, you type "Sleep." Then, your computer -sends the string "Sleep" over the Internet to the computer on which the MUD -is running. Within one tenth of a second, Circle checks with the operating -system to see if any of its users have typed anything. When Circle gets to -you, it asks the operating system, "Has this user typed anything?". Since you -typed "Sleep", the operating system will respond, "Yes!". The MUD will then -ask the operating system to deliver the message and will read your message of -"Sleep". (All the magic of talking to the operating system and checking to -see whether or not you've typed anything happens in comm.c.) - - So, now that the MUD now knows that you've typed "Sleep", it has to -decide which of several function in interpreter.c should get control next. -This depends on what state you're in. If you're in the normal PLAYING state, -it will pass control to a function called command_interpreter, which will -interpret "Sleep" as a normal command and put you to sleep. If you're in any -other state, control goes to a function called nanny, which is responsible for -handling all sockets in any state other than PLAYING. nanny checks what state -you're in and acts accordingly. For example, if you're in the GET_NAME state, -nanny activates the code to check whether or not "Sleep" is the name of a -known player (in which case it puts you into the state asking for your -password), or a new player (in which case it'll ask you the question, "Did I -get that right, Sleep?".) - - In a nutshell, that's how CircleMUD interacts with the Internet. If you -don't understand all the details, don't worry -- it's not necessary to -understand things on this level to be a successful MUD coder. If you are -interested, however, there are some excellent references you can read for more -information: - "Internetworking with TCP/IP" by Douglas Comer. The canonical text -describing Internet protocols; comes in three volumes. Volume 1 gives an -excellent description of how Internet protocols, error handling, routing, and -nameservice works. Volume 3 describes specifics of writing Internet Servers -in C. (Volume 2 describes how Internet protocols are implemented by operating -systems and is not as apropos to this discussion.) - "Advanced Programming in the UNIX Environment" by Richard Stevens. An -excellent UNIX reference for the serious system programmer. Describes POSIX -quite well -- worth its weight in gold for anyone trying to write portable -UNIX applications. Sections on signal semantics and non-blocking I/O -particularly apropos to Internet servers. - "UNIX Network Programming" by Richard Stevens. Similar to Volume 3 of -Comer's series, but goes into more detail in several areas, and offers more -practical code examples. - - -2.2. The Way Things Work -- Overview - -2.2.1. Boot Phase - - CircleMUD is a complex system of code, data files, and external -input all interacting in fun, unexpected ways. As with any program, it -doesn't just spring into existence ready to play, but must cull information -from the administrator and the system itself to determine how it should -begin. - - The first action by CircleMUD on startup is to check for the -existence of any command-line parameters, as seen in the main() function. -These can have radical impact on CircleMUD's operation so it must check -them before any other action. For example, CircleMUD might be given the -'-d' parameter, specifying an alternate library directory, so it cannot have -done any processing on data files prior to the command-line reading. - - After finishing the immediate input, the next step is to be able to -communicate to the outside world. The communication may be either the -"standard error" file descriptor or a file, depending on the command-line -options and whichever CircleMUD succeeds in opening. - - From here there are two possible branches depending on -administrator input. If "Syntax Check" mode is enabled, then we load only -the world. Otherwise, we start initializing the game in preparation for -loading the world and accepting players. Since syntax checking is a subset -of the normal startup phase, this document shall follow only the most -common action of a non-syntax-check boot. - - A few minor items precede the loading of the world: initializing -the random number generator, creating the '.killscript' file, finding (or -guessing) the maximum number of players the operating system will allow -simultaneously, and opening the file descriptor later to be used to accept -connections. This early opening of the "mother" file descriptor is why -there is a period of time during startup where a player connection will be -accepted but not receive a login prompt. CircleMUD does not check for -connection attempts while it loads the world database but the operating -system will complete the connection anyway and post notification to be seen -later. - - The world loading starts by reading in the MUD date and a few -simple text files for player reference. If the date file cannot be loaded, -then a default date is provided for the calculations. After randomly -generating the weather, in the date function, the following user text files -are loaded: news, credits, mortal message of the day, immortal message of -the day, help default message screen, general MUD info, wizard list, -immortal list, policies, immortal handbook, background story, and login -greeting screen. These files are reproduced verbatim by various user -commands and exist for the players and/or administrators to read. The MUD -doesn't interpret these in any way. - - Next, the spell definitions are loaded for player use. The -spello() function gives such important information as casting cost, valid -targets (area, self, etc.), spell type, valid casting positions (sitting, -standing, etc.), spell name, and wear off message. Any skill or spell that -isn't set up via mag_assign_spells() will not be usable even if appropriate -code exists elsewhere that would make it have an effect. Any spell defined -here that does not have appropriate code elsewhere to handle it will do -nothing when used. - - As far as the game world, the zones must be loaded first to define -the structure of the rest of the objects. The 'lib/world/zon/index' file -is first consulted for the list of zone files that are requested to load. -The 'index.mini' file is used in the event mini-MUD mode was requested -earlier on the command line. Each zone file is read in order to pull in -the name, description, reset time, room range, and zone commands. Any -error on loading will result in the MUD aborting startup. The rooms are -read next from 'lib/world/wld/index' in the same manner as the zones, with -the added restriction that each room must fall within the ranges defined by -the previously-loaded zones. This restriction ensures the code can access -the zone record of a room without worrying about any rooms not having an -associated zone. - - The rooms, as loaded, contain virtual numbers of the rooms they are -supposed to exit to. It's slow to do virtual->real number translation -while the MUD is running so all room exits are replaced by their real -number equivalents during startup. Then the pre-defined starting locations -for mortals, immortals, and frozen characters are checked to make sure they -exist. If the mortal start room does not exist, the MUD aborts with an -error. A missing immortal or frozen start room is redirected to the mortal -start room to allow booting to continue. The mortal start room must exist -in a room file loaded by 'lib/world/wld/index.mini' file for mini-MUD mode -to work. - - Mobiles from 'lib/world/mob/index' and objects from -'lib/world/obj/index' are loaded afterward. Mobile and object virtual -numbers need not correspond to the zone number ranges as rooms do but it is -encouraged. There are various sanity checks done to mobiles and objects -that may be printed during startup. Any warnings issued should be fixed -but should not adversely affect the MUD itself. - - In the same manner as the room number virtual->real translation, -the zone reset information is also translated. The zone reset structure -contains a variety of different records so it takes special care to find -the appropriate numbers to translate from virtual->real. Any virtual -numbers that cannot be resolved result in that zone command being disabled. -Such entries have their type set to '*' to avoid the error in the future. - - If special procedures are enabled, as they usually are, the shops -are loaded from 'lib/world/shp/index' last. Contrary to the rooms and -zones, the shops contain lists of virtual numbers to sell so any errors -will only show up when attempting to use the shop. The charisma of a -shopkeeper is important, as well as the buy/sell rates, as they define what -prices the players will pay when shopping. - - The entire help database for CircleMUD is loaded into memory after -the world has been loaded. This should be ~100kB with the stock CircleMUD -help files, but the extra memory used saves the MUD from having to -manipulate the help files to find the appropriate entries after the boot. -Even though the help index is stored by keyword, any entry having multiple -keywords is only stored once for each set. - - An index of the player file is built to allow random access to each -player as attempt to connect or save. The index stores the player's name, -to search by for login, and their ID number, for the mail system to search -by. The array index is their position in the player file, used for loading -and saving. - - Fight messages and socials loaded next are placed by line in their -appropriate categories. The messages and socials themselves aren't -interpreted beyond their placement but they'll be used extensively in the -game. Spells defined earlier from mag_assign_spells() get their battle -messages from this file. Defaults are provided for the battle messages if -none is defined. All socials loaded require a matching entry in the global -command table or they will not be accessible by the players. - - Special procedures must be associated with their now-loaded object -so they're processed now. A virtual number that cannot be resolved for the -special procedure elicits a warning message on startup but a missing -special procedure function will cause a compiler error. Shopkeepers are -assigned via assign_the_shopkeepers() instead of the standard -assign_mobiles() so they can be automatically handled as a result of the -shop files loaded earlier. - - Since the spells are skills were defined earlier, they can then be -assigned to each class upon a certain level. The spells and skills given -to the various classes only depend upon a SPELL_ or SKILL_ definition so -the assignment doesn't need to care if it is a generically handled spell or -a custom implemented skill. The spells and skills may be assigned per the -whims of the administrator based on their view of the appropriate classes. - - The command and spell tables need sorted for special circumstances. -In the case of the command table, it is for the 'commands' input which -displays all known commands for that player's level. The spell table is -sorted for the 'practice' command for easier visual searching by the -player. Neither are critical to the MUD's operation but exist for the -players' benefit. - - The CircleMUD mail system keeps a binary file of all MUD message -sent. It requires an index be built on startup to keep track of which -blocks are free and which blocks have mail messages yet to be delivered. -It is also important for the code to check the mail file to make sure it -hasn't been corrupted somehow. A report on the number of messages present -in the system is printed when finished. - - The stupid-people prevention code of site banning and invalid name -rejection comes next. The site ban code loads a text file list of all -sites that have been deemed unworthy to connect to the MUD. Invalid name -rejection loads a list of substrings that must not appear in any -character's name that is being created. The invalid name list is limited -in the number of entries it may hold but any amount of sites may be banned. -The length of each banned site name is limited, however. - - After deleting any expired rent files, the house code loads up any -abodes defined. It must make sure the rooms still exist and the owner is -still in the game before setting up the house, atrium, and guest list. -Houses aren't loaded in mini-MUD mode since most of the rooms will likely -not exist. - - The final step of the world startup resets every zone. This -populates the world with mobiles, the mobiles with objects, and places -other objects that should be on the ground. From here, all zone timers are -started and will continue to reset (or not) depending on their settings and -the number of people in the zone. The time is recorded after the zone -reset to provide a display of the amount of time the MUD has been running. - - Once the world has finished being loaded, CircleMUD tells the -operating system what sort of signals it wants to receive and which to -ignore. It doesn't want to receive a SIGPIPE, which would abort the -program whenever it tried to write to a player who abruptly disconnected. -The user-defined signals (Unix) SIGUSR1 and SIGUSR2 are set to re-read the -wizard list file and unrestrict the game, respectively. SIGUSR1 is sent by -'autowiz' whenever it finishes writing the file. SIGUSR2 may be sent by -the administrators, using 'kill -USR2 pid-of-mud`, if accidentally banning -themselves from their own MUD. A 3-minute timer signal prevents the MUD -from being stuck in an infinite loop forever. The common shutdown signals -of SIGHUP (Unix), SIGTERM, and SIGINT are mapped to a function that prints -their reception and then quits the program. The children signal, SIGCHLD, -is set up to remove finished 'autowiz' instances. - - From here, the '.killscript' file is removed since if we've made it -this far, we can start successfully. The only thing left now is to enter -the interactive phase in game_loop(), unless the "Syntax Check" option is -enabled. - - -2.2.2. Interactive Phase - - Everything that ever happens while the MUD is interactively -processing players occurs as a descendant of game_loop(). It is responsible -for all network I/O, periodic tasks, and executing player actions. -Consequently, game_loop() has the most concentration of newbie-eating code -in the code base. Care should be taken to fully understand the network I/O -infrastructure before trying to modify it. - - Each second of the game is divided into pulses, or points in time -that network I/O is processed and commands run. This works to limit the -number of possible commands the player can enter per second, such as -speed-walking. If the game falls behind schedule, it will continuously -process the pulses until it has caught up with where it is supposed to be. -If over 30 seconds have passed, only 30 seconds are processed as it would -be computationally expensive to do them all. If there isn't anyone -connected to the game at all, then the MUD sleeps until someone connects. -("If a tree falls in the forest, and no one's around to hear it...") - - The first task of the pulse is to check for network socket input. -First, any pending connections are given descriptors to track them. Then -any descriptors with a socket in the exception set is kicked from the game. -Incoming socket data is read next, checked for command history or repeat -operations, and placed on the appropriate descriptor's command queue. - - Having read commands, they are then set up to be executed. A -player must first be in a condition to execute those commands, so anyone -with a wait state is skipped and people idled are pulled back into the -game. Depending on the player's activities, the input may be sent through -either the message writing system, the text pager, the nanny() login -sequence, the alias system, or straight to the in-game command interpreter. - - In the message writing system (see modify.c), any input, except for -an '@' at the beginning of a line, is simply appended to the string the -character has decided to edit. An '@' at the beginning of a line finishes -the editing and returns the player to their previous state. Typical uses -of this are editing the character's description in the menu or writing to -boards and notes in the game. - - The text pager allows the player to scroll around pages of text the -MUD has produced. It allows refreshing the current page, going back a -page, or continuing down the page. The text pager returns the player to -their previous state upon reaching the end of the text or the user telling -it to quit. - - The nanny() login sequence guides the player through the initial -authentication and entering of the game. Here they are prompted for the -character name and password. Upon successful login they may take actions -such as changing their character's description, changing their password, -deleting the character, or entering the game. - - The alias system provides a method for player's to shortcut the -typing of commands. Each line of input is compared against their existing -aliases and, if a match is found, the desired alias result is applied to -their input and placed on the command queue. This process applies before -the command interpreter so the game need not care what aliases each player -may define. - - Finally, the command interpreter pulls off a line of input from the -player's command queue. It uses the command table in interpreter.c to find -the appropriate function, if any, to call for the given command. It does -various checks to ensure the character is the proper level, in the correct -position, and not frozen. Any applicable special procedures are checked -before running the function in the command table. The special procedure -may override the function completely, as the shopkeepers do with the 'buy' -and 'list' commands, or allow it to execute. - - Processing the commands likely generated output for the player so -the network output is processed next. As much data is sent from the MUD's -output queue as will fit in the operating system's socket buffer for each -player. Any output that can't fit in the socket buffer is held until the -next pulse when perhaps some of the pending output will have been -delivered. If any players decided to exit the game or otherwise -disconnected, their descriptor is marked for removal and the connection -closed. - - Lastly, the periodic tasks are executed via the heartbeat() -function. Each task may run every minute, every 5 minutes, every pulse, or -any other time increment. The list of tasks to run includes: - - * Process each zone's timed updates. - * Disconnect idle descriptors in the login sequence. - * Do basic mobile intelligence and special procedures. - * Determine effects of violence. - * Check the weather. - * Test for magical affect expiration. - * Regenerate health, mana, and movement. - * Auto-save characters. - * Saving the MUD time. - * Extracting dead characters. - - If the user-defined signals SIGUSR1 or SIGUSR2 have arrived, they -are processed at the bottom of the game loop. Doing such work in the -signal handler itself is unsafe and could cause unpredictable behavior. - - -2.2.3. Shutting Down - - The first responsibility on shutdown is to save the players' -characters to disk. CircleMUD tracks which characters have been modified -with a PLR_CRASH flag so it only needs to save those characters which have -changed in the period from the last auto-save to the shutdown. - - To disconnect the network connections, each player socket is closed -in turn. Closing their connection also frees up any memory associated but, -unless memory allocation tracing is enabled, it's not necessary since we're -about to exit anyway. The "mother" descriptor is closed last, preventing -any new players from connecting. - - Left to do are: closing the player database file, saving the -current MUD time for next startup, and logging normal termination of game. -The player database is kept open for fast access to loading and saving -characters as they come and go. Saving the MUD time tries to maintain some -appearance of continuity in your calendar. - - The final actions before exiting are only significant if the -program is running with a memory allocation tracer. Here it sets about -explicitly freeing every known piece of memory previously in use by the -MUD. This is done to leave only forgotten allocations that may indicate a -long-term memory leak in the program. The operating system will remove -even forgotten memory when the program exits but the information may help -prevent an ever-increasing memory usage while running. Memory tracing will -vary depending on your operating system and may not necessarily be -available on your particular platform. - - That's it, show's over. "return 0;" - - -2.3. CircleMUD's Global Variables - - CircleMUD doesn't use objects in the sense of object-oriented -languages so there are various global variables kept that must be manipulated -in order to change the game world. Some are stored as arrays; others as -lists. The global variables kept as arrays generally have an associated -'top_of_...' function to denote its boundary. - - This is not an exhaustive list but the most frequently encountered of -the ones in use. A large number of global, constant strings are kept in -constants.c but they're simply read from. Also see config.c for a number of -configuration global variables. - -2.3.1. World Variables - - * struct room_data *world; - - This array of 'struct room_data' stores all the information for the - rooms of the MUD universe. In addition to room titles, flags, and - descriptions, it also contains lists of people, mobiles, and objects - currently in the rooms. - - * struct char_data *mob_proto; - - While rooms are singular entities, there may be many copies of a - single mobile running around the game world. The 'mob_proto' array of - 'struct char_data' contains the base information for all mobiles, as - well as being used for string sharing amongst all the copies. - - * mob_rnum top_of_mobt; - - The highest valid array index of 'mob_proto' and 'mob_index' is stored - here. This is _not_ the count of items in the array. That's - "top_of_mobt + 1". - - * struct index_data *mob_index; - * struct index_data *obj_index; - - The number of instances of each particular mobile or object is - tracked through these dynamic arrays of 'struct index_data'. This - is also the location for reverse-mapping the mobile/object real - number back into a virtual number. In addition, the special - procedure and several other variables are stored here to avoid - keeping redundant data on every mobile/object in the game. - - * struct obj_data *obj_proto; - - This is analogous to 'mob_proto', except for objects. It's kept as a - dynamic array of 'struct obj_data'. - - * obj_rnum top_of_objt; - - The highest valid array index of 'obj_proto' and 'obj_index' is stored - here. This is _not_ the count of items in the array. That's - "top_of_objt + 1". - - * struct zone_data *zone_table; - - A dynamic array of type 'struct zone_data' storing all the - information for zone resets, titles, and room ranges. - - * zone_rnum top_of_zone_table; - - The highest valid array index of 'zone_table' is stored here. There - are "top_of_zone_table + 1" zones in the array. - -2.3.2. Object Instance Lists - - * struct descriptor_data *descriptor_list; - - All players connected to the MUD have a descriptor used to send the - MUD's output to and receive player input from. Each descriptor does - not necessarily have a character (not logged in yet). These are - stored as a linked list of 'struct descriptor_data' using the 'next' - field. - - * struct char_data *character_list; - - All player characters and mobiles are kept in a linked-list of 'struct - char_data'. This list uses the 'next' field of the structure. - - * struct obj_data *object_list; - - As all characters and descriptors are kept in a linked-list, so too - are all the objects in the world kept. This list uses the 'next' field - of 'struct obj_data'. - -2.3.3. Other - - * const struct command_info cmd_info[]; - - All user commands are kept in a large array in interpreter.c. The - ACMD functions use this array, along with the command array index - variable they are given, to figure out what specific text the user - typed to get to this command function. This allows them to handle - multiple commands with the same function with CMD_IS(). The size of - the array is static and determined by the computer at the time of - compilation. - - * struct weather_data weather_info; - - Raining? Snowing? Weather changes occurring in weather.c are stored in - this structure. The sun's current state (dawn, dusk, etc.) is kept - here as well. - - * struct time_info_data time_info; - - The current date and time of the game world. Used in the shop code - for opening and closing the stores on schedule. - - -2.4. Frequently Used Functions - -2.4.1. Basic String Handling - - * int str_cmp (const char *a, const char *b); - * int strn_cmp (const char *a, const char *b, int len); - - These are portable, case-insensitive versions of the strcmp() and - strncmp() functions. Like their C library counterparts, these - functions perform a character-by-character comparison and return the - difference of the first mismatching characters or zero, if the two - strings are equal. The strn_cmp() function only compares the first - 'len' characters of the first string to the second string. - - Many platforms have built-in routines to do case-insensitive string - comparisons. Where applicable, str_cmp() and strn_cmp() are aliases - for the platform-specific equivalents. On platforms without these - functions built-in, CircleMUD will supply a working implementation. - One should prefer the CircleMUD names to ensure portability since it - incurs no run-time performance cost. - - * int isname (const char *str, const char *namelist); - - Compare a string, 'str', to each of a list of space-delimited - keywords, 'namelist', using str_cmp(). This is used for matching - an argument to an object or mobile, which has its keywords arranged - like, "bottle brown beer." - - * bool is_abbrev (const char *str, const char *arg2); - - A case-insensitive substring match. Equivalent to: - "strn_cmp(needle, haystack, strlen(needle)) == 0" Generally this is - user-extended to act like isname(), except for abbreviated keywords. - - * void skip_spaces (char **string); - - The command interpreter hands off " cabbage" if the user types in - "look cabbage". Since comparisons need to be done without the extra - space in the string, this function removes it. It's also used - internally for the argument splitting functions to properly handle - user input such as: "put the cabbage in the bag". - - * bool is_number (const char *str); - - Tests if an entire string is an ASCII-encoded, unsigned decimal - number by performing isdigit() on each character of the string. - Only unsigned (zero or positive) numbers are recognized. - - * char *delete_doubledollar (char *string); - - The MUD, in processing input, converts a single dollar sign to a - double dollar sign. If you want to echo out a user's input through - something other than act(), you will want to smash '$$' into '$' by - using this function. - - -2.4.2. Argument Processing - - * char *one_argument (char *argument, char *first_arg); - * char *two_arguments (char *argument, char *first_arg, char *second_arg); - * char *any_one_arg (char *argument, char *first_arg); - - These functions are frequently used in MUD commands to parse the - arguments to those commands. As their names imply, one_argument() - will peel off one argument from the string given by the user while - two_arguments() will peel off two at a time. Note that these - functions ignore (and will not return) words such as: "in", "from", - "with", "the", "on", "at", and "to". This is so the commands do not - need to know the difference between "put the sword in the bag" and - "put sword bag". If those words are really needed for the command, - then use any_one_arg() instead. It works just like one_argument() in - all other respects. All of these functions convert the peeled off - argument(s) to lower case as part of the process of storing them in - the user-supplied buffer. - - * char *one_word (char *argument, char *first_arg); - - Peels an argument off from a string like one_argument, but respects - grouping via quoting. If the user supplies, '"moby dick"', - one_argument() would return an argument of '"moby', while one_word() - would return an argument of 'moby dick'. This function converts the - peeled off argument(s) to lower case as part of the process of storing - them in the user-supplied buffer. - - * void half_chop (char *string, char *arg1, char *arg2); - - Apparently a DikuMud relic. Instead of returning the leftover - argument bits in the return value, this copies the result (sans - leading spaces) into a second buffer. - -2.4.3. Character Output (Hello, world!) - - * void log (const char *format, ...); - - Whenever a piece of information needs to be sent to the MUD's logs, - this is the function to use. It's especially useful for debugging - and supports variable arguments like the printf() and sprintf() - functions. To prevent compilation errors due to a conflict with C's - natural logarithm function of the same name, 'log' is actually an - alias for this function's real name, basic_mud_log(). - - * void mudlog (const char *str, int type, int level, bool file); - - In most cases mudlog() is better than log() because it announces to - both the immortals on the MUD and, optionally, the file logs. Chances - are the immortals will notice something faster while logged in to the - game than in the system logs. - - * void send_to_char (struct char_data *ch, const char *messg, ...); - - This is the game's tether to the players; its mouth; its voice. Most - game output goes through this function so it is used very frequently. - It supports variable argument formatting like the C library's - printf() and sprintf() functions. - - * void act (const char *str, bool hide_invisible, - struct char_data *ch, struct obj_data *obj, - const void *vict_obj, int type); - - When dealing with character interactions there are frequently three - situations to cover: the actor, the target, and the observers. This - function takes care of such output along with handy cases for - his/her, he/she/it, and other language special cases. - - See the 'act()' documentation (act.pdf) for more information on - what each particular parameter is used for. - - * void page_string (struct descriptor_data *d, char *str, - bool keep_internal); - - Places the character into a pageable view of whatever string is - given to it. Handy for long board messages, opening announcements, - help text, or other static information. - -2.4.4. File Input - - * int get_line (FILE *fl, char *buf); - - Reads one or more lines, if possible, from the given file handle - into a user-supplied buffer. This skips lines that begin with an - asterisk (*), which are considered to be comments, and blank lines. - The returned line has the line terminator(s) removed, and the total - number of lines read to find the first valid line is returned. A - value of zero indicates that an error occurred or that end of file - was reached before a valid line was read. - - * int get_filename (char *orig_name, char *filename, int mode); - - Fills in the 'filename' buffer with the name of a file of type - 'mode' for a player with name 'orig_name'. The mode parameter can - be one of: - - * CRASH_FILE, for player object files, - * ALIAS_FILE, for player aliases, - * ETEXT_FILE, for the unimplemented e-text system. - - The returned filename contains a path to a file in a directory based - upon the file type and the first letter of 'orig_name'. - -2.4.5. Utility Functions - - * int rand_number (int from, int to); - - Rolls a random number using a (pseudo) random number generator in - the range [from, to]. The random number generator is seeded with - the time CircleMUD booted as returned by the time() system call. - This provides a good, difficult to predict sequence of numbers. - - * int dice (int num, int size); - - Simulate rolling 'num' dice, each with 'size' sides, and return the - sum of the rolls. - - * size_t sprintbit (bitvector_t bitvector, const char *names[], char *result, size_t reslen) - - Treat an array of strings as if they were descriptions for the - individual bits in 'bitvector' and create a string describing it. - This is used by the wizard function do_stat() to give - human-readable output to the various bitvectors used as storage by - the code. This is the approximate reverse of "PRF_LOG1 | PRF_DEAF", - for example. - - * size_t sprinttype (int type, const char *names[], char *result, size_t reslen) - - Retrieves a value from an array of strings. The difference between - this and "array[number]" is that this will avoid reading garbage - values past the end of the array. sprinttype() assumes the string - arrays are terminated by a "\n" entry. - - * int search_block (char *arg, const char **list, int exact) - - Searches an array of strings for a match to 'arg' and returns the - index in the array of the match, or -1 if not found. If 'exact' is - false, then a prefix match is done akin to is_abbrev(). This is - useful to map symbolic names to numerical constants. Think of it - as the opposite of array[number]: "What index has this value?" - -2.4.6. Character/Object Manipulation - - * void char_to_room (struct char_data *ch, room_rnum room); - * void char_from_room (struct char_data *ch); - - Reciprocal, low-level functions to put a character into and remove a - character from a given room. The room number must be specified with - a "real number" (an index into the room tables) as returned by - real_room(). Since a character can only be in one room at a time, - you must call char_from_room() to remove a character from his - current location before placing him in another. After a - char_from_room() call, the character is in NOWHERE and must be moved - to another room using char_to_room(). - - These functions do not check if the character is allowed to enter or - leave the room; nor do they provide output to indicate that the - character is moving. - - * void extract_char (struct char_data *ch); - - Remove the character from the game world and then frees the - memory associated with it. Players are saved before removal. Any - objects still on the character are dumped on the ground. - - * void equip_char (struct char_data *ch, struct obj_data *obj, int pos); - * struct obj_data *unequip_char (struct char_data *ch, int pos); - - Takes a free-floating object (i.e., not equipped, in inventory, on - the ground, or in another object) and equips it to the character - for the specified location. unequip_char() does the opposite; it - removes the object from the character's equipment list and returns - it as a free-floating object. The object being unequipped must be - placed elsewhere or destroyed. Note that some objects may not be - equipped by characters of certain classes and/or alignments. - - * void obj_to_char (struct obj_data *object, struct char_data *ch); - * void obj_from_char (struct obj_data *object); - - Reciprocal, low-level functions to put an object into and remove an - object from a given character's inventory. Since an object can only - be in one location at a time, you must use one of the obj_from_X() - functions to remove it from its current location before using - obj_to_char() to place it in someone's inventory. After an - obj_from_char() call, the object is in NOWHERE and must be moved to - another location using one of the obj_to_X() functions. - - These functions do not check if the character is allowed to carry or - discard the object; nor do they provide any output to inform anyone - that the character has received or discarded the object. - - * void obj_to_obj (struct obj_data *object, struct obj_data *cont); - * void obj_from_obj (struct obj_data *object); - - Reciprocal, low-level functions to put an object into and remove an - object from a given container object. Since an object can only be - in one location at a time, you must use one of the obj_from_X() - functions to remove it from its current location before using - obj_to_obj() to place it within another object. After an - obj_from_obj() call, the object is in NOWHERE and must be moved to - another location using one of the obj_to_X() functions. - - These functions do not check if the container is allowed to carry or - discard the object; nor do they provide any output to inform anyone - that the container has received or discarded the object. - - * void obj_to_room (struct obj_data *object, room_rnum room); - * void obj_from_room (struct obj_data *object); - - Reciprocal, low-level functions to put an object into and remove an - object from a given room. Since an object can only be in one - location at a time, you must use one of the obj_from_X() functions - to remove it from its current location before using obj_to_room() to - place it in a room. After an obj_from_room() call, the object is in - NOWHERE and must be moved to another location using one of the - obj_to_X() functions. - - These functions do not check if the room is allowed to contain or - discard the object; nor do they provide any output to inform anyone - that the room has received or discard the object. - - * void extract_obj (struct obj_data *obj); - - Removes the object from its place in the world, then destroys it. - -2.4.7. Object Locating - - * struct obj_data *get_obj_in_list_num (int num, struct obj_data *list); - - Get an object from 'list' with the specified real object number. - Only takes first object; no "2.bread" support. - - * struct obj_data *get_obj_num (obj_rnum nr); - - Find the first object in the world with the real object number - given. Does not have "2." support. - - * struct obj_data *get_obj_in_list_vis (struct char_data *ch, char *name, - int *number, struct obj_data *list); - - Find the 'number'-th object in 'list' with keyword 'name' that the - character can see. A NULL is returned on failure to locate such an - object, or if not enough objects to satisfy 'number' were found. - 'number' is a pointer to an integer so it can be decremented when - doing multiple searches, such as room then world. If the first - object is desired, 'number' is left NULL. - - * struct obj_data *get_obj_vis (struct char_data *ch, char *name, - int *number); - - Find the 'number'-th object in the world with keyword 'name' that - the character can see. A NULL is returned on failure to locate - such an object, or if not enough objects to satisfy 'number' were - found. 'number' is a pointer to an integer so it can be decremented - when doing multiple searches, such as room then world. If the - first object is desired, 'number' is left NULL. - - * struct obj_data *get_obj_in_equip_vis (struct char_data *ch, char *arg, - int *number, struct obj_data *equipment[]); - - Find the 'number'-th object in the character's equipment list with - keyword 'name' that the character can see. A NULL is returned on - failure to locate such an object, or if not enough objects to - satisfy 'number' were found. 'number' is a pointer to an integer so - it can be decremented when doing multiple searches, such as - equipment then inventory. If the first object is desired, 'number' - is left NULL. - - * int get_obj_pos_in_equip_vis (struct char_data *ch, char *arg, - int *number, struct obj_data *equipment[]); - - Return the index of the 'number'-th object in the character's - equipment list with keyword 'name' that the character can see. A - -1 is returned on failure to locate such an object, or if not - enough objects to satisfy 'number' were found. 'number' is a - pointer to an integer so it can be decremented when doing multiple - searches, such as equipment then inventory. If the first object is - desired, 'number' is left NULL. - - * int generic_find (char *arg, bitvector_t bitvector, - struct char_data *ch, struct char_data **tar_ch, - struct obj_data **tar_obj); - - Searches any or all of the character's equipment, inventory, - current room, and world for an object with the keyword given in - 'arg'. A 2nd or 3rd object is denoted in "2.object" notation. The - function's return value specifies where the object was found, or 0, - and the 'tar_obj' value is updated with the object itself, or NULL. - NOTE: This also does characters, either separately or - simultaneously. - -2.4.8. Character Locating - - * struct char_data *get_char_room (char *name, int *number, room_rnum room); - - Find the 'number'-th character in the room with the keyword 'name'. - A NULL is returned on failure to locate such a character, or if not - enough characters to satisfy 'number' were found. 'number' is a - pointer to an integer so it can be decremented when doing multiple - searches, such as room then world. If the first character is - desired, 'number' is left NULL. - - * struct char_data *get_char_num (mob_rnum nr); - - Find the first mobile in the world with real mobile number given. - This does not have support for "2." notation. - - * struct char_data *get_char_room_vis (struct char_data *ch, char *name, - int *number); - - Find the 'number'-th character in the room with the keyword 'name' - that is visible to the character given. A NULL is returned on - failure to locate such a character, or if not enough characters to - satisfy 'number' were found. 'number' is a pointer to an integer - so it can be decremented when doing multiple searches, such as room - then world. If the first character is desired, 'number' is left - NULL. - - * struct char_data *get_char_world_vis (struct char_data *ch, char *name, - int *number); - - Find the 'number'-th character in the world, searching the - character's room first, with the keyword 'name' that is visible to - the character given. A NULL is returned on failure to locate such a - character, or if not enough characters to satisfy 'number' were - found. 'number' is generally a pointer to an integer so it can be - decremented when this does both searches. If the first character is - desired, 'number' is left NULL. - - * struct char_data *get_char_vis (struct char_data *ch, char *name, - int *number, int where); - - When 'where' is FIND_CHAR_WORLD, call 'get_char_world_vis()'. If - 'where' is FIND_CHAR_ROOM, call 'get_char_room_vis()'. Otherwise, - return NULL. This is kept for compatibility with various calls in - the source code or if people want to easily change a search based - on a variable. - - * int generic_find (char *arg, bitvector_t bitvector, - struct char_data *ch, struct char_data **tar_ch, - struct obj_data **tar_obj); - - Searches the character's current room and/or world for a character - with the keyword given in 'arg'. A 2nd or 3rd character is denoted - in "2.character" notation. The function's return value specifies - where the character was found, or 0, and the 'tar_ch' value is - updated with the character itself, or NULL. NOTE: This also does - objects, either separately or simultaneously. - -2.4.9. Violence - - * void set_fighting (struct char_data *ch, struct char_data *victim); - - Initiates fighting between 'ch' and 'victim'. - - * void stop_fighting (struct char_data *ch); - - Removes the character from a fighting posture. Note that if an - enemy is still considered fighting this character, the character - will revert back to fighting as soon as the enemy hits them again. - - * void hit (struct char_data *ch, struct char_data *victim, int type); - - Makes the character attempt to hit the victim. The type determines - if it is a skill, backstab in particular, or other type of damage - to attempt to hit with. The type is generally left as - TYPE_UNDEFINED to use the character's natural type. - - * int damage (struct char_data *ch, struct char_data *victim, int dam, - int attacktype); - - Cause bodily harm to the victim, courtesy of the character. The - damage and attacktype determine the message reported. Immortals - and shopkeepers (that aren't charmed) may not be injured. Damage - is capped at 100 per hit. - - -3. Adding Features - -3.1. Adding Commands - - In the course of writing new functionality for your MUD, one of the -first projects you may try is to add your own command. Some commands, like -socials, are special, but most commands will require you to implement some -method to manipulate and parse the user's input. In CircleMUD, this is done -with 'command functions' which have a special declaration form: - - ACMD(do_/* Command name. */) - { - . - . /* Command code. */ - . - } - - The command functions are then registered with the command -interpreter by adding them to the cmd_info[] table in interpreter.c. The -order within the command table is significant; entries at the top are -substring matched prior to entries lower in the list. So if 'kill' is -before 'kiss', then 'ki' will match 'kill'. Something else to be aware of -is that this can render commands unreachable, such as 'goad' being before -'go'. The 'go' can never be matched because 'goad' will always have a valid -substring matched first. - - The fields of importance are: - - * const char *command - The name of the command being registered. Remember the substring - matching when deciding upon the order in the table. - - * byte minimum_position - One of the POS_xxx constants #define'd in structs.h. This enforces - the minimum position, inclusive, the user must be in, in order to - execute the command. - - * ACMD(*command_pointer) - This is the name of the function the command will call. It must be - defined in the code with the ACMD() macro and prototyped above the - command table itself. - - * int minimum_level - The minimum level, inclusive, the user must be to execute the - command. - - * int subcmd - To allow the same code function to handle multiple, similar - commands, this field allows an identifying number to be given to - the command's function. - - The ACMD declaration form is a C macro that sets up the command -function to receive the right arguments. All command functions in CircleMUD -receive the same set of parameters: - - * struct char_data *ch - - The character that issued the command (or, perhaps, was forced to - issue the command): the actor. - - * const char *argument - - A string that contains the arguments the user gave to the command, - with any leading spaces from the command interpreter still intact. - For example, if the user typed "tell ras Hello, there" at the - prompt, argument would be " ras Hello, there". This string is - typically processed using one or more of the functions from Sections - 2.4.1 (Basic String Handling) or 2.4.2 (Argument Processing). - - * int cmd - - The index within the command table where this command was found. - Useful when multiple commands can invoke the same command function - and you want to identify which command was issued. Since command - indices can change when you add new commands, the primary use of - this field is in special procedures and with the IS_CMD macro. Do - not confuse this with the subcmd parameter, which is more general - purpose. - - * int subcmd - - A special, user-defined integer value passed to select a - "subcommand." Usually zero, but sometimes used when multiple - commands with similar behavior are implemented with a single command - function. Since the subcmd's value is supplied within the command - table and has a meaning determined entirely by the command's author, - it will not change when you add new commands. - - A command with no arguments is very simple to write. For example, -here's a simple command that sends a nice, personalized greeting to the user -when she runs it: - - ACMD(do_hello) - { - act("Hello, $n.", FALSE, ch, NULL, NULL, TO_CHAR); - } - - To allow the user to access this command, you have to add it to the -command table as discussed before. This can be done by adding the ACMD -prototype above cmd_info[] (if necessary) in interpreter.c, like - - ACMD(do_hello); - -and then adding to cmd_info[] the command's information, as previously -discussed: - - { "hello", POS_DEAD, do_hello, 0, 0 }, - - Our information specifies this is a command named "hello" which -anyone can use, regardless of their position (since dead is the minimum) or -level (since 0 is the minimum), calls the do_hello() function to be -executed, and has no subcmd. Note that because cmd_info[] does not encode -information about the arguments to the command, we don't need to do anything -different for commands that take arguments. - - Since the command interpreter doesn't process arguments for us -(allowing cmd_info[] to be simple and general), we have to process them -ourselves. Suppose we want to update our "hello" command to send a greeting -to other users, when its invoked with an argument. First, we need to get -the first argument (if any) by using the one_argument() function. In order -to do this, we need a place to store the first argument (if any), which we -declare as a local character buffer of length MAX_INPUT_LENGTH. (Note that -regardless of what length we *expect* the argument to be, we always make our -buffer the maximum input size, so users cannot overflow the buffer and crash -the game.) - - After this, we need to see what the argument is. If it's nothing, -we'll default to our old behavior of just saying hello to our user. -Otherwise, we need to look up the character with the given name. If we -can't find anyone by that name, we send an error message. If we find -someone, we send the greeting to the character we found. We check if the -given argument is empty by seeing if its first character is C's end of -string marker ('\0' or 0). Since one_argument() strips leading spaces for -us, we don't have to worry about them. If the string is not empty, we need -to look up a character in the current room by that name, using -get_char_vis() (see Section 2.4.8. Character Locating). - - Our changes give us: - - ACMD(do_hello) - { - char arg[MAX_INPUT_LENGTH]; /* First argument. */ - struct char_data *targ; /* Who to greet? */ - - one_argument(argument, arg); - - if (!*arg) { /* Common idiom for empty string test. */ - act("Hello, $n.", FALSE, ch, NULL, NULL, TO_CHAR); - return; /* We're done for this case. */ - } else if (!(targ = get_char_vis(ch, arg, FIND_CHAR_ROOM))) { - send_to_char(ch, NOPERSON); - return; /* Done for this case. */ - } - - /* Otherwise we got a target: */ - act("You greet $N.", FALSE, ch, NULL, targ, TO_CHAR); - act("$n greets you.", FALSE, ch, NULL, targ, TO_VICT); - act("$n greets $N.", FALSE, ch, NULL, targ, TO_NOTVICT); - } - - NOPERSON is a constant defined in config.c for use an error message -when the target of a command cannot be found. Other such constants are OK -(for when everything goes well) and NOEFFECT (as a general failure message -for skills, spells, and commands whose success rely on chance). - - Of course, this command is little more than an overcomplicated -social (we'll see in the next section that socials don't require command -functions at all). Doing something of interest is up to you, as the -programmer. Our "hello" command only serves as a starting point and -demonstration of some idioms used throughout CircleMUD. - - -3.2. Adding Socials - - Socials are commands that only write messages to the user and -possibly his room and/or an optional victim. Examples are typical mud -commands like "nod" or "wave", to let players perform various demonstrative -actions. Our "hello" command above is an example. However, since socials -are very common and superficially simple, there's a simplified way to write -them. - - The lib/misc/socials file in the CircleMUD directory contains the -actual socials in the following format: - - - - - - - - - - - - - The exact meaning and format of these fields is described in -'socials.pdf', although much of it corresponds to act() (like the hide flag -or the format of the messages) and the command interpreter (like the command -name and the minimum position the *victim* must be in for the social to -work). - - Programmatically, the social is still a command and must be -registered in cmd_info[] like any other command. All socials have the same -command function, do_action(), which does the specialized social system -processing. Thus, to add a social "foobar" to the command interpreter, we -add the following line to the appropriate place in cmd_info[] (taking into -account that order is significant, as discussed in Section 3.1): - - { "foobar", POS_RESTING, do_action, 0, 0 }, - - Note that the second element in the table entry is the minimum -position the user of the social must be in, while the lib/misc/socials file -stores the minimum position that the *victim* (if any) must be in for the -social to work. In this case, the command can only be used by people that -are awake and fully conscious (resting, sitting, or standing). - - -3.3. Adding Spells - - CircleMUD improves greatly over standard Diku handling for spells, but -how you go about adding them depends on the type of spell you want to make. -Damage, affection, group, mass area, area, monster summoning, healing, status -removal, and item enchanting spells are all generated in a template format -with a touch of special messages and coding effects. More complicated spells -such as 'locate object', 'summon', or 'identify' are a combination of the -behavior of spells and commands. They are spells in the sense the code checks -for mana and requires the 'cast' syntax but are also commands in the sense -that beyond the basic handling, the spell is implemented as a subroutine with -given parameters. - - All spells require a definition to determine the amount of mana used, -how the spell behaves, and what the spell is named. To do that, the function -spello() is called from mag_assign_spells() in spell_parser.c. It is called -as: - - spello( - unique_spell_number = ID# from 0 .. TOP_SPELL_DEFINE for this spell. - spell_name = Name to be used for 'cast' command. - max_mana = Mana cost of spell when first learned. - min_mana = Minimum mana cost to ever cast the spell. - mana_change = Reduction in mana cost per level beyond learning it. - minimum_position = Whether castable sitting, standing, fighting, etc. - valid_targets = If the spell targets people, yourself, items, etc. - offensive = Whether casting on someone else is a hostile action. - spell_routines = One or more of the magic template classifications. - wear_off_message = Text to display when the spell wears off, or none. - ) - -A spell with a minimum position value of 0 may not be cast by mere mortal -players. For example, the spell "armor" is described as: - - spello(SPELL_ARMOR, "armor", 30, 15, 3, POS_FIGHTING, - TAR_CHAR_ROOM, FALSE, MAG_AFFECTS, - "You feel less protected."); - -This spell costs 30 mana at the first level it is learned and decreases in -cost by 3 mana per level afterward until it reaches the minimum of 15. The -spell may be cast either fighting or standing, but not sitting, resting, -sleeping, or otherwise incapacitated. Armor will target anyone in the current -room as a non-hostile action. It processes through MAG_AFFECTS so there will -be a lingering affection, after which the "You feel less protected" message -will display. - - To allocate a new spell, create a new #define symbol in spells.h in -the same pattern as the others there. In that header, give the new spell an -unused spell number equal to or less than MAX_SPELLS. If you run out of spell -slots then other means not covered here will be necessary to add more spells. - -3.3.1. Template Spells - - Similar types of spells have generalized routines that handle multiple -spells with very little different code. A damage spell is a damage spell is a -damage spell. Even if a spell does multiple actions, such as blinding + -damage + monster summon, the damage portion of the spell acts identical to a -spell that simply does damage. The only difference is how much it does and -whether there are special mitigating factors. For example, 'chain lightning' -in mag_damage() (since it is a MAG_DAMAGE spell) is simply: - - case SPELL_CALL_LIGHTNING: - dam = dice(7, 8) + 7; - break; - -So the spell does 7d8+7 damage. Simple enough. All checking for saving -throws, valid targets, proper mana reserves, etc. is all handled by the -generic code with a bit of definition for the code to operate by. - - The code fragment in the template sections can use any information -about the caster, target, or environment that it chooses to modify the damage, -success, or effect done to the target. Some spells do more damage if the -caster is a magic user. Others might outright kill lower level targets but -only slightly wound more experienced ones. The effect is up to you. - - Affection spells require more in their fragment than the simple damage -spells. They create affection structures that are then given to the target of -the spell for their specified duration if the spell succeeds. More than one -affection can be given by a single spell, as shown below in "bless": - - case SPELL_BLESS: - af[0].location = APPLY_HITROLL; - af[0].modifier = 2; - af[0].duration = 6; - - af[1].location = APPLY_SAVING_SPELL; - af[1].modifier = -1; - af[1].duration = 6; - - accum_duration = TRUE; - to_vict = "You feel righteous."; - break; - - Any modifier listed in structs.h in the APPLY_xxx section may be used -as the location field. The modifier's effect will depend on the affection -type used. Up to MAX_SPELL_AFFECTS values can be assigned to. Although not -listed in the above example, a '.bitvector' value may be assigned to if the -spell should tag the player with an AFF_ flag. If multiple castings of the -same spell should be cumulative in duration, the 'accum_duration' variable is -set to TRUE. Likewise, if the modifier is cumulative, the 'accum_effect' -variable should be set to TRUE. A string assigned to 'to_room' will be passed -through act() for the occupants of the same room as the caster. A 'to_vict' -string will be given to act() with the target of the spell as the recipient of -the message. - - Group spells simply call another spell on everyone in your current -group. If you want a 'group fly' spell, then you make a 'fly' spell first. -Afterward, you make the 'group fly' definition and then fill in some template -areas of the perform_mag_groups() function. What you write there will depend -on how your spell is designed. - - General summoning spells (not 'summon' itself) deal with the -conjuration of mobiles. They require: 'fmsg', a failure message array index -number; 'mob_num', the virtual mobile number to summon; 'pfail', the percent -chance of failure; and 'handle_corpse', mostly for the "animate dead" spell so -it can move the items from the corpse being animated to the mobile being -summoned. These spells lend themselves to more customization than some of the -other types. - - Healing spells in mag_points() can restore either health or movement -points by default. Just assign the amount of health healed to a 'healing' -variable, the amount of movement points restored to a 'move' variable, and -send the target a message with send_to_char(). The general code will handle -updating the character's attributes, position, and make sure a dying character -is restored to normal functions if healed sufficiently. - - Unaffection spells revert the effects of other spells, such as -"blindness", "silence", or "drunken stupor." There are only three variables -used in mag_unaffects(): to_vict, to_room, and spell. The important variable -is 'spell', which determines which spell effect this unaffection spell will -counter. The 'to_vict' and 'to_room' messages are optional but sent to the -victim and room, respectively, if provided. - - Object alteration spells deal with magical modifications to items, -such as poisoning, cursing, enchanting, or making them invisible. These -spells are all unique by nature so only 'to_char' and 'to_room' are expected -to be set, as messages to the character and room, respectively. If 'to_char' -is left NULL, it is assumed the spell failed and a "no effect" message is -given. - - A creation spell conjures an item out of nothingness. The only -variable expected is 'z', which specifies the object virtual number that -should be created. Note that only a single object is created and there is no -current mechanism for making multiples. - - The last function of note, mag_materials(), is not a spell type at all -but a helper function which can be used to require up to 3 spell reagents for -a particular spell to be cast. The function will return TRUE if the caster -has the objects, otherwise FALSE. If the 'extract' variable is TRUE, then the -objects in question will be consumed by the casting. You can also make the -function 'verbose', but it more of a debugging/funny option than practical. - -3.3.2. Manual Spells - - Any spell that doesn't fit one of the template molds is implemented as -a manual spell. Adding a manual spell requires a function to be written, -generally in spells.c, with the ASPELL() macro. After the requisite spell -identifier macro is added to spells.h, add it to the manual spell list in -spell_parser.c, call_magic(). (Search for "MANUAL_SPELL".) - -Manual spells are given: - - level - The effective character level of the spell being cast. This is NOT - the same as the level of the character because the spell could have - been case by a wand, staff, or scroll instead of the character. - ch - The character causing the spell. - victim - The target of the spell, if a character. - obj - The target of the spell, if an object. - -Other than that, manual spells can do anything. Think of them as being -similar to standard commands in power and scope. A useful modification is to -add 'argument' support to spells so that "locate object" works properly and a -"change weather" spell could make it "better" or "worse." - - -3.4. Adding Skills - - Skills in CircleMUD are usually implemented as commands. The first -steps to adding a skill are similar to those of adding a spell. First, make -sure you have a clear idea of what your skill is going to do, who you're -going to give it to, and how it fits in with the rest of the game. Try to -avoid making too many skills that do basically the same thing -- having lots -of skills isn't a meaningful feature if most of them can be ignored. - - After you have a good idea of what you want to do, why you want to -do it, and why it's a good idea to do it, then start by adding a SKILL_xxx -#define to spells.h and the corresponding skillo() line to -mag_assign_spells() in spell_parser.c. The skillo() function takes, as its -first argument, the SKILL_xxx #define and, as its second, the name of the -skill, as a string. This registers the skill as something that can be -practiced. As with spells, you have to register the skill's availability -with individual classes at the appropriate levels in the init_spell_levels() -function of class.c. - - Now your skill can be gained and practiced by players of an -appropriate level and class, but it doesn't actually do anything. Most -skills, like "bash" and "kick", are simply commands that perform skill -checks. The setup and everything else is the same as in Section 3.1, Adding -Commands. The body needs to account for (1) whether the command's user can -access the skill and (2) whether they were successful in using the skill. -For (1), CircleMUD uses the idiom - - if (IS_NPC(ch) || !GET_SKILL(ch, SKILL_xxx)) { - send_to_char(ch, "You have no idea how.\r\n"); - return; - } - -to check if the skill is available. The GET_SKILL macro returns the -proficiency (as a percentage) the given character has in the given skill. -If the proficiency is 0%, the player does not have the skill (either because -his class doesn't have it or he's not learned it, yet). This check is -preferred over directly testing if the player is of the right class(es) to -use the skill, since that would require you to change several functions -across several files to give skills to other classes (instead of just being -able to add spell_level() calls in class.c). - - At this point you would do argument processing in the typical -manner, as well as any other checks that are necessary (for instance, you -might want to check if the room is peaceful, as done in do_bash() in -act.offensive.c). Last, you want to check for the success or failure of the -skill by rolling a percentage to compare against the user's proficiency -(probability of success). This is typically done with: - - if (number(1, 101) > GET_SKILL(ch, SKILL_xxx)) { - /* Failure. */ - } else { - /* Success. */ - } - -where you'd replace the comments with the relevant failure or success code. - - For skills that do damage, like "bash" and "kick", the messages for -success and failure are typically not encoded in the skill itself, but -instead as damage messages in lib/misc/messages, which has the format: - - M - - - - - - - - - - - - - - -The skill number is the #define as appears in spells.h and the rest are -single line messages that will be passed to act(). This is similar in many -respects to lib/misc/socials. The format is discussed in more detail in a -comment at the beginning of lib/misc/messages. - - These messages are then displayed by calling damage() with the -appropriate arguments, as discussed in Section 2.4.9, Violence, with the -attacktype argument set to the SKILL_xxx #define, as in - - /* - * See above and Section 3.1, Adding Commands: - * ... skill checks, argument processing, etc. - * ... vict is set to skill's victim. - */ - - if (number(1, 101) > GET_SKILL(ch, SKILL_FOO)) { - /* Failure means 0 damage is done. */ - damage(ch, vict, 0, SKILL_FOO); - } else { - /* Success means we do some damage. */ - damage(ch, vict, 10, SKILL_FOO); - } - - Note that even when the skill succeeds and, thus, our call to do 10 -damage to the victim of the skill is made, we're not guaranteed to do the -damage. The hit may miss, in which case damage() returns 0. Additionally, -the hit may kill the victim, in which case damage() returns -1. If we're -going to be modifying vict in our skill's function after the call to -damage(), it's important to take these return values into consideration. -See do_bash() in act.offensive.c. - - -3.5. Adding Classes - - Classes are one of the implementors' most important decisions because -the players will constantly deal with them, their advantanges, and their -limitations. A good class should be balanced so that it has its own unique -perks and flaws, never making other classes pointless to play. - - Most changes to be done for classes will be found in the class.c file. -There may be special quirks for classes implemented in the other files but the -basic defining characteristics are all there. The class needs a name, -abbreviation, menu entry, unique class number, skill list, guild information, -saving throws, combat hit probabilities, an ability priority list, -hit/mana/move advancement per level, basic starting kit, opposing item flags, -spells, skills, experience charts, and level titles. It's an exhaustive list, -but the actual addition of a class isn't nearly as complicated as it sounds. - - The first change for a class required external of class.c is in -structs.h. There, search for CLASS_UNDEFINED and add a new CLASS_xxx -definition for your class name with the next available number. Remember to -bump the value of NUM_CLASSES, just below, by 1. - - Then search structs.h for "Extra object flags" so you can add an -"ITEM_ANTI_xxx" flag for your new class. As before, use the next available -number in the sequence for ITEM_xxx flags. Note that the limit is "(1 << 31)". -Beyond that you'll need special changes (not covered here) to add more flags. - - The "ITEM_xxx" extra flags have a corresponding text description in -constants.c, so search it for "ITEM_x (extra bits)". Add a string giving a -short name for the new ITEM_ANTI_xxx flag, in the appropriate order, before -the "\n" entry near the bottom. - - The shops have a similar "don't trade" setup, so search shop.h for -"TRADE_NOGOOD" to add a new TRADE_NOxxx item to the list for the class to be -added. Below that (near "NOTRADE_GOOD"), a line will need to be added for -each new class so the 'no trade' status of a shop can be tested for the class. - - With the definitions in shop.h, the shop code in shop.c can then be -modified to take into account the new classes. In a manner similar to -constants.c, there's a table in shop.c with textual names for the TRADE_NOxxx -values. Add the new class names to the "trade_letters[]" array in the same -order as the TRADE_NOxxx bits were added to shop.h. Also in shop.c, the -is_ok_char() function will need modified to add "IS_xyz(...) && -NOTRADE_xyz(...)" conditions, to make the above changes take effect. - - Lastly for changes beyond class.c, search utils.h for "IS_WARRIOR" and -make a similar definition below it for the new class. - - Most of the changes to class.c will be straight-forward if going by the -existing classes, so only a few items of note: - - 1) The letters used in parse_class() must be unique and should - correspond to the highlighted characters in the 'class_menu' variable. - - 2) Lower saving throw values are better. - - 3) Lower 'thaco' values are better. - - -3.6. Adding Levels - - Some people feel the standard 34 levels aren't enough and want to -add more. Others feel 34 is too many and want to reduce it. Fortunately, -changing the number of levels in the MUD is fairly painless. There are -only three important things to remember: adjusting the secondary tables to -match your new levels, making over 127 levels requires some additional -modifications, and to readjust the mobiles afterward. - - The secondary functions that rely on levels directly are: -saving_throws, thaco, backstab_mult, level_exp, title_male, and -title_female. These must be changed to correctly cover the entire range of -new levels for the MUD. If not, the missing levels will have incomplete -data and may act in unexpected ways. Fortunately, you'll receive error -messages in the logs if such an event happens. - - As the number of mortals levels is always one less than the lowest -immortal level, changing LVL_IMMORT in structs.h to a new value will give -the desired change. Make sure you change the functions described above at -the same time. The other immortals levels should be adjusted accordingly. - - If you're making more than 127 total levels on the MUD, a little -structs.h surgery is required. The default range on the 'level' variable -is -128 to 127. CircleMUD doesn't actually use negative levels so changing -it to 'ubyte level' will allow 255 levels. Note that this setting hasn't -been tested so test your new level settings to make sure they work as -expected. If you need more than 255 levels, you'll need to change the -'byte' to something larger, like ush_int (65,535) or unsigned int (4.2 -billion). Changing the variable type beyond byte will result in the -erasing of your player files and require changes elsewhere in the code -where levels are manipulated. - - Once you've changed the number of levels on your MUD, the -implementor character you may have already created will now have the wrong -level to be an implementor. If you've decreased the levels then a 'set -self level XX' command should work to drop yourself to the proper level, -since you're considered above the new implementor level still. Those -increasing the number of levels will find their implementor is now likely -considered a mortal. In that case, you can either erase the player files -to recreate yourself or make a command to make yourself the proper level, -such as: - - ACMD(do_fixmylevel) - { - if (GET_IDNUM(ch) == 1) - GET_LEVEL(ch) = LVL_IMPL; - } - - Now remember to change all the mobiles too so they have proper -levels. If you added levels, it'll make the mobiles weaker unless fixed. -If reducing the levels, then you'll end up with error messages in the logs -when those mobiles try to use saving throws or other level-dependent -values. - - -3.7. Adding Color - - Color in CircleMUD is handled on a varying scale of color levels -the player can choose to display. The possible levels are off, sparse, -normal, and complete. If a player has color off, no color must be sent. - - To send color to the players, use the CC* family of macros: - - CCNRM: Normal text color, as defined by player's terminal. - CCRED: Red - CCGRN: Green - CCYEL: Yellow - CCBLU: Blue - CCMAG: Magenta - CCCYN: Cyan - CCWHT: White - -Each macro takes a pointer to the character and the level at which the -color given should be displayed. If the player uses a lower level of color -than given to the macro in the code, the color code will reduce to an empty -string so it does not appear. See 'color.pdf' for more information on this -process. - - Now suppose you wish to add high-intensity colors, blinking, or -backgrounds for your text. The place to look for the existing color codes -is in screen.h, but you'll just see codes like "\x1B[31m" there. So what -is "\x1B[31m"? It's an ANSI color code understood by various terminal -emulations to display color. There are predefined colors for each code and -a special format to use so you can't just make up codes and expect them to -work. - - In order to compare the low-intensity colors with the -high-intensity, an additional color must be known to complete the pattern, -black: - - #define BBLK "\x1B[30m" - -The terminal background color is assumed black by CircleMUD so that -particular color definition isn't in screen.h. Now a comparison of red and -green with their bright counterparts: - - #define KRED "\x1B[31m" (Dark) - #define BRED "\x1B[0;1;31m" (Bright) - - #define KGRN "\x1B[32m" (Dark) - #define BGRN "\x1B[0;1;32m" (Bright) - -If you want the bright colors, you can extend this pattern to get the other -standard colors. - - Once the #define is in screen.h, it needs to be usable via the CC* -color convention to respect the color level of the players, so for every -new color code add a CC* for it, such as: - - #define CCBRED(ch,lvl) (clr((ch),(lvl))?BRED:KNUL) - #define CCBGRN(ch,lvl) (clr((ch),(lvl))?BGRN:KNUL) - - With a number of colors, making a new CC* code for each one may get -tedious. You may want to add a new macro, such as: - - #define CC(ch, color, lvl) (clr((ch),(lvl))?(color):KNUL) - -Then you can use CC(ch, KRED, C_NRM) instead of CCRED(ch, C_NRM). Whether -or not you want to use this idiom is up to you. It might come in handy -once you get into blinking (use sparingly!) and background colors. The -background colors are "\x1B[40m" (black), "\x1B[47m" (white), and -everything in the middle as per the foreground colors. - - -4. Writing Special Procedures - - Special procedures are the way to give life to your world. Through -special procedures you can, for instance, make Mobiles react to player -actions, fight intelligently,etc. - - Using special procedures, your virtual world is not just a bunch of -monsters, objects and rooms, reduced to a number of statistics. Just like -good descriptions add atmosphere to the world, good use of special -procedures adds flesh and life to the world. - - Several special procedures are provided with stock CircleMUD which you -can use to create your own and get used to the mechanics of special -procedures. These special procedures can be found in castle.c and -spec_procs.c. They range from very simple procedures, like puff (pulsed -special procedure) or bank (command-driven special procedure), to very -complex procedures like the guild master. - - In this chapter, false refers to the value 0 and true to any non-zero -value. - - -4.1. Overview of Special Procedures - - Special procedures are nothing more than C functions, which are -associated to mobiles, objects and rooms. - - In the standard version of CircleMUD, special procedures are defined -and assigned at compile time and cannot be changed or reassigned during -runtime. - - -4.2. Pulsed vs. Command-Driven Special Procedures - - Special procedures are called at three points in code: the command -interpreter (command-driven special procedures), the game heartbeat and the -violence code (pulsed special procedures). - - There is no information kept to know if the special procedure is -pulsed or command-driven, other than the behavior of the special procedure -itself. When creating a special procedure you must keep in mind that it will -be called in each of the three places and must therefore be prepared to react -to all situations accordingly. - - In the next two sub-sections we will present both types of special -procedures, and in the third sub-section we'll explain how to differentiate -the three types of call. - - -4.2.1. Pulsed Special Procedures - - Every tick, the function heartbeat goes through the list of mobiles -and the list of objects, updating everyone of them. If a mobile or an object -as a special procedure associated to it, that special procedure is run with -the parameters cmd and argument set to 0 and NULL respectively. The NULL -used to be sent as an empty string (""), but this was changed in 3.0bpl19. - - When there is a fight, the special procedure of a fighting mobile is -called once per round with the same arguments. - - -4.2.2. Command Driven Special Procedures - - Whenever a player issues a command, the command interpreter tries to -identify it in the Master Command Table. If it succeeds, before running the -command associated in the table, it checks for special procedures in the -following order: - - * room the player is in; - * objects in the player's equipment (does not enter the containers); - * objects in the player's inventory (does not enter the containers); - * mobiles in the room; - * objects in the room floor; - - The first special procedure to succeed and return true finishes the -interpreting of the command. - - If no special procedure returned true or no special procedure was -found, then the command interpreter runs the procedure specified in the -Master Command Table. - - -4.2.3. Preparing for all occurrences - - In order to make your special procedure react accordingly to all the -different places where the special procedure can be called you need to -distinguish those places. The way to do it is through the parameters. - - Whenever cmd is 0, the special procedure has been called as a pulsed -special procedure, otherwise it's a command-driven special procedure. - - To detect if the procedure was called through the violence code, it -is a pulsed special procedure and IS_FIGHTING(me) must be true. Of course, -this only has meaning for a mobile special procedure. - - -4.3. Relating Special Procedures to Objects, Mobiles, and Rooms - - The special procedures are assigned to the prototypes of the objects -and mobiles, not to the instances themselves. There are functions provided -to assign the special procedures: - - * ASSIGNMOB(,) - * ASSIGNOBJ(,) - * ASSIGNROOM(,) - - Stock CircleMUD also provides a place where to put all the special -procedure assignments: the functions assign_mobiles, assign_objects and -assign_rooms in spec_assign.c. - - -4.4. The Special Procedure Function Header - - The function header of any special procedure is defined in the macro -SPECIAL() and is as follows: - - int ()(struct char_data *ch, void *me, int cmd, char *argument) - -where is the name of the special procedure. - - The parameters to the function are: - - ch : Character that issued the command to command interpreter that - triggered this special procedure. - me : The mobile, object or room to which the special procedure is - given. - cmd : The command that ch issued as recognized by the command - interpreter, or zero if the special procedure is being called - by the pulse code. - argument : The command that the played has introduced at the prompt - or an empty string if the special procedure is being - called by the pulse code. - - -4.5. The Special Procedure Return Value - - The return value of a special procedure is looked at only by the -command interpreter and has meaning only for command-driven special -procedures. Pulsed special procedures should always return false. - - A command-driven special procedure can return two values: - - FALSE : The procedure did not process the command given and it - should be processed in the standard way by the command - interpreter. - TRUE : The procedure reacted to the command given and so, the - command interpreter should ignore it. - - Index: doc/coding.pdf =================================================================== RCS file: doc/coding.pdf diff -N doc/coding.pdf Binary files /dev/null and /tmp/cvs1Ce0zm differ Index: doc/color.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/color.pdf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 Binary files /tmp/cvsMJ7oQV and /tmp/cvsFtXT6u differ Index: doc/files.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/files.pdf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 Binary files /tmp/cvsIsTvn4 and /tmp/cvs5GwnED differ Index: doc/hacker.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/hacker.pdf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 Binary files /tmp/cvsjymmVc and /tmp/cvsGoyYcM differ Index: doc/license.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/license.pdf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 Binary files /tmp/cvsnG9Lul and /tmp/cvsEgN0MU differ Index: doc/porting.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/porting.pdf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 Binary files /tmp/cvszLCo5t and /tmp/cvsswSjo3 differ Index: doc/release.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/release.pdf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 Binary files /tmp/cvsRhjpHC and /tmp/cvsAqTX0b differ Index: doc/socials.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/socials.pdf,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 Binary files /tmp/cvszH5GkL and /tmp/cvs2LENEk differ Index: doc/utils.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/utils.pdf,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 Binary files /tmp/cvsD4s2YT and /tmp/cvsSCvqjt differ Index: doc/wizhelp.pdf =================================================================== RCS file: /home/circledb/.cvs/circle/doc/wizhelp.pdf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 Binary files /tmp/cvsda4XD2 and /tmp/cvss9XTYB differ Index: doc/sources/FAQ.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/FAQ.tex,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 --- doc/sources/FAQ.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/FAQ.tex 18 Nov 2002 23:22:25 -0000 1.3 @@ -1,6 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} \usepackage{times} +\usepackage[T1]{fontenc} \usepackage{varioref} % Document typeset from the original document that was typeset by Alex Fletcher. % This document typeset by Alex Fletcher on Dec 9/2001 @@ -15,7 +16,7 @@ \title{Frequently Asked Questions (FAQ) for CircleMUD with Answers} \author{Alex Fletcher\\ -\texttt{furry@circlemud.org}} +\texttt{$<$furry@circlemud.org$>$}} \begin{document} \maketitle @@ -63,10 +64,9 @@ and is from the Gamma v0.0 of DikuMud cr Madsen, Michael Seifert and Sebastian Hammer at DIKU (Computer Science Instutute at Copenhagen University). Note that CircleMUD is a Diku derivative, so its users must follow the DIKU license agreement -- most notably that it cannot be used to make money in {\em ANY} way, the original developers' names must be in the login screen that the \texttt{credits} command always presents the same information, etc.\newline Quoting from CircleMUD's \texttt{release.doc}: \begin{quote} -``CircleMUD is highly developed from the programming side, but highly UNdeveloped on the game-playing side. So, if you're looking for a huge MUD with billions of spells, skills, classes, races, and areas, Circle will probably disappoint you severely. Circle still has only the 4 original Diku classes, the original spells, the original skills, and about a couple dozen areas. On the other hand, if you're looking for a highly stable, well-developed, well-organized ``blank slate'' MUD on which you can put your OWN ideas for spells, skills, classes, and areas, then Circle might be just what you're looking for.'' +``CircleMUD is highly developed from the programming side, but highly UNdeveloped on the game-playing side. So, if you're looking for a huge MUD with billions of spells, skills, classes, races, and areas, Circle will probably disappoint you severely. Circle still has only the 4 original Diku classes, the original spells, the original skills, and about a couple dozen areas. On the other hand, if you're looking for a highly stable, well-developed, well-organized ``blank slate'' MUD on which you can put your {\em OWN} ideas for spells, skills, classes, and areas, then Circle might be just what you're looking for.'' \end{quote} -The latest full production release of Circle is 2.20, released on November 17, 1993. -Currently 3.0 is in beta, at patch level 20, released on January 15, 2002. +The latest full production release of Circle is 2.20, released on November 17, 1993. Version 3.1, the result of the version 3.0 beta patchlevel stream was released on November 18, 2002. \subsection{What is the history of CircleMUD?} \begin{itemize} @@ -76,8 +76,8 @@ Currently 3.0 is in beta, at patch level \item Version 2.10: September 1, 1993 \item Version 2.11: September 19, 1993 \item Version 2.20: November 17, 1993 +\item Version 3.1: November 18, 2002 \end{itemize} -Version 3.00 is currently in beta right now and is up to patchlevel 19. The final release is due out Real Soon Now(tm). Don't bother posting requests for it. It will be out when the CircleMUD group gets it done, and it will be announced on the mailing list and the newsgroup \texttt{rec.games.mud.diku}. \subsection{Where is the original CircleMUD so I can check it out?} CircleMUD is a public code base, freely distributable, but the authors of Circle do not actually run one personally. There used to be CircleMUD, and while the CircleMUD group continues to develop it, there is no original CircleMUD any more. To see other MUDs that are using the CircleMUD code base, check out the CircleMUD Site List \url{}. @@ -113,9 +113,9 @@ To subscribe, send a message to the list To unsubscribe from the list send a message to the same address with the words \texttt{unsubscribe circle} as the message body. {\em DO NOT} send unsubscription requests to the list in general. There are hundreds of people on the list, and it will only irritate a ton of people who have no power to remove you from the list. Read the Mailing List FAQ \url{} for more information. \subsection{To what platforms has CircleMUD been ported?} -Version 3.0, although still officially in beta-testing, is very portable because it uses the GNU autoconf system, meaning you only need to type ``configure'' to have it automatically determine various features of your system and configure the code accordingly. 3.0 compiles without changes under most BSD and SVR4 systems, including SunOS, Solaris, Ultrix, IRIX, AIX, Linux, BSD/OS, HP/UX, Mac OS X, and others. +Version 3.1 is very portable because it uses the GNU autoconf system, meaning you only need to type ``\texttt{configure}'' to have it automatically determine various features of your system and configure the code accordingly. 3.1 compiles without changes under most BSD and SVR4 systems, including SunOS, Solaris, Ultrix, IRIX, AIX, Linux, BSD/OS, HP/UX, Mac OS X, and others. \par -Version 3.0 is also being ported to various non-UNIX platforms. As of patchlevel 14, you can compile Circle under OS/2 2.x and 3.x with the OS/2 port of gcc, Windows 95/NT using Microsoft Visual C++ versions 4.0 through 6.0, Borland (now Inprise) C++ 4.5, Watcom v.11, Cygnus GNU-WIN32, LCC, Macintosh OS 9 (and earlier) with CodeWarrior, Amiga, and Acorn RiscOS. +Version 3.1 has also been ported to various non-UNIX platforms. As of patchlevel 14, you can compile Circle under OS/2 2.x and 3.x with the OS/2 port of gcc, Windows 95/NT using Microsoft Visual C++ versions 4.0 through 6.0, Borland (now Inprise) C++ 4.5, Watcom v.11, Cygnus GNU-WIN32, LCC, Macintosh OS 9 (and earlier) with CodeWarrior, Amiga, and Acorn RiscOS. \par The older version of the code, Version 2.20, compiles mainly on BSD UNIX systems but has some trouble under SVR4-based systems such as Solaris. The authors have personally compiled and tested v2.20 under Ultrix 4.0, IRIX 4.0.1, 4.0.4 and 4.0.5, SunOS 4.1.1 and 4.1.3, AIX 3.2, Linux 0.99.x and 1.0.x, and ConvexOS V10.2. Users have reported that v2.20 compiles with relatively minor changes under NeXTStep 2.1 and 3.0, and HP/UX 9.0. \par @@ -162,15 +162,14 @@ Finally, in modern patches, there are th Because Circle is written in ANSI C, and the standard C compilers distributed by Sun and HP are not capable of compiling ANSI C code. You can try the ANSI C compilers, but both cost extra money so your sysadmin may not have installed it. Most don't. The best solution is to get the GCC compiler from the GNU FTP site \url{} and install it, if you have enough time and space. \subsection{Why do I get all sorts of errors with ``crypt'' functions and header files?} -{\em (This information applies ONLY to Version 3.0 of the code.)} CircleMUD normally uses the UNIX \texttt{crypt()} function to encrypt players' passwords. Because of export restrictions imposed by the U.S., some systems do not have the \texttt{crypt()} function. ``configure'' will usually be able to figure out whether or not your system has \texttt{crypt()}, but if it guesses incorrectly and you see problems with the \texttt{crypt()} function or headers, you can manually disable password encryption by going into the \texttt{sysdep.h} source -file and uncommenting the line that reads: +{\em (This information applies ONLY to Version 3 of the code.)} CircleMUD normally uses the UNIX \texttt{crypt()} function to encrypt players' passwords. Because of export restrictions imposed by the U.S., some systems do not have the \texttt{crypt()} function. ``configure'' will usually be able to figure out whether or not your system has \texttt{crypt()}, but if it guesses incorrectly and you see problems with the \texttt{crypt()} function or headers, you can manually disable password encryption by going into the \texttt{sysdep.h} source file and uncommenting the line that reads: \begin{verbatim} #define NOCRYPT \end{verbatim} Be warned, however, that doing this causes the MUD to store players' passwords in plain text rather than as encrypted strings. Also, if you move from a system which has crypt to one that doesn't, players won't be able to log in with their old passwords! \subsection{When I try to compile, why do I get a lot of undefined symbols referenced in comm.o for functions like socket, accept, and bind?} -SVR4 systems require the socket and nsl libraries for network programs. You shouldn't see this error any more with version 3.0 because ``configure'' should automatically use those libraries for you; however, if you still have problems, try adding ``-lsocket -lnsl'' to the line in the \texttt{Makefile} that links all the object files together into the `circle' binary. +SVR4 systems require the socket and nsl libraries for network programs. You shouldn't see this error any more with version 3 because ``configure'' should automatically use those libraries for you; however, if you still have problems, try adding ``-lsocket -lnsl'' to the line in the \texttt{Makefile} that links all the object files together into the `circle' binary. \par If you're using V2.20 and you have this error, the best thing to do is simply to use V3.0 instead. If you insist on using 2.20, go into the \texttt{Makefile} and search for the comment next to ``SVR4''. @@ -187,12 +186,12 @@ You can remove the whole kernel source t (Thanks to Michael Chastain for providing this answer.) \subsection{I'm getting compilation errors from a header file, and I didn't even change it?} -Okay, if you really didn't change ``structs.h'' then the error isn't in ``structs.h''. We have seen numerous cases where this has happened, the first, is that the header file you included right before the header file messing has an error in it. We can't really say much beyond that, but look for a missing semicolon, are any other errors you can find. +Okay, if you really didn't change ``\texttt{structs.h}'' then the error isn't in ``\texttt{structs.h}''. We have seen numerous cases where this has happened, the first, is that the header file you included right before the header file messing has an error in it. We can't really say much beyond that, but look for a missing semicolon, are any other errors you can find. \par -If you include files out of order, it can mess things up. For example, B.h has stuff in it that is defined in A.h, and if you include B.h before A.h, you can get errors, your best bet here is to mess with the order of the headers, making sure you put ``conf.h'' and ``sysdep.h'' at the top, followed by ``structs.h'', ``utils.h'', etc. Any file specific headers should be the last one included just for coding style. +If you include files out of order, it can mess things up. For example, B.h has stuff in it that is defined in A.h, and if you include B.h before A.h, you can get errors, your best bet here is to mess with the order of the headers, making sure you put ``\texttt{conf.h}'' and ``\texttt{sysdep.h}'' at the top, followed by ``\texttt{structs.h}'', ``\texttt{utils.h}'', etc. Any file specific headers should be the last one included just for coding style. \subsection{I'm trying to compile the mud on Windows '95 and am having problems, what can I do?} -The first thing to do is to make sure you are compiling a recent version of the source code. Patch Level 11 and onwards all support Windows 95 winsock sockets now. Second, you should ensure that you have carefully read the \texttt{README.WIN} file for instructions on what to include. +The first thing to do is to make sure you are compiling a recent version of the source code. Patch Level 11 and onwards all support Windows '95 winsock sockets now. Second, you should ensure that you have carefully read the \texttt{README.WIN} file for instructions on what to include. Next, ensure that you are using a C compiler that supports long filenames (for example, MSVC 4.0 does, MSVC 1.0 does not). If you happen to be trying to patch something into your code, you should use one of the Cygnus Tools mentioned in section~\vref{patchfile}. \subsection{How can I do a ``grep'' on Windows 95?} @@ -551,19 +550,18 @@ to \end{verbatim} where ``i'' is either ``ch'' or ``d-$>$character'' depending on the call. -\section{CircleMUD 3.0 Questions} +\section{CircleMUD 3.1 Questions} \subsection{Are there any bugs in the current release?} There are no bugs. Only features. Seriously though, if perchance you find a bug, please mail it (along with a possible fix) to \url{} the bugs database \url{} and the CircleMUD list. Once in the bug database, it will be routed to the correct person. Note that no confirmation is sent back automatically. You can view the status of the bug at the bugs database \url{}. \subsection{How do I access Online Creation?} -Online Creation is not yet part of the Circle beta release. When it does become part of the release, it'll be accessed through a command called olc. Update: OLC will probably be in a future release rather than 3.0. In the mean time, check out the CircleMUD FTP server -\url{}. +Online Creation is not yet part of the Circle release. When it does become part of the release, it'll be accessed through a command called olc. OLC will probably be in a future release. In the mean time, check out the CircleMUD FTP server \url{}. \subsection{How does the new bitvector system work?} The new bitvector system in CircleMUD 3.0 is an ascii based one. The old numeric values can still be used, but the new system should make sorting flags out substantially easier. The system uses an ``a'' as the value for 1, ``b'' for 2, ``c'' for 4, ``d'' for 8, etc. Once ``z'' is reached, the next letter in sequence is ``A''. Detailed information about how to use bitvectors with CircleMUD can be found in the CircleMUD Building Manual \url{}. -\subsection{When will the production release of Circle 3.0 be?} -I don't know. Don't ask again. Same for the next patch level. If you must have bleeding edge stuff, check out the CVS snapshot \url{} if you do not want to set up an anonymous CVS account. Don't ask when the next CVS snapshot will be, we'll do it when we have some changes worth it. +\subsection{When will the production release of Circle 3.1 be?} +It's out. The following release? I don't know. Don't ask again. If you must have bleeding edge stuff, check out the CVS snapshot \url{} if you do not want to set up an anonymous CVS account. Don't ask when the next CVS snapshot will be, we'll do it when we have some changes worth it. \par There is anonymous read-only access available for the CVS repository. You can access this from your own server (assuming that you also have CVS installed on your machine. To connect to the CircleMUD CVS repository, you need to issue the following commands at your shell prompt: \begin{verbatim} @@ -604,14 +602,10 @@ Unfortunately, the current patchlevel of Hopefully this clears up the way buffers work. \subsection{How do I add a new class? How do I add more levels?} -Adding a new class is fairly easy in 3.0, in fact, someone has taken the time to put together a fairly complete document on adding a class, in this case a Knight class. The \texttt{class.txt} is available on the FTP site \url{}. -\par -The same applies for levels, in the file \texttt{levels.bpl14.txt} \url{} which can be found in the same place. +Adding a new class is fairly easy in 3.1, in fact, the \texttt{coding.pdf} has a section on doing just this. In addition, someone has taken the time to put together a fairly complete document on adding a class, in this case a Knight class. The \texttt{class.txt} is available on the FTP site \url{}. -\subsection{Is there a complete ``coding.doc''?} -No. Look at the \texttt{README.NOW} in the docs directory. It isn't complete, nor does anyone have the entire thing. It is being worked upon. -\par -{\em RTFM} +\subsection{Are there a complete documents?} +Yes and no. We have done our best to provide documentation that is as complete as possible, but it is impossible to have complete and perfect documentation. \par Further information on CircleMUD can be found in other documents in the docs directory, on the CircleMUD webpages \url{}, on the FTP server \url{}, and on the CircleMUD Mailing List (see section~\vref{mailinglist}). \end{document} Index: doc/sources/README =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/README,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/README 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/README 18 Nov 2002 12:11:32 -0000 1.2 @@ -8,7 +8,7 @@ either: or furry@circlemud.org -Please note that these are the first drafts, and changes will be forthcoming +Please note that these are still early drafts, and changes will be forthcoming with future Patch Levels. -Ae. Index: doc/sources/act.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/act.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/act.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/act.tex 18 Nov 2002 03:09:38 -0000 1.2 @@ -1,6 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} \usepackage{times} +\usepackage[T1]{fontenc} \usepackage{varioref} \usepackage{multicol} % Document typeset from the original document that was typeset by Jeremy Elson. Index: doc/sources/admin.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/admin.tex,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 --- doc/sources/admin.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/admin.tex 18 Nov 2002 23:22:25 -0000 1.3 @@ -1,5 +1,8 @@ \documentclass[11pt]{article} \usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} +\usepackage{varioref} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 5/2001 @@ -59,7 +62,7 @@ USE OF THIS SOFTWARE IN ANY CAPACITY IMP \section{Getting Started} \subsection{Section Requirements} -CircleMUD 3.0 was originally written as UNIX software and will automatically configure itself (using GNU autoconf) and compile under most versions of UNIX, both BSD and System V derivatives. With minor adjustments (documented below), the same source should compile under Microsoft Windows 95 and NT, IBM OS/2, and the Amiga. Users have also reported getting Circle to compile and run under MkLinux, the port of Linux to the Power Macintosh. CircleMUD will {\em not} work under DOS, Windows 3.x, Windows for Workgroups 3.x, or Mac System 7. +CircleMUD 3.1 was originally written as UNIX software and will automatically configure itself (using GNU autoconf) and compile under most versions of UNIX, both BSD and System V derivatives, including Mac OS X. With minor adjustments (documented below), the same source should compile under Microsoft Windows 95 and NT, IBM OS/2, and the Amiga. Users have also reported getting Circle to compile and run under MkLinux, the port of Linux to the Power Macintosh. CircleMUD will {\em not} work under DOS, Windows 3.x, Windows for Workgroups 3.x, or Mac System 7. \par Specifically, the following variants of UNIX have been tested and are known to work with Circle: \begin{itemize} @@ -73,7 +76,7 @@ Specifically, the following variants of \item BSD/OS 2.1 \item Mac OS X (10.0 and above) \end{itemize} -If your system is not listed, don't despair; because of the \texttt{autoconf} program, Circle will compile under most versions of UNIX on its own. A large effort was made to make Circle v3.0 more portable by converting many of its system calls over to POSIX compliance. Converting Circle to POSIX vastly helps portability on modern operating systems, most of which are POSIX-compliant. Unfortunately, on some older systems that are not (such as NextSTEP 2.x), it may be more difficult to compile 3.0 than it was to compile earlier versions of the code. (POSIX stands for Portable Operating System Interface for UNIX and is an effort to standardize the way UNIX programs talk to the operating system. For more information, see Stevens' excellent book, {\em Advanced Programming in the UNIX Environment}.) +If your system is not listed, don't despair; because of the \texttt{autoconf} program, Circle will compile under most versions of UNIX on its own. A large effort was made to make Circle v3 more portable by converting many of its system calls over to POSIX compliance. Converting Circle to POSIX vastly helps portability on modern operating systems, most of which are POSIX-compliant. Unfortunately, on some older systems that are not (such as NextSTEP 2.x), it may be more difficult to compile version 3 than it was to compile earlier versions of the code. (POSIX stands for Portable Operating System Interface for UNIX and is an effort to standardize the way UNIX programs talk to the operating system. For more information, see Stevens' excellent book, {\em Advanced Programming in the UNIX Environment}.) \par For a small, private MUD, or a MUD used only for testing and development, about 10 MB of disk space and 16 MB of memory should be sufficient. For large, public MUDs with a large player base, 30 to 50MB of disk space and at least 32 MB of memory are recommended. Free memory is much more important than CPU speed; CircleMUD uses virtually no CPU time. \par Index: doc/sources/building.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/building.tex,v retrieving revision 1.3 retrieving revision 1.4 diff -u -p -r1.3 -r1.4 --- doc/sources/building.tex 6 Sep 2002 12:06:56 -0000 1.3 +++ doc/sources/building.tex 18 Nov 2002 23:22:25 -0000 1.4 @@ -435,7 +435,7 @@ The format of mobiles varies depending o \end{verbatim} \item[Type Flag] This flag is a single letter which indicates what type of mobile is currently being defined, and controls what information CircleMUD expects to find next (i.e., in the file from the current point to the end of the current mobile). \par -Standard CircleMUD 3.0 supports two types of mobiles: \texttt{S} (for Simple), and \texttt{E} (for Enhanced). Type \texttt{C} (Complex) mobiles was part of the original DikuMUD Gamma and part of CircleMUD until version 3.0, but are no longer supported by CircleMUD v3.0 and above. +Standard CircleMUD 3.1 supports two types of mobiles: \texttt{S} (for Simple), and \texttt{E} (for Enhanced). Type \texttt{C} (Complex) mobiles was part of the original DikuMUD Gamma and part of CircleMUD until version 3.0, but are no longer supported by CircleMUD v3.0 and above. \par Check with your local implementor to see if there are any additional types supported on your particular MUD. \end{description} @@ -510,7 +510,7 @@ afghq p -200 S \par This is mobile vnum 3062. The Fido's action bitvector indicates that it has a special procedure (bit a), is aggressive (bit f), stays in its own zone (bit g), is wimpy (bit h), and cannot be bashed (bit q). Also, the Fido cannot be tracked (affection bit p), and has an initial alignment of -200. After the \texttt{S} flag we see that the Fido is level 0, has a THAC0 of 20, an Armor Class of 10, 1d6+4 hit points (a random value from 5 to 10), and will do 1d4 hit points of bare hand damage per round. The Fido has 0 gold and 25 experience points, has a load position and default position of STANDING, and is male. \subsection{Type E Mobiles} -Type E mobiles are specific to Circle 3.0 and are designed to provide an easy way for MUD implementors to extend the mobile format to fit their own needs. A type E mobile is an extension of type S mobiles; a type E mobile is a type S mobile with extra data at the end. After the last line normally found in type S mobs (the one ending with the mob's sex), type E mobiles end with a section called the Enhanced section. This section consists of zero or more enhanced mobile specifications (or {\bf E-specs}), one per line. Each E-spec consists of a keyword followed by a colon (``:'') and a value. The valid keywords are listed below. The literal letter \texttt{E} must then come after all E-specs to signal the end of the mob.\newline +Type E mobiles are specific to Circle 3.1 and are designed to provide an easy way for MUD implementors to extend the mobile format to fit their own needs. A type E mobile is an extension of type S mobiles; a type E mobile is a type S mobile with extra data at the end. After the last line normally found in type S mobs (the one ending with the mob's sex), type E mobiles end with a section called the Enhanced section. This section consists of zero or more enhanced mobile specifications (or {\bf E-specs}), one per line. Each E-spec consists of a keyword followed by a colon (``:'') and a value. The valid keywords are listed below. The literal letter \texttt{E} must then come after all E-specs to signal the end of the mob.\newline The format of an E mobile is as follows: \begin{verbatim} @@ -541,8 +541,8 @@ E \end{verbatim} In the above example, the two E-specs used were BareHandAttack and Str. Any number of the E-specs can be used in an Enhanced section and they may appear in any order. The format is simple: the E-spec keyword, followed by a colon, followed by a value. Note that unlike type S mobiles, type E mobiles require a terminator at the end of the record (the letter \texttt{E}). -\subsection{E-Spec Keywords Valid in CircleMUD 3.0} -The only keywords supported under Circle 3.0 are BareHandAttack, Str, StrAdd, Int, Wis, Dex, Con, and Cha. However, the E-Specs have been designed such that new ones are quite easy to add; check with your local implementor to see if your particular MUD has added any additional E-Specs. Future versions of CircleMUD will have considerably more features available in the Enhanced section such as the ability to individually set mobs' skill proficiencies. +\subsection{E-Spec Keywords Valid in CircleMUD 3.1} +The only keywords supported under Circle 3.1 are BareHandAttack, Str, StrAdd, Int, Wis, Dex, Con, and Cha. However, the E-Specs have been designed such that new ones are quite easy to add; check with your local implementor to see if your particular MUD has added any additional E-Specs. Future versions of CircleMUD will have considerably more features available in the Enhanced section such as the ability to individually set mobs' skill proficiencies. \begin{description} \item[BareHandAttack] This controls the description of violence given during battles, in messages such as ``The Beastly fido bites you very hard.'' BareHandAttack should be one of the following numbers: \begin{verbatim} @@ -1072,10 +1072,10 @@ S \end{verbatim} \section{Shop Files} -CircleMUD v3.0 now has a new shop file format. Since the old format is still supported, both formats will be documented. If you'd like to convert shop files in the old format to that of the new format, compile and run the utility \texttt{shopconv}. 3.0 shops must have a special marker (described below) to tell the server that the file is in the new format. +CircleMUD v3 now has a new shop file format. Since the old format is still supported, both formats will be documented. If you'd like to convert shop files in the old format to that of the new format, compile and run the utility \texttt{shopconv}. Version 3 shops must have a special marker (described below) to tell the server that the file is in the new format. -\subsection{CircleMUD v3.0 Shop Format} -The overall format of a v3.0 Shop File is: +\subsection{CircleMUD v3 Shop Format} +The overall format of a v3 Shop File is: \begin{verbatim} CircleMUD v3.0 Shop File~ @@ -1086,7 +1086,7 @@ CircleMUD v3.0 Shop File~ $~ \end{verbatim} -3.0 shop files start with the literal line ``\texttt{CircleMUD v3.0 Shop File\~{}}'', followed by any number of shop definitions, and terminated by \$\~{}. The format of a shop definition is: +Version 3 shop files start with the literal line ``\texttt{CircleMUD v3.0 Shop File\~{}}'', followed by any number of shop definitions, and terminated by \$\~{}. The format of a shop definition is: \begin{verbatim} #~ @@ -1186,7 +1186,7 @@ A brief note: Shopkeepers should be har \end{verbatim} \end{description} -\subsection{Item Name Lists for 3.0 Shops} +\subsection{Item Name Lists for v3 Shops} Name lists are formed by boolean expressions. The following operators are available: \begin{verbatim} ',^ = Not *, & = And +, | = Or @@ -1213,7 +1213,7 @@ WEAPON [sword & (long|short) | warhammer You can also include object extra flags (listed in the section ``Format of an Object'' above). The previous example used ``magic'' as a keyword that had to be on the object. If we wanted to make it so that the MAGIC flag had to be set on the item, we would change ``magic'' to ``MAGIC''. Similar changes could be made to add other flags such as ``HUM'' or ``GLOW''. It should be noted that these expressions are case sensitive and that all keywords should appear in lower-case, while the flag names should be in all caps. \subsection{The DikuMud Gamma and CircleMUD 2.20 Shop Format} -This format is obsolete but is presented because it is still supported by CircleMUD 3.0. In most cases, it is strongly recommended to simply use the \texttt{shopconv} utility shipped with Circle to convert older shop files to the new format. +This format is obsolete but is presented because it is still supported by CircleMUD 3.1. In most cases, it is strongly recommended to simply use the \texttt{shopconv} utility shipped with Circle to convert older shop files to the new format. \begin{verbatim} #num~ Shop Number (Used only for display purposes) @@ -1307,7 +1307,7 @@ Time when open end 2 \appendix \section{Spell Numbers} -These spell numbers are the spells shipped by default with CircleMUD 3.0. Note that most implementors add new spells so this list may not be complete for your particular MUD. Check with your implementor for details. +These spell numbers are the spells shipped by default with CircleMUD 3.1. Note that most implementors add new spells so this list may not be complete for your particular MUD. Check with your implementor for details. \begin{verbatim} animate dead 45 armor 1 Index: doc/sources/coding.tex =================================================================== RCS file: doc/sources/coding.tex diff -N doc/sources/coding.tex --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ doc/sources/coding.tex 18 Nov 2002 03:09:38 -0000 1.1 @@ -0,0 +1,855 @@ +\documentclass[11pt]{article} +\usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} +% Document typeset from the original document that was typeset by Jeremy Elson, +% George Greer, and others +% This document typeset by Alex Fletcher on Nov 5/2002 + +\addtolength{\topmargin}{-.5in} % repairing LaTeX's huge margins... +\addtolength{\textheight}{1in} % more margin hacking +\addtolength{\textwidth}{1in} % and here... +\addtolength{\oddsidemargin}{-0.5in} +\addtolength{\evensidemargin}{-0.5in} +\setlength{\parskip}{\baselineskip} +\setlength{\parindent}{20pt} +\newenvironment{Ventry}[1] + {\begin{list}{}{\renewcommand{\makelabel}[1]{\textsf{##1:}\hfil} + \settowidth{\labelwidth}{\textsf{#1:}} + \setlength{\leftmargin}{\labelwidth} + \addtolength{\leftmargin}{\labelsep} + } + } + {\end{list}} + +\title{How To Convert Your Ideas Into Reality\\ +A CircleMUD Coding Manual} +\author{Jeremy Elson and the rest of the CircleMUD Group\\ +$<$cdev@circlemud.org$>$\\ +Section 4 written by Luis Pedro Passos Carvalho\\ +$<$lpcarvalho@SONAE.PT$>$} +\begin{document} + +\maketitle + +\begin{abstract} +This is a guide to writing C code for use with CircleMUD. Includes a description of commonly used functions, tips on how to add new commands and spells, and other commonly asked coding questions. Good familiarity with both C and UNIX is assumed, although system-level UNIX C programming skill not required. The intended audience is for CircleMUD coders, and this document does not cover area-building. See the building document for details on that. +\par +More information about CircleMUD, including up-to-date versions of this documentation in ASCII and Postscript, can be found at the CircleMUD Home Page \url{} or +FTP site \url{} +\end{abstract} + +\tableofcontents + +\section{Introduction} +When DikuMUD was first released in 1990, the authors were rightly more concerned with getting their product released than with little cosmetic details. Between writing 25,000 lines of C code and building the entire DikuMUD world, complete with objects, rooms, and monsters, it's understandable that making the code portable or clean was not at the top of the list of their priorities. Most DikuMUD distributions were not portable and had a number of bad bugs and even syntax errors which prevented the code from compiling at all. If a potential MUD implementor wanted to run a Diku, an excellent knowledge of C was necessary, because the MUD simply wouldn't run otherwise. +\par +Now the situation is much different. With the proliferation of user-friendly code bases such as Merc and Circle, any Average Joe can just type ``make'' and inflict yet another MUD on the world. Therefore, the number of truly unique MUDs as a fraction of the total is dropping drastically because coding experience is no longer a prerequisite to being able to put a MUD up on the `Net. Some people may tell you that you don't need to know how to code in order to run a MUD -- don't believe them. Those people are wrong. +\par +If you want your MUD to succeed and flourish, you'll have to know how to code in C. Otherwise, your MUD will be exactly like every other MUD out there. You're not the only person who knows how to type \texttt{make}! Although the quality and originality of your areas is also very important, it is the code that transforms the areas from lifeless text files into a living, breathing virtual world. If you don't know how to code, you won't be able to add new features, respond to requests of your players, add new world flags for your area builders, or even fix the simplest of bugs. Running a MUD without knowing how to code is certainly a recipe for disaster. If you're a great game-player and have some terrific ideas about how a MUD should work, but don't know how to code, you should either learn or find a good coder who can join your team. Don't assume that you can get away with running a MUD without knowing C -- you can't. Not for very long, anyway. +\par +This document won't teach you how to program in C; you'll have to learn that on your own. Instead, it will try to familiarize you with the way Circle's code is structured so that you can put your C skills to good use. Even for the best programmers, it takes a while to ``get into'' a program and feel comfortable enough with the way it works to start modifying it. Hopefully, by reading this manual, your breaking-in period for getting to know Circle will be minimized. +\par +Circle consists of close to 30,000 lines of moderately dense C code, so you shouldn't expect familiarity to come overnight. The best way to learn is to DO. Get your hands dirty! Don't be afraid to tinker with things. Start small by modifying existing functions. Then, work your way up to creating new functions by copying old ones. Eventually you'll be able to write completely original functions, and even tear some of Circle's native functions out as you realize completely new ways of implementing them! But you should learn to walk before you try to run. +\par +Most of all, try to remember that coding for a MUD should be fun. It can sometimes be easy to lose site of the ultimate goal of personal enjoyment that MUDs are supposed to provide, particularly when they start to get crushed under the weight of their own politics or the egos of their administrators. If you enjoy coding, but find yourself spending more time on politics than you are on code, don't be afraid to restructure your MUD or even remove yourself as Imp to a lower wizard position which requires less politics. +\par +People often ask me why I do so much work on CircleMUD. They want to know why I spend so much time writing code {\em only} for the purpose of letting other people use it, since I don't actually run a MUD myself. After reading the preceding paragraph, the answer to that question should be clear. I've spent considerable time coding for on-line MUDs in the past, but after a while it just wasn't fun any more. I eventually found myself doing nothing but working politically and doing virtually no coding at all. Eventually, I even lost the will to write code completely. By quitting from my various Immortal positions on every MUD I was of which I was a member, and concentrating on my public Circle releases, I have the luxury of enjoying MUD coding in its purest form: all code, no politics. Well, almost none, anyway -- my past still comes back to haunt me now and then. :) +\par +A final thought: nothing will turn potential players away from your MUD more than logging in and finding that it's exactly like half the other CircleMUDs out there. Strive to show the world something new and unique. And may the source be with you. + +\section{Overview and Coding Basics} +Before getting down to the details of learning how to write code, we will first examine generally what a MUD is and what it does, to give you an overview of what type of program you're working with. +\par +The first section, ``An Internet Server Tutorial'', describes how Internet servers such as CircleMUD work. It contains interesting background material if you'd like a deeper understanding of how the MUD actually interacts with the Internet and the computer on which it runs, but little practical coding advice. So, if you're reading this document purely to learn how to write MUD code, you should skip to the second section. + +\subsection{An Internet Server Tutorial} +An Internet ``server'' is a program which provides some service to Internet users (called ``clients''). There are many different types of servers on the Internet. FTP servers allow you to transfer files between a remote computer and your own. Telnet servers allow you to connect to remote machines. News servers allow you to read USENET news. Similarly, CircleMUD +is a server which allows you to play a game. +\par +However, MUDs such as CircleMUD differ from most Internet servers in several very important ways. When ten different people connect to CircleMUD, they can all interact with one another. CircleMUD -- a single program -- must be aware of many users at the same time. On the other hand, most other Internet servers such as FTP servers are written to only be aware of {\em one} +user at a time. If more than one user wants to use an FTP server simultaneously, the operating system runs two copies of the server: one to handle each user. Each individual copy of the FTP server is not aware of anything but the single user it has been assigned to serve. +\par +This approach of making one copy of the program per user works quite well with an FTP server because all the users of an FTP server do not need to interact with one another. However, this approach does not work well at all with MUDs, because it makes the task of allowing users to communicate and interact with each other quite difficult. +\par +In addition, most simple Internet servers do not actually contain any network code -- the Internet superserver (\texttt{inetd}) contains most of the code to perform the network magic, allowing the individual servers such as FTP and telnet to be network-unaware for the most part, simply reading from standard input and writing to standard output as if a user at a normal terminal was using the program. The Internet superserver is responsible for setting up standard input and standard output so that they are actually network sockets and not a text terminal. +\par +To sum up, a MUD such as CircleMUD does not have the luxury of being able to handle multiple users by allowing the operating system to make many copies of the MUD. The MUD itself must be capable of handling many users. The MUD also doesn't have the luxury of allowing a pre-written program such as \texttt{inetd} to set up its network connections. The MUD itself is responsible for setting up and keeping track of all of its own network connections, as well as splitting its time evenly among all of its players. The MUD cannot stop and wait for a player to type something -- if it stops and waits for that player, the MUD will appear to have frozen from the point of view of all the +other players! +\par +Let's make this idea more concrete with an example. Imagine that your first programming assignment in a C class is to write a simple calculator that gets two numbers from a user as input, multiplies them together, and then prints the product on the screen as output. Your program would probably be quite simple: it would prompt the user for the two numbers, then stop and wait while the user types the numbers in. +\par +Now, imagine that your project is to write a program that lets 10 people simultaneously connect to your calculator and multiply their own numbers together. Forget for a moment the problem of how to write the network code that allows people to connect to your program remotely. There is a more +fundamental problem here: your original strategy of stopping and waiting for the user to type input won't work any more. With one user, that worked fine. But what will happen with 10 users? +\par +Let's say your program stops and waits for the first user to type something. Now, what happens if the second user types something in the meantime? The program will not respond to the second user because it is still waiting for a response from the first user. Your simple calculator has +suddenly become much more complex -- now, it must constantly cycle through all users, asking the operating system if any one of them have typed something, without ever stopping to wait for a single user. When input comes in from any one of the users, your program must immediately process it and move on to the next user. +\par +Let's say that you've written a program which does the cycling among users described in the previous paragraph. Now, imagine that the operating system tells you that User 4 has just typed the number 12. You might be able to see the second problem: what does that 12 mean? Is 12 the first or second multiplicand for your calculator? Should you immediately multiply the 12 with some other number, or store it and wait for another number to multiply by 12? +\par +Your simple calculator has become more complicated again! Now, in addition to cycling through all users to check if any have typed anything, you must remember the STATE each user is in. In other words, each user might start out in a state called ``Waiting for First Number.'' If a user types a +number while she's in the ``Waiting for First Number'' state, you'd store her number somewhere and move her into the ``Waiting for Second Number'' state. If she types a number while in the ``Waiting for Second Number'' state, you'd retrieve the first number from memory, multiply it by the number just typed, and print the result. Of course, each user can be in a different state -- there is no global state shared by all users. +\par +Now, you might be able to see how this calculator example relates to CircleMUD. Let's say that the MUD receives the string, ``Sleep'' from a user. What should Circle do with this string? Maybe the user is trying to log in, typing her name which happens to be ``Sleep''. Maybe the user is typing in her password. Maybe the user is already logged in, and is trying to go to sleep! Just like with our calculator, the MUD knows how to interpret data it receives from users by examining the users' state. +\par +You can see a list of all possible players' states in \texttt{structs.h} (they all start with ``\texttt{CON\_}''). All users are put into the \texttt{CON\_GET\_NAME} state when they first connect to the MUD. \texttt{CON\_GET\_NAME} simply means that the MUD is waiting for the user to type her name, at the ``By what name do you wish to be known?'' prompt. The normal state that most players are in most of the time is the \texttt{CON\_PLAYING} state, which indicates that they have already logged in and are playing normally. +\par +Now, let's go back to our previous example and trace exactly what happens when you type ``Sleep''. First, you type ``Sleep.'' Then, your computer sends the string ``Sleep'' over the Internet to the computer on which the MUD is running. Within one tenth of a second, Circle checks with the operating system to see if any of its users have typed anything. When Circle gets to you, it asks the operating system, ``Has this user typed anything?''. Since you typed ``Sleep'', the operating system will respond, ``Yes!''. The MUD will then ask the operating system to deliver the message and will read your message of ``Sleep''. (All the magic of talking to the operating system and checking to see whether or not you've typed anything happens in \texttt{comm.c}.) +\par +So, now that the MUD now knows that you've typed ``Sleep'', it has to decide which of several function in \texttt{interpreter.c} should get control next. This depends on what state you're in. If you're in the normal \texttt{PLAYING} state, it will pass control to a function called \texttt{command\_interpreter}, which will interpret ``Sleep'' as a normal command and put you to sleep. If you're in any other state, control goes to a function called nanny, which is responsible for handling all sockets in any state other than \texttt{PLAYING}. nanny checks what state you're in and acts accordingly. For example, if you're in the \texttt{GET\_NAME} state, nanny activates the code to check whether or not "Sleep" is the name of a known player (in which case it puts you into the state asking for your password), or a new player (in which case it'll ask you the question, ``Did I get that right, Sleep?''.) +\par +In a nutshell, that's how CircleMUD interacts with the Internet. If you don't understand all the details, don't worry -- it's not necessary to understand things on this level to be a successful MUD coder. If you are interested, however, there are some excellent references you can read for more +information: +\par +"Internetworking with TCP/IP" by Douglas Comer. The canonical text describing Internet protocols; comes in three volumes. Volume 1 gives an excellent description of how Internet protocols, error handling, routing, and nameservice works. Volume 3 describes specifics of writing Internet Servers in C. (Volume 2 describes how Internet protocols are implemented by operating systems and is not as apropos to this discussion.) +\par +"Advanced Programming in the UNIX Environment" by Richard Stevens. An excellent UNIX reference for the serious system programmer. Describes POSIX quite well -- worth its weight in gold for anyone trying to write portable UNIX applications. Sections on signal semantics and non-blocking I/O particularly apropos to Internet servers. +\par +"UNIX Network Programming" by Richard Stevens. Similar to Volume 3 of Comer's series, but goes into more detail in several areas, and offers more practical code examples. + +\subsection{The Way Things Work -- Overview} + +\subsubsection{Boot Phase} +CircleMUD is a complex system of code, data files, and external input all interacting in fun, unexpected ways. As with any program, it doesn't just spring into existence ready to play, but must cull information from the administrator and the system itself to determine how it should begin. +\par +The first action by CircleMUD on startup is to check for the existence of any command-line parameters, as seen in the \texttt{main()} function. These can have radical impact on CircleMUD's operation so it must check them before any other action. For example, CircleMUD might be given the \texttt{-d} parameter, specifying an alternate library directory, so it cannot have done any processing on data files prior to the command-line reading. +\par +After finishing the immediate input, the next step is to be able to communicate to the outside world. The communication may be either the ``standard error'' file descriptor or a file, depending on the command-line options and whichever CircleMUD succeeds in opening. +\par +From here there are two possible branches depending on administrator input. If ``Syntax Check'' mode is enabled, then we load only the world. Otherwise, we start initializing the game in preparation for loading the world and accepting players. Since syntax checking is a subset of the normal startup phase, this document shall follow only the most common action of a non-syntax-check boot. +\par +A few minor items precede the loading of the world: initializing the random number generator, creating the \texttt{.killscript} file, finding (or guessing) the maximum number of players the operating system will allow simultaneously, and opening the file descriptor later to be used to accept connections. This early opening of the ``mother'' file descriptor is why there is a period of time during startup where a player connection will be accepted but not receive a login prompt. CircleMUD does not check for connection attempts while it loads the world database but the operating system will complete the connection anyway and post notification to be seen later. +\par +The world loading starts by reading in the MUD date and a few simple text files for player reference. If the date file cannot be loaded, then a default date is provided for the calculations. After randomly generating the weather, in the date function, the following user text files are loaded: news, credits, mortal message of the day, immortal message of the day, help default message screen, general MUD info, wizard list, immortal list, policies, immortal handbook, background story, and login greeting screen. These files are reproduced verbatim by various user commands and exist for the players and/or administrators to read. The MUD doesn't interpret these in any way. +\par +Next, the spell definitions are loaded for player use. The \texttt{spello()} function gives such important information as casting cost, valid targets (area, self, etc.), spell type, valid casting positions (sitting, standing, etc.), spell name, and wear off message. Any skill or spell that isn't set up via \texttt{mag\_assign\_spells()} will not be usable even if appropriate code exists elsewhere that would make it have an effect. Any spell defined here that does not have appropriate code elsewhere to handle it will do nothing when used. +\par +As far as the game world, the zones must be loaded first to define the structure of the rest of the objects. The \texttt{lib/world/zon/index} file is first consulted for the list of zone files that are requested to load. The \texttt{index.mini} file is used in the event mini-MUD mode was requested +earlier on the command line. Each zone file is read in order to pull in the name, description, reset time, room range, and zone commands. Any error on loading will result in the MUD aborting startup. The rooms are read next from \texttt{lib/world/wld/index} in the same manner as the zones, with the added restriction that each room must fall within the ranges defined by the previously-loaded zones. This restriction ensures the code can access the zone record of a room without worrying about any rooms not having an associated zone. +\par +The rooms, as loaded, contain virtual numbers of the rooms they are supposed to exit to. It is slow to do virtual to real number translation while the MUD is running so all room exits are replaced by their real number equivalents during startup. Then the pre-defined starting locations for mortals, immortals, and frozen characters are checked to make sure they exist. If the mortal start room does not exist, the MUD aborts with an error. A missing immortal or frozen start room is redirected to the mortal start room to allow booting to continue. The mortal start room must exist in a room file loaded by \texttt{lib/world/wld/index.mini} file for mini-MUD mode to work. +\par +Mobiles from \texttt{lib/world/mob/index} and objects from \texttt{lib/world/obj/index} are loaded afterward. Mobile and object virtual numbers need not correspond to the zone number ranges as rooms do but it is encouraged. There are various sanity checks done to mobiles and objects that may be printed during startup. Any warnings issued should be fixed but should not adversely affect the MUD itself. +\par +In the same manner as the room number virtual to real translation, the zone reset information is also translated. The zone reset structure contains a variety of different records so it takes special care to find the appropriate numbers to translate from virtual to real. Any virtual numbers that cannot be resolved result in that zone command being disabled. Such entries have their type set to `\texttt{*}' to avoid the error in the future. +\par +If special procedures are enabled, as they usually are, the shops are loaded from \texttt{lib/world/shp/index} last. Contrary to the rooms and zones, the shops contain lists of virtual numbers to sell so any errors will only show up when attempting to use the shop. The charisma of a shopkeeper is important, as well as the buy/sell rates, as they define what prices the players will pay when shopping. +\par +The entire help database for CircleMUD is loaded into memory after the world has been loaded. This should be about 100kB with the stock CircleMUD help files, but the extra memory used saves the MUD from having to manipulate the help files to find the appropriate entries after the boot. Even though the help index is stored by keyword, any entry having multiple keywords is only stored once for each set. +\par +An index of the player file is built to allow random access to each player as attempt to connect or save. The index stores the player's name, to search by for login, and their ID number, for the mail system to search by. The array index is their position in the player file, used for loading and saving. +\par +Fight messages and socials loaded next are placed by line in their appropriate categories. The messages and socials themselves aren't interpreted beyond their placement but they'll be used extensively in the game. Spells defined earlier from \texttt{mag\_assign\_spells()} get their battle +messages from this file. Defaults are provided for the battle messages if none is defined. All socials loaded require a matching entry in the global command table or they will not be accessible by the players. +\par +Special procedures must be associated with their now-loaded object so they're processed now. A virtual number that cannot be resolved for the special procedure elicits a warning message on startup but a missing special procedure function will cause a compiler error. Shopkeepers are +assigned via \texttt{assign\_the\_shopkeepers()} instead of the standard \texttt{assign\_mobiles()} so they can be automatically handled as a result of the shop files loaded earlier. +\par +Since the spells are skills were defined earlier, they can then be assigned to each class upon a certain level. The spells and skills given to the various classes only depend upon a \texttt{SPELL\_} or \texttt{SKILL\_} definition so the assignment doesn't need to care if it is a generically handled spell or a custom implemented skill. The spells and skills may be assigned per the whims of the administrator based on their view of the appropriate classes. +\par +The command and spell tables need sorted for special circumstances. In the case of the command table, it is for the \texttt{commands} input which displays all known commands for that player's level. The spell table is sorted for the \texttt{practice} command for easier visual searching by the player. Neither are critical to the MUD's operation but exist for the players' benefit. +\par +The CircleMUD mail system keeps a binary file of all MUD message sent. It requires an index be built on startup to keep track of which blocks are free and which blocks have mail messages yet to be delivered. It is also important for the code to check the mail file to make sure it hasn't been corrupted somehow. A report on the number of messages present in the system is printed when finished. +\par +The stupid-people prevention code of site banning and invalid name rejection comes next. The site ban code loads a text file list of all sites that have been deemed unworthy to connect to the MUD. Invalid name rejection loads a list of substrings that must not appear in any character's name that is being created. The invalid name list is limited in the number of entries it may hold but any amount of sites may be banned. The length of each banned site name is limited, however. +\par +After deleting any expired rent files, the house code loads up any abodes defined. It must make sure the rooms still exist and the owner is still in the game before setting up the house, atrium, and guest list. Houses aren't loaded in mini-MUD mode since most of the rooms will likely not exist. +\par +The final step of the world startup resets every zone. This populates the world with mobiles, the mobiles with objects, and places other objects that should be on the ground. From here, all zone timers are started and will continue to reset (or not) depending on their settings and the number of people in the zone. The time is recorded after the zone reset to provide a display of the amount of time the MUD has been running. +\par +Once the world has finished being loaded, CircleMUD tells the operating system what sort of signals it wants to receive and which to ignore. It doesn't want to receive a \texttt{SIGPIPE}, which would abort the program whenever it tried to write to a player who abruptly disconnected. The user-defined signals (Unix) \texttt{SIGUSR1} and \texttt{SIGUSR2} are set to re-read the wizard list file and unrestrict the game, respectively. \texttt{SIGUSR1} is sent by \texttt{autowiz} whenever it finishes writing the file. \texttt{SIGUSR2} may be sent by the administrators, using \texttt{kill -USR2 pid-of-mud}, if accidentally banning themselves from their own MUD. A 3-minute timer signal prevents the MUD from being stuck in an infinite loop forever. The common shutdown signals of \texttt{SIGHUP} (Unix), \texttt{SIGTERM}, and \texttt{SIGINT} are mapped to a function that prints +their reception and then quits the program. The children signal, \texttt{SIGCHLD}, +is set up to remove finished \texttt{autowiz} instances. +\par +From here, the \texttt{.killscript} file is removed since if we've made it this far, we can start successfully. The only thing left now is to enter the interactive phase in \texttt{game\_loop()}, unless the ``Syntax Check'' option is enabled. + +\subsubsection{Interactive Phase} +Everything that ever happens while the MUD is interactively processing players occurs as a descendant of \texttt{game\_loop()}. It is responsible for all network I/O, periodic tasks, and executing player actions. Consequently, \texttt{game\_loop()} has the most concentration of newbie-eating code in the code base. Care should be taken to fully understand the network I/O infrastructure before trying to modify it. +\par +Each second of the game is divided into pulses, or points in time that network I/O is processed and commands run. This works to limit the number of possible commands the player can enter per second, such as speed-walking. If the game falls behind schedule, it will continuously process the pulses until it has caught up with where it is supposed to be. If over 30 seconds have passed, only 30 seconds are processed as it would be computationally expensive to do them all. If there isn't anyone connected to the game at all, then the MUD sleeps until someone connects. (``If a tree falls in the forest, and no one's around to hear it...") +\par +The first task of the pulse is to check for network socket input. First, any pending connections are given descriptors to track them. Then any descriptors with a socket in the exception set is kicked from the game. Incoming socket data is read next, checked for command history or repeat operations, and placed on the appropriate descriptor's command queue. +\par +Having read commands, they are then set up to be executed. A player must first be in a condition to execute those commands, so anyone with a wait state is skipped and people idled are pulled back into the game. Depending on the player's activities, the input may be sent through either the message writing system, the text pager, the \texttt{nanny()} login sequence, the alias system, or straight to the in-game command interpreter. +\par +In the message writing system (see \texttt{modify.c}), any input, except for an \texttt{@} at the beginning of a line, is simply appended to the string the character has decided to edit. An \texttt{@} at the beginning of a line finishes the editing and returns the player to their previous state. Typical uses of this are editing the character's description in the menu or writing to boards and notes in the game. +\par +The text pager allows the player to scroll around pages of text the MUD has produced. It allows refreshing the current page, going back a page, or continuing down the page. The text pager returns the player to their previous state upon reaching the end of the text or the user telling it to quit. +\par +The \texttt{nanny()} login sequence guides the player through the initial authentication and entering of the game. Here they are prompted for the character name and password. Upon successful login they may take actions such as changing their character's description, changing their password, deleting the character, or entering the game. +\par +The alias system provides a method for player's to shortcut the typing of commands. Each line of input is compared against their existing aliases and, if a match is found, the desired alias result is applied to their input and placed on the command queue. This process applies before the command interpreter so the game need not care what aliases each player may define. +\par +Finally, the command interpreter pulls off a line of input from the player's command queue. It uses the command table in \texttt{interpreter.c} to find the appropriate function, if any, to call for the given command. It does various checks to ensure the character is the proper level, in the correct +position, and not frozen. Any applicable special procedures are checked before running the function in the command table. The special procedure may override the function completely, as the shopkeepers do with the \texttt{buy} and \texttt{list} commands, or allow it to execute. +\par +Processing the commands likely generated output for the player so the network output is processed next. As much data is sent from the MUD's output queue as will fit in the operating system's socket buffer for each player. Any output that can't fit in the socket buffer is held until the next pulse when perhaps some of the pending output will have been delivered. If any players decided to exit the game or otherwise disconnected, their descriptor is marked for removal and the connection closed. +\par +Lastly, the periodic tasks are executed via the \texttt{heartbeat()} function. Each task may run every minute, every 5 minutes, every pulse, or any other time increment. The list of tasks to run includes: +\begin{itemize} +\item Process each zone's timed updates. +\item Disconnect idle descriptors in the login sequence. +\item Do basic mobile intelligence and special procedures. +\item Determine effects of violence. +\item Check the weather. +\item Test for magical affect expiration. +\item Regenerate health, mana, and movement. +\item Auto-save characters. +\item Saving the MUD time. +\item Extracting dead characters. +\end{itemize} +If the user-defined signals \texttt{SIGUSR1} or \texttt{SIGUSR2} have arrived, they are processed at the bottom of the game loop. Doing such work in the signal handler itself is unsafe and could cause unpredictable behavior. + +\subsubsection{Shutting Down} +The first responsibility on shutdown is to save the players' characters to disk. CircleMUD tracks which characters have been modified with a \texttt{PLR\_CRASH} flag so it only needs to save those characters which have changed in the period from the last auto-save to the shutdown. +\par +To disconnect the network connections, each player socket is closed in turn. Closing their connection also frees up any memory associated but, unless memory allocation tracing is enabled, it's not necessary since we're about to exit anyway. The ``mother'' descriptor is closed last, preventing any new players from connecting. +\par +Left to do are: closing the player database file, saving the current MUD time for next startup, and logging normal termination of game. The player database is kept open for fast access to loading and saving characters as they come and go. Saving the MUD time tries to maintain some appearance of continuity in your calendar. +\par +The final actions before exiting are only significant if the program is running with a memory allocation tracer. Here it sets about explicitly freeing every known piece of memory previously in use by the MUD. This is done to leave only forgotten allocations that may indicate a long-term memory leak in the program. The operating system will remove even forgotten memory when the program exits but the information may help prevent an ever-increasing memory usage while running. Memory tracing will vary depending on your operating system and may not necessarily be available on your particular platform. +\par +That's it, show's over. ``\texttt{return 0;'}' + +\subsection{CircleMUD's Global Variables} +CircleMUD doesn't use objects in the sense of object-oriented languages so there are various global variables kept that must be manipulated in order to change the game world. Some are stored as arrays; others as lists. The global variables kept as arrays generally have an associated +\texttt{top\_of\_...} function to denote its boundary. +\par +This is not an exhaustive list but the most frequently encountered of the ones in use. A large number of global, constant strings are kept in \texttt{constants.c} but they're simply read from. Also see \texttt{config.c} for a number of configuration global variables. + +\subsubsection{World Variables} +\begin{description} +\item[struct room\_data *world;] +This array of \texttt{struct room\_data} stores all the information for the rooms of the MUD universe. In addition to room titles, flags, and descriptions, it also contains lists of people, mobiles, and objects currently in the rooms. +\item[struct char\_data *mob\_proto;] +While rooms are singular entities, there may be many copies of a single mobile running around the game world. The \texttt{mob\_proto} array of \texttt{struct char\_data} contains the base information for all mobiles, as well as being used for string sharing amongst all the copies. +\item[mob\_rnum top\_of\_mobt;] +The highest valid array index of \texttt{mob\_proto} and \texttt{mob\_index} is stored here. This is {\em not} the count of items in the array. That is \texttt{top\_of\_mobt + 1}. +\item[struct index\_data *mob\_index;] +\item[struct index\_data *obj\_index;] +The number of instances of each particular mobile or object is tracked through these dynamic arrays of \texttt{struct index\_data}. This is also the location for reverse-mapping the mobile/object real number back into a virtual number. In addition, the special procedure and several other variables are stored here to avoid keeping redundant data on every mobile/object in the game. +\item[struct obj\_data *obj\_proto;] +This is analogous to \texttt{mob\_proto}, except for objects. It is kept as a dynamic array of \texttt{struct obj\_data}. +\item[obj\_rnum top\_of\_objt;] +The highest valid array index of \texttt{obj\_proto} and \texttt{obj\_index} is stored +here. This is {\em not} the count of items in the array. That is \texttt{top\_of\_objt + 1}. +\item[struct zone\_data *zone\_table;] +A dynamic array of type \texttt{struct zone\_data} storing all the information for zone resets, titles, and room ranges. +\item[zone\_rnum top\_of\_zone\_table;] +The highest valid array index of \texttt{zone\_table} is stored here. There are \texttt{top\_of\_zone\_table + 1} zones in the array. +\end{description} + +\subsubsection{Object Instance Lists} +\begin{description} +\item[struct descriptor\_data *descriptor\_list;] +All players connected to the MUD have a descriptor used to send the MUD's output to and receive player input from. Each descriptor does not necessarily have a character (not logged in yet). These are stored as a linked list of \texttt{struct descriptor\_data} using the \texttt{next} field. +\item[struct char\_data *character\_list;] +All player characters and mobiles are kept in a linked-list of \texttt{struct char\_data}. This list uses the \texttt{next} field of the structure. +\item[struct obj\_data *object\_list;] +As all characters and descriptors are kept in a linked-list, so too are all the objects in the world kept. This list uses the \texttt{next} field of \texttt{struct obj\_data}. +\end{description} + +\subsubsection{Other} +\begin{description} +\item[const struct command\_info cmd\_info[{]}] +All user commands are kept in a large array in \texttt{interpreter.c}. The \texttt{ACMD} functions use this array, along with the command array index variable they are given, to figure out what specific text the user typed to get to this command function. This allows them to handle multiple commands with the same function with \texttt{CMD\_IS()}. The size of the array is static and determined by the computer at the time of compilation. +\item[struct weather\_data weather\_info] +Raining? Snowing? Weather changes occurring in \texttt{weather.c} are stored in this structure. The sun's current state (dawn, dusk, etc.) is kept here as well. +\item[struct time\_info\_data time\_info] +The current date and time of the game world. Used in the shop code for opening and closing the stores on schedule. +\end{description} + +\subsection{Frequently Used Functions} +\subsubsection{Basic String Handling} + +\begin{description} +\item[int str\_cmp (const char *a, const char *b)] +\item[int strn\_cmp (const char *a, const char *b, int len)] +These are portable, case-insensitive versions of the \texttt{strcmp()} and \texttt{strncmp()} functions. Like their C library counterparts, these functions perform a character-by-character comparison and return the difference of the first mismatching characters or zero, if the two strings are equal. The \texttt{strn\_cmp()} function only compares the first \texttt{len} characters of the first string to the second string. +\par +Many platforms have built-in routines to do case-insensitive string comparisons. Where applicable, \texttt{str\_cmp()} and \texttt{strn\_cmp()} are aliases for the platform-specific equivalents. On platforms without these functions built-in, CircleMUD will supply a working implementation. One should prefer the CircleMUD names to ensure portability since it incurs no run-time performance cost. +\item[int isname (const char *str, const char *namelist)] +Compare a string, \texttt{str}, to each of a list of space-delimited keywords, \texttt{namelist}, using \texttt{str\_cmp()}. This is used for matching an argument to an object or mobile, which has its keywords arranged like, \texttt{bottle brown beer}. +\item[bool is\_abbrev (const char *str, const char *arg2)] +A case-insensitive substring match. Equivalent to: "\texttt{strn\_cmp(needle, haystack, strlen(needle)) == 0}" Generally this is user-extended to act like \texttt{isname()}, except for abbreviated keywords. +\item[void skip\_spaces (char **string)] +The command interpreter hands off " \texttt{cabbage}" if the user types in "\texttt{look cabbage}". Since comparisons need to be done without the extra space in the string, this function removes it. It is also used internally for the argument splitting functions to properly handle user input such as: "\texttt{put the cabbage in the bag}". +\item[bool is\_number (const char *str)] +Tests if an entire string is an ASCII-encoded, unsigned decimal number by performing \texttt{isdigit()} on each character of the string. Only unsigned (zero or positive) numbers are recognized. +\item[char *delete\_doubledollar (char *string)] +The MUD, in processing input, converts a single dollar sign to a double dollar sign. If you want to echo out a user's input through something other than \texttt{act()}, you will want to smash '\$\$' into '\$' by using this function. +\end{description} + +\subsubsection{Argument Processing} +\begin{description} +\item[char *one\_argument (char *argument, char *first\_arg)] +\item[char *two\_arguments (char *argument, char *first\_arg, char *second\_arg)] +\item[char *any\_one\_arg (char *argument, char *first\_arg)] +These functions are frequently used in MUD commands to parse the arguments to those commands. As their names imply, \texttt{one\_argument()} will peel off one argument from the string given by the user while \texttt{two\_arguments()} will peel off two at a time. Note that these +functions ignore (and will not return) words such as: ``in'', ``from'', ``with'', ``the'', ``on'', ``at'', and ``to''. This is so the commands do not need to know the difference between "put the sword in the bag" and ``\texttt{put sword bag}''. If those words are really needed for the command, then use \texttt{any\_one\_arg()} instead. It works just like \texttt{one\_argument()} in all other respects. All of these functions convert the peeled off argument(s) to lower case as part of the process of storing them in the user-supplied buffer. +\item[char *one\_word (char *argument, char *first\_arg)] +Peels an argument off from a string like \texttt{one\_argument}, but respects grouping via quoting. If the user supplies, `\,\texttt{"moby dick"}\,', \texttt{one\_argument()} would return an argument of '"moby', while \texttt{one\_word()} would return an argument of `\texttt{moby dick}'. This function converts the peeled off argument(s) to lower case as part of the process of storing them in the user-supplied buffer. +\item[void half\_chop (char *string, char *arg1, char *arg2)] +Apparently a DikuMud relic. Instead of returning the leftover argument bits in the return value, this copies the result (sans leading spaces) into a second buffer. +\end{description} + +\subsubsection{Character Output (Hello, world!)} +\begin{description} +\item[void log (const char *format, ...)] +Whenever a piece of information needs to be sent to the MUD's logs, this is the function to use. It is especially useful for debugging and supports variable arguments like the \texttt{printf()} and \texttt{sprintf()} functions. To prevent compilation errors due to a conflict with C's natural logarithm function of the same name, `\texttt{log}' is actually an alias for this function's real name, \texttt{basic\_mud\_log()}. +\item[void mudlog (const char *str, int type, int level, bool file)] +In most cases \texttt{mudlog()} is better than \texttt{log()} because it announces to both the immortals on the MUD and, optionally, the file logs. Chances are the immortals will notice something faster while logged in to the game than in the system logs. +\item[void send\_to\_char (struct char\_data *ch, const char *messg, ...)] +This is the game's tether to the players; its mouth; its voice. Most game output goes through this function so it is used very frequently. It supports variable argument formatting like the C library's \texttt{printf()} and \texttt{sprintf()} functions. +\item[void act (const char *str, bool hide\_invisible, struct char\_data *ch, struct obj\_data *obj, const void *vict\_obj, int type)] +When dealing with character interactions there are frequently three situations to cover: the actor, the target, and the observers. This function takes care of such output along with handy cases for his/her, he/she/it, and other language special cases. +\par +See the '\texttt{act()}' documentation (\texttt{act.pdf}) for more information on what each particular parameter is used for. +\item[void page\_string (struct descriptor\_data *d, char *str, bool keep\_internal)] +Places the character into a pageable view of whatever string is given to it. Handy for long board messages, opening announcements, help text, or other static information. +\end{description} + +\subsubsection{File Input} +\begin{description} +\item[int get\_line (FILE *fl, char *buf)] +Reads one or more lines, if possible, from the given file handle into a user-supplied buffer. This skips lines that begin with an asterisk (*), which are considered to be comments, and blank lines. The returned line has the line terminator(s) removed, and the total number of lines read to find the first valid line is returned. A value of zero indicates that an error occurred or that end of file was reached before a valid line was read. +\item[int get\_filename (char *orig\_name, char *filename, int mode)] +Fills in the 'filename' buffer with the name of a file of type `\texttt{mode}' for a player with name `\texttt{orig\_name}'. The mode parameter can +be one of: +\begin{itemize} +\item \texttt{CRASH\_FILE}, for player object files, +\item \texttt{ALIAS\_FILE}, for player aliases, +\item \texttt{ETEXT\_FILE}, for the unimplemented e-text system. +\end{itemize} +The returned filename contains a path to a file in a directory based upon the file type and the first letter of `\texttt{orig\_name}'. +\end{description} + +\subsubsection{Utility Functions} +\begin{description} +\item[int rand\_number (int from, int to)] +Rolls a random number using a (pseudo) random number generator in the range [from, to]. The random number generator is seeded with the time CircleMUD booted as returned by the \texttt{time()} system call. This provides a good, difficult to predict sequence of numbers. +\item[int dice (int num, int size)] +Simulate rolling `\texttt{num}' dice, each with `\texttt{size}' sides, and return the sum of the rolls. +\item[size\_t sprintbit (bitvector\_t bitvector, const char *names[{]}, char *result, size\_t reslen)] +Treat an array of strings as if they were descriptions for the individual bits in `\texttt{bitvector}' and create a string describing it. This is used by the wizard function \texttt{do\_stat()} to give human-readable output to the various bitvectors used as storage by the code. This is the approximate reverse of ``\texttt{PRF\_LOG1 | PRF\_DEAF}'', for example. +\item[size\_t sprinttype (int type, const char *names[{]}, char *result, size\_t reslen)] +Retrieves a value from an array of strings. The difference between +this and ``\texttt{array[number]}'' is that this will avoid reading garbage +values past the end of the array. \texttt{sprinttype()} assumes the string +arrays are terminated by a ``\texttt{$\backslash$n}'' entry. +\item[int search\_block (char *arg, const char **list, int exact)] +Searches an array of strings for a match to `\texttt{arg}' and returns the index in the array of the match, or -1 if not found. If 'exact' is false, then a prefix match is done akin to \texttt{is\_abbrev()}. This is useful to map symbolic names to numerical constants. Think of it as the opposite of \texttt{array[number]}: ``What index has this value?'' +\end{description} + +\subsubsection{Character/Object Manipulation} +\begin{description} +\item[void char\_to\_room (struct char\_data *ch, room\_rnum room)] +\item[void char\_from\_room (struct char\_data *ch)] +Reciprocal, low-level functions to put a character into and remove a character from a given room. The room number must be specified with a ``real number'' (an index into the room tables) as returned by \texttt{real\_room()}. Since a character can only be in one room at a time, you must call \texttt{char\_from\_room()} to remove a character from his current location before placing him in another. After a \texttt{char\_from\_room()} call, the character is in \texttt{NOWHERE} and must be moved to another room using \texttt{char\_to\_room()}. +\par +These functions do not check if the character is allowed to enter or leave the room; nor do they provide output to indicate that the character is moving. +\item[void extract\_char (struct char\_data *ch)] +Remove the character from the game world and then frees the memory associated with it. Players are saved before removal. Any objects still on the character are dumped on the ground. +\item[void equip\_char (struct char\_data *ch, struct obj\_data *obj, int pos)] +\item[struct obj\_data *unequip\_char (struct char\_data *ch, int pos)] +Takes a free-floating object (i.e., not equipped, in inventory, on the ground, or in another object) and equips it to the character for the specified location. \texttt{unequip\_char()} does the opposite; it removes the object from the character's equipment list and returns it as a free-floating object. The object being unequipped must be placed elsewhere or destroyed. Note that some objects may not be equipped by characters of certain classes and/or alignments. +\item[void obj\_to\_char (struct obj\_data *object, struct char\_data *ch)] +\item[void obj\_from\_char (struct obj\_data *object)] +Reciprocal, low-level functions to put an object into and remove an object from a given character's inventory. Since an object can only be in one location at a time, you must use one of the \texttt{obj\_from\_X()} functions to remove it from its current location before using \texttt{obj\_to\_char()} to place it in someone's inventory. After an \texttt{obj\_from\_char()} call, the object is in \texttt{NOWHERE} and must be moved to another location using one of the \texttt{obj\_to\_X()} functions. +\par +These functions do not check if the character is allowed to carry or discard the object; nor do they provide any output to inform anyone that the character has received or discarded the object. +\item[void obj\_to\_obj (struct obj\_data *object, struct obj\_data *cont)] +\item[void obj\_from\_obj (struct obj\_data *object)] +Reciprocal, low-level functions to put an object into and remove an object from a given container object. Since an object can only be in one location at a time, you must use one of the \texttt{obj\_from\_X()} functions to remove it from its current location before using \texttt{obj\_to\_obj()} to place it within another object. After an \texttt{obj\_from\_obj()} call, the object is in \texttt{NOWHERE} and must be moved to another location using one of the \texttt{obj\_to\_X()} functions. +\par +These functions do not check if the container is allowed to carry or discard the object; nor do they provide any output to inform anyone that the container has received or discarded the object. +\item[void obj\_to\_room (struct obj\_data *object, room\_rnum room)] +\item[void obj\_from\_room (struct obj\_data *object)] +Reciprocal, low-level functions to put an object into and remove an object from a given room. Since an object can only be in one location at a time, you must use one of the \texttt{obj\_from\_X()} functions to remove it from its current location before using \texttt{obj\_to\_room()} to place it in a room. After an \texttt{obj\_from\_room()} call, the object is in \texttt{NOWHERE} and must be moved to another location using one of the \texttt{obj\_to\_X()} functions. +\par +These functions do not check if the room is allowed to contain or discard the object; nor do they provide any output to inform anyone that the room has received or discard the object. +\item[void extract\_obj (struct obj\_data *obj)] +Removes the object from its place in the world, then destroys it. +\end{description} + +\subsubsection{Object Locating} +\begin{description} +\item[struct obj\_data *get\_obj\_in\_list\_num (int num, struct obj\_data *list)] +Get an object from `\texttt{list}' with the specified real object number. Only takes first object; no ``\texttt{2.bread}'' support. +\item[struct obj\_data *get\_obj\_num (obj\_rnum nr);] +Find the first object in the world with the real object number given. Does not have ``\texttt{2.}'' support. +\item[struct obj\_data *get\_obj\_in\_list\_vis (struct char\_data *ch, char *name, int *number, struct obj\_data *list)] +Find the `\texttt{number}'-th object in `\texttt{list}' with keyword 'name' that the character can see. A \texttt{NULL} is returned on failure to locate such an object, or if not enough objects to satisfy `\texttt{number}' were found. `\texttt{number}' is a pointer to an integer so it can be decremented when doing multiple searches, such as room then world. If the first object is desired, `\texttt{number}' is left \texttt{NULL}. +\item[struct obj\_data *get\_obj\_vis (struct char\_data *ch, char *name, int *number)] +Find the `\texttt{number}'-th object in the world with keyword `\texttt{name}' that +the character can see. A \texttt{NULL} is returned on failure to locate such an object, or if not enough objects to satisfy `\texttt{number}' were found. `\texttt{number}' is a pointer to an integer so it can be decremented when doing multiple searches, such as room then world. If the +first object is desired, `\texttt{number}' is left \texttt{NULL}. +\item[struct obj\_data *get\_obj\_in\_equip\_vis (struct char\_data *ch, char *arg, int *number, struct obj\_data *equipment[{]})] +Find the `\texttt{number}'-th object in the character's equipment list with keyword `\texttt{name}' that the character can see. A \texttt{NULL} is returned on failure to locate such an object, or if not enough objects to satisfy `\texttt{number}' were found. `\texttt{number}' is a pointer to an integer so it can be decremented when doing multiple searches, such as equipment then inventory. If the first object is desired, `\texttt{number}' is left \texttt{NULL}. +\item[int get\_obj\_pos\_in\_equip\_vis (struct char\_data *ch, char *arg, int *number, struct obj\_data *equipment[{]})] +Return the index of the 'number'-th object in the character's equipment list with keyword 'name' that the character can see. A -1 is returned on failure to locate such an object, or if not enough objects to satisfy `\texttt{number}' were found. `\texttt{number}' is a pointer to an integer so it can be decremented when doing multiple searches, such as equipment then inventory. If the first object is desired, `\texttt{number}' is left \texttt{NULL}. +\item[int generic\_find (char *arg, bitvector\_t bitvector, struct char\_data *ch, struct char\_data **tar\_ch, struct obj\_data **tar\_obj)] +Searches any or all of the character's equipment, inventory, current room, and world for an object with the keyword given in `\texttt{arg}'. A 2nd or 3rd object is denoted in ``\texttt{2.object}'' notation. The function's return value specifies where the object was found, or 0, and the `\texttt{tar\_obj}' value is updated with the object itself, or \texttt{NULL}. {\em NOTE:} This also does characters, either separately or simultaneously. +\end{description} + +\subsubsection{Character Locating} +\begin{description} +\item[struct char\_data *get\_char\_room (char *name, int *number, room\_rnum room);] +Find the `\texttt{number}'-th character in the room with the keyword `\texttt{name}'. A \texttt{NULL} is returned on failure to locate such a character, or if not enough characters to satisfy `\texttt{number}' were found. `\texttt{number}' is a pointer to an integer so it can be decremented when doing multiple searches, such as room then world. If the first character is desired, `\texttt{number}' is left \texttt{NULL}. +\item[struct char\_data *get\_char\_num (mob\_rnum nr);] +Find the first mobile in the world with real mobile number given. This does not have support for ``\texttt{2.}'' notation. +\item[struct char\_data *get\_char\_room\_vis (struct char\_data *ch, char *name, int *number);] +Find the `\texttt{number}'-th character in the room with the keyword `\texttt{name}' that is visible to the character given. A \texttt{NULL} is returned on failure to locate such a character, or if not enough characters to satisfy `\texttt{number}' were found. `\texttt{number}' is a pointer to an integer so it can be decremented when doing multiple searches, such as room then world. If the first character is desired, `\texttt{number}' is left \texttt{NULL}. +\item[struct char\_data *get\_char\_world\_vis (struct char\_data *ch, char *name, int *number);] +Find the `\texttt{number}'-th character in the world, searching the character's room first, with the keyword `\texttt{name}' that is visible to the character given. A \texttt{NULL} is returned on failure to locate such a character, or if not enough characters to satisfy `\texttt{number}' were +found. `\texttt{number}' is generally a pointer to an integer so it can be +decremented when this does both searches. If the first character is +desired, `\texttt{number}' is left \texttt{NULL}. +\item[struct char\_data *get\_char\_vis (struct char\_data *ch, char *name, int *number, int where);] +When `\{texttt{where}' is \texttt{FIND\_CHAR\_WORLD}, call `\texttt{get\_char\_world\_vis()}'. If `\texttt{where}' is \texttt{FIND\_CHAR\_ROOM}, call `\texttt{get\_char\_room\_vis()}'. Otherwise, return \texttt{NULL}. This is kept for compatibility with various calls in the source code or if people want to easily change a search based on a variable. +\item[int generic\_find (char *arg, bitvector\_t bitvector, struct char\_data *ch, struct char\_data **tar\_ch, struct obj\_data **tar\_obj);] +Searches the character's current room and/or world for a character +with the keyword given in `\texttt{arg}'. A 2nd or 3rd character is denoted +in ``\texttt{2.character}'' notation. The function's return value specifies +where the character was found, or 0, and the `\texttt{tar\_ch}' value is +updated with the character itself, or \texttt{NULL}. {\em NOTE:} This also does +objects, either separately or simultaneously. +\end{description} + +\subsubsection{Violence} +\begin{description} +\item[void set\_fighting (struct char\_data *ch, struct char\_data *victim);] +Initiates fighting between `\texttt{ch}' and `\texttt{victim}'. +\item[void stop\_fighting (struct char\_data *ch);] +Removes the character from a fighting posture. Note that if an enemy is still considered fighting this character, the character will revert back to fighting as soon as the enemy hits them again. +\item[void hit (struct char\_data *ch, struct char\_data *victim, int type);] +Makes the character attempt to hit the victim. The type determines if it is a skill, backstab in particular, or other type of damage to attempt to hit with. The type is generally left as \texttt{TYPE\_UNDEFINED} to use the character's natural type. +\item[int damage (struct char\_data *ch, struct char\_data *victim, int dam, int attacktype);] +Cause bodily harm to the victim, courtesy of the character. The damage and attacktype determine the message reported. Immortals and shopkeepers (that aren't charmed) may not be injured. Damage is capped at 100 per hit. +\end{description} + +\section{Adding Features} +\subsection{Adding Commands} +In the course of writing new functionality for your MUD, one of the first projects you may try is to add your own command. Some commands, like socials, are special, but most commands will require you to implement some method to manipulate and parse the user's input. In CircleMUD, this is done with 'command functions' which have a special declaration form: +\begin{verbatim} + ACMD(do_/* Command name. */) + { + . + . /* Command code. */ + . + } +\end{verbatim} + +The command functions are then registered with the command interpreter by adding them to the \texttt{cmd\_info[]} table in \texttt{interpreter.c}. The order within the command table is significant; entries at the top are substring matched prior to entries lower in the list. So if '\texttt{kill}' is before '\texttt{kiss}', then '\texttt{ki}' will match '\texttt{kill}'. Something else to be aware of is that this can render commands unreachable, such as '\texttt{goad}' being before '\texttt{go}'. The '\texttt{go}' can never be matched because '\texttt{goad}' will always have a valid substring matched first. +\par +The fields of importance are: +\begin{description} +\item[const char *command] +The name of the command being registered. Remember the substring matching when deciding upon the order in the table. +\item[byte minimum\_position] +One of the \texttt{POS\_xxx} constants \texttt{\#define}'d in \texttt{structs.h}. This enforces the minimum position, inclusive, the user must be in, in order to execute the command. +\item[ACMD(*command\_pointer)] +This is the name of the function the command will call. It must be defined in the code with the \texttt{ACMD()} macro and prototyped above the command table itself. +\item[int minimum\_level] +The minimum level, inclusive, the user must be to execute the command. +\item[int subcmd] +To allow the same code function to handle multiple, similar commands, this field allows an identifying number to be given to the command's function. +\end{description} +The ACMD declaration form is a C macro that sets up the command function to receive the right arguments. All command functions in CircleMUD receive the same set of parameters: +\begin{description} +\item[struct char\_data *ch] +The character that issued the command (or, perhaps, was forced to issue the command): the actor. +\item[const char *argument] +A string that contains the arguments the user gave to the command, with any leading spaces from the command interpreter still intact. For example, if the user typed "\texttt{tell ras Hello, there}" at the prompt, argument would be "\texttt{ ras Hello, there}". This string is typically processed using one or more of the functions from Sections 2.4.1 (Basic String Handling) or 2.4.2 (Argument Processing). +\item[int cmd] +The index within the command table where this command was found. Useful when multiple commands can invoke the same command function and you want to identify which command was issued. Since command indices can change when you add new commands, the primary use of this field is in special procedures and with the \texttt{IS\_CMD} macro. Do not confuse this with the subcmd parameter, which is more general purpose. +\item[int subcmd] +A special, user-defined integer value passed to select a "subcommand." Usually zero, but sometimes used when multiple commands with similar behavior are implemented with a single command function. Since the subcmd's value is supplied within the command table and has a meaning determined entirely by the command's author, it will not change when you add new commands. +\end{description} +A command with no arguments is very simple to write. For example, here is a simple command that sends a nice, personalized greeting to the user when she runs it: +\begin{verbatim} + ACMD(do_hello) + { + act("Hello, $n.", FALSE, ch, NULL, NULL, TO_CHAR); + } +\end{verbatim} +To allow the user to access this command, you have to add it to the command table as discussed before. This can be done by adding the \texttt{ACMD} prototype above \texttt{cmd\_info[]} (if necessary) in \texttt{interpreter.c}, like: +\begin{verbatim} + ACMD(do_hello); +\end{verbatim} +and then adding to \texttt{cmd\_info[]} the command's information, as previously discussed: +\begin{verbatim} + { "hello", POS_DEAD, do_hello, 0, 0 }, +\end{verbatim} +Our information specifies this is a command named "\texttt{hello}" which anyone can use, regardless of their position (since dead is the minimum) or level (since 0 is the minimum), calls the \texttt{do\_hello()} function to be executed, and has no subcmd. Note that because \texttt{cmd\_info[]} does not encode information about the arguments to the command, we don't need to do anything different for commands that take arguments. +\par +Since the command interpreter doesn't process arguments for us (allowing \texttt{cmd\_info[]} to be simple and general), we have to process them ourselves. Suppose we want to update our "\texttt{hello}" command to send a greeting to other users, when its invoked with an argument. First, we need to get the first argument (if any) by using the \texttt{one\_argument()} function. In order to do this, we need a place to store the first argument (if any), which we declare as a local character buffer of length \texttt{MAX\_INPUT\_LENGTH}. (Note that regardless of what length we {\em expect} the argument to be, we always make our buffer the maximum input size, so users cannot overflow the buffer and crash the game.) +\par +After this, we need to see what the argument is. If it is nothing, we'll default to our old behavior of just saying hello to our user. Otherwise, we need to look up the character with the given name. If we can't find anyone by that name, we send an error message. If we find someone, we send the greeting to the character we found. We check if the given argument is empty by seeing if its first character is C's end of string marker ('\texttt{\\0}' or 0). Since \texttt{one\_argument()} strips leading spaces for us, we don't have to worry about them. If the string is not empty, we need to look up a character in the current room by that name, using \texttt{get\_char\_vis()} (see Section 2.4.8. Character Locating). +\par +Our changes give us: +\begin{verbatim} + ACMD(do_hello) + { + char arg[MAX_INPUT_LENGTH]; /* First argument. */ + struct char_data *targ; /* Who to greet? */ + + one_argument(argument, arg); + + if (!*arg) { /* Common idiom for empty string test. */ + act("Hello, $n.", FALSE, ch, NULL, NULL, TO_CHAR); + return; /* We're done for this case. */ + } else if (!(targ = get_char_vis(ch, arg, FIND_CHAR_ROOM))) { + send_to_char(ch, NOPERSON); + return; /* Done for this case. */ + } + + /* Otherwise we got a target: */ + act("You greet $N.", FALSE, ch, NULL, targ, TO_CHAR); + act("$n greets you.", FALSE, ch, NULL, targ, TO_VICT); + act("$n greets $N.", FALSE, ch, NULL, targ, TO_NOTVICT); + } +\end{verbatim} +\texttt{NOPERSON} is a constant defined in \texttt{config.c} for use an error message when the target of a command cannot be found. Other such constants are \texttt{OK} (for when everything goes well) and \texttt{NOEFFECT} (as a general failure message for skills, spells, and commands whose success rely on chance). +\par +Of course, this command is little more than an overcomplicated social (we'll see in the next section that socials don't require command functions at all). Doing something of interest is up to you, as the programmer. Our "\texttt{hello}" command only serves as a starting point and demonstration of some idioms used throughout CircleMUD. + +\subsection{Adding Socials} +Socials are commands that only write messages to the user and possibly his room and/or an optional victim. Examples are typical mud commands like "\texttt{nod}" or "\texttt{wave}", to let players perform various demonstrative actions. Our "\texttt{hello}" command above is an example. However, since socials are very common and superficially simple, there's a simplified way to write them. +\par +The \texttt{lib/misc/socials} file in the CircleMUD directory contains the actual socials in the following format: +\begin{verbatim} + + + + + + + + + + +\end{verbatim} +The exact meaning and format of these fields is described in '\texttt{socials.pdf}', although much of it corresponds to \texttt{act()} (like the hide flag or the format of the messages) and the command interpreter (like the command name and the minimum position the {\em victim} must be in for the social to work). +\par +Programmatically, the social is still a command and must be registered in \texttt{cmd\_info[]} like any other command. All socials have the same command function, \texttt{do\_action()}, which does the specialized social system processing. Thus, to add a social "\texttt{foobar}" to the command interpreter, we add the following line to the appropriate place in \texttt{cmd\_info[]} (taking into account that order is significant, as discussed in Section 3.1): +\begin{verbatim} + { "foobar", POS_RESTING, do_action, 0, 0 }, +\end{verbatim} +Note that the second element in the table entry is the minimum position the user of the social must be in, while the \texttt{lib/misc/socials} file stores the minimum position that the {\em victim} (if any) must be in for the social to work. In this case, the command can only be used by people that are awake and fully conscious (resting, sitting, or standing). + +\subsection{Adding Spells} +CircleMUD improves greatly over standard Diku handling for spells, but how you go about adding them depends on the type of spell you want to make. Damage, affection, group, mass area, area, monster summoning, healing, status removal, and item enchanting spells are all generated in a template format with a touch of special messages and coding effects. More complicated spells such as '\texttt{locate object}', '\texttt{summon}', or '\texttt{identify}' are a combination of the behavior of spells and commands. They are spells in the sense the code checks for mana and requires the '\texttt{cast}' syntax but are also commands in the sense that beyond the basic handling, the spell is implemented as a subroutine with given parameters. +\par +All spells require a definition to determine the amount of mana used, how the spell behaves, and what the spell is named. To do that, the function \texttt{spello()} is called from \texttt{mag\_assign\_spells()} in \texttt{spell\_parser.c}. It is called as: +\begin{verbatim} + spello( + unique_spell_number = ID# from 0 .. TOP_SPELL_DEFINE for this spell. + spell_name = Name to be used for 'cast' command. + max_mana = Mana cost of spell when first learned. + min_mana = Minimum mana cost to ever cast the spell. + mana_change = Reduction in mana cost per level beyond learning it. + minimum_position = Whether castable sitting, standing, fighting, etc. + valid_targets = If the spell targets people, yourself, items, etc. + offensive = Whether casting on someone else is a hostile action. + spell_routines = One or more of the magic template classifications. + wear_off_message = Text to display when the spell wears off, or none. + ) +\end{verbatim} +A spell with a minimum position value of 0 may not be cast by mere mortal players. For example, the spell "\texttt{armor}" is described as: +\begin{verbatim} + spello(SPELL_ARMOR, "armor", 30, 15, 3, POS_FIGHTING, + TAR_CHAR_ROOM, FALSE, MAG_AFFECTS, + "You feel less protected."); +\end{verbatim} +This spell costs 30 mana at the first level it is learned and decreases in cost by 3 mana per level afterward until it reaches the minimum of 15. The spell may be cast either fighting or standing, but not sitting, resting, sleeping, or otherwise incapacitated. Armor will target anyone in the current +room as a non-hostile action. It processes through \texttt{MAG\_AFFECTS} so there will be a lingering affection, after which the "\texttt{You feel less protected}" message will display. +\par +To allocate a new spell, create a new \texttt{\#define} symbol in \texttt{spells.h} in the same pattern as the others there. In that header, give the new spell an unused spell number equal to or less than \texttt{MAX\_SPELLS}. If you run out of spell slots then other means not covered here will be necessary to add more spells. + +\subsubsection{Template Spells} +Similar types of spells have generalized routines that handle multiple spells with very little different code. A damage spell is a damage spell is a damage spell. Even if a spell does multiple actions, such as blinding plus damage plus monster summon, the damage portion of the spell acts identical to a spell that simply does damage. The only difference is how much it does and whether there are special mitigating factors. For example, '\texttt{chain lightning}' in \texttt{mag\_damage()} (since it is a \texttt{MAG\_DAMAGE} spell) is simply: +\begin{verbatim} + case SPELL_CALL_LIGHTNING: + dam = dice(7, 8) + 7; + break; +\end{verbatim} +So the spell does \texttt{7d8+7} damage. Simple enough. All checking for saving throws, valid targets, proper mana reserves, etc. is all handled by the generic code with a bit of definition for the code to operate by. +\par +The code fragment in the template sections can use any information about the caster, target, or environment that it chooses to modify the damage, success, or effect done to the target. Some spells do more damage if the caster is a magic user. Others might outright kill lower level targets but only slightly wound more experienced ones. The effect is up to you. +\par +Affection spells require more in their fragment than the simple damage spells. They create affection structures that are then given to the target of the spell for their specified duration if the spell succeeds. More than one affection can be given by a single spell, as shown below in "\texttt{bless}": +\begin{verbatim} + case SPELL_BLESS: + af[0].location = APPLY_HITROLL; + af[0].modifier = 2; + af[0].duration = 6; + + af[1].location = APPLY_SAVING_SPELL; + af[1].modifier = -1; + af[1].duration = 6; + + accum_duration = TRUE; + to_vict = "You feel righteous."; + break; +\end{verbatim} +Any modifier listed in structs.h in the \texttt{APPLY\_xxx} section may be used as the location field. The modifier's effect will depend on the affection type used. Up to \texttt{MAX\_SPELL\_AFFECTS} values can be assigned to. Although not listed in the above example, a `\texttt{.bitvector}' value may be assigned to if the spell should tag the player with an \texttt{AFF\_} flag. If multiple castings of the same spell should be cumulative in duration, the `\texttt{accum\_duration}' variable is set to \texttt{TRUE}. Likewise, if the modifier is cumulative, the `\texttt{accum\_effect}' variable should be set to \texttt{TRUE}. A string assigned to `\texttt{to\_room}' will be passed through \texttt{act()} for the occupants of the same room as the caster. A `\texttt{to\_vict}' string will be given to \texttt{act()} with the target of the spell as the recipient of the message. +\par +Group spells simply call another spell on everyone in your current group. If you want a `\texttt{group fly}' spell, then you make a `\texttt{fly}' spell first. Afterward, you make the `\texttt{group fly}' definition and then fill in some template areas of the \texttt{perform\_mag\_groups()} function. What you write there will depend on how your spell is designed. +\par +General summoning spells (not `\texttt{summon}' itself) deal with the conjuration of mobiles. They require: `\texttt{fmsg}', a failure message array index number; `\texttt{mob\_num}', the virtual mobile number to summon; `\texttt{pfail}', the percent chance of failure; and `\texttt{handle\_corpse}', mostly for the ``\texttt{animate dead}'' spell so it can move the items from the corpse being animated to the mobile being summoned. These spells lend themselves to more customization than some of the other types. +\par +Healing spells in \texttt{mag\_points()} can restore either health or movement points by default. Just assign the amount of health healed to a `\texttt{healing}' variable, the amount of movement points restored to a `\texttt{move}' variable, and send the target a message with \texttt{send\_to\_char()}. The general code will handle updating the character's attributes, position, and make sure a dying character is restored to normal functions if healed sufficiently. +\par +Unaffection spells revert the effects of other spells, such as ``\texttt{blindness}'', ``\texttt{silence}'', or ``\texttt{drunken stupor}.'' There are only three variables used in \texttt{mag\_unaffects()}: \texttt{to\_vict}, \texttt{to\_room}, and \texttt{spell}. The important variable is `\texttt{spell}', which determines which spell effect this unaffection spell will counter. The `\texttt{to\_vict}' and `\texttt{to\_room}' messages are optional but sent to the victim and room, respectively, if provided. +\par +Object alteration spells deal with magical modifications to items, such as poisoning, cursing, enchanting, or making them invisible. These spells are all unique by nature so only `\texttt{to\_char}' and `\texttt{to\_room}' are expected to be set, as messages to the character and room, respectively. If `\texttt{to\_char}' is left \texttt{NULL}, it is assumed the spell failed and a ``\texttt{no effect}'' message is given. +\par +A creation spell conjures an item out of nothingness. The only variable expected is `\texttt{z}', which specifies the object virtual number that should be created. Note that only a single object is created and there is no current mechanism for making multiples. +\par +The last function of note, \texttt{mag\_materials()}, is not a spell type at all but a helper function which can be used to require up to 3 spell reagents for a particular spell to be cast. The function will return \texttt{TRUE} if the caster has the objects, otherwise \texttt{FALSE}. If the `\texttt{extract}' variable is \texttt{TRUE}, then the objects in question will be consumed by the casting. You can also make the function `\texttt{verbose}', but it is more of a debugging/funny option than practical. + +\subsubsection{Manual Spells} +Any spell that doesn't fit one of the template molds is implemented as a manual spell. Adding a manual spell requires a function to be written, generally in \texttt{spells.c}, with the \texttt{ASPELL()} macro. After the requisite spell identifier macro is added to \texttt{spells.h}, add it to the manual spell list in \texttt{spell\_parser.c}, \texttt{call\_magic()}. (Search for ``\texttt{MANUAL\_SPELL}''.) +\par +Manual spells are given: +\begin{Ventry}{victim} +\item[level] The effective character level of the spell being cast. This is NOT the same as the level of the character because the spell could have been case by a wand, staff, or scroll instead of the character. +\item[ch] The character causing the spell. +\item[victim] The target of the spell, if a character. +\item[obj] The target of the spell, if an object. +\end{Ventry} +Other than that, manual spells can do anything. Think of them as being similar to standard commands in power and scope. A useful modification is to add '\texttt{argument}' support to spells so that ``\texttt{locate object}'' works properly and a ``\texttt{change weather}'' spell could make it ``\texttt{better}'' or ``\texttt{worse}.'' + +\subsection{Adding Skills} +Skills in CircleMUD are usually implemented as commands. The first steps to adding a skill are similar to those of adding a spell. First, make sure you have a clear idea of what your skill is going to do, who you're going to give it to, and how it fits in with the rest of the game. Try to avoid making too many skills that do basically the same thing -- having lots of skills isn't a meaningful feature if most of them can be ignored. +\par +After you have a good idea of what you want to do, why you want to do it, and why it's a good idea to do it, then start by adding a \texttt{SKILL\_xxx \#define} to \texttt{spells.h} and the corresponding \texttt{skillo()} line to \texttt{mag\_assign\_spells()} in \texttt{spell\_parser.c}. The \texttt{skillo()} function takes, as its first argument, the \texttt{SKILL\_xxx \#define} and, as its second, the name of the skill, as a string. This registers the skill as something that can be practiced. As with spells, you have to register the skill's availability with individual classes at the appropriate levels in the \texttt{init\_spell\_levels()} function of \texttt{class.c}. +\par +Now your skill can be gained and practiced by players of an appropriate level and class, but it doesn't actually do anything. Most skills, like "\texttt{bash}" and "\texttt{kick}", are simply commands that perform skill checks. The setup and everything else is the same as in Section 3.1, Adding Commands. The body needs to account for (1) whether the command's user can access the skill and (2) whether they were successful in using the skill. For (1), CircleMUD uses the idiom +\begin{verbatim} + if (IS_NPC(ch) || !GET_SKILL(ch, SKILL_xxx)) { + send_to_char(ch, "You have no idea how.\r\n"); + return; + } +\end{verbatim} +to check if the skill is available. The \texttt{GET\_SKILL} macro returns the proficiency (as a percentage) the given character has in the given skill. If the proficiency is 0\%, the player does not have the skill (either because his class doesn't have it or he's not learned it, yet). This check is +preferred over directly testing if the player is of the right class(es) to use the skill, since that would require you to change several functions across several files to give skills to other classes (instead of just being able to add \texttt{spell\_level()} calls in \texttt{class.c}). +\par +At this point you would do argument processing in the typical manner, as well as any other checks that are necessary (for instance, you might want to check if the room is peaceful, as done in \texttt{do\_bash()} in \texttt{act.offensive.c}). Last, you want to check for the success or failure of the skill by rolling a percentage to compare against the user's proficiency (probability of success). This is typically done with: +\begin{verbatim} + if (number(1, 101) > GET_SKILL(ch, SKILL_xxx)) { + /* Failure. */ + } else { + /* Success. */ + } +\end{verbatim} +where you'd replace the comments with the relevant failure or success code. +\par +For skills that do damage, like "\texttt{bash}" and "\texttt{kick}", the messages for success and failure are typically not encoded in the skill itself, but instead as damage messages in \texttt{lib/misc/messages}, which has the format: +\begin{verbatim} + M + + + + + + + + + + + + + +\end{verbatim} +The skill number is the \texttt{\#define} as appears in spells.h and the rest are single line messages that will be passed to \texttt{act()}. This is similar in many respects to \texttt{lib/misc/socials}. The format is discussed in more detail in a comment at the beginning of \texttt{lib/misc/messages}. +\par +These messages are then displayed by calling \texttt{damage()} with the appropriate arguments, as discussed in Section 2.4.9, Violence, with the \texttt{attacktype} argument set to the \texttt{SKILL\_xxx \#define}, as in +\begin{verbatim} + /* + * See above and Section 3.1, Adding Commands: + * ... skill checks, argument processing, etc. + * ... vict is set to skill's victim. + */ + + if (number(1, 101) > GET_SKILL(ch, SKILL_FOO)) { + /* Failure means 0 damage is done. */ + damage(ch, vict, 0, SKILL_FOO); + } else { + /* Success means we do some damage. */ + damage(ch, vict, 10, SKILL_FOO); + } +\end{verbatim} +Note that even when the skill succeeds and, thus, our call to do 10 damage to the victim of the skill is made, we're not guaranteed to do the damage. The hit may miss, in which case \texttt{damage()} returns 0. Additionally, the hit may kill the victim, in which case \texttt{damage()} returns -1. If we're going to be modifying \texttt{vict} in our skill's function after the call to \texttt{damage()}, it's important to take these return values into consideration. See \texttt{do\_bash()} in \texttt{act.offensive.c}. + +\subsection{Adding Classes} +Classes are one of the implementors' most important decisions because the players will constantly deal with them, their advantanges, and their limitations. A good class should be balanced so that it has its own unique perks and flaws, never making other classes pointless to play. +\par +Most changes to be done for classes will be found in the \texttt{class.c} file. There may be special quirks for classes implemented in the other files but the basic defining characteristics are all there. The class needs a name, abbreviation, menu entry, unique class number, skill list, guild information, saving throws, combat hit probabilities, an ability priority list, hit/mana/move advancement per level, basic starting kit, opposing item flags, spells, skills, experience charts, and level titles. It's an exhaustive list, but the actual addition of a class isn't nearly as complicated as it sounds. +\par +The first change for a class required external of \texttt{class.c} is in \texttt{structs.h}. There, search for \texttt{CLASS\_UNDEFINED} and add a new \texttt{CLASS\_xxx} definition for your class name with the next available number. Remember to bump the value of \texttt{NUM\_CLASSES}, just below, by 1. +\par +Then search \texttt{structs.h} for "\texttt{Extra object flags}" so you can add an "\texttt{ITEM\_ANTI\_xxx}" flag for your new class. As before, use the next available number in the sequence for \texttt{ITEM\_xxx} flags. Note that the limit is "\texttt{(1 << 31)}". Beyond that you'll need special changes (not covered here) to add more flags. +\par +The "\texttt{ITEM\_xxx}" extra flags have a corresponding text description in \texttt{constants.c}, so search it for "\texttt{ITEM\_x (extra bits)}". Add a string giving a short name for the new \texttt{ITEM\_ANTI\_xxx} flag, in the appropriate order, before the "\texttt{$\backslash$n}" entry near the bottom. +\par +The shops have a similar "\texttt{don't trade}" setup, so search \texttt{shop.h} for "\texttt{TRADE\_NOGOOD}" to add a new \texttt{TRADE\_NOxxx} item to the list for the class to be +added. Below that (near "NOTRADE\_GOOD"), a line will need to be added for each new class so the '\texttt{no trade}' status of a shop can be tested for the class. +\par +With the definitions in \texttt{shop.h}, the shop code in \texttt{shop.c} can then be modified to take into account the new classes. In a manner similar to \texttt{constants.c}, there's a table in \texttt{shop.c} with textual names for the \texttt{TRADE\_NOxxx} values. Add the new class names to the "\texttt{trade\_letters[]}" array in the same order as the \texttt{TRADE\_NOxxx} bits were added to \texttt{shop.h}. Also in \texttt{shop.c}, the \texttt{is\_ok\_char()} function will need modified to add "\texttt{IS\_xyz(...) \&\& NOTRADE\_xyz(...)}" conditions, to make the above changes take effect. +\par +Lastly for changes beyond \texttt{class.c}, search \texttt{utils.h} for "\texttt{IS\_WARRIOR}" and +make a similar definition below it for the new class. +\par +Most of the changes to \texttt{class.c} will be straight-forward if going by the existing classes, so only a few items of note: +\begin{enumerate} +\item The letters used in \texttt{parse\_class()} must be unique and should correspond to the highlighted characters in the '\texttt{class\_menu}' variable. +\item Lower saving throw values are better. +\item Lower '\texttt{thaco}' values are better. +\end{enumerate} + +\subsection{Adding Levels} +Some people feel the standard 34 levels aren't enough and want to add more. Others feel 34 is too many and want to reduce it. Fortunately, changing the number of levels in the MUD is fairly painless. There are only three important things to remember: adjusting the secondary tables to +match your new levels, making over 127 levels requires some additional modifications, and to readjust the mobiles afterward. +\par +The secondary functions that rely on levels directly are: \texttt{saving\_throws}, \texttt{thaco}, \texttt{backstab\_mult}, \texttt{level\_exp}, \texttt{title\_male}, and \texttt{title\_female}. These must be changed to correctly cover the entire range of new levels for the MUD. If not, the missing levels will have incomplete data and may act in unexpected ways. Fortunately, you'll receive error messages in the logs if such an event happens. +\par +As the number of mortals levels is always one less than the lowest immortal level, changing \texttt{LVL\_IMMORT} in \texttt{structs.h} to a new value will give the desired change. Make sure you change the functions described above at the same time. The other immortals levels should be adjusted accordingly. +\par +If you're making more than 127 total levels on the MUD, a little \texttt{structs.h} surgery is required. The default range on the '\texttt{level}' variable is -128 to 127. CircleMUD doesn't actually use negative levels so changing it to '\texttt{ubyte level}' will allow 255 levels. Note that this setting hasn't been tested so test your new level settings to make sure they work as expected. If you need more than 255 levels, you'll need to change the '\texttt{byte}' to something larger, like \texttt{ush\_int} (65,535) or \texttt{unsigned int} (4.2 billion). Changing the variable type beyond byte will result in the erasing of your player files and require changes elsewhere in the code where levels are manipulated. +\par +Once you've changed the number of levels on your MUD, the implementor character you may have already created will now have the wrong level to be an implementor. If you've decreased the levels then a '\texttt{set self level XX}' command should work to drop yourself to the proper level, since you're considered above the new implementor level still. Those increasing the number of levels will find their implementor is now likely considered a mortal. In that case, you can either erase the player files to recreate yourself or make a command to make yourself the proper level, such as: +\begin{verbatim} + ACMD(do_fixmylevel) + { + if (GET_IDNUM(ch) == 1) + GET_LEVEL(ch) = LVL_IMPL; + } +\end{verbatim} +Now remember to change all the mobiles too so they have proper levels. If you added levels, it'll make the mobiles weaker unless fixed. If reducing the levels, then you'll end up with error messages in the logs when those mobiles try to use saving throws or other level-dependent values. + +\subsection{Adding Color} +Color in CircleMUD is handled on a varying scale of color levels the player can choose to display. The possible levels are off, sparse, normal, and complete. If a player has color off, no color must be sent. +\par +To send color to the players, use the \texttt{CC*} family of macros: +\begin{Ventry}{CCNRM} +\item[CCNRM] Normal text color, as defined by player's terminal. +\item[CCRED] Red +\item[CCGRN] Green +\item[CCYEL] Yellow +\item[CCBLU] Blue +\item[CCMAG] Magenta +\item[CCCYN] Cyan +\item[CCWHT] White +\end{Ventry} +Each macro takes a pointer to the character and the level at which the color given should be displayed. If the player uses a lower level of color than given to the macro in the code, the color code will reduce to an empty string so it does not appear. See '\texttt{color.pdf}' for more information on this process. +\par +Now suppose you wish to add high-intensity colors, blinking, or backgrounds for your text. The place to look for the existing color codes is in \texttt{screen.h}, but you'll just see codes like "\texttt{$\backslash$x1B[31m}" there. So what is "\texttt{$\backslash$x1B[31m}"? It is an ANSI color code understood by various terminal emulations to display color. There are predefined colors for each code and a special format to use so you can't just make up codes and expect them to work. +\par +In order to compare the low-intensity colors with the high-intensity, an additional color must be known to complete the pattern, black: +\begin{verbatim} + #define BBLK "\\x1B[30m" +\end{verbatim} +The terminal background color is assumed black by CircleMUD so that particular color definition isn't in \texttt{screen.h}. Now a comparison of red and green with their bright counterparts: +\begin{verbatim} + #define KRED "\\x1B[31m" (Dark) + #define BRED "\\x1B[0;1;31m" (Bright) + + #define KGRN "\\x1B[32m" (Dark) + #define BGRN "\\x1B[0;1;32m" (Bright) +\end{verbatim} +If you want the bright colors, you can extend this pattern to get the other standard colors. +\par +Once the \texttt{\#define} is in \texttt{screen.h}, it needs to be usable via the \texttt{CC*} color convention to respect the color level of the players, so for every new color code add a \texttt{CC*} for it, such as: +\begin{verbatim} + #define CCBRED(ch,lvl) (clr((ch),(lvl))?BRED:KNUL) + #define CCBGRN(ch,lvl) (clr((ch),(lvl))?BGRN:KNUL) +\end{verbatim} +With a number of colors, making a new \texttt{CC*} code for each one may get tedious. You may want to add a new macro, such as: +\begin{verbatim} + #define CC(ch, color, lvl) (clr((ch),(lvl))?(color):KNUL) +\end{verbatim} +Then you can use \texttt{CC(ch, KRED, C\_NRM)} instead of \texttt{CCRED(ch, C\_NRM)}. Whether or not you want to use this idiom is up to you. It might come in handy once you get into blinking (use sparingly!) and background colors. The background colors are "\texttt{$\backslash$x1B[40m}" (black), "\texttt{$\backslash$x1B[47m}" (white), and everything in the middle as per the foreground colors. + +\section{Writing Special Procedures} +Special procedures are the way to give life to your world. Through special procedures you can, for instance, make Mobiles react to player actions, fight intelligently,etc. +\par +Using special procedures, your virtual world is not just a bunch of monsters, objects and rooms, reduced to a number of statistics. Just like good descriptions add atmosphere to the world, good use of special procedures adds flesh and life to the world. +\par +Several special procedures are provided with stock CircleMUD which you can use to create your own and get used to the mechanics of special procedures. These special procedures can be found in \texttt{castle.c} and \texttt{spec\_procs.c}. They range from very simple procedures, like \texttt{puff} (pulsed special procedure) or \texttt{bank} (command-driven special procedure), to very complex procedures like the guild master. +\par +In this chapter, \texttt{FALSE} refers to the value 0 and \texttt{TRUE} to any non-zero value. + +\subsection{Overview of Special Procedures} +Special procedures are nothing more than C functions, which are associated to mobiles, objects and rooms. +\par +In the standard version of CircleMUD, special procedures are defined and assigned at compile time and cannot be changed or reassigned during runtime. + +\subsection{Pulsed vs. Command-Driven Special Procedures} +Special procedures are called at three points in code: the command interpreter (command-driven special procedures), the game heartbeat and the violence code (pulsed special procedures). +\par +There is no information kept to know if the special procedure is pulsed or command-driven, other than the behavior of the special procedure itself. When creating a special procedure you must keep in mind that it will be called in each of the three places and must therefore be prepared to react to all situations accordingly. +\par +In the next two sub-sections we will present both types of special procedures, and in the third sub-section we'll explain how to differentiate the three types of call. + +\subsubsection{Pulsed Special Procedures} +Every tick, the function heartbeat goes through the list of mobiles and the list of objects, updating everyone of them. If a mobile or an object as a special procedure associated to it, that special procedure is run with the parameters cmd and argument set to 0 and \texttt{NULL} respectively. The \texttt{NULL} used to be sent as an empty string (""), but this was changed in 3.0bpl19. +\par +When there is a fight, the special procedure of a fighting mobile is called once per round with the same arguments. + +\subsubsection{Command Driven Special Procedures} +Whenever a player issues a command, the command interpreter tries to identify it in the Master Command Table. If it succeeds, before running the command associated in the table, it checks for special procedures in the following order: +\begin{itemize} +\item room the player is in; +\item objects in the player's equipment (does not enter the containers); +\item objects in the player's inventory (does not enter the containers); +\item mobiles in the room; +\item objects in the room floor; +\end{itemize} +The first special procedure to succeed and return \texttt{TRUE} finishes the interpreting of the command. +\par +If no special procedure returned true or no special procedure was found, then the command interpreter runs the procedure specified in the Master Command Table. + +\subsubsection{Preparing for all occurrences} +In order to make your special procedure react accordingly to all the different places where the special procedure can be called you need to distinguish those places. The way to do it is through the parameters. +\par +Whenever cmd is 0, the special procedure has been called as a pulsed special procedure, otherwise it is a command-driven special procedure. +\par +To detect if the procedure was called through the violence code, it is a pulsed special procedure and \texttt{IS\_FIGHTING(me)} must be true. Of course, this only has meaning for a mobile special procedure. + +\subsection{Relating Special Procedures to Objects, Mobiles, and Rooms} +The special procedures are assigned to the prototypes of the objects and mobiles, not to the instances themselves. There are functions provided to assign the special procedures: +\begin{itemize} +\item \texttt{ASSIGNMOB(,)} +\item \texttt{ASSIGNOBJ(,)} +\item \texttt{ASSIGNROOM(,)} +\end{itemize} +Stock CircleMUD also provides a place where to put all the special procedure assignments: the functions \texttt{assign\_mobiles}, \texttt{assign\_objects}, and \texttt{assign\_rooms} in \texttt{spec\_assign.c}. + +\subsection{The Special Procedure Function Header} +The function header of any special procedure is defined in the macro \texttt{SPECIAL()} and is as follows: +\begin{verbatim} + int ()(struct char\_data *ch, void *me, int cmd, char *argument) +\end{verbatim} +where \texttt{} is the name of the special procedure. +\par +The parameters to the function are: +\begin{Ventry}{argument} +\item[ch] Character that issued the command to command interpreter that triggered this special procedure. +\item[me] The mobile, object or room to which the special procedure is given. +\item[cmd] The command that \texttt{ch} issued as recognized by the command interpreter, or zero if the special procedure is being called by the pulse code. +\item[argument] The command that the played has introduced at the prompt or an empty string if the special procedure is being called by the pulse code. +\end{Ventry} + +\subsection{The Special Procedure Return Value} +The return value of a special procedure is looked at only by the command interpreter and has meaning only for command-driven special procedures. Pulsed special procedures should always return false. +\par +A command-driven special procedure can return two values: +\begin{Ventry}{FALSE:} +\item[FALSE:] The procedure did not process the command given and it should be processed in the standard way by the command interpreter. +\item[TRUE:] The procedure reacted to the command given and so, the command interpreter should ignore it. +\end{Ventry} + +\end{document} +\end Index: doc/sources/color.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/color.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/color.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/color.tex 18 Nov 2002 03:09:38 -0000 1.2 @@ -1,6 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} \usepackage{times} +\usepackage[T1]{fontenc} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 4/2001 Index: doc/sources/files.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/files.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/files.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/files.tex 18 Nov 2002 03:09:38 -0000 1.2 @@ -1,5 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 9/2001 Index: doc/sources/hacker.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/hacker.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/hacker.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/hacker.tex 18 Nov 2002 03:09:38 -0000 1.2 @@ -1,5 +1,7 @@ \documentclass{article} \usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 4/2001 Index: doc/sources/license.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/license.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/license.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/license.tex 18 Nov 2002 03:09:38 -0000 1.2 @@ -1,5 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 9/2001 Index: doc/sources/porting.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/porting.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/porting.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/porting.tex 18 Nov 2002 03:09:38 -0000 1.2 @@ -1,5 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 6/2001 Index: doc/sources/release.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/release.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/release.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/release.tex 18 Nov 2002 03:09:38 -0000 1.2 @@ -1,5 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 9/2001 Index: doc/sources/socials.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/socials.tex,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 --- doc/sources/socials.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/socials.tex 18 Nov 2002 23:22:25 -0000 1.3 @@ -1,5 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 4/2001 @@ -28,7 +30,7 @@ Socials are all handled through the gene text file \texttt{lib/text/socials} contains information on the game's socials. New socials can be added by 1) adding the name and level of the social to the master command list in \texttt{interpreter.c} (giving \texttt{do\_action} as the function pointer), and 2) adding information for the new social to the \texttt{lib/text/socials} file. \section{File Format} -In Circle 3.0, socials in the file are specified by name (instead of by command number, as was true of the original DikuMud and versions of CircleMUD before 3.0.). In the standard CircleMUD distribution, the socials appear in alphabetical order in the file, but they can appear in any order and can be rearranged if necessary. +In Circle 3.1, socials in the file are specified by name (instead of by command number, as was true of the original DikuMud and versions of CircleMUD before 3.0.). In the standard CircleMUD distribution, the socials appear in alphabetical order in the file, but they can appear in any order and can be rearranged if necessary. \par The file is formatted as follows: \begin{verbatim} Index: doc/sources/utils.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/utils.tex,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 --- doc/sources/utils.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/utils.tex 18 Nov 2002 23:22:25 -0000 1.3 @@ -1,6 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} \usepackage{times} +\usepackage[T1]{fontenc} % This document typeset by Alex Fletcher on Dec 9/2001 \addtolength{\topmargin}{-.5in} % repairing LaTeX's huge margins... @@ -24,14 +25,14 @@ This document gives a brief summary of t \tableofcontents \section{Conversion Utilities} -These utilities are generally one-time use utilities. Some are for converting older CircleMUD data files to the versions used in CircleMUD 3.0, while others are used to convert currently existing files into different formats. +These utilities are generally one-time use utilities. Some are for converting older CircleMUD data files to the versions used in CircleMUD v3, while others are used to convert currently existing files into different formats. \par Overall, these utilities have been created in an attempt to make the CircleMUD administrator's life a bit easier, and to give the administrator some ideas of further and more grandiose utilities to create. \par Please note that these utilities are not as rigorously tested as the rest of the CircleMUD server, and you should be certain to backup your data before using these utilities on it. Also note that the code layout and design for these utilities is not as tight and as thought out as the rest of the source code distributed with CircleMUD. \subsection{play2to3} -This utility is designed to convert player files from CircleMUD v2.20 to player files that will run under CircleMUD 3.0. This utility is designed to be run once, at which point the player file will be one that the CircleMUD 3.0 server will understand. It will not remove or overwrite the old player file when it runs. +This utility is designed to convert player files from CircleMUD v2.20 to player files that will run under CircleMUD v3. This utility is designed to be run once, at which point the player file will be one that the CircleMUD v3 server will understand. It will not remove or overwrite the old player file when it runs. \par The code is not terribly attractive, but should also serve as a good base for converting your binary player files if you make any changes to the player file structure. \par @@ -39,10 +40,10 @@ The command line syntax for \texttt{play \begin{verbatim} play2to3 \end{verbatim} -where \texttt{$<$old plrfile$>$} is the CircleMUD 2.20 player file, and \texttt{$<$new plrfile$>$} is the name of the new CircleMUD 3.0 player file. +where \texttt{$<$old plrfile$>$} is the CircleMUD 2.20 player file, and \texttt{$<$new plrfile$>$} is the name of the new CircleMUD v3 player file. \subsection{shopconv} -As discussed in the CircleMUD Building Guide, the format of shops changed between CircleMUD 2.20 and CircleMUD 3.0. To make the transition easier, Jeff Fink submitted a shop conversion utility, \texttt{shopconv}. Similar to the player file converter, this should only be run against any file once. It is best to run this immediately before the initial v2.2 to v3.0 changeover. +As discussed in the CircleMUD Building Guide, the format of shops changed between CircleMUD 2.20 and CircleMUD v3. To make the transition easier, Jeff Fink submitted a shop conversion utility, \texttt{shopconv}. Similar to the player file converter, this should only be run against any file once. It is best to run this immediately before the initial v2.20 to v3 changeover. \par The command line syntax for \texttt{shopconv} is as follows: \begin{verbatim} @@ -62,8 +63,8 @@ where \texttt{[filename]} is the file to \subsection{wld2html} This utility began its life as a small toy written by Jeremy Elson to put a CircleMUD world file on the world wide web. It converts the world file into a series of HTML files, one per room, all named according to the virtual number of the room, and linked via their exits. \par -An example of its use on Midgaard can be found online -\url{http://www.circlemud.org/~jelson/dikutest/>}. +An example of its use on Midgaard can be found online at +\url{}. \par The command line syntax for \texttt{wld2html} is as follows: \begin{verbatim} Index: doc/sources/wizhelp.tex =================================================================== RCS file: /home/circledb/.cvs/circle/doc/sources/wizhelp.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- doc/sources/wizhelp.tex 15 Jan 2002 00:58:47 -0000 1.1 +++ doc/sources/wizhelp.tex 18 Nov 2002 03:09:38 -0000 1.2 @@ -1,5 +1,7 @@ \documentclass[11pt]{article} \usepackage{url} +\usepackage{times} +\usepackage[T1]{fontenc} % Document typeset from the original document that was typeset by Jeremy Elson. % This document typeset by Alex Fletcher on Dec 9/2001 Index: lib/etc/time =================================================================== RCS file: lib/etc/time diff -N lib/etc/time --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/etc/time 13 Nov 2002 20:24:31 -0000 1.1 @@ -0,0 +1 @@ +650336715 Index: lib/text/credits =================================================================== RCS file: /home/circledb/.cvs/circle/lib/text/credits,v retrieving revision 1.5 retrieving revision 1.6 diff -u -p -r1.5 -r1.6 --- lib/text/credits 22 Aug 1999 01:31:35 -0000 1.5 +++ lib/text/credits 13 Nov 2002 19:39:11 -0000 1.6 @@ -6,11 +6,12 @@ CircleMUD was developed from DikuMUD (Gamma 0.0) by Jeremy "Ras" Elson at Johns Hopkins University's Department of Computer Science. All code unique to CircleMUD is protected under a copyright by the Trustees of the Johns -Hopkins University. +Hopkins University. Additional development coordinated by Alex Fletcher, +George Greer, and Daniel Koepke with feedback from CircleMUD mailing list. CircleMUD is freeware and can be downloaded via anonymous FTP from -ftp.circlemud.org or ftp2.circlemud.org in pub/CircleMUD. Its author can -be contacted at jelson@circlemud.org. +ftp.circlemud.org or ftp2.circlemud.org in pub/CircleMUD. Its developers +can be contacted at cdev@circlemud.org. Type HELP CIRCLEMUD for more information. Index: lib/text/greetings =================================================================== RCS file: /home/circledb/.cvs/circle/lib/text/greetings,v retrieving revision 1.4 retrieving revision 1.5 diff -u -p -r1.4 -r1.5 --- lib/text/greetings 16 Jan 1999 05:27:12 -0000 1.4 +++ lib/text/greetings 18 Nov 2002 21:39:36 -0000 1.5 @@ -1,7 +1,7 @@ Your MUD Name Here lib/text/greetings - Based on CircleMUD 3.0, + Based on CircleMUD 3.1, Created by Jeremy Elson A derivative of DikuMUD (GAMMA 0.0), Index: lib/text/imotd =================================================================== RCS file: /home/circledb/.cvs/circle/lib/text/imotd,v retrieving revision 1.5 retrieving revision 1.6 diff -u -p -r1.5 -r1.6 --- lib/text/imotd 14 Jul 1999 16:08:22 -0000 1.5 +++ lib/text/imotd 18 Nov 2002 21:39:36 -0000 1.6 @@ -1,6 +1,6 @@ (lib/text/imotd) -Welcome to the long-awaited, oft-belated, highly-rated CircleMUD 3.0! +Welcome to the long-awaited, oft-belated, highly-rated CircleMUD 3.1! This is the immortal MOTD -- the file that immortals will see when they log in to the game. You should change it to something more interesting Index: lib/world/README =================================================================== RCS file: /home/circledb/.cvs/circle/lib/world/README,v retrieving revision 1.3 retrieving revision 1.4 diff -u -p -r1.3 -r1.4 --- lib/world/README 2 Feb 2001 03:18:55 -0000 1.3 +++ lib/world/README 18 Nov 2002 21:40:57 -0000 1.4 @@ -1,11 +1,11 @@ -CircleMUD 3.0 - World Files +CircleMUD - World Files - Contained in this lovely archive is the present shape of the -world for Circle 3.0. Everything should be in the form of ASCII -flags for easy addition and removal of flags. All of the shop -files are in the CircleMUD 3.0 style (and they make good examples -since there is a bit of everything, from wandering shops through -to shops that dislike certain alignments or classes). + Contained in this lovely archive is the present shape of the world +for Circle. Everything should be in the form of ASCII flags for easy +addition and removal of flags. All of the shop files are in the +CircleMUD style (and they make good examples since there is a bit of +everything, from wandering shops through to shops that dislike certain +alignments or classes). Feedback on the world is more than welcome. This includes listing things that people like and things that people do not Index: src/Makefile.amiga =================================================================== RCS file: /home/circledb/.cvs/circle/src/Makefile.amiga,v retrieving revision 1.3 retrieving revision 1.4 diff -u -p -r1.3 -r1.4 --- src/Makefile.amiga 3 Nov 1998 17:58:04 -0000 1.3 +++ src/Makefile.amiga 18 Nov 2002 21:23:38 -0000 1.4 @@ -1,4 +1,4 @@ -# CircleMUD 3.0 Makefile.in - Makefile template used by 'configure' +# CircleMUD Makefile.in - Makefile template used by 'configure' # # C compiler to use Index: src/Makefile.arc =================================================================== RCS file: /home/circledb/.cvs/circle/src/Makefile.arc,v retrieving revision 1.3 retrieving revision 1.4 diff -u -p -r1.3 -r1.4 --- src/Makefile.arc 3 Nov 1998 17:58:05 -0000 1.3 +++ src/Makefile.arc 18 Nov 2002 21:23:38 -0000 1.4 @@ -1,4 +1,4 @@ -# CircleMUD 3.0 Makefile/arc - manually created (G. Duncan 13 June 98) +# CircleMUD Makefile/arc - manually created (G. Duncan 13 June 98) # # C compiler to use Index: src/Makefile.in =================================================================== RCS file: /home/circledb/.cvs/circle/src/Makefile.in,v retrieving revision 1.16 retrieving revision 1.17 diff -u -p -r1.16 -r1.17 --- src/Makefile.in 16 Apr 2002 02:22:12 -0000 1.16 +++ src/Makefile.in 18 Nov 2002 21:23:38 -0000 1.17 @@ -1,4 +1,4 @@ -# CircleMUD 3.0 Makefile.in - Makefile template used by 'configure' +# CircleMUD Makefile.in - Makefile template used by 'configure' # # C compiler to use Index: src/Makefile.lcc =================================================================== RCS file: /home/circledb/.cvs/circle/src/Makefile.lcc,v retrieving revision 1.10 retrieving revision 1.12 diff -u -p -r1.10 -r1.12 --- src/Makefile.lcc 30 Apr 2002 20:58:09 -0000 1.10 +++ src/Makefile.lcc 18 Nov 2002 21:23:38 -0000 1.12 @@ -1,4 +1,4 @@ -# Makefile for LCC-Win32 compile of CircleMUD 3.0 +# Makefile for LCC-Win32 compile of CircleMUD # Created by Eric Jones (mailto:fpicard@mindless.com) # 08/31/98 @@ -12,7 +12,7 @@ # thus less clutter on the screen during the make LCCDIR=c:\lccpub -DISTDIR=c:\circle30bpl22 +DISTDIR=c:\circle CFLAGS=-c -I$(LCCDIR)\include -DLCC_WIN32 CC=lcc OBJS=\ Index: src/Makefile.msvc =================================================================== RCS file: /home/circledb/.cvs/circle/src/Makefile.msvc,v retrieving revision 1.2 retrieving revision 1.3 diff -u -p -r1.2 -r1.3 --- src/Makefile.msvc 3 Nov 1998 17:58:06 -0000 1.2 +++ src/Makefile.msvc 18 Nov 2002 21:23:38 -0000 1.3 @@ -1,5 +1,5 @@ # -# CircleMUD 3.0 Makefile for Microsoft Visual C++ 4.0, Windows 95/NT +# CircleMUD Makefile for Microsoft Visual C++ 4.0, Windows 95/NT # (manually created by Jeremy Elson) # # NOTE: This Makefile is only for MSVC 4.0. If you have a different Index: src/Makefile.os2 =================================================================== RCS file: /home/circledb/.cvs/circle/src/Makefile.os2,v retrieving revision 1.4 retrieving revision 1.5 diff -u -p -r1.4 -r1.5 --- src/Makefile.os2 3 Nov 1998 17:58:06 -0000 1.4 +++ src/Makefile.os2 18 Nov 2002 21:23:38 -0000 1.5 @@ -1,4 +1,4 @@ -# CircleMUD 3.0 Makefile for OS/2 (manually created by David Carver) +# CircleMUD Makefile for OS/2 (manually created by David Carver) # C compiler to use CC = gcc Index: src/Smakefile =================================================================== RCS file: /home/circledb/.cvs/circle/src/Smakefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- src/Smakefile 29 Oct 1997 05:16:20 -0000 1.1 +++ src/Smakefile 18 Nov 2002 21:23:38 -0000 1.2 @@ -1,4 +1,4 @@ -# CircleMUD 3.0 makefile for the Amiga +# CircleMUD makefile for the Amiga # C compiler to use CC = sc Index: src/castle.c =================================================================== RCS file: /home/circledb/.cvs/circle/src/castle.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -p -r1.28 -r1.29 --- src/castle.c 9 Apr 2002 12:34:36 -0000 1.28 +++ src/castle.c 18 Nov 2002 02:30:47 -0000 1.29 @@ -51,7 +51,7 @@ int is_trash(struct obj_data *i); void fry_victim(struct char_data *ch); int castle_cleaner(struct char_data *ch, int cmd, int gripe); int castle_twin_proc(struct char_data *ch, int cmd, char *arg, int ctlnum, const char *twinname); -void castle_mob_spec(int mobnum, SPECIAL(*specproc)); +void castle_mob_spec(mob_vnum mobnum, SPECIAL(*specproc)); /**********************************************************************\ @@ -79,7 +79,7 @@ ACMD(do_follow); * NOTE: The mobile number isn't fully specified. It's only an offset * from the zone's base. */ -void castle_mob_spec(int mobnum, SPECIAL(*specproc)) +void castle_mob_spec(mob_vnum mobnum, SPECIAL(*specproc)) { mob_vnum vmv = castle_virtual(mobnum); mob_rnum rmr = NOBODY; Index: src/comm.c =================================================================== RCS file: /home/circledb/.cvs/circle/src/comm.c,v retrieving revision 1.117 retrieving revision 1.119 diff -u -p -r1.117 -r1.119 --- src/comm.c 4 Oct 2002 07:14:38 -0000 1.117 +++ src/comm.c 13 Nov 2002 20:02:18 -0000 1.119 @@ -962,7 +962,7 @@ void echo_off(struct descriptor_data *d) (char) 0, }; - write_to_output(d, off_string); + write_to_output(d, "%s", off_string); } @@ -979,7 +979,7 @@ void echo_on(struct descriptor_data *d) (char) 0 }; - write_to_output(d, on_string); + write_to_output(d, "%s", on_string); } @@ -996,41 +996,33 @@ char *make_prompt(struct descriptor_data "\r\n[ Return to continue, (q)uit, (r)efresh, (b)ack, or page number (%d/%d) ]", d->showstr_page, d->showstr_count); } else if (STATE(d) == CON_PLAYING && !IS_NPC(d->character)) { - int count, idx; + int count; size_t len = 0; - struct prompt_value_data { - bitvector_t pref; - long cur_value; - long max_value; - const char *format; - } prompt_display[] = { - { 0, GET_INVIS_LEV(d->character), 0, "i%d " }, - { PRF_DISPHP, GET_HIT(d->character), GET_MAX_HIT(d->character), "%dH " }, - { PRF_DISPMANA, GET_MANA(d->character), GET_MAX_MANA(d->character), "%dM " }, - { PRF_DISPMOVE, GET_MOVE(d->character), GET_MAX_MOVE(d->character), "%dV " }, - }; *prompt = '\0'; - for (idx = 0; idx < sizeof(prompt_display) / sizeof(struct prompt_value_data); idx++) { - if (prompt_display[idx].pref) { - if (PRF_FLAGGED(d->character, prompt_display[idx].pref)) - /* Always display. */ ; - else if (PRF_FLAGGED(d->character, PRF_DISPAUTO) && prompt_display[idx].cur_value * 3 < prompt_display[idx].max_value) - /* Under 33%, display. */ ; - else - continue; - } else if (!prompt_display[idx].cur_value) - continue; + if (GET_INVIS_LEV(d->character) && len < sizeof(prompt)) { + count = snprintf(prompt + len, sizeof(prompt) - len, "i%d ", GET_INVIS_LEV(d->character)); + if (count >= 0) + len += count; + } + + if (PRF_FLAGGED(d->character, PRF_DISPHP) && len < sizeof(prompt)) { + count = snprintf(prompt + len, sizeof(prompt) - len, "%dH ", GET_HIT(d->character)); + if (count >= 0) + len += count; + } - count = snprintf(prompt + len, sizeof(prompt) - len, prompt_display[idx].format, prompt_display[idx].cur_value); + if (PRF_FLAGGED(d->character, PRF_DISPMANA) && len < sizeof(prompt)) { + count = snprintf(prompt + len, sizeof(prompt) - len, "%dM ", GET_MANA(d->character)); if (count >= 0) len += count; - else - len = sizeof(prompt); /* -1 return value: old versions of snprintf give when truncating. */ + } - if (len >= sizeof(prompt)) - break; + if (PRF_FLAGGED(d->character, PRF_DISPMOVE) && len < sizeof(prompt)) { + count = snprintf(prompt + len, sizeof(prompt) - len, "%dV ", GET_MOVE(d->character)); + if (count >= 0) + len += count; } if (len < sizeof(prompt)) @@ -1149,8 +1141,11 @@ size_t vwrite_to_output(struct descripto buf_overflows++; } - /* if we have enough space, just write to buffer and that's it! */ - if (t->bufspace >= size) { + /* + * If we have enough space, just write to buffer and that's it! If the + * text just barely fits, then it's switched to a large buffer instead. + */ + if (t->bufspace > size) { strcpy(t->output + t->bufptr, txt); /* strcpy: OK (size checked above) */ t->bufspace -= size; t->bufptr += size; @@ -1461,9 +1456,10 @@ int process_output(struct descriptor_dat /* * If the overflow message or prompt were partially written, try to save - * them. There will be enough space for them if this is true. + * them. There will be enough space for them if this is true. 'result' + * is effectively unsigned here anyway. */ - if (result < strlen(osb)) { + if ((unsigned int)result < strlen(osb)) { size_t savetextlen = strlen(osb + result); strcat(t->output, osb + result); Index: src/constants.c =================================================================== RCS file: /home/circledb/.cvs/circle/src/constants.c,v retrieving revision 1.25 retrieving revision 1.26 diff -u -p -r1.25 -r1.26 --- src/constants.c 25 Apr 2002 06:04:53 -0000 1.25 +++ src/constants.c 18 Nov 2002 17:28:06 -0000 1.26 @@ -15,7 +15,7 @@ #include "interpreter.h" /* alias_data */ cpp_extern const char *circlemud_version = - "CircleMUD, version 3.00 beta patchlevel 22"; + "CircleMUD, version 3.1"; /* strings corresponding to ordinals/bitvectors in structs.h ***********/ Index: src/house.c =================================================================== RCS file: /home/circledb/.cvs/circle/src/house.c,v retrieving revision 1.29 retrieving revision 1.30 diff -u -p -r1.29 -r1.30 --- src/house.c 2 May 2002 03:13:33 -0000 1.29 +++ src/house.c 18 Nov 2002 02:29:54 -0000 1.30 @@ -33,7 +33,7 @@ int House_get_filename(room_vnum vnum, c int House_load(room_vnum vnum); int House_save(struct obj_data *obj, FILE *fp); void House_restore_weight(struct obj_data *obj); -void House_delete_file(int vnum); +void House_delete_file(room_vnum vnum); int find_house(room_vnum vnum); void House_save_control(void); void hcontrol_list_houses(struct char_data *ch); @@ -148,7 +148,7 @@ void House_crashsave(room_vnum vnum) /* Delete a house save file */ -void House_delete_file(int vnum) +void House_delete_file(room_vnum vnum) { char filename[MAX_INPUT_LENGTH]; FILE *fl; Index: src/limits.c =================================================================== RCS file: /home/circledb/.cvs/circle/src/limits.c,v retrieving revision 1.31 retrieving revision 1.32 diff -u -p -r1.31 -r1.32 --- src/limits.c 3 Mar 2002 23:19:17 -0000 1.31 +++ src/limits.c 13 Nov 2002 19:30:51 -0000 1.32 @@ -346,14 +346,14 @@ void gain_condition(struct char_data *ch switch (condition) { case FULL: send_to_char(ch, "You are hungry.\r\n"); - return; + break; case THIRST: send_to_char(ch, "You are thirsty.\r\n"); - return; + break; case DRUNK: if (intoxicated) send_to_char(ch, "You are now sober.\r\n"); - return; + break; default: break; } Index: src/magic.c =================================================================== RCS file: /home/circledb/.cvs/circle/src/magic.c,v retrieving revision 1.36 retrieving revision 1.37 diff -u -p -r1.36 -r1.37 --- src/magic.c 4 Oct 2002 04:02:14 -0000 1.36 +++ src/magic.c 18 Nov 2002 21:23:38 -0000 1.37 @@ -101,7 +101,7 @@ void affect_update(void) * mag_materials: * Checks for up to 3 vnums (spell reagents) in the player's inventory. * - * No spells implemented in Circle 3.0 use mag_materials, but you can use + * No spells implemented in Circle use mag_materials, but you can use * it to implement your own spells which require ingredients (i.e., some * heal spell which requires a rare herb or some such.) */ @@ -588,7 +588,7 @@ void mag_groups(int level, struct char_d /* * mass spells affect every creature in the room except the caster. * - * No spells of this class currently implemented as of Circle 3.0. + * No spells of this class currently implemented. */ void mag_masses(int level, struct char_data *ch, int spellnum, int savetype) { @@ -666,7 +666,7 @@ void mag_areas(int level, struct char_da /* * Every spell which summons/gates/conjours a mob comes through here. * - * None of these spells are currently implemented in Circle 3.0; these + * None of these spells are currently implemented in CircleMUD; these * were taken as examples from the JediMUD code. Summons can be used * for spells like clone, ariel servant, etc. * Index: src/shop.h =================================================================== RCS file: /home/circledb/.cvs/circle/src/shop.h,v retrieving revision 1.13 retrieving revision 1.14 diff -u -p -r1.13 -r1.14 --- src/shop.h 14 Nov 2001 16:29:28 -0000 1.13 +++ src/shop.h 13 Nov 2002 19:49:28 -0000 1.14 @@ -124,8 +124,8 @@ struct stack_data { -#define WILL_START_FIGHT 1 -#define WILL_BANK_MONEY 2 +#define WILL_START_FIGHT (1 << 0) +#define WILL_BANK_MONEY (1 << 1) #define SHOP_KILL_CHARS(i) (IS_SET(SHOP_BITVECTOR(i), WILL_START_FIGHT)) #define SHOP_USES_BANK(i) (IS_SET(SHOP_BITVECTOR(i), WILL_BANK_MONEY)) Index: src/structs.h =================================================================== RCS file: /home/circledb/.cvs/circle/src/structs.h,v retrieving revision 1.53 retrieving revision 1.56 diff -u -p -r1.53 -r1.56 --- src/structs.h 25 Sep 2002 22:29:47 -0000 1.53 +++ src/structs.h 18 Nov 2002 21:23:38 -0000 1.56 @@ -17,14 +17,14 @@ * You are supposed to compare this with the macro CIRCLEMUD_VERSION() * in utils.h. See there for usage. */ -#define _CIRCLEMUD 0x030016 /* Major/Minor/Patchlevel - MMmmPP */ +#define _CIRCLEMUD 0x030100 /* Major/Minor/Patchlevel - MMmmPP */ /* * If you want equipment to be automatically equipped to the same place * it was when players rented, set the define below to 1. Please note * that this will require erasing or converting all of your rent files. * And of course, you have to recompile everything. We need this feature - * for CircleMUD 3.0 to be complete but we refuse to break binary file + * for CircleMUD to be complete but we refuse to break binary file * compatibility. */ #define USE_AUTOEQ 0 /* TRUE/FALSE aren't defined yet. */ @@ -536,7 +536,7 @@ typedef char bool; #endif #if !defined(CIRCLE_WINDOWS) || defined(LCC_WIN32) /* Hm, sysdep.h? */ -typedef char byte; +typedef signed char byte; #endif /* Various virtual (human-reference) number types. */ Index: src/utils.h =================================================================== RCS file: /home/circledb/.cvs/circle/src/utils.h,v retrieving revision 1.57 retrieving revision 1.58 diff -u -p -r1.57 -r1.58 --- src/utils.h 18 May 2002 00:53:03 -0000 1.57 +++ src/utils.h 18 Nov 2002 02:29:42 -0000 1.58 @@ -184,7 +184,7 @@ void update_pos(struct char_data *victim #define IS_SET(flag,bit) ((flag) & (bit)) #define SET_BIT(var,bit) ((var) |= (bit)) #define REMOVE_BIT(var,bit) ((var) &= ~(bit)) -#define TOGGLE_BIT(var,bit) ((var) = (var) ^ (bit)) +#define TOGGLE_BIT(var,bit) ((var) ^= (bit)) /* * Accessing player specific data structures on a mobile is a very bad thing Index: src/util/Makefile.in =================================================================== RCS file: /home/circledb/.cvs/circle/src/util/Makefile.in,v retrieving revision 1.2 retrieving revision 1.3 diff -u -p -r1.2 -r1.3 --- src/util/Makefile.in 29 Oct 1997 22:04:09 -0000 1.2 +++ src/util/Makefile.in 18 Nov 2002 21:24:07 -0000 1.3 @@ -1,4 +1,4 @@ -# CircleMUD 3.0 Makefile.in - Makefile template used by 'configure' +# CircleMUD Makefile.in - Makefile template used by 'configure' # for the 'util' directory # C compiler to use