##Introduction This manual is not to be perfect, nor is it to contain all of the newest built-ins or extension verbs for the newest versions of the server. It is there merely for your convenience, whether you are an experienced programmer or not. Use it as you wish. Good luck in MOOing! Note: This manual describes the usage of built-in verbs, properties and objects of the LambdaCore database and its heritages, such as V-Core. Built-in functions are verbs which are not on any object, instead they are loaded when the server is compiled. Server compiling information, as well as good MOO servers, are found on-line. On 7 August, 2014 at 05:44AM. ##Types This section is meant to describe various value types in MOO code. NUM: number, for instance 34 STR String, for instance "\"Hi\," said John." OBJ object, for instance #23 LIST list, for instance {34, "a string", {"a", "sublist", 3}, {}} ERR error, for instance E_TYPE ##Errors This section explains what the different error types in MOO code mean. Below each error type, there is a short description of that type, as wel as an example of a few broken codelines which would return that error if executed.. E_TYPE type mismatch tostr(2)/4; E_DIV divide by zero 4/0; E_RANGE invalid subscript (range error in newer servers, at least after 1.8.1) if (this.weapons[4] == A) would return E_RANGE if said property, .weapons, would only have 3 or less list values, or would not be a list at all. E_INVARG invalid argument if (args[1] in $player.clothes) would return E_INVARG if arguments were not specified, therefore the first argument, args[1], would not be there E_VARNF variable not found if (ball ==0) would return E_VARNF if the variable 'ball' was not specified earlier in the MOO code. E_PROPNF property not found this.tack = 0; would return E_PROPNF if the propery .tack would not exist on the object. E_VERBNF verb not found this:attack(); would return E_VERBNF if the verb :attack would not be found on the object as callable. Being callable means that it must have the arguments 'this, none, this' (about these later on). E_PERM permission denied It's hard to give an example, but basically this happens when a task tries to execute a function which is not permitted for the user calling it. E_INVIND invalid object number (or malformed object number) return 34.base; Because object numbers must always have # (hash) before them, this would return E_INVIND. E_MAXREC exceeded maximum recursion depth Another one hard to give an example of. ##Subscripting Everything is 1-based. Subscript lists or strings: s[expr] is lvalue and rvalue s[expr..expr] does slices. Exprs must be in range. @expr does list splicing for lists or arguments. ##Special variables in functions this the object caller value of "this" in calling function, or player at top-level player player that invoked the task verb verb named used to invoke verb args list of arguments, use [], for instance: [For commands] argstr everything after first word of command dobjstr direct object string dobj direct object value prepstr preposition string iobjstr indirect object string iobj indirect object value ##Exprs Usual C stuff, except: cond ? expr1 | expr2 conditional expressions $foo #0.foo "str" + "str" concatenation expr in list list membership, returns index or 0 (false) Strings comparisons are case-insensitive. ##Statements if, elseif and else: if (expr); ... elseif (expr); ... else; ... endif for: for variable in (expression); ... endfor for variable in [expr1..expr2]; ... endfor while: while (expr); ... endwhile fork: fork (expr); ... endfork fork name (expr); ... endfork ##Mathematical expressions min(n1, n2, ...) minimum of n1,n2,... max(n1, n2, ...) maximum of n1,n2,... abs(n) absolute value of n sqrt(n) square root of n, rounded down random(n) random integer between 1 and n inclusive ##$math_utils This object has a lot of mathematical functions. Its verbs are explained below. Trigonometric/Exponential functions: :sin(a),cos(a),tan(a) returns 10000*(the value of the corresponding trigonometric function) angle a is in degrees. :arctan([x,]y) returns arctan(y/x) in degrees in the range -179..180. X defaults to 10000. Quadrant is that of (x,y). :exp(x[,n]) calculates e^x with an nth order taylor polynomial Statistical functions :combinations(n,r) returns the number of combinations given n objects taken r at a time. :permutations(n,r) returns the number of permutations possible given n objects taken r at a time. Number decomposition :div(n,d) correct version of / (handles negative numbers correctly) :mod(n,d) correct version of % (handles negative numbers correctly) :divmod(n,d) {div(n,d),mod(n,d)} :parts(n,q[,i]) returns a list of two elements {integer,decimal fraction} Other math functions :sqrt(x) returns the largest integer n <= the square root of x :pow(x,n) returns x to the power of n Series :fibonacci(n) returns the 1st n fibonacci numbers in a list :geometric(x,n) returns the value of the nth order geometric series at x Integer Properties :gcd(a,b) find the greatest common divisor of the two numbers :lcm(a,b) find the least common multiple of the two numbers :are_relatively_prime(a,b) return 1 if a and b are relatively prime :is_prime(n) returns 1 if the number is a prime and 0 otherwise Miscellaneous :random(n) returns a random number from 0..n if n > 0 or n..0 if n < 0 :random_range(n[,mean]) returns a random number from mean - n..mean + n with mean defaulting to 0 :simpson({a,b},{f(a),f((a+b)/2),f(b)}) returns the numerical approximation of an integral using simpson's rule Bitwise Arithmetic :AND(x,y) returns x AND y :OR(x,y) returns x OR y :XOR(x,y) returns x XOR y (XOR is the exclusive-or function) :NOT(x) returns the complement of x All bitwise manipulation is of 32-bit values. ##Time This section explains time-related built-in functions. time() current time in seconds since midnight GMT, 1 Jan 70 ctime([time]) time (or current time) converted to a human-readable string ##$time_utils This object has time-related verbs to help coders with their time needs. The verbs of this object are described below. Converting from seconds-since-1970 :dhms(time) => string ...DD:HH:MM:SS :english_time(time[, reference time) => string of y, m, d, m, s Converting to seconds :to_seconds("hh:mm:ss") => seconds since 00:00:00 :from_ctime(ctime) => corresponding time-since-1970 :from_day(day_of_week, which) => time-since-1970 for the given day* :from_month(month, which) => time-since-1970 for the given month* (* the first midnight of that day/month) :day([c]time) => what day it is :month([c]time) => what month it is :ampm([c]time[, precision]) => what time it is, with am or pm :time_sub(string, time) => substitute time information :sun([time]) => angle between sun and zenith :dst_midnight(time) No explanation available. ##Strings This section describes string-related built-in functions. index(str1, str2 [, case-matters]) index of first str2 in str1 rindex(str1, str2 [, case-matters]) index of last str2 in str1 strcmp(str1, str2) case-sensitive string comparison strsub(subject, what, with [, case-matters]) substitution in a string crypt(string [, salt]) one-way string encryption match(str1, str2 [, case-matters]) match first pattern str2 in str1 rmatch(str1, str2 [, case-matters]) match last pattern str2 in str1 substitute(template, subs) perform substitutions on template ##$string_utils This object has additional functions to ease the work of programmers with strings, and the functions are: Conversion routines :from_list (list [,sep]) => "foo1foo2foo3" :english_list (str-list[,none-str[,and-str[, sep]]]) => "foo1, foo2, and foo3" :title_list*c (obj-list[,none-str[,and-str[, sep]]]) => "foo1, foo2, and foo3" or => "Foo1, foo2, and foo3" :from_value (value [,quoteflag [,maxlistdepth]]) => "{foo1, foo2, foo3}" :english_number(42) => "forty-two" :english_ordinal(42) => "forty-second" :ordinal(42) => "42nd" :group_number(42135 [,sep]) => "42,135" Type checking :is_numeric(string) => return true if string is composed entirely of digits Parsing :explode (string,char) string => list of words delimited by char :words (string) string => list of words (like command line parser) :word_start (string) string => list of start-end pairs. Matching :match_string(string, pattern, options) => * wildcard matching :find_prefix(prefix, string-list) => list index of elt starting with prefix :index_delimited(string,target[,case]) => index of delimited string occur. :match(string, [obj-list, prop-name]+) => matching object :match_player(string-list[,me-object]) => list of matching players :match_object(string, location) => default object match... Pretty printing :space (n/string[,filler]) => n spaces :left (string,width[,filler]) => left justified string in field :right (string,width[,filler]) => right justified string in field :center/re (string,width[,filler]) => centered string in field :columnize/se(list,n[,width]) => list of strings in n columns Substitutions :substitute (string,subst_list [,case]) general substitutions. :pronoun_sub (string/list[,who[,thing[,location]]]) pronoun substitutions. :pronoun_sub_secure (string[,who[,thing[,location]]],default) substitute and check for names. :pronoun_quote (string/list/subst_list) quoting for pronoun substitutions. Miscellaneous string munging: :trim (string) => string with outside whitespace removed. :triml (string) => string with leading whitespace removed. :trimr (string) => string with trailing whitespace removed. :strip_chars (string,chars) => string with all chars in `chars' removed. :strip_all_but(string,chars) => string with all chars not in `chars' removed. :capitalize/se(string) => string with first letter capitalized. :uppercase/lowercase(string) => string with all letters upper or lowercase. :names_of (list of OBJ) => string with names and object numbers of items. .alphabet => "abcdefghijklmnopqrstuvwxyz" ##Lists This section tells about list-related built-in functions. listappend(list, value [, index]) adding an element at the end of a list listinsert(list, value [, index]) adding an element at the head of a list listset(list, value, index) updating a list at some index listdelete(list, index) removing an element from a list setadd(list, element) adding an element to a set represented as a list setremove(list, element) removing an element from such a set ##$list_utils This object is meant to add more functions to work with lists. The functions are below. :append (list,list,..) => result of concatenating the given lists :reverse (list) => reversed list :remove_duplicates (list) => list with all duplicates removed :compress (list) => list with consecutive duplicates removed :setremove_all (list,elt) => list with all occurrences of elt removed :find_insert (sortedlist,e) => index of first element > e in sortedlist :sort (list[,keys]) => sorted list :make (n[,e]) => list of n copies of e :range (m,n) => {m,m+1,...,n} :arrayset (list,val,i[,j,k...]) => array modified so that list[i][j][k]==val -- Mapping functions (take a list and do something to each element) :map_prop ({o...},prop) => list of o.(prop) for all o :map_verb ({o...},verb[,args) => list of o:(verb)(@args) for all o :map_arg ([n,]obj,verb,{a...},args) => list of obj:(verb)(a,@args) for all a Association list functions An association list (alist) is a list of pairs (2-element lists), though the following functions have been generalized for lists of n-tuples (n-element lists). In each case i defaults to 1. :assoc (targ,alist[,i]) => 1st tuple in alist whose i-th element is targ :iassoc (targ,alist[,i]) => index of same. :assoc_prefix (targ,alist[,i]) => ... whose i-th element has targ as a prefix :iassoc_prefix(targ,alist[,i]) => index of same. :slice (alist[,i]) => list of i-th elements :sort_alist (alist[,i]) => alist sorted on i-th elements. ##$seq_utils A sequence is a set of integers. This object supplies the following verbs: :add(seq,f,t) => seq with [f..t] interval added :remove(seq,f,t) => seq with [f..t] interval removed :range(f,t) => sequence corresponding to [f..t] {} => empty sequence :contains(seq,n) => n in seq :size(seq) => number of elements in seq :first(seq) => first integer in seq or E_NONE :firstn(seq,n) => first n integers in seq (as a sequence) :last(seq) => last integer in seq or E_NONE :lastn(seq,n) => last n integers in seq (as a sequence) :complement(seq) => [-2147483648..2147483647] - seq :union(seq,seq,...) :intersect(seq,seq,...) :extract(seq,array) => array[@seq] :for([n,]seq,obj,verb,@args) => for s in (seq) obj:verb(s,@args); endfor :tolist(seq) => list corresponding to seq :tostr(seq) => contents of seq as a string :from_list(list) => sequence corresponding to list :from_sorted_list(list) => sequence corresponding to list (assumed sorted) :from_string(string) => sequence corresponding to string For boolean expressions, note that the representation of the empty sequence is {} (boolean FALSE) and all non-empty sequences are represented as nonempty lists (boolean TRUE). The representation used works better than the usual list implementation for sets consisting of long uninterrupted ranges of integers. For sparse sets of integers the representation is decidedly non-optimal (though it never takes more than double the space of the usual list representation). Actually what this package implements is sets of integers-mod-2^32, but this assumes the underlying machine on which the server runs has 32-bit integers. If not, you need to change this.maxneg to be the largest negative ("smallest"?) integer available. ##$set_utils This object is useful for operations that treat lists as sets (i.e., without concern about order and assuming no duplication). :union(set, set, ...) => union :intersection(set, set, ...) => intersection :diff*erence(set 1, set 2, ..., set n) => result of removing all elements of sets 2..n from set 1. :exclusive_or(set, set, set, ...) => all elements that are contained in exactly one of the sets :contains(set 1, set 2, ..., set n) => true if and only if all of sets 2..n are subsets of set 1 ##Objects The following is a list of object-related built-in functions. valid(object) testing whether an object exists create(parent [, owner(*)]) creating a new MOO object recycle(object) destroying a MOO object Note: you can also use $recycler:_recycle(object) in which case the object is not literally destroyed, instead, it is changed to a parent of #1 with the name of Recyclable (object_id). move(object, where) altering the object-containment hierarchy chparent(object, new-parent) altering the object-inheritance hierarchy parent(object) object's parent in the inheritance hierarchy children(object) object's children in the inheritance hierarchy max_object() the highest-numbered object in the MOO renumber(object) changes an object's number to lowest available one* reset_max_object() resets max_object() to the largest valid object* properties(object) a list of the properties defined on an object add_property(object, prop-name, value, info) add a new property delete_property(object, prop-name) remove a property property_info(object, prop-name) {owner, perms} info on a prop set_property_info(object, prop-name, info) setting same is_clear_property(object, prop-name) find out if a prop. is "clear", which means 0 clear_property(object, prop-name) make a property "clear" verbs(object) a list of the verbs defined on an object add_verb(object, info, args) add a verb to an object delete_verb(object, verb-name) remove a verb from an object verb_info(object, verb-name) {owner, perms, names} info for a verb defn. verb_args(object, verb-name) {dobj, prep, iobj} argument info for a verb verb_code(object, verb-name [, fully-paren [, indent]]) program listing set_verb_info(object, verb-name, {owner, perms, names}) set_verb_args(object, verb-name, {dobj, prep, iobj}) set_verb_code(object, verb-name, {line, line, ...}) ##$object_utils This object is vital to MOO coding. The following will explain its functions. Examining everything an object has defined on it :all_verbs (object) => like it says :all_properties (object) => likewise :findable_properties(object) => tests to see if caller can "find" them :owned_properties (object[, owner]) => tests for ownership Investigating inheritance :ancestors(object[,object...]) => all ancestors :descendants (object) => all descendants :ordered_descendants(object) => descendants, in a different order :leaves (object) => descendants with no children :branches (object) => descendants with children :isa (object,class) => true iff object is a descendant of class (or ==) Considering containment :contains (obj1, obj2) => Does obj1 contain obj2 (nested)? :all_contents (object) => return all the (nested) contents of object Verifying verbs and properties :has_property(object,pname) => false/true according as object.(pname) exists :has_verb (object,vname) => false/{#obj} according as object:(vname) exists :has_callable_verb => same, but verb must be callable from a program :match_verb (object,vname) => false/{location, newvname} (identify location and usable name of verb) ##$command_utils This object handles commands from player, such as reading input, returning false command, ETC. Detecting and Handling Failures in Matching :object_match_failed(match_result, name) Test whether or not a :match_object() call failed and print messages if so. :player_match_failed(match_result, name) Test whether or not a :match_player() call failed and print messages if so. :player_match_result(match_results, names) ...similar to :player_match_failed, but does a whole list at once. Reading Input from the Player :read() Read one line of input from the player and return it. :yes_or_no([prompt]) Prompt for and read a `yes' or `no' answer. :read_lines() Read zero or more lines of input from the player. :dump_lines(lines) Return list of lines quoted so that feeding them to :read_lines() will reproduce the original lines. Utilities for Suspending :running_out_of_time() Return true if we're low on ticks or seconds. :suspend_if_needed(time) Suspend (and return true) if we're running out of time. Client Support for Lengthy Commands :suspend(args) Handle PREFIX and SUFFIX for clients in long commands. ##$code_utils These functions help with coding verbs with, for instance, a lot of arguments and prepositions. They also let you return a value as a number, object ID. :parse_propref("foo.bar") => {"foo","bar"} (or 0 if arg. isn't a prop. ref.) :parse_verbref("foo:bar") => {"foo","bar"} (or 0 if arg. isn't a verb ref.) :parse_argspec("any","in","front","of","this","baz"...) => {{"any", "in front of", "this"},{"baz"...}} (or string if args don't parse) :tonum(string) => number (or E_TYPE if string is not a number) :toobj(string) => object (or E_TYPE if string is not an object) :toerr(number or string) => error value (or 1 if out of range or unrecognized) :error_name(error value) => name of error (error_name(E_PERM) => "E_PERM") :verb_perms() => the current task_perms (as set by set_task_perms()). :verb_location() => the object where the current verb is defined. :verb_documentation([object,verbname]) => documentation at beginning of verb code, if any -- default is the calling verb Preposition routines :prepositions() => full list of prepositions :full_prep ("in") => "in/inside/into" :short_prep("into") => "in" :short_prep("in/inside/into") => "in" :get_prep ("off", "of", "the", "table") => {"off of", "the", "table"} Verb routines :verbname_match (fullname,name) => can `name' be used to call `fullname' :find_verb_named (object,name[,n]) => verb number or -1 if not found :find_callable_verb_named (object,name[,n]) => verb number or -1 if not found :find_verbs_containing (pattern[,object|objlist]) Verbs that do the actual dirty work for @show: :show_object(object) :show_property(object,propname) :show_verbdef(object,verbname) Dirty work for explain_syntax :explain_verb_syntax(thisname,verbname,@verbargs) A random but useful verb :verb_or_property(object,name[,@args]) => result of verb or property call, or E_PROPNF ##$building_utils These utils deal with building and extending the MOO, although they are really useful only if you use object-based exits, which is the default case in any LambdaCore-based database. Note: If you are thinking of using virtualized exits, the verbs and properties you need for that are described in appendix A. In the case of using virtualized exits, you don't need to worry about make_Exit(). Also, keep in mind that I am not providing any kind of building with virtualized exits in this manual, for that you will have to contact me. The info is in the virtual exit part. :make_exit(spec,source,dest[,don't-really-create]) => a new exit spec is an exit-spec as described in `help @dig' :set_names(object, spec) sets name and aliases for an object :parse_names(spec) => list of {name, aliases} in both of these, spec is of the form [[,:],,...] (as described in `help @rename') :recreate(object, newparent) effectively recycle and recreate object as a child of newparent :transfer_ownership(object, old-owner, new-owner) just what it sounds like ##Miscellaneous built-ins pass(arg, ...) calling a verb defined on this object's parent eval(string) parsing and executing strings as MOO code for instance eval $string_utils:columnize("name") => {"name"} So basically with eval you can execute MOO code without programming it into a verb. notify(player, string) sending text to a player's terminal read() reading a line of input from the player output_delimiters(player) return {prefix,suffix} set by PREFIX/SUFFIX cmds typeof(value) determining the data type of a value tostr(value, ...) converting any set of values into a string tofloat(value) converting any set of values into a float, for instance tofloat(1) >= 1.0 floatstr(value) same as tofloat(), but this time you can use a whole string tonum(value) converting any non-list value into a number toobj(value) converting any non-list value into an object length(value) returns the length of a string or list is_player(object) testing whether or not object is a player players() a list of all players, active or not connected_players() a list of all currently-connected players idle_seconds(player) seconds since given player typed anything connected_seconds(player) seconds given player has been logged in boot_player(player) disconnect player from the MOO immediately* set_player_flag(player, value) set/clear player bit; boot player if clear* connection_name(player) server-assigned name for player's connection open_network_connection(@args) open a connection to another network site caller_perms() the player whose permissions your caller was using set_task_perms(player) changing permissions of the running task * callers() list of {obj, verb, owner, vloc, player}: this task's stack suspend(secs) suspending the current task for a number of seconds seconds_left() number of seconds left in the current task ticks_left() number of ticks left in the current task task_id() a random number representing the currently-running task queued_tasks() list of {id,start,0,20000,owner,obj,verb,line,this} kill_task(id) delete one of your tasks from the queue server_log(string) add a comment to the server log file server_version() a string of three numbers "major.minor.release" memory_usage() {{blocksize, nused, nfree}, ...}, server's memory stats shutdown(msg) print msg and kill the server * dump_database() what it says * ##$match_utils These functions deal with matching, and are pretty self-explanatory. :match :match_nth :match_verb :match_list ##$lock_utils These utils are not used in most Lambda-based databases, but they are there nonetheless. Their purpose is to create some kind of exit locking system which, once again, works only with object-based exits. :init_scanner :scan_token :canonicalize_spaces :parse_keyexp :parse_E :parse_A :eval_key :match_object :unparse_key :eval_key_new :parse_A_new ##$perm_utils These functions deal with permissions. :controls :apply :caller ##$gender_utils Defines the list of standard genders, the default pronouns for each, and routines for adding or setting pronoun properties on any gendered object. Properties .genders list of standard genders .pronouns list of pronoun properties .ps .po .pp .pq .pr .psc .poc .ppc .pqc .prc lists of pronouns for each of the standard genders If foo is of gender this.gender[n], then the default pronoun foo.p is this.p[n) (where p is one of ps/po/pp/pq...) Verbs :set(object,newgender) changes pronoun properties to match new gender. :add(object[,perms[,owner]]) adds pronoun properties to object. :get_pronoun (which,object) return pronoun for a given object :get_conj*ugation(verbspec,object) return appropriately conjugated verb ##Appendix A: Virtualizing Exits I came across the possibility of virtualizing exits in large environments last midsummer. Since then I have been working on a system which would allow databases to use exits without them being actual object IDs. Since the game I am currently working on is a space-based one, I had to invent a system that worked in starships as well. However, the system I am going to tell you, my fellow readers, is the raw version of the virtualized exits for normal rooms ($room). Enjoy! Properties The following properties must be added to $room. You can leave the values as they are: Propnames: north, east, south, west, northeast, northwest, southeast, southwest, up, down (if you want, you can also add in and out, however, please keep in mind that the property 'in' will create misunderstandings between you and both evalling and verb coding.) To add a property, simply: @prop $room.north @prop $room.south and so on. Verbs The following is the verb for the actual exit invoking. You can copy and paste the text if you wish. Please note that this is the raw virtual exit code, with no checks for standing, for instance. Those are yours to add! @verb $room:north @edit $room:north enter exit = ""; if (verb == "n") exit = "north"; elseif (verb == "s") exit = "south"; elseif (verb == "e") exit = "east"; elseif (verb == "w") exit = "west"; elseif (verb == "ne") exit = "northeast"; elseif (verb == "nw") exit = "northwest"; elseif (verb == "sw") exit = "southwest"; elseif (verb == "se") exit = "southeast"; elseif (verb == "u") exit = "up"; elseif (verb == "d") exit = "down"; elseif (verb == "o" || verb == "ou") exit = "out"; else exit = verb; endif if (this.(exit) == 0 || !$ou:isa(this.(exit), $room)) return player:tell("You can't go that way."); endif player:tell("You walk ", exit, "."); this:announce(player.name, " walks ", exit, "."); player:moveto(this.(exit)); for x in (properties($room)) if (this.(exit).(x) == this) this.(exit):announce(player.name, " walks in from ", this.(exit).(x).name, "."); endif endfor . save done @rename $room:north to north n east e west w south s northeast ne southeast se northwest nw southwest sw up u down d out o ou in Note: If you don't want to use for x in(properties($room)) in the code, you can: @prop $room.exits ;room.exits={"north", "northeast", "east", "southeast", "south", "southwest", "west", "northwest", "up", "down", "in", "out"} @edit $room:north Find the line for x in(properties($room)), delete it and: enter for x in(this.exits) . save done That's it! You should now have a simple yet powerful virtual exit system. ##Appendix B: My Contact Information email (personal): konsta.ranta@hotmail.com email (company): prometheusmoo@gmail.com Skype: konstaranta Twitter handle: @konstaranta Facebook: http://www.facebook.com/konsta.ranta ##Appendix C: Prometheus Connection Information I am currently, along with a few other staff members, coding a MOO called Prometheus: The Eternal Wars. Its connection information is below. host: tagmanpro.com port: 2223 ##Appendix D: Compiling a MOO Server The following explains how to compile a MOO server on any Linux machine. Note: Please download: https://dl.dropboxusercontent.com/u/3599084/MOOServer.zip before proceeding. 1. Unzip the archive and .SSH to the machine you wish to compile the server on. You can also use SFTP with FileZilla. to .SSh, PuTTY works the best. 2. Transfer the contents of the archive into a new directory on the machine. For instance, you can mkdir moo cd moo and then transfer the content. I myself used FileZilla for this step, as follows: 2.1. Open FileZilla and connect to the host machine. 2.2. Go to the list which has the contents of the current host machine directory, press applications and choose Make a New Directory and Enter it. 2.3. Name the directory something simple, such as moo. 2.4. Now, go to the list which lists the contents of the current local directory. There, find the extracted archive, press CTRL+A, then applications and choose upload. 2.5. Wait for the upload to complete. 3. Now that the decompiled server is transferred, enter the directory you created with PuTTY, such as: cd moo 4. If you do not have autoconf and bison installed, you have to install them first: sudo apt-get install bison and sudo apt-get install autoconf You may also need gperf, so sudo apt-get install gperf 5. Type autoconf in the directory and wait for a few seconds, then type ./configure 6. The configuring may take a few minutes depending on your machine's specs. It is normal for it to return a few 'NO's during the process. 7. After the configuring is complete, type make or if you want to compile faster, type make -j4 8. If all is well, you should now have a compiled MOO server. You can then type ./moo databasename.db port to start your database. ##Thank You I would like to thank - Pavel Curtis, who inspired me in the idea of coding a game with the MOO environment - Joseph King, without whom Prometheus would lack much of what it now has, at least in descriptional and grammatic ways - and Jamie Shaw, without whom the idea of Prometheus would never have been true.