Merge branch 'master' into feature/unittesting

# Conflicts:
#	.gitignore
#	src/Makefile.in
This commit is contained in:
Thomas Arp 2025-07-02 22:49:38 +02:00
commit b76945f1ff
45 changed files with 1933 additions and 619 deletions

8
.clang-tidy Normal file
View file

@ -0,0 +1,8 @@
Checks: >
-*,
clang-analyzer-*,
bugprone-*,
performance-*,
portability-*
#WarningsAsErrors: '*'
HeaderFilterRegex: 'src/.*'

11
.gitignore vendored
View file

@ -84,4 +84,15 @@ src/test/testfile
.vscode .vscode
.project .project
.settings .settings
.idea
.cproject .cproject
# macOS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

407
CMakeLists.txt Normal file
View file

@ -0,0 +1,407 @@
cmake_minimum_required(VERSION 3.12)
project(TbaMUD C)
set(CMAKE_C_STANDARD 99)
# Include checker modules
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckTypeSize)
include(CheckStructHasMember)
include(CheckSymbolExists)
include(CheckCSourceCompiles)
# Output paths
set(BIN_OUTPUT_DIR ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIR})
# Include source and build paths
include_directories(src ${CMAKE_BINARY_DIR})
# ========== Compiler flags ==========
if (CMAKE_COMPILER_IS_GNUCC)
include(CheckCCompilerFlag)
check_c_compiler_flag(-Wall SUPPORTS_WALL)
check_c_compiler_flag(-Wno-char-subscripts SUPPORTS_WNO_CHAR_SUBSCRIPTS)
if (SUPPORTS_WALL)
set(MYFLAGS "-Wall")
if (SUPPORTS_WNO_CHAR_SUBSCRIPTS)
set(MYFLAGS "${MYFLAGS} -Wno-char-subscripts")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MYFLAGS}")
endif()
endif()
# clang-tidy if available
find_program(CLANG_TIDY_EXE NAMES clang-tidy)
if(CLANG_TIDY_EXE AND STATIC_ANALYSIS)
message(STATUS "clang-tidy enabled: ${CLANG_TIDY_EXE}")
set(CMAKE_C_CLANG_TIDY "${CLANG_TIDY_EXE}")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
else()
message(WARNING "clang-tidy not found. Static analysis disabled.")
endif()
# ========== Header checks ==========
check_include_file("fcntl.h" HAVE_FCNTL_H)
check_include_file("errno.h" HAVE_ERRNO_H)
check_include_file("string.h" HAVE_STRING_H)
check_include_file("strings.h" HAVE_STRINGS_H)
check_include_file("limits.h" HAVE_LIMITS_H)
check_include_file("sys/select.h" HAVE_SYS_SELECT_H)
check_include_file("sys/wait.h" HAVE_SYS_WAIT_H)
check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
check_include_file("unistd.h" HAVE_UNISTD_H)
check_include_file("memory.h" HAVE_MEMORY_H)
check_include_file("assert.h" HAVE_ASSERT_H)
check_include_file("arpa/telnet.h" HAVE_ARPA_TELNET_H)
check_include_file("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file("sys/stat.h" HAVE_SYS_STAT_H)
check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H)
check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H)
check_include_file("netinet/in.h" HAVE_NETINET_IN_H)
check_include_file("netdb.h" HAVE_NETDB_H)
check_include_file("signal.h" HAVE_SIGNAL_H)
check_include_file("sys/uio.h" HAVE_SYS_UIO_H)
check_include_file("mcheck.h" HAVE_MCHECK_H)
check_include_file("stdlib.h" HAVE_STDLIB_H)
check_include_file("stdarg.h" HAVE_STDARG_H)
check_include_file("float.h" HAVE_FLOAT_H)
if (HAVE_STDLIB_H AND HAVE_STDARG_H AND HAVE_STRING_H AND HAVE_FLOAT_H)
set(STDC_HEADERS 1)
endif()
# macros
macro(check_run_return_value CODE EXPECTED_RESULT VAR_NAME)
set(_file "${CMAKE_BINARY_DIR}/check_run_${VAR_NAME}.c")
file(WRITE "${_file}" "${CODE}")
try_run(_run_result _compile_result
${CMAKE_BINARY_DIR} ${_file}
)
if (_compile_result EQUAL 0 AND _run_result EQUAL ${EXPECTED_RESULT})
set(${VAR_NAME} TRUE)
else()
set(${VAR_NAME} FALSE)
endif()
endmacro()
# ========== Function checks ==========
foreach(FUNC gettimeofday select snprintf strcasecmp strdup strerror
stricmp strlcpy strncasecmp strnicmp strstr vsnprintf vprintf
inet_addr inet_aton)
string(TOUPPER "${FUNC}" _upper_name)
check_function_exists(${FUNC} HAVE_${_upper_name})
endforeach()
if (NOT HAVE_VPRINTF)
check_function_exists(_doprnt HAVE_DOPRNT)
endif()
# ========== Type checks ==========
check_type_size("pid_t" HAVE_PID_T)
check_type_size("size_t" HAVE_SIZE_T)
check_type_size("ssize_t" HAVE_SSIZE_T)
set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
check_type_size("socklen_t" HAVE_SOCKLEN_T)
unset(CMAKE_EXTRA_INCLUDE_FILES)
if (NOT HAVE_PID_T)
set(pid_t int)
endif()
if (NOT HAVE_SIZE_T)
set(size_t "unsigned")
endif()
if (NOT HAVE_SSIZE_T)
set(ssize_t int)
endif()
if (NOT HAVE_SOCKLEN_T)
set(socklen_t int)
endif()
# ========== const ==========
check_c_source_compiles("
int main() {
/* Ultrix mips cc rejects this. */
typedef int charset[2]; const charset x;
/* SunOS 4.1.1 cc rejects this. */
char const *const *ccp;
char **p;
/* NEC SVR4.0.2 mips cc rejects this. */
struct point {int x, y;};
static struct point const zero = {0,0};
/* AIX XL C 1.02.0.0 rejects this.
It does not let you subtract one const X* pointer from another in an arm
of an if-expression whose if-part is not a constant expression */
const char *g = \"string\";
ccp = &g + (g ? g-g : 0);
/* HPUX 7.0 cc rejects these. */
++ccp;
p = (char**) ccp;
ccp = (char const *const *) p;
{ /* SCO 3.2v4 cc rejects this. */
char *t;
char const *s = 0 ? (char *) 0 : (char const *) 0;
*t++ = 0;
}
{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
int x[] = {25, 17};
const int *foo = &x[0];
++foo;
}
{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
typedef const int *iptr;
iptr p = 0;
++p;
}
{ /* AIX XL C 1.02.0.0 rejects this saying
\"k.c\", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
struct s { int j; const int *ap[3]; };
struct s *b; b->j = 5;
}
{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
const int foo = 10;
}
; return 0; }
" HAVE_CONST)
if (HAVE_CONST)
set(CONST_KEYWORD const)
else()
set(CONST_KEYWORD "")
endif()
# ========== Struct checks ==========
if (HAVE_NETINET_IN_H)
check_struct_has_member("struct in_addr" s_addr netinet/in.h HAVE_STRUCT_IN_ADDR)
endif()
# ========== crypt()/libcrypt ==========
find_library(CRYPT_LIBRARY crypt)
if (CRYPT_LIBRARY)
message(STATUS "Found libcrypt: ${CRYPT_LIBRARY}")
list(APPEND EXTRA_LIBS ${CRYPT_LIBRARY})
set(_saved_lib_list ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${CRYPT_LIBRARY})
check_include_file("crypt.h" HAVE_CRYPT_H)
check_function_exists(crypt CIRCLE_CRYPT)
check_run_return_value("
#include <string.h>
#include <unistd.h>
${HAVE_CRYPT_H} ? \"#include <crypt.h>\" : \"\"
int main(void)
{
char pwd[11], pwd2[11];
strncpy(pwd, (char *)crypt(\"FooBar\", \"BazQux\"), 10);
pwd[10] = '\\\\0';
strncpy(pwd2, (char *)crypt(\"xyzzy\", \"BazQux\"), 10);
pwd2[10] = '\\\\0';
if (strcmp(pwd, pwd2) == 0)
exit(0);
exit(1);
}
" 0 HAVE_UNSAFE_CRYPT)
set(CMAKE_REQUIRED_LIBRARIES ${_saved_lib_list})
endif()
# ========== network libs ==========
check_function_exists(gethostbyaddr HAVE_GETHOSTBYADDR)
if (NOT HAVE_GETHOSTBYADDR)
message(STATUS "gethostbyaddr() not available, trying nsllib")
find_library(NSL_LIBRARY nsl)
if (NSL_LIBRARY)
message(STATUS "...nsllib found.")
list(APPEND EXTRA_LIBS ${NSL_LIBRARY})
endif()
endif()
check_function_exists(socket HAVE_SOCKET)
if (NOT HAVE_SOCKET)
message(STATUS "socket() not available, trying socketlib")
find_library(SOCKET_LIBRARY socket)
if (SOCKET_LIBRARY)
message(STATUS "...socketlib found")
list(APPEND EXTRA_LIBS ${SOCKET_LIBRARY})
endif()
endif()
# ========== time.h needs special treatment ==========
check_include_file("sys/time.h" HAVE_SYS_TIME_H)
check_include_file("sys/time.h" HAVE_TIME_H)
if (HAVE_SYS_TIME_H AND HAVE_TIME_H)
check_c_source_compiles("
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
int main() {
struct tm *tp;
; return 0; }
" TIME_WITH_SYS_TIME)
endif()
# ========== Determine return value of signal() ==========
check_c_source_compiles("
#include <signal.h>
int handler(int sig) { return 0; }
int main() {
signal(SIGINT, handler);
return 1;
}
" SIGNAL_RETURNS_INT FAIL_REGEX ".*incompatible pointer type.*")
check_c_source_compiles("
#include <signal.h>
void handler(int sig) { }
int main() {
signal(SIGINT, handler);
return 1;
}
" SIGNAL_RETURNS_VOID FAIL_REGEX ".*incompatible pointer type.*")
if (SIGNAL_RETURNS_INT)
message(STATUS "signal() returns int.")
set(RETSIGTYPE int)
elseif (SIGNAL_RETURNS_VOID)
message(STATUS "signal() returns void.")
set(RETSIGTYPE void)
else()
message(FATAL_ERROR "Could not determine return value from signal handler.")
endif()
# ========== Define general UNIX-system ==========
if (UNIX)
set(CIRCLE_UNIX 1)
endif()
set(PROTO_FUNCTIONS
accept
bind
gettimeofday
atoi
atol
bzero
chdir
close
fclose
fcntl
fflush
fprintf
fputc
fread
fscanf
fseek
fwrite
getpeername
getpid
getrlimit
getsockname
htonl
htons
inet_addr
inet_aton
inet_ntoa
listen
ntohl
perror
printf
qsort
read
remove
rewind
select
setitimer
setrlimit
setsockopt
snprintf
sprintf
sscanf
strcasecmp
strdup
strerror
stricmp
strlcpy
strncasecmp
strnicmp
system
time
unlink
vsnprintf
write
socket
)
configure_file(
${CMAKE_SOURCE_DIR}/src/conf.h.cmake.in
${CMAKE_BINARY_DIR}/tmp_conf.h
)
macro(check_function_prototype FUNCTION)
set(_code "
#define NO_LIBRARY_PROTOTYPES
#define __COMM_C__
#define __ACT_OTHER_C__
#include \"${CMAKE_BINARY_DIR}/tmp_conf.h\"
#include \"${CMAKE_SOURCE_DIR}/src/sysdep.h\"
#ifdef ${FUNCTION}
error - already defined!
#endif
void ${FUNCTION}(int a, char b, int c, char d, int e, char f, int g, char h);
int main() {
; return 0; }
")
string(TOUPPER "${FUNCTION}" _upper_name)
check_c_source_compiles("${_code}" NEED_${_upper_name}_PROTO FAIL_REGEX ".*incompatible pointer type.*")
if (NEED_${_upper_name}_PROTO)
message(STATUS "${FUNCTION}() has no prototype, NEED_${_upper_name}_PROTO set!")
else()
message(STATUS "${FUNCTION}() has a prototype, not setting NEED_${_upper_name}_PROTO")
endif()
endmacro()
foreach (FUNC ${PROTO_FUNCTIONS})
check_function_prototype(${FUNC})
endforeach()
# ========== Generate conf.h ==========
configure_file(
${CMAKE_SOURCE_DIR}/src/conf.h.cmake.in
${CMAKE_BINARY_DIR}/conf.h
)
# ========== Source-filer ==========
file(GLOB SRC_FILES src/*.c)
# ========== Bygg kjørbar ==========
add_executable(circle ${SRC_FILES})
target_link_libraries(circle ${EXTRA_LIBS})
add_subdirectory(src/util)
if (MEMORY_DEBUG)
message(STATUS "MEMORY_DEBUG is activated, setting up zmalloc")
target_compile_definitions(circle PRIVATE MEMORY_DEBUG)
endif()

View file

@ -1 +0,0 @@
cmake -B . -S ..\src -G "Visual Studio 17 2022"

71
configure vendored
View file

@ -1227,18 +1227,28 @@ if eval "test \"`echo '$ac_cv_func_'crypt`\" = yes"; then
cat >> confdefs.h <<\EOF cat >> confdefs.h <<\EOF
#define CIRCLE_CRYPT 1 #define CIRCLE_CRYPT 1
EOF EOF
CRYPTLIB="-lcrypt"
echo "CRYPTLIB set to: $CRYPTLIB" 1>&6
else else
echo "$ac_t""no" 1>&6 echo "$ac_t""no" 1>&6
echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
echo "configure:1235: checking for crypt in -lcrypt" >&5 echo "configure:1235: checking for crypt in -lcrypt" >&5
ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then OS_NAME=$(uname)
echo $ac_n "(cached) $ac_c" 1>&6 if [ "$OS_NAME" = "Darwin" ]; then
else # macOS: No need for -lcrypt
ac_save_LIBS="$LIBS" CRYPTLIB=""
LIBS="-lcrypt $LIBS" echo "CRYPTLIB not needed on macOS" 1>&6
cat > conftest.$ac_ext <<EOF else
# Other systems (Linux): Use -lcrypt
ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
LIBS="-lcrypt $LIBS"
cat > conftest.$ac_ext <<EOF
#line 1243 "configure" #line 1243 "configure"
#include "confdefs.h" #include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */ /* Override any gcc2 internal prototype to avoid an error. */
@ -1250,30 +1260,29 @@ int main() {
crypt() crypt()
; return 0; } ; return 0; }
EOF EOF
if { (eval echo configure:1254: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then if { (eval echo configure:1254: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest* rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes" eval "ac_cv_lib_$ac_lib_var=yes"
else else
echo "configure: failed program was:" >&5 echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5 cat conftest.$ac_ext >&5
rm -rf conftest* rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=no" eval "ac_cv_lib_$ac_lib_var=no"
fi fi
rm -f conftest* rm -f conftest*
LIBS="$ac_save_LIBS" LIBS="$ac_save_LIBS"
fi
fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6
echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF
cat >> confdefs.h <<\EOF
#define CIRCLE_CRYPT 1 #define CIRCLE_CRYPT 1
EOF EOF
CRYPTLIB="-lcrypt" CRYPTLIB="-lcrypt"
else echo "CRYPTLIB set to: $CRYPTLIB on Linux" 1>&6
echo "$ac_t""no" 1>&6 else
fi echo "$ac_t""no" 1>&6
fi
fi
fi fi

View file

@ -1,7 +1,7 @@
Updated: Apr 2007 Updated: Apr 2007
tbaMUD README tbaMUD README
------------- -------------
All requests for help or bugs should be reported to: builderacademy.net 9091. All requests for help or bugs should be reported to: tbamud.com 9091.
Information about CircleMUD can be found at the CircleMUD Home Page and FTP: Information about CircleMUD can be found at the CircleMUD Home Page and FTP:
http://www.circlemud.org http://www.circlemud.org

93
doc/README.CMAKE.md Normal file
View file

@ -0,0 +1,93 @@
Updated 2025-04
## Building TbaMUD with the cmake tool
# Building with CMake
This document describes how to configure, build and install tbamud
from source code using the CMake build tool. To build with CMake, you of
course first have to install CMake. The minimum required version of CMake is
specified in the file `CMakeLists.txt` found in the top of the tbamud source
tree. Once the correct version of CMake is installed you can follow the
instructions below for the platform you are building on.
CMake builds can be configured either from the command line, or from one of
CMake's GUIs.
NOTE: The current CMakeLists.txt only supports linux.
# Configuring
A CMake configuration of tbamud is similar to the autotools build of curl.
It consists of the following steps after you have unpacked the source.
We recommend building with CMake on Windows.
## Using `cmake`
You can configure for in source tree builds or for a build tree
that is apart from the source tree.
- Build in a separate directory (parallel to the source tree in this
example). The build directory is created for you. This is recommended over
building in the source tree to separate source and build artifacts.
```shell
$ cmake -B build -S .
```
- Build in the source tree. Not recommended.
```shell
$ cmake -B .
```
The examples below will assume you have created a build folder.
The above commands will generate the build files. If you need to regenerate
the files, you can delete the cmake cache file, and rerun the above command:
```shell
$ rm build/CMakeCache.txt
```
Once the build files are generated, the build is run with cmake
```shell
$ cmake --build build
```
This will generate the object files in a subdirectory under the specified
build folder and link the executable. The resulting binaries will be in the
bin/ folder.
### Utilities
It is possible to build only single tools, none or all of them,
by specifying the target in the build command:
```shell
# only build the mud
$ cmake --build build --target circle
# only build tools
$ cmake --build build --target utils
# only build one tool
$ cmake --build build --target wld2html
```
### Debugging memory
In case you want to run the mud with memory debugging turned on, you
can set the MEMORY_DEBUG flag during configuration by specifying the
flag:
```shell
$ cmake -B build -S . -DMEMORY_DEBUG:int=1
$ cmake --build build
```
When the mud is shut down, the zmalloc code will identify any leaks in your code.
Note that memory debugging may consume quite a lot of memory and take some time
to be handled on shutdown.

View file

@ -1,15 +1,21 @@
### Overview Updated: Apr 2025
This guide describes how to build TbaMUD in the Visual Studio through the new experimental CMake environment. Compiling CircleMUD under Microsoft Windows XP
using Microsoft Visual C++ 2022 (8.0)
### Prerequisites
* [Visual Studio 2022+](https://visualstudio.microsoft.com/ru/vs/) ### Overview
* [CMake 3.27+](https://cmake.org/) This guide describes how to build TbaMUD in the Visual Studio through the new experimental CMake environment.
### Build Steps ### Prerequisites
1. Goto the folder `src` and copy `conf.h.win` to `conf.h`. * [Visual Studio 2022+](https://visualstudio.microsoft.com/ru/vs/)
* [CMake 3.27+](https://cmake.org/)
2. Goto the folder `build` and execute `create_solution.bat`.
### Build Steps
3. Open `build/circle.sln` in Visual Studio. 1. Goto the folder `src` and copy `conf.h.win` to `conf.h`.
2. Run this command in the root folder:
cmake -B build -S . -G "Visual Studio 17 2022"
3. Open `build/circle.sln` in Visual Studio.
4. Compile and run. 4. Compile and run.

View file

@ -24,7 +24,7 @@ Contents
1.1 Overview 1.1 Overview
The act() function is used to process and send strings of text to characters The 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 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 characters filling in certain segments designated by control characters
in different ways, dependant on what each character can see and who each 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 character is. Once the text string passed to the function has been parsed, it
is capitalized and a newline is added to its tail. is capitalized and a newline is added to its tail.
@ -38,17 +38,17 @@ struct obj_data *obj, const void *vict_obj, int type)
These pieces are used as follows: These pieces are used as follows:
str: This is the basic string, a null terminated character array, including str: This is the basic string, a null terminated character array, including
control characters (see section 1.4 on Control Characters), to be sent to control characters (see section 1.4 on Control Characters), to be sent to
characters designated by the targets. characters designated by the targets.
hide_invisible: A TRUE or FALSE value indicating whether or not to hide the hide_invisible: A TRUE or FALSE value indicating whether or not to hide the
entire output from any characters that cannot see the “performing character”. entire output from any characters that cannot see the “performing character”.
ch: The “performing character”. This is the character that the output string 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 is associated with. The character is used to determine the room for the output
of the action in question. of the action in question.
obj: An object (an actual item obj_data) used in the course of the action. obj: An object (an actual item obj_data) used in the course of the action.
vict_obj: This can be either a character involved in the action, another vict_obj: This can be either a character involved in the action, another
object, or even a predefined string of text. object, or even a predefined string of text.
@ -73,7 +73,7 @@ The next parameter vict_objcan be a number of things ranging from a game object
null terminated character array (char *). null terminated character array (char *).
Do note, however, that obj and vict_obj are both ignored if there is no control Do note, however, that obj and vict_obj are both ignored if there is no control
character reference (see section 1.4 Control Characters) to them and the type character reference (see section 1.4 Control Characters) to them and the type
is set to TO_ROOM or TO_CHAR. In these cases, NULL should be supplied as the is set to TO_ROOM or TO_CHAR. In these cases, NULL should be supplied as the
input to the function. input to the function.
@ -96,7 +96,7 @@ TO_CHAR: Finally, this option sends the output to the ch.
TO_SLEEP: This is a special option that must be combined with one of the above TO_SLEEP: This is a special option that must be combined with one of the above
options. It tells act() that the output is to be sent even to characters that options. It tells act() that the output is to be sent even to characters that
are sleeping. It is combined with a bitwise or. i.e. TO_VICT | TO_SLEEP. are sleeping. It is combined with a bitwise or. i.e. TO_VICT | TO_SLEEP.
When the string has been parsed, it is capitalized and a newline is added. When the string has been parsed, it is capitalized and a newline is added.
@ -105,20 +105,20 @@ In a manner similar to the printf() family of functions, act() uses control
characters. However, instead of using the % symbol, act() uses the $ character characters. However, instead of using the % symbol, act() uses the $ character
to indicate control characters. to indicate control characters.
$n Write name, short description, or “someone”, for ch, depending on whether $n Write name, short description, or “someone”, for ch, depending on whether
ch is a PC, a NPC, or an invisible PC/NPC. ch is a PC, a NPC, or an invisible PC/NPC.
$N Like $n, except insert the text for vict_obj.* $N Like $n, except insert the text for vict_obj.*
$m “him,” “her,” or “it,” depending on the gender of ch. $m “him,” “her,” or “it,” depending on the gender of ch.
$M Like $m, for vict_obj.* $M Like $m, for vict_obj.*
$s “his,” “her,”or “it,” depending on the gender of ch. $s “his,” “her,”or “it,” depending on the gender of ch.
$S Like $s, for vict_obj.* $S Like $s, for vict_obj.*
$e “he,” “she,” “it,” depending on the gender of ch. $e “he,” “she,” “it,” depending on the gender of ch.
$E Like $e, for vict_obj.* $E Like $e, for vict_obj.*
$o Name or “something” for obj, depending on visibility. $o Name or “something” for obj, depending on visibility.
$O Like $o, for vict_obj.* $O Like $o, for vict_obj.*
$p Short description or “something” for obj. $p Short description or “something” for obj.
$P Like $p for vict_obj.* $P Like $p for vict_obj.*
$a “an” or“a”, depending on the first character of objs name. $a “an” or“a”, depending on the first character of objs name.
$A Like $a, for vict_obj.* $A Like $a, for vict_obj.*
$T Prints the string pointed to by vict_obj.* $T Prints the string pointed to by vict_obj.*
$F Processes the string pointed to by vict_obj with the fname() function prior $F Processes the string pointed to by vict_obj with the fname() function prior
@ -129,7 +129,7 @@ no action is taken.
$U Processes the buffer and uppercases the first letter of the following word $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 (the word immediately after to the control code). If there is no following
word, no action is taken. word, no action is taken.
$$ Print the character $. $$ Print the character $.
NOTE*: vict_obj must be a pointer of type struct char_data *. NOTE*: vict_obj must be a pointer of type struct char_data *.

View file

@ -9,8 +9,8 @@ to players in color in the tbaMUD game engine. Its intended audience is for
Coders of tbaMUD. Coders of tbaMUD.
tbaMUD allows you to create colorful messages by using ANSI control sequences. tbaMUD 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 Each player may select what “level” of color he/she desires from the four
levels “off,” “brief,” “normal,” and “complete.” Each player can select his/her levels “off,” “brief,” “normal,” and “complete.” Each player can select his/her
color level by using the TOGGLE COLOR command from within the MUD; you as the color level by using the TOGGLE COLOR command from within the MUD; you as the
programmer must decide which messages will be colored for each of the color programmer must decide which messages will be colored for each of the color
levels. levels.
@ -21,17 +21,17 @@ All files in which you wish to use color must have the line:
This should be put in after all other includes in the beginning of the file. This should be put in after all other includes in the beginning of the file.
There are 8 colors available “normal,” red, green, yellow, blue, magenta, There are 8 colors available “normal,” red, green, yellow, blue, magenta,
cyan and white. They are accessible by sending control sequences as part of cyan and white. They are accessible by sending control sequences as part of
another string, for example: another string, for example:
sprintf(buf, "If youre %shappy%s and you know it clap " sprintf(buf, "If youre %shappy%s and you know it clap "
"%d of your hands.\n\r", x, y, num_of_hands); "%d of your hands.\n\r", x, y, num_of_hands);
send_to_char(ch, buf); send_to_char(ch, buf);
In this example, x and y are the “on” and “off” sequences for the color you 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 (dont want. There are 2 main series of color macros available for you to use (dont
actually use “x” and “y,” of course!): the K series and the CC series. The CC 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. (Conditional Color) series is recommended for most general use.
The name of the actual sequence starts with the name of its series, plus a The name of the actual sequence starts with the name of its series, plus a
@ -51,21 +51,21 @@ CCBLU() (arguments defined below).
The K series requires no arguments, and is simply a macro to the ANSI color 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 code. Therefore, if you use a K-series color code, the color will ALWAYS be
sent, even if the person youre sending it to has color off. This can very bad. sent, even if the person youre sending it to has color off. This can very bad.
Some people who do not have ANSI-compatible terminals will see garbage Some people who do not have ANSI-compatible terminals will see garbage
characters instead of colors. If the terminal correctly ignores ANSI color 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 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 players color level will later be used to print colors to a string if the players color level will later be
tested manually (for an example, see do_gen_com in act.comm.c). 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 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 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 string is being sent, and the minimum color level the player must be set to in
order to see the color. Color sent as 'brief' (formerly known as sparse it was order to see the color. Color sent as 'brief' (formerly known as sparse it was
changed for consistency with the syslog command) (C_SPR) will be seen by people changed for consistency with the syslog command) (C_SPR) will be seen by people
with color set to sparse, normal, or complete; color sent as normal (C_NRM) 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 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. complete (C_CMP) will be seen only by people with color set to complete.
To illustrate the above, an example is in order: To illustrate the above, an example is in order:
@ -76,29 +76,29 @@ ACMD(do_showcolor)
{ {
char buf[300]; char buf[300];
sprintf(buf, "Dont you just love %scolor%s, %scolor%s, " "%sCOLOR%s!\n\r", sprintf(buf, "Dont 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), CCBLU(ch, C_CMP), CCNRM(ch, C_CMP), CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
CCRED(ch, C_SPR), CCNRM(ch, C_SPR)); CCRED(ch, C_SPR), CCNRM(ch, C_SPR));
send_to_char(ch, buf); send_to_char(ch, buf);
} }
What does this do? For people with color set to Complete, it prints: What does this do? For people with color set to Complete, it prints:
Dont you just love color, color, COLOR! (blue) (yellow) (red) Dont you just love color, color, COLOR! (blue) (yellow) (red)
People who have color set to Normal will see: People who have color set to Normal will see:
Dont you just love color, color, COLOR! (yellow) (red) Dont you just love color, color, COLOR! (yellow) (red)
People who have color set to Sparse will see: People who have color set to Sparse will see:
Dont you just love color, color, COLOR! (red) Dont you just love color, color, COLOR! (red)
People who have color set to Off will see: People who have color set to Off will see:
Dont you just love color, color, COLOR! (no color, as youd expect) Dont you just love color, color, COLOR! (no color, as youd expect)
There are several common pitfalls with using the CC series of color macros: 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 Do not confuse CCNRM with C_NRM. CCNRM() is a macro to turn the color back to
normal; C_NRMis a color level of “normal.” Always make sure that every pair of normal; C_NRMis a color level of “normal.” Always make sure that every pair of
“on” and “off” codes are at the same color level. For example: “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)); WRONG: sprintf(buf, "%sCOLOR%s\n\r", CCBLU(ch, C_NRM), CCNRM(ch, C_CMP));
@ -110,14 +110,14 @@ 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 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 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 dont have to. unnecessarily get the CCNRM code. Never send a color code if you dont have to.
The codes are several bytes long, and cause a noticeable pause at 2400 baud. The codes are several bytes long, and cause a noticeable pause at 2400 baud.
This should go without saying, but dont ever send color at the C_OFF level. This should go without saying, but dont ever send color at the C_OFF level.
Special precautions must be taken when sending a colored string to a large Special precautions must be taken when sending a colored string to a large
group of people. You cant use the color level of “ch” (the person sending the group of people. You cant use the color level of “ch” (the person sending the
string) each person receiving the string must get a string appropriately 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 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 players color level strings (one colored and one not), and test each players color level
individually (see do_gen_comin act.comm.c for an example). individually (see do_gen_comin act.comm.c for an example).

View file

@ -4,14 +4,14 @@ Builder Academy at telnet://tbamud.com:9091 or email rumble@tbamud.com -- Rumble
The Art of Debugging The Art of Debugging
Originally by Michael Chastain and Sammy Originally by Michael Chastain and Sammy
The following documentation is excerpted from Merc 2.0s hacker.txt file. It The following documentation is excerpted from Merc 2.0s hacker.txt file. It
was written by Furey of MERC Industries and is included here with his was written by Furey of MERC Industries and is included here with his
permission. We have packaged it with tbaMUD (changed in a couple of places, permission. We have packaged it with tbaMUD (changed in a couple of places,
such as specific filenames) because it offers good advice and insight into the such as specific filenames) because it offers good advice and insight into the
art and science of software engineering. More information about tbaMUD, art and science of software engineering. More information about tbaMUD,
can be found at the tbaMUD home page http://tbamud.com. can be found at the tbaMUD home page http://tbamud.com.
1 “Im running a Mud so I can learn C programming!” 1 “Im running a Mud so I can learn C programming!”
Yeah, right. The purpose of this document is to record some of our knowledge, 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 experience and philosophy. No matter what your level, we hope that this
@ -31,11 +31,11 @@ Play with it some more.
Read documentation again. Read documentation again.
Get the idea? Get the idea?
The idea is that your mind can accept only so much “new data” in a single The idea is that your mind can accept only so much “new data” in a single
session. Playing with something doesnt introduce very much new data, but it session. Playing with something doesnt introduce very much new data, but it
does transform data in your head from the “new” category to the “familiar” does transform data in your head from the “new” category to the “familiar”
category. Reading documentation doesnt make anything “familiar,” but it category. Reading documentation doesnt make anything “familiar,” but it
refills your “new” hopper. refills your “new” hopper.
Most people, if they even read documentation in the first place, never return 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 to it. They come to a certain minimum level of proficiency and then never
@ -47,17 +47,17 @@ through the two-step learning cycle many times to master it.
man gives you online manual pages. man gives you online manual pages.
grep stands for “global regular expression print;” searches for strings in text grep stands for “global regular expression print;” searches for strings in text
files. files.
vi, emacs, jove use whatever editor floats your boat, but learn the hell out vi, emacs, jove use whatever editor floats your boat, but learn the hell out
of it; you should know every command in your editor. of it; you should know every command in your editor.
ctags mags “tags” for your editor which allows you to go to functions by name ctags mags “tags” for your editor which allows you to go to functions by name
in any source file. in any source file.
>, >>, <, | input and output redirection at the command line; get someone to >, >>, <, | input and output redirection at the command line; get someone to
show you, or dig it out of “man csh” show you, or dig it out of “man csh”
These are the basic day-in day-out development tools. Developing without 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 knowing how to use all of these well is like driving a car without knowing
@ -70,21 +70,21 @@ the hypothesis, run the program and provide it experimental input, observe its
behavior, and confirm or refute the hypothesis. behavior, and confirm or refute the hypothesis.
A good hypothesis is one which makes surprising predictions which then come A good hypothesis is one which makes surprising predictions which then come
true; predictions that other hypotheses dont make. true; predictions that other hypotheses dont make.
The first step in debugging is not to write bugs in the first place. This The first step in debugging is not to write bugs in the first place. This
sounds obvious, but sadly, is all too often ignored. 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 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 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” 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 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. to fix the code that generates them, but it takes hours to find bugs otherwise.
“Desk checking” (proof reading) is almost a lost art these days. Too bad. You “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 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 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 peoples code, that in your group whose only job it is to desk-check other peoples code, that
person will find and fix more bugs than everyone else combined. 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 One can desk-check several hundred lines of code per hour. A top-flight
@ -95,20 +95,20 @@ fixing technique. Compare that to all the hours you spend screwing around with
broken programs trying to find one bug at a time. broken programs trying to find one bug at a time.
The next technique beyond desk-checking is the time-honored technique of The next technique beyond desk-checking is the time-honored technique of
inserting “print” statements into the code, and then watching the logged inserting “print” statements into the code, and then watching the logged
values. Within tbaMUD code, you can call printf(), fprintf(), or log()to dump values. Within tbaMUD code, you can call printf(), fprintf(), or log()to dump
interesting values at interesting times. Where and when to dump these values interesting values at interesting times. Where and when to dump these values
is an art, which you will learn only with practice. is an art, which you will learn only with practice.
If you dont already know how to redirect output in your operating system, now If you dont 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 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 about the “>” operator. You should also learn the difference between “standard
output” (for example, output from “printf”) and “standard error” (for example, output” (for example, output from “printf”) and “standard error” (for example,
output from “fprintf(stderr, ...)”). output from “fprintf(stderr, ...)”).
Ultimately, you cannot fix a program unless you understand how it is operating 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 in the first place. Powerful debugging tools will help you collect data, but
they cant interpret it, and they cant fix the underlying problems. Only you they cant interpret it, and they cant fix the underlying problems. Only you
can do that. can do that.
When you find a bug... your first impulse will be to change the code, kill the When you find a bug... your first impulse will be to change the code, kill the
@ -117,9 +117,9 @@ 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 bug, all the way down. You should grok the bug and cherish it in fullness
before causing its discorporation. before causing its discorporation.
Also, when finding a bug, ask yourself two questions: “What design and 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: 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?” “What habits would systematically prevent the introduction of bugs like this?”
5 Debugging: Tools 5 Debugging: Tools
@ -127,20 +127,20 @@ When a Unix process accesses an invalid memory location, or (more rarely)
executes an illegal instruction, or (even more rarely) something else goes executes an illegal instruction, or (even more rarely) something else goes
wrong, the Unix operating system takes control. The process is incapable of wrong, the Unix operating system takes control. The process is incapable of
further execution and must be killed. Before killing the process, however, the 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 operating system does something for you: it opens a file named “core” and
writes the entire data space of the process into it. 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. Thus, “dumping core” is not a cause of problems, or even an effect of problems.
Its something the operating system does to help you find fatal problems which Its something the operating system does to help you find fatal problems which
have rendered your process unable to continue. have rendered your process unable to continue.
One reads a “core” file with a debugger. The two most popular debuggers on Unix 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 are adb and gdb, although occasionally one finds dbx. Typically one starts a
debugger like this: “gdb bin/circle” or “gdb bin/circle lib/core”. debugger like this: “gdb bin/circle” or “gdb bin/circle lib/core”.
The first thing, and often the only thing, you need to do inside the debugger 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 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 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 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. were calling it. The debugger will also list the arguments to these functions.
Interpreting these arguments, and using more advanced debugger features, Interpreting these arguments, and using more advanced debugger features,
@ -343,12 +343,12 @@ new tools.
7 Profiling 7 Profiling
Another useful technique is “profiling,” to find out where your program is 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. spending most of its time. This can help you to make a program more efficient.
Here is how to profile a program: Here is how to profile a program:
1. Remove all the .o files and the “circle” executable: 1. Remove all the .o files and the “circle” executable:
make clean make clean
2. Edit your Makefile, and change the PROFILE=line: 2. Edit your Makefile, and change the PROFILE=line:
@ -359,25 +359,25 @@ make
4. Run circle as usual. Shutdown the game with the shutdown command when you 4. Run circle as usual. Shutdown the game with the shutdown command when you
have run long enough to get a good profiling base under normal usage 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 wont conditions. If you crash the game, or kill the process externally, you wont
get profiling information. get profiling information.
5. Run the profcommand: 5. Run the profcommand:
prof bin/circle > prof.out prof bin/circle > prof.out
6. Read prof.out. Run “man prof” to understand the format of the output. For 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” 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 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 exactly how many times any function calls any other function. This information
is valuable for debugging as well as performance analysis. is valuable for debugging as well as performance analysis.
Availability of “prof” and “gprof” varies from system to system. Almost every Availability of “prof” and “gprof” varies from system to system. Almost every
Unix system has “prof”. Only some systems have “gprof”. Unix system has “prof”. Only some systems have “gprof”.
7 Books for Serious Programmers 7 Books for Serious Programmers
Out of all the thousands of books out there, three stand out: Out of all the thousands of books out there, three stand out:
Kernighan and Plaugher, “The Elements of Programming Style” Kernighan and Plaugher, “The Elements of Programming Style”
Kernighan and Ritchie, “The C Programming Language” Kernighan and Ritchie, “The C Programming Language”
Brooks, “The Mythical Man Month” Brooks, “The Mythical Man Month”

View file

@ -3,7 +3,7 @@ Builder Academy at telnet://tbamud.com:9091 or email rumble@tbamud.com -- Rumble
tbaMUD File Manifest tbaMUD File Manifest
The main tbaMUD/ directory has the following subdirectories and files: The main tbaMUD/ directory has the following subdirectories and files:
autorun - Shell script to run the MUD (./autorun &). autorun - Shell script to run the MUD (./autorun &).
FAQ - Frequently Aske Questions with answers. FAQ - Frequently Aske Questions with answers.
@ -16,7 +16,7 @@ lib/ - MUD data.
log/ - System logs. log/ - System logs.
src/ - Source code. src/ - Source code.
The bin/directory contains only binaries: circle (the main MUD) and its The bin/directory contains only binaries: circle (the main MUD) and its
utilities, which are described in utils.txt. utilities, which are described in utils.txt.
The doc/ directory has its own README file, describing the contents of each The doc/ directory has its own README file, describing the contents of each
@ -51,12 +51,12 @@ time - Where the MUD time is saved.
The lib/misc/ directory contains the following files: The lib/misc/ directory contains the following files:
bugs - Bugs reported by players with the bug command. bugs - Bugs reported by players with the bug command.
ideas - Ideas from players from idea command. ideas - Ideas from players from idea command.
messages - Spell and skill damage messages. messages - Spell and skill damage messages.
socials - Text file with text of the socials. socials - Text file with text of the socials.
socials.new - New format of socials you can edit via AEDIT. socials.new - New format of socials you can edit via AEDIT.
typos - Typos reported by players with the typo command. typos - Typos reported by players with the typo command.
xnames - Text file of invalid names. xnames - Text file of invalid names.
The lib/plrobjs/ contains the following files and directories: The lib/plrobjs/ contains the following files and directories:
@ -80,18 +80,18 @@ zzz/
The lib/text/ directory contains the following files: The lib/text/ directory contains the following files:
background - Background story (for option 3 from main menu). background - Background story (for option 3 from main menu).
credits - Text for credits command. credits - Text for credits command.
greetings - Greeting message. greetings - Greeting message.
handbook - Text for Immortal Handbook (handbook command). handbook - Text for Immortal Handbook (handbook command).
immlist - Text for immlist command. immlist - Text for immlist command.
imotd - Immortal MOTD --seen by immortals on login. imotd - Immortal MOTD --seen by immortals on login.
info - Text for info command. info - Text for info command.
motd - MOTD --seen by mortals on login. motd - MOTD --seen by mortals on login.
news - Text for news command. news - Text for news command.
policies - Text for policy command. policies - Text for policy command.
wizlist - Text for wizlist command. wizlist - Text for wizlist command.
/help/screen - Text for help command as a mortal with no arguments. /help/screen - Text for help command as a mortal with no arguments.
/help/iscreen - Text for help command an an immortal with no arguments. /help/iscreen - Text for help command an an immortal with no arguments.
The lib/world/directory contains the following subdirectories: The lib/world/directory contains the following subdirectories:
@ -103,8 +103,8 @@ wld - Contains *.wld files (world files)
zon - Contains *.zon files (zone files) zon - Contains *.zon files (zone files)
Each of the 6 subdirectories in the lib/world/ directory also contains two Each of the 6 subdirectories in the lib/world/ directory also contains two
additional files one called index, which specifies which files in that additional files one called index, which specifies which files in that
directory should be loaded when the MUD boots, and index.mini, which 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 specifies which files should be loaded if the MUD is booted with the -m
(mini-mud) option. (mini-mud) option.
@ -128,6 +128,6 @@ trigger - Trigedit log messages.
usage - Mud system usage (player load & memory usage info). usage - Mud system usage (player load & memory usage info).
The src/ directory contains all of the C and header files for the MUD, along 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 tbaMUDs utility with a Makefile. The src/util/ directory contains source for tbaMUDs utility
programs. See admin.txt for more information on how to compile the MUD. See programs. See admin.txt for more information on how to compile the MUD. See
utils.txt for more information on how to use tbaMUDs utilities. utils.txt for more information on how to use tbaMUDs utilities.

View file

@ -9,16 +9,16 @@ every platform that exists. This document is for experienced programmers
trying to make tbaMUD work on their platform. trying to make tbaMUD work on their platform.
tbaMUD should work on most UNIX platforms without any modifications; simply run tbaMUD should work on most UNIX platforms without any modifications; simply run
the “configure” script and it should automatically detect what type of system the “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 you have and anything that may be strange about it. These findings are all
stored in a header file called conf.h which is created in the src directory stored in a header file called conf.h which is created in the src directory
from a template called conf.h.in. A Makefile is also created from the template from a template called conf.h.in. A Makefile is also created from the template
Makefile.in. Makefile.in.
Non-UNIX platforms are a problem. Some cant run tbaMUD at all. However, any Non-UNIX platforms are a problem. Some cant run tbaMUD at all. However, any
multitasking OS that has an ANSI C compiler, and supports non-blocking I/O and 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 tbaMUD; for socket-based TCP/IP networking, should theoretically be able to run tbaMUD; for
example, OS/2, AmigaOS, Mac OS (Classic versions; Mac OS X supports tbaMUDs example, OS/2, AmigaOS, Mac OS (Classic versions; Mac OS X supports tbaMUDs
configure script from the command line), and all versions of Windows. configure script from the command line), and all versions of Windows.
The port can be very easy or very difficult, depending mainly on whether or nor The port can be very easy or very difficult, depending mainly on whether or nor
@ -26,7 +26,7 @@ your OS supports the Berkeley socket API.
The general steps for porting tbaMUD to a non-UNIX platform are listed below. A The general steps for porting tbaMUD to a non-UNIX platform are listed below. A
number of tips for porting can be found after the porting steps. Note that we number of tips for porting can be found after the porting steps. Note that we
have already ported tba to Windows, so if youre confused as to how to perform have already ported tba to Windows, so if youre confused as to how to perform
some of these steps, you can look at what we have done as an example (see the some of these steps, you can look at what we have done as an example (see the
files README.CYGWIN). files README.CYGWIN).
@ -36,11 +36,11 @@ trying to port the code.
Porting the Code Porting the Code
Step 1. Create a “conf.h” file for your system. Copy the template “conf.h.in” Step 1. Create a “conf.h” file for your system. Copy the template “conf.h.in”
to “conf.h”, and then define or undefine each item as directed by the comments to “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 conf.h file, and based on the characteristics of your system. To write the conf.h file,
youll need to know which header files are included with your system, the youll need to know which header files are included with your system, the
return type of signals, whether or not your compiler supports the const return type of signals, whether or not your compiler supports the const
keyword, and whether or not you have various functions such as crypt()and keyword, and whether or not you have various functions such as crypt()and
random(). Also, you can ignore the HAVE_LIBxxx and HAVE_xxx_PROTO constants at random(). Also, you can ignore the HAVE_LIBxxx and HAVE_xxx_PROTO constants at
the end of conf.h.in; they are not used in the code (they are part of UNIX the end of conf.h.in; they are not used in the code (they are part of UNIX
@ -58,12 +58,12 @@ be in the source file comm.c.
Step 4. Test your changes! Make sure that multiple people can log in 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 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. 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 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 make sure that your changes are stable. Make sure that automatic events such as
zone resets, point regeneration, and corpse decomposition are being timed zone resets, point regeneration, and corpse decomposition are being timed
correctly (a tick should be about 75 seconds). Try resetting all the zones correctly (a tick should be about 75 seconds). Try resetting all the zones
repeatedly by typing “zr *” many times. Play the MUD and make sure that the repeatedly by typing “zr *” many times. Play the MUD and make sure that the
basic commands (killing mobs as a mortal, casting spells, etc.) work correctly. basic commands (killing mobs as a mortal, casting spells, etc.) work correctly.
Step 5. If you are satisfied that your changes work correctly, you are Step 5. If you are satisfied that your changes work correctly, you are
@ -71,20 +71,20 @@ encouraged to submit them to be included as part of the tbaMUD distribution so
that future releases of tbaMUD will support your platform. This prevents you that future releases of tbaMUD will support your platform. This prevents you
from re-porting the code every time a new version is released and allows other from re-porting the code every time a new version is released and allows other
people who use your platform to enjoy tbaMUD as well. To submit your changes people who use your platform to enjoy tbaMUD as well. To submit your changes
you must make a patch file using the GNU diff program. diff will create a you must make a patch file using the GNU diff program. diff will create a
patch file which can be later used with the patch utility to incorporate patch file which can be later used with the patch utility to incorporate
your changes into the stock tbaMUD distribution. For example, if you have a your changes into the stock tbaMUD distribution. For example, if you have a
copy of tbaMUD in the “stock-tba” directory, and your changes are in “my-tba”, copy of tbaMUD in the “stock-tba” directory, and your changes are in “my-tba”,
you can create a patch file like this: you can create a patch file like this:
diff -u --new-file --recursive stock-tba/src my-tba/src > patch diff -u --new-file --recursive stock-tba/src my-tba/src > patch
This will create a file called patch with your patches. You should then try This will create a file called patch with your patches. You should then try
to use the patch program (the inverse of diff) on a copy of tbaMUD to make to use the patch program (the inverse of diff) on a copy of tbaMUD to make
sure that tbaMUD is correctly changed to incorporate your patches. This step is sure that tbaMUD is correctly changed to incorporate your patches. This step is
very important: if you dont create these patches correctly, your work will be very important: if you dont create these patches correctly, your work will be
useless because no one will be able to figure out what you did! Make sure to useless because no one will be able to figure out what you did! Make sure to
read the documentation to diff and patch if you dont understand how to use read the documentation to diff and patch if you dont understand how to use
them. If your patches work, CELEBRATE!! them. If your patches work, CELEBRATE!!
Step 6. Write a README file for your operating system that describes everything Step 6. Write a README file for your operating system that describes everything
@ -107,7 +107,7 @@ Each system to which tba is already ported has a CIRCLE_xx constant associated
with it: CIRCLE_UNIX for plain vanilla UNIX tbaMUD, CIRCLE_WINDOWS for MS with it: CIRCLE_UNIX for plain vanilla UNIX tbaMUD, CIRCLE_WINDOWS for MS
Windows, CIRCLE_OS2 for IBM OS/2, and CIRCLE_AMIGA for the Amiga. You must use Windows, CIRCLE_OS2 for IBM OS/2, and CIRCLE_AMIGA for the Amiga. You must use
a similar constant for your system. At the top of your conf.h, make sure to a similar constant for your system. At the top of your conf.h, make sure to
comment out “#define CIRCLE_UNIX” and add “#define CIRCLE_YOUR_SYSTEM”. comment out “#define CIRCLE_UNIX” and add “#define CIRCLE_YOUR_SYSTEM”.
3.2 ANSI C and GCC 3.2 ANSI C and GCC
As long as your system has an ANSI C compiler, all of the code (except for As long as your system has an ANSI C compiler, all of the code (except for
@ -122,22 +122,22 @@ you use gcc.
Make absolutely sure to use non-blocking I/O; i.e. make sure to enable the Make absolutely sure to use non-blocking I/O; i.e. make sure to enable the
option so that the read() system call will immediately return with an error if option so that the read() system call will immediately return with an error if
there is no data available. If you do not use non-blocking I/O, read() will there is no data available. If you do not use non-blocking I/O, read() will
“block,” meaning it will wait infinitely for one particular player to type “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 something even if other players are trying to enter commands. If your system
does not implement non-blocking I/O correctly, try using the does not implement non-blocking I/O correctly, try using the
POSIX_NONBLOCK_BROKEN constant in sysdep.h. POSIX_NONBLOCK_BROKEN constant in sysdep.h.
3.4 Timing 3.4 Timing
tbaMUD needs a fairly precise (on the order of 5 or 10 ms) timer in order to tbaMUD 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”), correctly schedule events such as zone resets, point regeneration (“ticks”),
corpse decomposition, and other automatic tasks. If your system supports the corpse decomposition, and other automatic tasks. If your system supports the
select() system call with sufficient precision, the default timing code should select() system call with sufficient precision, the default timing code should
work correctly. If not, youll have to find out which system calls your system work correctly. If not, youll have to find out which system calls your system
supports for determining how much time has passed and replace the select() supports for determining how much time has passed and replace the select()
timing method. timing method.
3.5 Signals and Signal Handlers 3.5 Signals and Signal Handlers
A note about signals: Most systems dont support the concept of signals in the A note about signals: Most systems dont support the concept of signals in the
same way that UNIX does. Since signals are not a critical part of how tbaMUD same way that UNIX does. Since signals are not a critical part of how tbaMUD
works anyway (they are only used for updating the wizlist and some other 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 trivial things), all signal handling is turned off by default when compiling
@ -147,7 +147,7 @@ conf.h file and all signal code will be ignored automatically.
4 Final Note 4 Final Note
IMPORTANT: Remember to keep any changes you make surrounded by #ifdef IMPORTANT: Remember to keep any changes you make surrounded by #ifdef
statements (i.e. “#ifdef CIRCLE_WINDOWS ... #endif”). If you make absolutely statements (i.e. “#ifdef CIRCLE_WINDOWS ... #endif”). If you make absolutely
sure to mark all of your changes with #ifdef statements, then your patches sure to mark all of your changes with #ifdef statements, then your patches
(once you get them to work) will be suitable for incorporation into the (once you get them to work) will be suitable for incorporation into the
tbaMUD distribution, meaning that tbaMUD will officially support your platform. tbaMUD distribution, meaning that tbaMUD will officially support your platform.

View file

@ -10,6 +10,7 @@ to rec.games.mud.diku which originally announced CircleMUD as a publicly
available MUD source code. available MUD source code.
tbaMUD Release history: tbaMUD Release history:
Version 2025 release: January, 2025
Version 2023 release: January, 2023 Version 2023 release: January, 2023
Version 2021 release: March, 2021 Version 2021 release: March, 2021
Version 2020 release: January, 2020 Version 2020 release: January, 2020
@ -142,7 +143,7 @@ communication channels
totally ignores all commands from that player until they are thawed. totally ignores all commands from that player until they are thawed.
--Even handier DELETE flag allows you to delete players on the fly. --Even handier DELETE flag allows you to delete players on the fly.
--"set" command (mentioned above) allows you to freeze/unfreeze/ --"set" command (mentioned above) allows you to freeze/unfreeze/
delete/siteok/un-siteok players --even if they arent logged in! delete/siteok/un-siteok players --even if they arent logged in!
--Bad password attempts are written to the system log and saved; --Bad password attempts are written to the system log and saved;
if someone tries to hack your account, you see "4 LOGIN FAILURES if someone tries to hack your account, you see "4 LOGIN FAILURES
SINCE LAST SUCCESSFUL LOGIN" next time you log on. SINCE LAST SUCCESSFUL LOGIN" next time you log on.

View file

@ -110,12 +110,12 @@ is being specified. The command sort name is the shortest part of the command a
player must type for it to match. The hide-flag can be either 0 or 1; if 1, the player must type for it to match. 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 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 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 characters name character performing the social, although in such cases the characters name
will, of course, be replaced with “someone”. The min positions should be set to will, of course, be replaced with “someone”. The min positions should be set to
dictate the minimum position a player must be in to target the victim and dictate the minimum position a player must be in to target the victim and
perform the social. Min level allows you to further customize who can use what perform the social. Min level allows you to further customize who can use what
socials.Where it makes sense to do so, text fields may be left empty. If socials.Where it makes sense to do so, text fields may be left empty. If
editing manually you should by put a # in the first column on the line. Aedit editing manually you should by put a # in the first column on the line. Aedit
does this automatically. does this automatically.
Examples: Examples:

View file

@ -34,7 +34,7 @@ older CircleMUD data files to the versions used in CircleMUD v3, while others
are used to convert currently existing files into different formats. are used to convert currently existing files into different formats.
Overall, these utilities have been created in an attempt to make the tbaMUD Overall, these utilities have been created in an attempt to make the tbaMUD
administrators life a bit easier, and to give the administrator some ideas of administrators life a bit easier, and to give the administrator some ideas of
further and more grandiose utilities to create. Some are no longer applicable further and more grandiose utilities to create. Some are no longer applicable
but are retained as examples. but are retained as examples.
@ -61,7 +61,7 @@ the second, and so forth.
The split utility is designed to split large world files into smaller, zone 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 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 from the standard input and writes the output to files with names specified
within the larger world file. This is done by inserting =filename into the within the larger world file. This is done by inserting =filename into the
world file at the appropriate points, where filename is the name of the file world file at the appropriate points, where filename is the name of the file
for the following section. for the following section.
@ -141,8 +141,8 @@ The command line syntax for autowiz is as follows:
autowiz <wizlev> <wizlistfile> <immlev> <immlistfile> [pid to signal] autowiz <wizlev> <wizlistfile> <immlev> <immlistfile> [pid to signal]
where <wizlev> is equal to whatever LVL_GOD is set to in your tbaMUD server, where <wizlev> is equal to whatever LVL_GOD is set to in your tbaMUD server,
<wizlistfile> is the filename for the file containing the games Wizlist. <wizlistfile> is the filename for the file containing the games Wizlist.
<immlev> should be set to your games LVL_IMMORT, while <immlistfile> <immlev> should be set to your games LVL_IMMORT, while <immlistfile>
is the name of the Immlist file. is the name of the Immlist file.
This utility must be recompiled if you make any changes to the player file structure. This utility must be recompiled if you make any changes to the player file structure.

View file

@ -1,5 +1,5 @@
T B A M U D T B A M U D
2 0 2 3 2 0 2 5
Based on CircleMUD by Jeremy Elson and DikuMUD by Hans-Henrik Staerfeldt, Based on CircleMUD by Jeremy Elson and DikuMUD by Hans-Henrik Staerfeldt,
Katja Nyboe, Tom Madsen, Michael Seifert, and Sebastian Hammer Katja Nyboe, Tom Madsen, Michael Seifert, and Sebastian Hammer

View file

@ -865,7 +865,7 @@ AUTOQUESTS QUESTS QUESTMASTERS QUEST-MOBS QUESTMOBS
An autoquest is a quest that can be automatically started and completed An autoquest is a quest that can be automatically started and completed
without the intervention of an immortal. Simply visit a questmaster and join without the intervention of an immortal. Simply visit a questmaster and join
an available quest, and get rewarded on its completion. Keep an eye out for an available quest, and get rewarded on it's completion. Keep an eye out for
autoquests scattered throughout the World. autoquests scattered throughout the World.
See Also: QUEST-FLAG, QUESTPOINTS See Also: QUEST-FLAG, QUESTPOINTS
@ -1584,7 +1584,6 @@ qedit (quest editor)
questpoints questpoints
buildwalk buildwalk
dig dig
tell m-w (an in game dictionary lookup)
gemote gemote
history history
file file
@ -2444,25 +2443,6 @@ Example:
> diagnose doctor > diagnose doctor
See also: CONSIDER, HIT, KILL See also: CONSIDER, HIT, KILL
#0
DICTIONARY DICTIONARIES THESAURUS M-W.COM DEFINITION MERRIAM-WEBSTER M-W-DEFINITION WEBSTER MW TELL-M-W BREATHER SPELLING WORDS
Usage: tell m-w <word>
We have a direct link to Merriam Webster. To use the dictionary just
tell m-w <word>
>tell m-w breather
You get this feedback from Merriam-Webster:
That means:
1 : one that breathes
2 : a break in activity for rest or relief
3 : a small vent in an otherwise airtight enclosure
A few obscure definitions are not available through m-w since they are in the
unabridged version that requires membership. They also offer a thesaurus at:
@Chttp://m-w.com/@n
#31 #31
DIG UNDIG RDIG RELINK RLINKS DIG UNDIG RDIG RELINK RLINKS
@ -3173,7 +3153,7 @@ game.
Invest in a thesaurus. Makes a world of difference, and if that doesn't Invest in a thesaurus. Makes a world of difference, and if that doesn't
help, just make up your own words for things you create (just be sure to help, just make up your own words for things you create (just be sure to
describe them very well. Use @Chttp://m-w.com/@n for an online thesaurus describe them very well. Use @Chttp://m-w.com/@n for an online thesaurus
and dictionary. You can @Rtell m-w <word>@n to lookup a definition. and dictionary.
4. Where can I learn Trigedit? 4. Where can I learn Trigedit?
Here! Welcor is now the developer of trigedit. We have extensive help files, Here! Welcor is now the developer of trigedit. We have extensive help files,
@ -3564,8 +3544,8 @@ GRAMMAR GRAMMER TIPS
words can be particularly tricky and elude electronic spell checkers. A good words can be particularly tricky and elude electronic spell checkers. A good
dictionary, however, will help you spell archaic words. Whenever I am building dictionary, however, will help you spell archaic words. Whenever I am building
I use our Merriam Webster dictionary link on TBA to check any tough words for I use our Merriam Webster dictionary link on TBA to check any tough words for
proper spelling. Test it out @RTELL M-W DEFINITION@n. We hope to add a thesaurus proper spelling. We hope to add a thesaurus soon! Goto @Chttp://m-w.com/@n
soon! Goto @Chttp://m-w.com/@n until then. until then.
I have found that a good principle to make is to avoid the use of all I have found that a good principle to make is to avoid the use of all
contractions. For example, if you mean to say "it is", do not use "it's", spell contractions. For example, if you mean to say "it is", do not use "it's", spell
it out. This will help differentiate between "its" (which means 'belonging to it out. This will help differentiate between "its" (which means 'belonging to
@ -7192,7 +7172,7 @@ prefer to add the quest in the zone where quest completion takes place.
Quests use vnums in exactly the same way as mobiles, object and rooms. Each Quests use vnums in exactly the same way as mobiles, object and rooms. Each
zone will normally have 100 vnums available (#00 to #99, where # is the zone zone will normally have 100 vnums available (#00 to #99, where # is the zone
number). Usually, when creating the first quest in a zone, #00 is used, number). Usually, when creating the first quest in a zone, #00 is used,
then #01, etc then #01, etc.
When you qedit <vnum> to create a new quest (or edit an existing one), you will When you qedit <vnum> to create a new quest (or edit an existing one), you will
see the menu in @RHELP QEDIT-MENU@n see the menu in @RHELP QEDIT-MENU@n
@ -7203,12 +7183,12 @@ QEDIT-ACCEPT
This is the text that is sent to the player when they start the quest. It This is the text that is sent to the player when they start the quest. It
should describe in detail exactly what is required to complete the quest. The should describe in detail exactly what is required to complete the quest. The
text is simply output on the players screen, so be creative here. An example text is simply output on the player's screen, so be creative here. An example
of an accept message text could be something like: of an accept message text could be something like:
The questmaster rummages in a large pile of papers. The questmaster rummages in a large pile of papers.
The questmaster says Ah, here it is The questmaster says "Ah, here it is"
The questmaster says Bob, the local butcher has offered this quest The questmaster says "Bob, the local butcher has offered this quest"
The questmaster shows you a hastily scrawled note, that reads: The questmaster shows you a hastily scrawled note, that reads:
I am willing to offer any plucky adventurer 10 quest points if they bring me a I am willing to offer any plucky adventurer 10 quest points if they bring me a
@ -7218,7 +7198,7 @@ order to fill. I need these within 24 hours
Thanks, Bob the Butcher, Midgaard Thanks, Bob the Butcher, Midgaard
The questmaster sighs. The questmaster sighs.
The questmaster says A tricky quest, but itll cost you 5qp to back out now The questmaster says "A tricky quest, but it'll cost you 5qp to back out now"
#31 #31
QEDIT-COMPLETED QEDIT-ABANDONED QEDIT-COMPLETED QEDIT-ABANDONED
@ -7232,7 +7212,7 @@ all timed quests.
QEDIT-COMPLETION QEDIT-COMPLETION
Just like the accept message, this is simply text that is output on the Just like the accept message, this is simply text that is output on the
players screen when they successfully complete the quest. Prizes (quest player's screen when they successfully complete the quest. Prizes (quest
points, gold coins, experience points or an object) are automatically points, gold coins, experience points or an object) are automatically
announced after this text is shown, so this text does not need to have that announced after this text is shown, so this text does not need to have that
information in it. information in it.
@ -7258,7 +7238,7 @@ Quest flags: @cNOBITS@n
Enter quest flags, 0 to quit : Enter quest flags, 0 to quit :
Currently, only one flag is available, the REPEATABLE flag. When you have Currently, only one flag is available, the REPEATABLE flag. When you have
finished turning this on or off, select 0 (zero) to return to the main menu. finished turning this on or off, select "0" (zero) to return to the main menu.
#31 #31
QEDIT-LEVELS QEDIT-LEVELS
@ -7312,12 +7292,12 @@ QEDIT-NEXT
This is the quest vnum of next quest in a chain. When a player completes This is the quest vnum of next quest in a chain. When a player completes
the current quest, the next quest will automatically be joined. This allows the current quest, the next quest will automatically be joined. This allows
for long quests with a number of steps. for long quests with a number of "steps".
#31 #31
QEDIT-PREREQUISITE QEDIT-PREREQUISITE
This is the object vnum for a prerequisite object. The prerequisite object This is the object vnum for a prerequisite object. The prerequisite object
should be in the players inventory in order for them to be able to join the should be in the player's inventory in order for them to be able to join the
quest. It is not taken from the player when the quest starts. quest. It is not taken from the player when the quest starts.
#31 #31
QEDIT-PREVIOUS QEDIT-PREVIOUS
@ -7328,15 +7308,15 @@ completed by the player in order to join this quest.
QEDIT-QUANTITY QEDIT-QUANTITY
This is the number of times the player needs to repeat the quest. For This is the number of times the player needs to repeat the quest. For
example, it could be the number of items the player needs to find in a object example, it could be the number of items the player needs to find in a "object"
quest of the number of mobs the player should kill in a kill mob quest. This quest of the number of mobs the player should kill in a "kill mob" quest. This
should be used with caution, however. In an object quest picking up the same should be used with caution, however. In an object quest picking up the same
object 20 times will also complete the quest. object 20 times will also complete the quest.
#31 #31
QEDIT-QUIT QEDIT-MESSAGE QEDIT-QUIT QEDIT-MESSAGE
The quit message is sent to the player when they type quest leave. Players The quit message is sent to the player when they type quest leave. Players
can lose quest points for abandoning a quest (see “Abandoned” on the next can lose quest points for abandoning a quest (see "Abandoned" on the next
page), so if they lose quest points, this text really should inform them of page), so if they lose quest points, this text really should inform them of
that. that.
#31 #31
@ -7365,14 +7345,14 @@ Room, Clear Room - Room VNUM
#31 #31
QEDIT-TIME QEDIT-TIME
This is the number of ticks or game hours that the player has to complete This is the number of 'ticks' or game hours that the player has to complete
the quest. If this is set, then the builder should really try to do the quest the quest. If this is set, then the builder should really try to do the quest
themselves, and time how long it takes (typing time before and after the themselves, and time how long it takes (typing 'time' before and after the
attempt), and then giving at least one extra tick for players to complete it. attempt), and then giving at least one extra 'tick' for players to complete it.
#31 #31
QEDIT-TYPE QEDIT-TYPE
There are a few different quest types. When you select option 7 from the There are a few different quest types. When you select option '7' from the
main menu, you will be shown a list to choose from: main menu, you will be shown a list to choose from:
0) Object - Player needs to find a particular object. 0) Object - Player needs to find a particular object.
@ -7447,7 +7427,7 @@ Usage: quest [list | join <#> | progress | leave | history]
quest - Show usage information for the quest command. quest - Show usage information for the quest command.
quest list - Used at the questmaster to see which quests are available. quest list - Used at the questmaster to see which quests are available.
quest join # - Used to the questmaster to join the quest listed as number nn on quest list. quest join # - Used to the questmaster to join the quest listed as number 'nn' on quest list.
quest progress - Shows the player which quest they are doing, and their quest progress. quest progress - Shows the player which quest they are doing, and their quest progress.
quest leave - Allows the player to abandon the current quest, taking the quest point penalty. quest leave - Allows the player to abandon the current quest, taking the quest point penalty.
quest history - Shows all previously completed non-repeatable quests. quest history - Shows all previously completed non-repeatable quests.
@ -9352,7 +9332,7 @@ and simply bearing artistic merit. Second, by ensuring that they are absolutely
necessary to achieve the goals of the game! If your game is made for experience necessary to achieve the goals of the game! If your game is made for experience
and equipment gathering, and failure to read descriptions directly impedes this and equipment gathering, and failure to read descriptions directly impedes this
goal, then players will learn to read everything. If your game is made for goal, then players will learn to read everything. If your game is made for
exploring or role-play, most of your players probably already read them Â- exploring or role-play, most of your players probably already read them -
because knowing their environment is a basic requirement of play. In any case, because knowing their environment is a basic requirement of play. In any case,
builders exist to ensure that the goals of play are supported by game builders exist to ensure that the goals of play are supported by game
descriptions. descriptions.
@ -9364,7 +9344,7 @@ meaning behind descriptions, areas to find, special items, unique nooks and
crannies to spend time socializing, and hints that point to these things crannies to spend time socializing, and hints that point to these things
elsewhere outside of your own zone is an excellent idea. In fact, if you elsewhere outside of your own zone is an excellent idea. In fact, if you
don't wish to be building descriptions no one will read, you should employ don't wish to be building descriptions no one will read, you should employ
special secrets Â- most especially on games where knowing one's environment special secrets - most especially on games where knowing one's environment
does deeply affect a character's development. No matter what kind of zone you does deeply affect a character's development. No matter what kind of zone you
are building, keep it interesting throughout! are building, keep it interesting throughout!
@ -9387,7 +9367,7 @@ road.
shouldn't be the sole builder of your zone. Instead, seek the assistance of shouldn't be the sole builder of your zone. Instead, seek the assistance of
someone who adds creative merit to your descriptions. You can do practically someone who adds creative merit to your descriptions. You can do practically
everything from plot to secrets to minutiae, even write the zone in full and everything from plot to secrets to minutiae, even write the zone in full and
just ask someone you know who writes well to Â'say it better' and rewrite just ask someone you know who writes well to 'say it better' and rewrite
what you intended to have there all along. Novels have editors, and so what you intended to have there all along. Novels have editors, and so
should any zone. should any zone.
@ -9659,19 +9639,19 @@ have a point and here it is: *drum roll please*
Building is hard work! It is a form of expression and creativity. What kind Building is hard work! It is a form of expression and creativity. What kind
of areas you build generally reflects on what kind of person you are. You of areas you build generally reflects on what kind of person you are. You
do not have to be a good speller but you do need a good dictionary/thesaurus. do not have to be a good speller but you do need a good dictionary/thesaurus.
@RHELP M-W@n. Sometimes building can seem like a thankless job and sometimes Sometimes building can seem like a thankless job and sometimes building can be
building can be a reward in itself. Building a few areas, even a few good a reward in itself. Building a few areas, even a few good ones, does not make
ones, does not make you an Immortal or an Imp. It takes more than building to you an Immortal or an Imp. It takes more than building to be one of those and
be one of those and it entails even more work. Respect others and they will it entails even more work. Respect others and they will respect you. The more
respect you. The more detailed an area the better it is. Always choose Quality detailed an area the better it is. Always choose Quality over Quantity. Put
over Quantity. Put some pride in your areas, develop a style of your own. Try some pride in your areas, develop a style of your own. Try new things keep it
new things keep it interesting, if you become bored with building an area take interesting, if you become bored with building an area take a break and play a
a break and play a mortal or do something else, don't take advantage of builder mortal or do something else, don't take advantage of builder privileges.
privileges. Treat others as you wish to be treated. One more warning I would Treat others as you wish to be treated. One more warning I would give to
give to builders before they take things personally or get insulted. Everyone builders before they take things personally or get insulted. Everyone has their
has their own ideas on how to run a MUD, what it comes down to is whoever owns own ideas on how to run a MUD, what it comes down to is whoever owns the MUD
the MUD makes the final decision, so it does not matter how good you think your makes the final decision, so it does not matter how good you think your idea
idea is, it may never be used if the owner does not like it. Plain and simple. is, it may never be used if the owner does not like it. Plain and simple.
You see this on every MUD. So please keep the ideas coming, but do not try to You see this on every MUD. So please keep the ideas coming, but do not try to
force them onto anyone. Be constructive, not critical about peoples ideas. force them onto anyone. Be constructive, not critical about peoples ideas.
Everyone is allowed their opinions. Everyone is allowed their opinions.

81
power_curve.ipynb Normal file

File diff suppressed because one or more lines are too long

View file

@ -20,8 +20,8 @@ CFLAGS = @CFLAGS@ $(MYFLAGS) $(PROFILE)
LIBS = @LIBS@ @CRYPTLIB@ @NETLIB@ LIBS = @LIBS@ @CRYPTLIB@ @NETLIB@
SRCFILES := act.comm.c act.informative.c act.item.c act.movement.c act.offensive.c act.other.c act.social.c act.wizard.c aedit.c asciimap.c ban.c boards.c bsd-snprintf.c castle.c cedit.c class.c comm.c config.c constants.c db.c dg_comm.c dg_db_scripts.c dg_event.c dg_handler.c dg_misc.c dg_mobcmd.c dg_objcmd.c dg_olc.c dg_scripts.c dg_triggers.c dg_variables.c dg_wldcmd.c fight.c genmob.c genobj.c genolc.c genqst.c genshp.c genwld.c genzon.c graph.c handler.c hedit.c house.c ibt.c improved-edit.c interpreter.c limits.c lists.c magic.c mail.c main.c medit.c mobact.c modify.c msgedit.c mud_event.c oasis.c oasis_copy.c oasis_delete.c oasis_list.c objsave.c oedit.c players.c prefedit.c protocol.c qedit.c quest.c random.c redit.c sedit.c shop.c spec_assign.c spec_procs.c spell_parser.c spells.c tedit.c utils.c weather.c zedit.c zmalloc.c SRCFILES := $(shell ls *.c | sort)
OBJFILES := act.comm.o act.informative.o act.item.o act.movement.o act.offensive.o act.other.o act.social.o act.wizard.o aedit.o asciimap.o ban.o boards.o bsd-snprintf.o castle.o cedit.o class.o comm.o config.o constants.o db.o dg_comm.o dg_db_scripts.o dg_event.o dg_handler.o dg_misc.o dg_mobcmd.o dg_objcmd.o dg_olc.o dg_scripts.o dg_triggers.o dg_variables.o dg_wldcmd.o fight.o genmob.o genobj.o genolc.o genqst.o genshp.o genwld.o genzon.o graph.o handler.o hedit.o house.o ibt.o improved-edit.o interpreter.o limits.o lists.o magic.o mail.o main.o medit.o mobact.o modify.o msgedit.o mud_event.o oasis.o oasis_copy.o oasis_delete.o oasis_list.o objsave.o oedit.o players.o prefedit.o protocol.o qedit.o quest.o random.o redit.o sedit.o shop.o spec_assign.o spec_procs.o spell_parser.o spells.o tedit.o utils.o weather.o zedit.o zmalloc.o OBJFILES := $(patsubst %.c,%.o,$(SRCFILES))
default: all default: all
@ -32,10 +32,6 @@ all: .accepted
.accepted: .accepted:
@./licheck @MORE@ @./licheck @MORE@
.PHONY: test
test:
(cd test; $(MAKE) all)
utils: .accepted utils: .accepted
(cd util; $(MAKE) all) (cd util; $(MAKE) all)
@ -50,7 +46,6 @@ $%.o: %.c
clean: clean:
rm -f *.o depend rm -f *.o depend
(cd test; $(MAKE) clean)
# Dependencies for the object files (automagically generated with # Dependencies for the object files (automagically generated with
# gcc -MM) # gcc -MM)

56
src/Makefile.macOS Normal file
View file

@ -0,0 +1,56 @@
# tbaMUD Makefile.in - Makefile template used by 'configure'
# Clean-up provided by seqwith.
# C compiler to use
CC = gcc
# Any special flags you want to pass to the compiler
MYFLAGS = -Wall -Wno-char-subscripts -Wno-invalid-source-encoding -DMEMORY_DEBUG
#flags for profiling (see hacker.doc for more information)
PROFILE =
##############################################################################
# Do Not Modify Anything Below This Line (unless you know what you're doing) #
##############################################################################
BINDIR = ../bin
CFLAGS = -g -O0 $(MYFLAGS) $(PROFILE)
LIBS =
SRCFILES := $(shell ls *.c | sort)
OBJFILES := $(patsubst %.c,%.o,$(SRCFILES))
default: all
all: .accepted
$(MAKE) $(BINDIR)/circle
$(MAKE) utils
.accepted:
@./licheck less
utils: .accepted
(cd util; $(MAKE) all)
circle:
$(MAKE) $(BINDIR)/circle
$(BINDIR)/circle : $(OBJFILES)
$(CC) -o $(BINDIR)/circle $(PROFILE) $(OBJFILES) $(LIBS)
$%.o: %.c
$(CC) $< $(CFLAGS) -c -o $@
clean:
rm -f *.o depend
# Dependencies for the object files (automagically generated with
# gcc -MM)
depend:
$(CC) -MM *.c > depend
-include depend

View file

@ -150,39 +150,7 @@ ACMD(do_tell)
if (!*buf || !*buf2) if (!*buf || !*buf2)
send_to_char(ch, "Who do you wish to tell what??\r\n"); send_to_char(ch, "Who do you wish to tell what??\r\n");
else if (!strcmp(buf, "m-w")) { else if (GET_LEVEL(ch) < LVL_IMMORT && !(vict = get_player_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
#ifdef CIRCLE_WINDOWS
/* getpid() is not portable */
send_to_char(ch, "Sorry, that is not available in the windows port.\r\n");
#else /* all other configurations */
char word[MAX_INPUT_LENGTH], *p, *q;
if (last_webster_teller != -1L) {
if (GET_IDNUM(ch) == last_webster_teller) {
send_to_char(ch, "You are still waiting for a response.\r\n");
return;
} else {
send_to_char(ch, "Hold on, m-w is busy. Try again in a couple of seconds.\r\n");
return;
}
}
/* Only a-z and +/- allowed. */
for (p = buf2, q = word; *p ; p++)
if ((LOWER(*p) <= 'z' && LOWER(*p) >= 'a') || (*p == '+') || (*p == '-'))
*q++ = *p;
*q = '\0';
if (!*word) {
send_to_char(ch, "Sorry, only letters and +/- are allowed characters.\r\n");
return;
}
snprintf(buf, sizeof(buf), "../bin/webster %s %d &", word, (int) getpid());
last_webster_teller = GET_IDNUM(ch);
send_to_char(ch, "You look up '%s' in Merriam-Webster.\r\n", word);
#endif /* platform specific part */
} else if (GET_LEVEL(ch) < LVL_IMMORT && !(vict = get_player_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "%s", CONFIG_NOPERSON); send_to_char(ch, "%s", CONFIG_NOPERSON);
else if (GET_LEVEL(ch) >= LVL_IMMORT && !(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD))) else if (GET_LEVEL(ch) >= LVL_IMMORT && !(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "%s", CONFIG_NOPERSON); send_to_char(ch, "%s", CONFIG_NOPERSON);

View file

@ -46,10 +46,10 @@ static void list_obj_to_char(struct obj_data *list, struct char_data *ch, int mo
static void show_obj_to_char(struct obj_data *obj, struct char_data *ch, int mode); static void show_obj_to_char(struct obj_data *obj, struct char_data *ch, int mode);
static void show_obj_modifiers(struct obj_data *obj, struct char_data *ch); static void show_obj_modifiers(struct obj_data *obj, struct char_data *ch);
/* do_where utility functions */ /* do_where utility functions */
static void perform_immort_where(struct char_data *ch, char *arg); static void perform_immort_where(char_data *ch, const char *arg);
static void perform_mortal_where(struct char_data *ch, char *arg); static void perform_mortal_where(struct char_data *ch, char *arg);
static void print_object_location(int num, struct obj_data *obj, struct char_data *ch, int recur); static size_t print_object_location(int num, const obj_data *obj, const char_data *ch,
char *buf, size_t len, size_t buf_size, int recur);
/* Subcommands */ /* Subcommands */
/* For show_obj_to_char 'mode'. /-- arbitrary */ /* For show_obj_to_char 'mode'. /-- arbitrary */
#define SHOW_OBJ_LONG 0 #define SHOW_OBJ_LONG 0
@ -1603,41 +1603,71 @@ static void perform_mortal_where(struct char_data *ch, char *arg)
} }
} }
static void print_object_location(int num, struct obj_data *obj, struct char_data *ch, static size_t print_object_location(const int num, const obj_data *obj, const char_data *ch, // NOLINT(*-no-recursion)
int recur) char *buf, size_t len, const size_t buf_size, const int recur)
{ {
size_t nlen = 0;
if (num > 0) if (num > 0)
send_to_char(ch, "O%3d. %-25s%s - ", num, obj->short_description, QNRM); nlen = snprintf(buf + len, buf_size - len, "O%4d. %-25s%s - ", num, obj->short_description, QNRM);
else else
send_to_char(ch, "%33s", " - "); nlen = snprintf(buf + len, buf_size - len, "%37s", " - ");
len += nlen;
nlen = 0;
if (len > buf_size)
return len; // let the caller know we overflowed
if (SCRIPT(obj)) { if (SCRIPT(obj)) {
if (!TRIGGERS(SCRIPT(obj))->next) if (!TRIGGERS(SCRIPT(obj))->next)
send_to_char(ch, "[T%d] ", GET_TRIG_VNUM(TRIGGERS(SCRIPT(obj)))); nlen = snprintf(buf + len, buf_size - len, "[T%d] ", GET_TRIG_VNUM(TRIGGERS(SCRIPT(obj))));
else else
send_to_char(ch, "[TRIGS] "); nlen = snprintf(buf + len, buf_size - len, "[TRIGS] ");
} }
len += nlen;
if (len > buf_size)
return len; // let the caller know we overflowed
if (IN_ROOM(obj) != NOWHERE) if (IN_ROOM(obj) != NOWHERE)
send_to_char(ch, "[%5d] %s%s\r\n", GET_ROOM_VNUM(IN_ROOM(obj)), world[IN_ROOM(obj)].name, QNRM); nlen = snprintf(buf + len, buf_size - len, "[%5d] %s%s\r\n", GET_ROOM_VNUM(IN_ROOM(obj)), world[IN_ROOM(obj)].name, QNRM);
else if (obj->carried_by) else if (obj->carried_by) {
send_to_char(ch, "carried by %s%s\r\n", PERS(obj->carried_by, ch), QNRM); if (PRF_FLAGGED(ch, PRF_SHOWVNUMS))
else if (obj->worn_by) nlen = snprintf(buf + len, buf_size - len, "carried by [%5d] %s%s\r\n", GET_MOB_VNUM(obj->carried_by), PERS(obj->carried_by, ch), QNRM);
send_to_char(ch, "worn by %s%s\r\n", PERS(obj->worn_by, ch), QNRM); else
else if (obj->in_obj) { nlen = snprintf(buf + len, buf_size - len, "carried by %s%s\r\n", PERS(obj->carried_by, ch), QNRM);
send_to_char(ch, "inside %s%s%s\r\n", obj->in_obj->short_description, QNRM, (recur ? ", which is" : " ")); if (PRF_FLAGGED(ch, PRF_VERBOSE) && IN_ROOM(obj->carried_by) != NOWHERE && len + nlen < buf_size)
if (recur) nlen += snprintf(buf + len + nlen, buf_size - len - nlen, "%37sin [%5d] %s%s\r\n", " - ", GET_ROOM_VNUM(IN_ROOM(obj->carried_by)), world[IN_ROOM(obj->carried_by)].name, QNRM);
print_object_location(0, obj->in_obj, ch, recur); } else if (obj->worn_by) {
if (PRF_FLAGGED(ch, PRF_SHOWVNUMS))
nlen = snprintf(buf + len, buf_size - len, "worn by [%5d] %s%s\r\n", GET_MOB_VNUM(obj->worn_by), PERS(obj->worn_by, ch), QNRM);
else
nlen = snprintf(buf + len, buf_size - len, "worn by %s%s\r\n", PERS(obj->worn_by, ch), QNRM);
if (PRF_FLAGGED(ch, PRF_VERBOSE) && IN_ROOM(obj->worn_by) != NOWHERE && len + nlen < buf_size)
nlen += snprintf(buf + len + nlen, buf_size - len - nlen, "%37sin [%5d] %s%s\r\n", " - ", GET_ROOM_VNUM(IN_ROOM(obj->worn_by)), world[IN_ROOM(obj->worn_by)].name, QNRM);
} else if (obj->in_obj) {
nlen = snprintf(buf + len, buf_size - len, "inside %s%s%s\r\n", obj->in_obj->short_description, QNRM, (recur ? ", which is" : " "));
if (recur && nlen + len < buf_size) {
len += nlen;
nlen = 0;
len = print_object_location(0, obj->in_obj, ch, buf, len, buf_size, recur);
}
} else } else
send_to_char(ch, "in an unknown location\r\n"); nlen = snprintf(buf + len, buf_size - len, "in an unknown location\r\n");
len += nlen;
return len;
} }
static void perform_immort_where(struct char_data *ch, char *arg) static void perform_immort_where(char_data *ch, const char *arg)
{ {
struct char_data *i; char_data *i;
struct obj_data *k; obj_data *k;
struct descriptor_data *d; struct descriptor_data *d;
int num = 0, found = 0; int num = 0, found = FALSE; // "num" here needs to match the lookup in do_stat, so "stat 4.sword" finds the right one
const char *error_message = "\r\n***OVERFLOW***\r\n";
char buf[MAX_STRING_LENGTH];
size_t len = 0, nlen = 0;
const size_t buf_size = sizeof(buf) - strlen(error_message) - 1;
if (!*arg) { if (!*arg) {
send_to_char(ch, "Players Room Location Zone\r\n"); send_to_char(ch, "Players Room Location Zone\r\n");
@ -1658,26 +1688,64 @@ static void perform_immort_where(struct char_data *ch, char *arg)
} }
} }
} else { } else {
if (PRF_FLAGGED(ch, PRF_VERBOSE))
len = snprintf(buf, buf_size, " ### Mob name - Room # Room name\r\n");
for (i = character_list; i; i = i->next) for (i = character_list; i; i = i->next)
if (CAN_SEE(ch, i) && IN_ROOM(i) != NOWHERE && isname(arg, i->player.name)) { if (CAN_SEE(ch, i) && IN_ROOM(i) != NOWHERE && isname(arg, i->player.name)) {
found = 1; found = 1;
send_to_char(ch, "M%3d. %-25s%s - [%5d] %-25s%s", ++num, GET_NAME(i), QNRM, nlen = snprintf(buf + len, buf_size - len, "M%4d. %-25s%s - [%5d] %-25s%s", ++num, GET_NAME(i), QNRM,
GET_ROOM_VNUM(IN_ROOM(i)), world[IN_ROOM(i)].name, QNRM); GET_ROOM_VNUM(IN_ROOM(i)), world[IN_ROOM(i)].name, QNRM);
if (len + nlen >= buf_size) {
len += snprintf(buf + len, buf_size - len, "%s", error_message);
break;
}
len += nlen;
if (SCRIPT(i) && TRIGGERS(SCRIPT(i))) { if (SCRIPT(i) && TRIGGERS(SCRIPT(i))) {
if (!TRIGGERS(SCRIPT(i))->next) if (!TRIGGERS(SCRIPT(i))->next)
send_to_char(ch, "[T%d] ", GET_TRIG_VNUM(TRIGGERS(SCRIPT(i)))); nlen = snprintf(buf + len, buf_size - len, "[T%d]", GET_TRIG_VNUM(TRIGGERS(SCRIPT(i))));
else else
send_to_char(ch, "[TRIGS] "); nlen = snprintf(buf + len, buf_size - len, "[TRIGS]");
if (len + nlen >= buf_size) {
snprintf(buf + len, buf_size - len, "%s", error_message);
break;
}
len += nlen;
} }
send_to_char(ch, "%s\r\n", QNRM); nlen = snprintf(buf + len, buf_size - len, "%s\r\n", QNRM);
if (len + nlen >= buf_size) {
snprintf(buf + len, buf_size - len, "%s", error_message);
break;
}
len += nlen;
} }
for (num = 0, k = object_list; k; k = k->next)
if (CAN_SEE_OBJ(ch, k) && isname(arg, k->name)) { if (PRF_FLAGGED(ch, PRF_VERBOSE) && len < buf_size) {
found = 1; nlen = snprintf(buf + len, buf_size - len, " ### Object name Location\r\n");
print_object_location(++num, k, ch, TRUE); if (len + nlen >= buf_size) {
snprintf(buf + len, buf_size - len, "%s", error_message);
} }
len += nlen;
}
if (len < buf_size) {
for (k = object_list; k; k = k->next) {
if (CAN_SEE_OBJ(ch, k) && isname(arg, k->name)) {
found = 1;
len = print_object_location(++num, k, ch, buf, len, buf_size, TRUE);
if (len >= buf_size) {
snprintf(buf + buf_size, sizeof(buf) - buf_size, "%s", error_message);
break;
}
}
}
}
if (!found) if (!found)
send_to_char(ch, "Couldn't find any such thing.\r\n"); send_to_char(ch, "Couldn't find any such thing.\r\n");
else
page_string(ch->desc, buf, TRUE);
} }
} }
@ -1937,6 +2005,9 @@ ACMD(do_toggle)
{"pagelength", 0, 0, "\n", "\n"}, {"pagelength", 0, 0, "\n", "\n"},
{"screenwidth", 0, 0, "\n", "\n"}, {"screenwidth", 0, 0, "\n", "\n"},
{"color", 0, 0, "\n", "\n"}, {"color", 0, 0, "\n", "\n"},
{"verbose", PRF_VERBOSE, LVL_IMMORT,
"You will no longer see verbose output in listings.\n",
"You will now see verbose listings.\n"},
{"\n", 0, -1, "\n", "\n"} /* must be last */ {"\n", 0, -1, "\n", "\n"} /* must be last */
}; };
@ -1950,7 +2021,8 @@ ACMD(do_toggle)
if (!GET_WIMP_LEV(ch)) if (!GET_WIMP_LEV(ch))
strcpy(buf2, "OFF"); /* strcpy: OK */ strcpy(buf2, "OFF"); /* strcpy: OK */
else else
sprintf(buf2, "%-3.3d", GET_WIMP_LEV(ch)); /* sprintf: OK */ snprintf(buf2, sizeof(buf2), "%-3.3d", GET_WIMP_LEV(ch)); /* thanks to Ironfist for the fix for the buffer overrun here */
if (GET_LEVEL(ch) == LVL_IMPL) { if (GET_LEVEL(ch) == LVL_IMPL) {
send_to_char(ch, send_to_char(ch,
@ -1970,7 +2042,8 @@ ACMD(do_toggle)
" NoHassle: %-3s " " NoHassle: %-3s "
" Holylight: %-3s " " Holylight: %-3s "
" ShowVnums: %-3s\r\n" " ShowVnums: %-3s\r\n"
" Syslog: %-3s%s ", " Syslog: %-3s "
" Verbose: %-3s%s ",
ONOFF(PRF_FLAGGED(ch, PRF_BUILDWALK)), ONOFF(PRF_FLAGGED(ch, PRF_BUILDWALK)),
ONOFF(PRF_FLAGGED(ch, PRF_NOWIZ)), ONOFF(PRF_FLAGGED(ch, PRF_NOWIZ)),
@ -1979,6 +2052,7 @@ ACMD(do_toggle)
ONOFF(PRF_FLAGGED(ch, PRF_HOLYLIGHT)), ONOFF(PRF_FLAGGED(ch, PRF_HOLYLIGHT)),
ONOFF(PRF_FLAGGED(ch, PRF_SHOWVNUMS)), ONOFF(PRF_FLAGGED(ch, PRF_SHOWVNUMS)),
types[(PRF_FLAGGED(ch, PRF_LOG1) ? 1 : 0) + (PRF_FLAGGED(ch, PRF_LOG2) ? 2 : 0)], types[(PRF_FLAGGED(ch, PRF_LOG1) ? 1 : 0) + (PRF_FLAGGED(ch, PRF_LOG2) ? 2 : 0)],
ONOFF(PRF_FLAGGED(ch, PRF_VERBOSE)),
GET_LEVEL(ch) == LVL_IMPL ? "" : "\r\n"); GET_LEVEL(ch) == LVL_IMPL ? "" : "\r\n");
} }
if (GET_LEVEL(ch) >= LVL_IMPL) { if (GET_LEVEL(ch) >= LVL_IMPL) {

View file

@ -785,6 +785,9 @@ void name_from_drinkcon(struct obj_data *obj)
if (!obj || (GET_OBJ_TYPE(obj) != ITEM_DRINKCON && GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN)) if (!obj || (GET_OBJ_TYPE(obj) != ITEM_DRINKCON && GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN))
return; return;
if (obj->name == obj_proto[GET_OBJ_RNUM(obj)].name)
obj->name = strdup(obj_proto[GET_OBJ_RNUM(obj)].name);
liqname = drinknames[GET_OBJ_VAL(obj, 2)]; liqname = drinknames[GET_OBJ_VAL(obj, 2)];
remove_from_string(obj->name, liqname); remove_from_string(obj->name, liqname);

View file

@ -557,7 +557,7 @@ void aedit_parse(struct descriptor_data * d, char *arg) {
} }
if (OLC_ACTION(d)->command) if (OLC_ACTION(d)->command)
free(OLC_ACTION(d)->command); free(OLC_ACTION(d)->command);
OLC_ACTION(d)->command = strdup(arg); OLC_ACTION(d)->command = strdup(arg);
break; break;
@ -566,10 +566,10 @@ void aedit_parse(struct descriptor_data * d, char *arg) {
aedit_disp_menu(d); aedit_disp_menu(d);
return; return;
} }
if (OLC_ACTION(d)->sort_as) { if (OLC_ACTION(d)->sort_as)
free(OLC_ACTION(d)->sort_as); free(OLC_ACTION(d)->sort_as);
OLC_ACTION(d)->sort_as = strdup(arg); OLC_ACTION(d)->sort_as = strdup(arg);
}
break; break;
case AEDIT_MIN_CHAR_POS: case AEDIT_MIN_CHAR_POS:

View file

@ -104,8 +104,7 @@ unsigned long pulse = 0; /* number of pulses since game start */
ush_int port; ush_int port;
socket_t mother_desc; socket_t mother_desc;
int next_tick = SECS_PER_MUD_HOUR; /* Tick countdown */ int next_tick = SECS_PER_MUD_HOUR; /* Tick countdown */
/* used with do_tell and handle_webster_file utility */
long last_webster_teller = -1L;
/* static local global variable declarations (current file scope only) */ /* static local global variable declarations (current file scope only) */
static struct txt_block *bufpool = 0; /* pool of large output buffers */ static struct txt_block *bufpool = 0; /* pool of large output buffers */
@ -113,14 +112,11 @@ static int max_players = 0; /* max descriptors available */
static int tics_passed = 0; /* for extern checkpointing */ static int tics_passed = 0; /* for extern checkpointing */
static struct timeval null_time; /* zero-valued time structure */ static struct timeval null_time; /* zero-valued time structure */
static byte reread_wizlist; /* signal: SIGUSR1 */ static byte reread_wizlist; /* signal: SIGUSR1 */
/* normally signal SIGUSR2, currently orphaned in favor of Webster dictionary static byte emergency_unban; /* signal: SIGUSR2 */
* lookup
static byte emergency_unban;
*/
static int dg_act_check; /* toggle for act_trigger */ static int dg_act_check; /* toggle for act_trigger */
static bool fCopyOver; /* Are we booting in copyover mode? */ static bool fCopyOver; /* Are we booting in copyover mode? */
static char *last_act_message = NULL; static char *last_act_message = NULL;
static byte webster_file_ready = FALSE;/* signal: SIGUSR2 */
/* static local function prototypes (current file scope only) */ /* static local function prototypes (current file scope only) */
static RETSIGTYPE reread_wizlists(int sig); static RETSIGTYPE reread_wizlists(int sig);
@ -160,9 +156,6 @@ static int open_logfile(const char *filename, FILE *stderr_fp);
#if defined(POSIX) #if defined(POSIX)
static sigfunc *my_signal(int signo, sigfunc *func); static sigfunc *my_signal(int signo, sigfunc *func);
#endif #endif
/* Webster Dictionary Lookup functions */
static RETSIGTYPE websterlink(int sig);
static void handle_webster_file(void);
static void msdp_update(void); /* KaVir plugin*/ static void msdp_update(void); /* KaVir plugin*/
@ -959,7 +952,7 @@ void game_loop(socket_t local_mother_desc)
mudlog(CMP, LVL_IMMORT, TRUE, "Signal received - rereading wizlists."); mudlog(CMP, LVL_IMMORT, TRUE, "Signal received - rereading wizlists.");
reboot_wizlists(); reboot_wizlists();
} }
/* Orphaned right now as signal trapping is used for Webster lookup
if (emergency_unban) { if (emergency_unban) {
emergency_unban = FALSE; emergency_unban = FALSE;
mudlog(BRF, LVL_IMMORT, TRUE, "Received SIGUSR2 - completely unrestricting game (emergent)"); mudlog(BRF, LVL_IMMORT, TRUE, "Received SIGUSR2 - completely unrestricting game (emergent)");
@ -967,11 +960,7 @@ void game_loop(socket_t local_mother_desc)
circle_restrict = 0; circle_restrict = 0;
num_invalid = 0; num_invalid = 0;
} }
*/
if (webster_file_ready) {
webster_file_ready = FALSE;
handle_webster_file();
}
#ifdef CIRCLE_UNIX #ifdef CIRCLE_UNIX
/* Update tics_passed for deadlock protection (UNIX only) */ /* Update tics_passed for deadlock protection (UNIX only) */
@ -1597,7 +1586,7 @@ static int process_output(struct descriptor_data *t)
result = write_to_descriptor(t->descriptor, osb); result = write_to_descriptor(t->descriptor, osb);
if (result < 0) { /* Oops, fatal error. Bye! */ if (result < 0) { /* Oops, fatal error. Bye! */
close_socket(t); // close_socket(t); // close_socket is called after return of negative result
return (-1); return (-1);
} else if (result == 0) /* Socket buffer full. Try later. */ } else if (result == 0) /* Socket buffer full. Try later. */
return (0); return (0);
@ -2233,18 +2222,10 @@ static RETSIGTYPE reread_wizlists(int sig)
reread_wizlist = TRUE; reread_wizlist = TRUE;
} }
/* Orphaned right now in place of Webster ...
static RETSIGTYPE unrestrict_game(int sig) static RETSIGTYPE unrestrict_game(int sig)
{ {
emergency_unban = TRUE; emergency_unban = TRUE;
} }
*/
static RETSIGTYPE websterlink(int sig)
{
webster_file_ready = TRUE;
}
#ifdef CIRCLE_UNIX #ifdef CIRCLE_UNIX
@ -2319,7 +2300,7 @@ static void signal_setup(void)
/* user signal 2: unrestrict game. Used for emergencies if you lock /* user signal 2: unrestrict game. Used for emergencies if you lock
* yourself out of the MUD somehow. */ * yourself out of the MUD somehow. */
my_signal(SIGUSR2, websterlink); my_signal(SIGUSR2, unrestrict_game);
/* set up the deadlock-protection so that the MUD aborts itself if it gets /* set up the deadlock-protection so that the MUD aborts itself if it gets
* caught in an infinite loop for more than 3 minutes. */ * caught in an infinite loop for more than 3 minutes. */
@ -2781,45 +2762,6 @@ static void circle_sleep(struct timeval *timeout)
#endif /* CIRCLE_WINDOWS */ #endif /* CIRCLE_WINDOWS */
static void handle_webster_file(void) {
FILE *fl;
struct char_data *ch = find_char(last_webster_teller);
char retval[MAX_STRING_LENGTH], line[READ_SIZE];
size_t len = 0, nlen = 0;
last_webster_teller = -1L;
if (!ch) /* they quit ? */
return;
fl = fopen("websterinfo", "r");
if (!fl) {
send_to_char(ch, "It seems the dictionary is offline..\r\n");
return;
}
unlink("websterinfo");
get_line(fl, line);
while (!feof(fl)) {
nlen = snprintf(retval + len, sizeof(retval) - len, "%s\r\n", line);
if (len + nlen >= sizeof(retval))
break;
len += nlen;
get_line(fl, line);
}
if (len >= sizeof(retval)) {
const char *overflow = "\r\n**OVERFLOW**\r\n";
strcpy(retval + sizeof(retval) - strlen(overflow) - 1, overflow); /* strcpy: OK */
}
fclose(fl);
send_to_char(ch, "You get this feedback from Merriam-Webster:\r\n");
page_string(ch->desc, retval, 1);
}
/* KaVir's plugin*/ /* KaVir's plugin*/
static void msdp_update( void ) static void msdp_update( void )
{ {

View file

@ -61,9 +61,6 @@ void game_loop(socket_t mother_desc);
void heartbeat(int heart_pulse); void heartbeat(int heart_pulse);
void copyover_recover(void); void copyover_recover(void);
/** webster dictionary lookup */
extern long last_webster_teller;
extern struct descriptor_data *descriptor_list; extern struct descriptor_data *descriptor_list;
extern int buf_largecount; extern int buf_largecount;
extern int buf_overflows; extern int buf_overflows;

337
src/conf.h.cmake.in Normal file
View file

@ -0,0 +1,337 @@
/* src/conf.h.cmake.in. Used as basis for conf.h when building with cmake */
#ifndef _CONF_H_
#define _CONF_H_
/* Define to empty if the keyword does not work. */
#define const @CONST_KEYWORD@
/* Define if you don't have vprintf but do have _doprnt. */
#cmakedefine HAVE_DOPRNT
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#cmakedefine HAVE_SYS_WAIT_H
/* Define if you have the vprintf function. */
#cmakedefine HAVE_VPRINTF
/* Define to `int' if <sys/types.h> doesn't define. */
#cmakedefine pid_t @pid_t@
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE @RETSIGTYPE@
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#cmakedefine size_t @size_t@
/* Define if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#cmakedefine TIME_WITH_SYS_TIME
/* Define if we're compiling CircleMUD under any type of UNIX system. */
#cmakedefine CIRCLE_UNIX
/* Define if the system is capable of using crypt() to encrypt. */
#cmakedefine CIRCLE_CRYPT
/* Define if we don't have proper support for the system's crypt(). */
#cmakedefine HAVE_UNSAFE_CRYPT
/* Define is the system has struct in_addr. */
#cmakedefine HAVE_STRUCT_IN_ADDR
/* Define to `int' if <sys/socket.h> doesn't define. */
#cmakedefine socklen_t @socklen_t@
/* Define to `int' if <sys/types.h> doesn't define. */
#cmakedefine ssize_t @ssize_t@
/* Define if you have the gettimeofday function. */
#cmakedefine HAVE_GETTIMEOFDAY
/* Define if you have the inet_addr function. */
#cmakedefine HAVE_INET_ADDR
/* Define if you have the inet_aton function. */
#cmakedefine HAVE_INET_ATON
/* Define if you have the select function. */
#cmakedefine HAVE_SELECT
/* Define if you have the snprintf function. */
#cmakedefine HAVE_SNPRINTF
/* Define if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP
/* Define if you have the strdup function. */
#cmakedefine HAVE_STRDUP
/* Define if you have the strerror function. */
#cmakedefine HAVE_STRERROR
/* Define if you have the stricmp function. */
#cmakedefine HAVE_STRICMP
/* Define if you have the strlcpy function. */
#cmakedefine HAVE_STRLCPY
/* Define if you have the strncasecmp function. */
#cmakedefine HAVE_STRNCASECMP
/* Define if you have the strnicmp function. */
#cmakedefine HAVE_STRNICMP
/* Define if you have the strstr function. */
#cmakedefine HAVE_STRSTR
/* Define if you have the vsnprintf function. */
#cmakedefine HAVE_VSNPRINTF
/* Define if you have the <arpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H
/* Define if you have the <arpa/telnet.h> header file. */
#cmakedefine HAVE_ARPA_TELNET_H
/* Define if you have the <assert.h> header file. */
#cmakedefine HAVE_ASSERT_H
/* Define if you have the <crypt.h> header file. */
#cmakedefine HAVE_CRYPT_H
/* Define if you have the <errno.h> header file. */
#cmakedefine HAVE_ERRNO_H
/* Define if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H
/* Define if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H
/* Define if you have the <mcheck.h> header file. */
#cmakedefine HAVE_MCHECK_H
/* Define if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H
/* Define if you have the <net/errno.h> header file. */
#cmakedefine HAVE_NET_ERRNO_H
/* Define if you have the <netdb.h> header file. */
#cmakedefine HAVE_NETDB_H
/* Define if you have the <netinet/in.h> header file. */
#cmakedefine HAVE_NETINET_IN_H
/* Define if you have the <signal.h> header file. */
#cmakedefine HAVE_SIGNAL_H
/* Define if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H
/* Define if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H
/* Define if you have the <sys/fcntl.h> header file. */
#cmakedefine HAVE_SYS_FCNTL_H
/* Define if you have the <sys/resource.h> header file. */
#cmakedefine HAVE_SYS_RESOURCE_H
/* Define if you have the <sys/select.h> header file. */
#cmakedefine HAVE_SYS_SELECT_H
/* Define if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H
/* Define if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H
/* Define if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H
/* Define if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H
/* Define if you have the <sys/uio.h> header file. */
#cmakedefine HAVE_SYS_UIO_H
/* Define if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H
/* Define if you have the malloc library (-lmalloc). */
#cmakedefine HAVE_LIBMALLOC
/* Check for a prototype to accept. */
#cmakedefine NEED_ACCEPT_PROTO
/* Check for a prototype to atoi. */
#cmakedefine NEED_ATOI_PROTO
/* Check for a prototype to atol. */
#cmakedefine NEED_ATOL_PROTO
/* Check for a prototype to bind. */
#cmakedefine NEED_BIND_PROTO
/* Check for a prototype to bzero. */
#cmakedefine NEED_BZERO_PROTO
/* Check for a prototype to chdir. */
#cmakedefine NEED_CHDIR_PROTO
/* Check for a prototype to close. */
#cmakedefine NEED_CLOSE_PROTO
/* Check for a prototype to crypt. */
#cmakedefine NEED_CRYPT_PROTO
/* Check for a prototype to fclose. */
#cmakedefine NEED_FCLOSE_PROTO
/* Check for a prototype to fcntl. */
#cmakedefine NEED_FCNTL_PROTO
/* Check for a prototype to fflush. */
#cmakedefine NEED_FFLUSH_PROTO
/* Check for a prototype to fprintf. */
#cmakedefine NEED_FPRINTF_PROTO
/* Check for a prototype to fputc. */
#cmakedefine NEED_FPUTC_PROTO
/* Check for a prototype to fputs. */
#cmakedefine NEED_FPUTS_PROTO
/* Check for a prototype to fread. */
#cmakedefine NEED_FREAD_PROTO
/* Check for a prototype to fscanf. */
#cmakedefine NEED_FSCANF_PROTO
/* Check for a prototype to fseek. */
#cmakedefine NEED_FSEEK_PROTO
/* Check for a prototype to fwrite. */
#cmakedefine NEED_FWRITE_PROTO
/* Check for a prototype to getpeername. */
#cmakedefine NEED_GETPEERNAME_PROTO
/* Check for a prototype to getpid. */
#cmakedefine NEED_GETPID_PROTO
/* Check for a prototype to getrlimit. */
#cmakedefine NEED_GETRLIMIT_PROTO
/* Check for a prototype to getsockname. */
#cmakedefine NEED_GETSOCKNAME_PROTO
/* Check for a prototype to gettimeofday. */
#cmakedefine NEED_GETTIMEOFDAY_PROTO
/* Check for a prototype to htonl. */
#cmakedefine NEED_HTONL_PROTO
/* Check for a prototype to htons. */
#cmakedefine NEED_HTONS_PROTO
/* Check for a prototype to inet_addr. */
#cmakedefine NEED_INET_ADDR_PROTO
/* Check for a prototype to inet_aton. */
#cmakedefine NEED_INET_ATON_PROTO
/* Check for a prototype to inet_ntoa. */
#cmakedefine NEED_INET_NTOA_PROTO
/* Check for a prototype to listen. */
#cmakedefine NEED_LISTEN_PROTO
/* Check for a prototype to ntohl. */
#cmakedefine NEED_NTOHL_PROTO
/* Check for a prototype to perror. */
#cmakedefine NEED_PERROR_PROTO
/* Check for a prototype to printf. */
#cmakedefine NEED_PRINTF_PROTO
/* Check for a prototype to qsort. */
#cmakedefine NEED_QSORT_PROTO
/* Check for a prototype to read. */
#cmakedefine NEED_READ_PROTO
/* Check for a prototype to remove. */
#cmakedefine NEED_REMOVE_PROTO
/* Check for a prototype to rewind. */
#cmakedefine NEED_REWIND_PROTO
/* Check for a prototype to select. */
#cmakedefine NEED_SELECT_PROTO
/* Check for a prototype to setitimer. */
#cmakedefine NEED_SETITIMER_PROTO
/* Check for a prototype to setrlimit. */
#cmakedefine NEED_SETRLIMIT_PROTO
/* Check for a prototype to setsockopt. */
#cmakedefine NEED_SETSOCKOPT_PROTO
/* Check for a prototype to snprintf. */
#cmakedefine NEED_SNPRINTF_PROTO
/* Check for a prototype to socket. */
#cmakedefine NEED_SOCKET_PROTO
/* Check for a prototype to sprintf. */
#cmakedefine NEED_SPRINTF_PROTO
/* Check for a prototype to sscanf. */
#cmakedefine NEED_SSCANF_PROTO
/* Check for a prototype to strcasecmp. */
#cmakedefine NEED_STRCASECMP_PROTO
/* Check for a prototype to strdup. */
#cmakedefine NEED_STRDUP_PROTO
/* Check for a prototype to strerror. */
#cmakedefine NEED_STRERROR_PROTO
/* Check for a prototype to stricmp. */
#cmakedefine NEED_STRICMP_PROTO
/* Check for a prototype to strlcpy. */
#cmakedefine NEED_STRLCPY_PROTO
/* Check for a prototype to strncasecmp. */
#cmakedefine NEED_STRNCASECMP_PROTO
/* Check for a prototype to strnicmp. */
#cmakedefine NEED_STRNICMP_PROTO
/* Check for a prototype to system. */
#cmakedefine NEED_SYSTEM_PROTO
/* Check for a prototype to time. */
#cmakedefine NEED_TIME_PROTO
/* Check for a prototype to unlink. */
#cmakedefine NEED_UNLINK_PROTO
/* Check for a prototype to vsnprintf. */
#cmakedefine NEED_VSNPRINTF_PROTO
/* Check for a prototype to write. */
#cmakedefine NEED_WRITE_PROTO
#endif /* _CONF_H_ */

367
src/conf.h.macOS Normal file
View file

@ -0,0 +1,367 @@
#ifndef _CONF_H_
#define _CONF_H_
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define if you don't have vprintf but do have _doprnt. */
/* #undef HAVE_DOPRNT */
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#define HAVE_SYS_WAIT_H 1
/* Define if you have the vprintf function. */
#define HAVE_VPRINTF 1
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef pid_t */
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
/* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */
/* Define if you have the ANSI C header files. */
/* #undef STDC_HEADERS */
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Define if we're compiling CircleMUD under any type of UNIX system. */
#define CIRCLE_UNIX 1
/* Machine-specific dependencies for running on modern macOS systems 10.13+ (High Sierra)
* Updated by Victor Augusto Borges Dias de Almeida (aka Stoneheart), 26 June 2024.
*
* Tested on:
* - macOS 10.13: High Sierra - September 25, 2017 (Latest: 10.13.6)
* - macOS 10.14: Mojave - September 24, 2018 (Latest: 10.14.6)
* - macOS 10.15: Catalina - October 7, 2019 (Latest: 10.15.7)
* - macOS 11: Big Sur - November 12, 2020 (Latest: 11.7.10)
* - macOS 12: Monterey - October 25, 2021 (Latest: 12.7)
* - macOS 13: Ventura - November 7, 2022 (Latest: 13.7)
* - macOS 14: Sonoma - November 7, 2023 (Latest: 14.3)
*
* This file works on Apple Silicon Chips (M1, M2, M3) without futher configurations. */
#if defined(__APPLE__) && defined(__MACH__)
#define CIRCLE_MAC_OS 1
#endif
/* Define if the system is capable of using crypt() to encrypt. */
#define CIRCLE_CRYPT 1
/* Define if we don't have proper support for the system's crypt(). */
/* #undef HAVE_UNSAFE_CRYPT */
/* Define is the system has struct in_addr. */
#define HAVE_STRUCT_IN_ADDR 1
/* Define to `int' if <sys/socket.h> doesn't define. */
/* #undef socklen_t */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef ssize_t */
/* Define if you have the gettimeofday function. */
#define HAVE_GETTIMEOFDAY 1
/* Define if you have the inet_addr function. */
#define HAVE_INET_ADDR 1
/* Define if you have the inet_aton function. */
#define HAVE_INET_ATON 1
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the snprintf function. */
#define HAVE_SNPRINTF 1
/* Define if you have the strcasecmp function. */
#define HAVE_STRCASECMP 1
/* Define if you have the strdup function. */
#define HAVE_STRDUP 1
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
/* Define if you have the stricmp function. */
/* #undef HAVE_STRICMP */
/* Define if you have the strlcpy function. */
#ifndef CIRCLE_MAC_OS
#define HAVE_STRLCPY 1
#else
#define HAVE_STRLCPY 0
#endif
/* Define if you have the strncasecmp function. */
#define HAVE_STRNCASECMP 1
/* Define if you have the strnicmp function. */
/* #undef HAVE_STRNICMP */
/* Define if you have the strstr function. */
#define HAVE_STRSTR 1
/* Define if you have the vsnprintf function. */
#define HAVE_VSNPRINTF 1
/* Define if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define if you have the <arpa/telnet.h> header file. */
#define HAVE_ARPA_TELNET_H 1
/* Define if you have the <assert.h> header file. */
#define HAVE_ASSERT_H 1
/* Define if you have the <crypt.h> header file. */
/* #undef HAVE_CRYPT_H */
#ifdef CIRCLE_MAC_OS
#define HAVE_CRYPT_H 1
#endif
/* Define if you have the <errno.h> header file. */
#define HAVE_ERRNO_H 1
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define if you have the <mcheck.h> header file. */
/* #undef HAVE_MCHECK_H */
#ifdef CIRCLE_MAC_OS
#define HAVE_MCHECK_H 1
#endif
/* Define if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define if you have the <net/errno.h> header file. */
/* #undef HAVE_NET_ERRNO_H */
/* Define if you have the <netdb.h> header file. */
#define HAVE_NETDB_H 1
/* Define if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Define if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define if you have the <sys/fcntl.h> header file. */
#define HAVE_SYS_FCNTL_H 1
/* Define if you have the <sys/resource.h> header file. */
#define HAVE_SYS_RESOURCE_H 1
/* Define if you have the <sys/select.h> header file. */
#define HAVE_SYS_SELECT_H 1
/* Define if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define if you have the <sys/uio.h> header file. */
#define HAVE_SYS_UIO_H 1
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if you have the malloc library (-lmalloc). */
/* #undef HAVE_LIBMALLOC */
/* Check for a prototype to accept. */
/* #undef NEED_ACCEPT_PROTO */
#ifndef CIRCLE_MAC_OS
/* Check for a prototype to atoi. */
#define NEED_ATOI_PROTO
/* Check for a prototype to atol. */
#define NEED_ATOL_PROTO
#endif
/* Check for a prototype to bind. */
/* #undef NEED_BIND_PROTO */
/* Check for a prototype to bzero. */
/* #undef NEED_BZERO_PROTO */
/* Check for a prototype to chdir. */
/* #undef NEED_CHDIR_PROTO */
/* Check for a prototype to close. */
/* #undef NEED_CLOSE_PROTO */
/* Check for a prototype to crypt. */
/* #undef NEED_CRYPT_PROTO */
/* Check for a prototype to fclose. */
/* #undef NEED_FCLOSE_PROTO */
/* Check for a prototype to fcntl. */
/* #undef NEED_FCNTL_PROTO */
/* Check for a prototype to fflush. */
/* #undef NEED_FFLUSH_PROTO */
/* Check for a prototype to fprintf. */
/* #undef NEED_FPRINTF_PROTO */
/* Check for a prototype to fputc. */
/* #undef NEED_FPUTC_PROTO */
/* Check for a prototype to fputs. */
/* #undef NEED_FPUTS_PROTO */
/* Check for a prototype to fread. */
/* #undef NEED_FREAD_PROTO */
/* Check for a prototype to fscanf. */
/* #undef NEED_FSCANF_PROTO */
/* Check for a prototype to fseek. */
/* #undef NEED_FSEEK_PROTO */
/* Check for a prototype to fwrite. */
/* #undef NEED_FWRITE_PROTO */
/* Check for a prototype to getpeername. */
/* #undef NEED_GETPEERNAME_PROTO */
/* Check for a prototype to getpid. */
/* #undef NEED_GETPID_PROTO */
/* Check for a prototype to getrlimit. */
/* #undef NEED_GETRLIMIT_PROTO */
/* Check for a prototype to getsockname. */
/* #undef NEED_GETSOCKNAME_PROTO */
/* Check for a prototype to gettimeofday. */
/* #undef NEED_GETTIMEOFDAY_PROTO */
/* Check for a prototype to htonl. */
/* #undef NEED_HTONL_PROTO */
/* Check for a prototype to htons. */
/* #undef NEED_HTONS_PROTO */
/* Check for a prototype to inet_addr. */
/* #undef NEED_INET_ADDR_PROTO */
/* Check for a prototype to inet_aton. */
/* #undef NEED_INET_ATON_PROTO */
/* Check for a prototype to inet_ntoa. */
/* #undef NEED_INET_NTOA_PROTO */
/* Check for a prototype to listen. */
/* #undef NEED_LISTEN_PROTO */
/* Check for a prototype to ntohl. */
/* #undef NEED_NTOHL_PROTO */
/* Check for a prototype to perror. */
/* #undef NEED_PERROR_PROTO */
/* Check for a prototype to printf. */
/* #undef NEED_PRINTF_PROTO */
/* Check for a prototype to qsort. */
#ifndef CIRCLE_MAC_OS
#define NEED_QSORT_PROTO
#endif
/* Check for a prototype to read. */
/* #undef NEED_READ_PROTO */
/* Check for a prototype to remove. */
/* #undef NEED_REMOVE_PROTO */
/* Check for a prototype to rewind. */
/* #undef NEED_REWIND_PROTO */
/* Check for a prototype to select. */
/* #undef NEED_SELECT_PROTO */
/* Check for a prototype to setitimer. */
/* #undef NEED_SETITIMER_PROTO */
/* Check for a prototype to setrlimit. */
/* #undef NEED_SETRLIMIT_PROTO */
/* Check for a prototype to setsockopt. */
/* #undef NEED_SETSOCKOPT_PROTO */
/* Check for a prototype to snprintf. */
/* #undef NEED_SNPRINTF_PROTO */
/* Check for a prototype to socket. */
/* #undef NEED_SOCKET_PROTO */
/* Check for a prototype to sprintf. */
/* #undef NEED_SPRINTF_PROTO */
/* Check for a prototype to sscanf. */
/* #undef NEED_SSCANF_PROTO */
/* Check for a prototype to strcasecmp. */
/* #undef NEED_STRCASECMP_PROTO */
/* Check for a prototype to strdup. */
/* #undef NEED_STRDUP_PROTO */
/* Check for a prototype to strerror. */
/* #undef NEED_STRERROR_PROTO */
/* Check for a prototype to stricmp. */
#define NEED_STRICMP_PROTO
/* Check for a prototype to strlcpy. */
/* #undef NEED_STRLCPY_PROTO */
/* Check for a prototype to strncasecmp. */
/* #undef NEED_STRNCASECMP_PROTO */
/* Check for a prototype to strnicmp. */
#define NEED_STRNICMP_PROTO
/* Check for a prototype to system. */
#ifndef CIRCLE_MAC_OS
#define NEED_SYSTEM_PROTO
#endif
/* Check for a prototype to time. */
/* #undef NEED_TIME_PROTO */
/* Check for a prototype to unlink. */
/* #undef NEED_UNLINK_PROTO */
/* Check for a prototype to vsnprintf. */
/* #undef NEED_VSNPRINTF_PROTO */
/* Check for a prototype to write. */
/* #undef NEED_WRITE_PROTO */
#endif /* _CONF_H_ */

View file

@ -24,7 +24,7 @@
* @todo cpp_extern isn't needed here (or anywhere) as the extern reserved word * @todo cpp_extern isn't needed here (or anywhere) as the extern reserved word
* works correctly with C compilers (at least in my Experience) * works correctly with C compilers (at least in my Experience)
* Jeremy Osborne 1/28/2008 */ * Jeremy Osborne 1/28/2008 */
cpp_extern const char *tbamud_version = "tbaMUD 2023"; cpp_extern const char *tbamud_version = "tbaMUD 2025";
/* strings corresponding to ordinals/bitvectors in structs.h */ /* strings corresponding to ordinals/bitvectors in structs.h */
/* (Note: strings for class definitions in class.c instead of here) */ /* (Note: strings for class definitions in class.c instead of here) */
@ -877,6 +877,7 @@ const char *trig_types[] = {
"Door", "Door",
"UNUSED", "UNUSED",
"Time", "Time",
"Damage",
"\n" "\n"
}; };

View file

@ -1091,70 +1091,85 @@ int format_script(struct descriptor_data *d)
char nsc[MAX_CMD_LENGTH], *t, line[READ_SIZE]; char nsc[MAX_CMD_LENGTH], *t, line[READ_SIZE];
char *sc; char *sc;
size_t len = 0, nlen = 0, llen = 0; size_t len = 0, nlen = 0, llen = 0;
int indent = 0, indent_next = FALSE, found_case = FALSE, i, line_num = 0, ret; int indent = 0, indent_next = FALSE, line_num = 0, ret, i; // Declare i here
int block_stack[READ_SIZE]; // Stack to track block types
int stack_top = -1; // Initialize stack as empty
int switch_indent[READ_SIZE]; // Array to track switch indent levels
int switch_top = -1; // Index for switch_indent array
int case_indent = 0; // Track indent for case blocks
int in_switch = 0; // Flag to indicate if we're inside a switch block
if (!d->str || !*d->str) if (!d->str || !*d->str)
return FALSE; return FALSE;
sc = strdup(*d->str); /* we work on a copy, because of strtok() */ sc = strdup(*d->str); // Work on a copy
t = strtok(sc, "\n\r"); t = strtok(sc, "\n\r");
*nsc = '\0'; *nsc = '\0';
while (t) { while (t) {
line_num++; line_num++;
skip_spaces(&t); skip_spaces(&t);
if (!strn_cmp(t, "if ", 3) ||
!strn_cmp(t, "switch ", 7)) { if (!strn_cmp(t, "switch ", 7)) {
indent_next = TRUE; indent_next = TRUE;
} else if (!strn_cmp(t, "while ", 6)) { stack_top++;
found_case = TRUE; /* so you can 'break' a loop without complains */ block_stack[stack_top] = 's'; // 's' for switch
switch_top++;
switch_indent[switch_top] = indent; // Save current indent level for switch
in_switch++; // We're entering a switch block
} else if (!strn_cmp(t, "case", 4) || !strn_cmp(t, "default", 7)) {
if (in_switch > 0) { // If we're inside a switch
indent = switch_indent[switch_top] + 1; // Indent cases one level under switch
indent_next = TRUE; // Indent the next line after case
case_indent = indent; // Save indent for case block
}
} else if (!strn_cmp(t, "if ", 3) || !strn_cmp(t, "while ", 6)) {
indent_next = TRUE; indent_next = TRUE;
} else if (!strn_cmp(t, "end", 3) || stack_top++;
!strn_cmp(t, "done", 4)) { block_stack[stack_top] = 'l'; // 'l' for loop or conditional
if (!indent) { } else if (!strn_cmp(t, "end", 3) || !strn_cmp(t, "done", 4)) {
if (stack_top < 0) {
write_to_output(d, "Unmatched 'end' or 'done' (line %d)!\r\n", line_num); write_to_output(d, "Unmatched 'end' or 'done' (line %d)!\r\n", line_num);
free(sc); free(sc);
return FALSE; return FALSE;
} }
indent--; if (block_stack[stack_top] == 's') {
indent_next = FALSE; indent = switch_indent[switch_top]; // Reset to the exact indent level where switch was declared
switch_top--; // Decrease switch stack if ending a switch
case_indent = 0; // Reset case indent since we're leaving the switch
in_switch--; // We're leaving a switch block
} else {
indent--; // For other blocks like while
}
stack_top--;
indent_next = FALSE; // Reset for next line
} else if (!strn_cmp(t, "else", 4)) { } else if (!strn_cmp(t, "else", 4)) {
if (!indent) { if (stack_top < 0 || block_stack[stack_top] != 'l') {
write_to_output(d, "Unmatched 'else' (line %d)!\r\n", line_num); write_to_output(d, "Unmatched 'else' (line %d)!\r\n", line_num);
free(sc); free(sc);
return FALSE; return FALSE;
} }
indent--; indent--; // Reduce indent for else, then increment for next statement
indent_next = TRUE; indent_next = TRUE;
} else if (!strn_cmp(t, "case", 4) ||
!strn_cmp(t, "default", 7)) {
if (!indent) {
write_to_output(d, "Case/default outside switch (line %d)!\r\n", line_num);
free(sc);
return FALSE;
}
if (!found_case) /* so we don't indent multiple case statements without a break */
indent_next = TRUE;
found_case = TRUE;
} else if (!strn_cmp(t, "break", 5)) { } else if (!strn_cmp(t, "break", 5)) {
if (!found_case || !indent ) { if (stack_top < 0 || (block_stack[stack_top] != 's' && block_stack[stack_top] != 'l')) {
write_to_output(d, "Break not in case (line %d)!\r\n", line_num); write_to_output(d, "Break not in case or loop (line %d)!\r\n", line_num);
free(sc); free(sc);
return FALSE; return FALSE;
} }
found_case = FALSE; indent = case_indent + 1; // Indent break one level deeper than case
indent--; indent_next = FALSE; // Ensure no automatic increase for next line after break
} }
*line = '\0'; *line = '\0';
for (nlen = 0, i = 0;i<indent;i++) { for (nlen = 0, i = 0; i < indent; i++) {
strncat(line, " ", sizeof(line) - strlen(line) - 1); strncat(line, " ", sizeof(line) - strlen(line) - 1);
nlen += 2; nlen += 2;
} }
ret = snprintf(line + nlen, sizeof(line) - nlen, "%s\r\n", t); ret = snprintf(line + nlen, sizeof(line) - nlen, "%s\r\n", t);
llen = (size_t)ret; llen = (size_t)ret;
if (ret < 0 || llen + nlen + len > d->max_str - 1 ) { if (ret < 0 || llen + nlen + len > d->max_str - 1) {
write_to_output(d, "String too long, formatting aborted\r\n"); write_to_output(d, "String too long, formatting aborted\r\n");
free(sc); free(sc);
return FALSE; return FALSE;
@ -1169,8 +1184,8 @@ int format_script(struct descriptor_data *d)
t = strtok(NULL, "\n\r"); t = strtok(NULL, "\n\r");
} }
if (indent) if (stack_top >= 0)
write_to_output(d, "Unmatched if, while or switch ignored.\r\n"); write_to_output(d, "Unmatched block statements ignored.\r\n");
free(*d->str); free(*d->str);
*d->str = strdup(nsc); *d->str = strdup(nsc);

View file

@ -16,7 +16,7 @@
#include "dg_scripts.h" #include "dg_scripts.h"
#define NUM_TRIG_TYPE_FLAGS 20 #define NUM_TRIG_TYPE_FLAGS 21
/* Submodes of TRIGEDIT connectedness. */ /* Submodes of TRIGEDIT connectedness. */
#define TRIGEDIT_MAIN_MENU 0 #define TRIGEDIT_MAIN_MENU 0

View file

@ -2486,7 +2486,6 @@ int script_driver(void *go_adress, trig_data *trig, int type, int mode)
char cmd[MAX_INPUT_LENGTH], *p; char cmd[MAX_INPUT_LENGTH], *p;
struct script_data *sc = 0; struct script_data *sc = 0;
struct cmdlist_element *temp; struct cmdlist_element *temp;
unsigned long loops = 0;
void *go = NULL; void *go = NULL;
void obj_command_interpreter(obj_data *obj, char *argument); void obj_command_interpreter(obj_data *obj, char *argument);
@ -2578,8 +2577,8 @@ int script_driver(void *go_adress, trig_data *trig, int type, int mode)
if (process_if(p + 6, go, sc, trig, type)) { if (process_if(p + 6, go, sc, trig, type)) {
temp->original = cl; temp->original = cl;
} else { } else {
cl->loops = 0;
cl = temp; cl = temp;
loops = 0;
} }
} else if (!strn_cmp("switch ", p, 7)) { } else if (!strn_cmp("switch ", p, 7)) {
cl = find_case(trig, cl, go, sc, type, p + 7); cl = find_case(trig, cl, go, sc, type, p + 7);
@ -2599,9 +2598,10 @@ int script_driver(void *go_adress, trig_data *trig, int type, int mode)
if (cl->original && process_if(orig_cmd + 6, go, sc, trig, if (cl->original && process_if(orig_cmd + 6, go, sc, trig,
type)) { type)) {
cl = cl->original; cl = cl->original;
loops++; cl->loops++;
GET_TRIG_LOOPS(trig)++; GET_TRIG_LOOPS(trig)++;
if (loops == 30) { if (cl->loops == 30) {
cl->loops = 0;
process_wait(go, trig, type, "wait 1", cl); process_wait(go, trig, type, "wait 1", cl);
depth--; depth--;
return ret_val; return ret_val;

View file

@ -71,6 +71,7 @@
#define MTRIG_DOOR (1 << 17) /* door manipulated in room */ #define MTRIG_DOOR (1 << 17) /* door manipulated in room */
#define MTRIG_TIME (1 << 19) /* trigger based on game hour */ #define MTRIG_TIME (1 << 19) /* trigger based on game hour */
#define MTRIG_DAMAGE (1 << 20) /* trigger whenever mob is damaged */
/* obj trigger types */ /* obj trigger types */
#define OTRIG_GLOBAL (1 << 0) /* unused */ #define OTRIG_GLOBAL (1 << 0) /* unused */
@ -135,6 +136,7 @@ struct cmdlist_element {
char *cmd; /* one line of a trigger */ char *cmd; /* one line of a trigger */
struct cmdlist_element *original; struct cmdlist_element *original;
struct cmdlist_element *next; struct cmdlist_element *next;
int loops; /* for counting number of runs in a while loop */
}; };
struct trig_var_data { struct trig_var_data {
@ -263,6 +265,7 @@ void time_wtrigger(room_data *room);
int login_wtrigger(struct room_data *room, char_data *actor); int login_wtrigger(struct room_data *room, char_data *actor);
int damage_mtrigger(char_data *ch, char_data *victim, int dam, int attacktype);
/* function prototypes from dg_scripts.c */ /* function prototypes from dg_scripts.c */
ACMD(do_attach) ; ACMD(do_attach) ;
ACMD(do_detach); ACMD(do_detach);

View file

@ -554,6 +554,33 @@ int cast_mtrigger(char_data *actor, char_data *ch, int spellnum)
return 1; return 1;
} }
int damage_mtrigger(char_data *actor, char_data *victim, int dam, int attacktype)
{
trig_data *t;
char buf[MAX_INPUT_LENGTH];
if (victim == NULL)
return dam;
if (!SCRIPT_CHECK(victim, MTRIG_DAMAGE) || AFF_FLAGGED(victim, AFF_CHARM))
return dam;
for (t = TRIGGERS(SCRIPT(victim)); t; t = t->next) {
if (TRIGGER_CHECK(t, MTRIG_DAMAGE) &&
(rand_number(1, 100) <= GET_TRIG_NARG(t))) {
ADD_UID_VAR(buf, t, char_script_id(actor), "actor", 0);
ADD_UID_VAR(buf, t, char_script_id(victim), "victim", 0);
sprintf(buf, "%d", dam);
add_var(&GET_TRIG_VARS(t), "damage", buf, 0);
add_var(&GET_TRIG_VARS(t), "attacktype", skill_name(attacktype), 0);
return script_driver(&victim, t, MOB_TRIGGER, TRIG_NEW);
}
}
return dam;
}
int leave_mtrigger(char_data *actor, int dir) int leave_mtrigger(char_data *actor, int dir)
{ {
trig_data *t; trig_data *t;

View file

@ -620,6 +620,11 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
if (!IS_NPC(victim) && ((GET_LEVEL(victim) >= LVL_IMMORT) && PRF_FLAGGED(victim, PRF_NOHASSLE))) if (!IS_NPC(victim) && ((GET_LEVEL(victim) >= LVL_IMMORT) && PRF_FLAGGED(victim, PRF_NOHASSLE)))
dam = 0; dam = 0;
dam = damage_mtrigger(ch, victim, dam, attacktype);
if (dam == -1) {
return (0);
}
if (victim != ch) { if (victim != ch) {
/* Start the attacker fighting the victim */ /* Start the attacker fighting the victim */
if (GET_POS(ch) > POS_STUNNED && (FIGHTING(ch) == NULL)) if (GET_POS(ch) > POS_STUNNED && (FIGHTING(ch) == NULL))

View file

@ -146,7 +146,8 @@ static void prefedit_disp_main_menu(struct descriptor_data *d)
"%sImmortal Preferences\r\n" "%sImmortal Preferences\r\n"
"%s1%s) Syslog Level %s[%s%8s%s] %s4%s) ClsOLC %s[%s%3s%s]\r\n" "%s1%s) Syslog Level %s[%s%8s%s] %s4%s) ClsOLC %s[%s%3s%s]\r\n"
"%s2%s) Show Flags %s[%s%3s%s] %s5%s) No WizNet %s[%s%3s%s]\r\n" "%s2%s) Show Flags %s[%s%3s%s] %s5%s) No WizNet %s[%s%3s%s]\r\n"
"%s3%s) No Hassle %s[%s%3s%s] %s6%s) Holylight %s[%s%3s%s]\r\n", "%s3%s) No Hassle %s[%s%3s%s] %s6%s) Holylight %s[%s%3s%s]\r\n"
"%s7%s) Verbose %s[%s%3s%s] ",
CBWHT(d->character, C_NRM), CBWHT(d->character, C_NRM),
/* Line 1 - syslog and clsolc */ /* Line 1 - syslog and clsolc */
CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM), CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM),
@ -159,12 +160,17 @@ static void prefedit_disp_main_menu(struct descriptor_data *d)
/* Line 3 - nohassle and holylight */ /* Line 3 - nohassle and holylight */
CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM), CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM),
ONOFF(PREFEDIT_FLAGGED(PRF_NOHASSLE)), CCCYN(d->character, C_NRM), CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), ONOFF(PREFEDIT_FLAGGED(PRF_NOHASSLE)), CCCYN(d->character, C_NRM), CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM),
CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM), ONOFF(PREFEDIT_FLAGGED(PRF_HOLYLIGHT)), CCCYN(d->character, C_NRM) CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM), ONOFF(PREFEDIT_FLAGGED(PRF_HOLYLIGHT)), CCCYN(d->character, C_NRM),
/* Line 4 - Verbose */
CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM),
ONOFF(PREFEDIT_FLAGGED(PRF_VERBOSE)), CCCYN(d->character, C_NRM)
); );
if (GET_LEVEL(PREFEDIT_GET_CHAR) == LVL_IMPL) if (GET_LEVEL(PREFEDIT_GET_CHAR) == LVL_IMPL)
send_to_char(d->character, "%s7%s) Zone Resets %s[%s%3s%s]\r\n", send_to_char(d->character, "%s8%s) Zone Resets %s[%s%3s%s]\r\n",
CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM), CBYEL(d->character, C_NRM), CCNRM(d->character, C_NRM), CCCYN(d->character, C_NRM), CCYEL(d->character, C_NRM),
ONOFF(PREFEDIT_FLAGGED(PRF_ZONERESETS)), CCCYN(d->character, C_NRM)); ONOFF(PREFEDIT_FLAGGED(PRF_ZONERESETS)), CCCYN(d->character, C_NRM));
else
send_to_char(d->character, "\r\n");
} }
/* Finishing Off */ /* Finishing Off */
@ -505,7 +511,19 @@ void prefedit_parse(struct descriptor_data * d, char *arg)
} }
break; break;
case '7': case '7':
if (GET_LEVEL(PREFEDIT_GET_CHAR) < LVL_IMMORT)
{
send_to_char(d->character, "%sInvalid choice!%s\r\n", CBRED(d->character, C_NRM), CCNRM(d->character, C_NRM));
prefedit_disp_main_menu(d);
}
else
{
TOGGLE_BIT_AR(PREFEDIT_GET_FLAGS, PRF_VERBOSE);
}
break;
case '8':
if (GET_LEVEL(PREFEDIT_GET_CHAR) < LVL_IMPL) if (GET_LEVEL(PREFEDIT_GET_CHAR) < LVL_IMPL)
{ {
send_to_char(d->character, "%sInvalid choice!%s\r\n", CBRED(d->character, C_NRM), CCNRM(d->character, C_NRM)); send_to_char(d->character, "%sInvalid choice!%s\r\n", CBRED(d->character, C_NRM), CCNRM(d->character, C_NRM));
@ -901,6 +919,10 @@ void prefedit_Restore_Defaults(struct descriptor_data *d)
if (PREFEDIT_FLAGGED(PRF_AUTODOOR)) if (PREFEDIT_FLAGGED(PRF_AUTODOOR))
SET_BIT_AR(PREFEDIT_GET_FLAGS, PRF_AUTODOOR); SET_BIT_AR(PREFEDIT_GET_FLAGS, PRF_AUTODOOR);
/* PRF_VERBOSE - On */
if (PREFEDIT_FLAGGED(PRF_VERBOSE))
SET_BIT_AR(PREFEDIT_GET_FLAGS, PRF_VERBOSE);
/* Other (non-toggle) options */ /* Other (non-toggle) options */
PREFEDIT_GET_WIMP_LEV = 0; /* Wimpy off by default */ PREFEDIT_GET_WIMP_LEV = 0; /* Wimpy off by default */
PREFEDIT_GET_PAGELENGTH = 22; /* Default telnet screen is 22 lines */ PREFEDIT_GET_PAGELENGTH = 22; /* Default telnet screen is 22 lines */

View file

@ -1768,7 +1768,26 @@ static void PerformSubnegotiation( descriptor_t *apDescriptor, char aCmd, char *
Write(apDescriptor, RequestTTYPE); Write(apDescriptor, RequestTTYPE);
} }
if ( PrefixString("Mudlet", pClientName) ) if ( PrefixString("MTTS ", pClientName) )
{
pProtocol->pVariables[eMSDP_CLIENT_VERSION]->ValueInt = atoi(pClientName+5);
if (pProtocol->pVariables[eMSDP_CLIENT_VERSION]->ValueInt & 1)
{
pProtocol->pVariables[eMSDP_ANSI_COLORS]->ValueInt = 1;
}
if (pProtocol->pVariables[eMSDP_CLIENT_VERSION]->ValueInt & 4)
{
pProtocol->pVariables[eMSDP_UTF_8]->ValueInt = 1;
}
if (pProtocol->pVariables[eMSDP_CLIENT_VERSION]->ValueInt & 8)
{
pProtocol->pVariables[eMSDP_XTERM_256_COLORS]->ValueInt = 1;
pProtocol->b256Support = eYES;
}
}
else if ( PrefixString("Mudlet", pClientName) )
{ {
/* Mudlet beta 15 and later supports 256 colours, but we can't /* Mudlet beta 15 and later supports 256 colours, but we can't
* identify it from the mud - everything prior to 1.1 claims * identify it from the mud - everything prior to 1.1 claims

View file

@ -262,9 +262,10 @@
#define PRF_AUTOMAP 31 /**< Show map at the side of room descs */ #define PRF_AUTOMAP 31 /**< Show map at the side of room descs */
#define PRF_AUTOKEY 32 /**< Automatically unlock locked doors when opening */ #define PRF_AUTOKEY 32 /**< Automatically unlock locked doors when opening */
#define PRF_AUTODOOR 33 /**< Use the next available door */ #define PRF_AUTODOOR 33 /**< Use the next available door */
#define PRF_ZONERESETS 34 #define PRF_ZONERESETS 34 /**< Show when zones reset */
#define PRF_VERBOSE 35 /**< Listings like where are more verbose */
/** Total number of available PRF flags */ /** Total number of available PRF flags */
#define NUM_PRF_FLAGS 35 #define NUM_PRF_FLAGS 36
/* Affect bits: used in char_data.char_specials.saved.affected_by */ /* Affect bits: used in char_data.char_specials.saved.affected_by */
/* WARNING: In the world files, NEVER set the bits marked "R" ("Reserved") */ /* WARNING: In the world files, NEVER set the bits marked "R" ("Reserved") */

View file

@ -63,6 +63,24 @@
/* Do not change anything below this line. */ /* Do not change anything below this line. */
#if defined(__APPLE__) && defined(__MACH__)
/* Machine-specific dependencies for running on modern macOS systems 10.13+ (High Sierra)
* Updated by Victor Augusto Borges Dias de Almeida (aka Stoneheart), 26 June 2024.
*
* Tested on:
* - macOS 10.13: High Sierra (Lobo) - September 25, 2017 (Latest: 10.13.6)
* - macOS 10.14: Mojave (Liberty) - September 24, 2018 (Latest: 10.14.6)
* - macOS 10.15: Catalina (Jazz) - October 7, 2019 (Latest: 10.15.7)
* - macOS 11: Big Sur (GoldenGate) - November 12, 2020 (Latest: 11.7.10)
* - macOS 12: Monterey (Star) - October 25, 2021 (Latest: 12.7)
* - macOS 13: Ventura (Rome) - November 7, 2022 (Latest: 13.7)
* - macOS 14: Sonoma (Sunburst) - November 7, 2023 (Latest: 14.3)
*
* This file works on Apple Silicon Chips (M1, M2, M3) without futher configurations.
*/
#define CIRCLE_MAC_OS 1
#endif
/* Set up various machine-specific things based on the values determined from /* Set up various machine-specific things based on the values determined from
* configure and conf.h. */ * configure and conf.h. */
@ -78,7 +96,7 @@
#include <strings.h> #include <strings.h>
#endif #endif
#if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)) #if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) || defined(CIRCLE_MAC_OS))
#include <stdlib.h> #include <stdlib.h>
#else /* No standard headers. */ #else /* No standard headers. */
@ -88,9 +106,8 @@
#endif #endif
extern char *malloc(), *calloc(), *realloc(); extern char *malloc(), *calloc(), *realloc();
extern void free (); extern void free();
extern void abort(), exit();
extern void abort (), exit ();
#endif /* Standard headers. */ #endif /* Standard headers. */
@ -150,9 +167,11 @@ extern void abort (), exit ();
#include <sys/errno.h> #include <sys/errno.h>
#endif #endif
#ifndef CIRCLE_MAC_OS
#ifdef HAVE_CRYPT_H #ifdef HAVE_CRYPT_H
#include <crypt.h> #include <crypt.h>
#endif #endif
#endif
#ifdef TIME_WITH_SYS_TIME #ifdef TIME_WITH_SYS_TIME
# include <sys/time.h> # include <sys/time.h>
@ -434,9 +453,11 @@ struct in_addr {
char *strerror(int errnum); char *strerror(int errnum);
#endif #endif
#ifndef CIRCLE_MAC_OS
#ifdef NEED_STRLCPY_PROTO #ifdef NEED_STRLCPY_PROTO
size_t strlcpy(char *dest, const char *src, size_t copylen); size_t strlcpy(char *dest, const char *src, size_t copylen);
#endif #endif
#endif
#ifdef NEED_SYSTEM_PROTO #ifdef NEED_SYSTEM_PROTO
int system(const char *string); int system(const char *string);

46
src/util/CMakeLists.txt Normal file
View file

@ -0,0 +1,46 @@
set(TOOLS
asciipasswd
autowiz
plrtoascii
rebuildIndex
rebuildMailIndex
shopconv
sign
split
wld2html
webster
)
# common includes and flags
include_directories(${CMAKE_SOURCE_DIR}/src)
add_definitions(-DCIRCLE_UTIL)
find_library(CRYPT_LIBRARY crypt)
find_library(NETLIB_LIBRARY nsl socket) # for sign.c, hvis nødvendig
foreach(tool ${TOOLS})
if(${tool} STREQUAL "rebuildIndex")
add_executable(rebuildIndex rebuildAsciiIndex.c)
else()
add_executable(${tool} ${tool}.c)
endif()
# Set output location
set_target_properties(${tool} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin
)
# Link to libcrypt for asciipasswd
if(${tool} STREQUAL "asciipasswd" AND CRYPT_LIBRARY)
target_link_libraries(${tool} ${CRYPT_LIBRARY})
endif()
# Link to netlib for sign
if(${tool} STREQUAL "sign" AND NETLIB_LIBRARY)
target_link_libraries(${tool} ${NETLIB_LIBRARY})
endif()
endforeach()
add_custom_target(utils DEPENDS ${TOOLS})

View file

@ -23,7 +23,7 @@ CFLAGS = @CFLAGS@ $(MYFLAGS) $(PROFILE) -I$(INCDIR)
default: all default: all
all: $(BINDIR)/asciipasswd $(BINDIR)/autowiz $(BINDIR)/plrtoascii $(BINDIR)/rebuildIndex $(BINDIR)/rebuildMailIndex $(BINDIR)/shopconv $(BINDIR)/sign $(BINDIR)/split $(BINDIR)/wld2html $(BINDIR)/webster all: $(BINDIR)/asciipasswd $(BINDIR)/autowiz $(BINDIR)/plrtoascii $(BINDIR)/rebuildIndex $(BINDIR)/rebuildMailIndex $(BINDIR)/shopconv $(BINDIR)/sign $(BINDIR)/split $(BINDIR)/wld2html
asciipasswd: $(BINDIR)/asciipasswd asciipasswd: $(BINDIR)/asciipasswd
@ -43,8 +43,6 @@ split: $(BINDIR)/split
wld2html: $(BINDIR)/wld2html wld2html: $(BINDIR)/wld2html
webster: $(BINDIR)/webster
$(BINDIR)/asciipasswd: asciipasswd.c $(BINDIR)/asciipasswd: asciipasswd.c
$(CC) $(CFLAGS) -o $(BINDIR)/asciipasswd asciipasswd.c @CRYPTLIB@ $(CC) $(CFLAGS) -o $(BINDIR)/asciipasswd asciipasswd.c @CRYPTLIB@
@ -72,9 +70,6 @@ $(BINDIR)/split: split.c
$(BINDIR)/wld2html: wld2html.c $(BINDIR)/wld2html: wld2html.c
$(CC) $(CFLAGS) -o $(BINDIR)/wld2html wld2html.c $(CC) $(CFLAGS) -o $(BINDIR)/wld2html wld2html.c
$(BINDIR)/webster: webster.c
$(CC) $(CFLAGS) -o $(BINDIR)/webster webster.c
# Dependencies for the object files (automagically generated with # Dependencies for the object files (automagically generated with
# gcc -MM) # gcc -MM)

View file

@ -85,7 +85,7 @@ void read_file(void)
while (get_line(fl, line)) while (get_line(fl, line))
if (*line != '~') if (*line != '~')
recs++; recs++;
rewind(fl); rewind(fl);
for (i = 0; i < recs; i++) { for (i = 0; i < recs; i++) {
get_line(fl, line); get_line(fl, line);

View file

@ -155,7 +155,7 @@ static int boot_the_shops_conv(FILE * shop_f, FILE * newshop_f, char *filename)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
FILE *sfp, *nsfp; FILE *sfp, *nsfp;
char fn[256], part[256]; char fn[120], part[256];
int result, index, i; int result, index, i;
if (argc < 2) { if (argc < 2) {
@ -173,20 +173,20 @@ int main(int argc, char *argv[])
perror(fn); perror(fn);
} else { } else {
if ((nsfp = fopen(fn, "w")) == NULL) { if ((nsfp = fopen(fn, "w")) == NULL) {
printf("Error writing to %s.\n", fn); printf("Error writing to %s.\n", fn);
continue; continue;
} }
printf("%s:\n", fn); printf("%s:\n", fn);
result = boot_the_shops_conv(sfp, nsfp, fn); result = boot_the_shops_conv(sfp, nsfp, fn);
fclose(nsfp); fclose(nsfp);
fclose(sfp); fclose(sfp);
if (result) { if (result) {
sprintf(part, "mv %s.tmp %s", fn, fn); sprintf(part, "mv %s.tmp %s", fn, fn);
i = system(part); i = system(part);
} else { } else {
sprintf(part, "mv %s.tmp %s.bak", fn, fn); sprintf(part, "mv %s.tmp %s.bak", fn, fn);
i = system(part); i = system(part);
printf("Done!\n"); printf("Done!\n");
} }
} }
} }

View file

@ -1,175 +0,0 @@
/* ************************************************************************
* File: webster.c Part of tbaMUD *
* Usage: Use an online dictionary via tell m-w <word>. *
* *
* Based on the Circle 3.0 syntax checker and wld2html programs. *
************************************************************************ */
#define log(msg) fprintf(stderr, "%s\n", msg)
#include "conf.h"
#include "sysdep.h"
#define MEM_USE 10000
char buf[MEM_USE];
int get_line(FILE * fl, char *buf);
void skip_spaces(char **string);
void parse_webster_html(char *arg);
int main(int argc, char **argv)
{
int pid = 0;
if (argc != 3) {
return 0; /* no word/pid given */
}
pid = atoi(argv[2]);
snprintf(buf, sizeof(buf),
"lynx -accept_all_cookies -source http://www.thefreedictionary.com/%s"
" >webster.html", argv[1]);
system(buf);
parse_webster_html(argv[1]);
if (pid)
kill(pid, SIGUSR2);
return (0);
}
void parse_webster_html(char *arg) {
FILE *infile, *outfile;
char scanbuf[MEM_USE], outline[MEM_USE], *p, *q;
outfile = fopen("websterinfo", "w");
if (!outfile)
exit(1);
infile = fopen("webster.html", "r");
if (!infile) {
fprintf(outfile, "A bug has occured in webster. (no webster.html) Please notify Welcor.");
fclose(outfile);
return;
}
unlink("webster.html"); /* We can still read */
for ( ; get_line(infile, buf)!=0; ) {
if (strncmp(buf, "<script>write_ads(AdsNum, 0, 1)</script>", 40) != 0)
continue; // read until we hit the line with results in it.
p = buf+40;
if (strncmp(p, "<br>", 4) == 0)
{
fprintf(outfile, "That word could not be found.\n");
goto end;
}
else if (strncmp(p, "<div ", 5) == 0) // definition is here, all in one line.
{
while (strncmp(p, "ds-list", 7)) //seek to the definition
p++;
strncpy(scanbuf, p, sizeof(scanbuf)); // strtok on a copy.
p = strtok(scanbuf, ">"); // chop the line at the end of tags: <br><b>word</b> becomes "<br" "<b" "word</b"
p = strtok(NULL, ">"); // skip the rest of this tag.
fprintf(outfile, "Info on: %s\n\n", arg);
while (1)
{
q = outline;
while (*p != '<')
{
assert(p < scanbuf+sizeof(scanbuf));
*q++ = *p++;
}
if (!strncmp(p, "<br", 3) || !strncmp(p, "<p", 2) || !strncmp(p, "<div class=\"ds-list\"", 23) || !strncmp(p, "<div class=\"sds-list\"", 24))
*q++ = '\n';
// if it's not a <br> tag or a <div class="sds-list"> or <div class="ds-list"> tag, ignore it.
*q++='\0';
fprintf(outfile, "%s", outline);
if (!strncmp(p, "</table", 7))
goto end;
p = strtok(NULL, ">");
}
}
else if (strncmp(p, "<div>", 5) == 0) // not found, but suggestions are ample:
{
strncpy(scanbuf, p, sizeof(scanbuf)); // strtok on a copy.
p = strtok(scanbuf, ">"); // chop the line at the end of tags: <br><b>word</b> becomes "<br>" "<b>" "word</b>"
p = strtok(NULL, ">"); // skip the rest of this tag.
while (1)
{
q = outline;
while (*p != '<')
*q++ = *p++;
if (!strncmp(p, "<td ", 4))
*q++ = '\n';
// if it's not a <td> tag, ignore it.
*q++='\0';
fprintf(outfile, "%s", outline);
if (!strncmp(p, "</table", 7))
goto end;
p = strtok(NULL, ">");
}
}
else
{
// weird.. one of the above should be correct.
fprintf(outfile, "It would appear that the free online dictionary has changed their format.\n"
"Sorry, but you might need a webrowser instead.\n\n"
"See http://www.thefreedictionary.com/%s", arg);
goto end;
}
}
end:
fclose(infile);
fprintf(outfile, "~");
fclose(outfile);
}
/* get_line reads the next non-blank line off of the input stream.
* The newline character is removed from the input.
*/
int get_line(FILE * fl, char *buf)
{
char temp[MEM_USE];
do {
fgets(temp, MEM_USE, fl);
if (*temp)
temp[strlen(temp) - 1] = '\0';
} while (!feof(fl) && !*temp);
if (feof(fl))
return (0);
else {
strcpy(buf, temp);
return (1);
}
}
/*
* Function to skip over the leading spaces of a string.
*/
void skip_spaces(char **string)
{
for (; **string && isspace(**string); (*string)++);
}