Imported from archive.
authorJeremy Stanley <fungi@yuggoth.org>
Wed, 28 Sep 2005 23:14:53 +0000 (23:14 +0000)
committerJeremy Stanley <fungi@yuggoth.org>
Wed, 28 Sep 2005 23:14:53 +0000 (23:14 +0000)
* command (command:look), mudpy.py (command_look): New command
allowing avatars to view the description and contents of their
location.

* mudpy.conf (internal:directions), mudpy.py
(Element.move_direction, Element.portals): Made direction vectors
for actor movement configurable.

* mudpy.conf (internal:logging), mudpy.py (log): Made logging
configurable to write to a particular file, toggle printing to
stdout, and added the ability to specify a syslog tag.

* mudpy.py (Element.go_home, Element.move_direction): Added a
feedback message to notify the user when their avatar moves between
locations, and inform other users when actors depart from or arrive
at their location.
(User.send): Avoid unnecessarily duplicating prompts following
unsolicited/notification messages.

command
mudpy.conf
mudpy.py

diff --git a/command b/command
index 5319735..6d4509a 100644 (file)
--- a/command
+++ b/command
@@ -30,6 +30,11 @@ action = command_help(user, parameters)
 description = List commands or get help on one.
 help = This will list all comand words available to you along with a brief description or, alternatively, give you detailed information on one command.
 
+[command:look]
+action = command_look(user, parameters)
+description = Look around.
+help = With the look command, you can see where you are.
+
 [command:move]
 action = command_move(user, parameters)
 description = Move in a specific direction.
index fdacfe1..280368a 100644 (file)
@@ -18,6 +18,11 @@ punctuation_say = .
 max_avatars = 7
 password_tries = 3
 
+[internal:logging]
+#file = mudpy.log
+stdout = yes
+#syslog = mudpy
+
 [internal:network]
 host = 
 port = 6669
@@ -34,3 +39,11 @@ frequency_log = 6000
 frequency_save = 600
 increment = 0.1
 
+[internal:directions]
+down = { "vector": (0,0,-1), "exit": "downward", "enter": "above" }
+east = { "vector": (1,0,0), "exit": "to the east", "enter": "the west" }
+north = { "vector": (0,1,0), "exit": "to the north", "enter": "the south" }
+south = { "vector": (0,-1,0), "exit": "to the south", "enter": "the north" }
+up = { "vector": (0,0,1), "exit": "upward", "enter": "below" }
+west = { "vector": (-1,0,0), "exit": "to the west", "enter": "the east" }
+
index 4c3cdf5..7e23d23 100644 (file)
--- a/mudpy.py
+++ b/mudpy.py
@@ -139,7 +139,7 @@ class Element:
        def go_to(self, location):
                """Relocate the element to a specific location."""
                current = self.get("location")
-               if current and current in universe.contents[current].contents:
+               if current and self.key in universe.contents[current].contents:
                        del universe.contents[current].contents[self.key]
                if location in universe.contents: self.set("location", location)
                universe.contents[location].contents[self.key] = self
@@ -147,9 +147,13 @@ class Element:
        def go_home(self):
                """Relocate the element to its default location."""
                self.go_to(self.get("default_location"))
+               self.echo_to_location("You suddenly realize that " + self.get("name") + " is here.")
        def move_direction(self, direction):
                """Relocate the element in a specified direction."""
+               self.echo_to_location(self.get("name") + " exits " + universe.categories["internal"]["directions"].getdict(direction)["exit"] + ".")
+               self.send("You exit " + universe.categories["internal"]["directions"].getdict(direction)["exit"] + ".")
                self.go_to(universe.contents[self.get("location")].link_neighbor(direction))
+               self.echo_to_location(self.get("name") + " arrives from " + universe.categories["internal"]["directions"].getdict(direction)["enter"] + ".")
        def look_at(self, key):
                """Show an element to another element."""
                if self.owner:
@@ -172,14 +176,8 @@ class Element:
                portals = {}
                if match("""^location:-?\d+,-?\d+,-?\d+$""", self.key):
                        coordinates = [(int(x)) for x in self.key.split(":")[1].split(",")]
-                       offsets = {
-                               "down": (0,0,-1),
-                               "east": (1,0,0),
-                               "north": (0,1,0),
-                               "south": (0,-1,0),
-                               "up": (0,0,1),
-                               "west": (-1,0,0)
-                               }
+                       directions = universe.categories["internal"]["directions"]
+                       offsets = dict([(x, directions.getdict(x)["vector"]) for x in directions.facets()])
                        for portal in self.getlist("gridlinks"):
                                adjacent = map(lambda c,o: c+o, coordinates, offsets[portal])
                                neighbor = "location:" + ",".join([(str(x)) for x in adjacent])
@@ -337,6 +335,7 @@ class User:
                self.output_queue = []
                self.partial_input = ""
                self.echoing = True
+               self.received_newline = True
                self.terminator = IAC+GA
                self.negotiation_pause = 0
                self.avatar = None
@@ -377,6 +376,7 @@ class User:
                        "output_queue",
                        "partial_input",
                        "echoing",
+                       "received_newline",
                        "terminator",
                        "negotiation_pause",
                        "avatar",
@@ -451,7 +451,7 @@ class User:
                """Remove a user from the list of connected users."""
                universe.userlist.remove(self)
 
-       def send(self, output, eol="$(eol)", raw=False, flush=False, add_prompt=True):
+       def send(self, output, eol="$(eol)", raw=False, flush=False, add_prompt=True, just_prompt=False):
                """Send arbitrary text to a connected user."""
 
                # unless raw mode is on, clean it up all nice and pretty
