├── win32 ├── defines.h ├── pcre.lib ├── win32.c ├── win32.h ├── README.TXT └── autoconf.h ├── game ├── muf │ └── README ├── data │ ├── motd.txt │ ├── README │ ├── news.txt │ ├── connect-help.txt │ ├── edit-help.txt │ ├── welcome.txt │ └── credits.txt ├── logs │ └── README └── restart.in ├── include ├── .indent.pro ├── fbsignal.h ├── events.h ├── color.h ├── mcppkg.h ├── debugger.h ├── p_regex.h ├── autoconf.h.in ├── hashtab.h ├── look.h ├── p_mcp.h ├── diskprop.h ├── log.h ├── compile.h ├── move.h └── inst.h ├── auto ├── requirements.txt └── build-demo.py ├── .env ├── dbs ├── starterdb │ ├── muf │ │ ├── macros │ │ ├── 27.m │ │ ├── 29.m │ │ ├── 50.m │ │ ├── 28.m │ │ ├── 64.m │ │ ├── 54.m │ │ ├── 118.m │ │ ├── 3.m │ │ ├── 8.m │ │ ├── 73.m │ │ ├── 103.m │ │ ├── 85.m │ │ ├── 81.m │ │ ├── 32.m │ │ ├── 71.m │ │ ├── 30.m │ │ ├── 77.m │ │ ├── 83.m │ │ ├── 58.m │ │ ├── 87.m │ │ ├── 6.m │ │ ├── 21.m │ │ ├── 79.m │ │ ├── 10.m │ │ ├── 9.m │ │ ├── 91.m │ │ ├── 14.m │ │ ├── 34.m │ │ ├── 66.m │ │ ├── 60.m │ │ └── 52.m │ └── README └── minimal │ └── README ├── tests ├── command-cases │ ├── player.yml │ ├── p_misc.yml │ ├── move.yml │ ├── p_mcp.yml │ ├── p_array.yml │ ├── create.yml │ ├── p_regex.yml │ ├── look.yml │ ├── set.yml │ ├── p_math.yml │ └── p_stack.yml └── test_command.py ├── conanfile.txt ├── docker-compose.yml ├── .gitignore ├── docs └── index.html ├── scripts ├── trigger-dump.py ├── trigger-dump.muf ├── teledump-extract.py ├── fbmuck-add └── docker-entrypoint.sh ├── Dockerfile ├── Makefile.in ├── .github └── workflows │ └── main.yml ├── README_WINDOWS.md ├── README_UNIX.md ├── README.md └── src └── pennies.c /win32/defines.h: -------------------------------------------------------------------------------- 1 | #define BINDIR "." 2 | -------------------------------------------------------------------------------- /game/muf/README: -------------------------------------------------------------------------------- 1 | muf files will go here... 2 | -------------------------------------------------------------------------------- /include/.indent.pro: -------------------------------------------------------------------------------- 1 | -kr -psl -ci8 -l95 -lc75 -npcs -ss 2 | -------------------------------------------------------------------------------- /auto/requirements.txt: -------------------------------------------------------------------------------- 1 | git+https://github.com/tanabi/pyfuzzball.git 2 | 3 | -------------------------------------------------------------------------------- /win32/pcre.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzball-muck/fuzzball/HEAD/win32/pcre.lib -------------------------------------------------------------------------------- /game/data/motd.txt: -------------------------------------------------------------------------------- 1 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | FB_PORT=4201 2 | FB_SSL_PORT=4202 3 | FB_DATA_PATH=./fb-data 4 | FB_CERT_PATH=./fb-cert 5 | FB_USE_SSL=1 6 | FB_SELF_SIGN=1 7 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/macros: -------------------------------------------------------------------------------- 1 | no? 2 | "{0|n*}" smatch 3 | 1 4 | showhelp 5 | prog "_help" array_get_proplist me @ 1 array_make array_notify 6 | 1 7 | yes? 8 | "{1|y*}" smatch 9 | 1 10 | -------------------------------------------------------------------------------- /game/data/README: -------------------------------------------------------------------------------- 1 | This is where all online help documents and database files should 2 | normally go. If your database is to go elsewhere, please change 3 | the 'restart' script for your site. 4 | -------------------------------------------------------------------------------- /game/logs/README: -------------------------------------------------------------------------------- 1 | The normal netmuck program will use this directory to create four 2 | log files: status, commands, muf-errors, and gripes. commands is 3 | only used with the LOG_COMMANDS compiler option. 4 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/27.m: -------------------------------------------------------------------------------- 1 | ( con-bootme.muf by Aerowolf@HLM and Natasha@HLM ) 2 | : main 3 | "me" match awake? 1 > if 4 | 0 sleep 5 | "You have more than one connection. Type @bootme to drop the old ones." tell 6 | then 7 | ; 8 | -------------------------------------------------------------------------------- /game/data/news.txt: -------------------------------------------------------------------------------- 1 | General News 2 | ================================================================ 3 | 4 | Your general news info goes here. 5 | 6 | ================================================================ 7 | -------------------------------------------------------------------------------- /game/data/connect-help.txt: -------------------------------------------------------------------------------- 1 | connect - connect to your character 2 | create - create a character, if available 3 | help - this help message 4 | WHO - list visible players 5 | -------------------------------------------------------------------------------- /dbs/minimal/README: -------------------------------------------------------------------------------- 1 | * The database contains one player, named One. You should change One's 2 | password immediately: 3 | 4 | connect #1 potrzebie 5 | @password potrzebie= 6 | 7 | Only One can perform some functions like setting and removing players' 8 | Wizard flags. Keep its password safe! 9 | -------------------------------------------------------------------------------- /tests/command-cases/player.yml: -------------------------------------------------------------------------------- 1 | - name: pcreate 2 | setup: | 3 | @pcreate testplayer=testpassword 4 | commands: | 5 | ex *testplayer 6 | expect: 7 | - "testplayer\\(#2" 8 | - "Type: PLAYER" 9 | 10 | - name: pcreate-no-oldrefs 11 | setup: | 12 | @create IdTwo 13 | @recycle #2 14 | @pcreate testplayer=testpassword 15 | commands: | 16 | ex *testplayer 17 | expect: 18 | - "testplayer\\(#3" 19 | -------------------------------------------------------------------------------- /tests/test_command.py: -------------------------------------------------------------------------------- 1 | import os 2 | import test_util 3 | import unittest 4 | 5 | for name in os.listdir('command-cases'): 6 | if name.endswith('yml'): 7 | class_name = name.replace('.yml', '') 8 | base_class = globals()[class_name] = type(class_name, (test_util.CommandTestCase,), {}) 9 | test_util.create_command_tests_for(base_class, os.path.join('command-cases', name)) 10 | 11 | if __name__ == '__main__': 12 | unittest.main() 13 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/29.m: -------------------------------------------------------------------------------- 1 | ( con-recordhost 1.0 records the last host you connected from ) 2 | $def DISPLAY_MESG "## You last connected from %n" 3 | 4 | : recordhost 5 | me @ "@/host" getpropstr 6 | $ifdef DISPLAY_MESG 7 | dup if DISPLAY_MESG over "%n" subst tell then 8 | $endif 9 | me @ "@/lasthost" rot 0 addprop 10 | me @ descriptors 11 | begin 12 | dup 1 > while 13 | rot pop 1 - 14 | repeat 15 | pop descrhost 16 | me @ "@/host" rot 0 addprop 17 | ; 18 | -------------------------------------------------------------------------------- /win32/win32.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void sync(void) { return; } 5 | 6 | #define TOFFSET (((LONGLONG)27111902 << 32) + (LONGLONG)3577643008) 7 | 8 | static void ftconvert(const FILETIME *ft, struct timeval *ts) 9 | { 10 | ts->tv_sec = (int)((*(LONGLONG *)ft - TOFFSET) / 10000000); 11 | ts->tv_usec = (int)((*(LONGLONG *)ft - TOFFSET - ((LONGLONG)ts->tv_sec * (LONGLONG)10000000)) * 100) / 1000; 12 | } 13 | 14 | int gettimeofday(struct timeval *tv, struct timezone *tz) 15 | { 16 | FILETIME ft; 17 | GetSystemTimeAsFileTime(&ft); 18 | ftconvert(&ft,tv); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/50.m: -------------------------------------------------------------------------------- 1 | $include $lib/match 2 | 3 | : listem-loop (count dbref -- ) 4 | dup not if 5 | pop intostr " exits." strcat 6 | tell exit 7 | then 8 | swap 1 + swap dup unparseobj tell 9 | next listem-loop 10 | ; 11 | 12 | : main 13 | strip dup not if 14 | pop "here" 15 | then 16 | match_controlled dup not if pop exit then 17 | dup exit? over program? or if 18 | "That object doesn't have any exits." 19 | tell pop exit 20 | then 21 | exits dup not if 22 | "That object has no exits on it." 23 | tell pop exit 24 | then 25 | 0 swap listem-loop 26 | ; 27 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/28.m: -------------------------------------------------------------------------------- 1 | $version 1.2 2 | 3 | $include $lib/props 4 | 5 | $define maildir "_page/mail#" $enddef 6 | 7 | : mail-warn 8 | maildir me @ over locate-prop 9 | dup ok? if 10 | me @ over controls not if pop me @ then 11 | swap getpropstr atoi 12 | else 13 | pop pop 0 14 | then 15 | dup if 16 | dup 1 > if 17 | intostr " page-mail messages" strcat 18 | else pop "a page-mail message" 19 | then 20 | else pop exit 21 | then 22 | "You sense that you have " swap strcat 23 | " waiting." strcat 24 | tell 25 | "You can read your page-mail with 'page #mail'" tell 26 | ; 27 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/64.m: -------------------------------------------------------------------------------- 1 | ( cmd-list by Natasha@HLM 2 | 3 | Copyright 2002 Natasha O'Brien. Copyright 2002 Here Lie Monsters. 4 | "@view $box/mit" for license information. 5 | ) 6 | $include $lib/strings 7 | $include $lib/match 8 | : main ( str ) 9 | STRparse ( strX strY strZ ) 10 | rot "help" stringcmp not if pop pop .showhelp exit then ( strY strZ ) 11 | 12 | swap noisy_match dup ok? not if pop pop exit then swap ( db strZ ) 13 | array_get_proplist dup if ( arr ) 14 | me @ 1 array_make array_notify ( ) 15 | else 16 | pop "There is no such list." tell ( ) 17 | then ( ) 18 | ; 19 | -------------------------------------------------------------------------------- /conanfile.txt: -------------------------------------------------------------------------------- 1 | [requires] 2 | # Use compatible versions of OpenSSL accoding to semantic versioning. 3 | # See: https://docs.conan.io/en/latest/mastering/version_ranges.html 4 | openssl/[~=1.1.1l] 5 | 6 | 7 | [options] 8 | # Use shared .dll libraries (MD instead of MT) 9 | OpenSSL:shared=True 10 | 11 | [imports] 12 | # Copy .dll, .lib, and .h files according to the makefile expectations 13 | # This is specific to OpenSSL and NMake's makefile.win. In the future, it'd be 14 | # easier to integrate the Conan package manager by using CMake, or similar. 15 | bin, *.dll -> ./build 16 | lib, *.lib* -> ./bin/lib/vc 17 | include, *.h* -> ./bin/include 18 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | fbmuck: 4 | build: 5 | context: ./ 6 | dockerfile: Dockerfile 7 | command: /usr/bin/docker-entrypoint.sh 8 | init: true 9 | # Uncomment this before building if you want to have the database saved 10 | # when the container terminates 11 | #stop_signal: SIGUSR2 12 | # If you aren't using SSL, you can comment out the line for FB_SSL_PORT 13 | # so that it doesn't open the second port. 14 | ports: 15 | - "${FB_PORT}:4201" 16 | - "${FB_SSL_PORT}:4202" 17 | volumes: 18 | - "${FB_DATA_PATH}:/opt/fbmuck:z" 19 | - "${FB_CERT_PATH}:/opt/fbmuck-ssl:z" 20 | environment: 21 | - "USE_SSL=${FB_USE_SSL}" 22 | - "SELF_SIGN=${FB_SELF_SIGN}" 23 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/54.m: -------------------------------------------------------------------------------- 1 | $include $lib/strings 2 | $include $lib/match 3 | 4 | : main 5 | "me" match me ! 6 | 7 | "=" split strip 8 | "yes" stringcmp if 9 | "Use \"@purge =yes\" to purge a player's possessions." 10 | me @ swap notify pop exit 11 | then 12 | strip noisy_pmatch 13 | dup not if pop exit then 14 | 15 | dup me @ dbcmp not 16 | me @ "wizard" flag? not and if 17 | "Permission denied." tell 18 | pop exit 19 | then 20 | 21 | "Beginning purge." tell 22 | 0 sleep 23 | dbtop begin 24 | int 1 - dup 0 > while dbref 25 | dup ok? not if continue then 26 | dup player? if continue then 27 | over over owner dbcmp if dup recycle 0 sleep then 28 | repeat pop pop 29 | me @ "Purge complete." notify 30 | ; 31 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/118.m: -------------------------------------------------------------------------------- 1 | ( con-laston.muf by Natasha@HLM 2 | Sets users' @/laston and @/lastoff props appropriately, for use with Natasha's cmd-laston. 3 | 4 | Copyright 2002 Natasha O'Brien. Copyright 2002 Here Lie Monsters. 5 | "@view $box/mit" for license information. 6 | ) 7 | : main ( str -- ) 8 | systime ( str int ) 9 | background ( str int ) 10 | intostr ( str strSecs ) 11 | 12 | swap "Connect" strcmp if "@/last/off" else "@/last/on" then ( strSecs strProp ) 13 | me @ over 4 pick setprop ( strSecs strProp ) 14 | me @ over array_get_proplist ( strSecs strProp arrTimes ) 15 | rot swap array_appenditem ( strProp arrTimes ) 16 | dup array_count 10 > if 17 | 0 array_delitem ( strProp arrTimes ) 18 | then 19 | me @ -3 rotate array_put_proplist ( ) 20 | ; 21 | -------------------------------------------------------------------------------- /include/fbsignal.h: -------------------------------------------------------------------------------- 1 | /** @file fbsignal.h 2 | * 3 | * Header for the declaration of Fuzzball's signal handling system. 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #ifndef FBSIGNAL_H 9 | #define FBSIGNAL_H 10 | 11 | /** 12 | * Set signals for the forked dump processes 13 | * 14 | * These signals are not necessarily the same as the signals for the main 15 | * program, but are tailored towards the needs of the dump process. 16 | */ 17 | void set_dumper_signals(void); 18 | 19 | /** 20 | * This does the initial signal setup. 21 | */ 22 | void set_signals(void); 23 | 24 | #ifdef HAVE_PSELECT 25 | /** 26 | * @var the signal mask for pselect - this is set by set_signals 27 | */ 28 | extern sigset_t pselect_signal_mask; 29 | #endif 30 | 31 | #endif /* !FBSIGNAL_H */ 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | bin/fbmuck 31 | src/fbmuck 32 | fbhelp 33 | fb-resolver 34 | mkversion 35 | prochelp 36 | restart 37 | 38 | # Debug files 39 | *.dSYM/ 40 | 41 | # Generated files 42 | Makefile 43 | autom4te.cache/ 44 | config.log 45 | config.status 46 | include/autoconf.h 47 | include/defines.h 48 | src/version.c 49 | docs_html/ 50 | 51 | # Windows build files 52 | compile 53 | winsrc 54 | 55 | # Temporary backup files 56 | *~ 57 | 58 | # Python virtual environments 59 | venv 60 | 61 | # Password file 62 | pw-file.txt 63 | -------------------------------------------------------------------------------- /tests/command-cases/p_misc.yml: -------------------------------------------------------------------------------- 1 | - name: fmttime-crash-regression1 2 | setup: | 3 | @program test.muf 4 | i 5 | : main "" "Test." fmttime ; 6 | . 7 | c 8 | q 9 | @act test=here 10 | @link test=test.muf 11 | commands: | 12 | test 13 | expect: 14 | - "Program Error" 15 | 16 | - name: fmttime-crash-regression2 17 | setup: | 18 | @program test.muf 19 | i 20 | : main "Test." "" fmttime ; 21 | . 22 | c 23 | q 24 | @act test=here 25 | @link test=test.muf 26 | commands: | 27 | test 28 | expect: 29 | - "Program Error" 30 | 31 | - name: convtime-crash-regression 32 | setup: | 33 | @program test.muf 34 | i 35 | : main "" convtime ; 36 | . 37 | c 38 | q 39 | @act test=here 40 | @link test=test.muf 41 | commands: | 42 | test 43 | expect: 44 | - "Program Error" 45 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Fuzzball's documentation 6 | 7 | 8 |

Fuzzball's documentation

9 |

HTML documentation

10 | 15 |

Text documentation

