Compare commits

..

No commits in common. "modular-version" and "master" have entirely different histories.

428 changed files with 127986 additions and 4064 deletions

39
.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
aclocal.m4
autom4te.cache/
Makefile
Makefile.in
depcomp
install-sh
ltmain.sh
missing
config.h
config.h.in
configure
config.log
config.status
config.guess
config.sub
stamp-h1
*.swp
*~
*.exe
*.db
*.anjuta
tags
gtk-doc.make
m4
*.bak
create-world.sh
drop-world.sh
libtool
nbproject/private
conf/wmud.conf
cscope.out
var
/wmud/enumtypes.[ch]
/GPATH
/GRTAGS
/GSYMS
/GTAGS

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
Gergely POLONKAI <gergely@polonkai.eu>

674
COPYING Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

4
HACKING Normal file
View File

@ -0,0 +1,4 @@
Hacking wMUD
============
The whole source code is well documented with GtkDoc.

365
INSTALL Normal file
View File

@ -0,0 +1,365 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@ -1,5 +1,16 @@
ACLOCAL_AMFLAGS=-I m4 ACLOCAL_AMFLAGS = -I m4
SUBDIRS = libwmud-session libwmud-world libwmud-state-sqlite3 libwmud-protocol-telnet src doc/reference/libwmud-session doc/reference/libwmud-world SUBDIRS = wmud
dist_doc_DATA = README
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-debug if ENABLE_GTK_DOC
SUBDIRS += docs/reference/wmud
endif
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
csclean:
-rm -f cscope.out
cscope.out:
cscope -bR
cscope: csclean cscope.out

59
README
View File

@ -1,11 +1,54 @@
What is wMUD? What is wMUD?
============= =============
On one hand, wMUD is a new (well, yet another) MUD (Multi-User Dungeon)
server. It is designed to run as smoothly as possible, which is achieved by
using threads. During development I tried to eliminate everything which is not
GLib, so, although not tested yet, it should by highly portable.
On the other hand, wMUD is a learning project for GLib's several features. wMUD is a MUD code base. It is written from scratch, using GLib and CURL.
This means that although I double check every byte of code, it can still have Although it is just another MUD code base, I tried to add unique features, and
bugs or not-so-effective code chunks. If you find one, please don't hesitate to also tried to make it as flexible as possible.
contact me, or send a patch!
What are the key features?
==========================
wMUD stores everything in an SQLite3 database, and everything really means
everything. The whole world is dynamic, and most of it can be defined without
touching the code itself. Possible directions, areas, rooms, items, mobs,
races, classes and all important apects of the world are in the database
backend, and as such, can be reloaded runtime without stopping the MUD.
wMUD is modular. Except the basic commands, everything is loaded via dynamic
modules (well, on systems which support it). This again helps flexibility, as
commands, spells, and many more can be loaded or unloaded runtime. This, of
cource can sometimes cause funny things in game play (characters disappearing
because of unloaded race), but everything can be explained with a good story.
Or, if you are not creative enough, you can simply disable this functionality.
wMUD is a threaded application using GLib's GThread functionality. All tasks
are done by separate threads, so the game can run as smoothly as possible. The
game world is ran by one thread. Database updating is done by a separate
maintenance thread. This may cause some lags in the database update process,
but whenever it causes trouble, wizards can force the maintenance thread to
start immediately. The Out-of-Game chat functions also run in different
threads.
Why writing a new codebase?
===========================
The MUD codebases out there (well, the ones that are freely available) are a
bit outdated. Yes, I know that in the world of MMORPG games even MUD is
outdated, but who cares?
The other part of the story is that I needed challenge. Writing such a software
while creating a world to run in it is a huge job. However, creating a world in
a codebase that does not really support the features I need requires a lot of
coding. I realized it early during the world building with CircleMUD, so I've
decided to create a new codebase even if I have to recode everything from
scratch. As GLib, SQLite3 and CURL are at my hands, even if I'm just trying to
get to know them, it was not that hard.
How can I help in development, or add my own stuff?
===================================================
wMUD's development, so as other MUD codebases', is no easy task. Although each
thread is coded in a separate file (except the game thread), threading makes it
even difficult. I try to make this task as easy as possible with comments and
an API reference, but this is also a hard goal to accomplish. If you really
want to mess with things, the file HACKING is just the place for you.

450
TODO
View File

@ -1,76 +1,424 @@
CLIENT FLOW wMUD TODO file
=========== ==============
[X] connection arrives This file is continuously migrated into the Zim wiki (later it will become
[X] connection gets accept()'ed media or dokuwiki).
[ ] connection is closed if the IP is banned
[X] session object created
[ ] welcome banner gets sent
[X] user sends commans
[ ] commands get processed
[X] user sends the QUIT command
[X] session gets destroyed
[X] connection gets destroyed
Legend
------
TO-DO LIST [ ] planned
========== [f ] feature request added to flyspray
[ i] implementation began
[XX] finished
[X] Create own text formatting style Game world
----------
[o] Create converter that can convert from own style to [ ] * People start in a well-defined start location (randomly selected during
[X] ANSI character generation)
[ ] colourless text [ ] - Races may have at least one possible start locations, so different
[ ] HTML races can start at different locations
[ ] Pango markup [ ] - The whole world should have one fallback start location (Tree of
only the first two are very important Memories?). Characters with no specified starting locations will
start the game here.
[X] Do basic jobs for later threading support [ ] * Housing system should automatically expand towns (this will be fun to
write). Maybe a better alternative is to check for free housing and
if the amount goes too low, manually create some new one.
[ ] - To make the decision if a town actually needs new houses, some
statistics are required.
[ ] - Housing can be decorated with different objects ('decoration' item
flag; can not exceed a maximum number, depending on house size).
[ ] - Houses get untidy over time, so they need to be cleaned
[ ] - House maids (for cleaning, and maybe basic cooking)
[ ] - Houses have a fix price
[ ] - Locks
[ ] . Locks of houses not visited occasionally get more and more rusty,
making it easier to break into them. Burglars can take whatever
they want!
[ ] . Locks decompose after a given time, making the house door openable
and the house accessible to anyone
[ ] . Fixing the lock requires Mechanics after a given amount of condition
loss, otherwise a small amount of oil helps
[ ] . Unowned houses' locks are maintained regularly
[ ] . Players may occupy an abandoned house if the world is configured to
enable it. Otherwise abandoned houses get occupied by town guards,
and are sold again after a given time.
[X] Create and run the world object in a separate thread [ ] * Inn and Tavern system
[ ] - Characters can set their hometown in an Inn; however, Inns have only a
limited amount of rooms. Inn rooms cost some amount of gold per day,
which is pre-paid. If the rent is over, the character's start
location is set to one of the racial defaults. If the character is
online when the rent is over, they should get a warning message
about this. If the player gets an own house, their home location
should be automatically set to it
[ ] - Tavern system
[ ] . Tables and chairs
[ ] . Tables are private chat rooms with a maximum number of members
[ ] . Each tavern has a fixed amount of tables and chairs
[ ] . Chairs can be moved from one table to another if not occupied
[ ] . Tables have a maximum number of chairs (which may vary depending on
the table's size)
[X] Implement session handling [ ] * Item disposal methods
[ ] - Drop (DROP <item>)
Dropped items don't generate points, nor money. They also get the
dropped flag, so they loose some (most) of their property bonuses
unless their original owner picks them up
[ ] - Donation (DONATE <item>)
Donated items automatically appear in the nearest donation room (or
random, maybe). Donations are recorded, and the characters who
donate in larger amounts and/or more valuable items may get rewards
for public service. Items dropped in donation centers also count as
donated
[ ] - Sacrifice (SACRIFICE <item> [to] <god>)
Sacrificed items become energy, which the Gods retun as Sacrifice
Points
[ ] - Salvage (SALVAGE <item>)
Most items can be salvaged to get some raw materials back. Of
course, it is way less than the original amount required to craft
the item. Salvaging may require tools.
[ ] - Auction (AUCTION <item>)
Items can be auctioned at the Market Squares
[X] Create telnet interface that can process commands and send colourful [ ] * Item creation (AKA combining or Professions)
responses. This should go in a separate thread. [ ] - Trainers, who know only specific recipes
[ ] - Recipe scrolls (e.g to be dropped by mobs and such) (item flag
'recipe'; custom fields must be added for Profession ID and recipe
ID)
[ ] - Corpse skinning (only corpses of mobs with the 'skinnable' flag)
[ ] - Corpse butching (only corpses of mobs with the 'butchable' flag)
[ ] - Fishing (only in rooms with the 'fishing' flag)
[ ] - Mining (only if the room has an item with the 'minable' flag)
[ ] - Foraging (only if the room has an item with the 'foragable' flag)
[ ] - Blacksmithing (only if the room has an item with the 'anvil' flag, and
the character has an item with the 'blacksmith-hammer' flag)
[ ] - Alchemy (some recipes may require an item in the room with the
'alchemytools' flag)
[X] Plan configurable parameters and configuration file format [ ] * Companions
[ ] - Combat/Pack animals
[ [ - May be rented
[ ] - They should also advance in age
[ ] - Mounts (may also act as combat/pack animals)
[ ] - Charming
[ ] - Servants, pages
[X] Write configuration reading code [ ] * Gods
[ ] - Gods may be chosen upon character creation. Amount is configurable.
(for Iminiru, a character MUST have at least two Gods)
[ ] - Sacrifices
[ ] - Prayers
[o] Create XML schemas for world description [ ] * Reputation system
[ ] Specify a way how new attribute and object types can be inserted into [ ] * Player Clans
a running system [ ] - Clan bank
[ ] - Clan wars (Players from a Guild may PK players from another Guild if
the two Guilds are in war with each other)
[ ] Specify state-saving backends: [ ] * Item types
[ ] SQLite3 [ ] - Armour/Clothing
[ ] MySQL [ ] . Shields
[ ] PostgreSQL [ ] - Weapon
[ ] XML [ ] . Ballista
[ ] GDBM [ ] . Bashing
[ ] . Bow
[ ] . Crossbow
[ ] . Club
[ ] . Knuckle
[ ] . Lash
[ ] . Net
[ ] . Piercing
[ ] . Slashing
[ ] . Whip
[ ] - Potion
[ ] - Poison (appliable to weapons)
[ ] - Food/Water/Alcohol/Sugar
[ ] - Light
[ ] - Spell reagent
[ ] - Material
[ ] - Artifacts
[ ] - Containers
[ ] . Bags
[ ] . Chests
[ ] Specify data to be saved during state-save [ ] * Death system, Rebirth
[ ] Write state saving (command and timed hook) and loading (command and [ ] * War Machines
startup time) code
[o] Write world description loading and reloading code [ ] * Shops
[ ] - Most shops should open/close depending on the in-game time
[ ] Write User Account management code (possibility of registration, [ ] * Skills/Spells/Talents granted by the Gods
login, logout, account deletion, ban, kick and purge [ ] - Fear
[o] Write chat possibility [ ] * Magic Profession
[ ] Write Light-calculation code [ ] * Fighting Professions with practicing
[ ] - Disarm
[ ] - Dual Wield
[ ] - Stun
[ ] Plan initial character state (what attributes to use, look, cloths, [ ] * The whole system should be built with class support, although Iminiru
armour, weapon, etc.) will technically have only one "Adventurer" class. Also, multiclassing
should be possible
[ ] Create the possibility to enter the world [ ] * Character aging, with racial maximum age. When a character is too old,
they can retire (e.g they will become story tellers or such), or die
and reborn. Reborn characters have a bonus to their maximum age. Upon
rebirth they create a totally new character, with all their old data
remaining in the database. Reborn characters have the possibility to
regain all their old powers after a few years
[ ] Create the possibility to move in the world [ ] * Quests
[ ] - Quests given by NPCs
[ ] - Player creatable quests
[ ] - Character bounty, which can be placed by other characters for a fee
(should be enabled per world), or NPCs.
[ ] Create a DBus module to control the whole program [ ] * In-game chat (whisper, say, shout, emotes, group/party, guild). Guild
chat should be accessible without entering the game (from the
Circle-like main menu), or even via IRC or something like that
# vim: textwidth=78 : tabstop=8 : expandtab [ ] * Speedwalking?
[ ] * Arenas
[ ] * Mercy mob flag: mobs will stop attacking if their enemy is unable to
fight any more
[ ] * Mobs should be able to wear/wield items, have an inventory, have Skills,
Spells and Talents
[ ] * Sneaking, thieving, robbery
[ ] - A mob may steal stuff from you, you may detect it, and maybe able to
catch it and get your stuff back. However, killing them in a city
may result in punishment by the guards.
[ ] - Player killing/thieving should be enabled/disabled per world
[ ] * Gossips
[ ] - Bragging NPCs: if a character gets killed by specific NPCs, those
NPCs will humiliate that character for a while
[ ] * Weapon USE: wielded weapons may do something (like cast spells or such)
if a specific attribute is set. The item spell should recharge over
time, or recharge upon a specific condition
[ ] * Money (with the possibility to create several money types, like
different currencies for different Races or Countries)
[ ] - Money has weight
[ ] * Banks
[ ] - Money deposit (with interest in some banks)
[ ] - Storage, for a fee
[ ] - Loans
[ ] * All looted items should be used in some way or another. Sacrifice is a
common way, but some items may be milled (e.g bones and herbs) or
disassembled (e.g Mechanics objects or armour), others may be used as
raw materials. Extracted body parts (e.g blood or meat) should
decompose over time, even in an inventory, unless put in a special
container
[ ] * Object affects and attribute modifiers, like an earring which make the
character deaf. These affects may be hidden, and even delayed (e.g the
character puts on the earring that gives a high amount of charisma,
but after wearing it for a specific time, they will become deaf, and
they will have no idea what caused it. The same object can also be
cursed, so it cannot be removed except by some professional magicians
[ ] * Item modifiers, like sharpening stones
[ ] * Item durability. Items must have a Profession and a Profession Level
associated to them to show who can repair it
[ ] * Mob glowing (e.g they will be unable to sneak)
[ ] * Polls
[ ] * Configurable prompt
[ ] * Marriage?
[ ] * Character titles, which can be rewards for quests, or be bought for a
high amount of money
[ ] * Spirit world
[ ] - Some rooms (at least one) should be marked as Spirit World. Upon
death, characters get the DEAD flag, and get to this room. They must
find their way to remove the DEAD flag, and/or find a way back to
the real world.
[ ] * Blood may remain on the floor during a fight (even without a kill)
[ ] * Special rooms
[ ] - Death trap rooms
[ ] - Regeneration rooms
[ ] - Teleportation objects (portal machines) and rooms (elevators)
[ ] * Languages
[ ] * Books
[ ] * Rivers should have some kind of a current. If you get into a river (even
on a boat, or by swimming), it will move you automatically somewhere
[ ] * Gambling (may be illegal in some towns ;) )
[ ] * Guides that can be payed for. E.g in a big city, a guide can lead you to
the Inn, or something like that for a small fee.
[ ] * Automatically hiding/appearing exits (e.g to create mazes or to hide
stuff)
[ ] * Mailing
[ ] * Abilities
[ ] - Rolled upon character creation
[ ] - May be trained (ability training may be enabled/disabled system wide)
[ ] - There should be a racial maximum
[ ] - May be modified by affections and worn items
[ ] - May increase/decrease with age
[ ] * Tattoes, scars, piercings, etc.
[ ] * Lights that shine on each other and on the world
Commands
--------
[ ] * Commands already defined in Zim Wiki:
[ ] - DROP
[ ] - GET
[ ] - PRACISE/PRACTICE
[ ] - PRAY
[ ] - RECALL
Take back the character to their house, or the Inn room they have
rented. Specific rooms may have a flag so there must be no recall
from them (this should also mean that upon logout/login, the
character will get back to this room)
[ ] - SURVEY
[ ] - TALE
[ ] * Commands that should be present
[ ] - AFFECTS
Shows all the spells that affects the character (spell name, apply
count, duration, applier name)
[ ] - SCORE
Shows the player's statistics
[ ] - INVENTORY
Shows the character's inventory
[ ] - EQUIPMENT
Shows the equipped items
[ ] - LOOK
[ ] - EXITS
[ ] - EXAMINE should be an alias to LOOK, except it should work only on objects
[ ] - CONSIDER
[ ] - SET
[ ] . AUTOLOOT [OFF]
[ ] . AUTOSKIN [OFF]
[ ] . AUTODRAIN [OFF]
[ ] . AUTOSPLIT [OFF]
[ ] . AUTOEXIT [ON ]
[ ] . COLOR [ON ]
[ ] . AUTOLOOK [ON ]
[ ] . WIMPY [OFF]
[ ] . AUTOCONSUME [OFF]
(To automatically consume food and drink when hungry/thirsty)
[ ] . GROUPINV [ON ]
[ ] . PAGELENGTH [30 ]
[ ] - BURY/DIG
[ ] - EQUIP/WIELD
[ ] - IGNORE/UNIGNORE
[ ] - WHO/WHOIS
[ ] - QUIT
Exits the game
[ ] - LOGOUT
Goes back to the intro menu
[ ] - USE
Use objects in hand (map, weapons with spells, etc.), or in room
(buttons, levers, etc.)
Materia Magica command list
---------------------------
$ = gold
. = shout
/ = chat
; = formtalk
? = help
away affects affected auction align alias alliance bury build backstab bash
breathe bank cast channels combat ctf clear cls commands consider chat clan
clantalk ct close charge chess changes credits class challenge description
donate dream dig drink drop disarm dismount effects evoke equipment examine
enter extinguish emote eat empty equip fill feed flee friends faction formation
ft feign get gold give grab grapple guide gohome hitch help hold herald hint
hide history home inventory invoke ignore kill kick knock look light levels
lock locker lay mix memorize mail marks mount news novice notify order open
practice pktalk pray pick put pull push play protocols page quest quit rest
read report rules relay reply remove run recall rewardunit religion raise snare
sit stand sweep score socials skills scan survey say sayto shop shout search
sacrifice set sleep sneak ship steal shift slit strike tell tag time termreset
typo title turn take throw track train unhitch use unequip unlock vendor
visible version wield who whisper weather wimpy wear write wake where yell
CircleMUD commands
------------------
POS_DEAD
; advance alias at autodrain autoexit autoloot ban brief bug clear cls color
commands compact credits date dc display freeze gecho handbook hcontrol help
holylight idea immlist imotd inventory invis last levels load motd mute
noauction nogossip nograts nohassle norepeat nosummon notell notitle nowiz olc
page pardon policy poofin poofout prompt purge qecho quest qui quit reload
reroll restore return roomflags score set show shutdow shutdown slowns snoop
socials stat switch syslog teleport tell thaw time title toggle trackthru typo
unaffect unban ungroup uptime users version vnum vstat who whoami wimpy wizlist
wizlock wiznet zreset
POS_FIGHTING
assist bash flee hit kick kill murder rescue
POS_RESTING
: ' applaud ask beg bleed blush brb burp cackle chuckle clap comb comfort
consider cough cringe cry cuddle curse diagnose donate drink drool drop eat
emote exits fart flirt follow fondle french frown fume gasp get giggle give
glare gold grab greet grin groan grope group grovel growl hiccup hide hold
holler hop house hug insult junk kiss laugh lick look love massage moan nibble
nod nudge nuzzle order pat peer point poke ponder pout practice puke punch purr
put qsay quaff read recite remove report rest roll say scream shake shiver
shout shrug sigh sing sip sit slap smile smirk snap snarl sneeze snicker sniff
snuggle spank squeeze stand stare steam stroke sulk tackle take taste taunt
thank think tickle twiddle visible wave wear weather where whine whisper
whistle wield wink worship yawn yodel
POS_SITTING
accuse cast close examine lock open pray split unlock use
POS_SLEEPING
auction daydream echo equipment force gossip goto grats gsay gtell info news
noshout reply save send skillset sleep snore transfer wake wizhelp
POS_STANDING
backstab balance bounce bow bury buy check curtsey dance deposit dig down drain
east embrace enter fill flip leave list mail north offer pick pour receive rent
ruffle sell sneak snowball south spit steal strut tango track up value west
wiggle withdraw write
Fill-in words:
in from with the on at to
Reserved words:
a an self me all room someone something

10
autogen.sh Executable file
View File

@ -0,0 +1,10 @@
#! /bin/sh
mkdir m4 &> /dev/null
gtkdocize --copy || exit 1
libtoolize --install --copy || exit 1
autoheader || exit 1
aclocal || exit 1
autoconf || exit 1
automake --add-missing --copy || exit 1

71
conf/wmud.conf.example Normal file
View File

@ -0,0 +1,71 @@
[global]
# The game thread will listen on this port.
port = 4000
# The e-mail address of the MUD's administrator
admin email = gergely@polonkai.eu
# If set to true and only one race is defined in the database, registering
# players will automatically "choose" that, and they will not get any
# notification about this. Useful if your MUD is actually raceless.
hide single race = true
# If set to true and only one class is defined in the database, registering
# players will automatically "choose" that, and they will not get any
# notification about this. Useful if your MUD is actually classless.
hide single class = true
# If non-zero, characters can occupy houses not visited by their owner in the
# last <number> in-game days with the HOUSE OCCUPY command (of course only if
# they can get inside).
house occupy time = 100
# The minimum number of deities a player must choose during character
# generation.
minimum deities = 2
# If set to true, clans can decide war on other clans (the number of other
# clans depends on the clan's level)
clan wars = true
# The maximum size of a player group. You should not set this too high.
maximum group size = 5
# If set to true, abilities are trainable
trainable abilities = true
# If set to true, characters can choose to die, and reborn in a new body if
# they are old enough (80% of the racial maximum age)
reborn = true
# SMTP related settings go here. SMTP is required to send out initially
# generated passwords
[smtp]
# The SMTP server's address. It's in the format server[:port]. If port is
# omitted, the default given by libcurl will be used
smtp server = smtp.gmail.com:587
# Set to true if the SMTP server provides or requires TLS connections. It's a
# wise idea to set it to true, if you know your server supports it, even if it
# does not require it.
smtp tls = true
# The username to use to send e-mails
smtp username = wmud
# The password to use to send e-mails
smtp password = wmudPassWD1
# The sender's e-mail address. This will appear in all sent e-mails. Should be
# in the form Name <e-mail@address>, where Name can be omitted
smtp sender = wMUD <polesz@w00d5t0ck.info>
[database]
# The world database file. This file holds everything needed to create the
# in-game world and let players login.
#
# WARNING! If you are using SQLite as a backend, your database filename will
# WARNING! automatically have .db appended after the name you specify here!
dsn = SQLite://DB_DIR={statedir};DB_NAME=iminiru

View File

@ -1,30 +1,88 @@
AC_INIT([wmud], [1.0], [polesz@w00d5t0ck.info]) AC_INIT([wMUD], [0.1.0])
AM_INIT_AUTOMAKE([-Wall -Werror foreign]) AC_CONFIG_HEADER([config.h])
LT_INIT AC_CONFIG_SRCDIR([configure.ac])
AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug], [compile with debugging support. Be warned that debugging support can eat a large amount of CPU when many clients are connected. Also, debug logs can become very large!])], , enable_debug=no) AC_CONFIG_MACRO_DIR([m4])
if test "x$enable_debug" = "xyes" ; then AM_INIT_AUTOMAKE
AC_DEFINE([DEBUG], [1], [Define if debugging is enabled.]) LT_INIT
fi
AC_PROG_CC AC_PROG_CC
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
PKG_PROG_PKG_CONFIG PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES([GLIB], [glib-2.0])
PKG_CHECK_MODULES([GOBJECT], [gobject-2.0]) AC_CHECK_HEADERS([crypt.h])
PKG_CHECK_MODULES([GNET], [gnet-2.0]) AC_SEARCH_LIBS([crypt], [crypt])
PKG_CHECK_MODULES([EXTLIBS], [libxml-2.0, glib-2.0, gobject-2.0, gthread-2.0, gnet-2.0, gnome-vfs-2.0, sqlite3 gmodule-2.0]) AC_CHECK_FUNC([crypt], ac_have_crypt=yes, ac_have_crypt=no)
GTK_DOC_CHECK([1.10]) if test "$ac_have_crypt" != "yes"; then
AC_CONFIG_MACRO_DIR([m4]) echo "The crypt() function call can not be found."
AC_CONFIG_HEADERS([config.h]) exit 1
AC_CONFIG_FILES([ fi
Makefile
libwmud-session/Makefile AC_ARG_ENABLE(
libwmud-world/Makefile [debug],
libwmud-state-sqlite3/Makefile AS_HELP_STRING(
libwmud-protocol-telnet/Makefile [--enable-debug],
src/Makefile [Enable debugging support (default: disabled)]),
doc/reference/libwmud-session/Makefile [enable_debug=yes; CFLAGS="$CFLAGS -g -Wall"],
doc/reference/libwmud-world/Makefile [enable_debug=no])
AM_CONDITIONAL([ENABLE_DEBUG], [test "$enable_debug" = "yes"])
if test "$enable_debug" = "yes"; then
AC_DEFINE([DEBUG], [1], [Define to compile with debugging support])
fi
AC_DEFINE([WMUD_TICK_LENGTH], [500], [Length of a game tick, in milliseconds])
AC_DEFINE([WMUD_HEARTBEAT_LENGTH], [30], [Length of a heartbeat, in ticks])
AC_DEFINE([WMUD_MAINTENANCE_TIME],
[600],
[Time between maintenance runs, in seconds])
m4_ifdef([GTK_DOC_CHECK], [
GTK_DOC_CHECK([1.14], [--flavour no-tmpl])
],[
AM_CONDITIONAL([ENABLE_GTK_DOC], false)
]) ])
AC_OUTPUT
AC_ARG_ENABLE(
[memcached],
AS_HELP_STRING(
[--disable-memcached],
[Disable Memcached support (default: enabled)]),
[],
[enable_memcached=yes])
AM_CONDITIONAL([ENABLE_MEMCACHED], [test "$enable_memcached" = "yes"])
if test "$enable_memcached" = "yes"; then
PKG_CHECK_MODULES([MEMCACHED], libmemcached);
AC_DEFINE([ENABLE_MEMCACHED],
[1],
[Define to compile with Memcached support])
fi
AC_DEFINE([DEFAULT_PORT],
[4000],
[The default port number if not specified in the config file])
AC_DEFINE([MAX_RECV_LEN],
[1024],
[The maximum length of the recv() queue in bytes])
PKG_CHECK_MODULES([GIO], gio-2.0)
PKG_CHECK_MODULES([GLIB], glib-2.0)
PKG_CHECK_MODULES([GTHREAD], gthread-2.0)
PKG_CHECK_MODULES([GDA], libgda-5.0)
PKG_CHECK_MODULES([CURL], libcurl)
LIBCURL_CHECK_CONFIG
if test "$libcurl_protocol_SMTP" != "yes"; then
echo "Your libCURL installation does not support the SMTP protocol."
exit 1
fi
AM_PATH_GLIB_2_0
AC_OUTPUT(
Makefile
wmud/Makefile
docs/reference/wmud/Makefile
create-world.sh
drop-world.sh
)

10
create-world.sh.in Normal file
View File

@ -0,0 +1,10 @@
#! /bin/bash
sqlite3 "@localstatedir@"/iminiru.db < sql/menu.sql
sqlite3 "@localstatedir@"/iminiru.db < sql/planes.sql
sqlite3 "@localstatedir@"/iminiru.db < sql/planets.sql
sqlite3 "@localstatedir@"/iminiru.db < sql/rooms.sql
sqlite3 "@localstatedir@"/iminiru.db < iminiru/data.sql

1
data/texts/motd Normal file
View File

@ -0,0 +1 @@
Hello, and welcome to Iminiru!

View File

@ -1,68 +0,0 @@
# general options
[general]
# log can be "syslog" (to log through the syslog facility), "file:<filename>"
# to log to the specified file, "console" (to log to the console), or "none"
# (for no logging at all). console can be used only if compiled with debug
# support. If logging is set to console, wMUD cannot be daemonized!
log = console
# if you wish, you can send debug, info, warning and error message to different
# destinations by defining a "debug log", an "info log", a "warning log" and an
# "error log" respectively
#debug log = file:/home/polesz/Projektek/wMUD/data/debug.log
info log = console
warning log = console
error log = console
chat = yes
dbus = yes
# after initialization, send into the background. This setting is automatically
# set to "no" if logging is set to "console". However, if daemonize is set to
# "force", wMUD will be sent to the background, and will be forced to log
# through the syslog facilty
daemonize = no
# wMUD is highly extensible with the use of modules
[modules]
# modules dir sets the place where module files can be found
modules dir = /home/polesz/Projektek/wMUD/modules
# the statesave module is used to save all the state of a running wMUD server.
# Only one module can be specified here, and one MUST be specified. Without
# such a module, wMUD won't be able to save character states, thus won't start
# without one
statesave = sqlite3
# wMUD doesn't speak any protocols on its own. Of course, several protocol
# handler modules are provided with wMUD, and these can be loaded here. Module
# names (thus, protocol names) can be separated by colons. At least one
# protocol module must be loaded here. After startup, a client with
# administrator privileges can load up more modules
protocol = telnet:irc
# statesave * groups can have any keys and values, they won't get checked
# during the configfile read. They are only processed by the state saving
# module loaded in the modules group
[statesave sqlite3]
# for the sqlite3 state saving module, only a state file must be specified
state file = /home/polesz/Projektek/wMUD/data/state.sql
# similar to the statesave modules, protocol settings are also not checked
# during initialization, only while actually loading up the modules.
# telnet interface on all interfaces' port 4000, with the timeout value of 10
# minutes
[protocol telnet global]
port = 4000
timeout = 600
# telnet interface on localhost's port 9683 with the timeout value of 10
# minutes
[protocol telnet local]
address = 127.0.0.1
port = 9683
timeout = 600
# IRC interface listening on all interfaces' port 6667, with no timeout value
[protocol irc global]
port = 6667
# vim: ft=dosini

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<wmud>
<world id="1">
<name>Iminiru</name>
</world>
</wmud>

View File

@ -1,29 +0,0 @@
All texts must conform to the following standards:
They must provide a valid XML is wrapped with this template:
<?xml version="1.0" encoding="utf-8"?>
<wmud>
<formatted-text>
THE TEXT ITSELF
</formatted-text>
</wmud>
Text can be formatted with the following tags:
<normal>TEXT</normal> - provides normal text (clears all formatting)
<bold>TEXT</bold> - provides bold text
<underline>TEXT</underline> - provides underlined text
<COLOUR>TEXT</COLOUR> - provides coloured text in the given colour, see below for exact tag names
Possible values for COLOUR:
* black
* red
* green
* yellow
* blue
* magenta
* cyan
* white
Please note that although most MUD clients support the above text formatting, some older terminals not.
Also, for telnet-like clients, the text is wrapped into 78 columns after formatting has been applied.

View File

@ -1,102 +0,0 @@
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=wmud-session
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
DOC_MODULE_VERSION=1
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# The directory containing the source code. Relative to $(srcdir).
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting the functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk
DOC_SOURCE_DIR=$(top_srcdir)/libwmud-session
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
MKDB_OPTIONS=--sgml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=
CFILE_GLOB=
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files to ignore when scanning. Use base file name, no paths
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
IGNORE_HFILES=
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files=
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files=
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(GNET_CFLAGS)
GTKDOC_LIBS=$(GLIB_LIBS) $(GOBJECT_LIBS) $(GNET_LIBS) -L$(top_srcdir)/libwmud-session -lwmud-session-1.0
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
#DISTCLEANFILES +=
# Comment this out if you want your docs-status tested during 'make check'
if ENABLE_GTK_DOC
#TESTS_ENVIRONMENT = cd $(srcsrc) &&
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/git.mk

View File

@ -1,32 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>wmud-session Reference Manual</title>
<releaseinfo>
for wmud-session [VERSION].
The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://[SERVER]/wmud-session/index.html">http://[SERVER]/wmud-session/</ulink>.
</releaseinfo>
</bookinfo>
<chapter>
<title>[Insert title here]</title>
<xi:include href="xml/wmud-session.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@ -1,19 +0,0 @@
<SECTION>
<FILE>wmud-session</FILE>
<TITLE>wMUDSession</TITLE>
wMUDSession
wMUDSessionClass
wMUDSessionPrivate
wmud_session_new
wmud_session_new_with_connection
wmud_session_set_connection
<SUBSECTION Standard>
WMUD_SESSION
WMUD_IS_SESSION
WMUD_TYPE_SESSION
wmud_session_get_type
WMUD_SESSION_CLASS
WMUD_IS_SESSION_CLASS
WMUD_SESSION_GET_CLASS
</SECTION>

View File

@ -1,32 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>wmud-world Reference Manual</title>
<releaseinfo>
for wmud-world [VERSION].
The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://[SERVER]/wmud-world/index.html">http://[SERVER]/wmud-world/</ulink>.
</releaseinfo>
</bookinfo>
<chapter>
<title>[Insert title here]</title>
<xi:include href="xml/wmud-world.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@ -1,17 +0,0 @@
<SECTION>
<FILE>wmud-world</FILE>
<TITLE>wMUDWorld</TITLE>
wMUDWorld
wMUDWorldClass
wMUDWorldPrivate
wmud_world_new
<SUBSECTION Standard>
WMUD_WORLD
WMUD_IS_WORLD
WMUD_TYPE_WORLD
wmud_world_get_type
WMUD_WORLD_CLASS
WMUD_IS_WORLD_CLASS
WMUD_WORLD_GET_CLASS
</SECTION>

View File

@ -1 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>

14
docs/reference/wmud/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
*.stamp
*.args
*.hierarchy
*.interfaces
*.prerequisites
*.signals
*-decl-list.txt
*-decl.txt
*-overrides.txt
*-undeclared.txt
*-undocumented.txt
*-unused.txt
html
xml

View File

@ -9,20 +9,20 @@ AUTOMAKE_OPTIONS = 1.6
# of using the various options. # of using the various options.
# The name of the module, e.g. 'glib'. # The name of the module, e.g. 'glib'.
DOC_MODULE=wmud-world DOC_MODULE=wmud
# Uncomment for versioned docs and specify the version of the module, e.g. '2'. # Uncomment for versioned docs and specify the version of the module, e.g. '2'.
DOC_MODULE_VERSION=1 #DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to. # The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# The directory containing the source code. Relative to $(srcdir). # Directories containing the source code.
# gtk-doc will search all .c & .h files beneath here for inline comments # gtk-doc will search all .c and .h files beneath these paths
# documenting the functions and macros. # for inline comments documenting functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk # e.g. DOC_SOURCE_DIR=$(top_srcdir)/gtk $(top_srcdir)/gdk
DOC_SOURCE_DIR=$(top_srcdir)/libwmud-world DOC_SOURCE_DIR=$(top_srcdir)/wmud
# Extra options to pass to gtkdoc-scangobj. Not normally needed. # Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS= SCANGOBJ_OPTIONS=
@ -32,8 +32,8 @@ SCANGOBJ_OPTIONS=
SCAN_OPTIONS= SCAN_OPTIONS=
# Extra options to supply to gtkdoc-mkdb. # Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml # e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--xml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl # Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl
@ -56,8 +56,8 @@ CFILE_GLOB=
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h # e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES= EXTRA_HFILES=
# Header files to ignore when scanning. Use base file name, no paths # Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES= IGNORE_HFILES=
# Images to copy into HTML directory. # Images to copy into HTML directory.
@ -78,8 +78,8 @@ expand_content_files=
# signals and properties. # signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(GNET_CFLAGS) GTKDOC_CFLAGS=
GTKDOC_LIBS=$(GLIB_LIBS) $(GOBJECT_LIBS) $(GNET_LIBS) -L$(top_srcdir)/libwmud-world -lwmud-world-1.0 GTKDOC_LIBS=
# This includes the standard gtk-doc make rules, copied by gtkdocize. # This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make include $(top_srcdir)/gtk-doc.make
@ -93,9 +93,12 @@ EXTRA_DIST +=
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
#DISTCLEANFILES += #DISTCLEANFILES +=
# Comment this out if you want your docs-status tested during 'make check' # Comment this out if you want 'make check' to test you doc status
# and run some sanity checks
if ENABLE_GTK_DOC if ENABLE_GTK_DOC
#TESTS_ENVIRONMENT = cd $(srcsrc) && TESTS_ENVIRONMENT = cd $(srcdir) && \
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
#TESTS = $(GTKDOC_CHECK) #TESTS = $(GTKDOC_CHECK)
endif endif

View File

@ -0,0 +1,48 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>wmud Reference Manual</title>
<releaseinfo>
for wMUD 0.1.
The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://w00d5t0ck.info/wmud/index.html">http://w00d5t0ck.info/wmud/</ulink>.
</releaseinfo>
</bookinfo>
<chapter>
<title>wMUD hackers' guide</title>
<!--xi:include href="xml/types.xml"/-->
<xi:include href="xml/utils.xml"/>
<xi:include href="xml/wmudclient.xml"/>
<xi:include href="xml/wmudplayer.xml"/>
<xi:include href="xml/wmudworld.xml"/>
<xi:include href="xml/configuration.xml"/>
<xi:include href="xml/maintenance-thread.xml"/>
<xi:include href="xml/game-thread.xml"/>
<xi:include href="xml/game-networking.xml"/>
<xi:include href="xml/interpreter.xml"/>
<xi:include href="xml/db.xml"/>
<xi:include href="xml/player.xml"/>
<xi:include href="xml/menu.xml"/>
<!--xi:include href="xml/world.xml"/-->
</chapter>
<!--chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter-->
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<!--index id="deprecated-api-index" role="deprecated">
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index-->
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@ -0,0 +1,214 @@
<SECTION>
<TITLE>WmudClient</TITLE>
<FILE>wmudclient</FILE>
WmudClient
WmudClientPrivate
WmudClientState
WmudClientYesnoCallback
WMUD_CLIENT
WMUD_CLIENT_CLASS
WMUD_CLIENT_GET_CLASS
WMUD_IS_CLIENT
WMUD_IS_CLIENT_CLASS
WMUD_TYPE_CLIENT
WMUD_TYPE_CLIENT_STATE
wmud_client_close
wmud_client_get_bademail
wmud_client_get_buffer
wmud_client_get_buffer_length
wmud_client_get_last_recv_age
wmud_client_get_login_fail_count
wmud_client_get_player
wmud_client_get_socket
wmud_client_get_socket_source
wmud_client_get_state
wmud_client_get_type
wmud_client_get_yesno_callback
wmud_client_increase_login_fail_count
wmud_client_new
wmud_client_newchar_answer
wmud_client_quitanswer
wmud_client_set_authenticated
wmud_client_set_bademail
wmud_client_set_context
wmud_client_set_player
wmud_client_set_socket
wmud_client_set_state
wmud_client_set_yesno_callback
wmud_client_state_get_type
</SECTION>
<SECTION>
<TITLE>WmudPlayer</TITLE>
<FILE>wmudplayer</FILE>
WmudPlayer
WmudPlayerPrivate
WMUD_IS_PLAYER
WMUD_IS_PLAYER_CLASS
WMUD_PLAYER
WMUD_PLAYER_CLASS
WMUD_PLAYER_GET_CLASS
WMUD_TYPE_PLAYER
wmud_player_get_cpassword
wmud_player_get_email
wmud_player_get_fail_count
wmud_player_get_id
wmud_player_get_player_name
wmud_player_get_registered
wmud_player_get_type
wmud_player_increase_fail_count
wmud_player_new
wmud_player_password_valid
wmud_player_reset_fail_count
wmud_player_set_cpassword
wmud_player_set_email
wmud_player_set_id
wmud_player_set_player_name
wmud_player_set_registered
</SECTION>
<SECTION>
<TITLE>WmudWorld</TITLE>
<FILE>wmudworld</FILE>
WMUD_IS_WORLD
WMUD_IS_WORLD_CLASS
WMUD_TYPE_WORLD
WMUD_WORLD
WMUD_WORLD_CLASS
WMUD_WORLD_GET_CLASS
WmudWorldPrivate
wmud_world_new
</SECTION>
<SECTION>
<TITLE>Utility and uncategorized functions</TITLE>
<FILE>utils</FILE>
random_number
wmud_random_string
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>configuration</FILE>
WMUD_CONFIG_ERROR
wmudConfigError
ConfigData
active_config
wmud_config_init
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>maintenance-thread</FILE>
wmud_maintenance_init
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>game-thread</FILE>
elapsed_seconds
elapsed_cycle
game_context
wmud_game_init
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>game-networking</FILE>
TELNET_DO
TELNET_DONT
TELNET_IAC
TELNET_WILL
TELNET_WONT
TELNET_ECHO
clients
wmud_networking_init
wmud_client_send
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>interpreter</FILE>
wmudInterpreterError
WMUD_INTERPRETER_ERROR
wmudCommandFunc
wmudCommand
WMUD_COMMAND
wmud_interpret_game_command
wmud_interpreter_check_directions
wmud_interpreter_error_quark
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>db</FILE>
WMUD_DB_ERROR
wmudDbError
wmud_db_init
wmud_db_load_players
wmud_db_save_player
wmud_db_error_quark
wmud_db_load_areas
wmud_db_load_directions
wmud_db_load_exits
wmud_db_load_menu
wmud_db_load_planes
wmud_db_load_planet_planes
wmud_db_load_planets
wmud_db_load_rooms
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>player</FILE>
players
wmud_player_dup
wmud_player_exists
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>menu</FILE>
wmudMenu
wmudMenuCommandFunc
WMUD_MENU_COMMAND
WMUD_MENU_ERROR
wmud_menu_error_quark
wmud_menu_execute_command
wmud_menu_get_command_by_menuchar
wmud_menu_init
wmud_menu_items_check
wmud_menu_items_free
wmud_menu_present
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>world</FILE>
WMUD_WORLD_ERROR
wmudWorldError
wmud_world_assoc_exits_rooms
wmud_world_assoc_planets_planes
wmud_world_assoc_rooms_areas
wmud_world_assoc_rooms_planets
wmud_world_check_areas
wmud_world_check_exits
wmud_world_check_planes
wmud_world_check_planets
wmud_world_check_rooms
wmud_world_error_quark
wmud_world_load
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>area</FILE>
wmudArea
</SECTION>
<SECTION>
<TITLE></TITLE>
<FILE>room</FILE>
wmudRoom
wmudRoomExit
</SECTION>

3
drop-world.sh.in Normal file
View File

@ -0,0 +1,3 @@
#! /bin/bash
sqlite3 "@localstatedir@"/iminiru.db < sql/drop-world.sql

44
iminiru/data.sql Normal file
View File

@ -0,0 +1,44 @@
-- id menuchar need_active_char placement display_text fnctn
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'w', 0, 0, 'Enter the world', 'enter-world');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'p', 0, 1, 'Change password', 'change-password');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'c', 0, 2, 'Toggle colour', 'toggle-colour');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'd', 0, 3, 'Read the documentation', 'documentation');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'a', 0, 4, 'Change active character', 'caracter-select');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'n', 0, 5, 'Create new character', 'character-create');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'r', 1, 6, 'Delete active character', 'character-delete');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'i', 0, 7, 'Enter the chat rooms', 'chat');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'm', 0, 8, 'Check your player mail', 'player-mail');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 't', 0, 9, 'Colour test', 'colour-test');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'e', 0, 10, 'Change e-mail address', 'change-email');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'g', 0, 11, 'Change real name', 'change-name');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, 'q', 0, 12, 'Return to the real world', 'quit');
INSERT INTO menu (id, menuchar, need_active_char, placement, display_text, fnctn) VALUES (NULL, '?', 0, 13, 'Redisplay menu', 'redisplay-menu');
INSERT INTO directions (id, short_name, name) VALUES (1, 'n', 'north');
INSERT INTO directions (id, short_name, name) VALUES (2, 'nw', 'northwest');
INSERT INTO directions (id, short_name, name) VALUES (3, 'w', 'west');
INSERT INTO directions (id, short_name, name) VALUES (4, 'sw', 'southwest');
INSERT INTO directions (id, short_name, name) VALUES (5, 's', 'south');
INSERT INTO directions (id, short_name, name) VALUES (6, 'se', 'southeast');
INSERT INTO directions (id, short_name, name) VALUES (7, 'e', 'east');
INSERT INTO directions (id, short_name, name) VALUES (8, 'ne', 'northeast');
INSERT INTO directions (id, short_name, name) VALUES (9, 'u', 'up');
INSERT INTO directions (id, short_name, name) VALUES (10, 'd', 'down');
INSERT INTO planes (id, name) VALUES (1, 'Erodar');
INSERT INTO planes (id, name) VALUES (2, 'Indiar');
INSERT INTO planes (id, name) VALUES (3, 'Zothar');
INSERT INTO planets (id, name) VALUES (1, 'Erodar');
INSERT INTO planet_planes (planet_id, plane_id) VALUES (1, 1);
INSERT INTO planet_planes (planet_id, plane_id) VALUES (1, 2);
INSERT INTO planet_planes (planet_id, plane_id) VALUES (1, 3);
INSERT INTO areas (id, name) VALUES (1, 'Tutorial Area');
INSERT INTO rooms (id, area, name, distant_description, close_description) VALUES (1, 1, 'Tutorial Welcome Area', 'You see a small room with some tables and chairs in it.', 'You are in a small room with some tables and chairs.');
INSERT INTO rooms (id, area, name, distant_description, close_description) VALUES (2, 1, 'Tutorial Fighting Area', 'You see a small arena barely enough for a few people to fight.', 'You are in a small arena. It is barely large enough for few people to fight.');
INSERT INTO room_exits (room_id, direction, other_side) VALUES (1, 1, 2);
INSERT INTO room_exits (room_id, direction, other_side) VALUES (2, 5, 1);

View File

@ -1,6 +0,0 @@
LIBWMUD_PROTOCOL_TELNET_VERSION=1:0:0
lib_LTLIBRARIES = libwmud-protocol-telnet-1.0.la
libwmud_protocol_telnet_1_0_la_SOURCES = wmud-protocol-telnet.c
libwmud_protocol_telnet_1_0_la_CFLAGS = $(CFLAGS) $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(GNET_CFLAGS) -Wall -I../src -I../libwmud-session
libwmud_protocol_telnet_1_0_la_LIBADD = $(LIBS) $(GLIB_LIBS) $(GOBJECT_LIBS) $(GNET_LIBS)
libwmud_protocol_telnet_1_0_la_LDFLAGS = -version-info $(LIBWMUD_PROTOCOL_TELNET_VERSION)

View File

@ -1,102 +0,0 @@
#include "wmud-module.h"
gboolean
wmud_protocol_telnet_load(wMUDConfiguration *configuration)
{
/*
GSList *temp;
wMUDConfigurationInterface *interface;
gchar *iface_name;
struct _wMUDIfaceFinder *finder;
finder = g_new0(struct _wMUDIfaceFinder, 1);
finder->type = WMUD_SESSION_TYPE_TELNET;
finder->name = iface_name = g_utf8_offset_to_pointer(group, 7);
Context;
temp = g_slist_find_custom(conf->interfaces, finder, _wmud_find_iface);
Context;
g_free(finder);
if (temp == NULL)
{
Context;
interface = (wMUDConfigurationInterface *)g_new0(wMUDConfigurationInterface, 1);
interface->name = g_strdup(iface_name);
interface->type = WMUD_SESSION_TYPE_TELNET;
conf->interfaces = g_slist_append(conf->interfaces, interface);
}
else
{
Context;
interface = (wMUDConfigurationInterface *)(temp->data);
}
if (g_utf8_collate("port", key) == 0)
{
guint64 portnumber;
gchar *endptr;
portnumber = g_ascii_strtoull(value, &endptr, 10);
if ((endptr != NULL) && (*endptr != 0))
{
wmud_log_error("Error in configuration file. Value of port can only contain numbers in group [%s]!", group);
}
if (interface->inetaddr == NULL)
{
interface->inetaddr = gnet_inetaddr_new("0.0.0.0", portnumber);
}
else
{
gnet_inetaddr_set_port(interface->inetaddr, (gint)portnumber);
}
g_pattern_spec_free(group_ptn);
return TRUE;
}
if (g_utf8_collate("address", key) == 0)
{
GInetAddr *temp = gnet_inetaddr_new(value, 0);
if (interface->inetaddr)
{
gnet_inetaddr_set_port(temp, gnet_inetaddr_get_port(interface->inetaddr));
gnet_inetaddr_unref(interface->inetaddr);
interface->inetaddr = NULL;
}
interface->inetaddr = temp;
g_pattern_spec_free(group_ptn);
return TRUE;
}
if (g_utf8_collate("timeout", key) == 0)
{
guint64 timeout;
gchar *endptr;
timeout = g_ascii_strtoull(value, &endptr, 10);
if ((endptr != NULL) && (*endptr != 0))
{
wmud_log_error("Error in configuration file. Value of timeout can only contain numbers! in group [%s]", group);
}
interface->timeout = (guint)timeout;
g_pattern_spec_free(group_ptn);
return TRUE;
}
*/
return TRUE;
}
void
wmud_protocol_telnet_unload(void)
{
}

View File

@ -1,6 +0,0 @@
LIBWMUD_SESSION_VERSION=1:0:0
lib_LTLIBRARIES = libwmud-session-1.0.la
libwmud_session_1_0_la_SOURCES = wmud-session.c
libwmud_session_1_0_la_CFLAGS = $(CFLAGS) $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(GNET_CFLAGS) -Wall
libwmud_session_1_0_la_LIBADD = $(LIBS) $(GLIB_LIBS) $(GOBJECT_LIBS) $(GNET_LIBS)
libwmud_session_1_0_la_LDFLAGS = -version-info $(LIBWMUD_SESSION_VERSION)

View File

@ -1,304 +0,0 @@
/* wMUDSession - wMUD Session handler object
* Copyright (C) 2010, Gergely Polonkai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gnet.h>
#include "wmud-session.h"
/** SECTION:objects
* @short_description: wMUD Session object
* @title: wMUD Session handler object
*
* wMUDSession is an object to store session-related information in
* wMUD
*/
/* --- macros --- */
#define WMUD_SESSION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WMUD_TYPE_SESSION, wMUDSessionPrivate))
/* --- structures --- */
struct _wMUDSessionPrivate
{
GConn *connection;
wMUDSessionType type;
};
/* --- signals --- */
/* --- properties --- */
enum
{
PROP_0,
PROP_CONNECTION,
PROP_TYPE
};
/* --- prototypes --- */
static void wmud_session_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
static void wmud_session_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
static void wmud_session_dispose(GObject *object);
static void wmud_session_finalize(GObject *object);
static void wmud_session_class_init(wMUDSessionClass *klass);
static void wmud_session_init(wMUDSession *self);
wMUDSession *wmud_session_new(void);
wMUDSession *wmud_session_new_with_connection(GConn *connection);
GConn *wmud_session_get_connection(wMUDSession *session);
void wmud_session_set_connection(wMUDSession *session, GConn *connection);
wMUDSessionType wmud_session_get_session_type(wMUDSession *session);
void wmud_session_set_session_type(wMUDSession *session, wMUDSessionType type);
/* --- variables --- */
/* --- functions --- */
G_DEFINE_TYPE(wMUDSession, wmud_session, G_TYPE_OBJECT);
#define WMUD_TYPE_SESSION_TYPE wmud_session_type_get_type()
static GType
wmud_session_type_get_type(void)
{
static GType wmud_session_type_type = 0;
static const GEnumValue wmud_session_types[] = {
{ WMUD_SESSION_TYPE_UNKNOWN, "Unknown session type", "unknown" },
{ WMUD_SESSION_TYPE_TELNET, "Telnet session", "telnet" },
{ 0, NULL, NULL }
};
if (!wmud_session_type_type)
{
wmud_session_type_type = g_enum_register_static("wMUDSessionType", wmud_session_types);
}
return wmud_session_type_type;
}
static void
wmud_session_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
wMUDSession *self = WMUD_SESSION(object);
switch (property_id)
{
case PROP_CONNECTION:
if (self->priv->connection)
{
gnet_conn_unref(self->priv->connection);
}
self->priv->connection = (GConn *)g_value_get_pointer(value);
if (self->priv->connection)
{
gnet_conn_ref(self->priv->connection);
}
break;
case PROP_TYPE:
self->priv->type = g_value_get_enum(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void
wmud_session_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
wMUDSession *self = WMUD_SESSION(object);
switch (property_id)
{
case PROP_CONNECTION:
g_value_set_pointer(value, self->priv->connection);
break;
case PROP_TYPE:
g_value_set_enum(value, self->priv->type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void
wmud_session_dispose(GObject *object)
{
G_OBJECT_CLASS(wmud_session_parent_class)->dispose(object);
}
static void
wmud_session_finalize(GObject *object)
{
wMUDSession *self = WMUD_SESSION(object);
if (self->priv->connection)
{
gnet_conn_disconnect(self->priv->connection);
gnet_conn_unref(self->priv->connection);
self->priv->connection = NULL;
}
G_OBJECT_CLASS(wmud_session_parent_class)->finalize(object);
}
static void
wmud_session_class_init(wMUDSessionClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GParamSpec *wmud_session_param_spec;
gobject_class->set_property = wmud_session_set_property;
gobject_class->get_property = wmud_session_get_property;
gobject_class->dispose = wmud_session_dispose;
gobject_class->finalize = wmud_session_finalize;
g_type_class_add_private(klass, sizeof(wMUDSessionPrivate));
wmud_session_param_spec = g_param_spec_pointer("connection", "Connection handle", "GConn * handle of the connection", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property(gobject_class, PROP_CONNECTION, wmud_session_param_spec);
wmud_session_param_spec = g_param_spec_enum("type", "SessionType", "Type of the session's connection", WMUD_TYPE_SESSION_TYPE, WMUD_SESSION_TYPE_UNKNOWN, G_PARAM_READWRITE);
g_object_class_install_property(gobject_class, PROP_TYPE, wmud_session_param_spec);
}
static void
wmud_session_init(wMUDSession *self)
{
wMUDSessionPrivate *priv;
self->priv = priv = WMUD_SESSION_GET_PRIVATE(self);
priv->connection = NULL;
}
/**
* wmud_session_new:
*
* Creates a new wMUDSession object
*
* Returns: a new instance of wMUDSession
*/
wMUDSession *
wmud_session_new(void)
{
wMUDSession *new_session = g_object_new(WMUD_TYPE_SESSION, NULL);
return new_session;
}
/**
* wmud_session_new_with_connection:
* @connection: the connection this session is bound to. This object is
* g_unref()'d when the Session object is disposed
*
* Returns: a new instance of wMUDSession with the connection property set
*/
wMUDSession *
wmud_session_new_with_connection(GConn *connection)
{
wMUDSession *new_session = g_object_new(WMUD_TYPE_SESSION, "connection", connection, NULL);
wmud_session_set_connection(new_session, connection);
return new_session;
}
GConn *
wmud_session_get_connection(wMUDSession *session)
{
GConn *connection = NULL;
GValue value = {0};
g_value_init(&value, G_TYPE_POINTER);
wmud_session_get_property(G_OBJECT(session), PROP_CONNECTION, &value, NULL);
connection = g_value_get_pointer(&value);
g_value_unset(&value);
return connection;
}
/**
* wmud_session_set_connection:
* @session: the object which should receive the new connection
* @connection: the connection this session should be bound to. This object is g_unref()'d when the Session object is disposed
*/
void
wmud_session_set_connection(wMUDSession *session, GConn *connection)
{
GValue value = {0};
g_value_init(&value, G_TYPE_POINTER);
g_value_set_pointer(&value, (gpointer)connection);
wmud_session_set_property(G_OBJECT(session), PROP_CONNECTION, &value, NULL);
g_value_unset(&value);
}
/**
* wmud_session_has_connection:
* @session: the object which should be inspected
* @connection: the connection we are looking for
*
* Checks if the given #wMUDSession has the given #GConn connection
*
* Returns: %TRUE, if the connection is owned by this session, %FALSE otherwise
*/
gboolean
wmud_session_has_connection(wMUDSession *session, GConn *connection)
{
if (session->priv->connection == connection)
return TRUE;
return FALSE;
}
wMUDSessionType
wmud_session_get_session_type(wMUDSession *session)
{
GValue value = {0};
g_value_init(&value, WMUD_TYPE_SESSION_TYPE);
wmud_session_get_property(G_OBJECT(session), PROP_TYPE, &value, NULL);
return g_value_get_enum(&value);
}
void
wmud_session_set_session_type(wMUDSession *session, wMUDSessionType type)
{
GValue value = {0, };
g_value_init(&value, WMUD_TYPE_SESSION_TYPE);
g_value_set_enum(&value, type);
wmud_session_set_property(G_OBJECT(session), PROP_TYPE, &value, NULL);
}
wMUDSession *
wmud_session_ref(wMUDSession *session)
{
return WMUD_SESSION(g_object_ref(G_OBJECT(session)));
}
void
wmud_session_unref(wMUDSession *session)
{
g_object_unref(G_OBJECT(session));
}

View File

@ -1,53 +0,0 @@
#ifndef __WMUD_SESSION_H__
#define __WMUD_SESSION_H__
#include <glib.h>
#include <glib-object.h>
#include <gnet.h>
#define WMUD_TYPE_SESSION wmud_session_get_type()
#define WMUD_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WMUD_TYPE_SESSION, wMUDSession))
#define WMUD_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WMUD_TYPE_SESSION))
#define WMUD_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WMUD_TYPE_SESSION, wMUDSessionClass))
#define WMUD_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WMUD_TYPE_SESSION))
#define WMUD_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WMUD_TYPE_SESSION, wMUDSessionClass))
typedef enum
{
WMUD_SESSION_TYPE_UNKNOWN,
WMUD_SESSION_TYPE_TELNET,
WMUD_SESSION_TYPE_IRC,
WMUD_SESSION_TYPE_HTTP
} wMUDSessionType;
typedef struct _wMUDSession wMUDSession;
typedef struct _wMUDSessionClass wMUDSessionClass;
typedef struct _wMUDSessionPrivate wMUDSessionPrivate;
struct _wMUDSession
{
GObject parent_object;
wMUDSessionPrivate *priv;
};
struct _wMUDSessionClass
{
GObjectClass parent_class;
};
GType wmud_session_get_type(void);
wMUDSession *wmud_session_new(void);
wMUDSession *wmud_session_new_with_connection(GConn *connection);
gboolean wmud_session_has_connection(wMUDSession *session, GConn *connection);
wMUDSession *wmud_session_ref(wMUDSession *session);
void wmud_session_unref(wMUDSession *session);
GConn *wmud_session_get_connection(wMUDSession *session);
void wmud_session_set_connection(wMUDSession *session, GConn *connection);
wMUDSessionType wmud_session_get_session_type(wMUDSession *session);
void wmud_session_set_session_type(wMUDSession *session, wMUDSessionType type);
#endif /* __WMUD_SESSION_H__ */

View File

@ -1,11 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: wMUDSession
Description: Library to handle wMUD sessions
Requires: glib-2.0 gobject-2.0
Version: PACKAGE_VERSION
Libs: -L${libdir} -lwmud-session-1.0
Cflags: -I${includedir}/wmud-session -I${libdir}/wmud-session/include

View File

@ -1,6 +0,0 @@
LIBWMUD_STATE_SQLITE3_VERSION=1:0:0
lib_LTLIBRARIES = libwmud-state-sqlite3-1.0.la
libwmud_state_sqlite3_1_0_la_SOURCES = wmud-state-sqlite3.c
libwmud_state_sqlite3_1_0_la_CFLAGS = $(CFLAGS) $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(GNET_CFLAGS) -Wall -I../src -I../libwmud-session
libwmud_state_sqlite3_1_0_la_LIBADD = $(LIBS) $(GLIB_LIBS) $(GOBJECT_LIBS) $(GNET_LIBS)
libwmud_state_sqlite3_1_0_la_LDFLAGS = -version-info $(LIBWMUD_STATE_SQLITE3_VERSION)

View File

@ -1,91 +0,0 @@
#include <glib.h>
#include <sqlite3.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "module.h"
static gchar *state_file = NULL;
static sqlite3 *statesave_connection = NULL;
gboolean
wmud_statesave_sqlite3_is_statesave(void)
{
return TRUE;
}
static gint
_wmud_statesave_sqlite3_find_config_group(gconstpointer list_data, gconstpointer lookup_data)
{
wMUDConfigurationGroup *group = (wMUDConfigurationGroup *)list_data;
gchar *name_to_find = (gchar *)lookup_data;
Context return g_utf8_collate(group->name, name_to_find);
}
static void
_wmud_statesave_sqlite3_parse_config(gpointer data, gpointer userdata)
{
wMUDConfigurationValue *parameter = (wMUDConfigurationValue *)data;
if (g_utf8_collate("state file", parameter->key) == 0)
{
state_file = g_strdup(parameter->value);
}
}
gboolean
wmud_statesave_sqlite3_load(wMUDConfiguration *config)
{
GSList *statesave_params;
wMUDConfigurationGroup *config_group;
wmud_log_debug("Initializing SQLite3 state saving module...");
if (!sqlite3_threadsafe())
{
wmud_log_error("SQLite3 library is not compiled in a thread-safe manner.");
return FALSE;
}
Context statesave_params = g_slist_find_custom(config->statesave_parameters, "sqlite3", _wmud_statesave_sqlite3_find_config_group);
if (statesave_params == NULL)
{
wmud_log_error("Cannot find group [statesave sqlite3] in configfile!");
return FALSE;
}
config_group = (wMUDConfigurationGroup *)(statesave_params->data);
g_slist_foreach(config_group->datalist, _wmud_statesave_sqlite3_parse_config, NULL);
if (state_file == NULL)
{
wmud_log_error("Cannot find state file parameter in configuration file (should be under group [statesave sqlite3]");
return FALSE;
}
wmud_log_debug("Will save state into SQLite3 file %s", state_file);
switch (sqlite3_open(state_file, &statesave_connection))
{
case SQLITE_OK:
wmud_log_info("State file opened successfully");
break;
default:
wmud_log_error("Unprocessed return value from sqlite3_open()!");
return FALSE;
break;
}
return TRUE;
}
void
wmud_statesave_sqlite3_unload(void)
{
sqlite3_close(statesave_connection);
}

View File

@ -1,4 +0,0 @@
lib_LTLIBRARIES = libwmud-world-1.0.la
libwmud_world_1_0_la_SOURCES = wmud-world.c
libwmud_world_1_0_la_CFLAGS = $(CFLAGS) $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(GNET_CFLAGS) -Wall
libwmud_world_1_0_la_LIBADD = $(LIBS) $(GLIB_LIBS) $(GOBJECT_LIBS) $(GNET_LIBS)

View File

@ -1,104 +0,0 @@
#include "wmud-world.h"
#define WMUD_WORLD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WMUD_TYPE_WORLD, wMUDWorldPrivate))
struct _wMUDWorldPrivate
{
gchar *name;
};
enum
{
PROP_0,
PROP_NAME
};
G_DEFINE_TYPE(wMUDWorld, wmud_world, G_TYPE_OBJECT);
static void
wmud_world_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
wMUDWorld *self = WMUD_WORLD(object);
switch (property_id)
{
case PROP_NAME:
g_free(self->priv->name);
self->priv->name = g_value_dup_string(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void
wmud_world_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
wMUDWorld *self = WMUD_WORLD(object);
switch (property_id)
{
case PROP_NAME:
g_value_set_string(value, self->priv->name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void
wmud_world_dispose(GObject *object)
{
G_OBJECT_CLASS(wmud_world_parent_class)->dispose(object);
}
static void
wmud_world_finalize(GObject *object)
{
wMUDWorld *self = WMUD_WORLD(object);
if (self->priv->name)
{
g_free(self->priv->name);
}
G_OBJECT_CLASS(wmud_world_parent_class)->finalize(object);
}
static void
wmud_world_class_init(wMUDWorldClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GParamSpec *wmud_world_param_spec;
gobject_class->set_property = wmud_world_set_property;
gobject_class->get_property = wmud_world_get_property;
gobject_class->dispose = wmud_world_dispose;
gobject_class->finalize = wmud_world_finalize;
g_type_class_add_private(klass, sizeof(wMUDWorldPrivate));
wmud_world_param_spec = g_param_spec_string("name", "World name", "Set the name of the world", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property(gobject_class, PROP_NAME, wmud_world_param_spec);
}
static void
wmud_world_init(wMUDWorld *self)
{
wMUDWorldPrivate *priv;
self->priv = priv = WMUD_WORLD_GET_PRIVATE(self);
priv->name = NULL;
}
wMUDWorld *
wmud_world_new(void)
{
wMUDWorld *new_world = g_object_new(WMUD_TYPE_WORLD, NULL);
return new_world;
}

View File

@ -1,34 +0,0 @@
#ifndef __WMUD_WORLD_H__
#define __WMUD_WORLD_H__
#include <glib-object.h>
#define WMUD_TYPE_WORLD wmud_world_get_type()
#define WMUD_WORLD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WMUD_TYPE_WORLD, wMUDWorld))
#define WMUD_IS_WORLD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WMUD_TYPE_WORLD))
#define WMUD_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WMUD_TYPE_WORLD, wMUDWorldClass))
#define WMUD_IS_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WMUD_TYPE_WORLD))
#define WMUD_WORLD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WMUD_TYPE_WORLD, wMUDWorldClass))
typedef struct _wMUDWorld wMUDWorld;
typedef struct _wMUDWorldClass wMUDWorldClass;
typedef struct _wMUDWorldPrivate wMUDWorldPrivate;
struct _wMUDWorld
{
GObject parent_object;
wMUDWorldPrivate *priv;
};
struct _wMUDWorldClass
{
GObjectClass parent_class;
};
GType wmud_world_get_type(void);
wMUDWorld *wmud_world_new(void);
#endif /* __WMUD_WORLD_H__ */

View File

@ -0,0 +1,75 @@
#!/bin/bash -x
#
# Generated - do not edit!
#
# Macros
TOP=`pwd`
CND_PLATFORM=GNU-Linux-x86
CND_CONF=Default
CND_DISTDIR=dist
CND_BUILDDIR=build
NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
TMPDIRNAME=tmp-packaging
OUTPUT_PATH=MissingOutputInProject
OUTPUT_BASENAME=MissingOutputInProject
PACKAGE_TOP_DIR=wmud/
# Functions
function checkReturnCode
{
rc=$?
if [ $rc != 0 ]
then
exit $rc
fi
}
function makeDirectory
# $1 directory path
# $2 permission (optional)
{
mkdir -p "$1"
checkReturnCode
if [ "$2" != "" ]
then
chmod $2 "$1"
checkReturnCode
fi
}
function copyFileToTmpDir
# $1 from-file path
# $2 to-file path
# $3 permission
{
cp "$1" "$2"
checkReturnCode
if [ "$3" != "" ]
then
chmod $3 "$2"
checkReturnCode
fi
}
# Setup
cd "${TOP}"
mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
rm -rf ${NBTMPDIR}
mkdir -p ${NBTMPDIR}
# Copy files and create directories and links
cd "${TOP}"
makeDirectory "${NBTMPDIR}/wmud"
copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
# Generate tar file
cd "${TOP}"
rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/wmud.tar
cd ${NBTMPDIR}
tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/wmud.tar *
checkReturnCode
# Cleanup
cd "${TOP}"
rm -rf ${NBTMPDIR}

View File

@ -0,0 +1,402 @@
<?xml version="1.0" encoding="UTF-8"?>
<configurationDescriptor version="84">
<logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
<df name="wmud" root=".">
<df name="autom4te.cache">
</df>
<df name="conf">
</df>
<df name="data">
<df name="texts">
</df>
</df>
<df name="docs">
<df name="reference">
<df name="wmud">
<df name="html">
</df>
<df name="xml">
</df>
</df>
</df>
</df>
<df name="iminiru">
</df>
<df name="libgiosmtp">
<df name=".libs">
</df>
<in>gioextension.c</in>
<in>giomodule.c</in>
</df>
<df name="m4">
</df>
<df name="old-codebase">
<df name="bin">
</df>
<df name="cnf">
<in>acconfig.h</in>
</df>
<df name="doc">
<df name="OLD-DOCS">
</df>
<df name="sources">
</df>
</df>
<df name="lib">
<df name="etc">
</df>
<df name="house">
</df>
<df name="misc">
</df>
<df name="plralias">
<df name="A-E">
</df>
<df name="F-J">
</df>
<df name="K-O">
</df>
<df name="P-T">
</df>
<df name="U-Z">
</df>
<df name="ZZZ">
</df>
</df>
<df name="plrobjs">
<df name="A-E">
</df>
<df name="F-J">
</df>
<df name="K-O">
</df>
<df name="P-T">
</df>
<df name="U-Z">
</df>
<df name="ZZZ">
</df>
</df>
<df name="text">
<df name="help">
</df>
</df>
<df name="world">
<df name="mob">
</df>
<df name="obj">
</df>
<df name="shp">
</df>
<df name="wld">
</df>
<df name="zon">
</df>
</df>
</df>
<df name="log">
</df>
<df name="src">
<df name="doc">
</df>
<df name="util">
<in>autowiz.c</in>
<in>delobjs.c</in>
<in>listrent.c</in>
<in>mudpasswd.c</in>
<in>play2to3.c</in>
<in>purgeplay.c</in>
<in>shopconv.c</in>
<in>showplay.c</in>
<in>sign.c</in>
<in>split.c</in>
<in>wld2html.c</in>
</df>
<in>act.comm.c</in>
<in>act.informative.c</in>
<in>act.item.c</in>
<in>act.movement.c</in>
<in>act.offensive.c</in>
<in>act.other.c</in>
<in>act.social.c</in>
<in>act.wizard.c</in>
<in>alias.c</in>
<in>ban.c</in>
<in>boards.c</in>
<in>boards.h</in>
<in>bsd-snprintf.c</in>
<in>bsd-snprintf.h</in>
<in>castle.c</in>
<in>class.c</in>
<in>comm.c</in>
<in>comm.h</in>
<in>config.c</in>
<in>constants.c</in>
<in>constants.h</in>
<in>db.c</in>
<in>db.h</in>
<in>fight.c</in>
<in>graph.c</in>
<in>handler.c</in>
<in>handler.h</in>
<in>house.c</in>
<in>house.h</in>
<in>interpreter.c</in>
<in>interpreter.h</in>
<in>limits.c</in>
<in>magic.c</in>
<in>mail.c</in>
<in>mail.h</in>
<in>mobact.c</in>
<in>modify.c</in>
<in>objsave.c</in>
<in>olc.c</in>
<in>olc.h</in>
<in>races.c</in>
<in>random.c</in>
<in>screen.h</in>
<in>shop.c</in>
<in>shop.h</in>
<in>spec_assign.c</in>
<in>spec_procs.c</in>
<in>spell_parser.c</in>
<in>spells.c</in>
<in>spells.h</in>
<in>structs.h</in>
<in>sysdep.h</in>
<in>telnet.h</in>
<in>utils.c</in>
<in>utils.h</in>
<in>weather.c</in>
</df>
</df>
<df name="sql">
</df>
<df name="wmud">
<df name=".libs">
</df>
<in>configuration.c</in>
<in>configuration.h</in>
<in>db.c</in>
<in>db.h</in>
<in>game-networking.c</in>
<in>game-networking.h</in>
<in>game.c</in>
<in>game.h</in>
<in>interpreter.c</in>
<in>interpreter.h</in>
<in>main.c</in>
<in>main.h</in>
<in>maintenance.c</in>
<in>maintenance.h</in>
<in>menu.c</in>
<in>menu.h</in>
<in>players.c</in>
<in>players.h</in>
<in>texts.c</in>
<in>texts.h</in>
<in>wmud-types.h</in>
<in>world.c</in>
<in>world.h</in>
</df>
<in>config.h</in>
</df>
<logicalFolder name="ExternalFiles"
displayName="Important Files"
projectFiles="false"
kind="IMPORTANT_FILES_FOLDER">
<itemPath>Makefile</itemPath>
<itemPath>configure</itemPath>
</logicalFolder>
</logicalFolder>
<sourceFolderFilter>^(nbproject)$</sourceFolderFilter>
<sourceRootList>
<Elem>.</Elem>
</sourceRootList>
<projectmakefile>Makefile</projectmakefile>
<confs>
<conf name="Default" type="0">
<toolsSet>
<remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
<compilerSet>default</compilerSet>
</toolsSet>
<codeAssistance>
</codeAssistance>
<makefileType>
<makeTool>
<buildCommandWorkingDir>.</buildCommandWorkingDir>
<buildCommand>${MAKE} -f Makefile</buildCommand>
<cleanCommand>${MAKE} -f Makefile clean</cleanCommand>
<executablePath></executablePath>
<cTool>
<incDir>
<pElem>/usr/lib/glib-2.0/include</pElem>
<pElem>/usr/include/glib-2.0</pElem>
<pElem>.</pElem>
</incDir>
<preprocessorList>
<Elem>HAVE_CONFIG_H</Elem>
</preprocessorList>
</cTool>
</makeTool>
</makefileType>
<folder path="wmud/libgiosmtp">
<cTool>
<incDir>
<pElem>libgiosmtp</pElem>
</incDir>
<preprocessorList>
<Elem>PIC</Elem>
</preprocessorList>
</cTool>
</folder>
<folder path="wmud/wmud">
<cTool>
<incDir>
<pElem>wmud</pElem>
</incDir>
<preprocessorList>
<Elem>WMUD_CONFDIR="/usr/local/etc"</Elem>
<Elem>WMUD_STATEDIR="/usr/local/var"</Elem>
</preprocessorList>
</cTool>
</folder>
<item path="old-codebase/cnf/acconfig.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/act.comm.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/act.informative.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/act.item.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/act.movement.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/act.offensive.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/act.other.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/act.social.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/act.wizard.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/alias.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/ban.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/boards.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/boards.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/bsd-snprintf.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/bsd-snprintf.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/castle.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/class.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/comm.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/comm.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/config.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/constants.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/constants.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/db.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/db.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/fight.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/graph.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/handler.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/handler.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/house.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/house.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/interpreter.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/interpreter.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/limits.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/magic.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/mail.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/mail.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/mobact.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/modify.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/objsave.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/olc.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/olc.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/races.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/random.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/screen.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/shop.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/shop.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/spec_assign.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/spec_procs.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/spell_parser.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/spells.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/spells.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/structs.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/sysdep.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/telnet.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/util/autowiz.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/delobjs.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/listrent.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/mudpasswd.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/play2to3.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/purgeplay.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/shopconv.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/showplay.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/sign.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/split.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/util/wld2html.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/utils.c" ex="true" tool="0" flavor2="0">
</item>
<item path="old-codebase/src/utils.h" ex="true" tool="3" flavor2="0">
</item>
<item path="old-codebase/src/weather.c" ex="true" tool="0" flavor2="0">
</item>
</conf>
</confs>
</configurationDescriptor>

23
nbproject/project.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.cnd.makeproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/make-project/1">
<name>wmud</name>
<c-extensions>c</c-extensions>
<cpp-extensions/>
<header-extensions>h</header-extensions>
<sourceEncoding>UTF-8</sourceEncoding>
<make-dep-projects/>
<sourceRootList>
<sourceRootElem>.</sourceRootElem>
</sourceRootList>
<confList>
<confElem>
<name>Default</name>
<type>0</type>
</confElem>
</confList>
</data>
</configuration>
</project>

6
old-codebase/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
config.log
config.cache
config.status
syslog
syslog.CRASH
*.swp

3
old-codebase/TODO Normal file
View File

@ -0,0 +1,3 @@
* Make the Passage work as intended:
o characters should get back here upon logoff/logon
o there must be a way to get out from there

BIN
old-codebase/doc/FAQ.pdf Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
This directory contains documentation on various aspects of the game.
Area builders will be most interested in database.doc, dbsup.doc, defs.doc,
shop.doc, and values.doc. These five files can be mailed automatically
with the "do_mail" script in this directory. do_mail takes the recipient
as its only command-line argument. For example, to mail the documentation
to CircleMUD's author, you'd type "do_mail jelson@cs.jhu.edu".
CONTENTS:
--------
COLOR.DOC - Programmer's manual on how to use color codes
COMM.DOC - The game-to-player communications system, most importantly
the act() procedure
DATABASE.DOC - The format of the most important data files
DBSUP.DOC - Detailed information on each field in database.doc
DEFS.DOC - Important document on what rules should be followed
when creating a part of the world, to avoid complete chaos
HACKER.DOC - Insight into the art & science of programming (courtesy MERC)
HANDLER.DOC - Descriptions of most of the basic 'database handling'
procedures, found in handler.c
LICENSE.DOC - The conditions under which this game is distributed
NOTE: THIS FILE MUST ALWAYS BE PRESENT
RELEASE.DOC - CircleMUD release history
RUNNING.DOC - Directions for compiling, running, and maintaining the game
SHOP.DOC - Describes how to create a shop file
SOCIALS.DOC - Description of the 'social action' system
SPELL_INFO.DOC - Doc on spells, especially how damage is calculated
SPELLS.DOC - Info on the spell/affection system
TIME.DOC - How time is in DikuMud compared to real world
UTILS.DOC - Description of the CircleMUD maintenance utilities
VALUES.DOC - The 4 generic values for items, described in detail
WIZHELP.DOC - Description of all god commands

View File

@ -0,0 +1,9 @@
3/6/95
-----
This directory contains the documentation distributed with CircleMUD 2.2.
This directory and all the files in it will eventually disappear. They
are here now to serve as a reference while I write the new documentation.
--JE

View File

@ -0,0 +1,31 @@
/**************************************************************************
* Copyright (C) 1993 - see 'license.doc' for complete information. *
**************************************************************************/
HOW TO CONVERT YOUR IDEAS INTO REALITY
A CircleMUD Coding Manual
Table of Contents
---------------------------------------------------------------------------
i. Introduction
1. Overview and Coding Basics
1.1. The Way Things Work -- Overview
1.2. CircleMUD's Structures and Lists
1.3. Frequently Used Functions
2. Changing the Code
2.1. Adding Commands
2.2. Adding Socials
2.3. Adding Spells
2.4. Adding Skills
2.5. Writing Special Procedures
2.6. Adding Classes
2.9. Adding Color
3. Changing the World
3.1. Adding Areas
3.2. Removing Areas
3.2. Writing Areas

View File

@ -0,0 +1,134 @@
/**************************************************************************
* Copyright (C) 1993 - see 'license.doc' for complete information. *
**************************************************************************/
USING COLOR IN CIRCLEMUD
"color.doc"
CircleMUD allows you to create colorful messages by using ANSI control
sequences. Each player may select what "level" of color he/she desires
from the four levels "off", "sparse", "normal", and "complete." Each
player can select his/her color level by using the COLOR command from
within the MUD; you as the programmer must decide which messages will be
colored for each of the color levels.
All files in which you wish to use color must have the line:
#include "screen.h"
after all other includes in the beginning of the file.
There are 8 colors available -- "normal", red, green, yellow, blue, magenta,
cyan and white. They are accessible by sending control sequences as part of
another string, for example:
sprintf(buf, "If you're %shappy%s and you know it clap %d of your hands.\n\r",
x, y, num_of_hands);
send_to_char(buf, ch);
In this example, x and y are the "on" and "off" sequences for the color you
want. There are 2 main series of color macros available for you to use
(don't actually use "x" and "y", of course!): the K series and the CC series.
The CC (Conditional Color) series is recommended for most general use.
The name of the actual sequence starts with the name of its series, plus
a 3-letter color code, as follows:
Normal : NRM
Red : RED
Yellow : YEL
Green : GRN
Blue : BLU
Magenta: MAG
Cyan : CYN
White : WHT
For example, white in the K series is KWHT; blue in the CC series
is CCBLU() (arguments defined below).
The K series requires no arguments, and is simply a macro to the ANSI
color code. Therefore, if you use a K-series color code, the color will
ALWAYS be sent, even if the person you're sending it to has color off.
This is very bad -- people who do not have ANSI-compatible terminals
will see garbage characters instead of colors. The K series is mainly
used to print colors to a string if the player's color level will later
be tested manually (for an example, see do_gen_com in act.comm.c).
The recommended series is the CC series (i.e. CCNRM(), CCRED(), etc.)
The CC series macros require two arguments -- a pointer to the character
to whom the string is being sent, and the minimum color level the player
must be set to in order to see the color. Color sent as 'sparse' (C_SPR)
will be seen by people with color set to sparse, normal, or complete;
color sent as 'normal' (C_NRM) will be seen only by people with color
set to normal or complete; color sent as 'complete' (C_CMP) will be seen
only by people with color set to complete.
To illustrate the above, an example is in order:
#include "screen.h" /* include screen.h in all files that you use color in */
ACMD(do_showcolor)
{
char buf[300];
sprintf(buf, "Don't you just love %scolor%s, %scolor%s, %sCOLOR%s!\n\r",
CCBLU(ch, C_CMP), CCNRM(ch, C_CMP),
CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
CCRED(ch, C_SPR), CCNRM(ch, C_SPR));
send_to_char(buf, ch);
}
What does this do? For people with color set to Complete, it prints:
Don't you just love color, color, COLOR!
(blue) (yellow) (red)
People who have color set to Normal will see:
Don't you just love color, color, COLOR!
(yellow) (red)
People who have color set to Sparse will see:
Don't you just love color, color, COLOR!
(red)
People who have color set to Off will see:
Don't you just love color, color, COLOR!
(no color, as you'd expect)
There are several common pitfalls with using the CC series of color macros:
* Do not confuse CCNRM with C_NRM. CCNRM() is a macro to turn the color
back to normal; C_NRM is a color level of "normal".
* Always make sure that every pair of "on" and "off" codes are at the
same color level. For example:
WRONG: sprintf(buf, "%sCOLOR%s\n\r", CCBLU(ch, C_NRM), CCNRM(ch, C_CMP));
This is wrong because if someone has their color level set to Normal,
the CCBLU code will be sent but the CCNRM command will not, causing all
subsequent output to be blue.
WRONG: sprintf(buf, "%sCOLOR%s\n\r", CCBLU(ch, C_CMP), CCNRM(ch, C_NRM));
The above statement is also wrong, although not as bad. In this case,
someone with color set to Normal will (correctly) not get the CCBLU code,
but will then unnecessarily get the CCNRM code. Never send a color code if
you don't have to -- the codes are several bytes long, and cause a noticable
pause at 2400 baud.
* This should go without saying, but don't ever send color at the C_OFF
level.
* Special precautions must be taken when sending a colored string to a
large group of people -- you can't use the color level of "ch" (the
person sending the string) -- each person receiving the string must
get a string appropriately colored for his/her level. In such cases,
it's usually best to set up two strings (one colored and one not),
and test each player's color level individually (see do_gen_com in
act.comm.c for an example).

View File

@ -0,0 +1,146 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
Descriptions of the message-to-character routines of comm.c
void send_to_char(char *messg, struct char_data *ch)
Places messg in the output queue for ch, for later sending.
void send_to_all(char *messg)
Sends a message to all players.
void send_to_except(char *messg, struct char_data *ch)
Sends to all players, except the one pointed to by ch.
void send_to_room(char *messg, int room)
Sends messg to all players in the room.
void send_to_room_except(char *messg, int room, struct char_data *ch)
Send to all in room, with the exception of ch.
The following routine takes the place of all the old perform-routines. It is
to gradually replace these in the old code, and is to be used exclusively in
all additions.
FUNCTION ACT --- Process and send string to characters in a room.
SYNOPSIS
#include "comm.h"
act(string, hide_invisible, ch, obj, vict_obj, type)
char *string; /* the string to send */
int hide_invisible, /* hide the action if vict can't see us? */
type; /* who gets the string */
struct char_data *ch; /* the 'performing' character */
struct obj_data *obj; /* an object */
void *vict_obj; /* an object OR a char OR an ascii string */
DESCRIPTION
This function is used to send a string to one or more characters in a room. The
string may contain certain control characters which are expanded before the
string is sent.
Obj and vict_obj are ignored if no reference is made to them (via CONTROL
CHARACTERS), and if type (see below) is set to TO_ROOM. Thus, null-pointers
may be supplied in this case. Ch should always be defined. If String is a
null-pointer or if string points to a null-character, nothing will be sent.
When the string has been parsed, it is capitalized and a newline is added.
CONTROL CHARACTERS
Each control character is preceded by a '$'.
$n - Write name, short description, or "someone", for ch, depending on
whether ch is a PC, a NPC, or an invisible PC/NPC.
$N - Like $n, except insert the text for vict_obj. NOTE: vict_obj must
point to an object of type struct char_data.
$m - "him", "her", or "it", depending on the gender of ch.
$M - Like $m, for vict_obj. NOTE: vict_obj must be a pointer of type
struct char_data.
$s - "his", "her", or "it", depending on the gender of ch.
$S - Like $s, for vict_obj.
$e - "he", "she", "it", depending on the gender of ch.
$E - Like $e, for vict_obj.
$o - Name or "something" for obj, depending on visibility.
$O - Like $o, for vict_obj. NOTE: vict_obj must be a pointer of type
struct obj_data.
$p - Short description or "something" for obj.
$P - Like $p for vict_obj.
$a - "an" or "a", depending on the first character of obj's name.
$A - Like $a, for vict_obj.
$T - Prints the string pointed to by vict_obj.
$F - Processes the string pointed to by vict_obj with fname() prior to
printing.
$u - Processes the buffer and uppercases the first letter of the previous
word (the word immediately prior to the control code). If there is
no previous word, no action is taken. -- CircleMUD addition (09/18/00)
$U - Processes the buffer and uppercases the first letter of the following
word (the word immediately after to the control code). If there is
no following word, no action is taken. -- CircleMUD addition (09/18/00)
$$ - Print the character '$'.
HIDE_INVISIBLE
If this parameter is nonzero, the action will be hidden to those who are
unable to see ch.
TYPE
This value determines who the string is sent to. It may take one of four
values (the macros are defined in comm.h).
TO_ROOM - Send the string to everybody in the room, except ch.
TO_VICT - Send the string to the character (!) pointed to by vict_obj.
TO_NOTVICT - Send the string to everybody in the room except ch and vict_obj.
TO_CHAR - Send the string to the ch.
EXAMPLES
act("$n smiles happily.", TRUE, ch, 0, 0, TO_ROOM);
(eg: Rainbird smiles happily.)
act("You kiss $M.", FALSE, ch, 0, vict, TO_CHAR);
(eg: You kiss her.)
act("$n gives $p to $N.", TRUE, ch, obj, vict, TO_NOTVICT);
(eg: Dave gives a small sword to the giant.)
act("$n gives you $p.", FALSE, ch, obj, vict, TO_VICT);
(eg: Dave gives you a small sword.)
act("$n puts $p in $s $O.", TRUE, ch, obj1, obj2, TO_ROOM);
(eg: Jones puts a small sword in his sack.)

View File

@ -0,0 +1,389 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
DATABASE DOCUMENTATION
"database.doc"
1. The world file:
==================
This file contains all the rooms, and is loaded once and for all at
boot-time. It follows the this format:
--------------------------------------------
#<virtual number>
<name>~
<description>~
<zone nr>
<room_flags>
<sector_type>
{<direction fields and extra descriptions>}
'S'
#<virtual number>
.
.
.
#99999
$~
Explanation of fields:
----------------------
<Direction fields> follow this format:
D<exit number>
<general description>~
<keyword list>~
<Door flag> <key number> <to_room>
Extra descriptions
------------------
Format:
'E'
<blank separated keyword list>~
<description>~
-----
NOTE:
All the text fields above may be left blank, but the '~' should always be
there.
On the 'virtual' number:
Since the rooms for this game are expected to be written by several people,
we have made it possible to number the rooms freely. Thus, it is possible to,
say, number the rooms in zone 0 from 0 to 1000, the rooms in zone 1 from 1000
to 2000, and so on. Rooms can then be added to the room file without
upsetting the various references to rooms. In the reset command-tables, as well
as in the exits, references to a given room are made via the virtual number
rather than the array index. At boot-time, these references are substituted
with the actual array indices in order to improve the game-time execution
speed. In such places (ie the special routines for mobs/objs/rooms) where
this substitution cannot take place, a function 'real_room', with prototype
int real_room(int virtual_number)
must be used. This functions performs a binary search on the array of rooms,
looking for a room with a given virtual number. If found, the function
returns the index to this room; if not, the game is halted.
Note: Since a binary search is used, the rooms MUST be sorted (in the
room-file) after their virtual number.
-----------------------------------------------------------------------------
2. Objects and monsters
=======================
The objects and mobiles are stored in two separate files. They are loaded
once at boot-time, and then each time their zone is reset, according to the
information stored in the ZONE-FILE.
The world is split up into a number of zones that are updated independently.
The exact nature of these updates are defined by the contents of the ZONE-FILE.
-----------------------------------------------------------------------------
2.1. The Monster file:
======================
The format of this file is as follows:
#<virtual number>
<namelist>~
<short description>~
<long description>~
<description>~
<action flags> <affection flags> <alignment> <Detailed/Simple flag>
IF <Old/Simple flag> != 'S' {
<strength> <intelligence> <wisdom> <dexterity> <constitution>
<hit low> <hit high> <armour> <mana> <movement> <gold> <exp>
<position> <default> <sex> <class> <level> <age> <weight> <height>
<condition 0> <condition 1> <condition 2>
<savingthrow 0> <savingthrow 1> <savingthrow 2> <savingthrow 3> <savingthrow 4>
} else { /* Simple monsters flag is 'S' */
<Level> <Thac0> <AC> <Hit Points (format is xdy+z)> <Damage (as HP)>
<Gold> <Exp>
<position> <default position> <sex>
}
#<virtual number>
.
.
.
#<virtual number>
$~
-----------------------------------------------------------------------------
2.3. The object file:
=====================
The format is as follows:
#<virtual number>
<namelist>~
<short description>~
<long description>~
<action description>~
<type flag> <extra flag> <wear flag>
<value 0> <value 1> <value 2> <value 3>
<weight> <value> <cost/day>
'E'
<keyword-list>~
<extra description>~
'E'
<keyword-list>~
<extra description>~
.
.
.
'E'
<keyword-list>~
<extra description>~
'A'
<location> <modifier>
.
.
'A'
<location> <modifier>
#<virtual number>
.
.
.
#<virtual number>
'$~'
-----------------------------------------------------------------------------
2.3. The zone-file
==================
The zone-file contains the following information for each zone:
a) The top room-number of the zone. A room belongs to a zone X if:
zone[X-1].top < virtual_room_number <= zone[X]
for X > 0. Rooms belong to zone 0 if their number is between 0 and the
top of zone 0.
b) The LIFESPAN of the zone. When the age of the zone (measured in minutes
after last reset) reaches this number, the zone is queued for reset. The
zone is then reset as soon as possible (more or less), depending on the
value of the RESET_MODE-variable.
c) The RESET_MODE. This may take on of three values:
0: Don't reset the zone at all. In this case, the age of the zone is never
updated, and it will never be queued for reset. Thus, the value of the
lifespan-field is effectively ignored.
1: Reset the zone as soon as it is deserted, ie as soon as there are no
players located within the zone.
2: Reset the zone no matter who or what is in it.
d) The COMMAND TABLE. This is a series of commands to execute at reset. The
table is terminated by the pseudo-command 'S', and thus follows the
following format:
<command>
<command>
.
.
.
<command>
'S'
Each command consists of a letter, identifying the command-type, followed
by three or four arguments. The first argument, common to all the commands,
is called the 'if-flag'. If it is true (nonzero), the command is executed
ONLY if the preceding command was executed. If it is false (zero), the
command is executed anyway.
The commands:
M (load a mobile):
Format: 'M' <if-flag> <mobile nr> <max existing> <room nr>
mobile nr and room nr should be self-explanatory. The 'max
existing' parameter specifies the maximum permissible number of
existing units. In other words: If you only want one manifestation
of a given monster, you just specify the number '1'. If the max
number is about to be exceeded, the command won't be executed.
O (load an object):
Format: 'O' <if-flag> <object nr> <max existing> <room nr>
Load an object and place it in a room. (NOT -1)
G (give object to mobile):
Format: 'G' <if-flag> <object nr> <max existing>
Loads an object, and gives it to the last monster referenced (ie. by the
M-command).
Of course, this command doesn't make sense if a new mobile+object
pair has not just been created, which is where the if-flag comes
in handy. :)
E (object to equipment list of mobile)
Format: 'E' <if-flag> <object nr> <max existing> <equipment position>
Loads object and places it in the Equipment list of the last monster
referenced.
Note that it is NOT necessary to precede this command with a 'G' command.
Equipment position is one of:
WEAR_LIGHT 0
WEAR_FINGER_R 1
WEAR_FINGER_L 2
WEAR_NECK_1 3
WEAR_NECK_2 4
WEAR_BODY 5
WEAR_HEAD 6
WEAR_LEGS 7
WEAR_FEET 8
WEAR_HANDS 9
WEAR_ARMS 10
WEAR_SHIELD 11
WEAR_ABOUT 12
WEAR_WAISTE 13
WEAR_WRIST_R 14
WEAR_WRIST_L 15
WIELD 16
HOLD 17
P (put object in object):
Format: 'P' <if-flag> <object_nr1> <max existing> <object nr2>
Loads object1 and places it in object2.
D (set state of door)
Format: 'D' <if-flag> <room nr> <exit nr> <state>
State being one of:
0: Open.
1: Closed.
2: Closed and locked.
R (remove object from room)
Format: 'R' <if-flag> <room_nr> <object_nr>
More commands will probably be needed, and will be added as required.
Format of the zone-file:
---------------------------------------
#<arbitrary number (ignored)>
<name>~
<top of zone>
<lifespan>
<reset mode>
<command>
<command>
.
.
.
<command>
'S'
#<arbitrary number>
.
.
.
#<arbitrary number>
$~
2.2. The monster file:
----------------------
The format of this file is as follows:
----------------------------------------------
#<virtual number>
<namelist>~
<short description>~
<long description>~
<description>~
<action flags> <affection flags> <Detailed/Simple flag>
IF <Old/Simple flag> != 'S' {
<strength> <intelligence> <wisdom> <dexterity> <constitution>
<hit low> <hit high> <armour> <mana> <movement> <gold> <exp>
<position> <default> <sex> <class> <level> <age> <weight> <height>
<condition 0> <condition 1> <condition 2>
<savingthrow 0> <savingthrow 1> <savingthrow 2> <savingthrow 3> <savingthrow 4>
} else { /* Simple monsters flag should be 'D' */
<Level> <Thac0> <AC> <Hit Points (format is xdy+z)> <Damage (as HP)>
<Gold> <Exp>
<position> <default position> <sex>
}
#<virtual number>
.
.
.
#<virtual number>
$~
----------------------------------------------
On the skill fields:
Format:
--------------
S<skill number>
<learned> <affected by> <duration> <recognize>
--------------
On the virtual numbers:
This number may be considered the 'label' of the mobile, for use in eg. the
zonefile (see also the text about the roomfile format). When the mobile is to
be referenced from within the code itself, the function real_mobile
(real_object for objects) can be used to find indices to the file-index tables
(this is only of use when writing special routines). These functions are
automatically called from read_object/read_mobile, depending on their 'type'
parameter (see db.doc).

View File

@ -0,0 +1,600 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
DATABASE SUPPLEMENTAL DOCUMENTATION
"dbsup.doc"
World File field description:
=============================
Main structure notes:
---------------------
#<virtual number> is:
A number for the given room. No two rooms may have the same number.
The <virtual number> must always increase when browsing down the
world file (but increments can be larger than one).
<name>~<NL>:
This name is the "title" of the room. This title is also used in special
procedures like:
"exits"
"brief mode"
<description>~<NL>:
This is the general description of the room.
<zone nr> is:
The number of the zone in which this room is located. This number is used
for resetting zones and monster zone movement. See the zone file.
<room_flags> are:
A bitvector consisting of the room conditions as:
DARK 1 Light must be used to see anything.
DEATH 2 A player 'dies' (no xp lost) when entering.
It is a good idea to:
*Have these rooms light, because then EXITS will show
the room title, for example "In Boiling Water".
*Make exits to all rooms from which one can enter the
death_room, then the "death cry" will be heard by
other members of the group considering following...
NO_MOB 4 No monsters may walk around in here
INDOORS 8 This is inside (a house,cave or dungeon for example)
LAWFULL 16 ???
NEUTRAL 32 ???
CHAOTIC 64 ???
NO_MAGIC 128 Not implemented.
TUNNEL 256 ???
PRIVATE 512 It is impossible to teleport to this room if it
already contains two characters. The 'teleport'
spell will never teleport a player into this room.
GODROOM 1024 Super-private room: Immortals can not 'goto' this room.
BFS_MARK 2048 RESERVED FOR INTERNAL USE -- do not use.
??? means that the flag isn't used yet (and you Shouldn't use it either!)
<sector_type> is:
This determines how many movement points are used when moving through
a location of the type - use one of the numbers 0..7 (they are NOT the
movement-points used - merely indexes to a lookup-table):
SECT_INSIDE 0 Uses as if walking indoors
SECT_CITY 1 Uses as if walking in a city
SECT_FIELD 2 Uses as if walking in a field
SECT_FOREST 3 Uses as if walking in a forest
SECT_HILLS 4 Uses as if walking in hills
SECT_MOUNTAIN 5 Uses as if climbing in mountains
SECT_WATER_SWIM 6 Uses as if swimming
SECT_WATER_NOSWIM 7 Impossible to swim water - requires a boat
Direction fields:
-----------------
<Exit number> is one of:
0 = North
1 = East
2 = South
3 = West
4 = Up
5 = Down
<general description><NL>~<NL>:
What a player will see if he types 'look <direction>'
<keyword list>~<NL>:
used for commands like 'open', 'close', etc. should be 'door' for ordinary
doors. Example: An exit from a given room leads through a cupboard. The
keyword list for this exit might look like this:
"cupboard door~"
<Door flag> [NL]:
If <Door Flag> is 1, the exit can be locked/unlocked/opened/closed/picked.
If it is 2, the exit can only be locked/unlocked/opened/closed.
If it is 0, these commands won't work. (The exit can still be closed at
reset, however; maybe to be opened by some special routine, like a concealed
handle).
The state of the doors after reset may be controlled by a command in the
reset-command table (see the zone file). The initial state of a door is
open.
<Key Number> [NL]:
The number of the object which can unlock/lock the door (in the direction
given). If a player carries/holds this object, he can lock/unlock.
<Key Number> == -1 means no keyhole. If <Door flag> is 0, the value of this
field is ignored.
<to_room> <NL>:
The virtual number of the room to which the exit leads. If this number is
-1 (NOWHERE), the exit doesn't lead anywhere. This might be useful for
adding an exit-description in a direction which doesn't actually lead
anywhere.
** Note about doors. You must make a door in both rooms that the door
is set between.
Extra descriptions:
-------------------
<blank separated keyword list>~<NL> is:
A list of the keywords that will allow the extra description to be
displayed. The keywords must must be seperated by blanks.
<description><NL>~<NL>:
The description that is show when a player types 'look at <keyword>'
and keyword matches one of the above.
Example of a room entry is the database:
----------------------------------------
#100
The Lego temple~
You stand in a tiny, red temple built entirely from Lego bricks. It is,
sadly, not a very interesting place, and perhaps you should leave through
the portal which leads south to a sunny garden.
~
1 12 0
D2
You see the grand portal of the Lego church. Beyond is an inviting garden.
~
portal grand~
1 2 107
E
portal~
The portal is high and arched, built out of lego bricks of the finest quality.
~
E
brick~
The bricks are all in bright different colours.
~
S
#101
.
.
.
Facts about this room is:
Room number 100
Zone number 1
Room Flags (8+4=12) INDOORS and NO_MOB
Sector Type Inside (movement loss calc only)
One exit (D2) to the south with 'look south' description
Door Flag 1
Key no. 2
Leads to room 107
Extra description for the portal and bricks.
-------------------------------------------------------------------------
Monster fields description:
===========================
#<virtual number><NL> is:
The monsters virtual number. Rules are same as for room virtual numbers.
<namelist><!NL>~<NL>
The space-separated name alias list.
<short description><!NL>~<NL>
This string will be displayed when the monster take action, for example
if it is "The Beastly Fido", and fido leaves south the message will be
"The Beastly Fido leaves south."
<long description><NL>~<NL>
This description is displayed when the monster is in it's "default"
position. When not in the default position, a message like:
"<short description> is sleeping here." could be displayed.
<description><NL>~<NL>
This will be displayed when a player looks at the monster.
<action flags>[NL]
This bitvector define how the monster behave. The bits mean:
ACT_SPEC 1 This means that there is a special programmed C
procedure connected to the monster. When this bit
is set the monster "function pointer" must be
assigned in the "spec_assign.c" file.
ACT_SENTINEL 2 When this bit is set the monster will NOT
move around in the world.
ACT_SCAVENGER 4 When this bit is set, monsters will pick up stuff
lying on the ground. It will pick up the most
expensive items first.
ACT_ISNPC 8 RESERVED FOR INTERNAL USE
ACT_NICE_THIEF 16 When this bit is set, a monster will not attack
a thief which has been caught in the act of
stealing from this monster.
ACT_AGGRESSIVE 32 When this bit is set, the monster will attack and
attempt to kill any player it can get it's claws on.
It will not attack players it can't see (for example
dark rooms or when player is invisible, unless the
monster can detect invisibility)
ACT_STAY_ZONE 64 When this bit is set, the monster will never move
into another zone of the world (this is good for
keeping your monsters in your own adventure).
ACT_WIMPY 128 When this bit is set, the monster will flee when it's
getting percentwise low on hitpoints.
If the monster is both aggressive and wimpy, then it
will only attack players that are NOT awake! (ie. also
suffering players).
ACT_AGGRESSIVE_EVIL
256 When this bit is set, the monster will attack players
with evil alignment.
ACT_AGGRESSIVE_GOOD
512 When this bit is set, the monster will attack players
with good alignment.
ACT_AGGRESSIVE_NEUTRAL
1024 When this bit is set, the monster will attack players
who are neutrally aligned.
ACT_MEMORY 2056 When this bit is set, the monster will remember
players who attack it, and attack the player back
if it sees him or her again.
<affection flags>[NL]
This is a bitvector that indicates what the monster is affected by.
Puff could for example be able to "detect invisible" or maybe
"sanctuary" (1/2 damage). A lot of these bits are meant for players
only (in a context with a spell), and should NOT be used when indicated.
The bits are:
AFF_BLIND 1 RESERVED PLAYERS
AFF_INVISIBLE 2 The monster is invisible
AFF_DETECT_EVIL 4 RESERVED PLAYERS
AFF_DETECT_INVISIBLE 8 The monster can see invisible players
(Especially good for aggressive npc's)
AFF_DETECT_MAGIC 16 RESERVED PLAYERS
AFF_SENCE_LIFE 32 RESERVED PLAYERS
AFF_HOLD 64 ??? DO NOT USE
AFF_SANCTUARY 128 The monster has sanctuary (1/2 damage)
AFF_GROUP 256 RESERVED PLAYERS
AFF_CURSE 1024 ??? DO NOT USE
AFF_FLAMING 2048 ??? DO NOT USE
AFF_POISON 4096 RESERVED PLAYERS
AFF_PROTECT_EVIL 8192 ??? DO NOT USE
AFF_PARALYSIS 16384 ??? DO NOT USE
AFF_MORDEN_SWORD 32768 ??? DO NOT USE
AFF_FLAMING_SWORD 65536 ??? DO NOT USE
AFF_SLEEP 131072 RESERVED PLAYERS
AFF_DODGE 262144 ??? DO NOT USE
AFF_SNEAK 524288 The message "The xxx leaves direction" will
not be displayed when the monster moves
out/in to a room.
AFF_HIDE 1048576 The monster will be hidden, and can only
be detected by a "sense life" spell
AFF_FEAR 2097152 ??? DO NOT USE
AFF_CHARM 4194304 The monster will act as charmed when a
"follow <player>" is entered. Note that
players can't force monsters to follow
them.
AFF_FOLLOW 8388608 RESERVED PLAYERS
AFF_WIMPY 16777216 RESERVED PLAYERS
AFF_INFRARED 33554432 Allows monsters to see in the dark.
<Alignment Flag>[NL]
This is the monsters alignment, read as:
+1000 .. +350 Good Alignment
+349 .. -349 Neutral Alignment
-350 ..-1000 Evil Alignment
<Detailed/Simple flag><NL>
This flag must be entered as a uppercase "S". S indicates that "Simple"
monster data follow. Anything but an S will be interpreted as if
"Detailed" monster data is to follow. We will NOT describe detailed
monsters as they are VERY detailed.
<Level>
This is the level of the monster. See "defs.doc" for guidelines when
setting the level.
<THAC0>
The monsters THAC0.
See the file "defs.doc" for an explanation of armour vs. THAC0, and
guidelines for THAC0.
THAC0 is an abbrevation for "To Hit Armour Class Zero".
<AC>
The monsters armour class. See "defs.doc" for guidelines regarding
armour.
<Hit Points (format is xdy+z)>
This defines the number of hitpoints a given monster has. If this is
entered into the file:
... ... 3d8+10 ...
the monster will have 10 hitpoints plus the result of rolling 3 dice
with 8 side, and adding their sum. All the numbers (even zero), the
plus sign, and the letter 'd' MUST be entered!!! Example:
..... 1d6+0 ....
<Damage (as HP)><NL>
This is the damage a monster will cause when it is using NO weapons
(the Bare hand damage). The format is exacly like the one described
for hit points. A thing to note about damage:
The number after the plus sign, is the "strength bonus". This bonus
will apply to any weapons used, and bare hands too. Example:
..... 1d4+10
This monster will damage between 11 and 14 hitpoints each round. If the
monster picks up and wields a tiny stick which give 1d2 damage, then the
monster will now damage by : 1d2 + 10 points.
<Gold>
The amout of gold carried by the monster.
<Exp><NL>
The experience this monster has. Follow guidelines in "defs.doc".
<position>
This defines the monster's position when loaded into the game.
A position is one of:
POSITION_DEAD 0 DO NOT USE
POSITION_MORTALLYW 1 DO NOT USE
POSITION_INCAP 2 DO NOT USE
POSITION_STUNNED 3 DO NOT USE
POSITION_SLEEPING 4 The monster is sleeping.
POSITION_RESTING 5 The monster is resting.
POSITION_SITTING 6 The monster is sitting.
POSITION_FIGHTING 7 DO NOT USE.
POSITION_STANDING 8 The monster is standing.
<default position>
This is the position into which the monster will return after
a fight. This position also defines when the <long description>
is displayed - see above.
<sex><NL>
This is the monsters sex, on of:
SEX_NEUTRAL 0
SEX_MALE 1
SEX_FEMALE 2
No further explanation is needed (hopefully).
Object fields description:
==========================
#<virtual number><NL>
See rules for rooms above.
<namelist>~<NL>:
Same as for monsters above.
<short description>~<NL>
This string will be displayed when the object is used. For example
if it is "a rubber raft", and a player drops it, then a message like:
"Monthy drops a rubber raft."
could be displayed.
<long description>~<NL>
This description is displayed when the object is lying on the ground.
For example, if it is "A furled umbrella lies here.~" then this message
is displayed when the umbrella is lying on the ground.
<action description>~<NL>
Do not use.
<type flag>[NL]
This defines what kind of item you are defining, it can be one of:
ITEM_LIGHT 1 Item is a light.
ITEM_SCROLL 2 Not yet implemented
ITEM_WAND 3 Not yet implemented
ITEM_STAFF 4 Not yet implemented
ITEM_WEAPON 5 Item is a weapon
ITEM_FIREWEAPON 6 Not yet implemented
ITEM_MISSILE 7 Not yet implemented
ITEM_TREASURE 8 Item is a treasure (not money)
ITEM_ARMOR 9 Item is armour.
ITEM_POTION 10 Not yet implemented
ITEM_WORN 11 ???
ITEM_OTHER 12 Item is other
ITEM_TRASH 13 Item is trash
ITEM_TRAP 14 Not yet implemented
ITEM_CONTAINER 15 Item is a container
ITEM_NOTE 16 Item is a note that can be written upon (with a pen)
ITEM_DRINKCON 17 Item is a drink container, for example a bottle or
a barrel or a wine-skin.
A drinkcontainer whit contents must *always* have
two names: 1. The name of the drink, 2. the name
of the container, example:
tea cup~
ITEM_KEY 18 Item is a key
ITEM_FOOD 19 Item is food.
ITEM_MONEY 20 Item is money.
ITEM_PEN 21 Item is a pen.
ITEM_BOAT 22 Item is a boat, which must be carried by a player if
the player wishes to enter NOSWIM room sector types.
ITEM_FOUNTAIN 23 Item is a fountain (characters can drink from it
without having it in inventory).
<extra flag>[NL]
This bitvector defines mostly special effects:
ITEM_GLOW 1 The item is glowing.
ITEM_HUM 2 The item is "humming"/"buzzing".
ITEM_DARK 4 ???
ITEM_LOCK 8 ???
ITEM_EVIL 16 ???
ITEM_INVISIBLE 32 Item is invisible.
ITEM_MAGIC 64 Item will show a magical aura when 'detect magic'
is used.
ITEM_NODROP 128 Item can not be dropped (cursed for example)
ITEM_BLESS 256 Item is blessed.
ITEM_ANTI_GOOD 512 Item not usable by good people
ITEM_ANTI_EVIL 1024 Item not usable by evil people
ITEM_ANTI_NEUTRAL 2048 Item not usable by neutral people
ITEM_NORENT 4096 Players can not rent item
ITEM_NODONATE 8192 Players can not donate item
ITEM_NOINVIS 16384 Player can not make item invisible
<wear flag><NL>
This bitvector defines if items can be taken, and if they can be worn:
ITEM_TAKE 1 Item is takeable.
ITEM_WEAR_FINGER 2 Can be worn on a finger (rings usually)
ITEM_WEAR_NECK 4 Can be worn around neck.
ITEM_WEAR_BODY 8 Can be worn on body.
ITEM_WEAR_HEAD 16 Can be worn on head.
ITEM_WEAR_LEGS 32 Can be worn on legs.
ITEM_WEAR_FEET 64 Can be worn on feet
ITEM_WEAR_HANDS 128 Can be worn on hands (gauntlets, etc)
ITEM_WEAR_ARMS 256 Can be worn on arms.
ITEM_WEAR_SHIELD 512 Can be used as a shield.
ITEM_WEAR_ABOUT 1024 ???
ITEM_WEAR_WAISTE 2048 Can be worn around the waiste (belt)
ITEM_WEAR_WRIST 4096 Can be worn on wrist (bracelets)
ITEM_WIELD 8192 Can be wielded and used as a weapon
ITEM_HOLD 16384 Item can be held in a hand.
ITEM_THROW 32768 Not yet implemented.
Item can be thrown.
<value 0> <value 1> <value 2> <value 3> <NL>
These values are very central. They define the ability of items based on
the items <Item Type>. These values are defined in "values.doc". Note that
if you define an item as being anything but a weapon, you shouldn't set
the 'wield' flag. Many similar obvious rules apply. Example of 4 values:
If the <Item Type> == ITEM_CONTAINER then the values are interpeted as:
Value[0]: Maximum weight the container can contain.
Value[1]: Container flags:
CLOSEABLE - 1
PICKPROOF - 2
CLOSED - 4
LOCKED - 8
Value[2]: The item-number of the object which can open the object.
-1 means no lockability.
Value[3]: Internal use for Corpses that must "rot".
<weight>[NL]
The weight of the item in pounds.
<value>[NL]
The value of the item if sold - see "defs.doc" for ideas on prices.
<cost/day><NL>
The cost to store the item in the reception overnight.
Several extra descriptions or none at all may appear. They follow the room
format exactly.
'E'<NL>
<keyword-list>~<NL>
Exactly as in rooms.
<extra description><NL>~<NL>
Exactly as in rooms.
Between zero and two "affect's" may be set on an item. The affects could
for example modify a characters strength, height etc. The affect only goes
into affect when the character wear, wield or hold the item. The affect
is removed when the character removes the items.
'A'<NL>
When items are worn using wear/wield/grab/hold commands, the 'A' will
allow the items to affect a characters various abilities. Currently
a maximum of 2 'A' are allowed.
<location>[NL]
<location> is one of the below numbers, indicating which ability
will be changed.
APPLY_NONE 0 DO NOT USE.
APPLY_STR 1
APPLY_DEX 2
APPLY_INT 3
APPLY_WIS 4
APPLY_CON 5
APPLY_SEX 6 DO NOT USE.
APPLY_CLASS 7 DO NOT USE.
APPLY_LEVEL 8 DO NOT USE.
APPLY_AGE 9
APPLY_CHAR_WEIGHT 10
APPLY_CHAR_HEIGHT 11
APPLY_MANA 12 DO NOT USE.
APPLY_HIT 13 The MAXIMUM number of hitpoints.
APPLY_MOVE 14 DO NOT USE.
APPLY_GOLD 15 DO NOT USE.
APPLY_EXP 16 DO NOT USE.
APPLY_AC 17
APPLY_ARMOR 17 Same as APPLY_AC
APPLY_HITROLL 18 The bonus/penalty to hit the opponent.
APPLY_DAMROLL 19 The bouns/penalty to damage the opponent.
APPLY_SAVING_PARA 20 These five are saving throws.
APPLY_SAVING_ROD 21
APPLY_SAVING_PETRI 22
APPLY_SAVING_BREATH 23
APPLY_SAVING_SPELL 24 This is the most used saving throw.
<modifier><NL>
The modifier is added to the APPLY_XXX ability of the character
when he uses an item, and is subtracted when he stops using it.
Take great care when using this. This is an example of an item of
improve strength and armour class. Example:
A
1 2
A
17 -2
This adds +2 to the strength, and adds -2 to the AC (thus improving it).
No more 'A'ffects is allowed at this time.
-------------------------------------------------------------------------
Abbrevations:
=============
<contents> indicates that the contents MUST be entered.
[contents] indicates that the contents can OPTIONALLY be entered.
<NL> is Newline (return)
! This indicates "NOT" - for example <!NL> means NO newline (i.e. it is
forbidden to use newline here).

View File

@ -0,0 +1,373 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
DIKUMUD DEFINITIONS AND STANDARDS TO OBEY
"defs.doc"
PC's ~ Players
NPC's ~ Non Players (Monsters)
<name> is used for short names
[x..y] is used to indicate min and max
PC's level [0..20], level [21..24] is special, not useable in gameplay.
NPC's level [0..30]
All PC's and NPC's have following abilities <ABIL>:
Strength <STR>
<PC> [3..18/100]
<NPC> [0..25]
Dexterity <DEX>
<PC> [3..18]
<NPC> [0..25]
Intelligence <INT>
<PC> [3..18]
<NPC> [0..25]
Wisdom <WIS>
<PC> [3..18]
<NPC> [0..25]
Constitution <CON>
<PC> [3..18]
<NPC> [0..25]
All PC's must select one of four classes :
Magic User <MU>
Cleric <CL>
Thief <TH>
Warrior <WA>
Every PC class have a Primary ability (requisite) <PR> :
<MU> <INT>
<CL> <WIS>
<TH> <DEX>
<WA> <STR>
When creating a new <PC>, the <PC>'s <ABIL> are calculated as:
NOTE: This is when being raised from level 0 to level 1!
The size of the <ABIL> dice, is determined by rolling 4 1d6 dice,
and adding the sum of the three largest dice.
The <ABIL> is sorted and assigned a <PC> in descending order,
depending on the class.
<MU> == <INT> <WIS> <DEX> <STR> <CON>
<CL> == <WIS> <INT> <STR> <DEX> <CON>
<TH> == <DEX> <STR> <CON> <INT> <WIS>
<WA> == <STR> <DEX> <CON> <WIS> <INT>
<HP> base is set as 10
<MANA> is allways set to 100
Set level as 1
Set exp as 1
Set theives abilities as basic.
Call the "Advance Level" routines!
Hitpoints:
<HP> ~ Hitpoints
<PC>'s gain in the following range when advancing a level.
<WA> [10..15] Average (12.5)
<TH> [7..13] Average (10.0)
<CL> [5..10] Average (7.5)
<MA> [3..8] Average (5.5)
Advancing a level (<PC>'s only):
<HP> is gained as above
"Spells to learn" is increased by
MIN(1, WIS_APPLY) for <WA> & <TH>
else
MIN(2, WIS_APPLY) for <MU> & <CL>
<NPC> <ABIL> follow <PC>'s <ABIL> up to level 20, with the
exception that NPC may have 0 in abilities. Only unusual
<NPC>'s are assigned abilities.
<PR> may be in 18/00..100 for Warriors ONLY!
============================= MONSTER LOOKUP ==============================
This is general guidelines for creating monsters. This is when creating
"S"impel monsters. Detailed monsters require a great deal of care when
designing, and it is not really worth it.
The idea is that a X level fighter is equal to about a X level monster!
This implies that the <THAC0> ought to decrease by one every level
(starting at '20' on level 1 - minimum is '1' from level 20+). The damage
given by a monster is also important - average weapon damage is at the
moment 1d8.
Level AVERAGE AVERAGE SUGGESTED SUGGESTED SUGGESTED
<HP> <EXP> <THAC0> <AC> <DAM>
0 [001..010] [25] 20 10 1d4+0 (2.5)
1 [011..022] [100] 20 9 1d5+0 (3.0)
2 [023..035] [200] 19 8 1d6+0 (3.5)
3 [036..047] [350] 18 7 1d7+0 (4.0)
4 [048..060] [600] 17 6 1d8+0 (4.5)
5 [061..072] [900] 16 5 2d4+0 (5.0)
6 [073..085] [1500] 15 4 1d8+1 (5.5)
7 [086..097] [2250] 14 4 2d4+1 (6.0)
8 [098..110] [3750] 13 3 2d5+1 (7.0)
9 [111..122] [6000] 12 3 2d5+1 (7.0)
10 [123..135] [9000] 11 2 2d6+1 (8.0)
11 [136..147] [11000] 10 2 2d6+1 (8.0)
12 [148..160] [13000] 9 2 2d7+1 (9.0)
13 [161..172] [16000] 8 2 2d7+1 (9.0)
14 [173..185] [18000] 7 1 2d8+1 (10.0)
15 [186..197] [21000] 6 1 2d8+2 (11.0)
16 [198..210] [24000] 5 1 2d8+2 (11.0)
17 [211..222] [28000] 4 1 3d6+2 (12.5)
18 [223..235] [30000] 3 0 3d6+2 (12.5)
19 [236..247] [35000] 2 0 3d6+3 (13.5)
20 [248..260] [40000] 1 0 3d6+4 (14.5) /* Minor Demons */
Above level 20 is for NPC's only
21 [261..350] [50000] 0 -1 3d7+4 (16.0)
22 [351..400] [60000] 0 -1 3d8+4 (17.5)
23 [401..450] [80000] 0 -2 3d8+4 (17.5) /* Shopkeepers, Important Guards */
24 [451..500] [100000] 0 -3 3d8+4 (17.5) /* Guildmasters */
25 [501..550] [130000] 0 -4 4d6+4 (18.0)
26 [551..600] [155000] 0 -6 4d6+4 (18.0) /* Major Demons/ Devils */
27 [601..650] [200000] 0 -7 4d6+4 (18.0) /* Demi Gods */
28 [651..700] [310000] 0 -8 4d6+5 (19.0) /* Lesser Gods */
29 [701..900] [450000] 0 -9 4d7+5 (21.0) /* Demon Lords/Arch Devils */
30 [901..1000] [600000] 0 -10 4d8+5 (23.0)/* Greater Gods */
------------------------------ GUIDELINES ---------------------------------
MAGICAL ITEMS:
--------------
In DikuMud it is possible to create all kinds of Magic items - but to avoid
chaos (having 1st levels kill 20 level dragons) these rules for Magic must
be obeyed.
It is possible to create almost any item. Items can (example) change the
<STR>, <DEX>, <WIS>, <INT>, <CON>, <HP>, Age, Weight, Height, XP,
etc. None of these changes are directly permanent in effetct, but may be
so indirectly - example:
Iggy found a helmet of Increase Wisdom/Intelligence (some + modifier).
When Iggy wears this helmet - these abilities improve, when he removes
the helmet they return to their original state. Thus no direct change
has happened. BUT if Iggy practices spells (upon which INT and WIS
determines the rate & success) he will learn them much faster than
normal. This was an example of an indirect change.
Good ideas when making Magic Items:
NEVER use large modifiers, exceptional items should modify at most by +3.
This includes, swords, armours, ability changes.
Impose a penalty on the Item - for example make a helmet of wisdom may
at the same time reduce the constitution. Or maybe a ring of masochism -
when you wear it your MAX-HITPOINT increase by +200, when you remove it
they disappear again. The ring likes to remove itself from the finger.
============================================================================
MONSTER CLASSIFICATIONS:
------------------------
Major Demon == Balrog/etc.
Demon Lords == Orcus/etc.
Demi Gods == ??
Lesser Gods == Heimdal/Sif/etc.
Greater Gods == Thor/Odin/etc.
Arch Devil == Asmodeus/etc.
When creating monsters pay attention to the table above.
Example of Monsters:
--------------------
============================================================================
--------------------------------------------
CHARACTER & MONSTER ARMOR:
<AC> range from [10..-10] this is what it means :
AC 10 = Naked person
AC 0 = Very heavily armoured person (Full plate mail at *all* body parts)
AC -10 = Armored Tank (Hopefully impossible for players)
--------------------------------------------
Percentwise Coverage of Armour
and allowed AC range
Location Protects Range
-------- -------- -----
Body 30% [1..10]
Head 20% [1..10]
Legs 20% [1..10]
Feet 10% [1..10]
Arms 10% [1..10]
Hands 10% [1..10]
Shield 10% [1..10]
Magic 10% [1..10]
--------------------------------------------
PRICE GUIDELINES
AC BODY LEGS HEAD ARMS FEET ARMOUR
---- ---- ---- ---- ---- ---- ------
+1 100 50 50 25 25 Cloth (Heavy)
+2 200 100 100 50 50 Soft Leather
+3 500 150 150 75 75 Studded Leather
+4 1,000 500 500 250 250 Scale Mail
+5 2,500 1,250 1,250 625 625 Chain Mail
+6 7,000 3,500 3,500 1,750 1,750 Bronze Plate Mail
+7 18,000 9,000 9,000 4,500 4,500 Plate Mail
+8 35,000 17,500 17,500 8,750 8,750 Field Plate Mail
+9 50,000 25,000 25,000 12,500 12,500 Full Plate
+10 75,000 37,500 37,500 18,750 18,750 Anti Bomb ShieldPlate
*Hands and shields should be regarded as arms.
--------------------------------------------
IMPORTANT NOTICE
Rare items may only exist in minimal quantities!
Especially you should limit the occurence of
magical protection, since it is easy to carry.
============================================================================
Weapons & Carrying capacity
---------------------------
The weight of a weapon determines the strength needed to wield the weapon,
these values should be used:
STR Max. Weapon Weight Carrying capacity
--- ------------------ -----------------
0 0 0
1 1 3
2 2 3
3 3 10
4 4 25
5 5 55
6 6 80
7 7 90
8 8 100
9 9 100
10 10 115
11 11 115
12 12 140
13 13 140
14 14 170
15 15 170
16 16 195
17 18 220
18 20 255
18/01..50 22 280
18/51..75 24 305
18/76..90 26 330
18/91..99 28 380
18/100 30 480
Strength above 18/100 is only used by NPC's - not used by players.
No weapon may ever exceed 30 pounds in weight.
There are three kind of weapons :
(P)iercing
(S)lashing (Not useable by Clerics)
(B)ludgeoning
Backstabbing is only possible with piercing weapons.
No weapon may ever exceed 4d6 damage (as total of magic bouns too)!
(4d6 is 14 damage as average since 4*((1+6)/2)==14)
No weapon may ever exceed 30 pounds in weight.
No shop-produced weapon may exceed 2d8 in total damage or weigh more
than 20 pounds.
Read notes regarding Magic before making a monster-slayer +50 +70
with +800 to strength
PRIMARY BUYABLE WEAPONS <PBW>:
Name Damage Type Cost Weight Cost_pr_day
--------------- ----- ---- ---- ------ -----------
Dagger 1d4 P 10 1 Cost/3
Small sword 1d6 P 60 3 Cost/3
Long sword 1d8 S 600 8 Cost/3
Wooden Club 1d3 B 12 3 Cost/3
War hammer 1d5 B 50 6 Cost/3
===========================================================================
Notes:
<THAC0> this is the number needed to roll on a 20-sided dice to hit
opponent <AC> equivalent of zero. A 20 is always considered
a hit, a 1 is always a miss. Example:
Your <THAC0> is 14 (ei. level 7 fighter). You are fighting
an opponent with <AC> '3'. Thus to hit <AC> 0 you must
roll a 14 or greater. To hit <AC> 3 you must then roll
11 (14-3) or greater. If you had to hit <AC> '-3' you
would have to roll 17 (14-(-3)) or greater on a 20 sided
dice.

View File

@ -0,0 +1,6 @@
mail -s "CircleMUD World Builders' Documentation (1/5)" $1 < database.doc
mail -s "CircleMUD World Builders' Documentation (2/5)" $1 < dbsup.doc
mail -s "CircleMUD World Builders' Documentation (3/5)" $1 < defs.doc
mail -s "CircleMUD World Builders' Documentation (4/5)" $1 < shop.doc
mail -s "CircleMUD World Builders' Documentation (5/5)" $1 < values.doc

View File

@ -0,0 +1,117 @@
/**************************************************************************
* Copyright (C) 1993 - see 'license.doc' for complete information. *
**************************************************************************/
CircleMUD File Manifest
The main circle directory has the following subdirectories and files:
README - Information for the new CircleMudder
automaint - shell script to perform maintenance .. see running.doc
autorun - shell script to run the MUD .. see running.doc
bin/ - directory of all the compiled programs (binaries)
doc/ - documentation
lib/ - MUD data (playerfile, world files, etc.)
log/ - system logs
src/ - source code
syslog - the current system log
The bin/ directory contains only binaries: 'circle' (the main MUD) and
its utilities, which are described in utils.doc.
The doc/ directory has its own README file, describing the contents of
each of the documentation files.
The lib/ directory contains the following subdirectories:
etc - Files which the MUD uses internally (playerfile, mail, etc.)
misc - Misc. database files meant to be changed (i.e. socials)
plrobjs - Player object hierarchy and utility scripts
text - Text files such as MOTD, news, help, etc.
world - The world hierarchy
The lib/etc directory contains the following files (the MUD actively maintains
these files while it is running; they should not be modified unless the game
is down):
Board.* - Binary files with the contents of the bulletin boards
badsites - List of banned sites
hcontrol - Binary file with the state of the house control system
players - Binary file containing data on all players
plrmail - Binary file containing player mail
The lib/misc directory contains the following files:
bugs - Bugs reported by players with the 'bug' command
ideas - Ideas from players from 'idea' command
messages - Spell and skill damage messages
socials - Text file with text of the socials
typos - Typos reported by players with the 'typo' command
xnames - Text file of invalid names
The lib/plrobjs contains the following files and directories:
a-e \
f-j \
k-o \ Subdirectories where player objects files are stored
p-t /
u-z /
zzz/
purgedir - Script to purge an object dir (meant for use by purgeobjs)
purgeobjs - Script to purge player objects (see utils.doc)
searchfor - Script to search for objects in obj files (see utils.doc)
The lib/text directory contains the following files:
background - Background story (for option 3 from main menu)
credits - Text for 'credits' command
handbook - Text for Immortal Handbook ('handbook' command)
help - Text for 'help' command with no arguments
help_table - File of all help entries for 'help' command
immlist - Text for 'immlist' command
imotd - Immortal MOTD -- seen by immortals on login
info - Text for 'info' command
motd - MOTD -- seen by mortals on login
news - Text for 'news' command
policies - Text for 'policy' command
wizlist - Text for 'wizlist' command
The lib/world directory contains the following subdirectories:
mob - Contains *.mob files (mobile files)
obj - Contains *.obj files (object files)
shp - Contains *.shp files (shop files)
wld - Contains *.wld files (world files)
zon - Contains *.zon files (zone files)
Each of the 5 subdirectories in the lib/world directory also contains
two additional files -- one called 'index', which specifies which files
in that directory should be loaded when the MUD boots, and 'index.mini',
which specifies which files should be loaded if the MUD is booted with
the -m (mini-mud) option.
The log/ directory contains several files of the form syslog.n, where n
is a small number. These are the most recent CircleMUD syslogs.
In addition, it contains the following more permanent system logs:
badpws - Records of bad password attempts
delete - Players who have self-deleted
dts - Players who have hit death traps
errors - MUD system errors ("SYSERR" messages)
levels - Records of all levels gained by all players
newplayers - Records of the creation of new players
rentgone - Players who have lost their items in rent
restarts - List of times at which the MUD rebooted
rip - Player deaths
usage - Mud system usage (player load & memory usage info)
The src directory contains all of the C and header files for the MUD,
along with a Makefile. The src/util directory contains source for
CircleMUD's utility programs. See running.doc for more information
on how to compile the MUD. See utils.doc for more information on how
to use CircleMUD's utilities.

View File

@ -0,0 +1,214 @@
=============================================================================
The following documentation is excerpted from Merc 2.0's 'hacker.txt' file.
It was written by Furey of MERC Industries and is included here with his
permission. I've packaged it with Circle (very slightly changed in a couple
of places, i.e. specific filenames) because it offers good advice and insight
into the art and science of software engineering.
=============================================================================
=== 'I'm running a Mud so I can learn C programming!'
Yeah, right.
The purpose of this document is to record some of our knowledge, experience and
philosophy. No matter what your level, we hope that this document will help
you become a better software engineer.
Remember that engineering is work, and NO document will substitute for your
own thinking, learning and experimentation.
=== How to Learn in the First Place
(1) Play with something.
(2) Read the documentation on it.
(3) Play with it some more.
(4) Read documentation again.
(5) Play with it some more.
(6) Read documentation again.
(7) Play with it some more.
(8) Read documentation again.
(9) Get the idea?
The idea is that your mind can accept only so much 'new data' in a single
session. Playing with something doesn't introduce very much new data, but it
does transform data in your head from the 'new' category to the 'familiar'
category. Reading documentation doesn't make anything 'familiar', but it
refills your 'new' hopper.
Most people, if they even read documentation in the first place, never return
to it. They come to a certain minimum level of proficiency and then never
learn any more. But modern operating systems, languages, networks, and even
applications simply cannot be learned in a single session. You have to work
through the two-step learning cycle MANY times to master it.
=== Basic Unix Tools
'man' -- gives you online manual pages
'grep' -- stands for 'global regular expression print'
'vi'
'emacs'
'jove' -- use whatever editor floats your boat
but learn the hell out of it
you should know EVERY command in your editor
'ctags' -- makes 'tags' for your editor
allows you to goto functions by name in any source file
'>'
'>>'
'<'
'|' -- input and output redirection
get someone to show you, or dig it out of 'man csh'
These are the basic day-in day-out development tools. Developing without
knowing how to use ALL of these well is like driving a car without knowing how
to change gears.
=== Debugging: Theory
Debugging is a science. You formulate a hypothesis, make predictions based on
the hypothesis, run the program and provide it experimental input, observe its
behavior, and confirm or refute the hypothesis.
A good hypothesis is one which makes surprising predictions which then come
true; predictions that other hypotheses don't make.
The first step in debugging is not to write bugs in the first place. This
sounds obvious, but sadly, is all too often ignored.
If you build a program, and you get ANY errors or ANY warnings, you should fix
them before continuing. C was designed so that many buggy ways of writing code
are legal, but will draw warnings from a suitably smart compiler (such as 'gcc'
with the '-Wall' flag enabled). It takes only minutes to check your warnings
and to fix the code that generates them, but it takes hours to find bugs
otherwise.
'Desk checking' (proof reading) is almost a lost art in 1993. Too bad. You
should desk check your code before even compiling it, and desk-check it again
periodically to keep it fresh in mind and find new errors. If you have someone
in your group whose ONLY job it is to desk-check other people's code, that
person will find and fix more bugs than everyone else combined.
One can desk-check several hundred lines of code per hour. A top-flight
software engineer will write, roughly, 99% accurate code on the first pass,
which still means one bug per hundred lines. And you are not top flight.
So ... you will find several bugs per hour by desk checking. This is a very
rapid bug fixing technique. Compare that to all the hours you spend screwing
around with broken programs trying to find ONE bug at a time.
The next technique beyond desk-checking is the time-honored technique of
inserting 'print' statements into the code, and then watching the logged
values. Within Circle code, you can call 'printf' or 'fprintf' to dump
interesting values at interesting times. Where and when to dump these values
is an art, which you will learn only with practice.
If you don't already know how to redirect output in your operating system, now
is the time to learn. On Unix, type the command 'man csh', and read the part
about the '>' operator. You should also learn the difference between
'standard output' (e.g. output from 'printf') and 'error output' (e.g. output
from 'fprintf').
Ultimately, you cannot fix a program unless you understand how it's operating
in the first place. Powerful debugging tools will help you collect data, but
they can't interpret it, and they can't fix the underlying problems. Only you
can do that.
When you find a bug ... your first impulse will be to change the code, kill the
manifestation of the bug, and declare it fixed. Not so fast! The bug you
observe is often just the symptom of a deeper bug. You should keep pursuing
the bug, all the way down. You should grok the bug and cherish it in fullness
before causing its discorporation.
Also, when finding a bug, ask yourself two questions: 'what design and
programming habits led to the introduction of the bug in the first place?'
And: 'what habits would systematically prevent the introduction of bugs like
this?'
=== Debugging: Tools
When a Unix process accesses an invalid memory location, or (more rarely)
executes an illegal instruction, or (even more rarely) something else goes
wrong, the Unix operating system takes control. The process is incapable of
further execution and must be killed. Before killing the process, however, the
operating system does something for you: it opens a file named 'core' and
writes the entire data space of the process into it.
Thus, 'dumping core' is not a cause of problems, or even an effect of problems.
It's something the operating system does to help you find fatal problems which
have rendered your process unable to continue.
One reads a 'core' file with a debugger. The two most popular debuggers on
Unix are 'adb' and 'gdb', although occasionally one finds 'dbx'. Typically
one starts a debugger like this: 'adb bin/circle' or 'gdb bin/circle lib/core'.
The first thing, and often the only thing, you need to do inside the debugger
is take a stack trace. In 'adb', the command for this is '$c'. In gdb,
the command is 'backtrace'. In dbx, the command is 'where'. The stack trace
will tell you what function your program was in when it crashed, and what
functions were calling it. The debugger will also list the arguments to these
functions. Interpreting these arguments, and using more advanced debugger
features, requires a fair amount of knowledge about assembly language
programming.
If you have access to a program named 'Purify' ... learn how to use it.
=== Profiling
Here is how to profile a program:
(1) Remove all the .o files and the 'circle' executable:
rm src/*.o bin/circle
(2) Edit your makefile, and change the PROFILE= line:
PROFILE = -p
(3) Remake circle:
make
(4) Run circle as usual. Shutdown the game with shutdown when you have run long
enough to get a good profiling base. If you crash the game, or kill the
process externally, you won't get profiling information.
(5) Run the 'prof' command:
prof bin/circle > prof.out
(6) Read prof.out. Run 'man prof' to understand the format of the output.
For advanced profiling, you can use 'PROFILE = -pg' in step (2), and use the
'gprof' command in step 5. The 'gprof' form of profiling gives you a report
which lists exactly how many times any function calls any other function. This
information is valuable for debugging as well as performance analysis.
Availability of 'prof' and 'gprof' varies from system to system. Almost every
Unix system has 'prof'. Only some systems have 'gprof'.
=== Books for Serious Programmers
Out of all the thousands of books out there, three stand out:
Kernighan and Plaugher, _The Elements of Programming Style_.
Kernighan and Ritchie, _The C Programming Language_.
Brooks, _The Mythical Man Month_

View File

@ -0,0 +1,79 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
Description of module 'handler.c'.
*** Note: All the routines that takes something away from something assumes
that something is actually in/carried by something!
void char_from_room(struct char_data *ch)
Removes ch from whatever room he's in.
void char_to_room(struct char_data *ch, int room)
Places ch in room.
void object_to_char(struct obj_data *object, struct char_data *ch)
Gives object to ch.
void object_from_char(struct obj_data *object)
Takes object away from The character who is carrying it.
struct obj_data *find_object_in_list(char *name, struct obj_data *list)
This procedure assumes that list points to the head of a content-list of
objects. It then tries to locate the object with a given name within that
list. If succesful, the function returns a pointer to that object; if not,
it returns a null pointer.
struct obj_data *find_obj(char *name)
This function searches the 'global' list of objects (pointed to by
'object_list') for an object with a given name. It then returns either
a null pointer or a pointer to that object (note that in this version,
it will always return the first occurence of an object with a given name).
struct char_data *get_char_room(char *name, int room)
Searches room for character with 'name'. Returns null or pointer to that
character.
struct char_data *get_char(char *name)
Searches the entire world for a character. Assumes that all characters are
in a list pointed to by character_list (This might need changing).
void object_to_room(struct obj_data *object, int room)
Puts an object in a room.
void object_from_room(struct obj_data *object)
void object_to_object(struct obj_data *obj, *obj_to)
void object_from_object(struct obj_data *obj, *obj_from)
void extract_char(struct char_data *ch)
Extracts a character completely from the world, and leaves his stuff in
the room (might be useful.. might not..).
**** Higher level versions of the 'find' routines.
These routines work like the above versions, with the exception that they are
supplied with a pointer to a character as well as a keyword to look for. they
then return nil if they fail to locate the object/character OR if the character
'using' the routine can't see the searched-for object/character.
struct char_data *get_char_room_vis(struct char_data *ch, char *name)
struct char_data *get_char_vis(struct char_data *ch, char *name)
struct obj_data *find_object_in_list_vis(struct char_data *ch, char *name,
struct obj_data *list)
/*search the entire world for an object, and return a pointer */
struct obj_data *find_obj_vis(struct char_data *ch, char *name)

View File

@ -0,0 +1,13 @@
/**************************************************************************
* Copyright (C) 1993 - see 'license.doc' for complete information. *
**************************************************************************/
HOW TO CONVERT YOUR IDEAS INTO REALITY
A CircleMUD Coding Manual
Table of Contents
---------------------------------------------------------------------------
i. Introduction
1. Overview and Coding Basics

View File

@ -0,0 +1,117 @@
This file contains the original DikuMUD license. Since CircleMUD is based
on DikuMUD, the DikuMUD license applies to CircleMUD. Note well: the use
of CircleMUD in any capacity implies that you have read, understood, and
agreed to abide by the terms and conditions set down by this license.
Jeremy Elson
Department of Computer Science
Johns Hopkins University
Baltimore, MD 21218 USA
---------------------------------------------------------------------------
/* ************************************************************************
* Copyright (C) 1990, 1991 *
* All Rights Reserved *
************************************************************************* */
DikuMud License
Program & Concept created by
Sebastian Hammer
Prss. Maries Alle 15, 1
1908 Frb. C.
DENMARK
(email quinn@freja.diku.dk)
Michael Seifert
Nr. Soeg. 37C, 1, doer 3
1370 Copenhagen K.
DENMARK
(email seifert@freja.diku.dk)
Hans Henrik St{rfeldt
Langs} 19
3500 V{rl|se
DENMARK
(email bombman@freja.diku.dk)
Tom Madsen
R|de Mellemvej 94B, 64
2300 Copenhagen S.
DENMARK
(email noop@freja.diku.dk)
Katja Nyboe
Kildeg}rdsvej 2
2900 Hellerup
31 62 82 84
DENMARK
(email katz@freja.diku.dk)
This document contains the rules by which you can use, alter or publish
parts of DikuMud. DikuMud has been created by the above five listed persons
in their spare time, at DIKU (Computer Science Instutute at Copenhagen
University). You are legally bound to follow the rules described in this
document.
Rules:
!! DikuMud is NOT Public Domain, shareware, careware or the like !!
You may under no circumstances make profit on *ANY* part of DikuMud in
any possible way. You may under no circumstances charge money for
distributing any part of dikumud - this includes the usual $5 charge
for "sending the disk" or "just for the disk" etc.
By breaking these rules you violate the agreement between us and the
University, and hence will be sued.
You may not remove any copyright notices from any of the documents or
sources given to you.
This license must *always* be included "as is" if you copy or give
away any part of DikuMud (which is to be done as described in this
document).
If you publish *any* part of dikumud, we as creators must appear in the
article, and the article must be clearly copyrighted subject to this
license. Before publishing you must first send us a message, by
snail-mail or e-mail, and inform us what, where and when you are
publishing (remember to include your address, name etc.)
If you wish to setup a version of DikuMud on any computer system, you
must send us a message , by snail-mail or e-mail, and inform us where
and when you are running the game. (remember to include
your address, name etc.)
Any running version of DikuMud must include our names in the login
sequence. Furthermore the "credits" command shall always cointain
our name, addresses, and a notice which states we have created DikuMud.
You are allowed to alter DikuMud, source and documentation as long as
you do not violate any of the above stated rules.
Regards,
The DikuMud Group
Note:
We hope you will enjoy DikuMud, and encourage you to send us any reports
on bugs (when you find 'it'). Remember that we are all using our spare
time to write and improve DikuMud, bugs, etc. - and changes will take their
time. We have so far put extremely many programming hours into this project.
If you make any major improvements on DikuMud we would be happy to
hear from you. As you will naturally honor the above rules, you will receive
new updates and improvements made to the game.

View File

@ -0,0 +1,298 @@
CircleMUD Release History
-------------------------
This document is basically just a a compliation of all the README files
which accompanied each release of CircleMUD. At the end is the post
to rec.games.mud.diku which originally anounced CircleMUD as a publically
available MUD source code.
Version 2.20: November 17, 1993
Version 2.11: September 19, 1993
Version 2.10: September 1, 1993
Version 2.02: Early August
Version 2.01: July 20, 1993
Version 2.00: July 16, 1993
The latest version of Circle is 2.20, released on November 17, 1993.
Version 2.20 supercedes version 2.11, which was released on September 19, 1993.
Version 2.20 November 17, 1993
--------------------------------
New features:
o A completely new output buffering system which is far more network-efficient,
and somewhat more memory- and speed-efficient, than the original Diku system.
Definitely a major win for people with slow Net links. (Details available
by request, but this was discussed on rgmd recently.) Several other
functions (such as do_where() and do_who()) have been rewritten to take
advantage of the new system.
o Redesigned stat screens with better readability
o Command-line substitution via the "^" character (works identically to the
csh command)
o Code sent by Jeff Fink (thanks Jeff!): Help now handles ambiguous cases
correctly (i.e., "help color" will give you help for color and not
colorspray)
o vstat command to stat mobiles and object by virtual number
o updated documentation
And, bug fixes of varying degrees of severity:
o SunOS Bus errors on stealing
o +hit item bug
o Switched immort re-login bug
o Mob memory bug
o Poison/Stat bug (I think this one is native to Diku Gamma 0.0 -- the
function hit_gain was responsible for subtracting hits when a char is
poisoned, so you'd lose hits when someone statted you.)
o Stat room bug under Solaris and IRIX
o Ungroup bug
o "goto 3.guard" now works (takes you to the third guard instead of room 3)
o various other minor fixes
------------------------------------------------------------------------------
Version 2.11 September 19, 1993
----------------------------------
Changes in 2.11 (from 2.10):
Mostly bug fixes, including:
-- SET FILE bug
-- SIGBUS/unaligned data errors under SunOS and other OS's
-- Move limit modifier bug
-- wrist-wearing bug
-- Compilation problems with utility.c under some operating systems
The only notable change is that the hit_limit, move_limit, and mana_limit
functions have been removed (for many reasons). From the players' point of
view, this means that a character no longer gains movement points with age.
Hit, move, and mana gain speeds are still a function of age, however.
============================================================================
Version 2.10 was released on September 1, 1993.
Changes in 2.10 (from 2.01):
o Rewritten get/put/drop/junk/donate/give/wear/remove, so that "all" and
"all.x" work in a much wider variety of cases. Loosely based on code
sent in by Jeff Fink.
o "Track" function based on breadth-first search
o Configurable auto-save feature to automatically crash-save players
periodically
o More intense error-checking in object saving system to detect problems
with file permissions
o Many configuration options added to config.c
o Option to make death traps automatically have dump spec-proc assigned
o ASPELL and ACAST macros added to match the ACMD macros; spells1.c,
spells2.c, spell_parser.c, and magic.c changed to use the macros.
o SKILL macro split into GET_SKILL and SET_SKILL macros so that error
checking can be done
o Enhanced documentation -- a help entry now exists for every command
o Linux compatibility, and further steps to SVR4 compatibility which will
make it into Circle eventually. (Note: you must make a change in one
line of the Makefile for Linux compatibility.)
o All functions now prototyped before use
Jeremy Elson
August 31, 1993
=========================================================================
=========================================================================
Version 2.01 is basically the same as 2.00; most of the changes are for
making the MUD more portable, based on mail I've received after the
release of version 2.00.
-- Problems with OPEN_MAX and SEEK_x resolved
-- Some problems with the Makefile fixed
-- Compiles much more cleanly with the -Wall option
-- A couple of minor bugs fixed
-- A few small fixes to the documentation
July 20, 1993
--------------------------------------------------------------------------
CircleMUD was developed and tested under Ultrix 4.0; your mileage may vary.
If I have time, I'll try and port it to other machines. If you port it and
want to share your work with others, feel free to drop me a line.
The CircleMUD 'press release' is included below, in case you haven't seen
it and want to.
Good Luck!
Jeremy Elson aka Rasmussen (Ras)
July 16, 1993
---------------------------------------------------------------------------
Wake the kids and find the dog, because it's the FTP release of
C I R C L E M U D 2 . 0
That's right -- CircleMUD 2.0 is done and is now available for anonymous FTP
at ftp.cs.jhu.edu!
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 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.
Just take a gander at some of Circle's nifty features:
-- In-memory mobile and object prototypes and string sharing for
decreased memory usage and blazingly fast zone resets
-- All large realloc()s have been removed and replaced by boot-time
record counting and a single malloc() for superior memory efficiency
-- Split world/obj/mob/zon/shp files for easy addition of areas; plus,
all the world files are still in the original Diku format for
compatibility with existing areas
-- Boot-time and run-time error checking of most data files with
diagnostic messages a lot more helpful than "segmentation fault"!
-- Player mail system and bank
-- Rewritten board system: boards are now stable, robust, more
intelligent, and easily expandable -- adding a new board is
as easy as adding another line to an array
-- ANSI color codes with a fully documented programmers' interface
-- On-line system logs
-- Optional automatically regenerating wizlist -- a final end
to new immortals constantly asking you when they'll be added
to the immlist!
-- "config.c" file allows you to change aspects of the game such
as playerkilling/playerthieving legality, max number of objects
rentable, and nameserver usage -- WITHOUT recompiling the
entire MUD!
-- All text (help, mortal/immort MOTDs, etc.) is rebootable at
run-time with the "reboot" command
-- All players are given a unique serial number -- no more messy,
time consuming str_cmp()s when you're trying to identify people!
-- Fully integrated and robust rent/crash system -- allows normal
renting, cryo-renting, crash protection, and forced rent
(at an increased price) after an hour of idling
-- All the standard wizard stuff you're used to: level-sensitive
invisibility, settable poofin/poofouts, wizline
-- Advanced 'set' command which allows you to set dozens of aspects
of players -- even if they aren't logged in! "Stat" also allows
you to stat people who aren't logged in!
-- Intelligent 'autorun' script handles different types of reboots,
organizing your system logs, and more!
-- Circle comes with more than a dozen utilities, all fully
documented, to make maintenance a snap!
-- And much, much more!
Unfortunately, the original Circle had more than its fair share of Bad People
when it was alive, but it DID lead to an impressive list of security and
"asshole control" features:
-- 3 types of sitebanning available: 'all' to refuse all connections,
'new' to refuse new players, or 'select' to refuse new players and
all registered players who don't have a SITEOK flag.
-- 'wizlock' allows you to close the game to all new players or all
players below a certain level.
-- Handy 'mute' command squelches a player off of all public
communication channels
-- Handy 'freeze' command freezes a player in his tracks: the MUD
totally ignores all commands from that player until he's thawed.
-- Even handier DELETE flag allows you to delete players on the fly.
-- 'set' command (mentioned above) allows you to freeze/unfreeze/
delete/siteok/un-siteok players -- even if they aren't logged in!
-- Bad password attempts are written to the system log and saved;
if someone tries to hack your account, you see "4 LOGIN FAILURES
SINCE LAST SUCCESSFUL LOGIN" next time you log on.
-- Passwords don't echo to the screen; allows 3 bad PW attempts
before disconnecting you.
-- Players aren't allowed to choose their character's name as their
password -- you'd be surprised how many do!
-- "xnames" text file specifies a list of invalid name substrings
to prevent creation of characters with overly profane names.
Listen to all the rave reviews of CircleMUD 2.0!
"How long ago was that deadline you set for yourself?" -- My Friend
"NO ONE should be denied the power of computation." -- My Professor
"Multi-user WHAT?" -- My Mom
Give it a try -- what do you have to lose other than your GPA/job, friends,
and life?
---------------------------------------------------------------------------
Circle's complete source code and areas are available now for anonymous FTP
at ftp.cs.jhu.edu (128.220.13.50) in the directory pub/CircleMUD.
I welcome comments and constructive criticism about CircleMUD and would be
happy to discuss any design decisions I've made, but I'm not particularly
receptive to lunatics frothing at the mouth and thus will probably ignore
you if you flame me.
Also, remember the odds here: one person (me) against 29,000 lines of
code (Circle), so there are bound to be some mistakes in there somewhere.
Good luck, and happy Mudding,
Jeremy Elson aka Ras

View File

@ -0,0 +1,402 @@
/**************************************************************************
* Copyright (C) 1993 - see 'license.doc' for complete information. *
**************************************************************************/
----- Compiling, Running, and Maintaining CircleMUD -----
This manual is meant to be read by implementors just getting started with
CircleMUD. This should be the first document you should read after reading
the main README file.
It should be the first documentation you read (after the
README file in theIt describes how to get the MUD compiled, configured, and
running; use of command-line options and system logs; and required daily
maintenance.
This i
Table of Contents
---------------------------------------------------------------------------
1. Compiling Circle
1.1. Compatibility Issues
1.2. How-To
2. Configuring Circle
3. Running Circle
3.1. Execution and 'autorun'
3.2. Command-Line Options
4. System Logs
4.1. Player Information
4.2. Usage Information
4.3. Errors
1. Compiling Circle
-------------------
1.1. Compatibility Issues
Ultrix 4.0 was used as CircleMUD's development platform up through v2.00;
starting with 2.10, Linux 0.99.11 was used instead. If you have Ultrix,
Linux, or another BSD-compatible system, and the gcc compiler, you should
be able to compile right out of the electronix box. If you don't have gcc,
try using cc -- on some systems such as AIX, the cc compiler is ANSI
compliant.
The author has personally compiled CircleMUD under the following systems:
Ultrix 4.0
IRIX 4.0.1, 4.0.4, 4.0.5
SunOS 4.1.1, 4.1.3
AIX 3.2
Linux 0.99.11
ConvexOS V10.2
Others have reported successfully compiling Circle under many other
systems; if you have a BSD-compatible system, chances of getting Circle
to compile easily are pretty good. Non-BSD systems will probably have
trouble with certain functions; getting Circle to compile for the first time
on such systems may be difficult and time-consuming. SVR4 compatibility is
on the horizon; many functions have already been converted to be SVR4
compatible, but the code has not yet been fully ported.
The Makefile has options to compile the MUD under Linux, AIX, and IRIX.
It also has an option for SVR4 but, as mentioned above, it does not
yet completely work. The unmodified Makefile should work with many other
including those listed above.
If you port Circle to another operating system and wish to share your work
with others, feel free to mail me your changes so that they can be included
in future releases of CircleMUD (if any). You'll be given credit, of
course. :)
1.2. How-To
The /src directory contains the source code for the main MUD; /src/utils
has the source for a dozen or so MUD maintenance utilities. The makefile
is in the /src directory; type 'make' while in that directory to compile
only the Circle server, type 'make utils' to compile all the utilities, or
type 'make all' to compile everything. You can also make an individual
utility by typing 'make x', where x is the name of the utility you want to
compile. Complete documentation of the utility programs can be found in
utils.doc.
The Makefile directs all compiled programs to the /bin directory. Although
not necessary, you may want to put Circle's /bin directory in your $PATH.
2. Configuring Circle
---------------------
Your first instinct will probably be to put the game up as fast as possible
to see if it works. That's fine, but there are some files you should be
aware of before you put the game up 'for real'. This is just a partial
list -- see 'files.doc' for a complete description of all the files in the
Circle distribution.
First, you'll probably want to take a look at 'config.c' -- it has dozens
of variables you can set to configure various aspects of CircleMUD.
The place where most of your day-to-day changes will be is in the lib/text
directory; that's where the help files, MOTD (Message Of The Day), imotd
(MOTD for immortals), and other text files are all kept.
In particular, you should make sure to put something in your 'policy' file --
it's better to have definite rules from the beginning than to have problems
later on when people try to bend you as far as they can. Also, you should
put tips for new immortals in the 'handbook' file (i.e., "Don't help any
mortals", "Don't kill mobiles", "Don't run through puddles", "Don't bring
glassware into the pool area", etc.)
The area hierarchy is lib/world. lib/world has 5 subdirectories -- wld,
mob, obj, shp, and zon, which is where the world, mobile, object, shop,
and zone files go, respectively. Each directory has a set of world
files in it with the correct extension (i.e., the obj subdir will have
a bunch of files ending with ".obj", such as 30.obj, 31.obj, etc.) plus
two special files -- 'index' and 'index.mini'. You can control which files
are loaded by Circle simply by changing the list of files listed in 'index'.
'index.mini' controls which (smaller) set of world files should be loaded
in the debugging mode (Mini-Mud Mode, explained below.)
3. Running Circle
-----------------
3.1. Execution and 'autorun'
Circle should always be run from circle's "root" directory, not the /bin
directory. You can run it manually by typing 'bin/circle' (useful for
testing and debugging). For running the game "for real", it's better
to use the 'autorun' shell script provided in Circle's root directory.
Autorun lets Circle run itself for long periods of time. It continuously
runs the game as well as removing old system logs, moving newer system logs
to the /log directory, and saving certain log entries to permanent files.
Autorun can be controlled by creating files with certain names. You can
use the 'touch' command to create a file, and, of course, the 'rm' command
to remove a file. If a file called '.fastboot' exists, the Circle will reboot
immediately if it crashes or is shut down instead of waiting 40 seconds as
it normally does. A file called '.killscript' will cause the script to
terminate itself; i.e., if you want to bring the game down. If you want
to temporarily prevent the MUD from rebooting, create a file called 'pause';
the script will go into a wait loop until 'pause' is removed.
Although you can create these files manually, the SHUTDOWN command from
within the MUD has several command-line options which will create these
files for you. See the SHUTDOWN help entry in wizhelp.doc for more
information.
It's not uncommon for CircleMUD to run for a week without crashing. The
game can be rebooted manually with the SHUTDOWN command, or automatically.
Once a day, at a time specified by the REBOOT_AT macro in modify.c, the
game checks for the existence of the file "reboot" in the selected data
directory. If the file exists, the game is rebooted (it terminates nicely,
with a nonzero return value). If the size of the file is nonzero, its contents
are processed by "sh" (with a system() call). If the processing returns
with a nonzero status, the file is renamed to "reboot.FAILED", and the
rebooting is called off. If it returns zero, the file is moved to
"reboot.SUCCEEDED", and the game is rebooted.
The first character to log in to the MUD (i.e., when the playerfile is
empty) will be made the maximum level. You should fix your stats using
the RESTORE command when you first create the character. To make more
God characters, use the ADVANCE command.
3.2. Command-Line Options
There are a number of command-line options which Circle will recognize.
You can use these when running Circle manually, or put them in the FLAGS
variable in your autorun script to use them all the time.
The syntax is:
circle [-m] [-q] [-r] [-s] [-d <path>] [<port #>]
-m: "Mini-Mud Mode". Mini-mud will be one of your most powerful debugging
tools; it causes Circle to boot with an abridged world, cutting the
boot time down to several seconds. It is useful for testing features
which are not world-related (i.e, new commands or spells).
CircleMUD uses split world files (in the lib/world heirarchy); each
directory (i.e., wld, obj, mob, shp, and zon) has a file called 'index'
which specifies which files should be loaded at boot-time. The file
'index.mini' specifies which parts of the world should be loaded with
the -m option.
-q: Quick boot - prevents checking of timed out object files. Every time
Circle boots, it checks every object file to see if it has timed out;
if so, it is deleted. This is done primarily to save disk space. If
time is more important to you than space, use the -q option. -q is
automatically activated when you use -m.
-r: Restrict game to new players. Allows you to decide at run-time whether
the game is open to new players or not; -r is equivalent to typing
"wizlock 1" (see wizhelp.doc for more information).
-s: Disable special routines. This option prevents special procedures from
being assigned. It is still supported but obsolete because Circle checks
to make sure each mob exists before assigning a spec_proc to it.
-d: Select data directory. This is useful if you want to keep one or more
sets of game data in addition to the standard set. For example, you may
wish to make a copy of the entire world in a separate directory, so that
you can test additions to the code or worldfile without subjecting the
players to unnecessary hazards. The default data directory is 'lib'.
Any coredumps (may they never happen to you!) will take place in the
selected directory.
port : Select the port on which the game is to wait for connections.
Default port is 4000; you can change the default in config.c and
the PORT= line of the autorun script.
4. System Logs
--------------
CircleMUD writes a wide variety of information to its log file (called
"syslog"). During Circle's boot sequence, the syslog keeps a record of
everything the MUD is doing to initialize itself; this can be useful to
determine what the problem is if the MUD dies while it is booting. Once
the game is up and running, the syslog contains information about players
(i.e., when they connect, disconnect, rent, unrent, quit, die, hit death
traps, etc.) as well as status information about the game itself. The
game-related information falls generally into 2 categories: usage
information and errors.
4.1. Player Information
The player information recorded by Circle's system logs will serve you
very well as your players start to make wild claims about strange bugs
resulting in them losing equipment or points. Many mudders prey on the
insecurities of a new mud administrator who is terrified that his or her
MUD is riddled with bugs and will do anything to satisfy grumpy players --
don't let yourself fall into that trap! CircleMUD is bound to contain
bugs, but most of the core systems have been well tested, so you should
take claims such as "I magically lost all my stuff!" with a grain of salt
and check your system logs.
If a player ever asks you for reimbursement of equipment, money, gold,
experience points, or whatever, your gut reaction should always be to
check the logs first.
As a sidebar, let me point out that the value of system logs is twofold:
1) they actually provide you with valuable information, and 2) they make
your players paranoid. When I first started mudding and I heard about
this mysterious "system log", it made me incredibly paranoid. Now that
I've done a good deal of MUD administration, I've seen the same paranoia
in _many_ other players.
That paranoia is a very good thing. The system logs become an abstract
and shapeless but omnipresent force on the MUD. Players hear about "the
System Log" and then get paranoid that everything they do is being
recorded, so they tend to behave, lest the evil System Log betray their
wrongdoings to the Gods.
For this reason, when you go to check your logs, it's a good idea to
say something like "Hold on -- let me go check the system logs, OK?"
because it reinforces the syslog's presence in the collective psyche
of your players.
Back to the point. When someone claims that they've been wronged by the
evil system, always check the logs. The logs give you power to say things
like "What do you mean your items disappeared in rent -- it says right here
in the logs 'Rasmussen has quit the game.' -- you didn't rent at all, you
just QUIT!"
The logs also record when a player's items are dumped due to insufficient
funds (remember -- rent is calculated per day on a PER-SECOND basis! If you
rent at the rate of 100 coins per day and come back 36 hours later, you'll
be charged 150 coins!). Plus, when someone rents, it records in the logs how
much rent cost per day and how much the player had, to diffuse disputes such
as "But I had enough money!!"
In short: the system logs are your friends. Love them.
The autorun script saves 6 levels of raw system logs. In addition, it
greps the logs for certain pieces of extra-juicy information to save
indefinitely.
4.2. Usage Information
Every 5 minutes, the game counts how many people are playing and records
that information in the system log. Optionally, if you #define RUSAGE
in comm.c, it will also record system resource information such as CPU time
and memory used. The usage information currently logged by Circle is,
as you can see, somewhat sparse; local MUD admins are encouraged to add
to this code as is appropriate for their particular site.
Usage information isn't critical, but it is interesting to look at the
usage patterns to determine when your peak playing hours are. If you're
good at using 'cut' and other Unix utilities, you can even dazzle your
friends by graphing your MUD's system usage.
[ Note: friends not included with the CircleMUD distribution. ]
4.3. Errors
Just as your first gut instinct should be to look at the logs if a player
starts begging you for something, your first gut instinct in the event of
a crash or unexpected shutdown should also be to look at the system logs.
A Unix utility called 'tail' is used to look at the last few lines of a
text file; it's very useful for looking at the last entries in the system
log to see the last thing that happened before the shutdown. Often, Circle
will report an error in the logs just before it crashes. This method is
particularly useful if the MUD crashes during its boot sequence, because
the logging during boot is intensive.
If Circle shuts down unexpectedly and there is no core dump in the /lib
directory, the game probably detected an internal error and killed itself.
Such shutdowns are always preceeded by entries in the system log describing
the error.
If there's no error message at the end of the log, then there probably
IS a core dump, so you can use 'dbx', 'gdb', etc. to examine the core
dump and determine the reason for the crash. The file 'hacker.doc',
generously provided by Furey of MERC Industries, offers useful insight
into the art and science of debugging -- you'd be well advised to give it
a look-see.
Circle sometimes encouters a serious but non-fatal error; in this case,
the error will be written to the system log with the prefix SYSERR, but
the MUD will not shut itself down. You should always be aware of any
SYSERRs which occur -- they are often useful for forseeing imminent danger
or averting problems before they become critical. If a SYSERR does
occur, try to determine if a change you've made recently has caused it.
Ignoring SYSERRs is like ignoring compiler warnings: you can be tempted
to ignore them because the game keeps going even if they exist, but you
can easily get yourself into trouble by not listening. The autorun script
saves all SYSERRs to the file log/errors.
Day-To-Day MUD Administration
-----------------------------
Okay, so now you have your wonderful CircleMUD up and running and all is
right with the world. Right?
Well, technically, yes. Circle requires very little day-to-day attention
in order to keep the progam itself running smoothly. But the MUD itself
is just a series of instructions running on a computer, processing data.
Never lose sight of the fact that there will be dozens, hundreds, or maybe
even thousands of people connecting to your MUD -- and they are NOT
programs. They're people!
What I'm getting at is this: from the technical side, there are relatively
few things you have to do to keep the game running. But you can't just plop
a MUD on the Internet and then ignore it! Spend time on your MUD. Try to
keep up with the boards, and make an effort to respond to the complaints,
ideas, and suggestions posted there. Take a look at the 'bug', 'typo', and
'idea' files from time to time -- and maybe even respond to some of the ideas
using Mudmail. Try to respond to Mudmail you receive from players in a
timely manner. Make sure that your 'news', 'policy' and other text files
are up-to-date and suit the political climate on your MUD.
If you can't or just don't want to deal with the player politics, make sure
sure that you choose someone who can and will, and make them responsible for
dealing with it. If no one does it, your MUD will stagnate and die.
Maintaining CircleMUD
---------------------
CircleMUD requires little technical maintenance. You should look at the
log/errors file regularly to make sure there are no recurring problems.
Also, you probably will want to 'purge' the playerfile on a regular basis
(i.e., remove "deadweight" characters). You can decide how often to purge
the playerfile -- every day if disk space is tight, or every month if it
isn't. The purgeplay utility program (included) removes deadweight players.
You should run the 'purgeobjs' script (in the lib/plrobjs) directory after
you purge the playerfile -- it removes the object files of players who no
longer exist in the playerfile.
The 'automaint' script in the main circle directory will automatically purge
the playerfile and player objects for you. DO NOT RUN THIS SCRIPT WHILE
THE MUD IS RUNNING! Doing so will make your life (more) difficult.
Good luck with your MUD!
-- Jeremy Elson
jelson@cs.jhu.edu

View File

@ -0,0 +1,243 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
NEW FORMAT:
CircleMUD v3.0 now has a new shop file format. Since the old format
is still compatible, I've kept the old documetation at the end of
this file. If you'd like to convert shop files in the old format to that
of the new format, compile and run the utility shopconv. When writing new
files, you need to tell CircleMUD that the shopfile is in the new format
by including the following line BEFORE any shops in the file:
CircleMUD v3.0 Shop File~
The rest of the file is formatted as follows:
#<num>~
Shop Number (Used only for display purposes)
<num 1>
<num 2>
<num 3>
.
.
.
<num n>
-1
These numbers refer to the objects the shop produces. The numbers are
virtual numbers. The list MUST end with a -1.
<Profit when selling>
The object value is multiplied by this value when sold. This is a
floating point value. Must be >= 1.0
<Profit when buying>
The object value is multiplied by this value when bought. This is a
floating point value. Must be <= 1.0
<type 1> [namelist 1]
<type 2> [namelist 2]
<type 3> [namelist 3]
.
.
.
<type n> [namelist n]
-1
These lines contain the types of items that the shop will buy. The first
argument, called "type" is the type of item (see dbsup.doc). Numerical,
or english forms are valid (5 or WEAPON, 9 or ARMOR, etc) In addition,
you can provide optional keywords to give specific keywords that must
be present on the item. For further details on these expressions, see the
notes following the new file format. This list must be terminated by a -1.
<Message When Item to buy is non existing>~
<Message When item trying to sell is non existing>~
<Message When shop does not buy offered item>~
<Message when shop can't afford item>~
<Message when player can't afford item>~
<Message when buying an item>~
Price is %d
<Message when selling an item>~
Price is %d
<Temper>
When player can't afford an item, the shopkeeper tells them they
can't afford the item and then:
0 - The shopkeeper pukes on the player.
1 - The shopkeeper smokes his joint.
other - No action besides message above.
<Bitvector>
Allows you to set certain values for the shop.
WILL_START_FIGHT 1 /* Players can attack shopkeeper */
WILL_BANK_MONEY 2 /* Shopkeeper puts money > 15000
into the bank */
A brief note: Shopkeepers should be hard (if even possible) to kill.
The benefits players can receive from killing them is enough to unbalance
most non monty-haul campaigns.
<Shop Keeper Mobile Number>
Virtual number of the shopkeeper.
<With Who>
Designate certain alignments or classes that the shop will not
trade with. To determine this value, choose all elements on
the list below that you do not want sold to, and add their values.
TRADE_NOGOOD 1
TRADE_NOEVIL 2
TRADE_NONEUTRAL 4
TRADE_NOMAGIC_USER 8
TRADE_NOCLERIC 16
TRADE_NOTHIEF 32
TRADE_NOWARRIOR 64
<Room 1>
<Room 2>
<Room 3>
.
.
.
<Room n>
-1
The virtual numbers the mobile must be in for the shop to be effective.
(So trans'ed shopkeepers can't sell in the desert). The list must be
terminated by a -1.
<Time when open start 1>
<Time when open end 1>
The hours between which the shop is open.
<Time when open start 2>
<Time when open end 2>
The hours between which the shop is open.
ITEM NAME LISTS:
Name lists are formed by boolean expressions. The following operators
are available:
',^ = Not *, & = And +, | = Or
The precedence is Parenthesis, Not, And, Or. For example, the following line:
WEAPON [sword & long|short | warhammer | ^golden & bow] & magic
This shop will buy the following items of type WEAPON:
1) sword long magic
2) short magic (the first & is done before the first | )
3) warhammer magic
4) ^golden bow magic
Note that the ^ in front of golden affects ONLY golden, and nothing else
in the listing. Basically, the above expression could be written in
english as:
[(sword and long) or short or warhammer or (not golden and bow)] and magic
If I wanted the shop to only buy "short magic" only if they were also swords,
I would have to change the expression to:
WEAPON [sword & (long|short) | warhammer | ^golden & bow] & magic
^-Changes--^
You can also include object extra flags (listed in dbsup.doc). 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.
OLD FORMAT:
Default DIKU shop files have the following format:
#<xx>~
Shop Number (Used only for display purposes)
<num1>
<num2>
<num3>
<num4>
<num5>
These numbers refer to the objects the shop produces.
The numbers are virtual numbers.
<Profit when selling>
The object value is multiplied by this value when sold. This is a
floating point value. Must be >= 1.0
<Profit when buying>
The object value is multiplied by this value when bought. This is a
floating point value. Must be <= 1.0
<num1>
<num2>
<num3>
<num4>
<num5>
These five numbers are the item-types traded with by the shop.
See dbsup.doc.
<Message When Item to buy is non existing>~
<Message When item trying to sell is non existing>~
<Message When wrong item-type sold>~
<Message when shop can't afford item>~
<Message when player can't afford item>~
<Message when buying an item>~
Price is %d
<Message when selling an item>~
Price is %d
<Temper>
When player can't afford an item, the shopkeeper tells them they
can't afford the item and then:
0 - The shopkeeper pukes on the player.
1 - The shopkeeper smokes his joint.
other - No action besides message above.
<Bitvector>
Allows you to set certain values for the shop:
WILL_START_FIGHT 1 /* Players can attack shopkeeper */
WILL_BANK_MONEY 2 /* Shopkeeper puts money > 15000
into the bank */
A brief note: Shopkeepers should be hard (if even possible) to kill.
The benefits players can receive from killing them is enough to unbalance
most non monty-haul campaigns.
<Shop Keeper Mobile Number>
Virtual number of the shopkeeper.
<With Who>
Designate certain alignments or classes that the shop will not
trade with. To determine this value, choose all elements on
the list below that you do not want sold to, and add their values.
TRADE_NOGOOD 1
TRADE_NOEVIL 2
TRADE_NONEUTRAL 4
TRADE_NOMAGIC_USER 8
TRADE_NOCLERIC 16
TRADE_NOTHIEF 32
TRADE_NOWARRIOR 64
<Shop Room Number>
The virtual number the mobile must be in for the shop to be effective.
(So trans'ed shopkeepers can't sell in the desert).
<Time when open start 1>
<Time when open end 1>
The hours between which the shop is open.
<Time when open start 2>
<Time when open end 2>
The hours between which the shop is open.

View File

@ -0,0 +1,90 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
HANDLING 'SOCIALS' IN CIRCLEMUD
A general system exists to handle the 'social' commands -- those which
generally have no game-related purpose other than to convey emotions
between players. Socials are also useful for creating advanced DikuMUD
adventures and quests through the use of speical procedures; for example,
you could add a 'detonate' social which, within your quest, is handled by
a special procedure to cause something to explode.
Socials are all handled through the generalized command do_action. The
text file 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 interpreter.c (giving do_action as the
function pointer), and 2) adding information for the new social to the
lib/text/socials file.
In Circle 3.0, socials in the file are specified by name (instead of by
command number, as was true of the original Diku and versions of Circle
before 3.0.). In the standard Circle distribution, the socials appear
in alphabetical order in the file, but they can appear in any order and
can be rearranged if necessary.
The file is formatted as follows:
--------------------------------------------
<command name> <hide-flag> <minimum position of victim>
<messg to character if no argument>
<messg to others if no argument>
<messg to char if victim found> <---If this field is empty,
<messg to others if victim found> <-
<messg to victim> | then these fields must be
<messg to char if victim not found> | skipped, and the action will
<messg to char if vict is char> | ignore arguments.
<messg to others if vict is char> <-
<command name> <hide-flag> <minimum position of victim>
.
.
.
.
.
$~
-------------------------------------------------
Each social must contain either 1) only the first two messages (if the social
ignores arguments), or 2) all eight messages (if the social takes an argument).
Each message must be contained in one line.
The command-name indicates which social is being specified. The hide-flag
can be either 0 or 1; if 1, the social is hidden from OTHERS if they cannot
see the character performing the social. The action is not hidden from the
VICTIM, even if s/he cannot see the character performing the social, although
in such cases the character's name will, of course, be replaced with "someone".
Where it makes sense to do so, text fields may be left empty. This is done by
putting a '#' in the first column on the line. Doing so is legal in the
following fields:
a: messg to others if no arg
b: messg to others if victim found
c: messg to others if vict is char
Note again that if the field _messg to char if victim found_ is empty, then
the following fields must be omitted entirely (not even the '~'), and the
action will ignore any arguments supplied.
The procedure sends the text strings through act(), and they may contain
control codes (see the documentation for the act() function for details.)
Note that not all of act()'s control codes may be used; for example, codes
which refer to objects such as $p.
For the sake of efficiency, no tests or sanity checks are made on the
consistency or logic of the act() codes found in the social messages.
Hence, grave disorder may result if, say, the code '$N' occurs in a text
field that doesn't refer to a victim; like _messg to others if no arg_.
In previous versions of Circle, such grave disorder often manifested itself
in the form of crashes. However, the act() function itself in Circle 3.0
and above does sanity checks to make sure it's not dereferencing null
pointers, hopefully with the result of avoiding crashes. Nevertheless,
great care should be taken in making sure that the $ codes of socials are
used consistently and correctly.

View File

@ -0,0 +1,144 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
OFFENSIVE SPELL AVERAGE DAMAGE CHARTS
Upon learning a new spell, the manauser will always be able to cast
two of these spells. For each level, the manauser will be abel to cast
one additional spell of the type learned. The maximum abel to learn is
different between each spell, but for most offensive spells it is 7.
The number of spells that can be cast assume that everybody has got
100 mana points.
General Idea:
A M.U. Should be abel to kill a victim 3 levels below himself, by
using all his MANA points for offensive spells. This include
saving_throw calculations.
Saving throw has effect (level of victim = L, damage of spell = D)
Actual_Average_Damage = (L/20*(D/2))+(((20-L)/20)*D)
where L in [1..18] (Means saving never better than 2)
If you want to know how much dam, say E, a L level victim,
get from D dam, then:
Effective_Dam (E) = D/(1-(L/40))
---------------------------------------------------------------------------
TABLE:
LVL is level of victim.
HP is hit_points.
ERM is spell damage to effectively remove HPR
SAV is assumed saving throw
A.DIF. is Aprroximate adjusted difference.
LVL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
SAV 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 2
HP 22 35 47 60 72 85 97 110 122 135 147 160 172 185 197 210 222 235 247 260
ERM 22 37 51 67 82 100 118 138 157 180 203 229 255 285 315 350 386 427 470 495
A.DIF 15 15 16 16 18 18 20 20 23 23 26 26 30 30 35 35 41 43 -
---------------------------------------------------------------------------
Table of WHEN a MU can kill a Level X opponent by using 100 MANA points only.
MU Level 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Opponent 0 0 0 1 2 3 5 6 7 8 9 10 12 13 14 15 16 17 18 20
---------------------------------------------------------------------------
Magic Users New Damage Table. The damage listed by each spell shows how
much damage can be given by using 100 mana points at the apropriate level.
To make it worth-while to learn new damaging spells, a spell which is
"overlapped" by a new spell will give less damage than the exact calculated
average.
Spell 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Mag Mis 6 10 16 18 32 45 " " " " " " " " " " " " " "
Chill* 16 22 34 47 76 93 " " " " " " " " " " " "
Burn Han 37 51 79 96 112 132 " " " " " " " " " "
Shock 82 100 115 135 151 174 " " " " " " " "
Lightb 118 138 154 177 225 251 " " " " " "
Spray 157 180 229 255 280 310 " " " "
Energy 11 17 22 28 33 39 39 39(11)
Fireb 285 315 350 386 427 495
*Chill Touch may reduce STR by -1 when failing saving throw.
Clerics
Spell 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Earthq *
Dispel Evil *
Call Lightn X
Harm X
Dispel Evil is special (0..100) (7 Max)
Earthquake is special (7 Max)
Call Lightning is special (7 Max)
Harm is fairly special (3 Max)
*** NEW *** Spell listing By Level and Class
LEVEL Magic User Cleric
(1) Magic Missile (1) Armor
(1) Ventriloquate (1) Cure Light
(2) Detect Magic (2) Create Water
(2) Detect Invisible (2) Detect Poison
(3) Chill Touch (3) Create Food
(3) - (3) Detect Magic
(4) Invisibility (4) Cure Blind
(4) - (4) Detect Evil
(5) Burning Hands (5) Bless
(5) Armor (5) Detect Invisible
(6) Locate Object (6) Blindness
(6) - (6) Protection from Evil
(7) Shocking Grasp (7) Earthquake
(7) Strength (7) Sense Life
(8) Blindness (8) Summon
(8) Teleport with Error (8) Poison
(9) Lightning Bolt (9) Cure Critic
(9) - (9) Remove Poison
(10) Control Weather (10) Locate Object
(10) - (10) Dispel Evil
(11) Color Spray (11) Word of Recall
(11) - (11) -
(12) Enchant Weapon (12) Call Lightning
(12) Curse (12) Remove Curse
(13) Energy Drain (13) Control Weather
(13) - (13) Sanctuary
(14) Sleep (14) Heal
(14) Charm Person (14) -
(15) Clone (15) Harm
(15) Fireball (15) -

View File

@ -0,0 +1,85 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
OUT OF DATE I THINK (MS)
Description of affected_type structure:
struct affected_type
{
byte type; /* The type of spell that caused this */
byte duration; /* For how long its effects will last */
byte modifier; /* This is added to apropriate ability */
byte location; /* Tells which ability to change(APPLY_XXX)*/
long bitvector; /* Tells which bits to set (AFF_XXX) */
struct affected_type *next;
};
The type is set to the constants defined in spells.h. These are any of
SPELL_XXX, ei. SPELL_ARMOR.
Duration will be decreased at each time update.
Location is determined by the APPLY_XXX, ei. APPLY_STR to change strength.
Modifier will be added to the apropriate APPLY_XXX
Bitvector will set bits in the char_data->char_special_data.affected_by
---------------------------------
Description of handler.c routines:
void affect_location_apply ( struct char_data *ch,
struct affected_type *af, int type);
/* This procedure will (depending on type) Apply or Remove a characters */
/* special bonus to abilities, which have been gained by spells */
When Type is 1, Modifier will be added to an ability, and Bitvector will
set bits in the "char_data->char_special_data.affected_by" bitvector. When
Type == 0, Modifier is subtracted, and bits are removed.
void affect_to_char( struct char_data *ch, struct affected_type *af )
This procedure allocates new memory for an affected_type structure, and
inserts a copy of "*af" in the char_data->affected linked list. After
insertion, the "affect_location_apply" is called, with type == 1.
void affect_remove( struct char_data *ch, struct affected_type *af )
This procedure is the reverse of affect_to_char. Upon calling "af" MUST
point to the structure(element) in the linked list that is to be removed.
If not, the program will do an "exit()". Memory used is released, and
"affect_location_apply" is called, with type == 0.
BEWARE! Some spells may have several structures, since they must change
more than one attribute! Calling affect_from_char does not mean that you
have removed every occurence of a certain spell. But you can be sure that
bits are masked out! Use affect_from_char below.
---------------------------------
void affect_from_char( struct char_data *ch, byte skill )
This fixes the warning above, by calling affect_remove with every
structure that has same spelltype set as skill.
bool affected_by_spell( struct char_data *ch, byte skill )
This procedure will check if a character is affected by a spell (the
SPELL_XXX constants are used). Returns FALSE if not, otherwise TRUE.

View File

@ -0,0 +1,12 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
Time of DikuMud
DikuMud has 7 days per week
35 days per month
17 months per year
DikuMud time is 48 times faster than the real time. One hour of game
time passes every 75 seconds of real time.

View File

@ -0,0 +1,219 @@
/**************************************************************************
* Copyright (C) 1993 - see 'license.doc' for complete information. *
* Jeremy Elson; 7/12/93 *
**************************************************************************/
CIRCLEMUD UTILITIES
"utils.doc"
There are currently 12 utilities and several shell scripts which come with
CircleMUD to help you run and maintain it. This file documents them.
Brief Synopsis
--------------
AUTOWIZ Automatically generate a wizlist and an immlist from the
playerfile.
DELOBJS Delete the object files (i.e. crash-save, rent, cryo-rent,
etc.) of players who no longer exist in the playerfile.
HASMAIL Return an exit status of 0 or 1, depending on if the
recipient specified has MUDmail waiting or not.
LISTRENT Show the contents of one of more object files.
MAILINDEX Generate a list of all mail contained in a mail file.
MUDPASSWD Change the password of a MUD character in a playerfile.
PURGEPLAY Create a new playerfile with deadweight characters removed.
READMAIL Print mail contained in a mail file.
SHOWPLAY List players contained in a playerfile.
SIGN Present a sign on a port (i.e. "MUD will be down today").
SPLIT Split a large file into several smaller files.
SYNTAX_CHECK Check the syntax of a set of world files.
Detailed Documentation
----------------------
AUTOWIZ
Autowiz is not really meant to be run by a person; the MUD automatically
executes it every time someone reaches immortality or is promoted to an
immort or higher level.
It must be compiled and in the circle/bin directory in order for the
automatic wizlist system to work, of course.
DELOBJS
delobjs <playerfile> <file1> <file2> <filen>
Delobjs generates an index of all players in the playerfile, then checks
each file listed on the command line to make sure that the object file
has a corresponding player in the player index. If the player does not
exist, the object file is deleted.
Although this program can be run manually, it is much easier simply to
use the "purgeobjs" script in the lib/plrobjs directory. That script
will automatically run delobjs on every file in each of the 5 object
directory, and save a list of the files deleted to a file called DELETED.
LISTRENT
listrent <file1> <file2> ... <filen>
Listrent will simply list the contents of an object save file. You can
list as many files as you like on the command line; the contents of each
file will be listed.
Included in the lib/plrobjs directory is a script called 'searchfor', which
you can use to see who in the game has certain items. For example, if you
wanted to see who had object #3001 rented, you would switch into the
lib/plrobjs directory and type "searchfor 3001".
HASMAIL
hasmail <mail-file> <recipient-name>
Hasmail has no output -- it just returns a 0 or 1, depending on if you
have mail waiting or not. It's useful for putting something like this
in your .login (assuming you use csh):
set NAME = ras
if ( { hasmail ~/circle/lib/misc/plrmail $NAME } ) then
echo "You have mud-mail waiting."
endif
MAILINDEX and READMAIL
CircleMUD's mail files are binary files -- they can't be read with 'cat',
'more', etc. The MAILINDEX and READMAIL commands allow you to see the
contents of a mail file.
Obviously, there are a lot of serious privacy issues which go along with
programs like this. For exactly that reason, I didn't even write these
utilities for months after I wrote the mail system. I eventually broke
down and wrote them because there is no way to save Mudmail after you've
read it from within the MUD, but READMAIL allows you to do just that --
read your mail without deleting it.
As a footnote, the MUDmail system was intentionally designed so that
one is not able to save mail after having read it. I have a tendency
to save all of my (real) email, as do many other people, and I didn't
want hundreds of mud players to start saving all their MUDmail at the
expense of my disk.
Now that I've loaded these utilities with excessive moral baggage, I'll
describe how they are used.
mailindex <mailfile>
readmail <mailfile> <recipient-name>
MAILINDEX will show you a list of all letters currently in the mail file,
in the following format:
Recipient 1
Sender 1
[...]
Sender n
Recipient 2
Sender 1
[...]
Sender n
[...]
Recipient m
Sender 1
[...]
Sender n
READMAIL will show you all mail addressed to the recipient you specify.
MUDPASSWD
mudpasswd <playerfile> <character> <new-password>
MUDPASSWD is used to change the password of a character in the playerfile.
It can be done while the game is running, but "set passwd" from within the
game is probably safer.
MUDPASSWD is useful for people who forget their passwords, etc. SET PASSWD
does the same thing.
PURGEPLAY
purgeplay <playerfile-name>
PURGEPLAY will read all the characters in the playerfile you specify, and
output a new playerfile called 'players.new', with "deadweight" characters
removed. The original playerfile will not be changed. Characters meeting
one or more of the following criteria will not be included in players.new:
- Buggy characters (i.e., non-alphabetic name or invalid level)
- Characters with a DELETED flag
- Level 0 characters (connected but never entered game)
- If a character is NOT cryo-rented, the following timeouts apply:
- Level 1 characters who have not played in 4 days
- Level 2-4 characters who have not played in 7 days
- Level 5-10 characters who have not played in 30 days
- Level 11-30 characters who have not played in 60 days
- Level 31 characters who have not played in 90 days
- If a character IS cryo-rented, the timout for levels 1-31 is 90 days.
- A CHARACTER WITH A NODELETE FLAG WILL NOT BE REMOVED, even if
the character meets one or more of the above criteria.
PURGEPLAY will generate a report of all characters which were not included
in players.new and the reason for their omission.
SIGN
sign <filename | '-'> <port #>
SIGN is used for putting a message on a port, i.e., "BazookaMUD is currently
down for repairs." The second argument can either be the name of a text
file or a dash; if it is a dash, SIGN will prompt you for the sign text.
Port # is, of course, the port on which you'd like the sign to be displayed.
SPLIT
Split reads text files from standard input and writes a series of files
to disk as output. Its intended usage it to take a large diku world
file and split it into several smaller, more managable files. You'll
probably only need to use it if you're porting a large world file from
some other MUD to Circle.
To use SPLIT, insert a line containing only "=filename" at each point
in the original file where you'd like SPLIT to start writing to a
new file. When SPLIT reaches a line starting with '=', it will begin
writing all subsequent lines to a file called 'filename' until the next
'=' or EOF is encountered. #99999 is appended to the end of each file.
A file called 'index' is created, containing a list of all files which
were created (see running.doc for more information about index files.)
SYNTAX_CHECK
syntax_check <zone number>
Syntax_check is a utility for checking that world files are formatted
correctly. It should be run from the main lib/world directory. If you
type 'syntax_check 30', it will check the files wld/30.wld, obj/30.obj,
mob/30.mob, and zon/30.zon.

View File

@ -0,0 +1,312 @@
/* ************************************************************************
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
ITEM VALUE DOCUMENTATION
"values.doc"
These values are used, as illustrated below, with the different
item types. The various item types are shown in dbsup.doc.
ITEM_LIGHT (1)
Value[0]: Not Used
Value[1]: Not Used
Value[2]: Number of hours the light can be used for. Zero hours means that
the light has gone out. A negative number will create an eternal
light source.
Value[3]: Not Used
ITEM_SCROLL (2)
Value[0]: Level of the spell on the scroll.
Value[1]: Which spell (see list somewhere around the end of file)
Value[2]: Which spell
Value[3]: Which spell
The values(1-3) are three (or less) different spells, mixed 'on' the scroll.
Unused spells should be set to -1.
ITEM_WAND (3)
Value[0]: Level of spell in wand.
Value[1]: Max Charges (1..X)
Value[2]: Charges Left
Value[3]: Which spell in wand (see list somewhere around the end of file)
ITEM_STAFF (4)
Value[0]: Level of spell in staff.
Value[1]: Max Charges (1..X)
Value[2]: Charges Left
Value[3]: Which spell in staff (see list somewhere around the end of file)
ITEM_WEAPON (5)
Value[0]: Not Used
Value[1]: Number of dice to roll for damage
Value[2]: Size of dice to roll for damage
Value[3]: The weapon type. Type is one of:
NUMBER CATEGORY Message type
2 : Slash "whip/whips"
3 : Slash "slash/slashes"
6 : Bludgeon "crush/crushes"
7 : Bludgeon "pound/pounds"
11 : Pierce "pierce/pierces"
New types can be added as needed.
ITEM_FIREWEAPON (6)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_MISSILE (7)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_TREASURE (8)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_ARMOR (9)
Value[0]: The effective AC. >0 enhances the armour class. <0 reduces the
the armour class (cursed armour for example).
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_POTION (10)
Value[0]: Level of the spell in the potion.
Value[1]: Which spell (Listed elsewhere in this file)
Value[2]: Which spell
Value[3]: Which spell
The values(1-3) are three (or less) different spells, mixed in the potion.
Unused spells should be set to -1.
Eg.
Value 0 : 30 (Level)
Value 1 : 27 (Harm)
Value 2 : 17 (Curse)
Value 3 : 4 (Blindness)
(* Don't drink this - It's bad for your health! *)
ITEM_WORN (11)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_OTHER (12)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_TRASH (13)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_TRAP (14)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_CONTAINER (15)
Value[0]: Maximum weight the container can contain.
Value[1]: Container flags:
CLOSEABLE 1
PICKPROOF 2
CLOSED 4
LOCKED 8
Value[2]: The item-number of the object which can open the object. -1 means
no lockability.
Value[3]: Internal use for Corpses that must "rot".
ITEM_NOTE (16)
Value[0]: Tounge (language of writing). Not yet used.
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_DRINKCON (17)
Value[0]: Maximum drink-units the drink-container can contain.
Value[1]: Number of drink-units that are left in the container.
Value[2]: The type of liquid in the drink-container, one of:
Type nr. Effect
Drunkness Fullness Thirst
LIQ_WATER 0 0 1 10
LIQ_BEER 1 3 2 5
LIQ_WINE 2 5 2 5
LIQ_ALE 3 2 2 5
LIQ_DARKALE 4 1 2 5
LIQ_WHISKY 5 6 1 4
LIQ_LEMONADE 6 0 1 8
LIQ_FIREBRT 7 10 0 0
LIQ_LOCALSPC 8 3 3 3
LIQ_SLIME 9 0 4 -8
LIQ_MILK 10 0 3 6
LIQ_TEA 11 0 1 6
LIQ_COFFE 12 0 1 6
LIQ_BLOOD 13 0 2 -1
LIQ_SALTWATER 14 0 1 -2
LIQ_CLEARWATER 15 0 0 13
The above values for drunkness/fullness/thirst are used per
four "units" drunk. The values are expressed in HOURS!
Example:
Dragon empties a bottle (say 7 units) of saltwater.
His Drunkness is not changed ((7/4)*0)
His Fullness increases by ((7/4)*1) hours
His Thirst increases by ((7/4)*-2) hours, thus making
him More thirsty.
The hours above are numbers between 0 and 24. 24 hours is
maximum for drunkness/fullness/thirst. When hours are zero
for any drunkness/fullness/thirst the person will be
sober, hungry, or thirsty respectively.
Value[3]: if this value is non-zero, then the drink is poisoned.
ITEM_KEY (18)
Value[0]: The key-type. This value must match the lock-type the door
that the key can open.
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_FOOD (19)
Value[0]: The number of hours, that this food will fill the stomach
Value[1]: -
Value[2]: -
Value[3]: If this value is non-zero, the food is poisoned.
ITEM_MONEY (20)
Value[0]: The number of gold coins "in the pile of coins".
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_PEN (21)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_BOAT (22)
Value[0]: -
Value[1]: -
Value[2]: -
Value[3]: -
ITEM_FOUNTAIN (23)
Value[0]: Maximum drink-units the drink-container can contain.
Value[1]: Number of drink-units that are left in the container.
Value[2]: The type of liquid in the drink-container; definitions
are the same as for ITEM_DRINKCON.
Value[3]: Drink is posioned if non-zero.
-------------------------------------------------------------------------
IMPORTANT NOTICE!!
Since the level versus average damage calculations are performed as shown
in "spell_info.doc" all the offensive spells are individually much stronger
than higher level spells. For example:
1 fireball of level 15 gives more damage than one of level 16 which give
more damage than level 17 which give more damage than level 18 which
give more.... etc.
Thus please make all offensive potions/scrolls/etc. as the basic level
they are designed for. You can see the level below. You can see the spells
average damage, by looking at the spell versus the level of the spell,
divided by the number of spells learned at that particular level. Example:
Level 9 Lightning bolt give (102/2) average damage. Divided by 2, because
this is the level at which it is first learned (You can almost
always cast two spells are first learned level). At level 10 it
gives (120/3) average damage.
Looking at the table in "spell_info.doc", you should know that each spell
is designed so that it will kill a victim three levels below the mana user,
if the manauser ONLY cast his spell....
-------------------------------------------------------------------------
The Y/N rows below indicate which potions/scrolls/wands/staffs that are
possible to make. The MIN_LEV is the Minimum Level DEMANDED by the item
you are making. The game will crash if making level less than demanded.
-------------------------------------------------------------------------
POTION SCROLL WAND STAFF MIN_LEV
TYPE_UNDEFINED -1 Y Y Y Y -
SPELL_RESERVED_DBC 0 N N N N -
SPELL_ARMOR 1 Y Y Y N >0
SPELL_TELEPORT 2 Y Y Y Y >0
SPELL_BLESS 3 Y Y Y N ...
SPELL_BLINDNESS 4 Y Y Y Y
SPELL_BURNING_HANDS 5 N N N N == 5
SPELL_CALL_LIGHTNING 6 Y Y N Y >=12
SPELL_CHARM_PERSON 7 N Y N Y
SPELL_CHILL_TOUCH 8 N N N N == 3
SPELL_CLONE 9 Y Y Y N
SPELL_COLOUR_SPRAY 10 N Y Y N ==11
SPELL_CONTROL_WEATHER 11 N N N N
SPELL_CREATE_FOOD 12 N Y N N
SPELL_CREATE_WATER 13 N N N N
SPELL_CURE_BLIND 14 Y N N Y
SPELL_CURE_CRITIC 15 Y N N Y
SPELL_CURE_LIGHT 16 Y N N Y
SPELL_CURSE 17 Y Y N Y
SPELL_DETECT_EVIL 18 Y N N Y
SPELL_DETECT_INVISIBLE 19 Y N N Y
SPELL_DETECT_MAGIC 20 Y N N Y
SPELL_DETECT_POISON 21 Y Y N N
SPELL_DISPEL_EVIL 22 Y Y Y Y == 10
SPELL_EARTHQUAKE 23 N Y N Y == 7
SPELL_ENCHANT_WEAPON 24 N Y N N
SPELL_ENERGY_DRAIN 25 Y Y Y Y == 13
SPELL_FIREBALL 26 N Y Y N == 15
SPELL_HARM 27 Y N N Y == 15
SPELL_HEAL 28 Y N N Y
SPELL_INVISIBLE 29 Y Y Y Y
SPELL_LIGHTNING_BOLT 30 N Y Y N == 9
SPELL_LOCATE_OBJECT 31 N N N N
SPELL_MAGIC_MISSILE 32 N Y Y N == 1
SPELL_POISON 33 Y N N Y
SPELL_PROTECT_FROM_EVIL 34 Y Y Y Y
SPELL_REMOVE_CURSE 35 Y Y N Y
SPELL_SANCTUARY 36 Y Y N Y
SPELL_SHOCKING_GRASP 37 N N N N == 7
SPELL_SLEEP 38 Y Y Y Y
SPELL_STRENGTH 39 Y Y N Y
SPELL_SUMMON 40 N N N N
SPELL_VENTRILOQUATE 41 N N N N
SPELL_WORD_OF_RECALL 42 Y Y Y Y
SPELL_REMOVE_POISON 43 Y N N Y
SPELL_SENCE_LIFE 44 Y N N Y
SPELL_IDENTIFY *53* N Y N N

BIN
old-codebase/doc/act.pdf Normal file

Binary file not shown.

BIN
old-codebase/doc/admin.pdf Normal file

Binary file not shown.

Binary file not shown.

BIN
old-codebase/doc/coding.pdf Normal file

Binary file not shown.

BIN
old-codebase/doc/color.pdf Normal file

Binary file not shown.

BIN
old-codebase/doc/files.pdf Normal file

Binary file not shown.

BIN
old-codebase/doc/hacker.pdf Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,239 @@
/* ************************************************************************
* Copyright (C) 1995 by Jeremy Elson *
* All Rights Reserved *
************************************************************************ */
CircleMUD License
CircleMUD was created by:
Jeremy Elson
Department of Computer Science
Johns Hopkins University
Baltimore, MD 21218 USA
jelson@circlemud.org
CircleMUD is licensed software. This file contains the text of the CircleMUD
license. If you wish to use the CircleMUD system in any way, or use any of
its source code, you must read this license and are legally bound to comply
with it.
CircleMUD is a derivative work based on the DikuMUD system written by Hans
Henrik Staerfeldt, Katja Nyboe, Tom Madsen, Michael Seifert, and Sebastian
Hammer. DikuMUD is also licensed software; you are legally bound to comply
with the original DikuMUD license as well as the CircleMUD license if you
wish to use CircleMUD.
Use of the CircleMUD code in any capacity implies that you have read,
understood, and agreed to abide by the terms and conditions set down by this
license and the DikuMUD license. If you use CircleMUD without complying with
the license, you are breaking the law.
Using CircleMUD legally is easy. In short, the license requires three things:
1) You must not use CircleMUD to make money or be compensated in any way.
2) You must give the authors credit for their work.
3) You must comply with the DikuMUD license.
That's it -- those are the main conditions set down by this license.
Unfortunately, past experience has shown that many people are not willing
to follow the spirit of the license, so the remainder of this document will
clearly define those conditions in an attempt to prevent people from
circumventing them.
The first condition says that you must not use CircleMUD to make money in
any way or be otherwise compensated. CircleMUD was developed in people's
uncompensated spare time and was given to you free of charge, and you must
not use it to make money. CircleMUD must not in any way be used to
facilitate your acceptance of fees, donations, or other compensation.
Examples include, but are not limited to the following:
-- If you run CircleMUD, you must not require any type of fee or donation
in exchange for being able to play CircleMUD. You must not solicit,
offer or accept any kind of donation from your players in exchange for
enhanced status in the game such as increased levels, character stats,
gold, or equipment.
-- You must not solicit or accept money or other donations in exchange for
running CircleMUD. You must not accept money or other donations from
your players for purposes such as hardware upgrades for running
CircleMUD.
-- You must not sell CircleMUD. You must not accept any type of fee in
exchange for distributing or copying CircleMUD.
-- If you are a CircleMUD administrator, You must not accept any type of
reimbursement for money spent out of pocket for running CircleMUD, i.e.,
for equipment expenses or fees incurred from service providers.
The second part of the license states that you must give credit to the
creators of CircleMUD. A great deal of work went into the creation of
CircleMUD, and it was given to you completely free of charge; claiming that
you wrote the MUD yourself is a slap in the face to everyone who worked to
bring you a high quality product while asking for nothing but credit for
their work in return.
Specifically, the following are required:
-- The text in the 'credits' file distributed with CircleMUD must be
preserved. You may add your own credits to the file, but the existing
text must not be removed, abridged, truncated, or changed in any way.
This file must be displayed when the 'credits' command is used from
within the MUD.
-- The "CIRCLEMUD" help entry must be maintained intact and unchanged, and
displayed in its entirety when the 'help circlemud' command is used.
-- The login sequence must contain the names of the DikuMUD and CircleMUD
creators. The 'login sequence' is defined as the text seen by players
between the time they connect to the MUD and when they start to play
the game itself.
-- This license must be distributed AS IS with all copies or portions of
the CircleMUD that you distribute, if any, including works derived from
CircleMUD.
-- You must not remove, change, or modify any notices of copyright,
licensing or authorship found in any CircleMUD source code files.
-- Claims that any of the above requirements are inapplicable to a particular
MUD for reasons such as "our MUD is totally rewritten" or similar are
completely invalid. If you can write a MUD completely from scratch then
you are encouraged to do so by all means, but use of any part of the
CircleMUD or DikuMUD source code requires that their respective licenses
be followed, including the crediting requirements.
The third part of the license simply states that you must comply with the
DikuMUD license. This is required because CircleMUD is a DikuMUD derivative.
The DikuMUD license is included below.
You are allowed to use, modify and redistribute all CircleMUD source code
and documentation as long as such use does not violate any of the rules
set down by this license.
--Jeremy Elson
CircleMUD 3 -- Copyright (C) 1994-2001, The CircleMUD Group
Other portions copyright by authors as noted in ChangeLog and source code.
===========================================================================
Everything below this line is the original, unmodified DikuMUD license.
You must comply with the CircleMUD license above, as well as the DikuMUD
license below.
---------------------------------------------------------------------------
/* ************************************************************************
* Copyright (C) 1990, 1991 *
* All Rights Reserved *
************************************************************************* */
DikuMud License
Program & Concept created by
Sebastian Hammer
Prss. Maries Alle 15, 1
1908 Frb. C.
DENMARK
(email quinn@freja.diku.dk)
Michael Seifert
Nr. Soeg. 37C, 1, doer 3
1370 Copenhagen K.
DENMARK
(email seifert@freja.diku.dk)
Hans Henrik St{rfeldt
Langs} 19
3500 V{rl|se
DENMARK
(email bombman@freja.diku.dk)
Tom Madsen
R|de Mellemvej 94B, 64
2300 Copenhagen S.
DENMARK
(email noop@freja.diku.dk)
Katja Nyboe
Kildeg}rdsvej 2
2900 Hellerup
31 62 82 84
DENMARK
(email katz@freja.diku.dk)
This document contains the rules by which you can use, alter or publish
parts of DikuMud. DikuMud has been created by the above five listed persons
in their spare time, at DIKU (Computer Science Instutute at Copenhagen
University). You are legally bound to follow the rules described in this
document.
Rules:
!! DikuMud is NOT Public Domain, shareware, careware or the like !!
You may under no circumstances make profit on *ANY* part of DikuMud in
any possible way. You may under no circumstances charge money for
distributing any part of dikumud - this includes the usual $5 charge
for "sending the disk" or "just for the disk" etc.
By breaking these rules you violate the agreement between us and the
University, and hence will be sued.
You may not remove any copyright notices from any of the documents or
sources given to you.
This license must *always* be included "as is" if you copy or give
away any part of DikuMud (which is to be done as described in this
document).
If you publish *any* part of dikumud, we as creators must appear in the
article, and the article must be clearly copyrighted subject to this
license. Before publishing you must first send us a message, by
snail-mail or e-mail, and inform us what, where and when you are
publishing (remember to include your address, name etc.)
If you wish to setup a version of DikuMud on any computer system, you
must send us a message , by snail-mail or e-mail, and inform us where
and when you are running the game. (remember to include
your address, name etc.)
Any running version of DikuMud must include our names in the login
sequence. Furthermore the "credits" command shall always cointain
our name, addresses, and a notice which states we have created DikuMud.
You are allowed to alter DikuMud, source and documentation as long as
you do not violate any of the above stated rules.
Regards,
The DikuMud Group
Note:
We hope you will enjoy DikuMud, and encourage you to send us any reports
on bugs (when you find 'it'). Remember that we are all using our spare
time to write and improve DikuMud, bugs, etc. - and changes will take their
time. We have so far put extremely many programming hours into this project.
If you make any major improvements on DikuMud we would be happy to
hear from you. As you will naturally honor the above rules, you will receive
new updates and improvements made to the game.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,612 @@
\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 <furry@circlemud.org> on Dec 9/2001
\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}{0pt}
\title{Frequently Asked Questions (FAQ) for CircleMUD with Answers}
\author{Alex Fletcher\\
\texttt{$<$furry@circlemud.org$>$}}
\begin{document}
\maketitle
\begin{abstract}
This file is intended to cover common questions related to the CircleMUD distribution source by
Jeremy Elson \url{<http://www.circlemud.org/~jelson/>} and not general DikuMud questions. Any contributions and corrections are more than welcome. It is currently maintained by Alex Fletcher (aka Furry) \url{<furry@circlemud.org>} Please direct corrections to this address. The original author was Ryan Watkins (aka VampLestat).\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{<http://www.circlemud.org/>} or the FTP site \url{<ftp://ftp.circlemud.org/pub/CircleMUD/>}.
\end{abstract}
\tableofcontents
\section{Introduction}
\subsection{I've never played a MUD before. What should I do?}
Do not try to use your own copy of CircleMUD! There are two levels of MUD users: players and administrators. Administrators do what you're trying to do now -- get a copy of a MUD's source code, compile it, and run it. Players use MUDs that are being administered by someone else. If you try to actually run a MUD before you've ever played one, you'll get very confused indeed! Your best bet for now is to play someone else's MUD first. There are a large number of excellent MUDs out there already, some of which are based on CircleMUD code. A good place to start looking is the Mud Connector \url{<http://www.mudconnect.com/>}. The CircleMUD web server also has a smaller CircleMUD Site List \url{<http://www.circlemud.org/sites.shtml>}.
\subsection{I'm new to C and/or coding. What do I do?}
First, a Mud is not a learning project. It has thousands of lines to it many of which are obscure and unclear to even moderately skilled programmers. Those little, ``Hello, world,'' programs are for learning, maybe little math tests, etc. A Mud is a pretty ambitious project to start with. That is like trying to run before you can walk, and while there's more difficult things than a mud to start with, there's a ton of easier things you should start with.
\par
Second, if you are persistent, get a good C reference book and read the code, try to comprehend what everything is doing (to some small extent). You should probably avoid \texttt{comm.c} as it is home to the socket functions which general C books don't cover and are usually explained in other books on network programming.
For some good resources to learn C, see Question 18.9 in the C FAQ \url{<http://www.eskimo.com/~scs/C-faq/top.html>}.
\par
Third, try small projects, something similar to what already exists. This way, you can get away with a cut-and-paste job and changing some of the code. Adding a simple version of races is not all that difficult, just examine the class code in \texttt{class.c} and the \texttt{CON\_QCLASS} block in \texttt{interpreter.c}, cut, paste, and modify. Also look at \texttt{structs.h}, for \texttt{\#define CLASS\_} You'll begin understanding more and more of the code as you copy and change it, eventually you'll be able to write a whole function by yourself. Spend time learning, going with haste will hurt you more than it will help you.
\par
Remember that if you attempt to run a mud without knowing how to program in C, you will fail. Your mud will remain a stock mud, your friends will not play, and you will annoy off anyone you ask for help when you repeatedly show no drive to learn how to do it yourself.
\subsection{I want to build my own mud. Where do I start?}
Many common questions arise from new mud admins. It is a good idea to pay attention to them and take their answers to heart. These include things like the following:
\par
{\em I don't have any coding experience with MUDs, but do have a lot of ideas for my own. I have played many MUDs for a LONG time, though.}
\par
Read the FAQ. Mud Experience doesn't help a huge amount. Code experience does.
\par
{\em I am interested in having a level system of 1-50 mortal and 51-60 imms. I am also interested in adding races and classes. How can I accomplish these things?}
\par
By checking the FTP Site under the contrib tree \url{<ftp://ftp.circlemud.org/pub/CircleMUD/contrib/>}. Learn a lot from there. Especially the \texttt{code/} subdirectory. Above all, {\em know} the FAQ.
\par
{\em Also, is there anything that I should know about CircleMUD being a ``newbie'' to it?}
\par
See the above comment.
\subsection{What is CircleMUD?}
CircleMUD is a DikuMud derivative, developed by Jeremy Elson \url{<jelson@circlemud.org>}
and is from the Gamma v0.0 of DikuMud created by Hans Henrik Staerfeldt, Katja Nyboe, Tom
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 {\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. 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}
\item Version 2.00: July 16, 1993
\item Version 2.01: July 20, 1993
\item Version 2.02: Early August
\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}
\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{<http://www.circlemud.org/sites.shtml>}.
\subsection{What is UNIX?}
UNIX is not an operating system of itself, it's a type (flavour, if you will) of operating systems. Many different kinds of UNIXes exist. Some of them are free, some of them are not. How to tell if you have a UNIX operating system? Well, UNIXes have the `ps' command, tend to have a `\%' or `\#' prompt, give you a home directory, `who' will show who else is on the system, etc. Many UNIX systems (such as Linux) strive to be POSIX compatible, so you'll probably see POSIX mentioned, too. POSIX is, roughly, the standards which UNIX operating systems go by. It says what makes an operating system part of the UNIX family and so forth. Some UNIX operating systems are not 100\% POSIX compatible, actually, most aren't. The following are types of UNIX (but not all the existing flavours): Linux, FreeBSD, BSD, BSDi, Solaris. There are others. UNIX operating systems are command-based and Microsoft does not make a variant.
\section{Resources}
\subsection{Where do I find the source code for CircleMUD?}
Circle's complete source code and areas are available for anonymous FTP at the CircleMUD FTP site \url{<ftp://ftp.circlemud.org/pub/CircleMUD/>}. There is also a CircleMUD homepage \url{<http://www.circlemud.org/>} for more CircleMUD information. The Ceramic Mouse \url{<http://developer.circlemud.org/>} presents an alternate interface to the FTP site.
\par
If you cannot use FTP or interact with the FTP server using Ceramic Mouse, you can contact one of the site maintainers \url{<circleftp@circlemud.org>} and request a file.
\subsection{Where do I find areas, etc. for CircleMUD?}
A number of CircleMUD based Implementors have submitted areas to the public and they are
archived at the same site as the CircleMUD source \url{<ftp://ftp.circlemud.org/pub/CircleMUD/contrib/areas/>}. There used to be a separate Code Snippet site, but that has since be rolled into the main FTP server to present everything in one central location.
\subsection{I have questions about CircleMUD. Where should I go?}
If you have general questions about the MUD such as how to get it running, how to add new spells, how to add new skills, etc., the first place you should look is the documentation. `coding.doc' will have information about how to add new spells, skills, commands, etc. `building.doc' has
information about how to create new worlds, how to read the database files, etc. There are many other documents in the doc directory with useful information.
\par
There is also a new project, started in June of 1996, called the CircleMUD Documentation Project \url{<http://www.circlemud.org/cdp/>} which will eventually be a repository for all Circle-related information. It is still being built as of this writing, but hopefully will become a valuable resource as more documentation is added.
\par
If you still have questions {\em after} reading the documentation, you can try asking on the CircleMUD mailing list (see next section).
\par
If you have a question you think is too ``newbie'' for the mailing list, try the help database \url{<http://bugs.circlemud.org/>}. You can ask questions by sending mail to the help administrators \url{<help@circlemud.org>}. The webpage database is also, incidentally, where you should go to report bugs (also done by sending mail \url{<bugs@circlemud.org>}).
\subsection{So, what's this about a mailing list?}\label{mailinglist}
There is a CircleMUD mailing list for coders, builders, and administrators. This list is for the discussion of CircleMUD, and not a place to learn C.
\par
To subscribe, send a message to the list server \url{<listserv@post.queensu.ca>} with a message body of \texttt{subscribe circle $<$first name$>$ $<$last name$>$}.
\par
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{<http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html>} for more information.
\subsection{To what platforms has CircleMUD been ported?}
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.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
Jean-Jack Riethoven \url{<J.J.M.Riethoven@ab.agro.nl>} ported CircleMUD version 2.20 to the Amiga and has contributed his code for version 3.0 of CircleMUD. Questions about the Amiga source should be directed to Jean-Jack Riethoven, not the CircleMUD group.
\subsection{How can I submit code or areas for use with CircleMUD?}
There is a special uploads area \url{<ftp://upload.circlemud.org/pub/CircleMUD/incoming>}
on the CircleMUD ftp server for submissions of code, areas, utilities, scripts, and anything else that might be of use to CircleMUD users. When uploading anything, you should be certain to send a piece of email to the site maintainers \url{<circleftp@circlemud.org>} indicating what you uploaded, what it is, and where it should be placed. These portions of code or areas will probably not be added to the full release of CircleMUD unless you make specific arrangements with the CircleMUD group.
\subsection{How do I use a patch file and how can I make one?}\label{patchfile}
Patch files are created and used using the ``diff'' and ``patch'' utilities, respectively. They can both be downloaded from the GNU FTP site \url{<ftp://ftp.gnu.org/pub/gnu/>} under the name ``diffutils-xxx.tar.gz''. There is also a port of these utilities for Microsoft Windows now available from the
Cygnus GNU Win32 Project \url{http://sourceware.cygnus.com/cygwin/}.
\par
These are the various parameters to use with \texttt{diff} (all work in general on unix based systems, but check out the help entries to be certain.
\begin{verbatim}
diff -wuprN [original_src_directory] [altered_src_directory] > Patch
\end{verbatim}
\texttt{-w} tells the output to ignore differences in spacing on the same line.\newline
\texttt{-u} is the unified output. ie. it tells diff to output the text what is called ``patch'' style. On some systems, you will have to use \texttt{-c} but it generates much larger and harder to follow patches.\newline
\texttt{-p} tells diff to indicate what function is being ``patched'' in each section. This may not be supported by all versions of ``diff.''\newline
\texttt{-r} is recursive, add r to the uN above if you want it to recursively add in any subdirectories. (be careful with this one)\newline
\texttt{-N} tells diff to treat files that are in one directory and not there in the other as being empty in the one they are not there. It allows entire files to be included into the patch.\newline
See the manpage for \texttt{diff} for other possible options including \texttt{-x} for excluding files.
\par
If you download a patch file and would like to add it to your code, first make sure to read any instructions that the patch author might have written. The command used to add the patch may vary depending on how the patch was created. This should given in the first line of the patch or in the instructions. Normally, if using GNU patch with a unified diff, the command should be:
\begin{verbatim}
patch -u < [patchfile]
\end{verbatim}
If the patch was created with a SYSV patcher (i.e. not a unified diff), the patch should be added with:
\begin{verbatim}
patch -c < [patchfile]
\end{verbatim}
Of course, if the instructions state otherwise, ignore any instructions given here and follow the instructions given with the patchfile instead.\newline
Finally, in modern patches, there are three characters of interest to note:
\begin{itemize}
\item ! : The line changes between new and old.
\item + : This line is added to the old to make the new.
\item - : This line is removed from the old to make the new.
\item The rest of the lines are just there to give you an idea of where to change.
\end{itemize}
\section{Compiling CircleMUD}
\subsection{Why do I get many syntax errors with Sun's/HP-UX's ``cc'' compiler?}
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{<ftp://ftp.gnu.org/pub/gnu/>} 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 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 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''.
\subsection{Every time I try to compile Circle (or any other piece of software) under Linux, it gives me errors and says it cannot find include header files in the \texttt{linux/} and \texttt{asm/} directories. What can I do?}
Under Linux, you cannot compile any program unless you install the kernel source code because the kernel source includes the ANSI C header files. You need the files in \texttt{/usr/include/linux/}, which are distributed separately from the rest of \texttt{/usr/include/}.
\par
If your system does not have them already, you will have to set up your include files manually. The easiest way to get these is to download kernel source from one of the kernel.org mirrors
\url{<http://www.kernel.org/mirrors/>}. Get the kernel source that matches the kernel you're running (type `uname -a' to find your kernel version). Then unpack the kernel into the \texttt{/usr/src/} directory. It is about 20 megabytes compressed, and about 60 megabytes uncompressed.
\par
Read the \texttt{README} file that comes with the kernel, and make the symbolic links you need for \texttt{/usr/include/asm/} and \texttt{/usr/include/linux/}. Now compile the MUD. This will take care of most of the errors. You may have to do `make config' and `make dep' in \texttt{/usr/src/linux/} as well, in order to make \texttt{linux/config.h} and other files that get generated by these steps.
\par
You can remove the whole kernel source tree except for \texttt{include/} at this point and get most of your space back.
\par
(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 ``\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 ``\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.
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?}
\begin{enumerate}
\item Select ``start menu''-$>$``find''-$>$``files or folders''
\item Enter the files/dirs to search in.
\item Select ``Advanced''
\item In the ``Containing Text'' input box, type in the text you want.
\item Double click on a match to bring up the file that matched.
\end{enumerate}
Even better is to use MSVC's find command (if you have it).
\subsection{While compiling the mud, why do I get errors like ``foo.c:1231: Undefined symbol `\_whereamI' referenced from text segment''}
You forgot to include a source file into the make. Go edit your \texttt{Makefile} and make sure all the necessary *.c files are in there, in particular, whichever C file defines the function that the compiler is complaining is undefined. If all else fails, try deleting all the *.o files and recompiling from scratch.
\subsection{What is a parse error and how do I fix it?}
A parsing error is often a missing or extra semicolon, parenthesis, or bracket (\{). If the parse error is before a semicolon at the end of a line of code, it is something on that line. If it is at the beginning of a line within a function, it is usually a missing semicolon on the previous line. If it is at the beginning of a function, count your brackets (especially the \{\} ones) in the previous function. I can't think of any other parse errors. These are the ones I commonly see. With a bit of practice, they are very easy to locate and fix. For a more detailed explanation, check out the C Language FAQ \url{<http://www.eskimo.com/~scs/C-faq/top.html>}.
\subsection{I have this piece of code that calls bcopy(), bzero(), and bcmp() and it won't compile, so what can I do?}
All three of these functions are fairly standard on BSD systems. However, they are not considered to be very portable, and thus should be redefined. For example, the equivalents for SYSV are:
\begin{verbatim}
#define bcopy(from,to,len) memmove(to,from,len)
#define bzero(mem,len) memset(mem,0,len)
#define bcmp(a,b,len) memcmp(a,b,len)
\end{verbatim}
\subsection{My compiler doesn't have ``strdup()'', what can I do?}
Use Circle's built-in \texttt{str\_dup()} function instead.
\subsection{I am having trouble with my ``makefile'', what could be the problem?}
If you used cut and paste to insert items into your makefile, it is likely that you accidentally put spaces at the beginning of lines where tabs are needed. To check the tabs in your makefile, you can issue the \texttt{cat -v -t -e Makefile}, which will show all tabs as \texttt{\^I} and will show a \texttt{\$} at the end of each line to show any terminating white space. This is how the makefile must be constructed:
\begin{verbatim}
foo.o: foo.c conf.h sysdep.h structs.h utils.h interpreter.h \
handler.h db.h
{TAB}$(CC) -c $(CFLAGS)
\end{verbatim}
To add these lines properly, you can use \texttt{gcc} to assist you with the following shell script (from Daniel Koepke):
\begin{verbatim}
#!/bin/sh
gcc -MM $1 >> Makefile
echo "{TAB}\$(CC) -c \$(CFLAGS) $1" >> Makefile
\end{verbatim}
To use this script, replace \texttt{\{TAB\}} with a tab, and then run the script like: \texttt{add\_file foo.c}
\subsection{How can I handle directories in C?}
{\em Note that this seems only to be valid for UNIX OSes.} Handling of directories is accomplished through the \texttt{dirent.h} and \texttt{sys/types.h} files. The function \texttt{opendir()} returns a ``DIR*'' pointer (it's like {\em but not the same as} the ``FILE *'' pointer) when you pass it the name of a directory to open or NULL if it can't open the dir. After the directory has been opened, you can step through the files or search for particular files, etc. using \texttt{readdir()}, \texttt{seekdir()}, and \texttt{scandir()}. When you reach the end of the directory list, you can either go back to the start with \texttt{rewinddir()} or close the directory with \texttt{closedir()}. The following code (which has not been tested) should open a directory and go through it one by one and prints the filenames:
\begin{verbatim}
struct dirent * ffile;
DIR * my_dir;
if (!(my_dir = opendir("foo")))
return;
while (1) {
if (!(dirent = readdir(my_dir)))
break;
printf("%s\n", dirent->d_name);
}
closedir(my_dir);
\end{verbatim}
The dirent structure contains only two useful elements, the file's name (\texttt{d\_name}) and the files length (\texttt{d\_reclen}).\newline
Thanks to Daniel Koepke for the above.
\par
For Windows based machines (the Cygwin tools support the above code), the following code should be used instead:
\begin{verbatim}
#include <io.h>
struct _finddata_t filedata;
long fh;
if( (fh = _findfirst( "*.*", &filedata )) == -1L ) {
printf( "No files in current directory!\n" );
} else {
printf( "Listing of .c files\n\n" );
printf( " %-12s %.24s %9ld\n",filedata.name, ctime( &(
filedata.time_write ) ), filedata.size );
while( _findnext( hf, &filedata ) == 0 ) {
printf( " %-12s %.24s %9ld\n", filedata.name, ctime( &(
filedata.time_write ) ), filedata.size );
}
_findclose(hf)
}
/* note: filedata.attrib is a bitvector;
_A_ARCH has the archive bit set (does nothing)
_A_HIDDEN is hidden
_A_NORMAL nothing to see here
_A_RDONLY is read only
_A_SUBDIR is a directory
_A_SYSTEM is a system file (really does nothing)
..
so if(filedata.attrib & _A_SUBDIR) {
print "File is a directory!\n";
}
*/
\end{verbatim}
Please note that this is the file name without the path. DOS oriented functions do not gracefully or consistently deal with directory options where the directory/file being accessed is not in the current working directory. You'll have to remember what it is! You can try other things .. but it {\em really} does not handle {\em relative} paths well using the \_[system function] set of functions. The whole thing is rather ugly.
\par
Thanks for Patrick Dughi for the above.
\section{Running CircleMUD}
\subsection{I typed ``autorun'' but then my terminal just froze.}
\texttt{autorun} is a script which automatically runs, logs, and reboots the game for long-term runs. You should run autorun in the background by typing ``./autorun \&'' -- the MUD will start running in the background and you'll get the normal UNIX prompt back immediately (see section~\vref{loginprompt}). The game will then run unattended until you explicitly shut it down.
\par
On some systems, you may need to prepend ``nohup'' to the autorun command since some systems will kill off any processes left running when you leave the shell.
\subsection{I typed ``bin/circle'' and got lots of boot messages, but then it said ``Entering game loop'' and froze.}
It is not frozen, it is just waiting for people to connect. You have to run the MUD in the background by typing ``bin/circle \&'' and then use telnet to connect to the game (see next section).
\subsection{Okay, I think the MUD is running but why don't I get a login prompt?}\label{loginprompt}
In order to play the MUD, you must connect to it using the telnet command, i.e. ``telnet localhost 4000''.
\subsection{How come I get this error when running my mud: ``Error reading board: No such file or directory''}
This is not a bad thing, all it means is that you have some boards on the mud and that it can't find the file for them. Since it can't find the file, the mud will just create the file on the fly and use that, so the next time something is posted to the board, the files will exist. However, if you did have files for the boards and you are suddenly getting this error, it means that the board files have been deleted or something similar.
\subsection{I just got this SIGPIPE, what is it and what can I do about it?}
Often it appears that other people send your system SIGPIPEs when their connection is closed, in fact, it is not the person sending the SIGPIPE, it is your system. The SIGPIPE is generated when your program attempts to write to descriptor which has no one listening to it. This occurs if the character is sent a message by the mud after connecting, but before the socket is flagged with an exception or reads 0 bytes. By default, CircleMUD ignores these SIGPIPEs, with the line \texttt{my\_signal(SIGPIPE, SIG\_IGN)} in \texttt{signal\_setup()}. Where most people see the problems with SIGPIPE is while debugging with GDB. By default, GDB responds to a SIGPIPE by stopping the program, printing that a SIGPIPE was received, and passing it to the program. You can change the action taken by GDB by using the `\texttt{handle}' command. To stop the program from stopping at SIGPIPE, you would give GDB the command `\texttt{handle SIGPIPE nostop}'
\subsection{When I run Circle under Linux, it tells me ``gethostbyaddr: connection refused'' when the MUD boots, and then dies. Why?}
You need to make sure you have Networking and TCP/IP support compiled into your Linux kernel, even if you aren't actually connected to the Internet. Generally the default install of Linux supports networking, so if you have done this, double check that the networking is installed as per your specific distribution, and otherwise seek further help from your distribution's official site.
\subsection{When I run Circle under Windows, it tells me ``Winsock error \#10047'' when the MUD boots, and then dies. Why?}
You need to configure TCP/IP networking from the Network Control Panel, even if you are not connected to the Internet. From the Network Control Panel, select ``Add Protocol'', and under the vendor ``Microsoft'', choose ``TCP/IP''. It may ask you to insert your Windows CDROM in order to copy the drivers onto your hard drive.
\subsection{When I run Circle under Windows, players can't rent -- their equipment is just dropped on the ground, syslogs don't work, so what is the problem?}
The reason that objects aren't saved when your players quit is that certain unzip programs are buggy and don't completely recreate the MUD's directory structure (in particular, it doesn't create directories which have no files in them.) This is fixed in Circle 3.0 patchlevel 12 and above. Before patchlevel 12, you can fix it simply by manually creating the needed directories:
\begin{verbatim}
cd \Circle30bpl11
cd lib\plrobjs
mkdir A-E
mkdir F-J
mkdir K-O
mkdir P-T
mkdir U-Z
mkdir ZZZ
\end{verbatim}
Object saving should then work. It is also advised that you look at the {\bf AUTOEQ} option in \texttt{structs.h} for another possibility.
\par
The syslogs are a different story; no data is written to the system logs because the code currently is configured simply to write all errors to the standard error file
descriptor (stderr), and Windows doesn't seem to let you redirect stderr to a file the same way UNIX does. Patch level 12 and above allow you to direct logs to a specific file instead.
\subsection{When someone logs on to my Windows MUD, the console screen gives: ``gethostbyaddr: No such file or directory''}
This means the MUD can't resolve the IP address of the connecting player's source site into a hostname. You probably don't have DNS correctly configured in the Windows Network Control Panel menu (under configuration of the TCP protocol). Make sure you have the IP address of your ISP's DNS server listed.
\subsection{My Mud crashed and my connection got closed. What can I do?}
Just because your connection got closed from the mud (for example, if you get too much information sent to you and the telnet session gets closed), this doesn't always mean that the game itself crashed. Before reporting something as a crash bug, make sure that the game itself crashed, and above all, try to duplicate the circumstances before reporting it as a crash bug. You can also try using gdb to find out why the mud is crashing if it gives you a core dump.
\subsection{Ok, what's this ``gdb'' thing?}
GDB has some online help, though it is not the best. It does at least give a summary of commands and what they're supposed to do. What follows is Sammy's short intro to gdb with some bug hunting notes following it:\newline
If you've got a core file, go to your top circle directory and type:\par
\texttt{$>$ gdb bin/circle lib/core}\newline
If you want to hunt bugs in real time (causing bugs to find the cause as opposed to checking a core to see why the mud crashed earlier) use:\par
\texttt{$>$ gdb bin/circle}\newline
If you're working with a core, gdb should show you where the crash occurred. If you get an actual line that failed, you've got it made. If not, the included message should help. If you're working in real time, now's the time to crash the mud so you can see what gdb catches.
\par
When you've got the crash info, you can type ``\texttt{where}'' to see which function called the crash function, which function called that one, and so on all the way up to ``\texttt{main()}''.\par
I should explain about ``\texttt{context}'' You may type ``\texttt{print ch}'' which you would expect to show you the ch variable, but if you're in a function that doesn't get a ch passed to it (real\_mobile, etc), you can't see ch because it's not in that context. To change contexts (the function
levels you saw with where) type ``\texttt{up}'' to go up. You start at the bottom, but once you go up, and up, and up, you can always go back ``\texttt{down}''. You may be able to go up a couple functions to see a function with ch in it, if finding out who caused the crash is useful (it normally isn't).
\par
The ``\texttt{print}'' command is probably the single most useful command, and lets you print any variable, and arithmetic expressions (makes a nice calculator if you know C math). Any of the following are valid and sometimes useful:
\begin{verbatim}
print ch (fast way to see if ch is a valid pointer, 0 if it's not)
print *ch (prints the contents of ch, rather than the pointer address)
print ch->player.name (same as GET_NAME(ch))
print world[ch->in_room].number (vnum of the room the char is in)
\end{verbatim}
Note that you can't use macros (all those handy pseudo functions like \texttt{GET\_NAME} and \texttt{GET\_MAX\_HIT}), so you'll have to look up the full structure path of variables you need.
\par
Type ``\texttt{list}'' to see the source before and after the line you're currently looking at. There are other list options but I'm unfamiliar with them.\newline
(From Sammy \url{<samedi@cris.com>})\par
For more information, you can try checking out the GDB Debugger manual \url{<http://www.circlemud.org/cdp/gdb/>}.
\subsection{How can I hunt bugs more effectively?}
There are only a couple of commands to use in gdb, though with some patience they can be very powerful. The only commands I've ever used are:
\begin{verbatim}
run well, duh.
print [variable] also duh, though it does more than you might think
list shows you the source code in context
break [function] set a breakpoint at a function
clear [function] remove a breakpoint
step execute one line of code
cont continue running after a break or ctrl-c
\end{verbatim}
I've run into nasty problems quite a few times. The cause is often a memory problem, usually with pointers, pointers to nonexistent memory. If you free a structure, or a string or something, the pointer isn't always set to NULL, so you may have code that checks for a NULL pointer that thinks the pointer is ok since it's not NULL. You should make sure you always set pointers to NULL after freeing them.
\par
Ok, now for the hard part. If you know where the problem is, you should be able to duplicate it with a specific sequence of actions. That makes things much easier. What you'll have to do is pick a function to ``break'' at. The ideal place to break is immediately before the crash. For example, if the crash occurred when you tried to save a mob with medit, you might be able to ``break mobs\_to\_file''. Try that one first.
\par
When you `medit save', the mud will hang. GDB will either give you segfault info, or it will be stopped at the beginning of mobs\_to\_file. If it segfaulted, pick an earlier function, like copy\_mobile, or even do\_medit.
\par
When you hit a breakpoint, print the variables that are passed to the function to make sure they look ok. Note that printing the contents of pointers is possible with a little playing around. For example, if you \texttt{print ch}, you get a hex number that shows you the memory location where ch is at. It's a little helpful, but try \texttt{print *ch} and you'll notice that it prints the contents of the ch structure, which is usually more useful. \texttt{print ch-$>$player} will give you the name of the person who entered the command you're looking at, and some other info. If you get a \texttt{no ch in this context} it is because the ch variable wasn't passed to the function you're currently looking at.
\par
Ok, so now you're ready to start stepping. When GDB hit your breakpoint, it showed you the first line of executable code in your function, which will sometimes be in your variable declarations if you initialized any variables (ex: int i = 0). As you're stepping through lines of code, you'll see one line at a time. Note that the line you see hasn't been run yet. It's actually the {\bf next} line to be executed. So if the line is \texttt{a = b + c;}, printing a will show you what a was before this line, not the sum of b and c.
\par
If you have an idea of where the crash is occurring, you can keep stepping till you get to that part of the code (tip: pressing return will repeat the last GDB command, so you can type step once, then keep pressing return to step quickly). If you have no idea where the problem is, the quick and dirty way to find your crash is to keep pressing return rapidly (don't hold the return key or you'll probably miss it). When you get the seg fault, you can't step any more, so it should be obvious when that happens.
\par
Now that you've found the exact line where you get the crash, you should start the mud over and step more slowly this time. What I've found that works really well to save time is to create a dummy function. This one will work just fine:
\begin{verbatim}
void dummy(void){}
\end{verbatim}
Put that somewhere in the file you're working on. Then, right before the crash, put a call to dummy in the code (ex: \texttt{dummy();}). Then set your breakpoint at dummy, and when you hit the breakpoint, step once to get back to the crashing code.
\par
Now you're in total control. You should be looking at the exact line that gave you the crash last time. Print {\bf every} variable on this line. Chances are one of them will be a pointer to an unaccessible memory location. For example, printing \texttt{ch-$>$player.name} may give you an error. If it does, work your way back and print \texttt{ch-$>$player} to make sure that one's valid, and if it isn't, try printing ch.
\par
Somewhere in there you're going to have an invalid pointer. Once you know which one it is, it's up to you to figure out why it's invalid. You may have to move \texttt{dummy()} up higher in the code and step slowly, checking your pointer all the way to see where it changes from valid to invalid. You may just need to NULL a free'd pointer, or you may have to add a check for a NULL pointer, or you may have screwed up a loop. I've done all that and more.
\par
Well, that's it in a nutshell. There's a lot more to GDB that I haven't even begun to learn, but if you get comfortable with print and stepping you can fix just about any bug. I spent hours on the above procedure trying to get my ascii object and mail saving working right, but it could have taken weeks without gdb. The only other suggestion I have is to check out the online gdb help. It's not very helpful for learning, but you can see what commands are available and play around with them to see if you can find any new tools.
\par
(From Sammy \url{<samedi@cris.com>})
\subsection{I just added n levels to my mud (from the stock 34). How do I set my imp's up to level n without a pfile wipe?}
You can write a quick and nasty function that will advance your imp (and imp only) to the max level (LVL\_IMPL). This can be done with a quick idnum check so that only the original player (the first imp, he with id 1) can use the command to get to maximum level.
\begin{verbatim}
ACMD(do_upme)
{
if (GET_IDNUM(ch) != 1) {
send_to_char("You think IMP positions are that easy to come by? "
"Go Figure...\n\r", ch);
} else {
GET_LEVEL(ch) = LVL_IMPL;
send_to_char("Advanced.\n\r", ch);
}
}
\end{verbatim}
Remember that you will need to prototype it and add a call to it into the command table, but that is left as an exercise to the reader.
\subsection{I decided to wipe my pfile away anyway. What steps should I take to do this?}
In order:
\begin{enumerate}
\item Shutdown the mud with ``shutdown die'' so that it won't restart.
\item Remove the player file, \texttt{lib/etc/players}
\item Restart the mud and login to recreate your imp character.
\end{enumerate}
You should probably also remove files in \texttt{plrobjs}, unless you want the recreated characters to come back with the same equipment they had when they were deleted.
\subsection{I want to expand the ability to pk in my MUD, allowing ASSASSINS that'll be able to PK without getting flagged. How can I do this?}
The simple way to do this is to find all the ``pk\_allowed'' checks and replace them with a \texttt{can\_murder(ch, vict)} function call. Prototype the function in \texttt{utils.h}. Then, in \texttt{utils.c}, create a \texttt{can\_murder()} function something like this:
\begin{verbatim}
int can_murder(struct char_data *ch, struct char_data *victim) {
if (pk_allowed == TRUE)
return TRUE;
if (IS_NPC(ch) || IS_NPC(victim))
return TRUE; /* you can always kill these */
if (PLR_FLAGGED(ch, PLR_ASSASSIN))
return TRUE; /* they can kill anyone */
/* Add further checks here */
}
\end{verbatim}
\subsection{Why does it say ``Connection closed by foreign host.'' and not display the ``Byebye!'' message I'm trying to send before cutting someone off?}
This usually happens if you are doing something like this:
\begin{verbatim}
send_to_char("Bye bye. Come back soon, ya hear?", ch);
close_socket(ch->desc);
\end{verbatim}
The \texttt{close\_socket} immediately dispatches/closes the connection, while \texttt{send\_to\_char} puts the message on the output queue to be dispatched next
\texttt{game\_loop} cycle. Therefore, the socket is gone. On some systems (i.e., old linux), this can even cause a infinite loop attempting to write to a closed socket. The proper way of doing this and other ``Byebye'' messages is to set the CON state of the player to CLOSE, like this:
\begin{verbatim}
send_to_char("Bye bye. Come back soon, ya hear?", ch);
STATE(ch->desc) = CON_CLOSED;
\end{verbatim}
This will then cycle to the next \texttt{game\_loop}, dispatch the output queues (therefore sending the byebye message) and then close the socket. Further note, in some bizarre cases, this only seems to send about 40 characters and no escape codes. Sending more than 40 characters or escape codes (like the clear screen sequence) will crash the process reporting a problem similar to writing to a closed socket.
\subsection{I run my mud on a unix system and the pfile/rent file works great, but on my home system it's all screwed up. What gives?}
Some operating systems write binary data least-significant-digit-first, while others write it most-significant-first (big endian vs. little endian). Moving player files, rent files, mail files, and board files from one of these systems to the other will result in corrupted files. The solutions to this problem include:
\begin{itemize}
\item Don't bother trying to move those files.
\item Edit your code to always write in one format.
\item Develop a binary to ascii conversion tool (and ascii to binary) for all binary files.
\item Develop an ascii read/write system to allow portability.
\end{itemize}
Some ASCII systems for objects, boards, and player files have been designed and are available on the CircleMUD FTP server \url{<ftp://ftp.circlemud.org/>} in the contributions section. There are also plans for future versions of CircleMUD to remove all binary based files.
\subsection{How do I get the CircleMUD to autoload when the Unix server is restarted?}
In \texttt{/etc/rc.d/rc.local} find where things like sendmail and (maybe) gpm are started. Add something like:
\begin{verbatim}
cd /home/mudlogin/circlebpl15/
su mudlogin -c ./autorun &
cd
\end{verbatim}
Of course, change the ``\texttt{mudlogin}'' to whatever the name of the account is that normally has control of the mud, and change the path in the first \texttt{cd} to wherever the mud is run from.\newline
For more info: \texttt{man su}
\subsection{My server shuts down my MUD every time I logoff. How do I keep the MUD running when I logoff?}
Instead of typing ``\texttt{autorun \&}'' to start the autorun script (which starts and keeps the mud running), type ``\texttt{nohup autorun \&}''. Running the autorun via nohup will keep the script and the MUD running when you logoff of the server. For more information type ``\texttt{man nohup}'' at the prompt on your server.
\section{Code Changes for CircleMUD 2.20}
\subsection{How do I fix the bug where people can junk more coins than available?}
Apparently in Circle 2.2, you can drop any amount of coins, and then be rewarded with more coins than you had in the first place. Here is the fix from Jeremy Elson:\newline
Around line 480 of \texttt{act.obj1.c}, you will find the code:
\begin{verbatim}
if (!str_cmp("coins", arg) || !str_cmp("coin", arg))
perform_drop_gold(ch, amount, mode, RDR);
else {
/* code to drop multiple items. anyone want to write it? -je */
send_to_char("Sorry, you can't do that (yet)...\n\r", ch);
--> return;
}
....
\end{verbatim}
It should be changed to:
\begin{verbatim}
if (!str_cmp("coins", arg) || !str_cmp("coin", arg))
perform_drop_gold(ch, amount, mode, RDR);
else {
/* code to drop multiple items. anyone want to write it? -je */
send_to_char("Sorry, you can't do that (yet)...\n\r", ch);
}
--> return;
....
\end{verbatim}
\subsection{How do I fix the ``vstat'' bug that crashes the MUD?}
To the fix for the vstat bug, from Jeremy Elson:
\par
In the file act.wizard.c, in the function \texttt{do\_vstat}, in the mobile section of the switch (around line 1150), you'll find the code:
\begin{verbatim}
mob = read_mobile(r_num, REAL);
do_stat_character(ch, mob);
extract_char(mob);
\end{verbatim}
Add the line \texttt{char\_to\_room(mob, 0)} before \texttt{extract\_char()}, like this:
\begin{verbatim}
mob = read_mobile(r_num, REAL);
do_stat_character(ch, mob);
char_to_room(mob, 0);
extract_char(mob);
\end{verbatim}
\subsection{ How do I fix the ``wizlock'' bug that lets lower immortals lock out higher immortals?}
Simple, insert this code into `\texttt{do\_wizlock()}' in `\texttt{act.wizard.c}':
\begin{verbatim}
if (value < 0 || value > LEVEL_IMPL) {
send_to_char("Invalid wizlock value.\n\r", ch);
return;
}
+ /* Do not allow people to wizlock above their level.
+ * This bug came with Circle 2.20 source -- VampLestat
+ */
+ if (value > GET_LEVEL(ch)) {
+ send_to_char("You may only wizlock below your level.\n\r", ch);
+ return;
+ }
restrict = value;
\end{verbatim}
\subsection{ How do I fix the ``mudlog'' bug that lets people see me log in, even if I'm wizinvis?}
For all the mudlog calls for entering the game, quitting, and so forth, you must change
\begin{verbatim}
mudlog(MAX(LEVEL_IMMORT, ...
\end{verbatim}
to
\begin{verbatim}
mudlog(MAX(GET_LEVEL(i), ...
\end{verbatim}
where ``i'' is either ``ch'' or ``d-$>$character'' depending on the call.
\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{<bugs@circlemud.org>} the bugs database \url{<bugs@circlemud.org>} 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{<http://bugs.circlemud.org/>}.
\subsection{How do I access Online Creation?}
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{<ftp://ftp.circlemud.org/pub/CircleMUD/contrib/olc/online/>}.
\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{<http://www.circlemud.org/cdp/building/>}.
\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{<ftp://ftp.circlemud.org/pub/CircleMUD/cvs/>} 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}
setenv CVSROOT :pserver:cvs@cambot.circlemud.org:/home/circledb/cvs
cvs login
(password = cvs)
cvs checkout circle
\end{verbatim}
\subsection{If someone logs in and just sits at the password prompt, the MUD hangs (i.e., no one else can connect or do anything) until the person enters their password.}
Your system's POSIX non-blocking I/O might be broken. Look in the source file \texttt{sysdep.h} at the comment above the line that says ``\texttt{\#define POSIX\_NONBLOCK\_BROKEN}'' for a possible fix. Once this is done, recompile the mud and try again. If you use the \texttt{POSIX\_NONBLOCK\_BROKEN} constant and it fixes your problem, please send mail to the bugs database \url{<bugs@circlemud.org>} and let us know exactly what kind of system you are using and what you had to do to fix it.
\subsection{Why does CircleMUD use BUF switches all through the code, what's happening here?}
From Jeremy:
\par
This code is the new output buffering system that I wrote for Circle in the early (non-released) beta versions of 3.0. The old DikuMud code for queueing output (which stayed with Circle until version 2.20) was memory- and time-inefficient in many cases (and, in my opinion, was inefficient for the normal behavior of most MUDs).
\par
First, I should explain what output queueing is and why it is necessary. On each pass through the \texttt{game\_loop()}, the MUD performs a number of steps: check to see if there are any new players connecting, kick out people with bad links, read input over the network for all players, then process the input for each player that has sent a complete line over the net. The processing step is usually where output is generated because it is where MUD commands are processed (e.g., ``kill'' might generate output of ``Kill who?'') When output is generated, it is not immediately sent out to the player, but instead queued for output in a buffer. After all players' commands are processed (and each command generates the appropriate output for various players), the next step of the \texttt{game\_loop()} is to send all the queued output out over the network.
\par
The new output system that Circle now uses allocates a small, fixed size buffer (1024 bytes) for each descriptor in which output can be queued. When output is generated (via such functions as \texttt{send\_to\_char()}, \texttt{act()}, etc.), it is written to the fixed size buffer until the buffer fills. When the buffer fills, we switch over to a larger (12K) buffer instead. A ``buffer switch'', therefore, is when the 1024-byte fixed buffer overflows.
\par
When a large (12K) buffer is needed, it is taken from a pool of 12K buffers that already been created. It is used for the duration of that pass through the \texttt{game\_loop()} and then returned to the pool immediately afterwards, when the output is sent to the descriptor. If a large buffer
is needed but none are in the pool, one is created (thereby increasing the size of the pool); the ``\texttt{buf\_largecount}'' variable records the current pool size.
\par
If a player has {\em already} gone from their small to large buffer, and so much output is generated that it fills even the large buffer, the descriptor is changed to the overflow state, meaning that all future output for the duration of the current pass through the game loop is discarded. This is a buffer overflow, and the only state in which output is lost.
\par
Now that I've described how the system works, I'll describe the rationale. The main purpose for the two-tiered buffer system is to save memory and reduce CPU usage. From a memory standpoint: Allocating a fixed 12K buffer for each socket is a simple scheme (and very easy to code), but on a large MUD, 100 12K buffers can add up to a lot of wasted memory. (1.2 megs of memory used for buffering on a 100-player MUD may not seem like very much, but keep in mind that one of Circle's big selling points several years ago, when memory was expensive, was that it had a very small memory footprint (3 or 4 megs total!) And from a CPU standpoint: the original DikuMud used a dynamically allocated buffer scheme to queue output, which unfortunately meant that for {\em each} player, on {\em each} pass through the game loop, dozens of tiny buffers (often one for every line of output, depending on the code to execute the command) were allocated with \texttt{malloc()}, {\em individually} written to the system using individual calls to \texttt{write()}, and then \texttt{free()}'d. My system saves hundreds or thousands of calls per second to \texttt{malloc()} and \texttt{free()}, and reduces the number of system calls {\bf drastically} (to at most one per player per pass through the game loop).
\par
The trick is to choose the size of the small and large buffers correctly in order to find the optimal behavior. I consider ``optimal'' to mean that 90\% of the time, most players stay within the limits of their small buffer (for example, when wandering through town or mindlessly killing some monster while watching damage messages go by). Hopefully, a large buffer switch is only necessary when a player executes a special command that generates an unusually large amount of output, such as ``who'', ``read board'', or ``where sword''. This critically depends on the fact that not everyone will be executing such a special large-output command at the same instant.
\par
For example, imagine you have 10 players on your MUD. They are all wandering around town, and every once in a while one of them types ``who'', or reads the board, meaning that they are seeing more than 1024 bytes of output at a time. On such a MUD, I would hope that there would only be a {\em single} 12K buffer allocated which gets passed around among all the 10 players as needed. Now, all players think they can queue up to 12K of output per command without getting truncated even though only one 12K buffer actually exists -- they are all sharing it.
\par
But - there's a problem with this. There are certain cases when {\em many} players have to see a lot of output at the same instant (i.e. on the {\em same} pass through the \texttt{game\_loop()}), all of them will need a large buffer at the same time and the pool will get very big. For example, if
an evil god types ``force all who''; or if the MUD lags for several seconds, then suddenly gets unlagged causing many commands to be processed at the same moment; or if 20 people are all trying to kill the same MOB and are all seeing 20 damage messages (more than 1024 bytes) on the same pass through the \texttt{game\_loop()}.
\par
Unfortunately, the current patchlevel of Circle has no way to destroy large buffers so such cases are pathological and cause wasted memory. Unfortunately since I don't run a MUD I can't actually tell how often this happens on a real MUD. (If there are any IMPs out there who run large MUDs (say, $>$= 30-50 players on regularly), and you've read this far, please send me the output of ``show stats'' after your MUD has been played for at least several hours.)
\par
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.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{<ftp://ftp.circlemud.org/pub/CircleMUD/contrib/docs/3.x/class.txt>}.
\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{<http://www.circlemud.org/>}, on the FTP server \url{<ftp://ftp.circlemud.org/>}, and on the CircleMUD Mailing List (see section~\vref{mailinglist}).
\end{document}
\end

View File

@ -0,0 +1,14 @@
These files are the LaTeX source files for the CircleMUD Documentation
Project.
Use them as you will, but if you find any errors, typos, or have suggestions
for improvement, please submit them to the CircleMUD Development Team at
either:
bugs@circlemud.org
or
furry@circlemud.org
Please note that these are still early drafts, and changes will be forthcoming
with future Patch Levels.
-Ae.

View File

@ -0,0 +1,211 @@
\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.
% This document typeset by Alex Fletcher <furry@circlemud.org> on Dec 4/2001
\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{The \texttt{act()} Function}
\author{Alex Fletcher\\
{\it Based on text from the DikuMud authors}}
\begin{document}
\maketitle
\begin{abstract}
This document is intended to give an overview of the \texttt{act()} function and give a summary of the various flags and the associated descriptive control characters. The \texttt{act()} function is one of the primary functions for sending a message from the game to a character or number of characters in a room.
\end{abstract}
\tableofcontents
\section{The \texttt{act()} Function}
\subsection{Overview}\label{overview}
The \texttt{act()} function is used to process and send strings of text to characters in a room. It can be used to send the same basic string to a number of characters filling in certain segments -- designated by control characters -- in different ways, dependant on what each character can see and who each character is. Once the text string passed to the function has been parsed, it is capitalized and a newline is added to its tail.
\subsection{The Function}\label{function}
The \texttt{act()} function is found in the \texttt{comm.c} source file and is described as:
\begin{verbatim}
void act(const char *str, int hide_invisible, struct char_data *ch,
struct obj_data *obj, const void *vict_obj, int type)
\end{verbatim}
These pieces are used as follows:
\begin{Ventry}{hide\_invisible}
\item[str] This is the basic string, a null terminated character array, including control characters (see section~\vref{controlcharacters}~`Control Characters'), to be sent to characters designated by the targets.
\item[hide\_invisible] A \texttt{TRUE} or \texttt{FALSE} value indicating whether or not to hide the entire output from any characters that cannot see the ``performing character''.
\item[ch] The ``performing character''. This is the character that the output string is associated with. The character is used to determine the room for the output of the action in question.
\item[obj] An object (an actual item -- \texttt{obj\_data}) used in the course of the action.
\item[vict\_obj] This can be either a character involved in the action, another object, or even a predefined string of text.
\item[type] One of \texttt{TO\_VICT}, \texttt{TO\_CHAR}, \texttt{TO\_NOTVICT}, or \texttt{TO\_ROOM}. This indicates who it is to be targeted at.
\end{Ventry}
\subsection{The Parameters}\label{parameters}
Of the various parameters passed to the \texttt{act()} function, the \texttt{str} is the most important, as it is the basis for the actual final output. If this parameter is a null-pointer or points to a null-character, then the function returns immediately. The next important parameter is the \texttt{ch} parameter. This, as mentioned, points to the central character associated with the output string and action.
\par
\texttt{obj} is an object of type \texttt{struct obj\_data~*} that is passed to the function. If there is no object to pass to the function, then a \texttt{NULL} or \texttt{0} should be passed in this location.
\par
The next parameter \texttt{vict\_obj} can be a number of things ranging from a game object (\texttt{strcut obj\_data~*}), through to a character (\texttt{struct char\_data~*}), and even a null terminated character array (\texttt{char~*}).
\par
Do note, however, that \texttt{obj} and \texttt{vict\_obj} are both ignored if there is no control character reference (see section~\vref{controlcharacters}~`Control Characters') to them and the \texttt{type} is set to \texttt{TO\_ROOM} or \texttt{TO\_CHAR}. In these cases, \texttt{NULL} should be supplied as the input to the function.
\par
The \texttt{hide\_invisible} flag dictates whether or not the action output should be hidden from characters that cannot see \texttt{ch}. If the flag is set to \texttt{TRUE} (non-zero), then this is the case.
\par
The \texttt{type} determines who the output is to be sent to. There are four options for this (all defined in \texttt{comm.h}) described below:
\begin{Ventry}{TO\_NOTVICT}
\item[TO\_ROOM] This sends the output to everybody in the room, except \texttt{ch}.
\item[TO\_VICT] This option sends the output to the character pointed to by \texttt{vict\_obj}. Obviously, in this case, \texttt{vict\_obj} must point at a character rather than an object.
\item[TO\_NOTVICT] In another case where \texttt{vict\_obj} must point to a character. This sends the output to everybody in the room except \texttt{ch} and \texttt{vict\_obj}.
\item[TO\_CHAR] Finally, this option sends the output to the \texttt{ch}.
\item[TO\_SLEEP] This is a special option that must be combined with one of the above options. It tells \texttt{act()} that the output is to be sent even to characters that are sleeping. It is combined with a bitwise `or'. For example, \texttt{TO\_VICT $|$ TO\_SLEEP}.
\end{Ventry}
When the string has been parsed, it is capitalized and a newline is added.
\subsection{Control Characters}\label{controlcharacters}
In a manner similar to the \texttt{printf()} family of functions, \texttt{act()} uses control characters. However, instead of using the {\bf \%} symbol, \texttt{act()} uses the {\bf \$} character to indicate control characters.
\begin{description}
\item[\$n] Write name, short description, or ``{\it someone}'', for \texttt{ch}, depending on whether \texttt{ch} is a PC, a NPC, or an invisible PC/NPC.
\item[\$N] Like {\bf \$n}, except insert the text for \texttt{vict\_obj}. NOTE: \texttt{vict\_obj} must point to an object of type \texttt{struct char\_data~*}.
\item[\$m] ``{\it him},'' ``{\it her},'' or ``{\it it},'' depending on the gender of \texttt{ch}.
\item[\$M] Like {\bf \$m}, for \texttt{vict\_obj}. NOTE: \texttt{vict\_obj} must be a pointer of type \texttt{struct char\_data~*}.
\item[\$s] ``{\it his},'' ``{\it her},'' or ``{\it it},'' depending on the gender of \texttt{ch}.
\item[\$S] Like {\bf \$s}, for \texttt{vict\_obj}. NOTE: \texttt{vict\_obj} must be a pointer of type \texttt{struct char\_data~*}.
\item[\$e] ``{\it he},'' ``{\it she},'' ``{\it it},'' depending on the gender of \texttt{ch}.
\item[\$E] Like {\bf \$e}, for \texttt{vict\_obj}. NOTE: \texttt{vict\_obj} must be a pointer of type \texttt{struct char\_data~*}.
\item[\$o] Name or ``{\it something}'' for \texttt{obj}, depending on visibility.
\item[\$O] Like {\bf \$o}, for \texttt{vict\_obj}. NOTE: \texttt{vict\_obj} must be a pointer of type \texttt{struct obj\_data~*}.
\item[\$p] Short description or ``{\it something}'' for \texttt{obj}.
\item[\$P] Like {\bf \$p} for \texttt{vict\_obj}. NOTE: \texttt{vict\_obj} must be a pointer of type \texttt{struct obj\_data~*}.
\item[\$a] ``{\it an}'' or ``{\it a}'', depending on the first character of \texttt{obj}'s name.
\item[\$A] Like {\bf \$a}, for \texttt{vict\_obj}. NOTE: \texttt{vict\_obj} must be a pointer of type \texttt{struct obj\_data~*}.
\item[\$T] Prints the string pointed to by \texttt{vict\_obj}. NOTE: \texttt{vict\_obj} must be a pointer of type \texttt{char~*}.
\item[\$F] Processes the string pointed to by \texttt{vict\_obj} with the \texttt{fname()} function prior to printing. NOTE: \texttt{vict\_obj} must be a pointer of type \texttt{char~*}.
\item[\$u] Processes the buffer and uppercases the first letter of the previous word (the word immediately prior to the control code). If there is no previous word, no action is taken.
\item[\$U] Processes the buffer and uppercases the first letter of the following word (the word immediately after to the control code). If there is no following word, no action is taken.
\item[\$\$] Print the character `\$'.
\end{description}
\subsection{Examples}\label{examples}
In all of the following examples, \texttt{ch} points to male character {\bf Ras}, \texttt{vict} always points to the female character {\bf Anna}. \texttt{obj1} is {\it a small sword}, and \texttt{obj2} is {\it a small sack}.
\begin{verbatim}
act("$n smiles happily.", TRUE, ch, NULL, NULL, TO_ROOM);
\end{verbatim}
This is sent to the room that {\bf Ras} is currently in, and the string that they see if they can see him is:
\begin{quote}
{\em Ras smiles happily.}
\end{quote}
If a character cannot see Ras, then they will not see the action at all.
\begin{verbatim}
act("You kiss $M.", FALSE, ch, NULL, vict, TO_CHAR);
\end{verbatim}
In this action, {\bf Ras} is kissing {\bf Anna}, and Ras will see:
\begin{quote}
{\em You kiss her.}
\end{quote}
\begin{verbatim}
act("$n gives $p to $N.", TRUE, ch, obj1, vict, TO_NOTVICT);
\end{verbatim}
The output from this string is sent to everyone in the room except for {\bf Ras} and {\bf Anna}. Of course, if they cannot see Ras, then they will not see any output at all. The string that each character in the room will see is:
\begin{quote}
{\em Ras gives a small sword to Anna.}
\end{quote}
If a character cannot see Anna, then {\it someone} will be used in place of her name, and if they cannot see the small sword, then {\it something} will be used in its place.
\begin{verbatim}
act("$n gives you $p.", FALSE, ch, obj1, vict, TO_VICT);
\end{verbatim}
Similar to the prior example, this is the output for {\bf Anna}. She will see this even if she cannot see {\bf Ras}, and the output that she will get is:
\begin{quote}
{\em Ras gives you a small sword.}
\end{quote}
Just as per the last example, if she cannot see Ras, {\it someone} will be used in place of his name, and if she cannot see the sword, then {\it something} will be used in its place.
\begin{verbatim}
act("$n puts $p in $s $O.", TRUE, ch, obj1, obj2, TO_ROOM);
\end{verbatim}
This action uses two objects rather than two characters, and is displayed to the entire room (with the exception of {\bf Ras} of course). If the character can see Ras, they will see:
\begin{quote}
{\em Ras puts a small sword in his small sack.}
\end{quote}
Otherwise, they will see nothing. Again, as per the prior two examples, {\it something} will be used in place of any objects that the viewing character cannot see.
\begin{verbatim}
act("The $F opens quietly.", FALSE, ch, NULL, EXIT(ch, door)->keyword, TO_ROOM);
\end{verbatim}
If the keywords for the door were {\it gate wooden}, then this would send the output string of:
\begin{quote}
{\em The gate opens quietly.}
\end{quote}
to all of the characters in the room with the exception of Ras.
\par
In addition to these examples, a multitude of other examples can be found scattered throughout the CircleMUD source code.
\appendix
%
% The following is a reiteration of some of the above sections into a one-page, two column
% quick reference sheet.
%
\newpage
\pagestyle{empty}
\setlength{\topskip}{0cm}
\setlength{\footskip}{0cm}
\section{\texttt{act()} Reference Sheet}
\begin{verbatim}
void act(const char *str, int hide_invisible, struct char_data *ch,
struct obj_data *obj, const void *vict_obj, int type)
\end{verbatim}
\begin{Ventry}{hide\_invisible}
\item[str] String to be parsed.
\item[hide\_invisible] If \texttt{TRUE}, hide from characters that cannot see the ``performer''.
\item[ch] The ``performer''. Also determines the room for the output.
\item[obj] \texttt{struct obj\_data~*}
\item[vict\_obj] Predefined string of text, or second character or object.
\item[type] \texttt{TO\_VICT}, \texttt{TO\_CHAR}, \texttt{TO\_NOTVICT}, or \texttt{TO\_ROOM}.
\end{Ventry}
\vspace*{0.5cm}
\renewcommand{\columnseprule}{0.5pt}
\begin{multicols}{2}
\begin{description}
\item[\$a] ``{\it an}'' or ``{\it a}'', depending on the first character of \texttt{obj}'s name.
\item[\$A] Like {\bf \$a}, for \texttt{vict\_obj} which is of type \texttt{struct obj\_data~*}.
\item[\$e] ``{\it he},'' ``{\it she},'' ``{\it it},'' depending on the gender of \texttt{ch}.
\item[\$E] Like {\bf \$e}, for \texttt{vict\_obj} which is of type \texttt{struct char\_data~*}.
\item[\$F] Processes the string pointed to by \texttt{vict\_obj} (pointer of type \texttt{char~*}) with the \texttt{fname()} function prior to printing.
\item[\$n] Write name, short description, or ``{\it someone}'', for \texttt{ch}, depending on whether \texttt{ch} is a PC, a NPC, or an invisible PC/NPC.
\item[\$N] Like {\bf \$n}, except insert the text for \texttt{vict\_obj} which is of type \texttt{struct char\_data~*}.
\item[\$m] ``{\it him},'' ``{\it her},'' or ``{\it it},'' depending on the gender of \texttt{ch}.
\item[\$M] Like {\bf \$m}, for \texttt{vict\_obj} which is of type \texttt{struct char\_data~*}.
\item[\$o] Name or ``{\it something}'' for \texttt{obj}, depending on visibility.
\item[\$O] Like {\bf \$o}, for \texttt{vict\_obj} which is of type \texttt{struct obj\_data~*}.
\item[\$p] Short description or ``{\it something}'' for \texttt{obj}.
\item[\$P] Like {\bf \$p} for \texttt{vict\_obj} which is of type \texttt{struct obj\_data~*}.
\item[\$s] ``{\it his},'' ``{\it her},'' or ``{\it it},'' depending on the gender of \texttt{ch}.
\item[\$S] Like {\bf \$s}, for \texttt{vict\_obj} which is of type \texttt{struct char\_data~*}.
\item[\$T] Prints the string pointed to by \texttt{vict\_obj} which is of type \texttt{char~*}.
\item[\$u] Processes the buffer and uppercases the first letter of the previous word (the word immediately prior to the control code).
\item[\$U] Processes the buffer and uppercases the first letter of the following word (the word immediately after to the control code).
\item[\$\$] Print the character `\$'.
\end{description}
\end{multicols}
\end{document}
\end

View File

@ -0,0 +1,264 @@
\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 <furry@circlemud.org> on Dec 5/2001
\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}
\title{The CircleMUD Administrator's Manual}
\author{Jeremy Elson\\
$<$jelson@circlemud.org$>$}
\begin{document}
\maketitle
\begin{abstract}
This document describes how to configure CircleMUD and how to compile it for the first time. It also discusses how to run the server including documentation of command-line options, a description of system logs and how to use them, and a description of daily and long-term maintenance required by the MUD. The intended audience is implementors new to CircleMUD or MUD administration in general.
\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{<http://www.circlemud.org/>} or FTP site \url{<ftp://ftp.circlemud.org/pub/CircleMUD/>}.
\end{abstract}
\tableofcontents
\section{Welcome to CircleMUD!}
\subsection{Background and Introduction}
CircleMUD is a derivative of DikuMud, the Multi-User Dungeon developed at DIKU, the Department of Computer Science at the University of Copenhagen. The original CircleMUD, version 1.0, was run by Jeremy Elson at the Johns Hopkins University's Department of Computer Science with moderate popularity from January until September of 1992. The version 1.0 code, which was never released to the public, was archived and remained inactive for several months after the death of the original CircleMUD. In the summer of 1993, it was taken out of storage and cleaned up with the intention of making it a public code base that anyone could freely download and use to start a MUD. Version 2.0, the first publically available version, was released in June of 1993. Circle has been maintained as a public code base ever since then, although we do not actually run a MUD of our own. The original CircleMUD has not run since it went down in 1992, nor will it ever run again.
\par
Hundreds of carefully spent hours have gone into the development of Circle, but it is not a finished product -- it is only a beginning. It has only a small number of spells and skills, a small world with relatively few areas, and only the 4 original DikuMud classes. From a gamer's point of view, it pales in comparison to other MUDs which have dozens of spells spread over a dozen classes, a rich palette of skills, and thousands upon thousands rooms, mobiles, and objects.
\par
Yet from a programmer's point of view, Circle is very highly developed. While the look and feel of the original DikuMud has been maintained, most of the underlying code and many of the structures have been optimized, reworked, or completely redesigned to be efficient, compact, and easily changeable and extensible. Dozens of features which have become standard in the MUDding world over the past few years, although they were not part of the original DikuMud release, were added to Circle as well.
\par
The result is that CircleMUD is a launching pad for your own MUD ideas. Our hope in releasing it is that it will free potential MUD implementors from having to worry about dealing with bug-ridden code or wasting time reinventing the wheel by re-coding standard MUD features, allowing them to devote more effort towards creatively shaping Circle into their own unique vision of how a MUD should look and feel. The reason why Circle has so few specialized spells, skills, classes, and races is to encourage implementors just like you to create your own unique system instead of just another stock MUD that everyone has seen before.
\par
So, it is with this message that we inflict our code on the world: don't just put another generic MUD on the Net -- give us something new and exciting, and have as much fun as possible in the process!
\subsection{Are you a Player or an Administrator?}
If you're playing a game like Zork or Doom, you're both the administrator and the player of the game: you're the one who has to download the software and get it running, and you're also the one who gets to play. MUDding isn't that way at all, because there's usually a very strong division between people who play MUDs and people who administer MUDs. If you've never played a MUD before, jumping right in and trying to run one of your own will probably just get you hopelessly confused. Instead of trying to compile and run the CircleMUD package yourself (which is presumably what you're trying to do if you're reading this document), you should play someone else's copy of CircleMUD. There is a partial list of sites \url{<http://www.circlemud.org/sites.html>} using CircleMUD on the CircleMUD web server.
\subsection{So, you're sure you want to run your own MUD?}
If you're already an old hand at playing MUDs and you've decided you want to start one of your own, here is our advice: take a vailum, lie down, and hide in a dark closet until the desire goes away. Just playing MUDs is masochistic enough, isn't it? Or are you trying to shave that extra point off your GPA, jump down that one last notch on your next job evaluation, or get rid of that pesky Significant Other for good? If you think silly distractions like having friends and seeing daylight are preventing you from realizing your full potential in the MUD world, being a MUD Administrator is the job for you.
\par
Don't get me wrong: running a production MUD can be great fun. It can also be overburdened by politics and plagued by spiteful players devoted to making your life difficult, and otherwise be a highly frustrating endeavour. That's why I don't do it any more.
\subsection{Giving Credit Where Credit is Due}
If I haven't scared you away yet, and you're still sure you want to use CircleMUD, please stop for a moment and look at the CircleMUD license in the file \texttt{license.doc}. It outlines the terms under which you must use CircleMUD.
\par
The license is simple. It boils down to the message, ``Don't rip off other people's work.'' Unfortunately, this simple message ended up becoming somewhat long-winded because I am trying to prevent people from abusing DikuMud in the future as they have in the past.
\par
Also, out of courtesy if nothing else, please keep the \texttt{credits} file intact. You can add your own credits on top of the existing file, but I'd appreciate it if you would not simply remove it and all references to the word ``Circle'' everywhere in the MUD. How would {\em you} feel if someone took {\em your} code and then took credit for it?
\par
USE OF THIS SOFTWARE IN ANY CAPACITY IMPLIES THAT YOU HAVE READ, UNDERSTOOD, AND AGREED TO ABIDE BY THE TERMS AND CONDITIONS SET DOWN BY THE CIRCLEMUD LICENSE.
\section{Getting Started}
\subsection{Section Requirements}
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}
\item SunOS 4.1.4
\item Solaris 2.3 and above
\item Irix 5.2, 6.2
\item AIX 3.2
\item Ultrix 4.x
\item HP-UX 9.x
\item Linux 1.x, 2.x
\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 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
Historically, CircleMUD has always been developed under different variants of UNIX. The original CircleMUD was run on a DECstation 3100 running Ultrix 4.0, which remained Circle's development platform until v2.0. Starting with v2.0, Circle was developed under various versions of Linux and Solaris over the years ranging from Linux 0.99.11 through the current Linux 2.2.x and including Solaris x86 5.6.
\subsection{Downloading and Unpacking the Source}
The first step in setting up CircleMUD is to make sure you have the most recent version of the source; if you downloaded CircleMUD from an unofficial mirror site, it could be out of date. You can always find the most recent version of the source at CircleMUD's official FTP site \url{<ftp://ftp.circlemud.org/pub/CircleMUD/>}
\par
The archive is offered several formats: one which ends in \texttt{.tar.gz}, one which ends in \texttt{.zip} and one which ends in \texttt{.lha}. The files have the same contents but have been compressed using different programs. You should ensure that you get a copy that you can unpack on your operating system.
\par
Next, unpack the archive. If you have the \texttt{.tar.gz} version, unpack it using \texttt{gzip} (GNU unzip) and the \texttt{tar} archiver. If you don't already have them, both of these utilities can be downloaded from the GNU FTP site \url{<ftp://ftp.gnu.org/pub/gnu/>}. To unpack the archive on a UNIX system, type:
\begin{verbatim}
gzip -dc circle30xxx.tar.gz | tar xvf -
\end{verbatim}
\par
If you downloaded the \texttt{.zip} or \texttt{.lha} version, make sure to use an UNZIP program capable of handling long filenames and which preserves the original directory structure of the archive (PKUNZIP 2.04 does {\em not} do either of these things by default.) The best unzip program is probably Info-Zip's unzip program \url{<http://www.info-zip.org/>}; it is compatible with all UNIX variants, Windows, OS/2, the Amiga, and pretty much every other computer on the planet. If you have Windows 95/98 or NT, another good choice is WinZip \url{<http://www.winzip.com/>}.
\par
For the next few sections, please note that the Cygnus Tools (Cygwin) are available for the Windows platform, which allow users to use Unix tools on that operating system.
\subsection{Configuring CircleMUD}
{\bf Note: This section applies {\em only} to UNIX users. If you're using Windows, OS/2, or the Amiga, read \texttt{README.WIN}, \texttt{README.OS2} or \texttt{README.AMIGA} instead.}
\par
Circle must be configured using the \texttt{configure} program which attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create Makefiles and a header file called \texttt{conf.h}.
\par
From Circle's root directory, simply type
\begin{verbatim}
./configure
\end{verbatim}
If you're using \texttt{csh}, it may not execute ``configure'' properly, giving you an error message like ``\texttt{Permission denied}''. If this occurs, try ``\texttt{sh ./configure}'' instead.
\par
\texttt{configure} can take several minutes to run if you're using a slow computer. It will print out various status messages while it works, telling you what characteristics of your computer it has found. It should create two Makefiles (\texttt{src/Makefile} and \texttt{src/util/Makefile}) and one header file (\texttt{src/conf.h}).
\par
You should only need to run \texttt{configure} once -- right after you unpack CircleMUD from its archive. You will probably compile the source dozens of times as you add new features, but \texttt{configure} only needs to be run before the first time you compile. Please note that there is one exception to this rule: if you move your MUD to a different computer, you must run \texttt{configure} again before you can recompile the source code. To rerun configure after moving the source, make sure to delete the file called \texttt{config.cache} and then run \texttt{configure} again.
\subsection{Compiling CircleMUD}
{\bf Note: This section applies {\em only} to UNIX or Cygwin users. If you're using Windows, OS/2, or the Amiga, read \texttt{README.WIN}, \texttt{README.OS2}, or \texttt{README.AMIGA} instead.}
\par
The \texttt{src} directory contains the source code for the main MUD server; \texttt{src/util} has the source for a dozen or so MUD maintenance utilities. There are two Makefiles, one in each source directory, but all compiling is normally performed from the \texttt{src} directory only. To compile the only CircleMUD server itself, type ``\texttt{make}''. Use ``\texttt{make utils}'' to compile the utilities, or ``\texttt{make all}'' to compile both the server and the utilities. It is also possible to compile individual utilities from the \texttt{src/util} directory: from \texttt{src/util}, type ``\texttt{make [utility-name]}''. All compiled binaries go to the \texttt{bin} directory.
\par
The stock (unmodified) CircleMUD code should compile with no warnings or errors.
\par
Despite my best efforts there's a chance that you'll have problems compiling Circle if you're using some version of UNIX that I've never seen before. It's impossible to give general advice on how to port software, except to say that you should ask a friend who knows a lot about both UNIX and C to help you. Also, if you have problems, you should definitely look at the CircleMUD FAQ (Frequently Asked Questions list with Answers), which you'll find in Circle's home directory.
\par
If you do port Circle to some other platform successfully, please share your hard work with others by sending a description of what you had to do to get Circle to compile on your system to \url{<cdev@circlemud.org>}. Be sure to include the specific name of your operating system and hardware. Full details on porting to a new system can be found in the Porting CircleMUD document.
\par
The Makefile directs all compiled programs to the \texttt{/bin} directory. Although not recommended, you may want to put Circle's \texttt{/bin} directory in your \$PATH. The reason that this is not recommended is that most of the resources are referenced using relative paths, and thus require that you run the programs from the base CircleMUD directory.
\section{Running CircleMUD}
{\bf Note: This section applies {\em only} to UNIX or Cygwin users. If you're using Windows, OS/2, or the Amiga, read \texttt{README.WIN}, \texttt{README.OS2}, or \texttt{README.AMIGA} instead.}
\subsection{Execution and \texttt{autorun}}
\begin{enumerate}
\item type 'autorun \&'
\item Wait a few moments for the server to boot.
\item type: \texttt{telnet localhost 4000}
\end{enumerate}
\par
Circle should always be run from circle's ``root'' directory, not the \texttt{/bin} directory. You can run it manually by typing \texttt{bin/circle} (useful for testing and debugging). For running the game ``for real,'' it is better to use the \texttt{autorun} shell script provided in Circle's root directory.
\par
Autorun lets Circle run itself for long periods of time. It continuously runs the game as well as removing old system logs, moving newer system logs to the \texttt{log} directory, and saving certain log entries to permanent files.
\par
Autorun can be controlled by creating files with certain names. You can use the '\texttt{touch}' command to create a file, and, of course, the '\texttt{rm}' command to remove a file. If a file called '\texttt{.fastboot}' exists, the CircleMUD will reboot immediately if it crashes or is shut down instead of waiting 40 seconds as it normally does. A file called '\texttt{.killscript}' will cause the script to terminate itself; i.e.\ if you want to bring the game down. If you want to temporarily prevent the MUD from rebooting, create a file called ``\texttt{pause}''; the script will go into a wait loop until '\texttt{pause}' is removed.
\par
Although you can create these files manually, the{\bf shutdown} command from within the MUD has several options which will create these files for you. See the {\bf shutdown} help entry in \texttt{wizhelp.doc} for more information.
\subsection{Command-Line Options}
Circle recognizes a number of command-line options. You can use them by actually specifying them on the command-line when running Circle manually or, by adding them to the \texttt{FLAGS} variable in your autorun script to use the options automatically every time you run the MUD with autorun.\newline
\newline
The syntax is:
\begin{verbatim}
circle [-m] [-q] [-r] [-s] [-d <path>] [port]
\end{verbatim}
\begin{description}
\item[-m] Mini-Mud Mode. Mini-mud will be one of your most powerful debugging tools; it causes Circle to boot with an abridged world, cutting the boot time down to several seconds. It is useful for testing features which are not world-related (i.e, new commands or spells).\newline
CircleMUD uses split world files (in the lib/world hierarchy); each directory (i.e.\ wld, obj, mob, shp, and zon) has a file called "\texttt{index}" which specifies which files should be loaded at boot-time. The file "\texttt{index.mini}" specifies which parts of the world should be loaded with the -m option.
\item[-q] Quick Boot. Prevents checking of timed out object files. Every time Circle boots, it checks every object file to see if it has timed out; if so, it is deleted. This is done primarily to save disk space. If time is more important to you than space, use the -q option. -q is automatically activated when you use -m.
\item[-r] Restricted Game. Allows you to decide at run-time whether or not the game will allow new characters to be created. Using -r is equivalent to typing "\texttt{wizlock 1}" (see \texttt{wizhelp.doc} for more information).
\item[-s] Special Routines Disabled. Allows you to suppress the assigning and calling of all mobile, object, and world special procedures. Historically used as a debugging tool in conjunction with the -d option (see below), but now obsolete because Circle checks to make sure entities exist before attempting to assign a special procedure to them.
\item[-d] Data Directory. Useful as a debugging and development tool, if you want to keep one or more sets of game data in addition to the standard set, and choose which set is to be used at run-time. For example, you may wish to make a copy of the entire world in a separate directory, so that you can test additions to the world files without subjecting players to unnecessary hazards. The default data directory is '\texttt{lib}'. Any core dumps (may they never happen to you!) will take place in the selected data directory.
\item[port] Port Selection. Allows you to choose on which port the game is to listen for connections. The default port is 4000, which is historically the port used by most DikuMuds. You can change the default in \texttt{config.c} and the \texttt{PORT=} line of the autorun script. (The \texttt{PORT=} line of \texttt{config.c} simply passes the value as a command-line parameter to Circle.) The port specified on the command line or by the autorun script will take precedence over the port specified in \texttt{config.c}.
\end{description}
\subsection{Creating an Implementor Character}
The first character to log in to the MUD will be made the maximum (Implementor) level. If you log in and aren't made an implementor, then the playerfile probably is not empty -- take the MUD down, delete the playerfile (\texttt{lib/etc/players}), and start the MUD again. You should fix your stats using the RESTORE command when you first create the character (i.e.\ type "\texttt{RESTORE $<$your-name$>$}".
\par
Once you are logged in as an implementor, type WIZHELP for a list of privileged commands. Documentation of those commands is contained in the file \texttt{wizhelp.doc}. \texttt{wizhelp.doc} is in the standard help file format, so you can simply add it to the help index file if you want online help available for wizard commands. (\texttt{wizhelp.doc} is not contained in the online help by
default as a security precaution.)
\par
To create additional wizard characters, log them in normally as level 1. Then, advance them using your implementor character, using the \texttt{ADVANCE} command. See \texttt{wizhelp.doc} for more information.
\section{Customizing CircleMUD}
Once you get over the initial euphoria of having your own MUD compile and run successfully for the first time, you should be aware of some of the files which control how Circle looks and feels so that you can configure it for your personal taste.
\subsection{\texttt{config.c}}
The most useful file for configuration is the config.c source file. It has dozens of options useful for customizing your MUD. Before you open your MUD to players, you should carefully read through config.c from beginning to end, checking what options are available as well as making sure they're all set the way you want them. Remember, you have to recompile and rerun the MUD before any changes you make to \texttt{config.c} take effect, of course.
\subsection{Text Files}
The place where most of your day-to-day changes will be is in the \texttt{lib/text} directory, which contains all of the text files read by players. The most visible file is ``\texttt{motd}'', (Message Of The Day), which is the message that mortals seen (though not necessarily read!) when they log in. Similarly, the ``\texttt{imotd}'' (Immortal MOTD) is seen by immortals when they log in. Other interesting files are ``\texttt{news}'' (for the \texttt{NEWS} command), ``\texttt{help}'' (for the \texttt{HELP} command with no arguments), ``\texttt{help\_table}'' (for \texttt{HELP} with an argument), and others.
\par
One file is particularly important: ``\texttt{policy}''. Despite what anyone tells you, and your best efforts to the contrary, your MUD will have political problems. If anyone tells you that you can run a MUD without politics, they're wrong. If you tell your players that you're going to run a revolutionary MUD that doesn't have any politics, you're lying. Every MUD has political problems sooner or later. Unfortunately, this usually occurs ``sooner''. There are various ways to make political problems easier to handle, but the best way is to decide on some ground rules from the very beginning, and then set those decisions down in writing. That's what the ``\texttt{policy}'' file is for. You probably know what kind of political problems MUDs have (you are not trying to run a MUD without ever having played one, are you!?) -- stuff like playerkilling, thieving, kill stealing, client use, multi-char playing, reimbursements, etc. Decide on your policies early and make sure your characters know what those policies are.
\par
It is also important to write down a set of rules dictating what immortals are allowed to do and not allowed to do. That's what the ``\texttt{handbook}'' (Immortal Handbook) is for. Immortals will always try to bend you as far as they can, so it's important for you to decide on answers to questions before those questions come up. Can immortals assist players? What about giving a single 'cure light' for a player about to die? Can immortals kill mobiles for their own enjoyment? Can they kill players for the same reason? Are they allowed to make policy? Break policy? Moderate disputes? Turn over each others' decisions?
\subsection{World Files}
The root of the area hierarchy is \texttt{lib/world/}. \texttt{lib/world/} has 5 subdirectories: wld, mob, obj, shp, and zon, which is where the world, mobile, object, shop, and zone files go, respectively. Each directory has a set of world files in it with the appropriate extension (i.e.\ the obj subdir will have a bunch of files ending with ``\texttt{.obj}'', such as 30.obj, 31.obj, etc.) plus two special files called ``\texttt{index}'' and ``\texttt{index.mini}''. ``\texttt{index}'' is a list of which world files are to be loaded by Circle. This makes the job of adding new areas easier -- just add the new area files to
your area directory, and then add the name of the new file to ``\texttt{index}''. ``\texttt{index.mini}'' controls which (smaller) set of world files should be loaded in the debugging mode (Mini-Mud Mode, explained below.)
\section{System Logs}
CircleMUD writes a wide variety of information to standard output and standard error. If you're using the autorun script, the boot messages are put into a file called ``\texttt{syslog}''. During Circle's boot sequence, the system log keeps a record of everything the MUD is doing to initialize itself; this can be useful to determine what the problem is if the MUD dies while it is booting. Once the game is up and running, the syslog contains player information, recording when players connect, disconnect, rent, unrent, quit, die, hit death traps, etc. The game also records status information about itself, falling generally into two categories: usage information and errors.
\subsection{Player Information}
The player information recorded by Circle's system logs will serve you very well as your players start to make wild claims about strange bugs resulting in them losing equipment or points. Many mudders prey on the insecurities of a new mud administrator who is terrified that his or her MUD is riddled with bugs and will do anything to satisfy grumpy players -- don't let yourself fall into that trap! CircleMUD is bound to contain bugs, but most of the core systems have been well tested, so you should take claims such as ``I magically lost all my stuff!'' with a grain of salt and check your system logs.
\par
If a player ever asks you for reimbursement of equipment, money, gold, experience points (XP), or whatever, your gut reaction should always be to check the logs first.
\begin{quote}
As a sidebar, let me point out that the value of system logs is twofold: 1) they actually provide you with valuable information, and 2) they make your players paranoid. When I first started mudding and I heard about this mysterious ``system log'', it made me incredibly paranoid. Now that I've done a good deal of MUD administration, I've seen the same paranoia in \underline{many} other players.
\par
That paranoia is a very good thing. The system logs become an abstract and shapeless but omnipresent force on the MUD. Players hear about ``the System Log'' and then get paranoid that everything they do is being recorded, so they tend to behave, lest the evil System Log betray their wrongdoings to the Gods.
\par
For this reason, when you go to check your logs, it's a good idea to say something like ``Hold on... let me go check the system logs, OK?'' because it reinforces the syslog's presence in the collective
psyche of your players.
\end{quote}
Back to the point. When someone claims that they've been wronged by the evil system, always check the logs. The logs give you power to say things like ``What do you mean your items disappeared in rent? It says right here in the logs `Rasmussen has quit the game.' You did not rent at all, you just {\em quit}!''
\par
To diffuse disputes such as, ``The game dumped my stuff, but I had enough money!!'' or ``I logged in and my stuff was gone, there must be a bug!!'', two types of log entries are written. First, every time a character rents, the log records the character's per diem rent rate as well as the total amount of money on hand and in the bank. Second, the log records makes a record of all characters' equipment dumped due to insufficient funds.
\par
Remember, rent is specified as a daily rate but is amortized on a per-second basis! In other words, if you rent at the rate of 100 coins per day and come back 36 hours later, you'll be charged 150 coins.
\par
The \texttt{autorun} script saves 6 levels of raw system logs. In addition, it greps the logs for certain pieces of extra-juicy information to save indefinitely.
\par
The system logs are your friends. Love them.
\subsection{Usage Information}
Every 5 minutes, the game counts how many people are playing and records that information in the system log. Optionally, if you define RUSAGE in \texttt{comm.c}, it will also record system resource information such as CPU time and memory used. The usage information currently logged by Circle is, as you can see, somewhat sparse; local MUD admins are encouraged to add
to this code as is appropriate for their particular site.
\par
Usage information isn't critical, but it is interesting to look at the usage patterns to determine when your peak playing hours are. If you're good at using `cut' and other Unix utilities, you can even dazzle your friends by graphing your MUD's system usage.
\par
{\it Note: friends not included with the CircleMUD distribution.}
\subsection{Errors}
Just as your first gut instinct should be to look at the logs if a player starts begging you for something, your first gut instinct in the event of a crash or unexpected shutdown should also be to look at the system logs.
\par
A Unix utility called `\texttt{tail}' is used to look at the last few lines of a text file; it is very useful for looking at the last entries in the system log to see the last thing that happened before the shutdown. Often, Circle will report an error in the logs just before it crashes. This method is
particularly useful if the MUD crashes during its boot sequence, because the logging during boot is intensive.
\par
If Circle shuts down unexpectedly and there is no core dump in the \texttt{/lib} directory, the game probably detected an internal error and killed itself. Such shutdowns are always preceded by entries in the system log describing the error.
\par
If there is no error message at the end of the log, then there probably IS a core dump, so you can use `\texttt{dbx}', `\texttt{gdb}', etc. to examine the core dump and determine the reason for the crash. The file \texttt{hacker.doc}, generously provided by Furey of MERC Industries, offers useful insight into the art and science of debugging -- you'd be well advised to give it a look-see.
\par
Circle sometimes encounters a serious but non-fatal error; in this case, the error will be written to the system log with the prefix SYSERR, but the MUD will not shut itself down. You should always be aware of any SYSERRs which occur -- they are often useful for foreseeing imminent danger or averting problems before they become critical. If a SYSERR does occur, try to determine if a change you've made recently has caused it. Ignoring SYSERRs is like ignoring compiler warnings: you can be tempted to ignore them because the game keeps going even if they exist, but you can easily get yourself into trouble by not listening. The autorun script saves all SYSERRs to the file \texttt{log/errors}.
\section{MUD Maintenance}
\subsection{Technical Maintenance}
Once you get the MUD up and running, you will surely want to modify it -- adding new areas, new features, new code, and new ideas, however these topics are beyond the scope of this document. See \texttt{coding.doc}, \texttt{areas.doc}, and other creation documents for more information about how to customize your MUD once you get it up and running. This section simply focuses on some of the simple maintenance that'll be necessary to keep your MUD running smoothly. Make sure not to get so caught up in being a God that you forgot you're also supposed to be acting as a software engineer!
\par
First, you should look at the log/errors file regularly to make sure there are no recurring problems, particularly problems that may have been caused by code you've added. If the MUD crashes, it will usually generate what is called a ``core dump'' -- a big file called ``\texttt{core}'' in your lib directory, created by the operating system to record the state the game was in the moment before it crashed. You should look at the core dump using a debugger such as ``\texttt{gdb}'' or ``\texttt{dbx}'' to determine why the MUD crashed. See the file ``\texttt{hacker.doc}'' for more information about debugging.
\par
You probably will want to clean out the playerfile on a regular basis to remove deadweight characters (i.e.\ people who log in and look around for 10 minutes, and then never come back). You can decide how often to purge the playerfile -- every day if disk space is tight, or every month if it isn't. The \texttt{purgeplay} utility program included in the \texttt{src/util} directory removes deadweight players. Make sure to run the ``\texttt{purgeobjs}'' script (in the \texttt{lib/plrobjs} directory) after you purge the playerfile. \texttt{purgeobjs} removes the object files of players who no longer exist in the playerfile.
\par
The '\texttt{automaint}' script in the main circle directory will automatically purge the playerfile and player objects for you. {\em DO NOT RUN THIS SCRIPT WHILE THE MUD IS RUNNING!} Doing so will make your life (more) difficult.
\subsection{Diplomatic Maintenance}
Okay, so now you have your wonderful CircleMUD up and running smoothly and all is right with the world. Right?
\par
Wrong.
\par
Well, technically, right. Circle requires very little day-to-day attention in order to keep the program itself running smoothly. But the MUD itself is just a series of instructions running on a computer, processing data. Never lose sight of the fact that there will be dozens, hundreds, or maybe even thousands of people connecting to your MUD -- and they are not programs. They are people!
\par
From the technical side, there are relatively few things you have to do to keep the game running. But you cannot just dump a MUD on the Internet and then ignore it! Spend time on your MUD. Try to keep up with the boards, and make an effort to respond to the complaints, ideas, and
suggestions posted there. Take a look at the `\texttt{bug}', `\texttt{typo}', and `\texttt{idea}' files from time to time -- and maybe even respond to some of the ideas using Mudmail. Try to respond to Mudmail you receive from players in a timely manner. Make sure that your `\texttt{news}', `\texttt{policy}' and other text files are up-to-date and suit the political climate on your MUD.
\par
If you cannot or just do not want to deal with the player politics, make sure that you choose someone who can and will, and make them responsible for dealing with it. If no one does it, your MUD will stagnate and die.
\section{Final Thoughts}
Try to remember that running a MUD should be fun. It can sometimes be easy to lose sight of the ultimate goal of personal enjoyment that MUDs are supposed to provide, particularly when MUDs start to get crushed under the weight of their own politics or the egos of the administrators. If you find that your MUD is more of a source of frustration than enjoyment, don't be afraid to close it.
\par
Good luck with your MUD! Always feel free to write to us and let us know what you think of the MUD, and the interesting things you've done with it. We cannot promise a timely response, but we love hearing from people who are using our code.
\par
For further information and updates, you can be certain to check out the CircleMUD homepages \url{<http://www.circlemud.org/>}, the associated pages of Ceramic Mouse \url{<http://developer.circlemud.org/>}, and the CircleMUD Mailing List \url{<http://www.circlemud.org/maillist/>}.
\end{document}
\end

File diff suppressed because it is too large Load Diff

View File

@ -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 <furry@circlemud.org> 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{<http://www.circlemud.org/>} or
FTP site \url{<ftp://ftp.circlemud.org/pub/CircleMUD/>}
\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}
<command name> <hide-flag> <minimum position of victim>
<messg to character if no argument>
<messg to others if no argument>
<messg to char if victim found>
<messg to others if victim found>
<messg to victim>
<messg to char if victim not found>
<messg to others if victim not found>
<messg to char if vict is char>
<messg to others if vict is char>
\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
<skill number>
<death messg to skill user>
<death messg to skill victim>
<death messg to others>
<miss messg to skill user>
<miss messg to skill victim>
<miss messg to others>
<hit messg to skill user>
<hit messg to skill victim>
<hit messg to others>
<attempt to hit immortal messg to skill user>
<attempt to hit immortal messg to skill victim>
<attempt to hit immortal messg to others>
\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(<vnum>,<special procedure>)}
\item \texttt{ASSIGNOBJ(<vnum>,<special procedure>)}
\item \texttt{ASSIGNROOM(<vnum>,<special procedure>)}
\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(<name>)} and is as follows:
\begin{verbatim}
int (<name>)(struct char\_data *ch, void *me, int cmd, char *argument)
\end{verbatim}
where \texttt{<name>} 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

View File

@ -0,0 +1,126 @@
\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 <furry@circlemud.org> on Dec 4/2001
\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{Using Color In CircleMUD}
\author{Jeremy Elson}
\begin{document}
\maketitle
\begin{abstract}
This document is a description of how to write C code which displays messages to players in color in the CircleMUD game engine. Its intended audience is for Coders of CircleMUD.
\end{abstract}
CircleMUD allows you to create colorful messages by using ANSI control sequences. Each player may select what ``level'' of color he/she desires from the four levels ``off,'' ``sparse,'' ``normal,'' and ``complete.'' Each player can select his/her color level by using the \texttt{COLOR} command from within the MUD; you as the programmer must decide which messages will be colored for each of the color levels.
\par
All files in which you wish to use color must have the line:
\begin{verbatim}
#include "screen.h"
\end{verbatim}
This should be put in after all other includes in the beginning of the file.
\par
There are 8 colors available -- ``normal,'' red, green, yellow, blue, magenta, cyan and white. They are accessible by sending control sequences as part of another string, for example:
\begin{verbatim}
sprintf(buf, "If you're %shappy%s and you know it clap "
"%d of your hands.\n\r", x, y, num_of_hands);
send_to_char(buf, ch);
\end{verbatim}
In this example, \texttt{x} and \texttt{y} are the ``on'' and ``off'' sequences for the color you want. There are 2 main series of color macros available for you to use (don't actually use ``x'' and ``y,'' of course!): the K series and the CC series. The CC (Conditional Color) series is recommended for most general use.
\par
The name of the actual sequence starts with the name of its series, plus a 3-letter color code, as follows:
\begin{description}
\item[Normal:] NRM
\item[Red:] RED
\item[Yellow:] YEL
\item[Green:] GRN
\item[Blue:] BLU
\item[Magenta:] MAG
\item[Cyan:] CYN
\item[White:] WHT
\end{description}
For example, white in the K series is \texttt{KWHT}; blue in the CC series is \texttt{CCBLU()} (arguments defined below).
\par
The K series requires no arguments, and is simply a macro to the ANSI color code. Therefore, if you use a K-series color code, the color will ALWAYS be sent, even if the person you're sending it to has color off. This can very bad -- some people who do not have ANSI-compatible terminals will see garbage characters instead of colors. If the terminal correctly ignores ANSI color codes, then nothing will show up on their screen at all. The K series is mainly used to print colors to a string if the player's color level will later be tested manually (for an example, see \texttt{do\_gen\_com} in \texttt{act.comm.c}).
\par
The recommended series is the CC series (i.e.\ \texttt{CCNRM()}, \texttt{CCRED()}, etc.) The CC series macros require two arguments -- a pointer to the character to whom the string is being sent, and the minimum color level the player must be set to in order to see the color. Color sent as `sparse' (\texttt{C\_SPR}) will be seen by people with color set to sparse, normal, or complete;
color sent as `normal' (\texttt{C\_NRM}) will be seen only by people with color set to normal or complete; color sent as `complete' (\texttt{C\_CMP}) will be seen only by people with color set to complete.
\par
To illustrate the above, an example is in order:
\begin{verbatim}
#include "screen.h"
/* include screen.h in all files that you use color in */
ACMD(do_showcolor)
{
char buf[300];
sprintf(buf, "Don't you just love %scolor%s, %scolor%s, "
"%sCOLOR%s!\n\r",
CCBLU(ch, C_CMP), CCNRM(ch, C_CMP),
CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
CCRED(ch, C_SPR), CCNRM(ch, C_SPR));
send_to_char(buf, ch);
}
\end{verbatim}
What does this do? For people with color set to Complete, it prints:
\begin{verbatim}
Don't you just love color, color, COLOR!
(blue) (yellow) (red)
\end{verbatim}
People who have color set to Normal will see:
\begin{verbatim}
Don't you just love color, color, COLOR!
(yellow) (red)
\end{verbatim}
People who have color set to Sparse will see:
\begin{verbatim}
Don't you just love color, color, COLOR!
(red)
\end{verbatim}
People who have color set to Off will see:
\begin{verbatim}
Don't you just love color, color, COLOR!
(no color, as you'd expect)
\end{verbatim}
There are several common pitfalls with using the CC series of color macros:
\begin{itemize}
\item Do not confuse \texttt{CCNRM} with \texttt{C\_NRM}. \texttt{CCNRM()} is a macro to turn the color back to normal; \texttt{C\_NRM} is a color level of ``normal''.
\item Always make sure that every pair of ``on'' and ``off'' codes are at the same color level. For example:
\begin{verbatim}
WRONG: sprintf(buf, "%sCOLOR%s\n\r", CCBLU(ch, C_NRM),
CCNRM(ch, C_CMP));
\end{verbatim}
\par
This is wrong because if someone has their color level set to Normal, the \texttt{CCBLU} code will be sent but the \texttt{CCNRM} command will not, causing all subsequent output to be blue.
\begin{verbatim}
WRONG: sprintf(buf, "%sCOLOR%s\n\r", CCBLU(ch, C_CMP),
CCNRM(ch, C_NRM));
\end{verbatim}
The above statement is also wrong, although not as bad. In this case, someone with color set to Normal will (correctly) not get the \texttt{CCBLU} code, but will then unnecessarily get the \texttt{CCNRM} code. Never send a color code if you don't have to -- the codes are several bytes long, and cause a noticeable pause at 2400 baud.
\par
\item This should go without saying, but don't ever send color at the \texttt{C\_OFF} level.
\item Special precautions must be taken when sending a colored string to a large group of people -- you can't use the color level of ``ch'' (the person sending the string) -- each person receiving the string must get a string appropriately colored for his/her level. In such cases, it is usually best to set up two strings (one colored and one not), and test each player's color level individually (see \texttt{do\_gen\_com} in \texttt{act.comm.c} for an example).
\end{itemize}
\end{document}
\end

View File

@ -0,0 +1,138 @@
\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 <furry@circlemud.org> on Dec 9/2001
\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}
\title{CircleMUD File Manifest}
\author{}
\begin{document}
\maketitle
The main `\texttt{circle/}' directory has the following subdirectories and files:
\begin{verbatim}
README - Information for the new CircleMudder
automaint - shell script to perform maintenance .. see running.doc
autorun - shell script to run the MUD .. see running.doc
bin/ - directory of all the compiled programs (binaries)
doc/ - documentation
lib/ - MUD data (playerfile, world files, etc.)
log/ - system logs
src/ - source code
syslog - the current system log
\end{verbatim}
The \texttt{bin/} directory contains only binaries: `\texttt{circle}' (the main MUD) and its utilities, which are described in the CircleMUD Utility document.
\par
The \texttt{doc/} directory has its own \texttt{README} file, describing the contents of each of the documentation files.
\par
The \texttt{lib/} directory contains the following subdirectories:
\begin{verbatim}
etc - Files which the MUD uses internally (playerfile, mail, etc.)
misc - Misc. database files meant to be changed (i.e. socials)
plrobjs - Player object hierarchy and utility scripts
plralias - Hierarchy for saved player aliases.
text - Text files such as MOTD, news, help, etc.
world - The world hierarchy
\end{verbatim}
The \texttt{lib/etc/} directory contains the following files (the MUD actively maintains these files while it is running; they should not be modified unless the game is down):
\begin{verbatim}
Board.* - Binary files with the contents of the bulletin boards
badsites - List of banned sites
hcontrol - Binary file with the state of the house control system
players - Binary file containing data on all players
plrmail - Binary file containing player mail
\end{verbatim}
The \texttt{lib/misc/} directory contains the following files:
\begin{verbatim}
bugs - Bugs reported by players with the 'bug' command
ideas - Ideas from players from 'idea' command
messages - Spell and skill damage messages
socials - Text file with text of the socials
typos - Typos reported by players with the 'typo' command
xnames - Text file of invalid names
\end{verbatim}
The \texttt{lib/plrobjs/} contains the following files and directories:
\begin{verbatim}
a-e \
f-j \
k-o \ Subdirectories where player objects files are stored
p-t /
u-z /
zzz/
purgedir - Script to purge an object dir (meant for use by purgeobjs)
purgeobjs - Script to purge player objects (see utils.doc)
searchfor - Script to search for objects in obj files (see utils.doc)
\end{verbatim}
The \texttt{lib/plralias/} contains the following directories:
\begin{verbatim}
a-e \
f-j \
k-o \ Subdirectories where player alias files are stored.
p-t /
u-z /
zzz/
\end{verbatim}
The \texttt{lib/text/} directory contains the following files:
\begin{verbatim}
background - Background story (for option 3 from main menu)
credits - Text for 'credits' command
handbook - Text for Immortal Handbook ('handbook' command)
help - Text for 'help' command with no arguments
help_table - File of all help entries for 'help' command
immlist - Text for 'immlist' command
imotd - Immortal MOTD -- seen by immortals on login
info - Text for 'info' command
motd - MOTD -- seen by mortals on login
news - Text for 'news' command
policies - Text for 'policy' command
wizlist - Text for 'wizlist' command
\end{verbatim}
The \texttt{lib/world/} directory contains the following subdirectories:
\begin{verbatim}
mob - Contains *.mob files (mobile files)
obj - Contains *.obj files (object files)
shp - Contains *.shp files (shop files)
wld - Contains *.wld files (world files)
zon - Contains *.zon files (zone files)
\end{verbatim}
Each of the 5 subdirectories in the \texttt{lib/world/} directory also contains two additional files -- one called `\texttt{index}', which specifies which files in that directory should be loaded when the MUD boots, and `\texttt{index.mini}', which specifies which files should be loaded if the MUD is booted with the \texttt{-m} (mini-mud) option.
\par
The \texttt{log/} directory contains several files of the form \texttt{syslog.{\it n}}, where {\it n} is a small number. These are the most recent CircleMUD syslogs.
\par
In addition, it contains the following more permanent system logs:
\begin{verbatim}
badpws - Records of bad password attempts
delete - Players who have self-deleted
dts - Players who have hit death traps
errors - MUD system errors ("SYSERR" messages)
levels - Records of all levels gained by all players
newplayers - Records of the creation of new players
rentgone - Players who have lost their items in rent
restarts - List of times at which the MUD rebooted
rip - Player deaths
usage - Mud system usage (player load & memory usage info)
\end{verbatim}
The src directory contains all of the C and header files for the MUD, along with a \texttt{Makefile}. The \texttt{src/util/} directory contains source for CircleMUD's utility programs. See the Administering CircleMUD document for more information on how to compile the MUD. See the CircleMUD Utility document for more information on how to use CircleMUD's utilities.
\end{document}
\end

View File

@ -0,0 +1,135 @@
\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 <furry@cambot.circlemud.org> on Dec 4/2001
\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}
\title{The Art of Debugging}
\author{Michael Chastain}
\begin{document}
\maketitle
\begin{abstract}
The following documentation is excerpted from Merc 2.0's \texttt{hacker.txt} file. It was written by Furey of MERC Industries and is included here with his permission. We have packaged it with CircleMUD (very slightly changed in a couple of places, such as specific filenames) because it offers good advice and insight into the art and science of software engineering. 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{<http://www.circlemud.org/>} or FTP site \url{<ftp://ftp.circlemud.org/pub/CircleMUD/>}.
\end{abstract}
\section{``I'm running a Mud so I can learn C programming!''}
Yeah, right.
\par
The purpose of this document is to record some of our knowledge, experience and philosophy. No matter what your level, we hope that this document will help you become a better software engineer.
\par
Remember that engineering is work, and {\em no} document will substitute for your own thinking, learning and experimentation.
\section{How to Learn in the First Place}
\begin{itemize}
\item Play with something.
\item Read the documentation on it.
\item Play with it some more.
\item Read documentation again.
\item Play with it some more.
\item Read documentation again.
\item Play with it some more.
\item Read documentation again.
\item Get the idea?
\end{itemize}
The idea is that your mind can accept only so much ``new data'' in a single session. Playing with something doesn't introduce very much new data, but it does transform data in your head from the ``new'' category to the ``familiar'' category. Reading documentation doesn't make anything ``familiar,'' but it refills your ``new'' hopper.
\par
Most people, if they even read documentation in the first place, never return to it. They come to a certain minimum level of proficiency and then never learn any more. But modern operating systems, languages, networks, and even applications simply cannot be learned in a single
session. You have to work through the two-step learning cycle {\em many} times to master it.
\section{Basic Unix Tools}
\begin{description}
\item[man] gives you online manual pages
\item[grep] stands for ``global regular expression print;'' searches for strings in text files
\item[vi, emacs, jove] use whatever editor floats your boat, but learn the hell out of it; you should know {\em every} command in your editor
\item[ctags] mags ``tags'' for your editor which allows you to go to functions by name in any source file
\item[$>$, $>>$, $<$, $|$] input and output redirection at the command line; get someone to show you, or dig it out of ``man csh''
\end{description}
These are the basic day-in day-out development tools. Developing without knowing how to use {\em all} of these well is like driving a car without knowing how to change gears.
\section{Debugging: Theory}
Debugging is a science. You formulate a hypothesis, make predictions based on the hypothesis, run the program and provide it experimental input, observe its behavior, and confirm or refute the hypothesis.
\par
A good hypothesis is one which makes surprising predictions which then come true; predictions that other hypotheses don't make.
\par
The first step in debugging is not to write bugs in the first place. This sounds obvious, but sadly, is all too often ignored.
\par
If you build a program, and you get {\em any} errors or {\em any} warnings, you should fix them before continuing. C was designed so that many buggy ways of writing code are legal, but will draw warnings from a suitably smart compiler (such as ``gcc'' with the \texttt{-Wall} flag enabled). It
takes only minutes to check your warnings and to fix the code that generates them, but it takes hours to find bugs otherwise.
\par
``Desk checking'' (proof reading) is almost a lost art these days. Too bad. You should desk check your code before even compiling it, and desk-check it again periodically to keep it fresh in mind and find new errors. If you have someone in your group whose {\em only} job it is to desk-check other people's code, that person will find and fix more bugs than everyone else combined.
\par
One can desk-check several hundred lines of code per hour. A top-flight software engineer will write, roughly, 99\% accurate code on the first pass, which still means one bug per hundred lines. And you are not top flight. So... you will find several bugs per hour by desk checking. This is a very rapid bug fixing technique. Compare that to all the hours you spend screwing around with broken programs trying to find {\em one} bug at a time.
\par
The next technique beyond desk-checking is the time-honored technique of inserting ``print'' statements into the code, and then watching the logged values. Within Circle code, you can call \texttt{printf()}, \texttt{fprintf()}, or \texttt{log()} to dump interesting values at interesting times. Where and when to dump these values is an art, which you will learn only with practice.
\par
If you don't already know how to redirect output in your operating system, now is the time to learn. On Unix, type the command ``\texttt{man csh}'', and read the part about the ``\texttt{>}'' operator. You should also learn the difference between ``standard output'' (for example, output from ``\texttt{printf}'') and ``standard error'' (for example, output from ``\texttt{fprintf(stderr, ...)}'').
\par
Ultimately, you cannot fix a program unless you understand how it is operating in the first place. Powerful debugging tools will help you collect data, but they can't interpret it, and they can't fix the underlying problems. Only you can do that.
\par
When you find a bug... your first impulse will be to change the code, kill the manifestation of the bug, and declare it fixed. Not so fast! The bug you observe is often just the symptom of a deeper bug. You should keep pursuing the bug, all the way down. You should grok the bug and cherish it in fullness before causing its discorporation.
\par
Also, when finding a bug, ask yourself two questions: ``What design and programming habits led to the introduction of the bug in the first place?'' And: ``What habits would systematically prevent the introduction of bugs like this?''
\section{Debugging: Tools}
When a Unix process accesses an invalid memory location, or (more rarely) executes an illegal instruction, or (even more rarely) something else goes wrong, the Unix operating system takes control. The process is incapable of further execution and must be killed. Before killing the process, however, the operating system does something for you: it opens a file named ``\texttt{core}'' and writes the entire data space of the process into it.
\par
Thus, ``dumping core'' is not a cause of problems, or even an effect of problems. It's something the operating system does to help you find fatal problems which have rendered your process unable to continue.
\par
One reads a ``core'' file with a debugger. The two most popular debuggers on Unix are \texttt{adb} and \texttt{gdb}, although occasionally one finds \texttt{dbx}. Typically one starts a debugger like this: ``\texttt{adb bin/circle}'' or ``\texttt{gdb bin/circle lib/core}''.
\par
The first thing, and often the only thing, you need to do inside the debugger is take a stack trace. In \texttt{adb}, the command for this is ``\texttt{\$c}''. In \texttt{gdb}, the command is ``{\texttt{backtrace}''. In \texttt{dbx}, the command is ``\texttt{where}''. The stack trace will tell you what function your program was in when it crashed, and what functions were calling it. The debugger will also list the arguments to these functions. Interpreting these arguments, and using more advanced debugger features, requires a fair amount of knowledge about assembly language programming.
\par
If you have access to a program named ``\texttt{Purify}''... learn how to use it.
\section{Profiling}
Another useful technique is ``profiling,'' to find out where your program is spending most of its time. This can help you to make a program more efficient.
\par
Here is how to profile a program:
\par
\begin{enumerate}
\item Remove all the .o files and the ``circle'' executable:
\begin{verbatim}
make clean
\end{verbatim}
\item Edit your Makefile, and change the \texttt{PROFILE=} line:
\begin{verbatim}
PROFILE = -p
\end{verbatim}
\item Remake circle:
\begin{verbatim}
make
\end{verbatim}
\item Run circle as usual. Shutdown the game with the \texttt{shutdown} command when you have run long enough to get a good profiling base under normal usage conditions. If you crash the game, or kill the process externally, you won't get profiling information.
\item Run the \texttt{prof} command:
\begin{verbatim}
prof bin/circle > prof.out
\end{verbatim}
\item Read \texttt{prof.out}. Run ``\texttt{man prof}'' to understand the format of the output.
\end{enumerate}
For advanced profiling, you can use ``\texttt{PROFILE = -pg}'' in step 2, and use the ``\texttt{gprof}'' command in step 5. The ``\texttt{gprof}'' form of profiling gives you a report which lists exactly how many times any function calls any other function. This information is valuable for debugging as well as performance analysis.
\par
Availability of ``\texttt{prof}'' and ``\texttt{gprof}'' varies from system to system. Almost every Unix system has ``\texttt{prof}''. Only some systems have ``\texttt{gprof}''.
\section{Books for Serious Programmers}
Out of all the thousands of books out there, three stand out:
\begin{itemize}
\item Kernighan and Plaugher, ``{\em The Elements of Programming Style}''
\item Kernighan and Ritchie, ``{\em The C Programming Language}''
\item Brooks, ``{\em The Mythical Man Month}''
\end{itemize}
\end{document}
\end

View File

@ -0,0 +1,191 @@
\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 <furry@circlemud.org> on Dec 9/2001
\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}{0pt}
\title{CircleMUD License}
\author{Jeremy Elson}
\begin{document}
\maketitle
\begin{abstract}
This document presents the CircleMUD License and the DikuMud License. Both of these licenses must be followed in order to legally use or modify CircleMUD or any part of it.
\end{abstract}
\section{CircleMUD License}
CircleMUD was created by:
\par
Jeremy Elson\newline
Department of Computer Science\newline
Johns Hopkins University\newline
Baltimore, MD 21218 USA\newline
\url{<jelson@circlemud.org>}
\par
CircleMUD is licensed software. This file contains the text of the CircleMUD license. If you wish to use the CircleMUD system in any way, or use any of its source code, you must read this license and are legally bound to comply with it.
\par
CircleMUD is a derivative work based on the DikuMud system written by Hans Henrik Staerfeldt, Katja Nyboe, Tom Madsen, Michael Seifert, and Sebastian Hammer. DikuMud is also licensed software; you are legally bound to comply with the original DikuMud license as well as the CircleMUD license if you wish to use CircleMUD.
\par
Use of the CircleMUD code in any capacity implies that you have read, understood, and agreed to abide by the terms and conditions set down by this license and the DikuMud license. If you use CircleMUD without complying with the license, you are breaking the law.
\par
Using CircleMUD legally is easy. In short, the license requires three things:
\begin{enumerate}
\item You must not use CircleMUD to make money or be compensated in any way.
\item You must give the authors credit for their work.
\item You must comply with the DikuMud license.
\end{enumerate}
That's it -- those are the main conditions set down by this license. Unfortunately, past experience has shown that many people are not willing to follow the spirit of the license, so the remainder of this document will clearly define those conditions in an attempt to prevent people from circumventing them.
\subsection{You must not use CircleMUD to make money or be compensated in any way.}
The first condition says that you must not use CircleMUD to make money in any way or be otherwise compensated. CircleMUD was developed in people's uncompensated spare time and was given to you free of charge, and you must not use it to make money. CircleMUD must not in any way be used to facilitate your acceptance of fees, donations, or other compensation. Examples include, but are not limited to the following:
\begin{itemize}
\item If you run CircleMUD, you must not require any type of fee or donation in exchange for being able to play CircleMUD. You must not solicit, offer or accept any kind of donation from your players in exchange for enhanced status in the game such as increased levels, character stats, gold, or equipment.
\item You must not solicit or accept money or other donations in exchange for running CircleMUD. You must not accept money or other donations from your players for purposes such as hardware upgrades for running CircleMUD.
\item You must not sell CircleMUD. You must not accept any type of fee in exchange for distributing or copying CircleMUD.
\item If you are a CircleMUD administrator, You must not accept any type of reimbursement for money spent out of pocket for running CircleMUD, i.e., for equipment expenses or fees incurred from service providers.
\end{itemize}
\subsection{You must give the authors credit for their work.}
The second part of the license states that you must give credit to the creators of CircleMUD. A great deal of work went into the creation of CircleMUD, and it was given to you completely free of charge; claiming that you wrote the MUD yourself is a slap in the face to everyone who worked to bring you a high quality product while asking for nothing but credit for their work in return.
\par
Specifically, the following are required:
\begin{itemize}
\item The text in the `\texttt{credits}' file distributed with CircleMUD must be preserved. You may add your own credits to the file, but the existing text must not be removed, abridged, truncated, or changed in any way. This file must be displayed when the `\texttt{credits}' command is used from within the MUD.
\item The ``\texttt{CIRCLEMUD}'' help entry must be maintained intact and unchanged, and displayed in its entirety when the `\texttt{help circlemud}' command is used.
\item The login sequence must contain the names of the DikuMud and CircleMUD creators. The 'login sequence' is defined as the text seen by players between the time they connect to the MUD and when they start to play the game itself.
\item This license must be distributed AS IS with all copies or portions of the CircleMUD that you distribute, if any, including works derived from CircleMUD.
\item You must not remove, change, or modify any notices of copyright, licensing or authorship found in any CircleMUD source code files.
\item Claims that any of the above requirements are inapplicable to a particular MUD for reasons such as ``our MUD is totally rewritten'' or similar are completely invalid. If you can write a MUD completely from scratch then you are encouraged to do so by all means, but use of any part of the CircleMUD or DikuMud source code requires that their respective licenses be followed, including the crediting requirements.
\end{itemize}
\subsection{You must comply with the DikuMud license.}
The third part of the license simply states that you must comply with the DikuMud license. This is required because CircleMUD is a DikuMud derivative. The DikuMud license is included below.
\par
You are allowed to use, modify and redistribute all CircleMUD source code and documentation as long as such use does not violate any of the rules set down by this license.
\par
--Jeremy Elson
\par
CircleMUD 3 -- Copyright \copyright 1994-2001, The CircleMUD Group\newline
Other portions copyright by authors as noted in ChangeLog and source code.
\section{DikuMud License}
Everything below this point is the original, unmodified DikuMud license. You must comply with the CircleMUD license above, as well as the DikuMud license below.
\begin{verbatim}
/* ************************************************************************
* Copyright (C) 1990, 1991 *
* All Rights Reserved *
************************************************************************* */
DikuMud License
Program & Concept created by
Sebastian Hammer
Prss. Maries Alle 15, 1
1908 Frb. C.
DENMARK
(email quinn@freja.diku.dk)
Michael Seifert
Nr. Soeg. 37C, 1, doer 3
1370 Copenhagen K.
DENMARK
(email seifert@freja.diku.dk)
Hans Henrik St{rfeldt
Langs} 19
3500 V{rl|se
DENMARK
(email bombman@freja.diku.dk)
Tom Madsen
R|de Mellemvej 94B, 64
2300 Copenhagen S.
DENMARK
(email noop@freja.diku.dk)
Katja Nyboe
Kildeg}rdsvej 2
2900 Hellerup
31 62 82 84
DENMARK
(email katz@freja.diku.dk)
This document contains the rules by which you can use, alter or publish
parts of DikuMud. DikuMud has been created by the above five listed persons
in their spare time, at DIKU (Computer Science Instutute at Copenhagen
University). You are legally bound to follow the rules described in this
document.
Rules:
!! DikuMud is NOT Public Domain, shareware, careware or the like !!
You may under no circumstances make profit on *ANY* part of DikuMud in
any possible way. You may under no circumstances charge money for
distributing any part of dikumud - this includes the usual $5 charge
for "sending the disk" or "just for the disk" etc.
By breaking these rules you violate the agreement between us and the
University, and hence will be sued.
You may not remove any copyright notices from any of the documents or
sources given to you.
This license must *always* be included "as is" if you copy or give
away any part of DikuMud (which is to be done as described in this
document).
If you publish *any* part of dikumud, we as creators must appear in the
article, and the article must be clearly copyrighted subject to this
license. Before publishing you must first send us a message, by
snail-mail or e-mail, and inform us what, where and when you are
publishing (remember to include your address, name etc.)
If you wish to setup a version of DikuMud on any computer system, you
must send us a message , by snail-mail or e-mail, and inform us where
and when you are running the game. (remember to include
your address, name etc.)
Any running version of DikuMud must include our names in the login
sequence. Furthermore the "credits" command shall always cointain
our name, addresses, and a notice which states we have created DikuMud.
You are allowed to alter DikuMud, source and documentation as long as
you do not violate any of the above stated rules.
Regards,
The DikuMud Group
Note:
We hope you will enjoy DikuMud, and encourage you to send us any reports
on bugs (when you find 'it'). Remember that we are all using our spare
time to write and improve DikuMud, bugs, etc. - and changes will take their
time. We have so far put extremely many programming hours into this project.
If you make any major improvements on DikuMud we would be happy to
hear from you. As you will naturally honor the above rules, you will receive
new updates and improvements made to the game.
\end{verbatim}
\end{document}
\end

View File

@ -0,0 +1,87 @@
\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 <furry@cambot.circlemud.org> on Dec 6/2001
\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}
\title{Porting CircleMUD to New Platforms}
\author{Jeremy Elson}
\begin{document}
\maketitle
\begin{abstract}
CircleMUD is a very portable program by design, but is not guaranteed to run on every platform that exists. This document is for experienced programmers trying to make CircleMUD work on their platform.
\end{abstract}
\section{Introduction}
CircleMUD should work on most UNIX platforms without any modifications; simply run the ``\texttt{configure}'' script and it should automatically detect what type of system you have and anything that may be strange about it. These findings are all stored in a header file called \texttt{conf.h} which is created in the src directory from a template called \texttt{conf.h.in}. A \texttt{Makefile} is also created from the template \texttt{Makefile.in}.
\par
Non-UNIX platforms are a problem. Some can't run CircleMUD at all. However, any multitasking OS that has an ANSI C compiler, and supports non-blocking I/O and socket-based TCP/IP networking, should theoretically be able to run CircleMUD; for example, OS/2, AmigaOS, Mac OS (Classic versions; Mac OS X supports CircleMUD's configure script from the command line), Windows 3.11/NT/9*.
\par
The port can be very easy or very difficult, depending mainly on whether or nor your OS supports the Berkeley socket API. Windows 95, for example, supports Berkeley sockets with a few modifications using the WinSock library, and OS/2 supports Berkeley sockets with no source changes at all.
\par
The general steps for porting CircleMUD to a non-UNIX platform are listed below. A number of tips for porting can be found after the porting steps. Note that we have already ported Circle to Windows 95, so if you're confused as to how to perform some of these steps, you can look at what we have done as an example (see the files \texttt{conf.h.win}, \texttt{Makefile.win} and \texttt{README.WIN}).
\par
Note that you should not try to do this unless you are an experienced C programmer and have a solid, working knowledge of the system to which you are trying to port the code.
\section{Porting the Code}
\begin{description}
\item[Step 1.] Create a ``\texttt{conf.h}'' file for your system.\newline
Copy the template ``\texttt{conf.h.in}'' to ``\texttt{conf.h}'', and then define or undefine each item as directed by the comments and based on the characteristics of your system. To write the \texttt{conf.h} file, you'll need to know which header files are included with your system, the return type of signals, whether or not your compiler supports the `\texttt{const}' keyword, and whether or not you have various functions such as \texttt{crypt()} and \texttt{random()}.\newline
Also, you can ignore the \texttt{HAVE\_LIBxxx} and \texttt{HAVE\_xxx\_PROTO} constants at the end of \texttt{conf.h.in}; they are not used in the code (they are part of UNIX \texttt{autoconf}).
\item[Step 2.] Create a \texttt{Makefile}.\newline
Again, copy the template \texttt{Makefile.in} and make any changes which may be appropriate for your system. Make sure to remove the \texttt{@xxx@} variables such as \texttt{@LIBS@}, \texttt{@CC@}, \texttt{@NETLIB@}, etc., and replace them with the appropriate values if necessary.
\item[Step 3.] Make the appropriate patches to the code so that the TCP/IP reads and writes and signal handling are compatible with your system. This is the hardest part of porting CircleMUD. All of the changes you will need to make will probably be in the source file \texttt{comm.c}.
\item[Step 4.] Test your changes! Make sure that multiple people can log in simultaneously and that they can all type commands at the same time. No player should ever have a ``frozen'' screen just because another is waiting at a prompt. Leave the MUD up for at least 24 hours, preferably with people playing it, to make sure that your changes are stable. Make sure that automatic events such as zone resets, point regeneration, and corpse decomposition are being timed correctly (a tick should be about 75 seconds). Try resetting all the zones repeatedly by typing ``\texttt{zr *}'' many times. Play the MUD and make sure that the basic commands (killing mobs as a mortal, casting spells, etc.) work correctly.
\item[Step 5.] If you are satisfied that your changes work correctly, you are encouraged to submit them to be included as part of the stock CircleMUD distribution so that future releases of Circle will support your platform. This prevents you from re-porting the code every time a new version is released and allows other people who use your platform to enjoy CircleMUD as well.\newline
To submit your changes you must make a patch file using the GNU `\texttt{diff}' program which can be downloaded by anonymous FTP from \url{ftp://ftp.gnu.org:/pub/gnu/diffutils-x.x.tar.gz}. \texttt{diff} will create a patch file which can be later used with the `\texttt{patch}' utility to incorporate your changes into the stock CircleMUD distribution. For example, if you have a copy of stock (plain) CircleMUD in the ``\texttt{stock-circle}'' directory, and your changes are in ``\texttt{my-circle}'', you can create a patch file like this:
\begin{verbatim}
diff -u --new-file --recursive stock-circle/src my-circle/src > patch
\end{verbatim}
This will create a file called `\texttt{patch}' with your patches. You should then try to use the `\texttt{patch}' program (the inverse of `\texttt{diff}') on a copy of stock circle to make sure that Circle is correctly changed to incorporate your patches.\newline
This step is very important: if you don't create these patches correctly, your work will be useless because no one will be able to figure out what you did! Make sure to read the documentation to `\texttt{diff}' and `\texttt{patch}' if you don't understand how to use them.\newline
If your patches work, CELEBRATE!!
\item[Step 6.] Write a \texttt{README} file for your operating system that describes everything that has to be done by another user of your operating system to get CircleMUD to compile from scratch. You should include a section on required hardware, software, compilers, libraries, etc. Also include detailed, step-by-step instructions on how to compile and run everything. You can look at the other \texttt{README} files in the distribution (\texttt{README.WIN}, \texttt{README.OS2}, etc.) for examples of what your \texttt{README} file should include.
\item[Step 7.] You are done! Congratulations! Mail your \texttt{conf.h}, \texttt{Makefile}, patches,
and \texttt{README} file to the CircleMUD Group $<$cdev@circlemud.org$>$ so that they can be included in future releases of CircleMUD. Please share your work so that other users of your OS can use Circle, too.
\end{description}
\section{Porting Tips}
Some tips about porting:
\subsection{Making your own \texttt{CIRCLE\_system} constant}
Each system to which Circle is already ported has a \texttt{CIRCLE\_xx} constant associated with it: \texttt{CIRCLE\_UNIX} for plain vanilla UNIX CircleMUD, \texttt{CIRCLE\_WINDOWS} for MS Win95/NT, \texttt{CIRCLE\_OS2} for IBM OS/2, and \texttt{CIRCLE\_AMIGA} for the Amiga. You must use a similar constant for your system. At the top of your \texttt{conf.h}, make sure to comment out ``\texttt{\#define CIRCLE\_UNIX}'' and add ``\texttt{\#define CIRCLE\_YOUR\_SYSTEM}''.
\subsection{ANSI C and GCC}
As long as your system has an ANSI C compiler, all of the code (except for \texttt{comm.c}) should compile with no major complaints. However, Circle was written using \texttt{gcc}, and some compilers are nitpicky about things that \texttt{gcc} does not care about (and the other way around). Therefore, you are {\em highly} encouraged to use \texttt{gcc} if at all possible. \texttt{gcc} has been ported to a very large number of platforms, possibly including yours, and your port will be made much easier if you use \texttt{gcc}. You can download \texttt{gcc} via anonymous FTP from \url{ftp://ftp.gnu.org:/pub/gnu/}.
\subsection{Non-Blocking I/O}
Make absolutely sure to use non-blocking I/O; i.e.\ make sure to enable the option so that the \texttt{read()} system call will immediately return with an error if there is no data available. If you do {\em not} use non-blocking I/O, \texttt{read()} will ``block,'' meaning it will wait infinitely for one particular player to type something even if other players are trying to enter commands. If your system does not implement non-blocking I/O correctly, try using the \texttt{POSIX\_NONBLOCK\_BROKEN} constant in \texttt{sysdep.h}.
\subsection{Timing}
CircleMUD needs a fairly precise (on the order of 5 or 10 ms) timer in order to correctly schedule events such as zone resets, point regeneration (``ticks''), corpse decomposition, and other automatic tasks. If your system supports the \texttt{select()} system call with sufficient precision, the default timing code should work correctly. If not, you'll have to find out which system calls your system supports for determining how much time has passed and replace the \texttt{select()} timing method.
\subsection{Signals and Signal Handlers}
A note about signals: Most systems don't support the concept of signals in the same way that UNIX does. Since signals are not a critical part of how Circle works anyway (they are only used for updating the wizlist and some other trivial things), all signal handling is turned off by default when compiling under any non-UNIX platform (i.e.\ the Windows 95 and Amiga ports do not use signals at all.) Simply make sure that \texttt{CIRCLE\_UNIX} is {\em not} defined in your \texttt{conf.h} file and all signal code will be ignored automatically.
\section{Final Note}
{\bf IMPORTANT:} Remember to keep any changes you make surrounded by \texttt{\#ifdef} statements (i.e.\ ``\texttt{\#ifdef CIRCLE\_WINDOWS} ... \texttt{\#endif}''). If you make absolutely sure to mark all of your changes with \texttt{\#ifdef} statements, then your patches (once you get them to work) will be suitable for incorporation into the CircleMUD distribution, meaning that CircleMUD will officially support your platform.
\end{document}
\end

View File

@ -0,0 +1,258 @@
\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 <furry@circlemud.org> on Dec 9/2001
\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}{0pt}
\title{CircleMUD Release History}
\author{Jeremy Elson}
\begin{document}
\maketitle
\begin{abstract}
This document is basically just a a compliation of all the \texttt{README} files which accompanied each release of CircleMUD. At the end is the post to \texttt{rec.games.mud.diku} which originally anounced CircleMUD as a publically available MUD source code.
\end{abstract}
\begin{itemize}
\item Version 2.20: November 17, 1993
\item Version 2.11: September 19, 1993
\item Version 2.10: September 1, 1993
\item Version 2.02: Early August
\item Version 2.01: July 20, 1993
\item Version 2.00: July 16, 1993
\end{itemize}
The latest production version of Circle is 2.20, released on November 17, 1993. Version 2.20 supercedes version 2.11, which was released on September 19, 1993.
\section{Version 2.20 - November 17, 1993}
New features:
\begin{itemize}
\item A completely new output buffering system which is far more network-efficient, and somewhat more memory- and speed-efficient, than the original Diku system. Definitely a major win for people with slow Net links. (Details available by request, but this was discussed on rgmd recently.) Several other functions (such as do\_where() and do\_who()) have been rewritten to take advantage of the new system.
\item Redesigned stat screens with better readability
\item Command-line substitution via the ``\^{}'' character (works identically to the csh command)
\item Code sent by Jeff Fink (thanks Jeff!): Help now handles ambiguous cases correctly (i.e., ``help color'' will give you help for color and not colorspray)
\item vstat command to stat mobiles and object by virtual number
\item updated documentation
\end{itemize}
And, bug fixes of varying degrees of severity:
\begin{itemize}
\item SunOS Bus errors on stealing
\item +hit item bug
\item Switched immort re-login bug
\item Mob memory bug
\item Poison/Stat bug (I think this one is native to Diku Gamma 0.0 -- the function hit\_gain was responsible for subtracting hits when a char is poisoned, so you'd lose hits when someone statted you.)
\item Stat room bug under Solaris and IRIX
\item Ungroup bug
\item ``goto 3.guard'' now works (takes you to the third guard instead of room 3)
\item various other minor fixes
\end{itemize}
\section{Version 2.11 - September 19, 1993}
Changes in 2.11 (from 2.10):\newline
Mostly bug fixes, including:
\begin{itemize}
\item SET FILE bug
\item SIGBUS/unaligned data errors under SunOS and other OS's
\item Move limit modifier bug
\item wrist-wearing bug
\item Compilation problems with utility.c under some operating systems
\end{itemize}
The only notable change is that the hit\_limit, move\_limit, and mana\_limit functions have been removed (for many reasons). From the players' point of view, this means that a character no longer gains movement points with age. Hit, move, and mana gain speeds are still a function of age, however.
\section{Version 2.10 - September 1, 1993}
Changes in 2.10 (from 2.01):
\begin{itemize}
\item Rewritten get/put/drop/junk/donate/give/wear/remove, so that ``all'' and ``all.x'' work in a much wider variety of cases. Loosely based on code sent in by Jeff Fink.
\item ``Track'' function based on breadth-first search
\item Configurable auto-save feature to automatically crash-save players periodically
\item More intense error-checking in object saving system to detect problems with file permissions
\item Many configuration options added to config.c
\item Option to make death traps automatically have dump spec-proc assigned
\item ASPELL and ACAST macros added to match the ACMD macros; spells1.c, spells2.c, spell\_parser.c, and magic.c changed to use the macros.
\item SKILL macro split into GET\_SKILL and SET\_SKILL macros so that error checking can be done
\item Enhanced documentation -- a help entry now exists for every command
\item Linux compatibility, and further steps to SVR4 compatibility which will make it into Circle eventually. (Note: you must make a change in one line of the Makefile for Linux compatibility.)
\item All functions now prototyped before use
\end{itemize}
Jeremy Elson\newline
August 31, 1993
\section{Version 2.01 - July 20, 1993}
Version 2.01 is basically the same as 2.00; most of the changes are for making the MUD more portable, based on mail I've received after the release of version 2.00.
\begin{itemize}
\item Problems with OPEN\_MAX and SEEK\_x resolved
\item Some problems with the Makefile fixed
\item Compiles much more cleanly with the -Wall option
\item A couple of minor bugs fixed
\item A few small fixes to the documentation
\end{itemize}
July 20, 1993
\section{Version 2.00 - July 16, 1993}
CircleMUD was developed and tested under Ultrix 4.0; your mileage may vary. If I have time, I'll try and port it to other machines. If you port it and want to share your work with others, feel free to drop me a line.
\par
The CircleMUD `press release' is included below, in case you haven't seen it and want to.
\par
Good Luck!
\par
Jeremy Elson aka Rasmussen (Ras)\newline
July 16, 1993
\begin{verbatim}
Wake the kids and find the dog, because it's the FTP release of
C I R C L E M U D 2 . 0
That's right -- CircleMUD 2.0 is done and is now available for anonymous FTP
at ftp.cs.jhu.edu!
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 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.
Just take a gander at some of Circle's nifty features:
-- In-memory mobile and object prototypes and string sharing for
decreased memory usage and blazingly fast zone resets
-- All large realloc()s have been removed and replaced by boot-time
record counting and a single malloc() for superior memory efficiency
-- Split world/obj/mob/zon/shp files for easy addition of areas; plus,
all the world files are still in the original Diku format for
compatibility with existing areas
-- Boot-time and run-time error checking of most data files with
diagnostic messages a lot more helpful than "segmentation fault"!
-- Player mail system and bank
-- Rewritten board system: boards are now stable, robust, more
intelligent, and easily expandable -- adding a new board is
as easy as adding another line to an array
-- ANSI color codes with a fully documented programmers' interface
-- On-line system logs
-- Optional automatically regenerating wizlist -- a final end
to new immortals constantly asking you when they'll be added
to the immlist!
-- "config.c" file allows you to change aspects of the game such
as playerkilling/playerthieving legality, max number of objects
rentable, and nameserver usage -- WITHOUT recompiling the
entire MUD!
-- All text (help, mortal/immort MOTDs, etc.) is rebootable at
run-time with the "reboot" command
-- All players are given a unique serial number -- no more messy,
time consuming str_cmp()s when you're trying to identify people!
-- Fully integrated and robust rent/crash system -- allows normal
renting, cryo-renting, crash protection, and forced rent
(at an increased price) after an hour of idling
-- All the standard wizard stuff you're used to: level-sensitive
invisibility, settable poofin/poofouts, wizline
-- Advanced 'set' command which allows you to set dozens of aspects
of players -- even if they aren't logged in! "Stat" also allows
you to stat people who aren't logged in!
-- Intelligent 'autorun' script handles different types of reboots,
organizing your system logs, and more!
-- Circle comes with more than a dozen utilities, all fully
documented, to make maintenance a snap!
-- And much, much more!
Unfortunately, the original Circle had more than its fair share of Bad People
when it was alive, but it DID lead to an impressive list of security and
"asshole control" features:
-- 3 types of sitebanning available: 'all' to refuse all connections,
'new' to refuse new players, or 'select' to refuse new players and
all registered players who don't have a SITEOK flag.
-- 'wizlock' allows you to close the game to all new players or all
players below a certain level.
-- Handy 'mute' command squelches a player off of all public
communication channels
-- Handy 'freeze' command freezes a player in his tracks: the MUD
totally ignores all commands from that player until he's thawed.
-- Even handier DELETE flag allows you to delete players on the fly.
-- 'set' command (mentioned above) allows you to freeze/unfreeze/
delete/siteok/un-siteok players -- even if they aren't logged in!
-- Bad password attempts are written to the system log and saved;
if someone tries to hack your account, you see "4 LOGIN FAILURES
SINCE LAST SUCCESSFUL LOGIN" next time you log on.
-- Passwords don't echo to the screen; allows 3 bad PW attempts
before disconnecting you.
-- Players aren't allowed to choose their character's name as their
password -- you'd be surprised how many do!
-- "xnames" text file specifies a list of invalid name substrings
to prevent creation of characters with overly profane names.
Listen to all the rave reviews of CircleMUD 2.0!
"How long ago was that deadline you set for yourself?" -- My Friend
"NO ONE should be denied the power of computation." -- My Professor
"Multi-user WHAT?" -- My Mom
Give it a try -- what do you have to lose other than your GPA/job, friends,
and life?
---------------------------------------------------------------------------
Circle's complete source code and areas are available now for anonymous FTP
at ftp.cs.jhu.edu (128.220.13.50) in the directory pub/CircleMUD.
I welcome comments and constructive criticism about CircleMUD and would be
happy to discuss any design decisions I've made, but I'm not particularly
receptive to lunatics frothing at the mouth and thus will probably ignore
you if you flame me.
Also, remember the odds here: one person (me) against 29,000 lines of
code (Circle), so there are bound to be some mistakes in there somewhere.
Good luck, and happy Mudding,
Jeremy Elson aka Ras
\end{verbatim}
\end{document}
\end

View File

@ -0,0 +1,73 @@
\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 <furry@circlemud.org> on Dec 4/2001
\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}
\title{CircleMUD Socials}
\author{Jeremy Elson}
\begin{document}
\maketitle
\begin{abstract}
This document is a description of how to create new `social' commands in CircleMUD. C programming experience generally not required at all for creating new CircleMUD socials. The intended audience for this document is all CircleMUD administrators. This document ties together closely with the document on the \texttt{act()} function.
\end{abstract}
\section{Introduction}
A general system exists to handle the `social' commands -- those which generally have no game-related purpose other than to convey emotions between players. Socials are also useful for creating advanced DikuMud adventures and quests through the use of speical procedures; for example, you could add a `detonate' social which, within your quest, is handled by a special procedure to cause something to explode.
\par
Socials are all handled through the generalized command \texttt{do\_action}. The
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.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}
<command name> <hide-flag> <minimum position of victim>
<messg to character if no argument>
<messg to others if no argument>
<messg to char if victim found> <---If this field is empty,
<messg to others if victim found> <-
<messg to victim> | then these fields must be
<messg to char if victim not found> | skipped, and the action will
<messg to char if vict is char> | ignore arguments.
<messg to others if vict is char> <-
<command name> <hide-flag> <minimum position of victim>
.
.
$~
\end{verbatim}
Each social must contain either 1) only the first two messages (if the social ignores arguments), or 2) all eight messages (if the social takes an argument). Each message must be contained in one line.
\par
The command-name indicates which social is being specified. The hide-flag can be either 0 or 1; if 1, the social is hidden from OTHERS if they cannot see the character performing the social. The action is not hidden from the VICTIM, even if s/he cannot see the character performing the social, although in such cases the character's name will, of course, be replaced with ``\texttt{someone}''.
\par
Where it makes sense to do so, text fields may be left empty. This is done by putting a `\#' in the first column on the line. Doing so is legal in the following fields:
\begin{itemize}
\item a: messg to others if no arg
\item b: messg to others if victim found
\item c: messg to others if vict is char
\end{itemize}
Note again that if the field {\it messg to char if victim found} is empty, then the following fields must be omitted entirely (not even the `\~{}'), and the action will ignore any arguments supplied.
\par
The procedure sends the text strings through \texttt{act()}, and they may contain control codes (see the documentation for the \texttt{act()} function for details.) Note that not all of \texttt{act()}'s control codes may be used; for example, codes which refer to objects such as \texttt{\$p}.
\par
For the sake of efficiency, no tests or sanity checks are made on the consistency or logic of the \texttt{act()} codes found in the social messages. Hence, grave disorder may result if, say, the code `\texttt{\$N}' occurs in a text field that does not refer to a victim; like {\it messg to others if no arg}.
In previous versions of Circle, such grave disorder often manifested itself in the form of crashes. However, the \texttt{act()} function itself in CircleMUD 3.0 and above does sanity checks to make sure it is not dereferencing null pointers, hopefully with the result of avoiding crashes. Nevertheless, great care should be taken in making sure that the \$ codes of socials are used consistently and correctly.
\par
More information can be found in the documentation on the \texttt{act()} function.
\end{document}
\end

View File

@ -0,0 +1,158 @@
\documentclass[11pt]{article}
\usepackage{url}
\usepackage{times}
\usepackage[T1]{fontenc}
% This document typeset by Alex Fletcher <furry@circlemud.org> on Dec 9/2001
\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}{0pt}
\title{CircleMUD Utility Programs}
\author{Alex Fletcher}
\begin{document}
\maketitle
\begin{abstract}
This document gives a brief summary of the various utility programs that come with the CircleMUD distribution. The summaries include the description of the utility, how it is called, and any caveats to watch out for when using them.
\end{abstract}
\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 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 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
The command line syntax for \texttt{play2to3} is as follows:
\begin{verbatim}
play2to3 <old plrfile> <new plrfile>
\end{verbatim}
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 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}
shopconv <file1> [<file2> .. <filen>]
\end{verbatim}
where \texttt{$<$file1$>$} is the first file to convert, \texttt{$<$file2$>$} the second, and so forth.
\subsection{split}
The split utility is designed to split large world files into smaller, zone-sized files that are easier to manage and maintain. The utility reads its input from the standard input and writes the output to files with names specified within the larger world file. This is done by inserting `\texttt{={\it filename}}' into the world file at the appropriate points, where {\it filename} is the name of the file for the following section.
\par
The command line syntax for \texttt{split} is as follows:
\begin{verbatim}
split < [filename]
\end{verbatim}
where \texttt{[filename]} is the file to redirect into the utility. The syntax above indicates how to do this on platforms that support command line redirection.
\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 at
\url{<http://www.circlemud.org/~jelson/dikutest/>}.
\par
The command line syntax for \texttt{wld2html} is as follows:
\begin{verbatim}
wld2html <wldfile>
\end{verbatim}
where \texttt{$<$wldfile$>$} is the world file to be turned into web pages.
\section{Maintenance Utilities}
\subsection{mudpasswd}
The \texttt{mudpasswd} utility allows you to change the password of any player from the shell prompt. It does not require any verification beyond the initial login to the shell account.
\par
The command line syntax for \texttt{mudpasswd} is as follows:
\begin{verbatim}
mudpasswd <plrfile> <charname> <newpwd>
\end{verbatim}
where \texttt{$<$plrfile$>$} is your player file, \texttt{$<$charname$>$} is the name of the character to change the password for, and \texttt{$<$newpwd$>$} is the new password for the character.
\par
This utility must be recompiled if you make any changes to the player file structure.
\subsection{purgeplay}
This utility is used to purge {\em useless} players from the game's player file. It is best to run this utility fairly regularly, but it should only be run when the CircleMUD server is not running. It will delete all players that have had the \texttt{DELETED} flag set, except for those that also have the \texttt{NODELETE} flag set.
\par
The \texttt{purgeplay} utility will also remove idle players from the player file. For example, any character with an invalid name, of level 0 (or less) or, of a level greater than \texttt{LVL\_IMPL} will be immediately marked for removal. Level 1 characters that have not played for 4 days will be removed, as will characters of levels 2-4 that have not played for 7 days, levels 5-10 that have not played for 30 days, levels 11-30 that have not played for 60 days, and immortals that have not played for 90 days.
\par
The command line syntax for \texttt{purgeplay} is as follows:
\begin{verbatim}
purgeplay <plrfile>
\end{verbatim}
where \texttt{$<$plrfile$>$} is your player file.
\par
This utility must be recompiled if you make any changes to the player file structure.
\subsection{sign}
This utility allows you to display some static text on a port when anyone connects to it. This is useful when the mud server is moving, changing ports, or is down for maintenance.
\par
The command line syntax for \texttt{sign} is as follows:
\begin{verbatim}
sign <port> <filename | - (for stdin)>
\end{verbatim}
where \texttt{$<$port$>$} is the tcp port to put the information on. This is usually the same as the mud server port (when the server is not running), which defaults to 4000. The \texttt{$<$filename$>$} is an ASCII file to display on the port when a connection is made to it. If \texttt{-} is specified as a filename, the utility will wait for you to enter the text to be displayed and will take in all text until ended by an EOF marker (\texttt{ctrl}-D on Unix based systems).
\section{Informational Utilities}
\subsection{listrent}
This utility allows you to view player rent files offline. It displays the type of rent; {\em Rent}, {\em Crash}, {\em Cryo}, or lost link ({\em TimedOut}). It also displays the object vnum and first keyword.
\par
The command line syntax for \texttt{listrent} is as follows:
\begin{verbatim}
listrent <objfile1> [<objfile2> .. <objfilen>]
\end{verbatim}
where \texttt{$<$objfile1$>$} is the first object file to view, \texttt{$<$objfile2$>$} the second, and so forth.
\par
This utility must be recompiled if you make any changes to the rent file structure.
\subsection{showplay}
This utility is used to list the contents of the game's player file. It gives a brief summary of the characters contained therein including their idnumber, sex, level, class, name, gold, and banked gold.
\par
The command line syntax for \texttt{showplay} is as follows:
\begin{verbatim}
showplay <plrfile>
\end{verbatim}
where \texttt{$<$plrfile$>$} is the player file to summarize.
\par
This utility must be recompiled if you make any changes to the player file structure.
\section{Internal Utilities}
\subsection{autowiz}
This utility is called from within the CircleMUD server and manages the self-updating Wizlist and Immlist. At this point, it only works on Unix-based systems, but a solution for all other systems is being designed. If you wish to change the text in the headers of the Wizlist or the Immlist, this is the utility to edit.
\par
The command line syntax for \texttt{autowiz} is as follows:
\begin{verbatim}
autowiz <wizlev> <wizlistfile> <immlev> <immlistfile> [pid to signal]
\end{verbatim}
where \texttt{$<$wizlev$>$} is equal to whatever \texttt{LVL\_GOD} is set to in your CircleMUD server, \texttt{$<$wizlistfile$>$} is the filename for the file containing the game's Wizlist. \texttt{$<$immlev$>$} should be set to your game's \texttt{LVL\_IMMORT}, while \texttt{$<$immlistfile$>$} is the name of the Immlist file.
\par
This utility must be recompiled if you make any changes to the player file structure.
\subsection{delobjs}
This utility is to be used in conjunction with the \texttt{purgeplay} utility. It cleans out the rent files for players who no longer exist in the player file. As with \texttt{purgeplay}, this should never be run when the CircleMUD server is running. It is best not to run the \texttt{delobjs} utility on its own, and there is a script in the \texttt{lib/plrobjs/} directory called \texttt{purgeobjs} that should be used in its place. This script will walk through each rent directory and check each and every file to ensure that all of the characters exist.
\par
The command line syntax for \texttt{delobjs} is as follows:
\begin{verbatim}
delobjs <plrfile> <objfile1> [<objfile2> .. <objfilen>]
\end{verbatim}
where \texttt{$<$plrfile$>$} is the player file to search for non-existant players in, \texttt{$<$objfile1$>$} is the first rent file to check, \texttt{$<$objfile2$>$} is the second rent file to check, and so forth.
\par
This utility must be recompiled if you make any changes to the player file or rent file structure.
\end{document}
\end

View File

@ -0,0 +1,493 @@
\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 <furry@circlemud.org> on Dec 9/2001
\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}
\title{CircleMUD Wizard Commands}
\author{Jeremy Elson}
\begin{document}
\maketitle
\begin{abstract}
Help text for all priveldged CircleMUD commands. File is in help text format so that it can be pasted into the \texttt{lib/text/help\_text} if online help is desired.\newline
Intended Audience: CircleMUD immortals, Gods, and player administrators.
\end{abstract}
\begin{verbatim}
ADVANCE
advance <victim> <level>
ADVANCE moves a player to a new level. If used to promote a player to an
immortal level, and if you have the autowiz program installed, the wizlist and
immlist will automatically be recreated.
> advance rasmussen 34
#
WIZAT
AT can be used to perform an action in a location other than where you are
standing. The first argument can be a virtual room number or the name of a
character or object. The remainder of the line is passed to the command
interpreter.
> at 3001 look
> at fido kill fido
> at 3.corpse get all corpse
See also: GOTO
#
BAN UNBAN
These commands prevent anyone from a site with a hostname containing the
site substring from logging in to the game. You may ban a site to ALL, NEW
or SELECT players. Banning a site to NEW players prevents any new players
from registering. Banning a site to ALL players disallows ANY connections
from that site. Banning a site SELECTively allows only players with site-ok
flags to log in from that site. Ban with no argument returns a list of
currently banned sites.
Unban removes the ban.
ban [<'ALL' | 'NEW' | 'SELECT'> <site>]
unban <site>
> ban new ai.mit.edu
> unban ai.mit.edu
#
DATE
Shows the current real time.
#
DC
dc <descriptor number>
DC (DisConnect) is used to disconnect a socket. If used on a playing socket,
the player will lose his/her link, but, unlike PURGE, will not extract the
player or dump the player's inventory on the ground.
DC is also useful for disconnecting people who have accidentally left
themselves at the main menu, or connections sitting in the "Get name" state.
See also: USERS
#
ECHO GECHO SEND
echo <message>
gecho <message>
send <victim> <message>
ECHO displays a string to everyone in your room. GECHO displays the string
to everyone in the game. SEND displays the string to a particular person.
> echo Hi, everyone in the room.
> gecho Hi, everyone in the game, isn't this annoying?
> send rasmussen You are being watched.
#
FORCE
FORCE forces a character, either monster or player, to perform a certain
action. FORCE ALL forces everyone in the game; FORCE ROOM forces everyone in
your room.
> force fido drop meat
> force all save
> force room look fido
#
FREEZE THAW
FREEZE, originally invented here at CircleMUD (we think), is used to prevent
a player from playing. If frozen, the game will ignore all commands entered
by the player, including QUIT, until the player is unfrozen with THAW.
Obviously, this command should only be used in extreme disciplinary
circumstances.
See also: SET FROZEN
#
GOTO TRANS WIZTELEPORT
goto <location>
trans <victim>
teleport <victim> <location>
These commands are used to transports yourself and others to different rooms.
GOTO allows you to go to other rooms; TRANS transports a person from wherever
they are to the room YOU are in; TELEPORT transports your victim to some other
location.
For both GOTO and TELEPORT, the location specifier can be either a virtual
room number, or the name of a character or object.
> goto 3001
> goto rasmussen
> trans fido
> teleport fido 3001
> teleport fido 2.fido
See also: WIZAT, SET ROOM, POOFIN
#
HANDBOOK
Guidelines for having an Immortal character -- you should read it.
#
HOLYLIGHT
A toggle which allows you to see:
Invisible people and objects, even if you don't have 'detect invisibility'
Hidden people, even if you don't have 'sense life'
Dark rooms, even if you don't have a light
It is expected most immortals will keep HOLYLIGHT on most of the time;
it exists so that you have the ability to see what mortals see for
debugging purposes.
#
INVIS
invis [level]
INVIS sets your invisibility level. With no argument, invis toggles between
making you fully visible and fully invisible. If you specify a level, only
people at and above the level you specify will be able to see you.
> invis
> invis 31
#
LAST
last <player_name>
For checking the last time a person logged on, their sitename, and their
ID number.
> last rasmussen
#
LOAD
load <mob|obj> <virtual number>
LOAD is used to create mobiles and objects. The first argument specifies if
you are trying to load a mobile or an object; the second is the virtual
number.
> load obj 3099
> load char 3005
See also: VNUM
#
MUTE
MUTE is used to shut a player up; if a player is muted, he/she will not be
able to use most communication channels until he/she is unmuted.
> mute MrNoisy
#
NOHASSLE
Toggles a flag to prevent aggressive monsters from attacking.
#
NOTITLE
NOTITLE is used to prevent players from being able to set their own titles;
i.e., if the player consistently has an offensive title. The definition of
offensive is left as an exercise for the reader.
#
NOWIZ
Allows you to hear or ignore messages coming over the wizline.
See also: WIZNET
#
PAGE
page <player|'all'> <message>
PAGE is used to send a message, along with a beep, to another player. Use
PAGE ALL to send a message and a beep to everyone in the game.
> page rasmussen Hey, are you still at the keyboard?
> page all GAME WILL BE SHUTTING DOWN IN 10 MINUTES
Do not abuse this command.
#
PARDON
Removes killer and thief flags from a player.
#
POOFIN POOFOUT
Sets the message seen by players when you use GOTO to move to a different
room. POOFIN with no argument resets your poofin to the default "appears with
an ear-splitting bang"; POOFOUT with no argument defaults to "disappears in
a puff of smoke."
See also: GOTO
#
PURGE
purge [name]
Purge destroys things. If used with no arguments, it will clear a room of all
mobiles and objects, but will not harm players. If the argument is an object,
that object (and all of its contents, if any) will be destroyed. If the
argument is a mobile, the mobile will be destroyed, leaving its inventory and
equipment lying on the ground.
If the argument is the name of a player, the player's inventory and equipment
will drop on the ground and the player will lose his/her connection. For this
reason, PURGE should only be used on players in disciplinary situations.
> purge
> purge <character>
> purge <object>
See also: DC
#
REBOOT
reboot <'*'|file>
REBOOT is used to load text files such as the MOTD from disk into memory.
REBOOT * reads all text files. Valid files are:
#
REROLL
reroll <player>
REROLL gives a player new stats (i.e., str, int, wis, dex, and con.)
#
RESTORE
RESTORE restores a player or mobile to full hit, mana, and move points. If
used on immortals, it sets all skill levels to 100%.
#
RETURN
RETURN returns you to your regular body if you are switched.
See also: SWITCH
#
ROOMFLAGS
Toggles a flag which causes the virtual room number and room flags, if any,
to be displayed next to room names.
#
SET
set [file|player] <character> <field> <value>
SET is an extremely powerful command, capable of setting dozens of aspects of
characters, both players and mobiles.
SET PLAYER forces set to look for a player and not a mobile; useful for
players with lame names such as 'guard'.
SET FILE lets you change players who are not logged on. If you use SET FILE
on a player who IS logged on, your change will be lost. If you wish to set
a player who is in the game but is linkless, use set twice -- once with the
FILE argument, and once without -- to make sure that the change takes.
For toggled fields, the value must be ON, OFF, YES, or NO.
Look at do_set in act.wizard.c for a list of valid set fields.
See also: STAT
#
SHOW
show <mode> [argument]
The SHOW command displays information. Some modes of show require additional
information, such as a player name. Show without any arguments shows a list
of valid modes.
#
SHUTDOWN
shutdown [reboot|die|pause]
SHUTDOWN shuts the MUD down. The SHUTDOWN command works in conjunction with
CircleMUD's 'autorun' script. If you are not using autorun, the arguments are
meaningless. If you are using autorun, the following arguments are available:
REBOOT Pause only 5 seconds instead of the normal 60 before trying to
restart the MUD.
DIE Kill the autorun script; the MUD will not reboot until autorun is
explicitly run again.
PAUSE Create a file called 'paused' in Circle's root directory; do not
try to restart the MUD until 'paused' is removed.
#
SLOWNS
Toggles the namserver_is_slow setting. See circle/src/config.c for
more information.
#
SNOOP
Snoop allows you to listen in on another player's session; everything the
player sees or types will be displayed on your terminal preceeded by a '%'.
Obviously, there are many ethical considerations to the use of this command;
snoop should be used minimally, and only for disciplinary purposes.
Type snoop <your name> to stop snooping.
#
SNOWBALL
Snowball is just a social -- it prints a funny message, and nothing more.
#
STAT
STAT [player|object|mobile|file] <name>
Gives information about players, monsters, and objects in the game. The type
argument is optional.
STAT PLAYER will search only for players; useful for statting people with lame
names such as Red or Cityguard.
STAT OBJECT will search only for objects.
STAT MOBILE will search only for monsters.
STAT FILE is used to stat players who are not logged in; the information
displayed comes from the playerfile.
> stat fido
> stat player red
> stat mobile red
> stat file rasmussen
> stat object thunderbolt
See also: VSTAT
#
SWITCH
switch <monster>
SWITCH is used to take over the body of mobiles; useful for interactive
adventures.
See also: RETURN
#
SYSLOG
The SYSLOG command controls how detailed of an on-line system log you see.
Messages surrounded by '[' and ']' are syslog messages and are in green
if you have color on.
The messages you receive are level dependent.
syslog <off | brief | normal | complete>
> syslog complete
> syslog off
See also: COLOR
#
UNAFFECT
unaffect <victim>
Removes all affections (i.e., spell effects) from a player.
#
UPTIME
Displays when the game was booted and calculates how long ago that was.
> uptime
#
USERS
USERS gives a list of all sockets (i.e., connections) currently active on the
MUD. The multi-column display shows the socket number (used by DC), class,
level, and name of the player connected, connection state, idle time, and
hostname.
The following switches are available:
-k or -o Show only outlaws (killers and thieves)
-p Show only sockets in the playing sockets
-d Show only non-playing (deadweight) sockets.
-l min-max Show only sockets whose characters are from level min to max
-n <name> Show the socket with <name> associated with it.
-h <host> Show all sockets from <host>.
-c list Show only sockets whose characters' classes are in list
See also: DC
#
VNUM
vnum <mob|obj> <name>
Gives a list of the virtual numbers of objects or mobiles which have the
specified name.
> vnum obj ring
> vnum mob dragon
#
VSTAT
vstat <mob|obj> <virtual number>
Used to stat a prototypical mobile or object by virtual number.
> vstat obj 3000
> vstat mob 3001
See also: STAT VNUM LAOD
#
WIZHELP
Gives a list of the special commands available at your level.
#
WIZLOCK
wizlock [value]
WIZLOCK allows you to restrict the game. WIZLOCK 1 prevents new characters
from being created. WIZLOCK n, 2 <= n <= 34, prevents new characters and
allows only characters level n and above to log on. WIZLOCK with no argument
displays the current WIZLOCK level.
#
WIZNET ;
The immortal communication channel.
wizsay [ '@' | '+' | '-' | '#' ] [<text>]
>; <text> - just sends text
>; @ - shows all gods that are on and visible to you
- also shows if the gods who are visible to you are writing
>; + - allows you to hear the wizchannel
>; - - turns off the wizchannel
This code was provided by Gnort.
See also: NOWIZ
#
ZRESET
zreset <zone | '*' | '.'>
Used to force a zone to reset. '*' forces all zones to reset. '.' forces
the zone you are in to reset.
See also: SHOW ZONES
#~
\end{verbatim}
\end{document}
\end

View File

@ -0,0 +1,4 @@
Work in progress. Please don't bug me to finish this as only Jeremy knows what he wants here at the moment.
-George Greer
greerga@circlemud.org

BIN
old-codebase/doc/utils.pdf Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More