@@ -470,10 +470,13 @@ class User:
                        # start with a newline, append the message, then end
                        # with the optional eol string passed to this function
                        # and the ansi escape to return to normal text
-                       output = "$(eol)" + output + eol + chr(27) + "[0m"
+                       if not just_prompt: output = "$(eol)$(eol)" + output
+                       output += eol + chr(27) + "[0m"
 
                        # tack on a prompt if active
-                       if self.state == "active" and add_prompt: output += "$(eol)> "
+                       if self.state == "active":
+                               if not just_prompt: output += "$(eol)"
+                               if add_prompt: output += "> "
 
                        # find and replace macros in the output
                        output = replace_macros(self, output)
@@ -521,6 +524,10 @@ class User:
        def flush(self):
                """Try to send the last item in the queue and remove it."""
                if self.output_queue:
+                       if self.received_newline:
+                               self.received_newline = False
+                               if self.output_queue[0].startswith("\r\n"):
+                                       self.output_queue[0] = self.output_queue[0][2:]
                        try:
                                self.connection.send(self.output_queue[0])
                                del self.output_queue[0]
@@ -697,6 +704,7 @@ class User:
                if self.avatar:
                        current = self.avatar.get("location")
                        self.avatar.set("default_location", current)
+                       self.avatar.echo_to_location("You suddenly wonder where " + self.avatar.get("name") + " went.")
                        del universe.contents[current].contents[self.avatar.key]
                        self.avatar.remove_facet("location")
                        self.avatar.owner = None
@@ -722,9 +730,9 @@ def makedict(value):
        elif value.find(":") > 0: return eval("{" + value + "}")
        else: return { value: None }
 
-def broadcast(message):
+def broadcast(message, add_prompt=True):
        """Send a message to all connected users."""
-       for each_user in universe.userlist: each_user.send("$(eol)" + message)
+       for each_user in universe.userlist: each_user.send("$(eol)" + message, add_prompt=add_prompt)
 
 def log(message):
        """Log a message."""
@@ -732,13 +740,23 @@ def log(message):
        # the time in posix log timestamp format
        timestamp = asctime()[4:19]
 
+       file_name = universe.categories["internal"]["logging"].get("file")
+       if file_name:
+               file_descriptor = file(file_name, "a")
+               file_descriptor.write(timestamp + " " + message + "\n")
+               file_descriptor.flush()
+               file_descriptor.close()
+
        # send the timestamp and message to standard output
-       print(timestamp + " " + message)
+       if universe.categories["internal"]["logging"].getboolean("stdout"):
+               print(timestamp + " " + message)
 
        # send the message to the system log
-       openlog("mudpy", LOG_PID, LOG_INFO | LOG_DAEMON)
-       syslog(message)
-       closelog()
+       syslog_name = universe.categories["internal"]["logging"].get("syslog")
+       if syslog_name:
+               openlog(syslog_name, LOG_PID, LOG_INFO | LOG_DAEMON)
+               syslog(message)
+               closelog()
 
 def wrap_ansi_text(text, width):
        """Wrap text with arbitrary width while ignoring ANSI colors."""
@@ -1157,7 +1175,7 @@ def handle_user_input(user):
        user.menu_seen = False
 
        # if the user's client echo is off, send a blank line for aesthetics
-       if not user.echoing: user.send("", "")
+       if user.echoing: user.received_newline = True
 
 def generic_menu_handler(user):
        """A generic menu choice handler."""
@@ -1287,27 +1305,33 @@ def handler_active(user):
        # get the next waiting line of input
        input_data = user.input_queue.pop(0)
 
-       # split out the command (first word) and parameters (everything else)
-       if input_data.find(" ") > 0:
-               command_name, parameters = input_data.split(" ", 1)
-       else:
-               command_name = input_data
-               parameters = ""
+       # is there input?
+       if input_data:
 
-       # lowercase the command
-       command_name = command_name.lower()
+               # split out the command (first word) and parameters (everything else)
+               if input_data.find(" ") > 0:
+                       command_name, parameters = input_data.split(" ", 1)
+               else:
+                       command_name = input_data
+                       parameters = ""
 
-       # the command matches a command word for which we have data
-       if command_name in universe.categories["command"]:
-               command = universe.categories["command"][command_name]
-       else: command = None
+               # lowercase the command
+               command_name = command_name.lower()
 
-       # if it's allowed, do it
-       if user.can_run(command): exec(command.get("action"))
+               # the command matches a command word for which we have data
+               if command_name in universe.categories["command"]:
+                       command = universe.categories["command"][command_name]
+               else: command = None
+
+               # if it's allowed, do it
+               if user.can_run(command): exec(command.get("action"))
 
-       # otherwise, give an error
-       elif command_name: command_error(user, input_data)
+               # otherwise, give an error
+               elif command_name: command_error(user, input_data)
 
+       # if no input, just idle back with a prompt
+       else: user.send("", just_prompt=True)
+       
 def command_halt(user, parameters):
        """Halt the world."""
 
@@ -1316,7 +1340,7 @@ def command_halt(user, parameters):
        else: message = "User " + user.account.get("name") + " halted the world."
 
        # let everyone know
-       broadcast(message)
+       broadcast(message, add_prompt=False)
        log(message)
 
        # set a flag to terminate the world
@@ -1396,6 +1420,11 @@ def command_move(user, parameters):
                user.avatar.move_direction(parameters)
        else: user.send("You cannot go that way.")
 
+def command_look(user, parameters):
+       """Look around."""
+       if parameters: user.send("You look at or in anything yet.")
+       else: user.avatar.look_at(user.avatar.get("location"))
+
 def command_say(user, parameters):
        """Speak to others in the same room."""