16 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/command-cases/move.yml: -------------------------------------------------------------------------------- 1 | - name: home 2 | setup: | 3 | @dig IdTwo 4 | @link me=#2 5 | home 6 | commands: | 7 | ex me 8 | expect: "Location: IdTwo\\(" 9 | - name: leave 10 | setup: | 11 | @tune vehicles=yes 12 | @create IdTwo 13 | @set IdTwo=V 14 | drop IdTwo 15 | @idesc Idtwo=TestInsideDesc 16 | commands: | 17 | @tel me=#2 18 | ex me 19 | leave 20 | ex me 21 | expect: 22 | - "You exit the" 23 | - "TestInsideDesc" 24 | - "Location: IdTwo" 25 | - "Location: Room Zero" 26 | - name: drop 27 | setup: | 28 | @create IdTwo 29 | commands: | 30 | drop Idtwo 31 | ex IdTwo 32 | expect: 33 | - "Location: Room Zero" 34 | - name: get 35 | setup: | 36 | @create IdTwo 37 | drop IdTwo 38 | commands: | 39 | get IdTwo 40 | ex IdTwo 41 | expect: 42 | - "Taken." 43 | - "Location: One" 44 | - name: recycle 45 | setup: | 46 | @create IdTwo 47 | @recycle IdTwo 48 | commands: | 49 | ex #2 50 | expect: 51 | - "is garbage" 52 | 53 | -------------------------------------------------------------------------------- /game/data/edit-help.txt: -------------------------------------------------------------------------------- 1 | Program commands: 2 | compile [c] compile program 3 | delete [d] delete lines 4 | insert [i] insert program lines 5 | list [l] list program lines 6 | publics [p] show PUBLIC/WIZCALL words in program 7 | unassemble [u] disassemble program (not usually useful) 8 | 9 | can be nothing, a single number, or two numbers for a range. 10 | 11 | Editor commands: 12 | help [h] show this file 13 | numbers [n] toggle line numbers 14 | quit [q] quit the program editor 15 | view [v] list initial single-line comments 16 | cancel [x] quit the program editor without saving 17 | 18 | Macro library commands: 19 | abridged [a] show list of library functions, names only 20 | kill [k] kill a macro/library reference (wizard only) 21 | show [s] show list of library functions, full display 22 | def Define a macro for use as . 23 | 24 | can be nothing, a single string, or two strings for a range. 25 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/3.m: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy 2 | of this software and associated documentation files {the "Software"}, to 3 | deal in the Software without restriction, including without limitation the 4 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 5 | sell copies of the Software, and to permit persons to whom the Software is 6 | furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in 9 | all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 16 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 17 | IN THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/8.m: -------------------------------------------------------------------------------- 1 | ( ***** Misc String routines -- STR ***** 2 | sms [ str -- str' ] strips out mult. internal spaces 3 | fillfield [ str char width -- padstr ] return padding string to width chars 4 | STRparse [ str -- str1 str2 str3 ] " #X Y y = Z" -> "X" "Y y" " Z" 5 | ) 6 | 7 | $doccmd @list __PROG__=!@1-5 8 | 9 | : sms ( str -- str') 10 | begin 11 | dup " " instr while 12 | " " " " subst 13 | repeat 14 | ; 15 | 16 | : fillfield (str padchar fieldwidth -- padstr) 17 | rot ansi_strlen - dup 1 < if pop pop "" exit then 18 | swap over begin swap dup strcat swap 2 / dup not until pop 19 | swap ansi_strcut pop 20 | ; 21 | 22 | : STRparse ( s -- s1 s2 s3 ) 23 | ( 24 | Before: " #option tom dick harry = message " 25 | After: "option" "tom dick harry" " message " 26 | ) 27 | "=" rsplit swap 28 | striplead dup "#" 1 strncmp not if 29 | 1 strcut swap pop 30 | " " split 31 | else 32 | "" swap 33 | then 34 | strip sms rot 35 | ; 36 | 37 | public sms $libdef sms 38 | public fillfield $libdef fillfield 39 | public STRparse $libdef STRparse 40 | -------------------------------------------------------------------------------- /win32/win32.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN32_H_ 2 | #define _WIN32_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define CURRENTLY_UNAVAILABLE "If you see this message, visit us at https://github.com/fuzzball-muck/fuzzball and open an issue. We'd be happy to fix it, but we would like more detail on how it is being used." 10 | 11 | #define pid_t int 12 | #define sa_family_t ADDRESS_FAMILY 13 | #define socklen_t int 14 | #define ssize_t long 15 | 16 | #define close(x) closesocket(x) 17 | #define chdir _chdir 18 | #define execv _execv 19 | #define getpid _getpid 20 | #define inet_pton InetPton 21 | #define pclose _pclose 22 | #define popen _popen 23 | #define read(fd, buf, count) \ 24 | recv(fd, (char *)buf, count, 0) 25 | #define strcasecmp _stricmp 26 | #define strdup _strdup 27 | #define strncasecmp _strnicmp 28 | #define strtok_r strtok_s 29 | #define tzname _tzname 30 | #define unlink _unlink 31 | #define write(fd, buf, count) \ 32 | send(fd, (char *)buf, count, 0) 33 | 34 | int gettimeofday(struct timeval *tv, struct timezone *tz); 35 | void set_console(); 36 | void sync(); 37 | struct tm *uw32localtime(const time_t *t); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/73.m: -------------------------------------------------------------------------------- 1 | ( cmd-reconnect by Natasha@HLM 2 | A Fuzzball 6 program for creating new players on the MUCK. 3 | 4 | Copyright 2002-2003 Natasha O'Brien. Copyright 2002-2003 Here Lie Monsters. 5 | "@view $box/mit" for license information. 6 | ) 7 | $include $lib/strings 8 | : main ( str -- ) 9 | strip ( str ) 10 | dup not over "#" stringpfx or if pop .showhelp exit then ( str ) 11 | sms " " split ( strName strPass ) 12 | 13 | ( Find old. ) 14 | over pmatch dup ok? not if ( strName strPass db ) 15 | pop pop "I don't see anyone named '%s'." fmtstring tell ( ) 16 | exit ( ) 17 | then ( strName strPass db ) 18 | dup "Reconnecting as %D." fmtstring tell ( strName strPass db ) 19 | 20 | rot pop swap ( db strPass ) 21 | 22 | me @ descrleastidle ( db strPass intDescr ) 23 | 3 pick rot ( db intDescr db strPass ) 24 | 3 try 25 | descr_setuser 26 | catch ( db strErr ) 27 | swap "Could not reconnect you as %D: %s" fmtstring tell ( ) 28 | exit ( ) 29 | endcatch ( db intReconnected ) 30 | 31 | if ( db ) 32 | "Reconnected." notify ( ) 33 | else pop 34 | "Could not reconnect." tell ( ) 35 | then ( ) 36 | ; 37 | -------------------------------------------------------------------------------- /include/events.h: -------------------------------------------------------------------------------- 1 | /** @file events.h 2 | * 3 | * Header for functions that handle periodic events on the MUCK. 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #ifndef EVENTS_H 9 | #define EVENTS_H 10 | 11 | #include 12 | 13 | /** 14 | * Do a database dump now 15 | * 16 | * This doesn't do any of the purges that the periodic dump does, but 17 | * it does set the last dump time property and resets the timer to now. 18 | */ 19 | void dump_db_now(void); 20 | 21 | /** 22 | * Runs muckevents 23 | * 24 | * This will run timequeue events, dumps, and cleanups. While it tries 25 | * each function, the functions will only do something if something is 26 | * ready to happen. This is safe to run whenever, but next_muckevent_time 27 | * will return the time until this will actually do something. 28 | * 29 | * @see next_muckevent_time 30 | */ 31 | void next_muckevent(void); 32 | 33 | /** 34 | * Calculate the time until a MUCK event will happen 35 | * 36 | * Could be an event, a dump, or a cleanup. Whichever comes next 37 | * will determine which time is returned. 38 | * 39 | * @return the time until the next MUCK event 40 | */ 41 | time_t next_muckevent_time(void); 42 | 43 | #endif /* !EVENTS_H */ 44 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/103.m: -------------------------------------------------------------------------------- 1 | 2 | $def confirm tell read 1 strcut pop "y" stringcmp not 3 | 4 | : show-docs ( d -- ) 5 | "_docs" getpropstr dup if 6 | dup "Command to view: " swap strcat tell 7 | "Run this command? (y/n)" confirm if 8 | me @ swap force 9 | else 10 | me @ "Command cancelled." notify pop 11 | then 12 | else 13 | me @ "No documents available for that program, sorry." notify 14 | pop 15 | then 16 | ; 17 | : show-defs-iter ( d s -- d s' ) 18 | over over getpropstr 19 | over " = " strcat swap strcat 6 strcut swap pop 20 | tell 21 | over swap nextprop 22 | ; 23 | : show-defs ( d -- ) 24 | dup "_defs/" nextprop dup if 25 | "Read definitions? (y/n)" confirm if 26 | begin 27 | show-defs-iter 28 | dup not until 29 | pop pop 30 | else 31 | pop pop 32 | then 33 | else 34 | pop 35 | then 36 | ; 37 | : @view 38 | dup not if 39 | me @ "Usage: @view program (#dbref or $name)" notify pop exit 40 | then 41 | match 42 | dup program? not if 43 | pop me @ "That isn't a program!" notify exit 44 | then 45 | dup show-docs 46 | show-defs 47 | ; 48 | -------------------------------------------------------------------------------- /game/data/welcome.txt: -------------------------------------------------------------------------------- 1 | ,... ,, ,, ,, 2 | .d' "" *MM `7MM `7MM 3 | dM` MM MM MM 4 | mMMmm`7MM `7MM M"""MMV M"""MMV MM,dMMb. ,6"Yb. MM MM 5 | MM MM MM ' AMV ' AMV MM `Mb 8) MM MM MM 6 | MM MM MM AMV AMV MM M8 ,pm9MM MM MM 7 | MM MM MM AMV , AMV , MM. ,M9 8M MM MM MM 8 | .JMML. `Mbod"YML.AMMmmmM AMMmmmM P^YbmdP' `Moo9^Yo..JMML..JMML. 9 | 10 | `7MMM. ,MMF'`7MMF' `7MF' .g8"""bgd `7MMF' `YMM' 11 | MMMb dPMM MM M .dP' `M MM .M' 12 | M YM ,M MM MM M dM' ` MM .d" 13 | M Mb M' MM MM M MM MMMMM. 14 | M YM.P' MM MM M MM. MM VMA 15 | M `YM' MM YM. ,M `Mb. ,' MM `MM. 16 | .JML. `' .JMML. `bmmmmd"' `"bmmmd' .JMML. MMb. 17 | 18 | 19 | To connect to your character use 'connect ' 20 | To create a new character use 'create ' 21 | 22 | 'WHO' and 'help' also work in this context. 23 | -------------------------------------------------------------------------------- /scripts/trigger-dump.py: -------------------------------------------------------------------------------- 1 | """Python script to trigger a dump on a MUCK and wait for it. 2 | 3 | Uses pyfuzzball repo here: https://github.com/tanabi/pyfuzzball 4 | 5 | Change the password, please :) 6 | 7 | Returns status code 0 on success, or 1 on failure. Failure will only be 8 | if there happens to be another dump triggered at the exact moment you're 9 | triggering your own dump. 10 | """ 11 | 12 | # 13 | # CONFIGURATION - Change these 14 | # 15 | HOST = 'localhost' 16 | PORT = 4201 17 | SSL = False 18 | AUTHTOKEN = 'change-me-please' 19 | 20 | # 21 | # LEAVE THIS STUFF ALONE 22 | # 23 | from pyfuzzball.mcp import MCP 24 | import sys 25 | 26 | # Open MCP connection 27 | m = MCP(HOST, PORT, SSL, True) 28 | 29 | # Negotiate 30 | m.negotiate(['org-fuzzball-dump']) 31 | 32 | # Call dump with auth token 33 | m.call('org-fuzzball-dump', 'dump', { 34 | 'auth': AUTHTOKEN 35 | }) 36 | 37 | # Process results 38 | results = m.process() 39 | 40 | # results[1] will have the dump output messages most likely. You 41 | # could process these instead of waiting for the MCP event if you 42 | # preferred, but I wrote an MCP parser, so by golly I'm going to 43 | # use it :) 44 | while not results[0] and 'org-fuzzball-dump' not in results[0]: 45 | results = m.process() 46 | 47 | # 'success' should be in the parameters if it worked. 48 | if 'success' in results[0]['org-fuzzball-dump'][0]['parameters']: 49 | sys.exit(0) 50 | else: 51 | sys.exit(1) 52 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/85.m: -------------------------------------------------------------------------------- 1 | $include $lib/timestr 2 | 3 | : collate-entry (i -- s) 4 | dup descrdbref name 5 | over descrtime mtimestr 6 | over strlen over strlen + 7 | dup 19 < if 8 | " " (19 spaces) 9 | swap strcut swap pop 10 | else 11 | 19 - rot dup strlen rot - 12 | strcut pop swap "" 13 | then 14 | swap strcat strcat 15 | swap descridle stimestr strcat 16 | ; 17 | 18 | : get-namelist ( -- {s} ) 19 | 0 #-1 firstdescr 20 | begin dup while 21 | dup collate-entry 22 | rot 1 + rot 23 | nextdescr 24 | repeat 25 | pop 26 | ; 27 | lvar col 28 | : show-namelist ({s} -- ) 29 | begin 30 | dup 3 >= while 31 | swap " " strcat 32 | over 3 / 3 pick 3 % 2 + 3 / + 33 | dup col ! 2 + 34 | rotate strcat " " strcat 35 | over 3 / 3 pick 3 % 1 + 36 | 3 / + col @ + 1 + 37 | rotate strcat 38 | tell 3 - 39 | repeat 40 | dup if 41 | "" 42 | begin 43 | over 0 > while 44 | rot strcat " " strcat 45 | swap 1 - swap 46 | repeat 47 | tell 48 | then 49 | pop 50 | ; 51 | 52 | : show-who 53 | preempt 54 | "Name OnTime Idle " dup strcat 55 | "Name Ontime Idle" strcat tell 56 | get-namelist 57 | show-namelist 58 | concount intostr 59 | " players are connected." 60 | strcat tell 61 | ; 62 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/81.m: -------------------------------------------------------------------------------- 1 | ( @stats.MUF ) 2 | ( Freeware, by Nimravid for SPR ) 3 | 4 | : header ( d -- ) 5 | "Stats for : " swap unparseobj strcat tell 6 | ; 7 | 8 | : pad ( s i -- s ) 9 | " " 10 | rot swap strcat 11 | swap strcut pop 12 | ; 13 | 14 | : make_str ( s i i ) 15 | over 100 * over / 16 | intostr "%" strcat 17 | swap intostr 9 pad 18 | rot intostr 9 pad 19 | swap strcat 20 | swap strcat 21 | strcat 22 | ; 23 | 24 | : stuff ( d -- ) 25 | stats 26 | #-1 stats 27 | " " "Owned" 9 pad "MUCK" 9 pad "% owned" strcat strcat strcat tell 28 | "Garbage : " 9 rotate rot make_str tell 29 | "Players : " 8 rotate rot make_str tell 30 | "Programs : " 7 rotate rot make_str tell 31 | "Things : " 6 rotate rot make_str tell 32 | "Exits : " 5 rotate rot make_str tell 33 | "Rooms : " 4 rotate rot make_str tell 34 | "==================================" tell 35 | "Total : " rot rot make_str tell 36 | ; 37 | 38 | : main 39 | "me" match owner me ! 40 | caller exit? not if "Hey now." tell exit then 41 | dup if 42 | dup "#help" stringcmp not if pop .showhelp exit then ( Added #help option Natasha@HLM 31 October 2002 ) 43 | me @ "wizard" flag? 44 | if pmatch 45 | dup ok? if 46 | dup header stuff exit 47 | else 48 | pop "Invalid player ref." tell 49 | exit 50 | then 51 | else 52 | pop "Sorry, WIZ only." tell exit 53 | then 54 | else 55 | me @ dup header stuff 56 | then 57 | ; 58 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | RUN apt update && apt dist-upgrade -y 3 | RUN apt-get install -y build-essential \ 4 | libpcre3-dev libssl-dev git autoconf \ 5 | automake autoconf-archive 6 | COPY . fuzzball/ 7 | RUN cd fuzzball && \ 8 | ./configure --with-ssl --prefix /root/scratch && make clean && \ 9 | make && make install 10 | 11 | FROM ubuntu:20.04 12 | RUN apt update && apt dist-upgrade -y \ 13 | && apt-get install -y libssl1.1 openssl \ 14 | && mkdir -p /opt/fbmuck-base \ 15 | && mkdir -p /opt/fbmuck-ssl 16 | 17 | COPY --from=0 /root/scratch /usr 18 | 19 | # Copy docker-entrypoint.sh into /usr/bin 20 | COPY scripts/docker-entrypoint.sh /usr/bin/ 21 | 22 | # It will be looking for globals in /root/scratch/share because of how 23 | # we are building. The link will fix it so we're looking in the right 24 | # spot. 25 | RUN chmod a+rx /usr/bin/docker-entrypoint.sh && ln -s /usr /root/scratch 26 | 27 | # Copy FB base into /opt/fbmuck-base in case we need to start a blank DB 28 | COPY game/ dbs/starterdb/ /opt/fbmuck-base/ 29 | # Additionally, copy files in docs into the fbmuck-base/data directory 30 | # so users have helpful things like help.txt 31 | COPY docs/ /opt/fbmuck-base/data 32 | 33 | # Rename the base db to the right db file name 34 | RUN mv /opt/fbmuck-base/data/starterdb.db /opt/fbmuck-base/data/std-db.db 35 | 36 | # Uncomment this before building if you want the database saved upon 37 | # process termination 38 | #STOPSIGNAL SIGUSR2 39 | 40 | ENTRYPOINT ["bash", "/usr/bin/docker-entrypoint.sh"] 41 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | #!/bin/make -f 2 | 3 | # ####################################################################### 4 | # Variables set by the configure script. 5 | # ####################################################################### 6 | 7 | INSTALL=@INSTALL@ 8 | INSTALL_PROGRAM=@INSTALL_PROGRAM@ 9 | INSTALL_SCRIPT=@INSTALL_SCRIPT@ 10 | INSTALL_DATA=@INSTALL_DATA@ 11 | 12 | subdirs=src 13 | RM=rm -f 14 | MAKE=make 15 | 16 | all: Makefile 17 | for d in ${subdirs}; do \ 18 | cd $${d} && ${MAKE} all; \ 19 | done 20 | 21 | install: Makefile 22 | for d in ${subdirs}; do \ 23 | cd $${d} && ${MAKE} install; \ 24 | done 25 | @if grep "^#define HAVE_LIBSSL" include/autoconf.h > /dev/null; then \ 26 | if [ ! -f game/data/server.pem ]; then \ 27 | echo "You can use letsencrypt (with certbot, acme-client, acme.sh, or other clients) to get a free TLS certificate for use in enabling secure, encrypted connections to your MUCK."; \ 28 | fi; \ 29 | fi 30 | 31 | docker: 32 | docker build -t fbmuck . 33 | 34 | docker-compose: 35 | docker-compose build 36 | 37 | install-sysv-inits: Makefile 38 | for d in ${subdirs}; do \ 39 | cd $${d} && ${MAKE} install-sysv-inits; \ 40 | done 41 | 42 | clean: 43 | for d in ${subdirs}; do \ 44 | cd $${d} && ${MAKE} clean; \ 45 | done 46 | 47 | nuke: 48 | for d in ${subdirs}; do \ 49 | cd $${d} && ${MAKE} nuke; \ 50 | done 51 | ${RM} include/autoconf.h 52 | ${RM} Makefile config.status config.cache config.log game/restart include/autoconf.h 53 | 54 | Makefile: Makefile.in 55 | ./config.status Makefile 56 | @echo Please re-run ${MAKE}, because the Makefile was re-generated. 57 | 58 | help: 59 | for d in ${subdirs}; do \ 60 | cd $${d} && ${MAKE} help; \ 61 | done 62 | -------------------------------------------------------------------------------- /win32/README.TXT: -------------------------------------------------------------------------------- 1 | A lot has changed since the last native windows build, particularly with the server code itself. 2 | It now supports TLS, write behind saving and deltas, and a whole bunch of other features. Most 3 | of these have been enabled in the server itself for the native windows compile, and a lot of 4 | stuff has been fixed since the last build. If you want to compile this code for windows, you'll 5 | need a few things: 6 | 7 | - The OpenSSL Library (if you want to enable SSL support) 8 | - Some sort of win32 c++ compiler 9 | 10 | First, install the OpenSSL suite if you're going to use it. Second, edit the Makefile.win file 11 | in this directory. About 15 lines down, change the OPENSSLDIR define to represent where you 12 | installed the OpenSSL suite. Next, run precompile.bat from this directory. This will create 13 | a few folders, rename some files, and set things up for compilation. Next, make sure your 14 | environment variables for your compiler are set correctly. Visual Studio has a file called 15 | VCVARS32.BAT that contains all of the relevant setup necessary. Finally, run NMAKE and if 16 | everything goes right, you should have a working executable in the game directory, as well 17 | as a restart.exe file. To create a restart.ini file, just run restart with the -c option 18 | and it will generate one for you. If you compiled with the SSL option enabled, you'll need 19 | to generate a keyfile/certificate for your server. letsencrypt is recommended for this. 20 | For more information on how to generate this file, see the OpenSSL 21 | documentation, or e-mail for assistance. If you have specific questions about this variant 22 | of the code feel free to email Keet Fox using the following address: winfuzz at foxpaws.net. 23 | -------------------------------------------------------------------------------- /game/data/credits.txt: -------------------------------------------------------------------------------- 1 | Based on the original code written by these programmers: 2 | David Applegate James Aspnes Timothy Freeman Bennet Yee 3 | 4 | Others who have done major coding work along the way: 5 | Lachesis, ChupChup, FireFoot, and Russ 'Random' Smith 6 | 7 | This is a user-extensible, user-programmable multi-user adventure game. 8 | TinyMUCK was derived from TinyMUD v1.5.2, with extensive modifications. 9 | Because of all the modifications, this program is not in any way, shape, 10 | or form being supported by any of the original authors. Any bugs, ideas, 11 | suggestions, etc, should be directed to the persons listed below. 12 | Do not send diff files, send us mail about the bug and describe as best 13 | as you can, where you were at when the bug occured, and what you think 14 | caused the bug to be produced, so we can try to reproduce it and track 15 | it down. 16 | 17 | The code is currently maintained on GitHub. 18 | Repository URL: https://github.com/fuzzball-muck/fuzzball/ 19 | Feedback Email: feedback@fuzzball.org 20 | 21 | The following programmers have contributed greatly: 22 | Akari, Alynna, Arcticwolf (Schneelocke), Cerilus, Fentonator, Ferretbun, 23 | Foxbird, Foxen/Revar, Jenora, Naiya, Natasha O'Brien, Points, Sombre, 24 | Tanabi, Tiger (Fre'ta), Winged, Wog, and Wyld. 25 | 26 | The following people helped out a lot along the way: 27 | Caspian, Kim "Bookwyrm" Liu, Chris, Jenora, Lynx, WhiteFire, 28 | Kimi, Cynbe, Myk, Taldin, Howard, darkfox, Moonchilde, Felorin, Xixia, 29 | Doran, Riss, King_Claudius, Sarusa@FurryMUCK, and 30 | Henri@Voregotten Realm. 31 | 32 | Thanks also goes to those persons not mentioned here who have added 33 | their advice, opinions, and code to TinyMUCK FB. 34 | -------------------------------------------------------------------------------- /dbs/starterdb/README: -------------------------------------------------------------------------------- 1 | * The database contains two players, One and Keeper. You should change One's 2 | password immediately: 3 | 4 | connect #1 potrzebie 5 | @password potrzebie= 6 | 7 | Only One can perform some functions like setting and removing players' 8 | Wizard flags. Keep its password safe! 9 | 10 | Keeper is for owning general MUCK property such as MUF programs and public 11 | areas. Programs that need a "force wizard" can use Keeper. Feel free to 12 | rename Keeper with your MUCK's name or initials. 13 | 14 | * There are three environment rooms for public building: 15 | 16 | $env/null Null Environment Room 17 | $env/in Indoor Environment Room 18 | $env/out Outdoor Environment Room 19 | 20 | By default new rooms are placed in the Null Environment Room. 21 | 22 | * Some commands in this database to which you may not be accustomed are: 23 | 24 | alias Set an alias, like a page #alias, to be used in page, 25 | whisper, laston, meetme, etc. 26 | ansi Shows an ANSI test pattern; "ansi #on" enables color. 27 | away Set an "away" flag that's shown in page, ws, and WHO. 28 | banish Allows a room owner to ban players from a room or area. 29 | feel;taste Sense verbs like "smell". 30 | ignore Operates Fuzzball 6's inserver "ignore" function. 31 | @muf Runs short MUF programs, like @mpi. 32 | programs Searches for MUF programs set Viewable. 33 | 34 | Use " #help" to get documentation on any of them. To use alias and 35 | away in your own MUF programs, "@view $lib/alias" and "@view $lib/away". 36 | "@view $lib/table" for another unusual library, for tabular output, as in 37 | ws, wd, and laston. 38 | 39 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/32.m: -------------------------------------------------------------------------------- 1 | ( neobootme.muf by Natasha@HLM. 2 | 3 | Copyright 1999 Natasha O'Brien. 4 | "@view $box/mit" for licensing information. 5 | 6 | A new @bootme program that works under the theory that booting all the users 7 | but the one who did the '@bootme' is more intuitive than booting all but the 8 | newest user. 9 | 10 | Anyone who's wanted to use @bootme to remotely disconnect a connection from 11 | another room, and has happened to disconnect oneself instead, understands 12 | that booting the lowest connection number isn't always desired. This program 13 | works under the theory that the connection that did the '@bootme' will be 14 | the least idle connection {since it just issued a command, after all}, and 15 | thusly boots all one's connections but the least idle. 16 | 17 | ) 18 | : main ( s -- ) 19 | pop ( ) 20 | 21 | ( Do we even need to @bootme? ) 22 | me @ descriptors 2 < if ( ix..i1 ) 23 | "You only have the one connection." tell exit 24 | then ( ix..i1 } ix..i1=user's descriptors ) 25 | 26 | ( Remove the descriptor that has been idle for the least time, on the 27 | theory that that's the one who did the @bootme. Boot the others off. ) 28 | begin depth 1 > while ( ix..i2 i1 ) 29 | over descridle ( ix..i2 i1 it2 } it2=number of seconds i2 has been connected ) 30 | over descridle ( ix..i2 i1 it2 it1 ) 31 | ( If it2 is greater than it1, we'll want to boot i2, not i1. ) 32 | > if ( ix..i2 i1 ) 33 | ( Get the one we should boot on top of the stack. ) 34 | swap ( ix..i1 i2 ) 35 | then ( ix..i? i? ) 36 | dup "You have been booted by yourself." descrnotify descrboot ( ix..i? ) 37 | repeat ( i } i=the one descriptor left over ) 38 | "Old connections booted." descrnotify ( ) 39 | ; 40 | -------------------------------------------------------------------------------- /include/color.h: -------------------------------------------------------------------------------- 1 | /** @file color.h 2 | * 3 | * Header for defining ANSI color attributes and codes. 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #ifndef COLOR_H 9 | #define COLOR_H 10 | 11 | /* ANSI attributes and color codes */ 12 | 13 | #define ANSI_RESET "\033[0m" /**< Reset ANSI */ 14 | 15 | #define ANSI_BOLD "\033[1m" /**< Toggle bold */ 16 | #define ANSI_DIM "\033[2m" /**< Toggle dim */ 17 | #define ANSI_ITALIC "\033[3m" /**< Toggle italic */ 18 | #define ANSI_UNDERLINE "\033[4m" /**< Toggle underline */ 19 | #define ANSI_FLASH "\033[5m" /**< Toggle flash */ 20 | #define ANSI_REVERSE "\033[7m" /**< Toggle reverse FG/BG */ 21 | #define ANSI_OSTRIKE "\033[9m" /**< Toggle overstrike */ 22 | 23 | #define ANSI_FG_BLACK "\033[30m" /**< Foreground black */ 24 | #define ANSI_FG_RED "\033[31m" /**< Foreground red */ 25 | #define ANSI_FG_GREEN "\033[32m" /**< Foreground green */ 26 | #define ANSI_FG_YELLOW "\033[33m" /**< Foreground yellow */ 27 | #define ANSI_FG_BLUE "\033[34m" /**< Foreground blue */ 28 | #define ANSI_FG_MAGENTA "\033[35m" /**< Foreground magenta */ 29 | #define ANSI_FG_CYAN "\033[36m" /**< Foreground cyan */ 30 | #define ANSI_FG_WHITE "\033[37m" /**< Foreground white */ 31 | 32 | #define ANSI_BG_BLACK "\033[40m" /**< Background black */ 33 | #define ANSI_BG_RED "\033[41m" /**< Background red */ 34 | #define ANSI_BG_GREEN "\033[42m" /**< Background green */ 35 | #define ANSI_BG_YELLOW "\033[43m" /**< Background yellow */ 36 | #define ANSI_BG_BLUE "\033[44m" /**< Background blue */ 37 | #define ANSI_BG_MAGENTA "\033[45m" /**< Background magenta */ 38 | #define ANSI_BG_CYAN "\033[46m" /**< Background cyan */ 39 | #define ANSI_BG_WHITE "\033[47m" /**< background white */ 40 | 41 | #endif /* !COLOR_H */ 42 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/71.m: -------------------------------------------------------------------------------- 1 | ( cmd-programs.muf by Natasha@HLM 2 | A Fuzzball 6 program lister. 3 | 4 | Copyright 2003 Natasha O'Brien. Copyright 2003 Here Lie Monsters. 5 | "@view $box/mit" for license information. 6 | ) 7 | 8 | $include $lib/strings 9 | 10 | : main ( str -- ) 11 | STRparse pop ( strX strY ) 12 | 13 | var! vsearch ( strX ) 14 | #-1 var! vowner 15 | "FV" var! vflags ( strX ) 16 | 17 | dup if ( strX ) 18 | "mine" stringcmp if 19 | me @ vowner ! 20 | "F" vflags ! 21 | then ( ) 22 | else pop then ( ) 23 | 24 | " Dbref Name Author Owner Modified @view" "bold" textattr tell 25 | 26 | background ( ) 27 | #-1 begin ( dbStart ) 28 | vowner @ "*" vflags @ findnext ( db ) 29 | dup ok? ( db boolOK? ) 30 | while ( db ) 31 | dup ( db db ) 32 | dup "_note" getpropstr dup if "\r " swap strcat then ( db db strNote ) 33 | 34 | ( Wait, are we really listing this object? ) 35 | vsearch @ if 36 | over over "%s%D" fmtstring vsearch @ instring not if ( db db strNote ) 37 | pop pop continue ( db ) 38 | then ( db db strNote ) 39 | then swap ( db strNote db ) 40 | 41 | dup "_docs" getpropstr if "\[[1;32myes\[[0m" else "\[[1;31mno\[[0m" then swap ( db strNote strDocs db ) 42 | dup timestamps pop pop swap pop "%D" swap timefmt swap ( db strNote strDocs strModified db ) 43 | dup owner swap ( db strNote strDocs strModified dbOwner db ) 44 | dup "_author" getpropstr swap ( db strNote strDocs strModified dbOwner strAuthor db ) 45 | dup ( db strNote strDocs strModified dbOwner strAuthor db db ) 46 | "%6.6d %-24.24D %-20.20s %-10.10D %8.8s %-4.4s%s" fmtstring tell 47 | repeat pop ( ) 48 | 49 | "Done." tell 50 | ; 51 | -------------------------------------------------------------------------------- /tests/command-cases/p_mcp.yml: -------------------------------------------------------------------------------- 1 | - name: gui-set-value-dict 2 | setup: | 3 | #$#mcp version: "2.1" to: "2.1" authentication-key: "1234" 4 | #$#mcp-negotiate-can 1234 package: "org-fuzzball-gui" min-version: "1.0" max-version: "1.0" 5 | #$#mcp-negotiate-can 1234 package: "mcp-negotiate" min-version: "1.0" max-version: "1.0" 6 | #$#mcp-negotiate-end 1234 7 | @program test.muf 8 | 1 i 9 | : main 10 | descr D_SIMPLE "testing dialog" { }list gui_dlog_create 11 | dup C_SPINNER "example-id" { }list gui_ctrl_create 12 | dup "example-id" { 1 2 }dict gui_value_set 13 | ; 14 | . 15 | c 16 | q 17 | @act test=me 18 | @link test=test.muf 19 | commands: 20 | test 21 | expect: 22 | - "#\\$#org-fuzzball-gui-dlog-create 1234" 23 | - "#\\$#org-fuzzball-gui-ctrl-spinner 1234" 24 | - "Program Error." 25 | - "#\\$#org-fuzzball-gui-dlog-close 1234" 26 | 27 | - name: gui-set-value-list 28 | setup: | 29 | #$#mcp version: "2.1" to: "2.1" authentication-key: "1234" 30 | #$#mcp-negotiate-can 1234 package: "org-fuzzball-gui" min-version: "1.0" max-version: "1.0" 31 | #$#mcp-negotiate-can 1234 package: "mcp-negotiate" min-version: "1.0" max-version: "1.0" 32 | #$#mcp-negotiate-end 1234 33 | @program test.muf 34 | 1 i 35 | : main 36 | descr D_SIMPLE "testing dialog" { }list gui_dlog_create 37 | dup C_SPINNER "example-id" { }list gui_ctrl_create 38 | dup "example-id" { 1 2 3 }list gui_value_set 39 | 0 sleep 40 | me @ "After set." notify 41 | ; 42 | . 43 | c 44 | q 45 | @act test=me 46 | @link test=test.muf 47 | commands: 48 | test 49 | expect: 50 | - "#\\$#org-fuzzball-gui-dlog-create 1234" 51 | - "#\\$#org-fuzzball-gui-ctrl-spinner 1234" 52 | - "#\\$#org-fuzzball-gui-ctrl-value 1234 .* id: \"example-id\"" 53 | - "value: 1" 54 | - "value: 2" 55 | - "value: 3" 56 | - "After set." 57 | - "#\\$#org-fuzzball-gui-dlog-close 1234" 58 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Fuzzball CI 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | build-linux: 7 | name: Linux 8 | runs-on: ubuntu-latest 9 | strategy: 10 | fail-fast: false # Show all results 11 | matrix: 12 | compiler: [clang, gcc] 13 | # This might not be the most "proper" way to do this 14 | flag_ssl: ['', '--with-ssl'] 15 | flag_debug: ['', '--enable-debug'] 16 | flag_memprof: ['', '--enable-memprof'] 17 | 18 | steps: 19 | - name: Check out source code 20 | uses: actions/checkout@v2 21 | 22 | - name: Display build details 23 | run: | 24 | echo "Build configuration:" 25 | echo " * Compiler: $CC" 26 | if [ -n "$FLAG_SSL" ]; then echo " * With SSL ('$FLAG_SSL') " ; fi 27 | if [ -n "$FLAG_DEBUG" ]; then echo " * Debug enabled ('$FLAG_DEBUG')" ; fi 28 | if [ -n "$FLAG_MEMPROF" ]; then echo " * memprof enabled ('$FLAG_MEMPROF')" ; fi 29 | env: 30 | CC: ${{ matrix.compiler }} 31 | FLAG_SSL: ${{ matrix.flag_ssl }} 32 | FLAG_DEBUG: ${{ matrix.flag_debug }} 33 | FLAG_MEMPROF: ${{ matrix.flag_memprof }} 34 | 35 | - name: Configure flags 36 | run: ./configure --prefix="$PWD/fuzzpre" $FLAG_SSL $FLAG_MEMPROF $FLAG_DEBUG 37 | env: 38 | CC: ${{ matrix.compiler }} 39 | FLAG_SSL: ${{ matrix.flag_ssl }} 40 | FLAG_DEBUG: ${{ matrix.flag_debug }} 41 | FLAG_MEMPROF: ${{ matrix.flag_memprof }} 42 | 43 | - name: Clean up build 44 | run: make clean 45 | 46 | - name: Compile 47 | run: make -j$(nproc) 48 | 49 | - name: Install 50 | run: make install 51 | 52 | - name: Compile documentation 53 | run: make help 54 | 55 | - name: Run tests 56 | run: cd tests && python3 -m unittest -b 57 | 58 | # Travis CI migration notes 59 | # 60 | # Originally had to add these packages: 61 | # * libssl-dev (for OpenSSL support) 62 | # * python3-yaml (for tests) 63 | # 64 | # GitHub Actions has these by default 65 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/30.m: -------------------------------------------------------------------------------- 1 | ( cmd-@doing ver 1.2 2 | version 1.0 created by Whitefire. 3 | version 1.1 modified by Kimi. 4 | clears doing on logout. 5 | version 1.2 modified by Foxen. 6 | doesn't clear doing unless you logged out for longer than 20 minutes. 7 | ) 8 | 9 | $version 1.2 10 | 11 | : add-doing (s -- ) 12 | dup strlen 40 > 13 | if 14 | 40 strcut strlen 15 | "Warning: " swap dup 1 > 16 | if 17 | intostr strcat " characters" strcat 18 | else 19 | intostr strcat " character" strcat 20 | then 21 | " lost." strcat tell 22 | then 23 | me @ "_/do" rot 0 addprop 24 | me @ "Set." notify 25 | ; 26 | 27 | : cmd-@doing ( s -- ) 28 | strip 29 | dup not 30 | if 31 | pop 32 | me @ "You are currently doing: " me @ "_/do" getpropstr strcat notify 33 | exit 34 | then 35 | dup tolower "#c" 2 strncmp not 36 | if 37 | pop 38 | me @ "_/do" remove_prop 39 | me @ "Cleared." notify 40 | else 41 | add-doing 42 | then 43 | ; 44 | 45 | : clear-doing ( -- ) 46 | me @ "_/do" remove_prop 47 | ; 48 | 49 | : main ( s -- ) 50 | command @ "Queued event." stringcmp not 51 | if 52 | pop 53 | me @ awake? not (awake? returns number of connections player has) 54 | if (player disconected. has 0 connections) 55 | me @ "@/doingpid" "" pid addprop (remember the pid, fluke) 56 | 20 60 * sleep (sleep 20 minutes) 57 | me @ "@/doingpid" remove_prop (clear the pid) 58 | clear-doing 59 | exit 60 | else (player connected. >=1 connections) 61 | me @ "@/doingpid" getpropval 62 | dup if (there's a logout process to nuke) 63 | dup ispid? if (just make SURE that it's still there) 64 | kill pop (kill it if it is.) 65 | then 66 | me @ "@/doingpid" remove_prop (clear the logout pid) 67 | then 68 | then 69 | exit 70 | then 71 | cmd-@doing 72 | ; 73 | -------------------------------------------------------------------------------- /tests/command-cases/p_array.yml: -------------------------------------------------------------------------------- 1 | - name: simple-array-notify 2 | setup: | 3 | @program test.muf 4 | i 5 | : main { "Test 0" "Test 1" "Test 2" "Test 3" }list { me @ }list array_notify ; 6 | . 7 | c 8 | q 9 | @act test=here 10 | @link test=test.muf 11 | commands: | 12 | test 13 | expect: | 14 | Test 0 15 | Test 1 16 | Test 2 17 | Test 3 18 | 19 | - name: array-notify-nothing 20 | setup: | 21 | @program test.muf 22 | i 23 | : main { "Test 0" "Test 1" "Test 2" "Test 3" }list { #-1 }list array_notify ; 24 | . 25 | c 26 | q 27 | @act test=here 28 | @link test=test.muf 29 | commands: | 30 | test 31 | expect: 32 | - "Program Error" 33 | 34 | - name: array-notify-bad 35 | setup: | 36 | @program test.muf 37 | i 38 | : main { "Test 0" "Test 1" "Test 2" "Test 3" }list { #-1000 }list array_notify ; 39 | . 40 | c 41 | q 42 | @act test=here 43 | @link test=test.muf 44 | commands: | 45 | test 46 | expect: 47 | - "Program Error" 48 | 49 | - name: array-notify-remote 50 | setup: | 51 | @dig NewPlayerRoom==newplayerroom 52 | @program test.muf 53 | i 54 | : main { "Test 0" "Test 1" "Test 2" "Test 3" }list { #1 }list array_notify ; 55 | . 56 | c 57 | q 58 | @act test=#0 59 | @link test=test.muf 60 | @pcreate OwnerPlayer=foo 61 | @chown test.muf=OwnerPlayer 62 | @set test.muf=1 63 | @set *OwnerPlayer=1 64 | @tel *OwnerPlayer=$newplayerroom 65 | @force *OwnerPlayer=test 66 | commands: | 67 | ex test.muf=.debug/errcount 68 | expect: 69 | - "int /.debug/errcount:1" 70 | 71 | - name: array-compare-cycle 72 | setup: | 73 | @program test.muf 74 | i 75 | : main 76 | { 1 2 3 }list ARRAY_PIN var! x 77 | { 4 5 6 }list ARRAY_PIN var! y 78 | x @ y @ 0 ARRAY_SETITEM POP 79 | y @ x @ 0 ARRAY_SETITEM POP 80 | x @ y @ ARRAY_COMPARE 81 | 0 = intostr me @ swap notify 82 | ; 83 | . 84 | c 85 | q 86 | @act test=here 87 | @link test=test.muf 88 | commands: | 89 | test 90 | expect: 91 | - "0" 92 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/77.m: -------------------------------------------------------------------------------- 1 | ( cmd-@mpi+ 1.2 by Natasha@HLM 2 | 3 | This program {C} 1998-2002 Natasha O'Brien, and is released under 4 | the GNU General Public License. https://www.gnu.org/copyleft/gpl.html 5 | for the license agreement. 6 | 7 | __version history 8 | 1.0, circa 1998: first version 9 | 1.1, 28 May 2000: Modified to support Jaffa's '@mpi #null' syntax for quiet 10 | parsing; commented, better spacing. 11 | 1.2, 28 May 2002: Added Fuzzball support. 12 | 1.3, 6 June 2002: Added wizards-only @wmpi for executing blessed MPI. 13 | ) 14 | 15 | lvar v_loud? 16 | : main ( str -- } Parses str for MPI and displays the result. ) 17 | 18 | ( The program uses two display sections with the parsing in the middle, 19 | so if the code gets an error, we already displayed what they typed, so 20 | if the user typoed or something, they can see. ) 21 | 22 | command @ "do" stringcmp not var! v_do? 23 | 24 | ( Should we be quiet? ) 25 | dup if dup "#null " stringpfx else 0 then if 26 | ( Strip out the '#null ' if it was there. ) 27 | 6 strcut swap pop ( str ) 28 | 0 ( str boolLoud? ) 29 | else 30 | command @ tolower "q" instr v_do? @ or not ( str boolLoud? ) 31 | then ( str boolLoud? ) 32 | ( Remember for when we need to Result:. ) 33 | dup v_loud? ! ( str boolLoud? ) 34 | if ( str ) 35 | "Command: \"" over strcat "\"" strcat tell ( str ) 36 | then ( str ) 37 | 38 | me @ "_temp/mpi" rot setprop ( ) 39 | command @ "@wmpi" strcmp if 0 else me @ "wizard" flag? then if ( ) 40 | me @ "_temp/mpi" blessprop ( ) 41 | then ( ) 42 | me @ "_temp/mpi" ( db str ) 43 | $def parsempi \parseprop 44 | ( Parse! ) 45 | "(" command @ strcat ")" strcat 0 ( db strMpi strHow intDelay ) 46 | parsempi ( str' ) 47 | 48 | v_do? @ if 49 | dup if 50 | me @ over force 51 | else 52 | "Nothing to do." tell 53 | then 54 | then ( str' ) 55 | 56 | ( Display the result if we didn't get an error. ) 57 | v_loud? @ if ( str' ) 58 | " Result: \"" over strcat "\"" strcat tell ( ) 59 | then ( str' ) 60 | 61 | pop ( ) 62 | 63 | ; 64 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/83.m: -------------------------------------------------------------------------------- 1 | ( cmd-@teleport by Natasha@HLM 2 | A simple @teleport command for Fuzzball 6, thanks to the magic of exceptions. 3 | 4 | You can teleport anything anywhere as long as it's within the rules of the 5 | "moveto" primitive. Type "man moveto" to see the three rules. Unfortunately 6 | this means wizards can't @teleport things willy-nilly; to do that, they 7 | must type "!@tel" to use the in-server @teleport command. On HLM we decided 8 | that's actually a good thing, so there you go. 9 | 10 | Since the program's protections are based on the limits of the moveto prim, 11 | the program should NOT be set above M2, including W. Sorry, you can't 12 | customize the permission-related error messages: they're generated by 13 | Fuzzball itself. 14 | 15 | Copyright 2002 Natasha O'Brien. Copyright 2002 Here Lie Monsters. 16 | "@view $box/mit" for licensing information. 17 | ) 18 | $author Natasha O'Brien 19 | $version 1.001 20 | $note A simple @teleport command for Fuzzball 6, using exceptions. 21 | 22 | : rtn-match ( str -- db ) 23 | dup "#" stringpfx if ( str ) 24 | stod ( db ) 25 | else ( str ) 26 | match ( db ) 27 | then 28 | ; 29 | 30 | : main ( str -- ) 31 | dup not if pop .showhelp exit then ( str ) 32 | dup strip "#help" stringcmp not if pop .showhelp exit then ( str ) 33 | 34 | "=" "" tokensplit pop ( strY strZ ) 35 | 36 | ( If '@tel foo', assume 'me=foo' instead. ) 37 | dup not if pop "me" swap then ( strY strZ ) 38 | 39 | 1 2 1 for pop ( strY strZ ) 40 | dup rtn-match dup ok? not if ( strY strZ dbZ ) 41 | pop "I don't know what '%s' is." fmtstring tell ( strY ) 42 | pop exit ( ) 43 | then swap pop ( strY dbZ ) 44 | ( At this point we can do it again, only with dbZ for strY and strY for strZ. ) 45 | swap 46 | repeat ( dbY dbZ ) 47 | 48 | ( Do extra checks here. ) 49 | 50 | 0 try 51 | over over moveto ( dbY dbZ ) 52 | catch ( dbY dbZ strErr ) 53 | swap rot ( strErr dbZ dbY ) 54 | "Could not teleport %D to %D: %s" fmtstring tell ( ) 55 | exit ( ) 56 | endcatch ( dbY dbZ ) 57 | swap "Teleported %D to %D." fmtstring tell 58 | ; 59 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/58.m: -------------------------------------------------------------------------------- 1 | ( cmd-ignore by Natasha@HLM 2 | Adds to, removes from, and displays your in-server ignore list. 3 | 4 | Copyright 2002 Natasha O'Brien. Copyright 2002 Here Lie Monsters. 5 | "@view $box/mit" for license information. 6 | ) 7 | $author Natasha O'Brien 8 | $version 1.0 9 | $note Adds to, removes from, and displays your in-server ignore list. 10 | 11 | $include $lib/match 12 | : main ( str -- ) 13 | ( To whom are we doing things? ) 14 | strip dup if ( str ) 15 | 16 | dup "#" stringpfx if ( str ) 17 | pop .showhelp exit ( ) 18 | then ( str ) 19 | 20 | " " explode_array ( arrNames ) 21 | 0 array_make dup rot ( arrAdd arrDel arrNames ) 22 | foreach swap pop ( arrAdd arrDel strName ) 23 | dup not if pop continue then ( arrAdd arrDel strName ) 24 | 25 | dup "!" stringpfx if 1 else 0 then strcut ( arrAdd arrDel strDel? strName ) 26 | noisy_pmatch dup ok? not if pop pop continue then ( arrAdd arrDel strDel? db ) 27 | 28 | ( Add to which list? ) 29 | swap if ( arrAdd arrDel db ) 30 | swap array_appenditem ( arrAdd arrDel ) 31 | else 32 | rot array_appenditem swap ( arrAdd arrDel ) 33 | then ( arrAdd arrDel ) 34 | repeat ( arrAdd arrDel ) 35 | 36 | ( Anyone to act upon? ) 37 | over over or not if ( arrAdd arrDel ) 38 | "No one to ignore. Try 'ignore #help' for help." tell 39 | then ( arrAdd arrDel ) 40 | 41 | ( Are we actually 'adding to the unignore list?' ) 42 | command @ tolower "un" stringpfx if swap then ( arrAdd arrDel ) 43 | 44 | foreach swap pop ( arrAdd db ) 45 | me @ over ignore_del ( arrAdd db ) 46 | "%D unignored." fmtstring tell ( arrAdd ) 47 | repeat ( arrAdd ) 48 | 49 | foreach swap pop ( db ) 50 | me @ over ignore_add ( db ) 51 | "%D ignored." fmtstring tell ( ) 52 | repeat ( ) 53 | 54 | else 55 | ( View ignore list. ) 56 | "" me @ array_get_ignorelist foreach swap pop ( strList db ) 57 | name ( strList strDb ) 58 | ", " swap strcat strcat ( strList ) 59 | repeat ( strList ) 60 | 2 strcut swap pop ( strList ) 61 | "You are globally ignoring: " swap strcat tell ( ) 62 | then ( ) 63 | ; 64 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/87.m: -------------------------------------------------------------------------------- 1 | ( cmd-ansi.muf for Fuzzball 6 by Natasha@HLM 2 | 3 | Copyright 2002 Natasha@HLM. Copyright 2002 Here Lie Monsters. 4 | "@view $box/mit for license information. 5 | ) 6 | 7 | : do-core ( strOther strMsgdir strFlag -- ) 8 | me @ swap set ( strOther strMsgdir ) 9 | 10 | prog swap array_get_proplist ( strOther arr ) 11 | random over array_count % ( strOther arr intKey ) 12 | array_getitem ( strOther str ) 13 | swap command @ " '%s %s' to revert." fmtstring strcat 14 | tell 15 | ; 16 | : do-on "off" "_msg/on" "c" do-core ; 17 | : do-off "on" "_msg/off" "!c" do-core ; 18 | 19 | $define dict_commands { 20 | "on" 'do-on 21 | "off" 'do-off 22 | }dict $enddef 23 | 24 | : do-pattern ( str -- } With the given string yielding special codes. ) 25 | { 26 | "\[[1;30m>\[[0;37m>\[[1;37m> 0 1 2 3 4 5 6 7 \[[1m\[[31mA\[[32mN\[[33mS\[[35mI\[[37m guide" ( strHead ) 27 | " \[[30mblack \[[31mred \[[32mgreen \[[33myellow \[[34mblue \[[35mmagenta \[[36mcyan \[[37white " ( strHead str ) 28 | 4 rotate dup if textattr else pop then ( strHead str ) 29 | dup "\[[1;30m>\[[0;37m>\[[1;37m> \[[0m" swap strcat swap "\[[1;30m>\[[0;37m>\[[1;37m> " swap strcat ( strHead strBold strDim ) 30 | "\[[1;30m>\[[0;37m>\[[1;37m> ansi [on|off] toggle your viewing of color" 31 | "\[[1;30m>\[[0;37m>\[[1;37m> ansi see pattern with for background" 32 | }list { me @ }list array_notify 33 | ; 34 | 35 | : main ( str -- ) 36 | strip tolower 37 | dup "#" stringpfx if 1 strcut swap pop then ( str ) 38 | 39 | ( Is it a command? ) 40 | 0 try ( str ) 41 | dict_commands over array_getitem ( str adr ) 42 | execute exit ( str ) 43 | catch pop endcatch ( str ) 44 | 45 | ( No, not a command. Is it a background color code? ) 46 | 0 try ( str ) 47 | { 48 | "" "" 49 | "black" "bg_black" 50 | "red" "bg_red" 51 | "yellow" "bg_yellow" 52 | "green" "bg_green" 53 | "cyan" "bg_cyan" 54 | "blue" "bg_blue" 55 | "magenta" "bg_magenta" 56 | "white" "bg_white" 57 | }dict over array_getitem ( str strColor ) 58 | do-pattern exit ( str ) 59 | catch pop endcatch ( str ) 60 | 61 | ( No. Is it nothing? ) 62 | "I don't know what you mean by '%s'." fmtstring tell ( ) 63 | ; 64 | -------------------------------------------------------------------------------- /scripts/trigger-dump.muf: -------------------------------------------------------------------------------- 1 | (* 2 | * trigger-dump.muf 3 | * 4 | * This is the MUF companion to trigger-dump.py that waits for an MCP 5 | * event, triggers a dump, then returns an MCP-event when the dump is 6 | * complete. 7 | * 8 | * It is not part of the regular distribution because it requires some 9 | * configuration. PLEASE change the password in this file to something 10 | * that is unique to your MUCK, otherwise anyone with access to the 11 | * fuzzball source [i.e. everyone] can just dump your database constantly. 12 | * 13 | * This program should be set 'A' for autorun. 14 | * 15 | * If you are also using mcp-extern.muf, you can easily merge this code 16 | * into that and have 1 listener MUF instead of 2 :] 17 | * 18 | * - tanabi 19 | *) 20 | 21 | $def AUTHTOKEN "change-me-please" 22 | $def ALLOWED_HOSTS "::1" "localhost" "127.0.0.1" 23 | 24 | : check_auth[ int:dscr dict:args -- int:is_ok ] 25 | { ALLOWED_HOSTS }list dscr @ descrhost 26 | array_findval not if 0 exit then 27 | 28 | args @ "auth" [] 29 | 30 | dup array? not if 31 | pop 0 exit 32 | then 33 | 34 | 0 [] 35 | AUTHTOKEN strcmp not 36 | ; 37 | 38 | (* Keep track of the descriptor that did the dumping so we can notify them *) 39 | lvar dumping_descr 40 | 41 | : do_dump[ int:dscr dict:args -- ] 42 | dscr @ dumping_descr ! 43 | DUMP not if 44 | dscr @ [] "org-fuzzball-dump" "dump" { 45 | "failed" "Already Dumping" 46 | }dict mcp_send 47 | -1 dumping_descr ! 48 | then 49 | ; 50 | 51 | : report_dump ( -- ) 52 | dumping_descr @ 0 < if 53 | (* This was probably an auto-dump *) 54 | exit 55 | then 56 | 57 | dumping_descr @ "org-fuzzball-dump" "dump" { 58 | "success" "Dump Finished" 59 | }dict mcp_send 60 | 61 | -1 dumping_descr ! 62 | ; 63 | 64 | : main ( s -- ) 65 | pop 66 | "org-fuzzball-dump" 1.0 1.0 MCP_REGISTER_EVENT 67 | 68 | -1 dumping_descr ! 69 | 70 | begin 71 | { 72 | "MCP.org-fuzzball-dump-dump" 'do_dump 73 | "DUMP" 'report_dump 74 | }dict 75 | 76 | dup array_keys array_make 77 | event_waitfor var! event var! ctx 78 | 79 | event @ [] dup if 80 | (* For DUMP, this will be an integer 1 *) 81 | ctx @ int? if 82 | execute (* Run report dump *) 83 | else 84 | ctx @ "descr" [] 85 | ctx @ "args" [] 86 | over over check_auth if 87 | rot execute 88 | else 89 | pop pop pop 90 | then 91 | then 92 | else 93 | pop 94 | then 95 | repeat 96 | ; 97 | -------------------------------------------------------------------------------- /auto/build-demo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # 3 | # This python script uses the Fuzzball python library to initialize the demo 4 | # MUCK database assuming a fresh advancedb install. 5 | # 6 | # This specifically targets muck.fuzzball.org at this time and is a way 7 | # for FB developers to add to the spinup process. 8 | 9 | from pyfuzzball.base import FuzzballBase 10 | 11 | # Load password from a file 12 | pw = None 13 | 14 | with open('pw-file.txt', 'r') as i: 15 | pw = i.readline().strip() 16 | 17 | conn = FuzzballBase("muck.fuzzball.org", 4202, True, True) 18 | conn.login("One", "potrzebie") 19 | conn.write("@password potrzebie=%s\r\n" % pw) 20 | conn.write("@tune autolink_actions=no\r\n") 21 | conn.write("@tune registration=no\r\n") 22 | conn.write("lsedit #0=welcome\r\n") 23 | conn.write( 24 | ".del 1 100\r\n" 25 | " ,... ,, ,, ,,\r\n" 26 | " .d' \"\" *MM `7MM `7MM\r\n" 27 | " dM` MM MM MM \r\n" 28 | " mMMmm`7MM `7MM M\"\"\"MMV M\"\"\"MMV MM,dMMb. ,6\"Yb. MM MM\r\n" 29 | " MM MM MM ' AMV ' AMV MM `Mb 8) MM MM MM\r\n" 30 | " MM MM MM AMV AMV MM M8 ,pm9MM MM MM\r\n" 31 | " MM MM MM AMV , AMV , MM. ,M9 8M MM MM MM\r\n" 32 | " .JMML. `Mbod\"YML.AMMmmmM AMMmmmM P^YbmdP' `Moo9^Yo..JMML..JMML.\r\n" 33 | " \r\n" 34 | " `7MMM. ,MMF'`7MMF' `7MF' .g8\"\"\"bgd `7MMF' `YMM'\r\n" 35 | " MMMb dPMM MM M .dP' `M MM .M'\r\n" 36 | " M YM ,M MM MM M dM' ` MM .d\"\r\n" 37 | " M Mb M' MM MM M MM MMMMM.\r\n" 38 | " M YM.P' MM MM M MM. MM VMA\r\n" 39 | " M `YM' MM YM. ,M `Mb. ,' MM `MM.\r\n" 40 | " .JML. `' .JMML. `bmmmmd\"' `\"bmmmd' .JMML. MMb.\r\n" 41 | " \r\n" 42 | " Development Port\r\n" 43 | " \r\n" 44 | "To connect to your character use 'connect '\r\n" 45 | "To create a new character use 'create '\r\n" 46 | " \r\n" 47 | "'WHO' and 'help' also work in this context.\r\n" 48 | ".end\r\n" 49 | ) 50 | conn.write("@chown #0=keeper\r\n") 51 | conn.write("@pcreate Tanabi=%s\r\n" % pw) 52 | conn.write("@set *Tanabi=W\r\n") 53 | conn.quit() 54 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/6.m: -------------------------------------------------------------------------------- 1 | ( PROPS Library -- Contains useful property handling routines. 2 | 3 | setpropstr [dbref propname strval -- ] 4 | sets a property, or removes it if the string is null. 5 | 6 | envprop [startdbref propname -- stringval] 7 | searches down the environment tree from the given object, looking for 8 | a property with the given name. Returns it's value, or a null string 9 | if it wasn't found. 10 | 11 | envsearch [startdbref propname -- locationdbref] 12 | Also searches down the envtree for the given property, but returns the 13 | dbref of the object it was found on instead of the string value. Returns 14 | #-1 if it cannot find the property. 15 | 16 | locate-prop [startdbref propname -- locationdbref] 17 | Given a property name and dbref, finds the property, whether on the dbref 18 | itself, an environment of the dbref, or a proploc of the dbref. If none, 19 | returns #-1. 20 | ) 21 | 22 | $doccmd @list __PROG__=!@1-20 23 | 24 | : setpropstr (dbref propname strval -- ) 25 | dup not if 26 | pop remove_prop 27 | else 28 | 0 addprop 29 | then 30 | ; 31 | 32 | : envprop (startdbref propname -- stringvalue) 33 | envpropstr swap pop 34 | ; 35 | 36 | : envsearch (startdbref propname -- locationdbref) 37 | envpropstr pop 38 | ; 39 | 40 | : proplocsearch ( startdbref propname -- locationdbref ) 41 | over swap ( d d s ) 42 | me @ "search" remove_prop 43 | begin over ok? while 44 | over over getpropstr if 45 | me @ "search" remove_prop 46 | pop swap pop exit ( d ) 47 | then 48 | over intostr "search/" swap strcat me @ swap getpropstr if 49 | me @ "search" remove_prop 50 | pop pop intostr 51 | "Error: loop in proploc found at #" swap strcat tell 52 | #-1 exit 53 | then 54 | over intostr "search/" swap strcat me @ swap "yes" 0 addprop 55 | swap "_proploc" getpropstr dup if ( d s d' ) 56 | atoi dbref swap ( d d' s ) 57 | else 58 | pop #-1 swap 59 | then 60 | repeat 61 | me @ "search" remove_prop 62 | pop pop pop #-1 exit 63 | ; 64 | 65 | : locate-prop ( d s -- d' ) 66 | over ok? not over not or if 67 | pop pop #-1 exit 68 | then 69 | over over proplocsearch dup ok? if ( d s d' ) 70 | rot rot pop pop exit 71 | then 72 | pop envsearch 73 | ; 74 | 75 | public envprop $libdef envprop 76 | public envsearch $libdef envsearch 77 | public locate-prop $libdef locate-prop 78 | public setpropstr $libdef setpropstr 79 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/21.m: -------------------------------------------------------------------------------- 1 | $version 1.4 2 | 3 | $include $lib/editor 4 | $include $lib/lmgr 5 | 6 | $def LMGRgetcount lmgr-getcount 7 | $def LMGRgetrange lmgr-getrange 8 | $def LMGRputrange lmgr-putrange 9 | $def LMGRdeleterange lmgr-deleterange 10 | 11 | : LMGRdeletelist 12 | over over LMGRgetcount 13 | 1 4 rotate 4 rotate LMGRdeleterange 14 | ; 15 | 16 | : LMGRgetlist 17 | over over LMGRgetcount 18 | rot rot 1 rot rot 19 | LMGRgetrange 20 | ; 21 | 22 | : lsedit-loop ( listname dbref {rng} mask currline cmdstr -- ) 23 | EDITORloop 24 | dup "save" stringcmp not if 25 | pop pop pop pop 26 | 3 pick 3 + -1 * rotate 27 | over 3 + -1 * rotate 28 | dup 5 + pick over 5 + pick 29 | over over LMGRdeletelist 30 | 1 rot rot LMGRputrange 31 | 4 pick 4 pick LMGRgetlist 32 | dup 3 + rotate over 3 + rotate 33 | "< List saved. >" tell 34 | "" lsedit-loop exit 35 | then 36 | dup "abort" stringcmp not if 37 | "< list not saved. >" tell 38 | pop pop pop pop pop pop pop pop pop exit 39 | then 40 | dup "end" stringcmp not if 41 | pop pop pop pop pop pop 42 | dup 3 + rotate over 3 + rotate 43 | over over LMGRdeletelist 44 | 1 rot rot LMGRputrange 45 | "< list saved. >" tell exit 46 | then 47 | ; 48 | 49 | : cmd-lsedit 50 | "me" match me ! 51 | "=" split strip 52 | dup not if 53 | "You must specify a listname. Syntax: lsedit =" tell 54 | pop pop exit 55 | then 56 | "/" swap strcat 57 | begin dup "//" instr while "/" "//" subst repeat 58 | dup "/@" instr 59 | over "/~" instr or 60 | me @ "wizard" flag? not and if 61 | "Permission denied." tell 62 | pop pop exit 63 | then 64 | swap strip 65 | dup not if 66 | "You must specify an object. Syntax: lsedit =" tell 67 | pop pop exit 68 | then 69 | match dup not if pop 70 | "I don't know what object you mean. Syntax: lsedit =" tell 71 | pop exit 72 | else dup #-2 dbcmp if pop 73 | "I don't know which one you mean. Syntax: lsedit =" tell 74 | pop exit 75 | then then 76 | me @ over owner dbcmp not 77 | me @ "w" flag? not and if 78 | pop pop "Permission denied." tell exit 79 | then 80 | "< Welcome to the list editor. You can get help by entering '.h' >" 81 | tell 82 | "< '.end' will exit and save the list. '.abort' will abort any changes. >" 83 | tell 84 | "< To save changes to the list, and continue editing, use '.save' >" 85 | tell 86 | read_wants_blanks 87 | over over LMGRgetlist 88 | "save" 1 ".i $" lsedit-loop 89 | ; 90 | -------------------------------------------------------------------------------- /include/mcppkg.h: -------------------------------------------------------------------------------- 1 | /** @file mcppkg.h 2 | * 3 | * Header for built-in MCP packages. 4 | * Specification is here: https://www.moo.mud.org/mcp/ 5 | * 6 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 7 | */ 8 | 9 | #ifndef MCPPKG_H 10 | #define MCPPKG_H 11 | 12 | #include "mcp.h" 13 | 14 | /** 15 | * Implementation of the simpleedit MCP command 16 | * 17 | * reference is in the format objnum.category.misc where objnum is the 18 | * object reference, and category can be one of the following: 19 | * prop to set a property named by misc. 20 | * proplist to store a string proplist named by misc. 21 | * prog to set the program text of the given object. Ignores misc. 22 | * sysparm to set an \@tune value. Ignores objnum. 23 | * user to return data to a muf program. 24 | * 25 | * If the category is prop, then it accepts the following types: 26 | * string to set the property to a string value. 27 | * string-list to set the property to a multi-line string value. 28 | * integer to set the property to an integer value. 29 | * 30 | * Any other values are ignored. 31 | * 32 | * @param mfr the frame 33 | * @param msg the message to process 34 | * @param ver the MCP version at play 35 | * @param context this is always NULL for this call 36 | */ 37 | void mcppkg_simpleedit(McpFrame * mfr, McpMesg * msg, McpVer ver, void *context); 38 | 39 | /** 40 | * Implementation of the org-fuzzball-languages MCP package 41 | * 42 | * Currently only mentions MUF. Uses the message 'request' to list 43 | * supported languages. 44 | * 45 | * @param mfr the frame 46 | * @param msg the mcp message 47 | * @param ver the version being requested 48 | * @param context this is always NULL for this call 49 | */ 50 | void mcppkg_languages(McpFrame * mfr, McpMesg * msg, McpVer ver, void *context); 51 | 52 | /** 53 | * Implementation of the org-fuzzball-help MCP package 54 | * 55 | * This lets you request different help files. 'topic' is the help item 56 | * requested and 'type' is either mpi, help, news, or man. 57 | * 58 | * Returns 'error' message if not found. 59 | * 60 | * @param mfr the frame 61 | * @param msg the mcp message 62 | * @param ver the version being requested 63 | * @param context this is always NULL for this call 64 | */ 65 | void mcppkg_help_request(McpFrame * mfr, McpMesg * msg, McpVer ver, void *context); 66 | 67 | /** 68 | * Send an MCP error message using the org-fuzzball-notify package 69 | * 70 | * Sends it to the given frame, with arguments 'topic' and 'text' sent 71 | * and using the -error message. 72 | * 73 | * @param mfr the frame 74 | * @param topic the topic to use 75 | * @param text the text to send 76 | */ 77 | void show_mcp_error(McpFrame * mfr, const char *topic, const char *text); 78 | 79 | #endif /* !MCPPKG_H */ 80 | -------------------------------------------------------------------------------- /tests/command-cases/create.yml: -------------------------------------------------------------------------------- 1 | - name: link 2 | setup: | 3 | @dig IdTwo 4 | @open foo;bar=#2=property 5 | commands: | 6 | ex me=_reg/property 7 | ex bar 8 | expect: 9 | - "Destination: IdTwo.*" 10 | - "- ref /_reg/property:foo;bar\\(#3" 11 | 12 | - name: link-multilink 13 | setup: | 14 | @dig IdTwo 15 | @create IdThree 16 | @open foo;bar=#2;#3=property 17 | commands: | 18 | ex bar 19 | ex me=_reg/property 20 | expect: 21 | - "Destination: IdTwo.*" 22 | - "Destination: IdThree.*" 23 | - "- ref /_reg/property:foo;bar\\(#4" 24 | 25 | - name: clone 26 | setup: | 27 | @create Foo 28 | @desc Foo={null:to preserve} 29 | @propset Foo=dbref:~protectedprop:#0 30 | @propset Foo=lock:_lockprop:me 31 | @set Foo=@secretprop:secretvalue 32 | @set Foo=_proplist/a:foo 33 | @set Foo=_proplist/b:bar 34 | @clone Foo 35 | commands: | 36 | ex #3 37 | ex #3=/ 38 | ex #3=_proplist/ 39 | expect: 40 | - "Type: THING" 41 | - "Foo\\(#3" 42 | - "{null:to preserve}" 43 | - "- str /@secretprop:secretvalue" 44 | - "- ref /~protectedprop:Room Zero" 45 | - "- lok /_lockprop:One" 46 | - "- str /_proplist/a:foo" 47 | - "- str /_proplist/b:bar" 48 | 49 | - name: attach 50 | commands: | 51 | @act foo=me 52 | @attach foo=#0 53 | ex foo 54 | expect: | 55 | Source: Room Zero.* 56 | 57 | - name: dig-simple 58 | setup: | 59 | @dig IdTwo 60 | commands: | 61 | ex #2 62 | expect: 63 | - "IdTwo\\(#2" 64 | - "Type: ROOM" 65 | 66 | - name: dig-parent 67 | setup: | 68 | @dig IdTwo==regtwo 69 | @dig IdThree=$regtwo=regthree 70 | commands: | 71 | ex $regthree 72 | expect: 73 | - "IdThree\\(#3" 74 | - "Parent: IdTwo" 75 | - "Type: ROOM" 76 | 77 | - name: dig-fail-badparent 78 | commands: | 79 | @dig IdTwo=badbadbad=regtwo 80 | ex $regtwo 81 | expect: 82 | - "I don't understand 'bad" 83 | - "Parent: Room Zero" 84 | 85 | - name: dig-fail-formatstringparent 86 | comment: regression for pull request 540 87 | commands: | 88 | @dig IdTwo=%n%n%n%n%n%n%n=regtwo 89 | ex $regtwo 90 | expect: 91 | - "I don't understand '%n" 92 | - "Parent: Room Zero" 93 | 94 | - name: program-ambiguous 95 | setup: | 96 | @program Foo program 1.muf 97 | q 98 | @program Foo program 2.muf 99 | q 100 | commands: | 101 | @program Foo 102 | expect: 103 | - "I don't know which 'Foo'" 104 | 105 | - name: program-ambiguous-fmtstring 106 | setup: | 107 | @program %n%n%n program 1.muf 108 | q 109 | @program %n%n%n program 2.muf 110 | q 111 | commands: | 112 | @program %n%n%n 113 | expect: 114 | - "I don't know which '%n%n%n'" 115 | -------------------------------------------------------------------------------- /tests/command-cases/p_regex.yml: -------------------------------------------------------------------------------- 1 | - name: regsplit-normal 2 | setup: | 3 | @program test.muf 4 | i 5 | : main 6 | "fooXbarYbazXquux" "X|Y" 0 regsplit 7 | { me @ }list array_notify 8 | ; 9 | . 10 | c 11 | q 12 | @act test=here 13 | @link test=test.muf 14 | @set test.muf=D 15 | commands: | 16 | test 17 | expect: | 18 | foo 19 | bar 20 | baz 21 | quux 22 | 23 | - name: regsplit-normal2 24 | setup: | 25 | @program test.muf 26 | i 27 | : main 28 | "fooXXbXarYXbazXXquux" "XX|Y" 0 regsplit 29 | { me @ }list array_notify 30 | ; 31 | . 32 | c 33 | q 34 | @act test=here 35 | @link test=test.muf 36 | @set test.muf=D 37 | commands: | 38 | test 39 | expect: | 40 | foo 41 | bXar 42 | Xbaz 43 | quux 44 | 45 | - name: regsplit-normal-with-empty 46 | setup: | 47 | @program test.muf 48 | i 49 | : main 50 | "fooXbarYbazXXYquux" "X|Y" 0 regsplit 51 | foreach swap pop ":" swap strcat me @ swap notify repeat 52 | ; 53 | . 54 | c 55 | q 56 | @act test=here 57 | @link test=test.muf 58 | commands: | 59 | test 60 | expect: | 61 | :foo 62 | :bar 63 | :baz 64 | : 65 | : 66 | :quux 67 | 68 | - name: regsplit_noempty-normal-with-empty 69 | setup: | 70 | @program test.muf 71 | i 72 | : main 73 | "fooXbarYbazXXYquux" "X|Y" 0 regsplit_noempty 74 | foreach swap pop ":" swap strcat me @ swap notify repeat 75 | ; 76 | . 77 | c 78 | q 79 | @act test=here 80 | @link test=test.muf 81 | commands: | 82 | test 83 | expect: | 84 | :foo 85 | :bar 86 | :baz 87 | :quux 88 | 89 | - name: regsplit-noempty-match-every-char 90 | setup: | 91 | @program test.muf 92 | i 93 | : main 94 | "abZcdZZef" "Z|" 0 regsplit_noempty 95 | { me @ }list array_notify 96 | ; 97 | . 98 | c 99 | q 100 | @act test=here 101 | @link test=test.muf 102 | @set test.muf=D 103 | commands: | 104 | test 105 | expect: | 106 | a 107 | b 108 | c 109 | d 110 | e 111 | f 112 | 113 | - name: regsplit-empty-match-every-char 114 | setup: | 115 | @program test.muf 116 | i 117 | : main 118 | "abZcdZZef" "Z|" 0 regsplit 119 | foreach 120 | swap pop (remove index) 121 | ":" swap strcat me @ swap notify 122 | repeat 123 | ; 124 | . 125 | c 126 | q 127 | @act test=here 128 | @link test=test.muf 129 | commands: | 130 | test 131 | expect: | 132 | : 133 | :a 134 | : 135 | :b 136 | : 137 | :c 138 | : 139 | :d 140 | : 141 | : 142 | :e 143 | : 144 | :f 145 | 146 | -------------------------------------------------------------------------------- /README_WINDOWS.md: -------------------------------------------------------------------------------- 1 | Building and Running Fuzzball on Windows 2 | =============== 3 | *For documentation and general help, see [the general README](README.md)* 4 | 5 | ## Running 6 | * Install the [32-bit Visual C++ Redistributable for Visual Studio 2019](https://www.microsoft.com/en-us/download/details.aspx?id=48145) (*Fuzzball currently does not support 64-bit*) 7 | * Pick the `x86` version, [or just use this direct link to `vc_redist.x86.exe`](https://aka.ms/vs/16/release/vc_redist.x86.exe) 8 | * Manage the server with ```restart.exe``` 9 | 10 | For a comprehensive guide to running a MUCK, check out [MINK - The Muck Information Kiosk](http://www.rdwarf.com/users/mink/muckman/). 11 | 12 | ### Quick-start 13 | * **Follow the build directions, or [download a pre-built package](README.md#downloads)** 14 | * Set up configuration in ```restart.ini``` 15 | ```bat 16 | cd "path\to\fuzzball\folder" 17 | restart -c 18 | ``` 19 | * Edit and save ```restart.ini``` with your options, e.g. with ```notepad restart.ini``` 20 | * If using SSL, save your certificate and key as ```data\server.pem```, or later configure ```@tune ssl_cert_file``` and ```@tune ssl_key_file``` 21 | * Start the server 22 | ```bat 23 | restart 24 | ``` 25 | 26 | ## Building 27 | Tools needed: 28 | * [Visual Studio 2015 or higher](https://www.visualstudio.com/downloads/download-visual-studio-vs) 29 | * [Conan.io package manager](https://www.conan.io/downloads), or a manually installed SSL library, e.g. [OpenSSL for Windows](https://wiki.openssl.org/index.php/Binaries) 30 | * Optionally, the [Git revision control system](https://git-scm.com/download/win) 31 | 32 | ### Get source 33 | * First time 34 | * Open a Git Bash shell in the desired folder (*if Windows Explorer integration is active, right-click, ```Git Bash```*) 35 | ```sh 36 | cd ~ # Or any other desired directory 37 | git clone https://github.com/fuzzball-muck/fuzzball.git 38 | cd fuzzball 39 | ``` 40 | * To update 41 | * Open a Git Bash shell 42 | ```sh 43 | cd ~/fuzzball # Same path as above, plus the 'fuzzball' directory 44 | git pull 45 | ``` 46 | * Or [download a zip archive from Github](https://github.com/fuzzball-muck/fuzzball/archive/master.zip) 47 | 48 | ### Configure 49 | *Use the Windows command prompt instead of Git Bash* 50 | * Set up Visual Studio environment variables 51 | * Use ```Program Files``` instead of ```Program Files (x86)``` if on a 32-bit machine 52 | * Fuzzball does not currently support compiling as 64-bit 53 | ```bat 54 | "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 55 | ``` 56 | * Set up dependencies with Conan.io 57 | ```bat 58 | conan install -s arch=x86 59 | set OPENSSLDIR=C:\path\to\fuzzball\bin 60 | ``` 61 | * *Or*, use a manually-installed version of OpenSSL 62 | ```bat 63 | set OPENSSLDIR=C:\path\to\openssl 64 | ``` 65 | 66 | ### Build 67 | ```bat 68 | nmake /f makefile.win 69 | ``` 70 | -------------------------------------------------------------------------------- /README_UNIX.md: -------------------------------------------------------------------------------- 1 | Building and Running Fuzzball on Unix 2 | =============== 3 | *For documentation and general help, see [the general README](README.md)* 4 | 5 | ## Building 6 | Tools needed: 7 | * Make, a C compiler, [PCRE library](https://pcre.org/), and friends 8 | * Optionally, an SSL library, e.g. [OpenSSL](https://openssl.org/) 9 | * Optionally, the Git revision control system 10 | 11 | For an Ubuntu system, apt-get install these packages 12 | ```sh 13 | build-essential # Make tools, compiler 14 | libpcre3-dev # PCRE headers 15 | libssl-dev # SSL library headers 16 | git # Git revision control system 17 | autoconf # Optional, to re-build configure 18 | automake # Optional, to re-build makefile 19 | autoconf-archive # Optional, to re-build configure 20 | ``` 21 | 22 | ### Get source 23 | * First time 24 | ```sh 25 | cd ~ # Or any other desired directory 26 | git clone https://github.com/fuzzball-muck/fuzzball.git 27 | cd fuzzball 28 | ``` 29 | * To update 30 | ```sh 31 | cd ~/fuzzball # Same path as above, plus the 'fuzzball' directory 32 | git pull 33 | ``` 34 | * Or [download a zip archive from Github](https://github.com/fuzzball-muck/fuzzball/archive/master.zip) 35 | 36 | ### Configure 37 | If you need to rebuild the configuration file (Because you have edited configure.in), you can use the following command: 38 | 39 | ```sh 40 | autoreconf 41 | ``` 42 | 43 | This is not typically needed. You can then continue to run configure thusly: 44 | 45 | ```sh 46 | ./configure --with-ssl # Or choose your own options 47 | ``` 48 | * See ```./configure --help``` 49 | * If needed, specify SSL headers via ```--with-ssl=/path/to/dir```, or PCRE headers via ```--with-pcre=/path/to/dir``` 50 | * When testing, use a different ```--prefix```, e.g. ```./configure --prefix="$HOME/fuzzball-test"``` 51 | * If using TLS, cat your certificate ```fullchain.pem``` and key ```privkey.pem``` into ```game/data/server.pem```, or later configure ```@tune ssl_cert_file``` and ```@tune ssl_key_file``` 52 | 53 | ### Build 54 | ```sh 55 | make clean && make 56 | make install 57 | make install-sysv-inits # Skip to not run at startup 58 | ``` 59 | 60 | ## Running 61 | For a comprehensive guide to running a MUCK, check out [MINK - The Muck Information Kiosk](http://www.rdwarf.com/users/mink/muckman/). 62 | 63 | ### Quick-start 64 | * **Follow the build directions above** 65 | * Copy the relevant databases (*alternatively, use ```fuzzball/scripts/fbmuck-add```*) 66 | ```sh 67 | FB_DIR="$(pwd)" # Directory containing Fuzzball 68 | PREFIX="." # If installing to a different prefix, set it here 69 | cp -r "$FB_DIR/game/." "$PREFIX/game" # Copy game information 70 | cp -r "$FB_DIR/dbs/starterdb/." "$PREFIX/game" # Copy database 71 | mv "$PREFIX/game/data/starterdb.db" "$PREFIX/game/data/std-db.db" # Rename database to standard 72 | ``` 73 | * Start Fuzzball 74 | ```sh 75 | /usr/local/sbin/fb-restart 76 | # If using a custom prefix, $PREFIX/sbin/fb-restart 77 | ``` 78 | -------------------------------------------------------------------------------- /include/debugger.h: -------------------------------------------------------------------------------- 1 | /** @file debugger.h 2 | * 3 | * This is the header file that declares the different functions that 4 | * support the MUF debugger. 5 | * 6 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 7 | */ 8 | 9 | #ifndef DEBUGGER_H 10 | #define DEBUGGER_H 11 | 12 | #include "config.h" 13 | 14 | #include "inst.h" 15 | #include "interp.h" 16 | 17 | /** 18 | * List program lines to a player 19 | * 20 | * This is used by the debugger for listing lines and for backtraces. 21 | * Uses the editor's list_program under the hood. 22 | * 23 | * @see list_program 24 | * 25 | * @param player the player to send the listing to 26 | * @param program the program to list 27 | * @param fr the running program frame 28 | * @param start the start line 29 | * @param end the end line 30 | */ 31 | void list_proglines(dbref player, dbref program, struct frame *fr, int start, int end); 32 | 33 | /** 34 | * Displays a MUF Backtrace message. 35 | * 36 | * This is used when a MUF program is aborted, if someone who has 'controls' 37 | * permissions was running it, or if you type 'where' in the debugger. 38 | * Shows a fairly straight forward backtrace, going 'count' deep. If 39 | * 'count' is 0, it will display up to STACK_SIZE depth. 40 | * 41 | * @param player the player getting the backtrace 42 | * @param program the program being backtraced 43 | * @param count the depth of the trace, or 0 for STACK_SIZE 44 | * @param fr the frame pointer 45 | */ 46 | void muf_backtrace(dbref player, dbref program, int count, struct frame *fr); 47 | 48 | /** 49 | * Implementation of the MUF debugger 50 | * 51 | * This implements the command parsing for the MUF debugger. It also clears 52 | * temporary bookmarks if this was triggered from a temporary one. 53 | * 54 | * This relies on some static globals, so it is not threadsafe. If the 55 | * 'prim' debugger command is ever used to trigger the MUF debugger somehow 56 | * in a recursive fashion, and then you call 'prim' again, it will probably 57 | * cause havock. 58 | * 59 | * @param descr the descriptor of the debugging player 60 | * @param player the debugging player 61 | * @param program the program we are debugging 62 | * @param text the input text from the user 63 | * @param fr the current frame pointer 64 | * @return boolean true if the program should exit, false if not 65 | */ 66 | int muf_debugger(int descr, dbref player, dbref program, const char *text, struct frame *fr); 67 | 68 | /** 69 | * This is for showing line listings in "instruction" format. 70 | * 71 | * This returns a single line of code's primitives. It uses a static buffer, 72 | * so be careful with it. Not multi-threaded. 73 | * 74 | * @param program the program to show listings for 75 | * @param pc the program counter where the listing starts 76 | * @param maxprims the maximum primitives 77 | * @param markpc do a special mark when listing the 'pc' line 78 | * @return pointer to static buffer containing primitives 79 | */ 80 | char *show_line_prims(dbref program, struct inst *pc, int maxprims, int markpc); 81 | 82 | #endif /* !DEBUGGER_H */ 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Fuzzball MUCK [![GNU/Linux Build Status][ci-linux-badge]](https://github.com/fuzzball-muck/fuzzball/actions/workflows/main.yml) [![Windows Build Status][ci-windows-badge]](https://ci.appveyor.com/project/fuzzball-muck/fuzzball/branch/master) [![FreeBSD Build Status][ci-freebsd-badge]](https://cirrus-ci.com/github/fuzzball-muck/fuzzball) 2 | =============== 3 | 4 | Fuzzball is a [MUCK](https://en.wikipedia.org/wiki/MUCK) server, an online text-based multi-user chat and roleplaying game. Multiple people may join, set up characters, talk, and interact, exploring and building a common world. Nearly every aspect of the game can be customized via [MPI-driven descriptions](https://www.fuzzball.org/docs/mpihelp.html) and [MUF programs](https://www.fuzzball.org/docs/mufman.html). 5 | 6 | ## Documentation 7 | 8 | * [Fuzzball website](https://www.fuzzball.org/) 9 | * [GitHub repository](https://github.com/fuzzball-muck/fuzzball/) 10 | * [A live version of the docs on GitHub](https://fuzzball-muck.github.io/fuzzball/) 11 | * [User commands](https://www.fuzzball.org/docs/muckhelp.html) 12 | * [MPI functions](https://www.fuzzball.org/docs/mpihelp.html) 13 | * [MUF reference](https://www.fuzzball.org/docs/mufman.html) 14 | * [MINK - The Muck Information Kiosk](https://fuzzball-muck.github.io/muckman/) 15 | 16 | Fuzzball also offers a built-in help system. Connect, then type ```help``` for guidance. 17 | 18 | ## Downloads 19 | * **Stable** 20 | * *Tested and supported, recommended for everyday usage* 21 | * **Unix**: download from [the Fuzzball homepage](https://www.fuzzball.org/), follow the steps in [the Unix README](README_UNIX.md#building), skipping *Get Source* 22 | * **Windows**: download from [the Fuzzball homepage](https://www.fuzzball.org/), follow the steps under *Running* in [the Windows README](README_WINDOWS.md#running) 23 | * **Development** 24 | * *Try out the latest features and help find issues, but if it breaks you get to keep all the pieces* 25 | * **Unix**: follow the steps in [the Unix README](README_UNIX.md#building). 26 | * **Windows**: download a pre-built package from [the Appveyor build artifacts page](https://ci.appveyor.com/project/fuzzball-muck/fuzzball/branch/master/artifacts), follow the steps under *Running* in [the Windows README](README_WINDOWS.md#running). 27 | 28 | ### Building and Running from Source 29 | * [Unix README](README_UNIX.md#building) 30 | * [Windows README](README_WINDOWS.md#building) 31 | 32 | ## Usage 33 | 34 | For a comprehensive guide to running a muck, check out [MINK - The Muck Information Kiosk](https://fuzzball-muck.github.io/muckman/). 35 | 36 | If you only need a quick test environment, read the instructions for your operating system in [Building and Running from Source](#building-and-running-from-source) right above. 37 | 38 | ## Feedback 39 | 40 | You can send bug reports, feature requests, or other general feedback to feedback@fuzzball.org 41 | 42 | [ci-linux-badge]: https://github.com/fuzzball-muck/fuzzball/actions/workflows/main.yml/badge.svg 43 | [ci-windows-badge]: https://ci.appveyor.com/api/projects/status/ktwrfcsjbv4xt3op/branch/master?svg=true&passingText=Windows%3A%20passing&pendingText=Windows%3A%20pending&failedText=Windows%3A%20failing 44 | [ci-freebsd-badge]: https://api.cirrus-ci.com/github/fuzzball-muck/fuzzball.svg 45 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/79.m: -------------------------------------------------------------------------------- 1 | ( cmd-@muf by Natasha@HLM 2 | Runs MUF code. A MUF version of @mpi. 3 | 4 | Copyright 2002 Natasha O'Brien. Copyright 2002 Here Lie Monsters. 5 | "@view $box/mit" for license information. 6 | ) 7 | $author Natasha O'Brien 8 | $note Runs MUF code you enter. A MUF version of @mpi. 9 | $version 1.0 10 | 11 | : rtn-pretty ( arr -- str } Return a prettily formatted string displaying all the contents of arr. ) 12 | "" swap ( str arr ) 13 | dup dictionary? var! isDict ( str arr ) 14 | 15 | foreach ( str ?key ?val ) 16 | ( Format a special type? ) 17 | dup string? if ( str ?key strVal ) 18 | "\\\"" "\"" subst 19 | "\"%s\"" fmtstring ( str ?key strVal ) 20 | then ( str ?key ?val ) 21 | dup dbref? if "%d" fmtstring then 22 | dup array? if rtn-pretty "{%s}" fmtstring then ( str ?key ?val ) 23 | 24 | swap isDict @ if 25 | ", %~:%~" 26 | else 27 | pop ", %~" 28 | then fmtstring ( str -str ) 29 | 30 | strcat ( str ) 31 | repeat ( str ) 32 | 2 strcut swap pop 33 | ; 34 | 35 | : main ( str -- ) 36 | 0 var! debug 37 | striplead dup "#" stringpfx if ( str ) 38 | 1 strcut swap pop ( str ) 39 | " " split swap ( str strCommand ) 40 | "debug" stringcmp if 41 | pop .showhelp exit ( ) 42 | else 43 | 1 debug ! ( str ) 44 | then ( str ) 45 | then ( str ) 46 | 47 | ( The user must be a player, and must have an Mlevel or be a Wizard {Quelled is OK}. ) 48 | me @ player? me @ mlevel me @ "truewizard" flag? or and not if ( str ) 49 | "@muf is only available to users with a MUCKer bit." tell 50 | pop exit ( ) 51 | then ( str ) 52 | 53 | ( Make a new program and set its contents. ) 54 | random intostr "@@muf.muf" strcat newprogram ( str dbProg ) 55 | swap var! programtext ( dbProg ) 56 | 57 | 0 try ( dbProg ) 58 | 59 | dup programtext @ ( dbProg dbProg str ) 60 | ": main %s ;" fmtstring 1 array_make program_setlines ( dbProg ) 61 | 62 | ( Program saved. Compile it. ) 63 | dup 1 compile if ( dbProg ) 64 | 65 | ( Yay, compiled! Set it D if desired. ) 66 | debug @ if dup "d" set then 67 | 68 | ( Run. ) 69 | depth var! howDeep 70 | "" var! resultStr 71 | 0 var! error 72 | 0 try ( dbProg ) 73 | dup call ( dbProg ... ) 74 | catch ( dbProg strErr ) 75 | "Your program had an error: %s" fmtstring tell ( dbProg ) 76 | 1 error ! ( dbProg ) 77 | endcatch ( dbProg [...] ) 78 | 79 | error @ not if ( dbProg ... ) 80 | depth howDeep @ - array_make rtn-pretty ( dbProg str ) 81 | "Result: " swap strcat ( dbProg strMsg ) 82 | tell ( dbProg ) 83 | then ( dbProg ) 84 | 85 | else ( dbProg ) 86 | ( Boo, didn't compile. ) 87 | "There were compile errors, shown above." tell 88 | then ( dbProg ) 89 | 90 | catch ( dbProg strExc ) 91 | "@muf encountered an error running your program: %s" fmtstring tell 92 | endcatch ( dbProg ) 93 | 94 | recycle ( ) 95 | ; 96 | -------------------------------------------------------------------------------- /scripts/teledump-extract.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | # 3 | # This is a script that will take the output of @teledump and export it into 4 | # a database file, macrofile, and a directory of muf's. 5 | # 6 | # Be mindful of where you run this script; it will create (if it doesn't exist) 7 | # a 'muf.outputfilename' directory. If it already exists, files in there 8 | # will probably get overwritten. 9 | # 10 | 11 | import base64 12 | import os 13 | import sys 14 | 15 | if len(sys.argv) != 3: 16 | print("Two arguments required: input file and output file") 17 | sys.exit(1) 18 | 19 | def find_marker(input, marker): 20 | """Advance the file pointer line by line until we find the string 'marker' 21 | If we never find it, raise exception 22 | 23 | Args: 24 | input: input file string 25 | marker: string we are looking for 26 | 27 | Raises: 28 | RuntimeError if marker not found 29 | """ 30 | 31 | while True: 32 | line = input.readline() 33 | 34 | if not line: 35 | raise RuntimeError("Could not find %s marker" % marker) 36 | 37 | if marker in line: 38 | break 39 | 40 | 41 | def read_block(input, marker): 42 | """Read a block of data from 'input' until we find 'marker', return it 43 | as a string 44 | 45 | Args: 46 | input: the file stream 47 | marker: the terminating marker 48 | 49 | Returns: 50 | String contents of what we loaded 51 | 52 | Raises: 53 | RuntimeError if marker not found 54 | """ 55 | 56 | ret = "" 57 | 58 | while True: 59 | line = input.readline() 60 | 61 | if not line: 62 | print("File too short, no %s marker" % marker) 63 | sys.exit(1) 64 | 65 | if marker in line: 66 | break 67 | 68 | ret += line 69 | 70 | return ret 71 | 72 | 73 | # Open input file, output file, and make MUF directory if it dosn't exist. 74 | with open(sys.argv[1], 'r') as input, open(sys.argv[2], 'wb') as output: 75 | # make muf dir if exists 76 | muf_dir = "muf.%s" % sys.argv[2] 77 | 78 | if not os.path.isdir(muf_dir): 79 | os.mkdir(muf_dir) 80 | 81 | # Skip lines until we find *** DB DUMP *** 82 | find_marker(input, "*** DB DUMP ***") 83 | 84 | # Accumulate lines until we get *** DB DUMP END *** 85 | db_str = read_block(input, "*** DB DUMP END ***") 86 | 87 | # Split db_str by * and base64 decode each line 88 | for block in db_str.split('*'): 89 | output.write(base64.b64decode(block)) 90 | 91 | # Macros are next -- find mac marker 92 | find_marker(input, "*** MACRO START ***") 93 | 94 | # Load macros 95 | mac_str = read_block(input, "*** MACRO END ***") 96 | 97 | with open("%s/macros" % muf_dir, "wb") as macfile: 98 | for block in mac_str.split('*'): 99 | macfile.write(base64.b64decode(block)) 100 | 101 | # Load MUFs ... we have to extract the MUF ref from the marker so we 102 | # can't use find_marker for this. 103 | for line in input: 104 | # Find next marker 105 | if "*** MUF " not in line: 106 | continue 107 | 108 | (stars, muf, ref, stars) = line.split(" ", 3) 109 | 110 | muf_str = read_block(input, "*** MUF END ***") 111 | 112 | with open("%s/%s.m" % (muf_dir, ref), "wb") as muffile: 113 | for block in muf_str.split('*'): 114 | muffile.write(base64.b64decode(block)) 115 | 116 | print("Done!") 117 | -------------------------------------------------------------------------------- /tests/command-cases/look.yml: -------------------------------------------------------------------------------- 1 | - name: examine-props 2 | setup: | 3 | @create Foo 4 | @propset Foo=int:~testint:43 5 | @propset Foo=dbref:@testref:#1 6 | @propset Foo=lock:_testlock:_foo:1 7 | @propset Foo=float:_testfloat:42.0 8 | @set Foo=_testdir:normalvalue 9 | @set Foo=_testdir/innervalue:xyz 10 | @set Foo=_blessprop:{null:} 11 | @bless Foo=_blessprop 12 | commands: | 13 | examine Foo=/ 14 | expect: 15 | - "- int /~testint:43" 16 | - "- ref /@testref:One\\(#1" 17 | - "- lok /_testlock:_foo:1" 18 | - "- flt /_testfloat:42" 19 | - "- str /_testdir/:normalvalue" 20 | - "B str /_blessprop:{null:}" 21 | 22 | - name: examine-propdir 23 | setup: | 24 | @create Foo 25 | @set Foo=_testdir:normalvalue 26 | @set Foo=_testdir/innervalue1:xyz 27 | @set Foo=_testdir/innervalue2:abc 28 | commands: | 29 | ex Foo=/_testdir/ 30 | expect: 31 | - "- str /_testdir/innervalue1:xyz" 32 | - "- str /_testdir/innervalue2:abc" 33 | - "2 properties listed" 34 | 35 | - name: examine-named-fields 36 | setup: | 37 | @create Foo 38 | @chlock Foo=_chlocktest:1 39 | @flock Foo=_flocktest:1 40 | @conlock Foo=_conlocktest:1 41 | @readlock Foo=_readlocktest:1 42 | @linklock Foo=_linklocktest:1 43 | @lock Foo=_locktest:1 44 | @describe Foo={null:description} 45 | @drop Foo=Drop message. 46 | @odrop Foo=Odrop message. 47 | @idesc Foo={null:inside description} 48 | @pecho Foo=Foo pecho>>> 49 | @oecho Foo=Foo oecho>>> 50 | commands: | 51 | ex Foo 52 | expect: 53 | - "Foo\\(#2\\)" 54 | - "Owner: One" 55 | - "Value: 1" 56 | - "Type: THING" 57 | - "{null:description}" 58 | - "Idesc: {null:inside description}" 59 | - "Drop: Drop message." 60 | - "Odrop: Odrop message." 61 | - "Chown_OK Key: _chlocktest:1" 62 | - "Link_OK Key: _linklocktest:1" 63 | - "Force Key: _flocktest:1" 64 | - "Container Key: _conlocktest:1" 65 | - "Read Key: _readlocktest:1" 66 | - "Pecho: Foo pecho>>>" 67 | - "Oecho: Foo oecho>>>" 68 | 69 | - name: look-thing-desc 70 | setup: | 71 | @create Foo 72 | @desc Foo=Example description. 73 | commands: | 74 | look Foo 75 | expect: 76 | - "Example description." 77 | 78 | - name: look-thing-nodesc 79 | setup: | 80 | @create Foo 81 | @tune description_default=[DEFAULT] 82 | commands: | 83 | look Foo 84 | expect: 85 | - "[DEFAULT]" 86 | 87 | - name: look-thing-detail 88 | setup: | 89 | @create Foo 90 | @set Foo=_details/Bar:Example detail. 91 | commands: | 92 | look Foo=Bar 93 | expect: 94 | - "Example detail." 95 | 96 | - name: look-thing-detail-nodesc 97 | setup: | 98 | @create Foo 99 | @tune description_default=[DEFAULT] 100 | commands: | 101 | look Foo=Bar 102 | expect: 103 | - "[DEFAULT]" 104 | 105 | - name: look-thing-detail-ambig 106 | setup: | 107 | @create Foo 108 | @set Foo=_details/Bar;x:Example 1. 109 | @set Foo=_details/Bar;y:Example 2. 110 | commands: | 111 | look Foo=Bar 112 | expect: 113 | - "don't know which 'Bar' you mean" 114 | 115 | - name: look-thing-detail-ambig-fmtstring 116 | setup: | 117 | @create Foo 118 | @set Foo=_details/%n;x:Example 1. 119 | @set Foo=_details/%n;y:Example 2. 120 | commands: | 121 | look Foo=%n 122 | expect: 123 | - "don't know which '%n' you mean" 124 | 125 | - name: look-fail-fmtstring 126 | commands: | 127 | look %n%n%n%n%n%n%n%n%n%n 128 | expect: 129 | - "I don't understand '%n" 130 | 131 | -------------------------------------------------------------------------------- /tests/command-cases/set.yml: -------------------------------------------------------------------------------- 1 | - name: create 2 | setup: | 3 | @create Foo 4 | commands: | 5 | ex Foo 6 | expect: 7 | - | 8 | Foo\(#2\)\s+Owner: One.* 9 | - | 10 | Location: One\(#1.* 11 | 12 | - name: rename 13 | setup: | 14 | @create Foo 15 | @name Foo=Bar 16 | commands: | 17 | ex Bar 18 | expect: | 19 | Bar\(#2\).* 20 | 21 | - name: prohibited-rename 22 | commands: | 23 | @create Foo 24 | @name Foo=me 25 | expect: | 26 | That is not a reasonable name.* 27 | 28 | - name: relink 29 | setup: | 30 | @dig IdTwo 31 | @dig IdThree 32 | @open foo=#2 33 | @relink foo=#3 34 | commands: | 35 | ex foo 36 | expect: | 37 | Destination: IdThree.* 38 | 39 | - name: relink-multilink 40 | setup: | 41 | @dig IdTwo 42 | @dig IdThree 43 | @create IdFour 44 | @open foo=#2 45 | @relink foo=#3;#4 46 | commands: | 47 | ex foo 48 | expect: | 49 | Destination: IdThree.* 50 | Destination: IdFour.* 51 | 52 | - name: failed-multilink 53 | setup: | 54 | @dig IdTwo 55 | @dig IdThree 56 | @program IdFour.muf 57 | q 58 | @open foo=#2 59 | commands: | 60 | @relink foo=#3;#4 61 | ex foo 62 | expect: 63 | - "Only one.*" 64 | - "Destination IdFour.muf.*ignored" 65 | - "Destination: IdTwo" 66 | 67 | - name: relink-loop 68 | setup: | 69 | @dig IdTwo 70 | @dig IdThree 71 | @open IdFour=IdTwo 72 | @open IdFive=IdFour 73 | @open IdSix=IdFive 74 | commands: | 75 | @relink IdFour=IdSix 76 | ex IdFour 77 | expect: 78 | - "would create a loop" 79 | - "Destination: IdTwo" 80 | 81 | - name: set-simple-str1 82 | setup: | 83 | @set me=_test:foo 84 | commands: | 85 | ex me=_test 86 | expect: | 87 | - str /_test:foo 88 | 1 property listed\. 89 | 90 | - name: set-simple-str2 91 | setup: | 92 | @propset me=str:_test:foo 93 | commands: | 94 | ex me=_test 95 | expect: | 96 | - str /_test:foo 97 | 1 property listed\. 98 | 99 | - name: set-simple-int 100 | setup: | 101 | @propset me=int:_test:42 102 | commands: | 103 | ex me=_test 104 | expect: | 105 | - int /_test:42 106 | 1 property listed\. 107 | 108 | - name: set-simple-float 109 | setup: | 110 | @propset me=float:_test:42.5 111 | commands: | 112 | ex me=_test 113 | expect: | 114 | - flt /_test:42.5 115 | 1 property listed\. 116 | 117 | - name: set-simple-dbref 118 | setup: | 119 | @propset me=dbref:_test:#1 120 | commands: | 121 | ex me=_test 122 | expect: | 123 | - ref /_test:One.* 124 | 1 property listed\. 125 | 126 | - name: propset-erase 127 | setup: | 128 | @set me=_test:foo 129 | @propset me=erase:_test 130 | commands: | 131 | ex me=_test 132 | expect: | 133 | 0 properties listed\. 134 | 135 | - name: propset-erase-propdir 136 | setup: | 137 | @set me=_test:foo 138 | @set me=_test/bar:foo 139 | @propset me=erase:_test 140 | commands: | 141 | ex me=_test 142 | expect: | 143 | 0 properties listed\. 144 | 145 | - name: set-clear 146 | setup: | 147 | @create Foo 148 | @set Foo=_/foo/bar/baz:test 149 | @set Foo=:clear 150 | commands: | 151 | ex Foo=/ 152 | expect: | 153 | 0 properties listed\. 154 | 155 | - name: set-clear-priv 156 | setup: | 157 | @create Foo 158 | @set Foo=~specialprop:foo 159 | @set Foo=_abb/~special:bar 160 | @set me=QUELL 161 | @set Foo=:clear 162 | @set me=!QUELL 163 | @set Foo=_aaa:before 164 | @set Foo=_bbb:after 165 | commands: | 166 | ex Foo=/ 167 | expect: | 168 | - str /_aaa:before 169 | - str /_bbb:after 170 | - str /~specialprop:foo 171 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/10.m: -------------------------------------------------------------------------------- 1 | ( lib-timestr.muf 2 | MUF versions of MPI's {stimestr}, {timestr}, and {ltimestr}. 3 | 4 | Public domain. 5 | 6 | Version history: 7 | 1.1, 16 March 2003: added rtimestr 8 | ) 9 | $author Natasha O'Brien, Revar 10 | $version 1.1 11 | $lib-version 1.1 12 | $note MUF versions of MPI's {stimestr}, {timestr}, and {ltimestr}. 13 | 14 | 15 | : ltimestr[ int:amt -- str:result ] 16 | 0 array_make var! result ( arr ) 17 | var unit 18 | 19 | 1 "%i sec%s" 20 | 60 "%i min%s" 21 | 3600 "%i hour%s" 22 | 86400 "%i day%s" 23 | 24 | 4 begin dup while ( intN strN..int1 str1 intN ) 25 | swap unit ! swap ( intN strN..int2 str2 intN int1 ) 26 | amt @ over >= if ( intN strN..int2 str2 intN int1 ) 27 | amt @ over / ( intN strN..int2 str2 intN int1 intHowMany1s ) 28 | dup 1 = if "" else "s" then swap unit @ fmtstring ( intN strN..int2 str2 intN int1 strHowMany1s ) 29 | result @ array_appenditem result ! ( intN strN..int2 str2 intN int1 ) 30 | amt @ swap % amt ! ( intN strN..int2 str2 intN ) 31 | else pop then ( intN strN..int2 str2 intN ) 32 | 1 - repeat pop ( ) 33 | result @ ", " array_join ( str ) 34 | ; 35 | 36 | : rtimestr ( int -- str } Show a human-readable 'ago' message. Algorithm taken from SC-Track Roundup issue tracking Python software. ) 37 | dup case ( intSince ) 38 | 63072000 (730 days) >= when 31536000 (365 days) / "%i years ago" fmtstring end 39 | 31536000 (365 days) >= when pop "A year ago" end 40 | 5184000 ( 60 days) >= when 2592000 ( 30 days) / "%i months ago" fmtstring end 41 | 2505600 ( 29 days) >= when pop "A month ago" end 42 | 1209600 ( 14 days) >= when 604800 ( 7 days) / "%i weeks ago" fmtstring end 43 | 604800 ( 7 days) >= when pop "A week ago" end 44 | 172800 ( 2 days) >= when 86400 ( 1 day ) / "%i days ago" fmtstring end 45 | 46800 (13 hours) >= when pop "Yesterday" end 46 | 7200 ( 2 hours) >= when 3600 ( 2 hours) / "%i hours ago" fmtstring end 47 | 6300 (1 3/4 hours) >= when pop "1 3/4 hours ago" end 48 | 5400 (1 1/2 hours) >= when pop "1 1/2 hours ago" end 49 | 4500 (1 1/4 hours) >= when pop "1 1/4 hours ago" end 50 | 3600 ( 1 hour ) >= when pop "An hour ago" end 51 | 2700 ( 45 minutes) >= when pop "3/4 hour ago" end 52 | 1800 ( 30 minutes) >= when pop "1/2 an hour ago" end 53 | 900 ( 15 minutes) >= when pop "1/4 hour ago" end 54 | 120 ( 2 minutes) >= when 60 / "%i minutes ago" fmtstring end 55 | ( Where Roundup would say '1 minute ago' we go ahead and say 'Just now.' ) 56 | default pop pop "Just now" end 57 | endcase ( str ) 58 | ; 59 | 60 | : stimestr (i -- s} from standard fbmuf 3who ) 61 | dup 0 < if pop 0 then 62 | dup 86400 > if 63 | 86400 / intostr "d" strcat 64 | else dup 3600 > if 65 | 3600 / intostr "h" strcat 66 | else dup 60 > if 67 | 60 / intostr "m" strcat 68 | else 69 | intostr "s" strcat 70 | then 71 | then 72 | then 73 | " " swap strcat 74 | dup strlen 4 - strcut swap pop 75 | ; 76 | 77 | : mtimestr (i -- s} from standard fbmuf 3who ) 78 | dup 0 < if pop 0 then 79 | "" over 86400 > if 80 | over 86400 / intostr "d " strcat strcat 81 | swap 86400 % swap 82 | then 83 | over 3600 / intostr 84 | "00" swap strcat 85 | dup strlen 2 - strcut 86 | swap pop strcat ":" strcat 87 | swap 3600 % 60 / intostr 88 | "00" swap strcat 89 | dup strlen 2 - strcut 90 | swap pop strcat 91 | ; 92 | 93 | PUBLIC ltimestr $libdef ltimestr 94 | PUBLIC mtimestr $libdef mtimestr 95 | PUBLIC stimestr $libdef stimestr 96 | PUBLIC rtimestr $libdef rtimestr 97 | 98 | $pubdef timestr mtimestr 99 | -------------------------------------------------------------------------------- /scripts/fbmuck-add: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | 4 | show_usage() { 5 | (cat <&2 28 | exit 1 29 | } 30 | 31 | 32 | show_db_list() { 33 | # TODO: make muckdb listing real. 34 | echo "There are no available starter databases yet." 35 | exit 0 36 | } 37 | 38 | 39 | muckpath=$(pwd) 40 | muckscript="restart" 41 | muckports="8888,8899s" 42 | muckuser="" 43 | muckdb="" 44 | 45 | if [ $# -lt 1 ]; then 46 | show_usage 47 | fi 48 | 49 | muckname="$1" 50 | shift 51 | 52 | while [ $# -gt 0 ]; do 53 | case $1 in 54 | -n) muckdb="$2"; shift 2;; 55 | --new=*) muckdb=${1#--new=}; shift;; 56 | 57 | -l) show_db_list;; 58 | --list-dbs) show_db_list;; 59 | 60 | -d) muckpath="$2"; shift 2;; 61 | --dir=*) muckpath=${1#--dir=}; shift;; 62 | 63 | -u) muckuser="$2"; shift 2;; 64 | --user=*) muckuser=${1#--user=}; shift;; 65 | 66 | -s) muckscript="$2"; shift 2;; 67 | --script=*) muckscript=${1#--script=}; shift;; 68 | 69 | -p) muckports="$2"; shift 2;; 70 | --ports=*) muckports=${1#--ports=}; shift;; 71 | 72 | *) show_usage;; 73 | esac 74 | done 75 | 76 | if [ -e "/etc/fbmucks" ]; then 77 | preventry=$(grep "^$muckname"'[ ]' /etc/fbmucks) 78 | if [ ! -z "$preventry" ]; then 79 | echo "A muck named $muckname already exists in /etc/fbmucks." 1>&2 80 | exit 2 81 | fi 82 | prevdir=$(grep '[ ]'"$muckpath"'[ ]' /etc/fbmucks | awk '{print $3}') 83 | if [ ! -z "$prevdir" ]; then 84 | echo "A muck in $muckpath already exists in /etc/fbmucks." 1>&2 85 | exit 2 86 | fi 87 | fi 88 | 89 | if [ -z "$muckdb" ]; then 90 | if [ ! -d "$muckpath" ]; then 91 | echo "$muckpath is not a valid directory." 1>&2 92 | exit 2 93 | fi 94 | 95 | if [ ! -e "$muckpath/$muckscript" ]; then 96 | echo "$muckpath/$muckscript does not exist." 1>&2 97 | exit 2 98 | fi 99 | 100 | if [ ! -x "$muckpath/$muckscript" ]; then 101 | echo "$muckpath/$muckscript is not a valid executable script." 1>&2 102 | exit 2 103 | fi 104 | 105 | if [ -z "$muckuser" ]; then 106 | muckuser=$(/bin/ls -l $muckpath/$muckscript | awk '{print $3}') 107 | fi 108 | 109 | echo "$muckname $muckuser $muckpath $muckscript $muckports" >> /etc/fbmucks 110 | else 111 | if [ -e "$muckpath/$muckscript" ]; then 112 | echo "$muckpath/$muckscript already exists! Aborting." 1>&2 113 | exit 2 114 | fi 115 | 116 | if [ -z "$muckuser" ]; then 117 | echo "You MUST specify a target user when using --new." 1>&2 118 | exit 2 119 | fi 120 | 121 | if [ ! -d "$muckpath" ]; then 122 | mkdir -p $muckpath 123 | fi 124 | 125 | # TODO: add db installation code. 126 | echo "$muckname $muckuser $muckpath $muckscript $muckports" >> /etc/fbmucks 127 | fi 128 | -------------------------------------------------------------------------------- /src/pennies.c: -------------------------------------------------------------------------------- 1 | /** @file pennies.c 2 | * 3 | * Source for commands to do with money. Giving them, and viewing your "score". 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #include "config.h" 9 | 10 | #include "commands.h" 11 | #include "db.h" 12 | #include "interface.h" 13 | #include "match.h" 14 | #include "player.h" 15 | #include "props.h" 16 | #include "tune.h" 17 | 18 | /** 19 | * Implementation of give command 20 | * 21 | * This transfers "pennies" or value from one player to another. 22 | * Or, if you are a wizard, you can use this to take pennies or set the 23 | * value of an object. 24 | * 25 | * This does all necessary permission checks and works pretty much how 26 | * you would expect. Players cannot cause another player to exceed 27 | * tp_max_pennies 28 | * 29 | * @param descr the descriptor of the giving player 30 | * @param player the giving player 31 | * @param recipient the person receiving the gift 32 | * @param amount the amount to transfer. 33 | */ 34 | void 35 | do_give(int descr, dbref player, const char *recipient, int amount) 36 | { 37 | dbref who; 38 | struct match_data md; 39 | 40 | 41 | if (amount == 0 || (amount < 0 && !Wizard(OWNER(player)))) { 42 | notifyf(player, "You must specify a valid number of %s.", tp_pennies); 43 | return; 44 | } 45 | 46 | init_match(descr, player, recipient, TYPE_PLAYER, &md); 47 | match_neighbor(&md); 48 | match_me(&md); 49 | 50 | if (Wizard(OWNER(player))) { 51 | match_player(&md); 52 | match_absolute(&md); 53 | } 54 | 55 | if ((who = noisy_match_result(&md)) == NOTHING) { 56 | return; 57 | } 58 | 59 | if (!Wizard(OWNER(player))) { 60 | if (Typeof(who) != TYPE_PLAYER) { 61 | notify(player, "You can only give to other players."); 62 | return; 63 | } else if (GETVALUE(who) + amount > tp_max_pennies) { 64 | notifyf(player, "That player doesn't need that many %s!", tp_pennies); 65 | return; 66 | } 67 | } 68 | 69 | if (!payfor(player, amount)) { 70 | notifyf(player, "You don't have that many %s to give!", tp_pennies); 71 | return; 72 | } 73 | 74 | switch (Typeof(who)) { 75 | case TYPE_PLAYER: 76 | SETVALUE(who, GETVALUE(who) + amount); 77 | 78 | if (amount >= 0) { 79 | notifyf(player, "You give %d %s to %s.", 80 | amount, amount == 1 ? tp_penny : tp_pennies, NAME(who)); 81 | notifyf(who, "%s gives you %d %s.", 82 | NAME(player), amount, amount == 1 ? tp_penny : tp_pennies); 83 | } else { 84 | notifyf(player, "You take %d %s from %s.", 85 | -amount, amount == -1 ? tp_penny : tp_pennies, NAME(who)); 86 | notifyf(who, "%s takes %d %s from you!", 87 | NAME(player), -amount, -amount == 1 ? tp_penny : tp_pennies); 88 | } 89 | 90 | break; 91 | case TYPE_THING: 92 | SETVALUE(who, (GETVALUE(who) + amount)); 93 | notifyf(player, "You change the value of %s to %d %s.", 94 | NAME(who), GETVALUE(who), GETVALUE(who) == 1 ? tp_penny : tp_pennies); 95 | break; 96 | default: 97 | notifyf(player, "You can't give %s to that!", tp_pennies); 98 | break; 99 | } 100 | 101 | DBDIRTY(who); 102 | } 103 | 104 | /** 105 | * Implementation of score command 106 | * 107 | * Which is how you see how many "pennies" you have. 108 | * 109 | * @param player the player doing the call 110 | */ 111 | void 112 | do_score(dbref player) 113 | { 114 | notifyf(player, "You have %d %s.", GETVALUE(player), 115 | GETVALUE(player) == 1 ? tp_penny : tp_pennies); 116 | } 117 | -------------------------------------------------------------------------------- /include/p_regex.h: -------------------------------------------------------------------------------- 1 | /** @file p_regex.h 2 | * 3 | * Declaration of regex related primitives for MUF. 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #ifndef P_REGEX_H 9 | #define P_REGEX_H 10 | 11 | #include "interp.h" 12 | 13 | /* 14 | * The following defines can be bitwise OR'd together to use multple flags 15 | */ 16 | 17 | /** 18 | * @var MUF_RE_ICASE 19 | * Case insensitive search 20 | */ 21 | #define MUF_RE_ICASE 1 22 | 23 | /** 24 | * @var MUF_RE_ALL 25 | * Substitute ALL on a regex substitution call 26 | */ 27 | #define MUF_RE_ALL 2 28 | 29 | /** 30 | * @var MUF_RE_EXTENDED 31 | * Enable PCRE extended features 32 | */ 33 | #define MUF_RE_EXTENDED 4 34 | 35 | /** 36 | * Implementation of MUF REGEXP 37 | * 38 | * Consumes some text, a Perl-style pattern, and an integer flags. 39 | * Returns a list of submatch values and a list of submatch indexes. 40 | * 41 | * The flags can be a bitwise OR of the MUF_RE_* defines. See the comments 42 | * for those defines to see what they do exactly. 43 | * 44 | * @param player the player running the MUF program 45 | * @param program the program being run 46 | * @param mlev the effective MUCKER level 47 | * @param pc the program counter pointer 48 | * @param arg the argument stack 49 | * @param top the top-most item of the stack 50 | * @param fr the program frame 51 | */ 52 | void prim_regexp(PRIM_PROTOTYPE); 53 | 54 | /** 55 | * Implementation of MUF REGSUB 56 | * 57 | * Consumes some text, a Perl-style pattern, a replacement string, 58 | * and an integer flags. Returns a string that has replaced the 59 | * pattern with the replacement string. 60 | * 61 | * The flags can be a bitwise OR of the MUF_RE_* defines. See the comments 62 | * for those defines to see what they do exactly. 63 | * 64 | * @param player the player running the MUF program 65 | * @param program the program being run 66 | * @param mlev the effective MUCKER level 67 | * @param pc the program counter pointer 68 | * @param arg the argument stack 69 | * @param top the top-most item of the stack 70 | * @param fr the program frame 71 | */ 72 | void prim_regsub(PRIM_PROTOTYPE); 73 | 74 | /** 75 | * Implementation of MUF REGSPLIT 76 | * 77 | * Consumes a string, a pattern, and an integer which is the addition 78 | * of MUF_RE_* defines. Returns a list which is the string split by 79 | * the pattern. It will push empty pieces on the stack for consecutive 80 | * matches. 81 | * 82 | * @param player the player running the MUF program 83 | * @param program the program being run 84 | * @param mlev the effective MUCKER level 85 | * @param pc the program counter pointer 86 | * @param arg the argument stack 87 | * @param top the top-most item of the stack 88 | * @param fr the program frame 89 | */ 90 | void prim_regsplit(PRIM_PROTOTYPE); 91 | 92 | /** 93 | * Implementation of MUF REGSPLIT_NOEMPTY 94 | * 95 | * Consumes a string, a pattern, and an integer which is the addition 96 | * of MUF_RE_* defines. Returns a list which is the string split by 97 | * the pattern. It will not put empty pieces on the stack. 98 | * 99 | * @param player the player running the MUF program 100 | * @param program the program being run 101 | * @param mlev the effective MUCKER level 102 | * @param pc the program counter pointer 103 | * @param arg the argument stack 104 | * @param top the top-most item of the stack 105 | * @param fr the program frame 106 | */ 107 | void prim_regsplit_noempty(PRIM_PROTOTYPE); 108 | 109 | /** 110 | * Primitive callback functions 111 | */ 112 | #define PRIMS_REGEX_FUNCS prim_regexp, prim_regsub, prim_regsplit, \ 113 | prim_regsplit_noempty 114 | 115 | /** 116 | * Primitive names - must be in same order as the callback functions 117 | */ 118 | #define PRIMS_REGEX_NAMES "REGEXP", "REGSUB", "REGSPLIT", "REGSPLIT_NOEMPTY" 119 | 120 | #endif /* !P_REGEX_H */ 121 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/9.m: -------------------------------------------------------------------------------- 1 | ( lib-table.muf by Natasha@HLM 2 | Library for tabular output {whodoing, laston, whospecies, etc}. 3 | 4 | 5 | table-process[ dict:processors list:data -- list:results ] 6 | 7 | For each item of list:data, executes each address value of dict:processors, 8 | placing the result in a dictionary as a value with the same key. These 9 | dictionaries are held in list:results. 10 | 11 | For example, say dict:processors is: 12 | 13 | { "name": 'rtn-getname, "species": 'rtn-getspecies } 14 | 15 | and list:data contains the dbrefs: 16 | 17 | { #71, #208 } 18 | 19 | list:results might contain: 20 | 21 | { { "name": "Natasha", "species": "fox" }, 22 | { "name": "Lumi", "species": "snowmeow"} } 23 | 24 | 25 | table-format[ str:linefmt dict:headers list:results -- list:output ] 26 | 27 | Format results from table-process into strings. str:linefmt should be a 28 | string suitable for array_fmtstrings. In the above example, it might be: 29 | 30 | "%-16.16[name]s %-16.16[species]s" 31 | 32 | dict:headers contains a set of strings to place in the line format, to be 33 | printed as a header. If it's empty, it's not used. In the above example, 34 | it might be: 35 | 36 | { "name": "Name", "species": "Species" } 37 | 38 | The example results would be output from table-format as: 39 | 40 | { "Name Species ", 41 | "Natasha fox ", 42 | "Lumi snowmeow " } 43 | 44 | 45 | table-table-sort[ str:linefmt dict:headers dict:processors list:data str:sorthow -- ] 46 | 47 | Processes, formats, and outputs the given data as explained above, 48 | sorted by the output data with key sorthow. 49 | 50 | 51 | table-table[ str:linefmt dict:headers dict:processors list:data -- ] 52 | 53 | Processes, formats, and outputs the given data as explained above, 54 | in the natural order of the data list. 55 | 56 | 57 | Copyright 2002-2003 Natasha O'Brien. Copyright 2002-2003 Here Lie Monsters. 58 | "@view $box/mit" for license information. 59 | ) 60 | $author Natasha O'Brien 61 | $version 1.1 62 | $lib-version 1.1 63 | $note Library for tabular output (whodoing, laston, whospecies, etc). 64 | $doccmd @list __PROG__=1-51 65 | 66 | : table-process[ dict:processors list:data -- list:results ] 67 | data @ 0 array_make ( arrData arrResults ) 68 | swap foreach swap pop ( arrResults ?Datum ) 69 | ( Make a dictResult containing everything in processors, only with the results of each adr for values. ) 70 | 0 array_make_dict ( arrResults ?Datum dictResult ) 71 | processors @ foreach ( arrResults ?Datum dictResult strKey adrValue ) 72 | 4 pick swap execute ( arrResults ?Datum dictResult strKey strValue ) 73 | -3 rotate array_setitem ( arrResults ?Datum dictResult ) 74 | repeat ( arrResults ?Datum dictResult ) 75 | rot array_appenditem ( ?Datum arrResults ) 76 | swap pop ( arrResults ) 77 | repeat ( arrResults ) 78 | ; 79 | 80 | 81 | : table-format[ str:linefmt dict:headers list:results -- list:output ] 82 | headers @ if headers @ results @ array_appenditem else results @ then ( arrResults ) 83 | linefmt @ array_fmtstrings ( arrOutput ) 84 | array_reverse ( arrOutput ) 85 | ; 86 | 87 | 88 | : table-table-sort[ str:linefmt dict:headers dict:processors list:data str:sorthow -- ] 89 | linefmt @ headers @ ( strLinefmt arrHeaders ) 90 | processors @ data @ table-process ( strLinefmt arrHeaders arrResults ) 91 | sorthow @ if SORTTYPE_NOCASE_DESCEND sorthow @ array_sort_indexed then ( strLinefmt arrHeaders arrResults' ) 92 | table-format ( arrOutput ) 93 | me @ 1 array_make array_notify ( ) 94 | ; 95 | 96 | 97 | PUBLIC table-process $libdef table-process 98 | PUBLIC table-format $libdef table-format 99 | PUBLIC table-table-sort $libdef table-table-sort 100 | 101 | $pubdef table-table "" table-table-sort 102 | -------------------------------------------------------------------------------- /win32/autoconf.h: -------------------------------------------------------------------------------- 1 | /* Define to 1 if you have the header file, and it defines `DIR'. 2 | */ 3 | /* #undef HAVE_DIRENT_H */ 4 | 5 | /* Define to 1 if you have the `getrlimit' function. */ 6 | #define HAVE_GETRLIMIT 1 7 | 8 | /* Define to 1 if you have the `getrusage' function. */ 9 | /* #undef HAVE_GETRUSAGE */ 10 | 11 | /* Define to 1 if you have the header file. */ 12 | /* #undef HAVE_INTTYPES_H */ 13 | 14 | /* Define to 1 if you have the `m' library (-lm). */ 15 | #define HAVE_LIBM 1 16 | 17 | /* Define to 1 if you have the `pcre' library (-lpcre). */ 18 | #define HAVE_LIBPCRE 1 19 | 20 | /* Define to 1 if the headers are under , not */ 21 | /* #undef HAVE_PCREINCDIR */ 22 | 23 | /* Define to 1 if you have the `socket' library (-lsocket). */ 24 | /* #undef HAVE_LIBSOCKET */ 25 | 26 | /* Define to 1 if you have the `ssl' library (-lssl). */ 27 | #define HAVE_LIBSSL 1 28 | 29 | /* Define to 1 if you have the `mallinfo' function. */ 30 | /* #undef HAVE_MALLINFO */ 31 | 32 | /* Define to 1 if you have the header file. */ 33 | #define HAVE_MALLOC_H 1 34 | 35 | /* Define to 1 if you have the header file, and it defines `DIR'. */ 36 | /* #undef HAVE_NDIR_H */ 37 | 38 | /* ssl headers are under openssl dir. */ 39 | #define HAVE_OPENSSL 40 | 41 | /* Did the user specify debugging assertions? */ 42 | /* #undef DEBUG */ 43 | 44 | /* Define to 1 if you have the `arc4random_uniform' function. */ 45 | /* #undef HAVE_ARC4RANDOM_UNIFORM */ 46 | 47 | /* Define to 1 if you have the header file. */ 48 | /* #undef HAVE_STDINT_H */ 49 | 50 | /* Define to 1 if you have the header file, and it defines `DIR'. 51 | */ 52 | /* #undef HAVE_SYS_DIR_H */ 53 | 54 | /* Define to 1 if you have the header file, and it defines `DIR'. 55 | */ 56 | /* #undef HAVE_SYS_NDIR_H */ 57 | 58 | /* Define to 1 if you have the header file. */ 59 | #define HAVE_SYS_STAT_H 1 60 | 61 | /* Define to 1 if you have the header file. */ 62 | #define HAVE_SYS_TYPES_H 1 63 | 64 | /* Define to 1 if you have the header file. */ 65 | /* #undef HAVE_UNISTD_H */ 66 | 67 | /* Enables memory usage profiling. */ 68 | /* #undef MALLOC_PROFILING */ 69 | 70 | /* With MALLOC_PROFILING, can detect double-frees, buffer overruns, etc. */ 71 | /* #undef MALLOC_PROFILING_EXTRA */ 72 | 73 | /* Define to the address where bug reports for this package should be sent. */ 74 | #define PACKAGE_BUGREPORT "feedback@fuzzball.org" 75 | 76 | /* Define to the full name of this package. */ 77 | #define PACKAGE_NAME "fbmuck" 78 | 79 | /* Define to the full name and version of this package. */ 80 | #define PACKAGE_STRING "fbmuck 7.00b1+master" 81 | 82 | /* Define to the one symbol short name of this package. */ 83 | #define PACKAGE_TARNAME "fbmuck" 84 | 85 | /* Define to the home page for this package. */ 86 | #define PACKAGE_URL "" 87 | 88 | /* Define to the version of this package. */ 89 | #define PACKAGE_VERSION "7.00b1+master" 90 | 91 | /* Define to 1 if you can safely include both and . */ 92 | /* #undef TIME_WITH_SYS_TIME */ 93 | 94 | /* Define to 1 if your declares `struct tm'. */ 95 | /* #undef TM_IN_SYS_TIME */ 96 | 97 | /* The base path to the installation for openssl. Usually /usr. */ 98 | /* #undef ssldir */ 99 | 100 | /* Define to `int' if doesn't define. */ 101 | /* #undef uid_t */ 102 | 103 | /* Defined to 1 if struct mallinfo.hblks exists. */ 104 | /* #undef HAVE_STRUCT_MALLINFO_HBLKS */ 105 | 106 | /* Defined to 1 if struct mallinfo.keepcost exists. */ 107 | /* #undef HAVE_STRUCT_MALLINFO_KEEPCOST */ 108 | 109 | /* Defined to 1 if struct mallinfo.treeoverhead exists. */ 110 | /* #undef HAVE_STRUCT_MALLINFO_TREEOVERHEAD */ 111 | 112 | /* Defined to 1 if struct mallinfo.grain exists. */ 113 | /* #undef HAVE_STRUCT_MALLINFO_GRAIN */ 114 | 115 | /* Defined to 1 if struct mallinfo.allocated exists. */ 116 | /* #undef HAVE_STRUCT_MALLINFO_ALLOCATED */ 117 | 118 | -------------------------------------------------------------------------------- /include/autoconf.h.in: -------------------------------------------------------------------------------- 1 | /* include/autoconf.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Enable debugging assertions. */ 4 | #undef DEBUG 5 | 6 | /* Force TLS 1.2. */ 7 | #undef FORCE_TLS12 8 | 9 | /* Define to 1 if you have the `arc4random_uniform' function. */ 10 | #undef HAVE_ARC4RANDOM_UNIFORM 11 | 12 | /* Define to 1 if you have the header file, and it defines `DIR'. 13 | */ 14 | #undef HAVE_DIRENT_H 15 | 16 | /* Define to 1 if you have the `getrlimit' function. */ 17 | #undef HAVE_GETRLIMIT 18 | 19 | /* Define to 1 if you have the `getrusage' function. */ 20 | #undef HAVE_GETRUSAGE 21 | 22 | /* Define to 1 if you have the header file. */ 23 | #undef HAVE_INTTYPES_H 24 | 25 | /* Define to 1 if you have the `crypto' library (-lcrypto). */ 26 | #undef HAVE_LIBCRYPTO 27 | 28 | /* Define to 1 if you have the `pcre' library (-lpcre). */ 29 | #undef HAVE_LIBPCRE 30 | 31 | /* Define to 1 if you have the `ssl' library (-lssl). */ 32 | #undef HAVE_LIBSSL 33 | 34 | /* Define to 1 if you have the `mallinfo' function. */ 35 | #undef HAVE_MALLINFO 36 | 37 | /* Define to 1 if you have the header file. */ 38 | #undef HAVE_MALLOC_H 39 | 40 | /* Define to 1 if you have the header file, and it defines `DIR'. */ 41 | #undef HAVE_NDIR_H 42 | 43 | /* ssl headers are under openssl dir. */ 44 | #undef HAVE_OPENSSL 45 | 46 | /* PCRE headers are under pcre dir. */ 47 | #undef HAVE_PCREINCDIR 48 | 49 | /* Define to 1 if you have the `pselect' function. */ 50 | #undef HAVE_PSELECT 51 | 52 | /* Define to 1 if you have the header file. */ 53 | #undef HAVE_STDINT_H 54 | 55 | /* Define to 1 if you have the header file. */ 56 | #undef HAVE_STDIO_H 57 | 58 | /* Define to 1 if you have the header file. */ 59 | #undef HAVE_STDLIB_H 60 | 61 | /* Define to 1 if you have the header file. */ 62 | #undef HAVE_STRINGS_H 63 | 64 | /* Define to 1 if you have the header file. */ 65 | #undef HAVE_STRING_H 66 | 67 | /* Define to 1 if you have the header file, and it defines `DIR'. 68 | */ 69 | #undef HAVE_SYS_DIR_H 70 | 71 | /* Define to 1 if you have the header file, and it defines `DIR'. 72 | */ 73 | #undef HAVE_SYS_NDIR_H 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_SYS_STAT_H 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_SYS_TYPES_H 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #undef HAVE_UNISTD_H 83 | 84 | /* Enables memory usage profiling. */ 85 | #undef MALLOC_PROFILING 86 | 87 | /* With MALLOC_PROFILING, can detect double-frees, buffer overruns, etc. */ 88 | #undef MALLOC_PROFILING_EXTRA 89 | 90 | /* Enable freeing memory on exit. */ 91 | #undef MEMORY_CLEANUP 92 | 93 | /* Define to the address where bug reports for this package should be sent. */ 94 | #undef PACKAGE_BUGREPORT 95 | 96 | /* Define to the full name of this package. */ 97 | #undef PACKAGE_NAME 98 | 99 | /* Define to the full name and version of this package. */ 100 | #undef PACKAGE_STRING 101 | 102 | /* Define to the one symbol short name of this package. */ 103 | #undef PACKAGE_TARNAME 104 | 105 | /* Define to the home page for this package. */ 106 | #undef PACKAGE_URL 107 | 108 | /* Define to the version of this package. */ 109 | #undef PACKAGE_VERSION 110 | 111 | /* Define to 1 if all of the C90 standard headers exist (not just the ones 112 | required in a freestanding environment). This macro is provided for 113 | backward compatibility; new code need not use it. */ 114 | #undef STDC_HEADERS 115 | 116 | /* The base path to the installation for PCRE. Usually /usr. */ 117 | #undef pcredir 118 | 119 | /* Define as a signed integer type capable of holding a process identifier. */ 120 | #undef pid_t 121 | 122 | /* Define to `unsigned int' if does not define. */ 123 | #undef size_t 124 | 125 | /* The base path to the installation for openssl. Usually /usr. */ 126 | #undef ssldir 127 | -------------------------------------------------------------------------------- /include/hashtab.h: -------------------------------------------------------------------------------- 1 | /** @file hashtab.h 2 | * 3 | * Header for the implementation of hash tables. 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #ifndef HASHTAB_H 9 | #define HASHTAB_H 10 | 11 | #include "config.h" 12 | 13 | /** 14 | * Possible data types that may be stored in a hash table 15 | */ 16 | union u_hash_data { 17 | int ival; /**< Store compiler tokens here */ 18 | dbref dbval; /**< Player hashing will want this */ 19 | void *pval; /**< compiler $define strings use this */ 20 | }; 21 | 22 | /** 23 | * The actual hash entry for each item 24 | */ 25 | struct t_hash_entry { 26 | struct t_hash_entry *next; /**< Pointer for conflict resolution */ 27 | const char *name; /**< The name of the item */ 28 | union u_hash_data dat; /**< Data value for item */ 29 | }; 30 | 31 | typedef union u_hash_data hash_data; /**< Union hash data type */ 32 | typedef struct t_hash_entry hash_entry; /**< entry for hash table */ 33 | typedef hash_entry *hash_tab; /**< A hash table itself */ 34 | 35 | #define PLAYER_HASH_SIZE (1024) /**< Table for player lookups */ 36 | #define COMP_HASH_SIZE (256) /**< Table for compiler keywords */ 37 | #define DEFHASHSIZE (256) /**< Table for compiler $defines */ 38 | 39 | /** 40 | * Add a string to a hash table 41 | * 42 | * Will supercede old values in the table, returns pointer to 43 | * the hash entry, or NULL on failure. 44 | * 45 | * The name is copied when a new entry is added. 46 | * 47 | * @param name the name of the entry to add 48 | * @param data the data to store 49 | * @param table the hash stable to store it in 50 | * @param size the page size of the hash table 51 | */ 52 | hash_entry *add_hash(const char *name, hash_data data, hash_tab * table, 53 | unsigned int size); 54 | 55 | /* 56 | * @todo All these functions take a size parameter. Wouldn't it make more 57 | * sense to have a hash header struct that keeps track of that? Its 58 | * Maybe its not worth the effort, but it seems like something that 59 | * would be easy to break if we're not careful. 60 | */ 61 | 62 | /** 63 | * Lookup a name in a hash table 64 | * 65 | * Returns NULL if not found, otherwise a pointer to the data union. 66 | * The key string comparison is case insensitive. 67 | * 68 | * @param s the string to look up 69 | * @param table the table to look the string up in 70 | * @param size the hash page size 71 | * @return NULL if not found, otherwise a pointer to the data union 72 | */ 73 | hash_data *find_hash(const char *s, hash_tab * table, unsigned size); 74 | 75 | /** 76 | * Free a hash table entry associated with a name 77 | * 78 | * Frees the dynamically allocated hash table entry associated with 79 | * a name. Returns 0 on success, or -1 if the name cannot be found. 80 | * Frees the entry name, but does not free the data associated with 81 | * the entry. 82 | * 83 | * @param name the name of the hash entry to free 84 | * @param table the table to delete from 85 | * @param size the page size 86 | * @return 0 on success, -1 if 'name' was not found. 87 | */ 88 | int free_hash(const char *name, hash_tab * table, unsigned size); 89 | 90 | /** 91 | * Compute hash value for a string (case-insensitive) 92 | * 93 | * This particular hash function is fairly simple. Note that it 94 | * throws away the information from the 0x20 bit in the character. 95 | * This means that upper and lower case letters will hash to the 96 | * same value. 97 | * 98 | * @param s the string to hash 99 | * @param hash_size the hash value will be between 0 and hash_size-1 100 | * @return the hash value as an integer 101 | */ 102 | unsigned int hash(const char *s, unsigned int hash_size); 103 | 104 | /** 105 | * Kill an entire hash table, by freeing every entry 106 | * 107 | * This will optionally also delete the data pointers if freeptrs is 108 | * true. 109 | * 110 | * @param table the hash table to operate on 111 | * @param size the page size 112 | * @param freeptrs boolean if true, free the data union value. 113 | */ 114 | void kill_hash(hash_tab * table, unsigned size, int freeptrs); 115 | 116 | #endif /* !HASHTAB_H */ 117 | -------------------------------------------------------------------------------- /include/look.h: -------------------------------------------------------------------------------- 1 | /** @file look.h 2 | * 3 | * Header for declaring the "checkflags" search system that is used by 4 | * \@find, \@entrances, etc. Also includes look_room. 5 | * 6 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 7 | */ 8 | 9 | #ifndef LOOK_H 10 | #define LOOK_H 11 | 12 | #include 13 | 14 | #include "config.h" 15 | 16 | /** 17 | * This structure defines a database search query in Fuzzball 18 | */ 19 | struct flgchkdat { 20 | int fortype; /**< check FOR a type? */ 21 | int istype; /**< If check FOR a type, which one? */ 22 | int isnotroom; /**< not a room. */ 23 | int isnotexit; /**< not an exit. */ 24 | int isnotthing; /**< not type thing */ 25 | int isnotplayer; /**< not a player */ 26 | int isnotprog; /**< not a program */ 27 | int forlevel; /**< check for a mucker level? */ 28 | int islevel; /**< if check FOR a mucker level, which level? */ 29 | int isnotzero; /**< not ML0 */ 30 | int isnotone; /**< not ML1 */ 31 | int isnottwo; /**< not ML2 */ 32 | int isnotthree; /**< not ML3 */ 33 | int setflags; /**< flags that are set to check for */ 34 | int clearflags; /**< flags to check are cleared. */ 35 | int forlink; /**< check linking? */ 36 | int islinked; /**< if yes, check if not unlinked */ 37 | int forold; /**< check for old object? */ 38 | int isold; /**< if yes, check if old */ 39 | int loadedsize; /**< check for propval-loaded size? */ 40 | int issize; /**< list objs larger than size? */ 41 | size_t size; /**< what size to check against. No check if 0 */ 42 | }; 43 | 44 | /** 45 | * Checks an object 'what' against a set of flags 'check' 46 | * 47 | * This is defined in look.c 48 | * 49 | * 'check' should be initialized with init_checkflags. Then you 50 | * can pass 'what' in to check that object against the flags. 51 | * 52 | * @see init_checkflags 53 | * 54 | * @param what the object to check 55 | * @param check the flags to check -- see init_checkflags 56 | * @return boolean - 1 if object matches, 0 if not 57 | */ 58 | int checkflags(dbref what, struct flgchkdat check); 59 | 60 | /** 61 | * Initialize the checkflags search system 62 | * 63 | * This is defined in look.c 64 | * 65 | * This is the underpinning of \@find, \@owned, \@entrance, and a few 66 | * other similar calls. It parses over a set of 'flags' to consider, 67 | * and loads the struct 'check' with the necessary filter paramters. 68 | * 69 | * Flags is parsed as follows; it may have an = in it, in which case 70 | * the "right" side of the = is 71 | * 72 | * owners (1), locations (3), links (2), count (4), size (5) or default (0) 73 | * 74 | * The numbers are the "ID"s associated with each type, and are the numbers 75 | * returned by this function. 76 | * 77 | * On the left side are the flags to check for. Flags can be the first 78 | * letter of any flag (like A for ABODE, B for BUILDER, etc.), a number 79 | * for MUCKER levels, or a type: E(xit), (MU)F, G(arbage), P(layer), 80 | * R(oom), and T(hing). God help us if we ever have an overlap in 81 | * flag names and types. 82 | * 83 | * It can also check U(nlinked), \@ (objects older than about 90 days old), 84 | * ~size (match greater than or equal to current memory usage , must be 85 | * last modifier) or ^size (match greater than or equal to total memory 86 | * usage - wizard only, uses ~size for regular players). 87 | * 88 | * @param player the player doing the checking 89 | * @param flags a string containing the flags and output format 90 | * @param check the flgchkdat object to initialize 91 | * @return output type integer 92 | */ 93 | int init_checkflags(dbref player, const char *flags, struct flgchkdat *check); 94 | 95 | /** 96 | * Look at a room 97 | * 98 | * This handles all the nuances of looking at a room; displaying room name, 99 | * description, title, and success prop processing. 100 | * 101 | * @private 102 | * @param descr the descriptor of the looking person 103 | * @param player the looking person 104 | * @param loc the location to look at. 105 | */ 106 | void look_room(int descr, dbref player, dbref loc); 107 | #endif /* !LOOK_H */ 108 | -------------------------------------------------------------------------------- /include/p_mcp.h: -------------------------------------------------------------------------------- 1 | /** @file p_mcp.h 2 | * 3 | * Declaration of MCP calls for MUF. 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #ifndef P_MCP_H 9 | #define P_MCP_H 10 | 11 | #include "interp.h" 12 | 13 | /** 14 | * Implementation of MUF MCP_REGISTER 15 | * 16 | * Consumes a string package name, a float min version, and a float max 17 | * version. This is a thin wrapper around mcp_package_register 18 | * 19 | * @see mcp_package_register 20 | * 21 | * So when you run this function, it registers the CURRENT PROGRAM with 22 | * the given package name. When the MCP is triggered, the current 23 | * program will run with the descriptor and argument array on the stack. 24 | * 25 | * @param player the player running the MUF program 26 | * @param program the program being run 27 | * @param mlev the effective MUCKER level 28 | * @param pc the program counter pointer 29 | * @param arg the argument stack 30 | * @param top the top-most item of the stack 31 | * @param fr the program frame 32 | */ 33 | void prim_mcp_register(PRIM_PROTOTYPE); 34 | 35 | /** 36 | * Implementation of MUF MCP_REGISTER_EVENT 37 | * 38 | * Consumes a string package name, a float min version, and a float max 39 | * version. This is a thin wrapper around mcp_package_register 40 | * 41 | * @see mcp_package_register 42 | * 43 | * Instead of instancing a new MUF call (which MCP_REGISTER does), this 44 | * uses MUF's event system instead. 45 | * 46 | * @param player the player running the MUF program 47 | * @param program the program being run 48 | * @param mlev the effective MUCKER level 49 | * @param pc the program counter pointer 50 | * @param arg the argument stack 51 | * @param top the top-most item of the stack 52 | * @param fr the program frame 53 | */ 54 | void prim_mcp_register_event(PRIM_PROTOTYPE); 55 | 56 | /** 57 | * Implementation of MUF MCP_BIND 58 | * 59 | * Consumes a string package name, a string message name, and a callback 60 | * function reference from the stack. This registers a function to 61 | * service a particular package/message combination. 62 | * 63 | * @param player the player running the MUF program 64 | * @param program the program being run 65 | * @param mlev the effective MUCKER level 66 | * @param pc the program counter pointer 67 | * @param arg the argument stack 68 | * @param top the top-most item of the stack 69 | * @param fr the program frame 70 | */ 71 | void prim_mcp_bind(PRIM_PROTOTYPE); 72 | 73 | /** 74 | * Implementation of MUF MCP_SUPPORTS 75 | * 76 | * Consumes a descriptor and a string package name, and pushes a float 77 | * version number on the stack or 0.0 if the package version is not 78 | * supported. This is to check versions/support of negotiated packages 79 | * for a given descriptor. 80 | * 81 | * @param player the player running the MUF program 82 | * @param program the program being run 83 | * @param mlev the effective MUCKER level 84 | * @param pc the program counter pointer 85 | * @param arg the argument stack 86 | * @param top the top-most item of the stack 87 | * @param fr the program frame 88 | */ 89 | void prim_mcp_supports(PRIM_PROTOTYPE); 90 | 91 | /** 92 | * Implementation of MUF MCP_SEND 93 | * 94 | * Consumes a descriptor integer, a string package name, a string message name, 95 | * and a dictionary mapping string keys to values which are either strings, 96 | * floats, dbrefs, integers, or array lists consisting only of strings. 97 | * 98 | * This "sends" an MCP message which is to say it displays a formatted string 99 | * with the correct structure and prefixing. 100 | * 101 | * @param player the player running the MUF program 102 | * @param program the program being run 103 | * @param mlev the effective MUCKER level 104 | * @param pc the program counter pointer 105 | * @param arg the argument stack 106 | * @param top the top-most item of the stack 107 | * @param fr the program frame 108 | */ 109 | void prim_mcp_send(PRIM_PROTOTYPE); 110 | 111 | /** 112 | * Primitive callback functions 113 | */ 114 | #define PRIMS_MCP_FUNCS prim_mcp_register, prim_mcp_bind, prim_mcp_supports, \ 115 | prim_mcp_send, prim_mcp_register_event 116 | 117 | /** 118 | * Primitive names - must be in same order as the callback functions 119 | */ 120 | #define PRIMS_MCP_NAMES "MCP_REGISTER", "MCP_BIND", "MCP_SUPPORTS", \ 121 | "MCP_SEND", "MCP_REGISTER_EVENT" 122 | 123 | #endif /* !P_MCP_H */ 124 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/91.m: -------------------------------------------------------------------------------- 1 | ( cmd-edit 2 | ( This is a program that will let you replace errors in a message ) 3 | ( or property so that you can fix up typo's without having to ) 4 | ( retype the entire thing. ) 5 | ( ) 6 | ( Usage: edit = or ) 7 | ( edit =@ ) 8 | ( ) 9 | ( CHANGES: Added a 'checkperms' routine to prevent non-wiz users ) 10 | ( from changing @wizard or ~restricted props -- Jessy 7/00 ) 11 | ( ) 12 | 13 | $author Tygryss 14 | $doccmd @list __PROG__=!@1-12 15 | $version 1.02 16 | 17 | : checkperms ( s -- ) 18 | dup "@" stringpfx 19 | over "/@" instr 20 | 3 pick "~" stringpfx 21 | 4 rotate "/~" instr or or or 22 | me @ "W" flag? not and if 23 | "Permission denied." tell pid kill 24 | then 25 | ; 26 | 27 | : replace-text ( str -- str ) 28 | "Please enter the text it should be changed to." tell 29 | "##edit> " swap strcat tell read 30 | ; 31 | 32 | : error 33 | "Name: Edit v1.02 Written by Tygryss Last updated 3/31/92" tell 34 | "Desc: Lets you use the tinyfugue /grab feature to edit a message" tell 35 | " or property. Requires tinyfugue 1.5.0 or later with this" tell 36 | " trigger defined: /def -fg -p100 -t\"##edit> *\" = /grab %-1" tell 37 | " " tell 38 | "Syntax: edit = or" tell 39 | " edit =@" tell 40 | " " tell 41 | " can be name/desc/succ/osucc/fail/ofail/drop/odrop" tell 42 | ; 43 | 44 | : change-main 45 | "me" match me ! 46 | "=" split strip 47 | dup not if error exit then 48 | swap strip 49 | dup not if error exit then 50 | swap dup "@" 1 strncmp if ( property? ) 51 | swap match 52 | dup #-1 dbcmp if 53 | "I don't see that here." 54 | tell exit 55 | then 56 | dup #-2 dbcmp if 57 | "I don't know which one you mean!" 58 | tell exit 59 | then 60 | dup #-3 dbcmp if 61 | "I don't know what you mean!" 62 | tell exit 63 | then 64 | dup owner me @ dbcmp not 65 | me @ "w" flag? not and if 66 | "Permission denied." 67 | tell exit 68 | then 69 | swap over over 70 | dup checkperms 71 | getpropstr 72 | replace-text 73 | dup not if 74 | pop remove_prop 75 | else 76 | 0 addprop 77 | then 78 | "Property changed." tell 79 | else ( ; for message? ) 80 | 1 strcut swap pop 81 | swap match 82 | dup #-1 dbcmp if 83 | "I don't see that here." 84 | tell exit 85 | then 86 | dup #-2 dbcmp if 87 | "I don't know which one you mean!" 88 | tell exit 89 | then 90 | dup #-3 dbcmp if 91 | "I don't know what you mean!" 92 | tell exit 93 | then 94 | dup owner me @ dbcmp not 95 | me @ "w" flag? not and if 96 | "Permission denied." 97 | tell exit 98 | then 99 | swap dup "name" stringcmp not if 100 | over player? if "Cannot change a player's name." tell pop exit then 101 | pop dup name replace-text setname 102 | else dup "desc" stringcmp not if 103 | pop dup desc replace-text setdesc 104 | else dup "succ" stringcmp not if 105 | pop dup succ replace-text setsucc 106 | else dup "osucc" stringcmp not if 107 | pop dup osucc replace-text setosucc 108 | else dup "fail" stringcmp not if 109 | pop dup fail replace-text setfail 110 | else dup "ofail" stringcmp not if 111 | pop dup ofail replace-text setofail 112 | else dup "drop" stringcmp not if 113 | pop dup drop replace-text setdrop 114 | else dup "odrop" stringcmp not if 115 | pop dup odrop replace-text setodrop 116 | else pop error 117 | then then then then then then then then 118 | "Message changed." tell 119 | then 120 | ; 121 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/14.m: -------------------------------------------------------------------------------- 1 | ( **** Message Object -- MSG- **** 2 | A message is a set of elements with a count and an information string, 3 | stored in properties. 4 | 5 | base is a string containing the name of the message. 6 | itemnum is the number of an item within a message. 7 | itemstr is a single item's string. 8 | infostr is the messages information string. 9 | {strrange} is a string range that is all the elements of the message 10 | with an integer count. 11 | 12 | MSG-destroy [base dbref -- ] 13 | Clears and removes the message. 14 | 15 | MSG-create [{strrange} infostr base dbref -- ] 16 | Create a new message with the given items and info string on 17 | the given object with the given name. 18 | 19 | MSG-count [base dbref -- count] 20 | Returns how many items are in the given message. 21 | 22 | MSG-info [base dbref -- infostr] 23 | Returns the information string for the given message. 24 | 25 | MSG-setinfo [infostr base dbref -- ] 26 | Sets the information string on an existing message. 27 | 28 | MSG-message [base dbref -- {strrange}] 29 | Returns the items of a message as a range on the stack. 30 | 31 | MSG-item [itemnum base dbref -- itemstr] 32 | Returns the given message item from the message. 33 | 34 | MSG-setitem [itemstr itemnum base dbref -- ] 35 | Sets the specified message item to the given string. 36 | 37 | MSG-insitem [itemstr itemnum base dbref -- ] 38 | Inserts a new message item into the message at the given point. 39 | 40 | MSG-append [itemstr base dbref -- ] 41 | Appends a message item to the given message. 42 | 43 | MSG-delitem [itemnum base dbref -- ] 44 | Deletes the specified message item from the given message. 45 | 46 | 47 | Message data type: 48 | Base# Count of Message Items 49 | Base#/X Message Items 50 | Base#/i Info String 51 | ) 52 | 53 | $doccmd @list __PROG__=!@1-50 54 | 55 | $include $lib/lmgr 56 | $include $lib/props 57 | 58 | : MSG-destroy (base dbref -- ) 59 | over over swap "#/i" strcat remove_prop 60 | LMGR-deletelist 61 | ; 62 | 63 | : MSG-setinfo (infostr base dbref -- ) 64 | swap 65 | "#" strcat 66 | "/i" strcat rot setpropstr 67 | ; 68 | 69 | : MSG-create ({strrange} infostr base dbref -- ) 70 | over over MSG-destroy 71 | rot 3 pick 3 pick MSG-setinfo 72 | ({strrange} base dbref) 73 | 1 rot rot 74 | LMGR-putrange 75 | ; 76 | 77 | : MSG-count (base dbref -- count) 78 | LMGR-getcount 79 | ; 80 | 81 | : MSG-message (base dbref -- {strrange}) 82 | LMGR-getlist 83 | ; 84 | 85 | : safeclear (d s -- ) 86 | over over propdir? if 87 | over over "" -1 addprop 88 | "" 0 addprop 89 | else 90 | remove_prop 91 | then 92 | ; 93 | 94 | : MSG-clearoldinfo (base dbref -- ) 95 | swap 96 | over over 97 | "#/i" strcat safeclear 98 | ; 99 | 100 | : MSG-oldinfo (base dbref -- infostr) 101 | swap "/i" strcat getpropstr 102 | ; 103 | 104 | : MSG-newinfo (base dbref -- infostr) 105 | swap "#/i" strcat getpropstr 106 | ; 107 | 108 | : convert-info (base dbref value -- ) 109 | 3 pick 3 pick MSG-clearoldinfo 110 | rot rot MSG-setinfo 111 | ; 112 | 113 | : MSG-info (base dbref -- infostr) 114 | over over MSG-newinfo 115 | dup if rot rot pop pop exit then 116 | pop over over MSG-oldinfo 117 | dup if dup -4 rotate convert-info exit then 118 | pop pop pop "" 119 | ; 120 | 121 | : MSG-item (itemnum base dbref -- itemstr) 122 | LMGR-getelem 123 | ; 124 | 125 | : MSG-setitem (itemstr itemnum base dbref -- ) 126 | LMGR-putelem 127 | ; 128 | 129 | : MSG-insitem (itemstr itemnum base dbref -- ) 130 | 1 -4 rotate LMGR-insertrange 131 | ; 132 | 133 | : MSG-append (itemstr base dbref -- ) 134 | over over LMGR-getcount 1 + 135 | rot rot LMGR-putelem 136 | ; 137 | 138 | : MSG-delitem (itemnum base dbref -- ) 139 | 1 -4 rotate LMGR-deleterange 140 | ; 141 | 142 | public MSG-append $libdef MSG-append 143 | public MSG-count $libdef MSG-count 144 | public MSG-create $libdef MSG-create 145 | public MSG-delitem $libdef MSG-delitem 146 | public MSG-destroy $libdef MSG-destroy 147 | public MSG-info $libdef MSG-info 148 | public MSG-insitem $libdef MSG-insitem 149 | public MSG-item $libdef MSG-item 150 | public MSG-message $libdef MSG-message 151 | public MSG-setinfo $libdef MSG-setinfo 152 | public MSG-setitem $libdef MSG-setitem 153 | -------------------------------------------------------------------------------- /game/restart.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # @configure_input@ 3 | # 4 | # Optional arguments are port numbers. 5 | # If none are given, defaults to 4201. 6 | # 7 | 8 | prefix=@prefix@ 9 | exec_prefix=@exec_prefix@ 10 | 11 | # 12 | # You'll want to edit this to match the base directory of your muck's files. 13 | # This should be the directory containing the 'data' and 'muf' directories. 14 | # 15 | GAMEDIR="$prefix/game" 16 | 17 | # If you want your database to be accessible by someone other than the 18 | # user the MUCK is running under, you should change this to the appropriate 19 | # umask value. 077 is owner-only. 20 | UMASK=077 21 | 22 | # 23 | # The following are the paths to the db files to load, save to, and archive to. 24 | # DBOLD is the path and filename of the the previous database archive. 25 | # DBIN is the path and filename of the database to read in. 26 | # DBOUT is the path and filename of the database that the muck should save to. 27 | # 28 | # On a successful restart, DBIN is moved to DBOLD, and DBOUT is moved to DBIN, 29 | # then the server is started. The server will save it's db to DBOUT. 30 | # 31 | DBOLD="$GAMEDIR/data/std-db.old" 32 | DBIN="$GAMEDIR/data/std-db.db" 33 | DBOUT="$GAMEDIR/data/std-db.new" 34 | 35 | 36 | # 37 | # The ports that the MUCK server should listen to. This will be overridden if 38 | # this script is called with port number arguments. If you want an SSL port, 39 | # the MUCK must be configured with --with-ssl, make cert must have been run, 40 | # and you must include "-sport PORTNUM" for each SSL port. 41 | # 42 | PORTS="4201" 43 | 44 | # 45 | # This is the name of the fbmuck program to run. You probably don't want to 46 | # change this unless you renamed the server program to something other than 47 | # fbmuck. 48 | # 49 | SERVER="@bindir@/fbmuck" 50 | 51 | 52 | # 53 | # This is the name of the file to log server restarts to. 54 | # 55 | RESTARTS_LOGFILE="$GAMEDIR/logs/restarts" 56 | 57 | 58 | # 59 | # This is the name of the file that the fbmuck program creates that contains 60 | # the process ID of the server currently running in this game directory. 61 | # You probably don't want to change this unless you change the PID_FILE 62 | # #define in include/config.h 63 | # 64 | PIDFILE="$GAMEDIR/fbmuck.pid" 65 | 66 | 67 | # 68 | # You probably won't need to edit anything after this line. 69 | # 70 | ############################################################################# 71 | ############################################################################# 72 | 73 | 74 | if [ -x /usr/ucb/ps ]; then 75 | PS="/usr/ucb/ps x" 76 | elif ps x >> /dev/null 2>&1 ; then 77 | PS="ps x" 78 | else 79 | PS="ps -e" 80 | fi 81 | 82 | cd $GAMEDIR 83 | # echo "Restarting at: $(date)" 84 | 85 | umask $UMASK 86 | 87 | 88 | if [ -r $PIDFILE -a -s $PIDFILE ]; then 89 | muckpid=$(cat $PIDFILE) 90 | if [ "x$muckpid" != "x" ]; then 91 | serverexec=$(basename $SERVER) 92 | muck=$(${PS} | grep "${serverexec}" | awk '{print $1}' | egrep "\\<${muckpid}\\>" | wc -l) 93 | if [ $muck -gt 0 ]; then 94 | echo "This server is already running. Restart aborted." 95 | exit 1 96 | fi 97 | fi 98 | fi 99 | 100 | 101 | PANICDB="${DBOUT}.PANIC" 102 | if [ -r $PANICDB ]; then 103 | end=$(tail -1 $PANICDB) 104 | if [ "x$end" = "x***END OF DUMP***" ]; then 105 | mv $PANICDB $DBOUT 106 | else 107 | echo "Warning: PANIC dump failed on "$(date) | mail $(whoami) 108 | fi 109 | fi 110 | 111 | if [ -r $DBOUT ]; then 112 | mv -f $DBIN $DBOLD 113 | mv $DBOUT $DBIN 114 | fi 115 | 116 | if [ ! -r $DBIN ]; then 117 | echo "Hey! The $DBIN file has to exist and be readable to restart the server!" 118 | echo "Restart attempt aborted." 119 | exit 2 120 | fi 121 | 122 | end=$(tail -1 $DBIN) 123 | if [ "x$end" != 'x***END OF DUMP***' ]; then 124 | echo "WARNING! The $DBIN file is incomplete and therefore corrupt!" 125 | echo "Restart attempt aborted." 126 | exit 3 127 | fi 128 | 129 | dbsiz=$(ls -1s $DBIN | awk '{print $1}') 130 | diskfree=$(df -k . | tail -1 | awk '{print $4}') 131 | 132 | diskneeded=$(expr $dbsiz \* 3) 133 | spacediff=$(expr $diskneeded - $diskfree) 134 | 135 | if [ $diskfree -lt $diskneeded ]; then 136 | echo "WARNING: you have insufficient disk space." 137 | echo "The server is starting anyways, but you should immediately remove" 138 | echo "old log files, etc. to free up about ${spacediff}K more disk space." 139 | fi 140 | 141 | if [ "x$*" != "x" ]; then 142 | PORTS=$* 143 | fi 144 | 145 | mkdir -p logs 146 | 147 | touch $RESTARTS_LOGFILE 148 | echo "$(date +%Y-%m-%dT%H:%M:%S): $(who am i)" >> $RESTARTS_LOGFILE 149 | 150 | # echo "Server started at: $(date)" 151 | $SERVER -gamedir $GAMEDIR -dbin $DBIN -dbout $DBOUT $PORTS 152 | -------------------------------------------------------------------------------- /tests/command-cases/p_math.yml: -------------------------------------------------------------------------------- 1 | - name: past-max-localvar-pp 2 | setup: | 3 | @program test.muf 4 | 1 i 5 | : main max_variable_count localvar ++ ; 6 | . 7 | c 8 | q 9 | @act test=here 10 | @link test=test.muf 11 | commands: | 12 | test 13 | expect: 14 | - "Program Error" 15 | - name: past-max-localvar-mm 16 | setup: | 17 | @program test.muf 18 | 1 i 19 | : main max_variable_count localvar -- ; 20 | . 21 | c 22 | q 23 | @act test=here 24 | @link test=test.muf 25 | commands: | 26 | test 27 | expect: 28 | - "Program Error" 29 | - name: past-max-var-pp 30 | setup: | 31 | @program test.muf 32 | 1 i 33 | : main max_variable_count variable ++ ; 34 | . 35 | c 36 | q 37 | @act test=here 38 | @link test=test.muf 39 | commands: | 40 | test 41 | expect: 42 | - "Program Error" 43 | - name: past-max-var-mm 44 | setup: | 45 | @program test.muf 46 | 1 i 47 | : main max_variable_count variable -- ; 48 | . 49 | c 50 | q 51 | @act test=here 52 | @link test=test.muf 53 | commands: | 54 | test 55 | expect: 56 | - "Program Error" 57 | - name: past-max-svar-pp 58 | setup: | 59 | @program test.muf 60 | 1 i 61 | : bad_scoped_var var my_scoped my_scoped ; 62 | : main bad_scoped_var ++ ; 63 | . 64 | c 65 | q 66 | @act test=here 67 | @link test=test.muf 68 | commands: | 69 | test 70 | expect: 71 | - "Program Error" 72 | - name: past-max-svar-mm 73 | setup: | 74 | @program test.muf 75 | 1 i 76 | : bad_scoped_var var my_scoped my_scoped ; 77 | : main bad_scoped_var -- ; 78 | . 79 | c 80 | q 81 | @act test=here 82 | @link test=test.muf 83 | commands: | 84 | test 85 | expect: 86 | - "Program Error" 87 | - name: at-max-localvar-pp 88 | setup: | 89 | @program test.muf 90 | 1 i 91 | : main 92 | max_variable_count 1 - localvar 93 | (stack contains localvar#max) 94 | 42 over ! 95 | (set to 42) 96 | dup ++ 97 | (increment to 43) 98 | @ 99 | (retrieve value) 100 | me @ swap intostr notify 101 | ; 102 | . 103 | c 104 | q 105 | @act test=here 106 | @link test=test.muf 107 | commands: | 108 | test 109 | expect: 110 | - "43" 111 | - name: at-max-localvar-mm 112 | setup: | 113 | @program test.muf 114 | 1 i 115 | : main 116 | max_variable_count 1 - localvar 117 | (stack contains localvar#max) 118 | 42 over ! 119 | (set to 42) 120 | dup -- 121 | (decrement to 43) 122 | @ 123 | (retrieve value) 124 | me @ swap intostr notify 125 | ; 126 | . 127 | c 128 | q 129 | @act test=here 130 | @link test=test.muf 131 | commands: | 132 | test 133 | expect: 134 | - "41" 135 | - name: at-max-var-pp 136 | setup: | 137 | @program test.muf 138 | 1 i 139 | : main 140 | max_variable_count 1 - variable 141 | (stack contains var#max) 142 | 42 over ! 143 | (set to 42) 144 | dup ++ 145 | (increment to 43) 146 | @ 147 | (retrieve value) 148 | me @ swap intostr notify 149 | ; 150 | . 151 | c 152 | q 153 | @act test=here 154 | @link test=test.muf 155 | commands: | 156 | test 157 | expect: 158 | - "43" 159 | - name: at-max-var-mm 160 | setup: | 161 | @program test.muf 162 | 1 i 163 | : main 164 | max_variable_count 1 - variable 165 | (stack contains var#max) 166 | 42 over ! 167 | (set to 42) 168 | dup -- 169 | (increment to 41) 170 | @ 171 | (retrieve value) 172 | me @ swap intostr notify 173 | ; 174 | . 175 | c 176 | q 177 | @act test=here 178 | @link test=test.muf 179 | commands: | 180 | test 181 | expect: 182 | - "41" 183 | - name: scoped-var-pp 184 | setup: | 185 | @program test.muf 186 | 1 i 187 | : main 188 | var x 189 | 42 x ! 190 | x ++ 191 | me @ x @ intostr notify 192 | ; 193 | . 194 | c 195 | q 196 | @act test=here 197 | @link test=test.muf 198 | commands: | 199 | test 200 | expect: 201 | - "43" 202 | - name: scoped-var-mm 203 | setup: | 204 | @program test.muf 205 | 1 i 206 | : main 207 | var x 208 | 42 x ! 209 | x -- 210 | me @ x @ intostr notify 211 | ; 212 | . 213 | c 214 | q 215 | @act test=here 216 | @link test=test.muf 217 | commands: | 218 | test 219 | expect: 220 | - "41" 221 | -------------------------------------------------------------------------------- /tests/command-cases/p_stack.yml: -------------------------------------------------------------------------------- 1 | - name: checkargs-multiple-okay 2 | setup: | 3 | @program test.muf 4 | i 5 | : main pop 6 | "string" #0 #1 #-1 #-2 42 7 | "sddddi" checkargs 8 | "sd4i" checkargs 9 | "sRPddi" checkargs 10 | "RPddi" checkargs 11 | me @ "Complete." notify 12 | ; 13 | . 14 | c 15 | q 16 | @act test=here 17 | @link test=test.muf 18 | commands: | 19 | test 20 | expect: 21 | - "Complete" 22 | 23 | - name: checkargs-single-ranges-okay 24 | setup: | 25 | @program test.muf 26 | i 27 | : main pop 28 | { "X" }list 1 0 "xxx" "string" 2 #0 #1 #-1 #-2 4 29 | "{y}{?}{s}{d}" checkargs 30 | "yii{s}{d}" checkargs 31 | "{y}{f}{s}{d}" checkargs 32 | "{ y }{ f }{ s }{ d }" checkargs 33 | me @ "Complete." notify 34 | ; 35 | . 36 | c 37 | q 38 | @act test=here 39 | @link test=test.muf 40 | commands: | 41 | test 42 | expect: 43 | - "Complete" 44 | 45 | - name: checkargs-multi-ranges-okay 46 | setup: | 47 | @program test.muf 48 | i 49 | : main pop 50 | "~" { "X" }list 1 0 42 "xxx" 43 "string" 2 #0 #1 #-1 #-2 4 51 | "{sy}{?}{is}{d}" checkargs 52 | "{sy}{FFFF}{is}{d}" checkargs 53 | "{ s y } { ? }{ i s } { d }" checkargs 54 | me @ "Complete." notify 55 | ; 56 | . 57 | c 58 | q 59 | @act test=here 60 | @link test=test.muf 61 | commands: | 62 | test 63 | expect: 64 | - "Complete" 65 | 66 | - name: checkargs-empty-range 67 | setup: | 68 | @program test.muf 69 | i 70 | : main pop 71 | 0 "{}" checkargs 72 | 1 "{}" checkargs 73 | 1000 "{}" checkargs 74 | me @ "Complete." notify 75 | ; 76 | . 77 | c 78 | q 79 | @act test=here 80 | @link test=test.muf 81 | commands: | 82 | test 83 | expect: 84 | - "Complete" 85 | 86 | - name: checkargs-empty-range-negative 87 | setup: | 88 | @program test.muf 89 | i 90 | : main pop 91 | -1 "{}" checkargs 92 | ; 93 | . 94 | c 95 | q 96 | @act test=here 97 | @link test=test.muf 98 | commands: | 99 | test 100 | expect: 101 | - "Program Error" 102 | 103 | - name: checkargs-huge-empty-range1 104 | setup: | 105 | @program test.muf 106 | i 107 | : main pop 108 | 1000 1000 * 1000 * "{}" checkargs 109 | me @ "Complete." notify 110 | ; 111 | . 112 | c 113 | q 114 | @act test=here 115 | @link test=test.muf 116 | commands: | 117 | test 118 | timeout: 1 119 | expect: 120 | - "Complete" 121 | 122 | - name: checkargs-huge-empty-range2 123 | setup: | 124 | @program test.muf 125 | i 126 | : main pop 127 | 1000 1000 * 1000 * "{ }" checkargs 128 | me @ "Complete." notify 129 | ; 130 | . 131 | c 132 | q 133 | @act test=here 134 | @link test=test.muf 135 | commands: | 136 | test 137 | timeout: 1 138 | expect: 139 | - "Complete" 140 | 141 | - name: deepcopy-pinned-array-nocycle 142 | setup: | 143 | @program test.muf 144 | i 145 | : main 146 | { "x0" "x1" }list ARRAY_PIN var! x 147 | { "y0" "y1" }list ARRAY_PIN var! y 148 | y @ x @ 1 ARRAY_SETITEM POP 149 | x @ DEEP_COPY ARRAY_PIN var! x_copy 150 | "changed-in-orig" x @ { 1 1 }list ARRAY_NESTED_SET 151 | "changed-in-copy" x_copy @ { 1 0 }list ARRAY_NESTED_SET 152 | me @ "x->1->0=" x @ 1 ARRAY_GETITEM 0 ARRAY_GETITEM strcat notify 153 | me @ "x->1->1=" x @ 1 ARRAY_GETITEM 1 ARRAY_GETITEM strcat notify 154 | me @ "x_copy->1->0=" x_copy @ 1 ARRAY_GETITEM 0 ARRAY_GETITEM strcat notify 155 | me @ "x_copy->1->1=" x_copy @ 1 ARRAY_GETITEM 1 ARRAY_GETITEM strcat notify 156 | me @ "y->0=" y @ 0 ARRAY_GETITEM strcat notify 157 | me @ "y->1=" y @ 1 ARRAY_GETITEM strcat notify 158 | ; 159 | . 160 | c 161 | q 162 | @act test=here 163 | @link test=test.muf 164 | commands: | 165 | test 166 | expect: 167 | - "x->1->0=y0" 168 | - "x->1->1=changed-in-orig" 169 | - "x_copy->1->0=changed-in-copy" 170 | - "x_copy->1->1=y1" 171 | - "y->0=y0" 172 | - "y->1=changed-in-orig" 173 | 174 | - name: deepcopy-array-cycle 175 | setup: | 176 | @program test.muf 177 | i 178 | : main 179 | { 1 2 3 }list ARRAY_PIN var! x 180 | { 4 5 6 }list ARRAY_PIN var! y 181 | x @ y @ 0 ARRAY_SETITEM POP 182 | y @ x @ 0 ARRAY_SETITEM POP 183 | x @ DEEP_COPY 184 | ; 185 | . 186 | c 187 | q 188 | @act test=here 189 | @link test=test.muf 190 | commands: | 191 | test 192 | expect: 193 | - "Program Error" 194 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/34.m: -------------------------------------------------------------------------------- 1 | ( cmd-laston.muf by Natasha@HLM 2 | A laston for Fuzzball 6. 3 | 4 | Forked from cmd-whodoing for Fuzzball 6. Factored table code into $lib/table. 5 | 6 | Copyright 2002 Natasha O'Brien. Copyright 2002 Here Lie Monsters. 7 | "@view $box/mit" for license information. 8 | 9 | Version history 10 | 1.001, 16 March 2003: don't use .rtimestr macro, use rtimestr in 11 | $lib/timestr. Default USE_ATLASTON to on. 12 | 13 | 1.002, 29 August 2023: if a stale dbref is on your wf list [a toaded player] 14 | then laston #wf would fail with a crash error. Added a filtering for 15 | non-player refs on the wf list. [HopeIslandCoder] 16 | ) 17 | $author Natasha O'Brien 18 | $version 1.002 19 | $note A Fuzzball 6 laston. 20 | 21 | $include $lib/strings 22 | $include $lib/table 23 | $include $lib/timestr 24 | $iflib $lib/alias $include $lib/alias $endif ( Honor aliases issue417 Natasha@HLM 9 January 2003 ) 25 | 26 | $def prop_wsobject "_prefs/ws/object" 27 | $def prop_wflist "_prefs/wf/list" 28 | $def prop_def "_prefs/laston/def" 29 | $def prop_laston "@/last/on" 30 | $def prop_lastoff "@/last/off" 31 | 32 | ( Uncomment if a _connect event sets users' @/laston properties. ) 33 | $def USE_ATLASTON 34 | 35 | var lineformat 36 | var metadata 37 | 38 | 39 | : rtn-lasttime ( db strProp -- intTime } Gets the systime in the given property. If the program is not configured to use @/laston properties, the player's last usetime time of connection} is used instead. ) 40 | $ifdef USE_ATLASTON 41 | getpropstr ( strTime ) 42 | dup number? if atoi else pop -1 then ( intTime ) 43 | $else 44 | pop timestamps pop -3 rotate pop pop ( intTime ) 45 | $endif 46 | ; 47 | 48 | : rtn-lastcon ( db -- intTime } Gets the systime when the given dbref most recently connected. ) 49 | prop_laston rtn-lasttime 50 | ; 51 | : rtn-lastdiscon ( db -- intTime } Gets the systime when the given dbref most recently disconnected. Use this time for when a player was last 'on.' ) 52 | prop_lastoff rtn-lasttime 53 | ; 54 | 55 | 56 | ( ** data getters { db -- str } ) 57 | : get-name name ; 58 | : get-con rtn-lastcon "%R %e %b %Y" swap timefmt ; 59 | : get-discon rtn-lastdiscon "%R %e %b %Y" swap timefmt ; 60 | 61 | : get-laston ( db -- str ) 62 | dup awake? if pop "\[[1;32mOnline now\[[0m" exit then ( db ) 63 | rtn-lastdiscon dup -1 = if ( intTime ) 64 | pop "\[[1;33mNever connected\[[0m" exit ( str ) 65 | then ( intTime ) 66 | systime swap - ( intSince ) 67 | rtimestr ( str ) 68 | ; 69 | 70 | 71 | ( ** list makers { str -- arr } ) 72 | : do-help pop .showhelp "exit" abort ; 73 | : do-all 74 | dup not if do-help then 75 | $iflib $lib/alias 76 | me @ swap alias-expand ( Honor aliases issue417 Natasha@HLM 9 January 2003 ) 77 | $else 78 | pmatch dup ok? if 1 array_make else pop 0 array_make then 79 | $endif 80 | ; 81 | : do-watchfor 82 | pop me @ prop_wflist array_get_reflist 83 | 84 | ( Filter out invalid ref's ) 85 | 0 array_make 86 | swap foreach 87 | swap pop 88 | dup player? if 89 | swap array_appenditem 90 | else 91 | pop 92 | then 93 | repeat 94 | ; 95 | : do-room ( strY -- arr ) 96 | pop loc @ contents_array ( arrContents ) 97 | 0 array_make swap foreach swap pop ( arrPlayers db ) 98 | dup player? if swap array_appenditem else pop then 99 | repeat ( arrPlayers ) 100 | ; 101 | 102 | 103 | $define dict_commands { 104 | "" 'do-all 105 | "room" 'do-room 106 | "here" 'do-room 107 | "wf" 'do-watchfor 108 | "wat" 'do-watchfor 109 | "watchfor" 'do-watchfor 110 | "help" 'do-help 111 | }dict $enddef 112 | 113 | 114 | : main ( str -- ) 115 | dup not if pop me @ prop_def getpropstr then ( str ) 116 | 117 | STRparse pop ( strX strY ) 118 | swap dict_commands over array_getitem ( strY strX ? ) 119 | dup address? not if ( strY strX ? ) 120 | pop "I don't know what you mean by '#%s'." fmtstring tell ( strY ) 121 | pop exit ( ) 122 | then ( strY strX adr ) 123 | swap pop ( strY adr ) 124 | 125 | "%-16.16[name]s %-18.18[laston]s %-20.20[con]s %-20.20[discon]s" lineformat ! 126 | { 127 | "name" 'get-name 128 | "laston" 'get-laston 129 | "con" 'get-con 130 | "discon" 'get-discon 131 | }dict metadata ! ( strY adr ) 132 | 133 | 2 try 134 | execute ( arr ) 135 | catch exit endcatch ( arr ) 136 | dup array_count not if ( arr ) 137 | "No one to show." tell ( arr ) 138 | pop exit ( ) 139 | then ( arr ) 140 | 141 | lineformat @ ( arr strLinefmt ) 142 | { "name" "\[[1;37mName" "laston" "\[[1;37mLast on" "con" "\[[1;37mLast connected" "discon" "\[[1;37mLast disconnected" }dict ( arr strLinefmt dictHeaders ) 143 | metadata @ ( arr strLinefmt dictHeaders dictProcessors ) 144 | 4 rotate ( strLinefmt dictHeaders dictProcessors arr ) 145 | 146 | table-table ( ) 147 | ; 148 | -------------------------------------------------------------------------------- /include/diskprop.h: -------------------------------------------------------------------------------- 1 | /** @file diskprop.h 2 | * 3 | * Header for diskprops - disk based properties for the diskbase database 4 | * system. 5 | * 6 | * Diskprop is used to store properties on disk instead of memory, to 7 | * save compute resources on memory-tight systems. It is part of the DISKBASE 8 | * system which seeks to keep things on the disk unless they are needed. 9 | * 10 | * It requires the DISKBASE define be set. 11 | * 12 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 13 | */ 14 | #include "config.h" 15 | 16 | #ifdef DISKBASE 17 | #ifndef DISKPROP_H 18 | #define DISKPROP_H 19 | 20 | #include "props.h" 21 | 22 | /** 23 | * Set an object as having 'dirty' or changed props 24 | * 25 | * Does the necessary addition to the ring-queue as well 26 | * 27 | * @param obj the object to befoul 28 | */ 29 | void dirtyprops(dbref obj); 30 | 31 | /** 32 | * Call to dispaly property cache information and disk fetch statistics 33 | * 34 | * Dumps a bunch of performance relevant data to the user. 35 | * 36 | * @param player the player to display information to 37 | */ 38 | void display_propcache(dbref player); 39 | 40 | /** 41 | * Iterate over the entire database and expire properties based on time 42 | * 43 | * Expires properties on objects who have propstime older than 44 | * tp_clean_interval 45 | */ 46 | void dispose_all_oldprops(void); 47 | 48 | 49 | /** 50 | * Fetch properties for an object 51 | * 52 | * Checks to see if the object's properties are already loaded first, 53 | * and if not, will fetch them. This also runs the periodic clean-up 54 | * of properties to keep the cache from getting too large. 55 | * 56 | * @param obj the object to fetch properties for 57 | * @param pdir the prop directory to load, or NULL for "/" 58 | */ 59 | void fetchprops(dbref obj, const char *pdir); 60 | 61 | /** 62 | * Fetch property values off the disk 63 | * 64 | * This recursively fetches property values off the disk. Typically, 65 | * you would pass "/" as the dir to get an entire property structure 66 | * for the given object. 67 | * 68 | * @param obj the object to load properties for. 69 | * @param dir the directory to load property values for 70 | * @return boolean true if props were fetched, false if not 71 | */ 72 | int fetch_propvals(dbref obj, const char *dir); 73 | 74 | /** 75 | * @var PID of the process doing a DB dump 76 | */ 77 | extern pid_t global_dumper_pid; 78 | 79 | /** 80 | * @var the number of cache "hits" (successful use of cache) we get 81 | */ 82 | extern long propcache_hits; 83 | 84 | /** 85 | * @var the number of cache "misses" (requiring the loading of properties) 86 | * we get 87 | */ 88 | extern long propcache_misses; 89 | 90 | /** 91 | * Fetch a single property 'p', loading the data into it 92 | * 93 | * @param obj the object the property belongs to 94 | * @param p the property structure to load data for 95 | * @return boolean true if property was loaded 96 | */ 97 | int propfetch(dbref obj, PropPtr p); 98 | 99 | /** 100 | * This handles writing properties to the disk for the diskbase system 101 | * 102 | * It is called by db_write_object - @see db_write_object 103 | * 104 | * The reason it is called _copy is because if properties are not loaded 105 | * in memory, this function will load the prop data off the input_file 106 | * and write it to 'f' as a straight copy. 107 | * 108 | * @param f the file to write out to 109 | * @param obj the object to write properties for 110 | */ 111 | void putprops_copy(FILE * f, dbref obj); 112 | 113 | /** 114 | * Skip over the properties block in file handle 'f' 115 | * 116 | * This assumes the next line in 'f' is the *Props* marker that starts 117 | * the prop list. This is prety vulnerable against malformed files; 118 | * there is no error checking here. 119 | * 120 | * If there are LISTEN_PROPQUEUE, WLISTEN_PROPQUEUE, or WOLISTEN_PROPQUEUE 121 | * props then the "LISTENER" flag will be added to 'obj'. Otherwise, 122 | * the flag will be removed if already set. 123 | * 124 | * The file handle will be positioned ready to read the next line after 125 | * the prop's *End* line. 126 | * 127 | * @param f the file handle to work on 128 | * @param obj the current object we are skipping properties for 129 | */ 130 | void skipproperties(FILE * f, dbref obj); 131 | 132 | /** 133 | * Clear all in-memory properties off the given object 134 | * 135 | * Does all necessary cleanup; sets PROPS_UNLOADED, removes it from 136 | * the ringqueue that keeps track of objects with loaded properties, etc. 137 | * 138 | * @param obj the object to clean up props for 139 | */ 140 | void unloadprops_with_prejudice(dbref obj); 141 | 142 | /** 143 | * Remove 'dirty' or changed props setting 144 | * 145 | * This removes the props from the object as well. It does nothing if 146 | * the props are not loaded. 147 | * 148 | * @param obj the object to undirty 149 | */ 150 | void undirtyprops(dbref obj); 151 | 152 | #endif /* !DISKPROP_H */ 153 | #endif /* DISKBASE */ 154 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/66.m: -------------------------------------------------------------------------------- 1 | ( smell6.muf by Natasha@HLM 2 | A smell, feel, and taste program for Fuzzball 6. 3 | 4 | Copyright 2002 Natasha O'Brien. Copyright 2002 Here Lie Monsters. 5 | "@view $box/mit" for license information. 6 | ) 7 | $author Natasha O'Brien 8 | $version 1.0 9 | $note A smell, feel, and taste program for Fuzzball 6. 10 | 11 | $include $lib/match 12 | $include $lib/strings 13 | 14 | $define dict_pastforms { 15 | "feel" "felt" 16 | "taste" "tasted" 17 | }dict $enddef 18 | 19 | var obj 20 | 21 | : rtn-parse ( db str -- str' ) 22 | dup "%ved" instr if 23 | dict_pastforms command @ array_getitem ( db str' strVed ) 24 | dup not if pop command @ "ed" strcat then ( db str' strVed ) 25 | "%ved" subst ( db str' ) 26 | then ( db str' ) 27 | 28 | command @ "%v" subst ( db str' ) 29 | obj @ "%obj" subst ( db str' ) 30 | 31 | over name "%N" subst ( db str' ) 32 | pronoun_sub ( str' ) 33 | ; 34 | 35 | : rtn-set-notify ( strSucc strProp strQ strY -- ) 36 | dup not if pop ( strSucc strProp strQ ) 37 | command @ swap fmtstring tell ( strSucc strProp ) 38 | read strip ( strSucc strProp strY' ) 39 | dup "." strcmp not if pop "Cancelled." tell exit then ( strSucc strProp strY' ) 40 | dup not if ( strSucc strProp strY' ) 41 | pop swap pop ( strProp ) 42 | me @ command @ rot fmtstring remove_prop ( ) 43 | "Cleared." tell exit ( ) 44 | then ( strSucc strProp strY' ) 45 | else swap pop then ( strSucc strProp strY ) 46 | 47 | me @ command @ 4 rotate fmtstring ( strSucc strY dbMe strProp' ) 48 | 3 pick setprop ( strSucc strY ) 49 | command @ rot fmtstring tell ( ) 50 | ; 51 | 52 | : do-set 53 | "Your %s message has been set to: %s" "_prefs/%s" "What do you want to %s like? Enter '.' to cancel or ' ' (space) to clear." 54 | 4 rotate rtn-set-notify 55 | ; 56 | 57 | : do-notify ( strY -- ) 58 | "Your %s notify message has been set to: %s" "_prefs/%s_notify" "What do you want to see when someone %ss you? Enter '.' to cancel or ' ' to clear." 59 | 4 rotate rtn-set-notify 60 | ; 61 | 62 | : do-help pop .showhelp ; 63 | 64 | $define dict_hashcmds { 65 | "set" 'do-set 66 | "format" 'do-notify 67 | "notify" 'do-notify 68 | "help" 'do-help 69 | }dict $enddef 70 | 71 | : main 72 | command @ tolower command ! 73 | 74 | STRparse dup if "=" swap strcat strcat else pop then ( strX strY ) 75 | over over or not if pop pop "help" "" then ( strX strY ) 76 | 77 | swap dup if ( strY strZ ) 78 | dict_hashcmds over array_getitem ( strY strX ? ) 79 | dup address? if ( strY strX adr ) 80 | swap pop execute ( ) 81 | else pop ( strY strX ) 82 | "I don't know what you mean by '#%s'." fmtstring tell ( strY ) 83 | pop ( ) 84 | then exit ( ) 85 | then pop ( strY ) 86 | 87 | ( Whom am I %verbing? ) 88 | "you" obj ! 89 | dup match dup ok? if ( strY db ) 90 | swap pop ( db ) 91 | dup room? if ( db ) 92 | "here" obj ! 93 | dup contents_array 0 array_insertitem ( arrDb ) 94 | else 95 | 1 array_make ( arrDb ) 96 | then ( arrDb ) 97 | else ( strY db ) 98 | pop ( strY ) 99 | " " explode_array ( arrStr ) 100 | 0 array_make swap foreach swap pop ( arrDb str ) 101 | noisy_match dup ok? if swap array_appenditem else pop then ( arrDb ) 102 | repeat ( arrDb ) 103 | then ( arrDb ) 104 | dup array_count ( arrDb intHowMany ) 105 | dup not if pop pop exit then ( arrDb intHowMany ) 106 | 1 - var! mult ( arrDb ) 107 | 108 | foreach swap pop ( db ) 109 | dup command @ "(%s)" fmtstring 0 ( db db strHow boolOdelay ) 110 | 111 | ( Message. ) 112 | 3 pick 3 pick 3 pick ( db db strHow boolOdelay db strHow boolOdelay ) 113 | "_prefs/" command @ strcat -3 rotate ( db db strHow boolOdelay db strProp strHow boolOdelay ) 114 | parseprop ( db db strHow boolOdelay strValue ) 115 | dup not if pop "You %v nothing special." then ( db db strHow boolOdelay strValue ) 116 | 4 pick swap rtn-parse ( db db strHow boolOdelay strValue ) 117 | mult @ if 4 pick "%D: %s" fmtstring then ( db db strHow boolOdelay strValue ) 118 | tell ( db db strHow boolOdelay ) 119 | 120 | ( Notify. ) 121 | command @ "_prefs/%s_notify" fmtstring ( db db strHow boolOdelay strProp ) 122 | 4 pick over getprop int? if ( db db strHow boolOdelay strProp ) 123 | pop pop pop pop "[ %N just %ved %obj! ]" ( db strNotify ) 124 | else ( db db strHow boolOdelay strProp ) 125 | -3 rotate ( db db strProp strHow boolOdelay ) 126 | parseprop ( db strNotify ) 127 | then ( db strNotify ) 128 | dup strip if 129 | me @ swap rtn-parse ( db strNotify ) 130 | notify ( ) 131 | else pop pop then ( ) 132 | repeat ( ) 133 | ; 134 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/60.m: -------------------------------------------------------------------------------- 1 | ( cmd-mv-cp 2 | cp [origobj][=prop],[destobj][=destprop] 3 | Copies prop from origobj to destobj, renaming it to destprop. 4 | 5 | mv [origobj][=prop],[destobj][=destprop] 6 | Moves prop from origobj to destobj, renaming it to destprop. 7 | 8 | Arguments in []s are optional. 9 | if origobj is omitted, it assumes a property on the user. 10 | if destobj is omitten, it assumes destobj is the same as origobj. 11 | if destprop is omitted, it assumes the same name as prop. 12 | if prop is omitted, it prompts for it. 13 | if both prop and origobj are omitted, it prompts for both. 14 | if both destobj and destprop are omitted, it prompts for them. 15 | 16 | CHANGES: 17 | 9/99 Added checkperms [ s -- ] to allow the program to safely be 18 | set Wizard. cp and mv will copy or move ~ and @ props only if the 19 | user is a !Quelled Wizard. -- Jessy 20 | 9/99 Added a line at the beginning of main to catch dbref spoofing. 21 | -- Jessy 22 | 6/2019 Fixed it so prop type is preserved on copy/move, generally 23 | modernized the code around prop handling as it has a lot of FB4 24 | and FB5 era weirdness. [tanabi] 25 | ) 26 | 27 | $doccmd @list __PROG__=!@1-22 28 | 29 | $include $lib/match 30 | 31 | lvar copy? 32 | 33 | : checkperms ( s -- ) 34 | dup "@" stringpfx 35 | over "/@" instr 36 | 3 pick "~" stringpfx 37 | 4 rotate "/~" instr or or or 38 | me @ "W" flag? not and if 39 | "Permission denied." tell pid kill 40 | then 41 | ; 42 | 43 | : cp-mv-prop ( d s d s -- i ) 44 | dup checkperms 45 | 3 pick checkperms 46 | 47 | 4 pick 4 pick getprop ( d s d s ? ) 48 | 49 | dup if 50 | 3 pick 3 pick rot setprop 51 | else 52 | pop 4 pick 4 pick propdir? not if 53 | "I don't see what property to " 54 | copy? @ if "copy." else "move." then 55 | strcat tell pop pop pop pop 0 exit 56 | then 57 | then 58 | 59 | 4 pick 4 pick propdir? if 60 | 4 pick dup 5 pick "/" strcat nextprop 61 | (d s dd ds d ss) 62 | begin 63 | dup while 64 | over dup 3 pick nextprop 65 | 4 rotate 4 rotate 66 | 6 pick 6 pick "/" strcat 67 | 3 pick dup "/" rinstr 68 | strcut swap pop strcat 69 | cp-mv-prop pop 70 | repeat 71 | pop pop 72 | then 73 | 74 | pop pop 75 | copy? @ not if remove_prop else pop pop then 76 | 1 77 | ; 78 | 79 | : cp-prop ( d s d s -- i ) 80 | 1 copy? ! cp-mv-prop 81 | ; 82 | 83 | : mv-prop ( d s d s -- i ) 84 | 0 copy? ! cp-mv-prop 85 | ; 86 | 87 | : strip-slashes ( s -- s' ) 88 | begin 89 | dup while 90 | dup strlen 1 - strcut 91 | dup "/" strcmp if strcat exit then 92 | pop 93 | repeat 94 | ; 95 | 96 | : parse-command ( s -- ) 97 | "me" match me ! 98 | command @ tolower 99 | "command @ = \"" over strcat "\"" strcat tell 100 | "c" instr copy? ! 101 | 102 | dup "#help" stringcmp not if 103 | pop { 104 | copy? @ if 105 | "cp origobj=prop,destobj=destprop" 106 | " Copies prop from origobj to destobj, renaming it to destprop." 107 | else 108 | "mv origobj=prop,destobj=destprop" 109 | " Moves prop from origobj to destobj, renaming it to destprop." 110 | then 111 | " " 112 | " if origobj is omitted, it assumes a property on the user." 113 | " if destobj is omitted, it assumes destobj is the same as origobj." 114 | " if destprop is omitted, it assumes it is the same name as prop." 115 | " if prop is omitted, it asks the user for it." 116 | " if both prop and origobj are omitted, it asks the user for both." 117 | " if both destobj and destprop are omitted, it asks the user for them." 118 | }tell exit 119 | then 120 | 121 | "," split strip swap strip 122 | "=" split strip swap strip 123 | dup if 124 | noisy_match 125 | dup not if pop exit then 126 | else 127 | over not if 128 | "Please enter the name of the original object." 129 | tell pop read strip 130 | then 131 | dup if 132 | noisy_match 133 | dup not if pop exit then 134 | else pop me @ 135 | then 136 | then 137 | -3 rotate 138 | begin 139 | strip-slashes 140 | dup not while 141 | "Please enter the name of the original property." tell 142 | pop read strip 143 | repeat 144 | swap 145 | "=" split strip strip-slashes swap strip 146 | begin 147 | over over or not while 148 | pop pop 149 | "Please enter the name of the destination object." tell 150 | read strip 151 | "Please enter the name of the destination property." tell 152 | read strip 153 | strip-slashes swap 154 | repeat 155 | dup if 156 | noisy_match 157 | dup not if pop exit then 158 | else 159 | pop 3 pick 160 | then 161 | swap 162 | dup not if pop over then 163 | 164 | (origdbref origpropname destdbref destpropname) 165 | cp-mv-prop if 166 | copy? @ if "Property copied." 167 | else "Property moved." 168 | then tell 169 | then 170 | ; 171 | 172 | public cp-prop 173 | public mv-prop 174 | 175 | $pubdef copy-prop __PROG__ "cp-prop" call 176 | $pubdef move-prop __PROG__ "mv-prop" call 177 | -------------------------------------------------------------------------------- /include/log.h: -------------------------------------------------------------------------------- 1 | /** @file log.h 2 | * 3 | * Header that supports the MUCK's logging system. Anything that wants to 4 | * log (which is pretty much everything) will include this. 5 | * 6 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 7 | */ 8 | 9 | #ifndef LOG_H 10 | #define LOG_H 11 | 12 | #include "config.h" 13 | #include "inst.h" 14 | 15 | /** 16 | * Log a string to a file, with sprinf-style replacements 17 | * 18 | * @param myfilename the file to write to 19 | * @param format the format string with sprinf-style replacements 20 | * @param ... whatever sprintf replacement variables 21 | */ 22 | void log2file(const char *myfilename, const char *format, ...); 23 | 24 | /** 25 | * Log to the commands file 26 | * 27 | * The commands file is configured with tp_file_log_commands. 28 | * 29 | * This attaches a timestamp to 'format' and does sprintf-style replacements 30 | * with a variable argument list. 31 | * 32 | * @param format the log line to submit 33 | * @param ... the arguments 34 | */ 35 | void log_command(const char *format, ...); 36 | 37 | /** 38 | * Log to the gripes file 39 | * 40 | * The gripes file is configured with tp_file_log_gripes. 41 | * 42 | * This attaches a timestamp to 'format' and does sprintf-style replacements 43 | * with a variable argument list. 44 | * 45 | * @param format the log line to submit 46 | * @param ... the arguments 47 | */ 48 | void log_gripe(const char *format, ...); 49 | 50 | /** 51 | * Log to the muf errors file 52 | * 53 | * The muf errors file is configured with tp_file_log_muf_errors. 54 | * 55 | * This attaches a timestamp to 'format' and does sprintf-style replacements 56 | * with a variable argument list. 57 | * 58 | * @param format the log line to submit 59 | * @param ... the arguments 60 | */ 61 | void log_muf(const char *format, ...); 62 | 63 | /** 64 | * Log a program's text to the program log file 65 | * 66 | * The program log file is controlled by the tp_file_log_programs variable. 67 | * All the text is dumped with a header that notes who saved the program 68 | * file. This way, naughty programmers can't write naughty programs then 69 | * delete them to hide from the admins. 70 | * 71 | * @param first the first 'struct line' of a program's text 72 | * @param player the player who saved the MUF program text 73 | * @param i the program dbref 74 | */ 75 | void log_program_text(struct line *first, dbref player, dbref i); 76 | 77 | /** 78 | * Log to the sanity fix file 79 | * 80 | * The sanity file is configured with tp_file_log_sanfix. 81 | * 82 | * This attaches a timestamp to 'format' and does sprintf-style replacements 83 | * with a variable argument list. 84 | * 85 | * @param format the log line to submit 86 | * @param ... the arguments 87 | */ 88 | void log_sanfix(const char *format, ...); 89 | 90 | /** 91 | * Log to the sanity file 92 | * 93 | * The sanity file is configured with tp_file_log_sanity. 94 | * 95 | * This attaches a timestamp to 'format' and does sprintf-style replacements 96 | * with a variable argument list. 97 | * 98 | * @param format the log line to submit 99 | * @param ... the arguments 100 | */ 101 | void log_sanity(const char *format, ...); 102 | 103 | /** 104 | * Log to the status file 105 | * 106 | * The status file is configured with tp_file_log_status. 107 | * 108 | * This attaches a timestamp to 'format' and does sprintf-style replacements 109 | * with a variable argument list. 110 | * 111 | * @param format the log line to submit 112 | * @param ... the arguments 113 | */ 114 | void log_status(const char *format, ...); 115 | 116 | /** 117 | * Log something to the user log file used by USERLOG primitive 118 | * 119 | * The message is formatted thusly: 120 | * 121 | * @verbatim 122 | * Winged(#4023) [newaction.muf(#666)] 2000-01-01T03:09:31: 123 | * @endverbatim 124 | * 125 | * Messages are stripped of all non-printable characters. 126 | * 127 | * @param player the player triggering the log message 128 | * @param program the program triggering the log message 129 | * @param logmessage the message to log 130 | */ 131 | void log_user(dbref player, dbref program, char *logmessage); 132 | 133 | /** 134 | * From a given 'who', generate a standard log 'name' entry. 135 | * 136 | * This is used in a number of places, such as command logging, where 137 | * we want a user's name, location, and if they are a wizard. 138 | * 139 | * The string produced will look something like this. Items in {curly} 140 | * braces would be empty if they don't apply: 141 | * 142 | * @verbatim 143 | * {WIZ}{Name owned by <-- if not player}Name of who's owner(#who) in 144 | * location name(#location ref) 145 | * @endverbatim 146 | * 147 | * For instance: 148 | * 149 | * @verbatim 150 | * WIZ Tanabi(#1234) in Some Place(#4321) 151 | * @endverbatim 152 | * 153 | * or 154 | * 155 | * @verbatim 156 | * Bleh owned by Tanabi (#1234) in Some Place(#4321) 157 | * @endverbatim 158 | * 159 | * You should free the memory returned by this call as you 'own' it. 160 | * 161 | * @param player the person to generate a log entry string for. 162 | * @return a newly allocated string as described above 163 | */ 164 | char *whowhere(dbref player); 165 | 166 | #endif /* !LOG_H */ 167 | -------------------------------------------------------------------------------- /scripts/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Restart script for Docker 3 | # 4 | # Optional arguments are port numbers. 5 | # If none are given, defaults to 4201. 6 | # 7 | 8 | prefix=/opt 9 | exec_prefix=/usr 10 | 11 | # 12 | # In a Docker environment, the GAMEDIR should always be the value below. 13 | # This assures that directory mapping will always point to the correct place. 14 | # 15 | GAMEDIR="$prefix/fbmuck" 16 | 17 | # If you want your database to be accessible by someone other than the 18 | # user the MUCK is running under, you should change this to the appropriate 19 | # umask value. 077 is owner-only. 20 | UMASK=077 21 | 22 | # 23 | # The following are the paths to the db files to load, save to, and archive to. 24 | # DBOLD is the path and filename of the the previous database archive. 25 | # DBIN is the path and filename of the database to read in. 26 | # DBOUT is the path and filename of the database that the muck should save to. 27 | # 28 | # On a successful restart, DBIN is moved to DBOLD, and DBOUT is moved to DBIN, 29 | # then the server is started. The server will save it's db to DBOUT. 30 | # 31 | DBOLD="$GAMEDIR/data/std-db.old" 32 | DBIN="$GAMEDIR/data/std-db.db" 33 | DBOUT="$GAMEDIR/data/std-db.new" 34 | 35 | 36 | # 37 | # The ports that the MUCK server should listen to. This will be overridden if 38 | # this script is called with port number arguments. If you want an SSL port, 39 | # the MUCK must be configured with --with-ssl, make cert must have been run, 40 | # and you must include "-sport PORTNUM" for each SSL port. 41 | # 42 | PORTS="-port 4201" 43 | 44 | # 45 | # This is the name of the fbmuck program to run. You probably don't want to 46 | # change this unless you renamed the server program to something other than 47 | # fbmuck. 48 | # 49 | SERVER="${exec_prefix}/bin/fbmuck" 50 | 51 | 52 | # 53 | # This is the name of the file to log server restarts to. 54 | # 55 | RESTARTS_LOGFILE="$GAMEDIR/logs/restarts" 56 | 57 | 58 | # 59 | # This is the name of the file that the fbmuck program creates that contains 60 | # the process ID of the server currently running in this game directory. 61 | # You probably don't want to change this unless you change the PID_FILE 62 | # #define in include/config.h 63 | # 64 | PIDFILE="$GAMEDIR/fbmuck.pid" 65 | 66 | 67 | # 68 | # You probably won't need to edit anything after this line. 69 | # 70 | ############################################################################# 71 | ############################################################################# 72 | 73 | 74 | cd $GAMEDIR 75 | # echo "Restarting at: $(date)" 76 | 77 | umask $UMASK 78 | 79 | 80 | PANICDB="${DBOUT}.PANIC" 81 | if [ -r $PANICDB ]; then 82 | end=$(tail -1 $PANICDB) 83 | if [ "x$end" = "x***END OF DUMP***" ]; then 84 | mv $PANICDB $DBOUT 85 | else 86 | echo "Warning: PANIC dump failed on "$(date) | mail $(whoami) 87 | fi 88 | fi 89 | 90 | # We may need to do an initial setup 91 | if [ ! -r "$GAMEDIR/data" ]; then 92 | echo "Initializing your Fuzzball MUCK Base Directory" 93 | cp -a /opt/fbmuck-base/* "$GAMEDIR/" 94 | 95 | # Remove documentation so we get it off share. This makes things more 96 | # ugpradable. 97 | rm -f "$GAMEDIR/data/help.txt" "$GAMEDIR/data/man.txt" \ 98 | "$GAMEDIR/data/mpihelp.txt" 99 | fi 100 | 101 | if [ -r $DBOUT ]; then 102 | mv -f $DBIN $DBOLD 103 | mv $DBOUT $DBIN 104 | fi 105 | 106 | if [ ! -r $DBIN ]; then 107 | echo "Hey! The $DBIN file has to exist and be readable to restart the server!" 108 | echo "Restart attempt aborted." 109 | exit 110 | fi 111 | 112 | end=$(tail -1 $DBIN) 113 | if [ "x$end" != 'x***END OF DUMP***' ]; then 114 | echo "WARNING! The $DBIN file is incomplete and therefore corrupt!" 115 | echo "Restart attempt aborted." 116 | exit 117 | fi 118 | 119 | # We may need to set up SSL. 120 | if [ "$USE_SSL" == "1" ]; then 121 | # If we're using Let's Encrypt, let's make a server PEM file. 122 | if [[ -f "/opt/fbmuck-ssl/privkey.pem" && -f "/opt/fbmuck-ssl/fullchain.pem" ]] ; then 123 | cat "/opt/fbmuck-ssl/privkey.pem" "/opt/fbmuck-ssl/fullchain.pem" > \ 124 | "$GAMEDIR/data/server.pem" 125 | fi 126 | 127 | # Is SSL already set up? 128 | if [ ! -f "$GAMEDIR/data/server.pem" ]; then 129 | if [ -f "/opt/fbmuck-ssl/server.pem" ]; then 130 | cp "/opt/fbmuck-ssl/server.pem" "$GAMEDIR/data/server.pem" 131 | elif [ "$SELF_SIGN" == "1" ]; then 132 | # Generate certs 133 | openssl req -x509 -nodes -newkey rsa:4096 \ 134 | -keyout "/opt/fbmuck-ssl/privkey.pem" \ 135 | -out "/opt/fbmuck-ssl/fullchain.pem" \ 136 | -days 3650 \ 137 | -subj "/C=US/ST=NA/L=Fuzzball/O=Fuzzball/OU=Org/CN=muck" 138 | cat "/opt/fbmuck-ssl/privkey.pem" "/opt/fbmuck-ssl/fullchain.pem" > \ 139 | "$GAMEDIR/data/server.pem" 140 | fi 141 | fi 142 | 143 | PORTS="$PORTS -sport 4202" 144 | fi 145 | 146 | mkdir -p logs 147 | 148 | touch $RESTARTS_LOGFILE 149 | echo "$(date +%Y-%m-%dT%H:%M:%S): $(who am i)" >> $RESTARTS_LOGFILE 150 | 151 | # echo "Server started at: $(date)" 152 | exec $SERVER -nodetach -gamedir $GAMEDIR -dbin $DBIN -dbout $DBOUT $PORTS 153 | -------------------------------------------------------------------------------- /include/compile.h: -------------------------------------------------------------------------------- 1 | /** @file compile.h 2 | * 3 | * Header for the various functions that handles the MUF compiler. 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #ifndef COMPILE_H 9 | #define COMPILE_H 10 | 11 | #include 12 | 13 | #include "config.h" 14 | 15 | #define MUF_AUTHOR_PROP "_author" /**< Author name string location */ 16 | #define MUF_DOCCMD_PROP "_docs" /**< Command to list docs */ 17 | #define MUF_ERRCOUNT_PROP ".debug/errcount" /**< error count */ 18 | #define MUF_LASTCRASH_PROP ".debug/lastcrash" /**< last crash timestamp */ 19 | #define MUF_LASTCRASHTIME_PROP ".debug/lastcrashtime" /**< last crash time str */ 20 | #define MUF_LASTERR_PROP ".debug/lasterr" /**< last error */ 21 | #define MUF_LIB_VERSION_PROP "_lib-version" /**< Library version */ 22 | #define MUF_NOTE_PROP "_note" /**< Notes */ 23 | #define MUF_VERSION_PROP "_version" /**< Version */ 24 | 25 | /** 26 | * @var IN_FOR 27 | * integer primitive ID for FOR primitive 28 | */ 29 | extern int IN_FOR; 30 | 31 | /** 32 | * @var IN_FOREACH 33 | * integer primitive ID for FOREACH primitive 34 | */ 35 | extern int IN_FOREACH; 36 | 37 | /** 38 | * @var IN_FORITER 39 | * integer primitive ID for FORITER primitive 40 | */ 41 | extern int IN_FORITER; 42 | 43 | /** 44 | * @var IN_FORPOP 45 | * integer primitive ID for FORPOP primitive 46 | */ 47 | extern int IN_FORPOP; 48 | 49 | /** 50 | * @var IN_TRYPOP 51 | * integer primitive ID for TRYPROP primitive 52 | */ 53 | extern int IN_TRYPOP; 54 | 55 | /** 56 | * Free the memory used by the primitive hash 57 | */ 58 | void clear_primitives(void); 59 | 60 | /** 61 | * Compile MUF code associated with a given dbref 62 | * 63 | * Live the dream, compile some MUF. According to the original docs, this 64 | * does piece-meal tokenization parsing and backward checking. 65 | * 66 | * This takes some program text associated with 'program_in', converts it 67 | * to INTERMEDIATE's, and then does some optimizations before turning it 68 | * into an array of struct inst's. 69 | * 70 | * Once compiled, the program is ready to run. 71 | * 72 | * A few notes: 73 | * 74 | * - When compile starts, it kills any running copies of the program. 75 | * - If the program is both set A (ABODE/AUTOSTART) and owned by a wizard, 76 | * it will be run automatically if successfully compiled. 77 | * - force_err_display when true will display all compile errors to the 78 | * player. Error messages are still displayed anyway if the player 79 | * is INTERACTIVE but not READMODE (which I believe means they are in the 80 | * \@program/\@edit editor). 81 | * 82 | * @param descr the descriptor of the person compiling 83 | * @param in_player the player compiling 84 | * @param in_program the program to compile 85 | * @param force_err_disp boolean - true to always show compile errors 86 | */ 87 | void do_compile(int descr, dbref in_player, dbref in_program, 88 | int force_err_disp); 89 | 90 | /** 91 | * Free ("uncompile") unused programs 92 | * 93 | * An unused program is one who's program object has a ts_lastused time 94 | * that is older than tp_clean_interval seconds and also is not set 95 | * ABODE (Autostart) or INTERNAL. 96 | * 97 | * This scans over the entire database and is thus kind of expensive 98 | */ 99 | void free_unused_programs(void); 100 | 101 | /** 102 | * Return primitive instruction number 103 | * 104 | * @param token the primitive token name such as "GETPROPSTR", etc. 105 | * @return integer token instruction number 106 | */ 107 | int get_primitive(const char * token); 108 | 109 | /** 110 | * Initialize the hash of primitives 111 | * 112 | * This must run before the compile will work. It first clears anything 113 | * currently in the primitive hash, then loads all the primitives from 114 | * base_inst into the hash. 115 | * 116 | * This also loads the value of variables IN_FORPOP, IN_FORITER, IN_FOR, 117 | * IN_FOREACH, and IN_TRYPOP. The number of primitives is logged via 118 | * log_status 119 | * 120 | * @see log_status 121 | */ 122 | void init_primitives(void); 123 | 124 | /** 125 | * See if 'token' is a primitive 126 | * 127 | * @param token the token to check 128 | * @return boolean true if 'token' is a primitive, false otherwise 129 | */ 130 | int primitive(const char *token); 131 | 132 | /** 133 | * Calculate the in-memory size of a program 134 | * 135 | * This may be 0 if the program is not loaded (PROGRAM_CODE(prog) is NULL) 136 | * Otherwise it is a (hopefully) accurate representation of a program's 137 | * memory usage. 138 | * 139 | * @param prog the dbref of the program we are size checking 140 | * @return the size in bytes of consumed memory 141 | */ 142 | size_t size_prog(dbref prog); 143 | 144 | /** 145 | * Delete a program from memory 146 | * 147 | * "Uncompile" is a really awkward way to put this, because (to me) it 148 | * sounds a lot like "decompile". It has absolutely nothing to do with 149 | * decompiling. "free_program" is probably more accurate. 150 | * 151 | * @param i the program ref to decompile 152 | */ 153 | void uncompile_program(dbref i); 154 | 155 | #endif /* !COMPILE_H */ 156 | -------------------------------------------------------------------------------- /dbs/starterdb/muf/52.m: -------------------------------------------------------------------------------- 1 | $include $lib/match 2 | 3 | $def IMAGE_PACKAGE "dns-org-fuzzball-image" 4 | 5 | : list-imagers[ -- ] 6 | 0 var! count 7 | preempt 8 | descr IMAGE_PACKAGE mcp_supports 9 | 0.0 > if 10 | { }list var! names 11 | { }list var! targrefs 12 | { }list var! urls 13 | me @ location contents 14 | begin 15 | dup while 16 | dup room? if next continue then 17 | count @ 1 + dup count ! 150 <= while 18 | dup "_/image" getpropstr dup if 19 | urls @ array_appenditem urls ! 20 | dup targrefs @ array_appenditem targrefs ! 21 | dup name names @ array_appenditem names ! 22 | else 23 | pop 24 | then 25 | next 26 | repeat pop 27 | descr IMAGE_PACKAGE "viewable" 28 | { 29 | "names" names @ 30 | "refs" targrefs @ 31 | "urls" urls @ 32 | }dict 33 | mcp_send 34 | else 35 | "(@imaged objects)" tell 36 | me @ location contents 37 | begin 38 | dup while 39 | dup room? if next continue then 40 | count @ 1 + dup count ! 50 > if 41 | "(Too many objects in this room. Skipping the remainder.)" 42 | tell break 43 | then 44 | dup "_/image" getpropstr if 45 | dup name tell 46 | then 47 | next 48 | repeat pop 49 | "(Done.)" tell 50 | then 51 | ; 52 | 53 | 54 | : cmd-@image[ str:cmdline -- ] 55 | cmdline @ tolower "#help" stringcmp not if 56 | { 57 | "@Image ver. 2.0 Copyright 7/10/1994 by Revar" 58 | "-------------------------------------------------------------------" 59 | "@image To see where to find a gif of the object" 60 | "@image = To specify where one can find a gif of " 61 | " that object. The URL is the WWW URL " 62 | " format for specifying where on the net" 63 | " a file is. " 64 | "@image =clear To clear the image reference. " 65 | "-------------------------------------------------------------------" 66 | "URLs have the following format: type://machine.name/path/file" 67 | "If I wanted to show that people can find an image of Revar on" 68 | "www.belfry.com, via the web, I'd just do:" 69 | " @image Revar=https://www.belfry.com/pics/revar-cw3.jpg" 70 | " " 71 | "Those of you who have used the web should find URLs familiar." 72 | }tell 73 | exit 74 | then 75 | 76 | cmdline @ not if 77 | list-imagers 78 | exit 79 | then 80 | 81 | cmdline @ "=" split strip 82 | var! newurl 83 | 84 | strip 85 | dup not if 86 | "Usage: @image or @image =" tell 87 | pop exit 88 | then 89 | noisy_match 90 | var! targref 91 | 92 | targref @ not if 93 | exit 94 | then 95 | 96 | newurl @ not if 97 | cmdline @ "=" instr if 98 | ( @image = ) 99 | "me" match targref @ controls not if 100 | "Permission denied." tell 101 | exit 102 | then 103 | 104 | targref @ "_/image" "" 0 addprop 105 | "Image unset." tell 106 | exit 107 | then 108 | 109 | ( @image ) 110 | targref @ "_/image" getpropstr 111 | " " "\r" subst 112 | var! currurl 113 | 114 | currurl @ not if 115 | "No image available." tell 116 | exit 117 | then 118 | 119 | descr IMAGE_PACKAGE mcp_supports 120 | 0.0 > if 121 | descr IMAGE_PACKAGE "view" 122 | { 123 | "name" targref @ name 124 | "ref" targref @ 125 | "url" currurl @ 126 | }dict 127 | mcp_send 128 | else 129 | "(@image) " currurl @ strcat tell 130 | then 131 | else 132 | ( @image = ) 133 | "me" match targref @ controls not if 134 | "Permission denied." tell 135 | exit 136 | then 137 | 138 | newurl @ "://" split strip swap strip 139 | dup "file" stringcmp 140 | over "http" stringcmp and 141 | over "ftp" stringcmp and 142 | over "https" stringcmp and if 143 | pop pop 144 | "Unknown URL service type. The acceptable types are ftp, http, https, and file." tell 145 | "Example: https://www.belfry.com/pics/revar-cw3.jpg" tell 146 | exit 147 | then 148 | "://" strcat swap 149 | "/" split swap 150 | dup "*[^-:%.a-z0-9_]*" smatch if 151 | "Invalid character in machine name. Valid chars are a-z, 0-9, _, period, colon, and -." tell 152 | pop pop pop exit 153 | then 154 | "/" strcat swap 155 | strcat strcat 156 | targref @ "_/image" rot 0 addprop 157 | "Image set." tell 158 | then 159 | ; 160 | -------------------------------------------------------------------------------- /include/move.h: -------------------------------------------------------------------------------- 1 | /** @file move.h 2 | * 3 | * Header for handling movement on the MUCK, such as moving a player from 4 | * room to room. 5 | * 6 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 7 | */ 8 | 9 | #ifndef MOVE_H 10 | #define MOVE_H 11 | 12 | #include "config.h" 13 | 14 | /** 15 | * Have a given player (or player-like thing) enter a room and do all processing 16 | * 17 | * Note: This call has some partial support for rooms and programs 18 | * to be moved with it, however that does not appear to be the 19 | * primary purpose and using this call with rooms, players, or 20 | * non-zombie THINGS may have odd results and is not recommended. 21 | * 22 | * This does the following things: 23 | * 24 | * - Checks for parent loops of 'player' and 'loc'; the logic of what happens 25 | * when a parent loop is detected is somewhat complicated but in most 26 | * cases the player or thing is sent home with a few edge cases that 27 | * probably don't happen much. 28 | * 29 | * - If the starting location of 'player' is not the same as 'loc', then 30 | * 'player' is moved to 'loc' ( @see moveto ) 31 | * 32 | * Then, if 'player' didn't come from NOTHING, depart propqueues are run. 33 | * A "X has left." message is sent from the source room based on 34 | * player flags, room flags, exit flags, and tp_quiet_moves (basically 35 | * this is where the DARK flag checking is done) 36 | * 37 | * Then, If the previous location of 'player' wasn't NOTHING, and was set 38 | * STICKY and has a dropto, dropto processing is done (objects sent to 39 | * DROPTO only if there are no players or zombies left in the room). 40 | * 41 | * Finally, the "X has arrived" notification is sent to the target room. 42 | * To make propqueues run after autolook, this message is disconnected from 43 | * the arrive propqueue processing which is done further down. 44 | * This notification follows the same rules as the "has left" message 45 | * 46 | * - If 'player' is not a thing, or if 'player' is a ZOMBIE or VEHICLE, then 47 | * look is triggered. Note that this is where this function falls down for 48 | * rooms and programs. Look action loops are detected and if they are found 49 | * to go 8 deep an error is displayed. This is NOT threadsafe because it 50 | * uses a global static 'donelook'. This supports tp_autolook_cmd if 51 | * set, otherwise @see look_room 52 | * 53 | * - If tp_penny_rate != 0, player doesn't control loc, player has less 54 | * than tp_max_pennies, and a random number % tp_penny_rate == 0, then 55 | * the owner of the player gets a penny. 56 | * 57 | * - Finally, arrive propqueue is processed if loc != old 58 | * 59 | * There's a lot going on here :) 60 | * 61 | * @param descr the descriptor of the person doing the action 62 | * @param player the object moving 63 | * @param loc the place the object is moving to 64 | * @param exit the exit that triggered the move 65 | */ 66 | void enter_room(int descr, dbref player, dbref loc, dbref exit); 67 | 68 | /** 69 | * Do a move of 'what' to 'where', handling special cases of 'where' 70 | * 71 | * This is used to move rooms and non-zombie things; exits are moved 72 | * in a different fashion, and players/zombies should be moved using 73 | * enter_room instead. 74 | * 75 | * @see enter_room 76 | * 77 | * Technically it wouldn't be the end of the world if a player or zombie 78 | * were moved with this call, but, it wouldn't handle the special processing, 79 | * messaging, and whatnot so it would move them in a weird fashion. 80 | * 81 | * @param what the thing to move 82 | * @param where the destination to move it to 83 | */ 84 | void moveto(dbref what, dbref where); 85 | 86 | /** 87 | * Send all the contents of 'loc' to 'dest' 88 | * 89 | * Loops through all the contents of 'loc' and send it over to 'dest'. 90 | * 91 | * @param descr the descriptor of the person who triggered the move 92 | * @param loc the location to to move contents from 93 | * @param dest the location to send contents to 94 | */ 95 | void send_contents(int descr, dbref loc, dbref dest); 96 | 97 | /** 98 | * Sweep 'thing' home 99 | * 100 | * For players or things where puppethome is true, their contents are 101 | * swept home as well. Programs are swept to their owner. Rooms and 102 | * exits cannot be swept. 103 | * 104 | * @param descr the descriptor associated with the person doing the action 105 | * @param thing the thing to return home 106 | * @param homepuppet if true, and thing is a THING, sweep its contents 107 | */ 108 | void send_home(int descr, dbref thing, int homepuppet); 109 | 110 | /** 111 | * Implementation of recycling an object 112 | * 113 | * Does all the sanity checking necessary. For instance, if something is 114 | * being forced to recycle, we make sure that it won't create an unstable 115 | * situation. 116 | * 117 | * Rooms and things have all their exits deleted. Programs have their 118 | * filesystem file deleted. 119 | * 120 | * Then the fields are all nulled out as necessary and the object converted 121 | * to garbage. 122 | * 123 | * @param descr the descriptor of the player trigging the recycle 124 | * @param player the player doing recycling 125 | * @param thing the thing to recycle 126 | */ 127 | void recycle(int descr, dbref player, dbref thing); 128 | 129 | #endif /* !MOVE_H */ 130 | -------------------------------------------------------------------------------- /include/inst.h: -------------------------------------------------------------------------------- 1 | /** @file inst.h 2 | * 3 | * Header for various defines and data structures used by MUF programs. 4 | * 5 | * This file is part of Fuzzball MUCK. Please see LICENSE.md for details. 6 | */ 7 | 8 | #ifndef INST_H 9 | #define INST_H 10 | 11 | #include 12 | 13 | #include "boolexp.h" 14 | #include "config.h" 15 | 16 | #define IN_JMP 1 /**< Jump the program counter */ 17 | #define IN_READ 2 /**< Do a READ */ 18 | #define IN_SLEEP 3 /**< Do a SLEEP */ 19 | #define IN_CALL 4 /**< Call a public function */ 20 | #define IN_EXECUTE 5 /**< EXECUTE a program */ 21 | #define IN_RET 6 /**< Internal return instruction */ 22 | #define IN_EVENT_WAITFOR 7 /**< Wait for an event */ 23 | #define IN_CATCH 8 /**< Catch block */ 24 | #define IN_CATCH_DETAILED 9 /**< More detailed catch */ 25 | 26 | /** 27 | * A line of code 28 | */ 29 | struct line { 30 | const char *this_line; /**< the line itself */ 31 | struct line *next; /**< the next line */ 32 | struct line *prev; /**< the previous line */ 33 | }; 34 | 35 | /** 36 | * For sharing strings in programs 37 | */ 38 | struct shared_string { 39 | int links; /**< number of pointers to this struct */ 40 | size_t length; /**< length of string data */ 41 | char data[1]; /**< shared string data */ 42 | }; 43 | 44 | /** 45 | * For address references 46 | */ 47 | struct prog_addr { 48 | int links; /**< number of pointers */ 49 | dbref progref; /**< program dbref */ 50 | struct inst *data; /**< pointer to the code */ 51 | }; 52 | 53 | /** 54 | * For system callstack 55 | */ 56 | struct stack_addr { 57 | dbref progref; /**< program call was made from */ 58 | struct inst *offset; /**< the address of the call */ 59 | }; 60 | 61 | struct stk_array_t; /**< The MUF array stack type */ 62 | 63 | /** 64 | * MUF Process information 65 | */ 66 | struct muf_proc_data { 67 | char *procname; /**< Process name */ 68 | int vars; /**< Number of variables */ 69 | int args; /**< Number of arguments */ 70 | const char **varnames; /**< table of variable names */ 71 | }; 72 | 73 | /* stack and object declarations */ 74 | /* Integer types go here */ 75 | #define PROG_CLEARED 0 /**< Null */ 76 | #define PROG_PRIMITIVE 1 /**< forth prims and hard-coded C routines */ 77 | #define PROG_INTEGER 2 /**< integer types */ 78 | #define PROG_FLOAT 3 /**< float types */ 79 | #define PROG_OBJECT 4 /**< database objects */ 80 | #define PROG_VAR 5 /**< variables */ 81 | #define PROG_LVAR 6 /**< local variables, unique per program */ 82 | #define PROG_SVAR 7 /**< scoped variables, unique per procedure */ 83 | 84 | /* Pointer types go here, numbered *AFTER* PROG_STRING */ 85 | #define PROG_STRING 9 /**< string types */ 86 | #define PROG_FUNCTION 10 /**< function names for debugging. */ 87 | #define PROG_LOCK 11 /**< boolean expression */ 88 | #define PROG_ADD 12 /**< program address - used in calls&jmps */ 89 | #define PROG_IF 13 /**< A low level IF statement */ 90 | #define PROG_EXEC 14 /**< EXECUTE shortcut */ 91 | #define PROG_JMP 15 /**< JMP shortcut */ 92 | #define PROG_ARRAY 16 /**< Array of other stack items. */ 93 | #define PROG_MARK 17 /**< Stack marker for [ and ] */ 94 | #define PROG_SVAR_AT 18 /**< \@ shortcut for scoped vars */ 95 | #define PROG_SVAR_AT_CLEAR 19 /**< \@ for scoped vars, with var clear optim */ 96 | #define PROG_SVAR_BANG 20 /**< ! shortcut for scoped vars */ 97 | #define PROG_TRY 21 /**< TRY shortcut */ 98 | #define PROG_LVAR_AT 22 /**< \@ shortcut for local vars */ 99 | #define PROG_LVAR_AT_CLEAR 23 /**< \@ for local vars, with var clear optim */ 100 | #define PROG_LVAR_BANG 24 /**< ! shortcut for local vars */ 101 | 102 | #define MAX_VAR 54 /**< maximum number of variables including the 103 | * basic ME, LOC, TRIGGER, and COMMAND vars 104 | */ 105 | #define RES_VAR 4 /**< no of reserved variables */ 106 | 107 | #define STACK_SIZE 1024 /**< maximum size of stack */ 108 | 109 | /** 110 | * If 'x' is NULL, return an empty string, otherwise return ->data 111 | * 112 | * @param x the variable to fetch data for 113 | * @return either x->data or "" if x is NULL 114 | */ 115 | #define DoNullInd(x) ((x) ? (x) -> data : "") 116 | 117 | /** 118 | * An instruction in a MUF program 119 | */ 120 | struct inst { 121 | short type; /**< Instruction type */ 122 | int line; /**< Line number */ 123 | union { 124 | struct shared_string *string; /**< strings */ 125 | struct boolexp *lock; /**< boolean lock expression */ 126 | int number; /**< used for both primitives and integers */ 127 | double fnumber; /**< used for float storage */ 128 | dbref objref; /**< object reference */ 129 | struct stk_array_t *array; /**< pointer to muf array */ 130 | struct inst *call; /**< use in IF and JMPs */ 131 | struct prog_addr *addr; /**< the result of 'funcname */ 132 | struct muf_proc_data *mufproc; /**< Data specific to each procedure */ 133 | } data; /**< Different kinds of instructions */ 134 | }; 135 | 136 | #endif /* !INST_H */ 137 | --------------------------------------------------------------------------------