Ejemplo n.º 1
0
    def execInstruction(self, instruction):
        # returns the next address or -1 if the
        # loop should be broken

        def getOffset(self, text):
            if text[0] == "@":
                label = text[1:]
                return self._labels[label]
            elif text == "end":
                return len(self._script) + 1
            elif text[0] == "+" or text[0] == "-":
                return self._scriptPtr + int(text)
            else:
                return int(text)

        def push(self, value):
            self._stack.insert(0, value)

        def pop(self):
            if self._stack == []:
                self.warning("Stack underflow.")
                return None
            val = self._stack[0]
            del self._stack[0]

            return val

        token = string.split(instruction)

        nextPtr = self._scriptPtr + 1

        # :dprint <<expression>>
        #
        # Print some debugging info in the server stdout.
        #
        if token[0] == ":dprint":
            print "DPRINT[" + self._id + "." + ` self._oid ` + "]:", self.evalExpr(string.join(token[1:]))

        # :reset
        #
        #
        elif token[0] == ":reset":
            self.reset()

        # :write <<expression>>
        #
        # Write the expression result into the room.
        #
        elif token[0] == ":write":
            room = self.getLocation()
            room.writeToRoom(self.evalExpr(string.join(token[1:])) + "\r\n")

        # :putcookie <<Character>> <cookie>
        #
        # Adds a piece of arbitrary string to a character cookie box.
        #
        elif token[0] == ":putcookie":
            char = self.evalExpr(token[1])
            char.putCookie(token[2])

        # :hascookie <<Character>> <cookie> <command>
        #
        # Checks whether the character has the cookie and executes the
        # command if yes.
        #
        elif token[0] == ":hascookie":
            char = self.evalExpr(token[1])
            if char.hasCookie(token[2]):
                nextPtr = self.execInstruction(string.join(token[3:]))

                # :removecookie <<Character>> <cookie>
                #
                # Removes the cookie from the character's cookie box if it's there.
                #
        elif token[0] == ":removecookie":
            char = self.evalExpr(token[1])
            char.removeCookie(token[2])

        # :addquest <<Character>> <quest descr>
        #
        # Adds a quest description to the character.
        #
        elif token[0] == ":addquest":
            char = self.evalExpr(token[1])
            char._quests.append(token[2])

        # :removequest <<Character>> <keyword>
        #
        # Remove a quest description that contains the keyword from
        # the character.
        #
        elif token[0] == ":removequest":
            char = self.evalExpr(token[1])
            for q in char._quests:
                if string.find(q, token[2]) >= 0:
                    char._quests.remove(q)
                    break

                # :do <mud command> <<expression>>
                #
                # Execute a MUD command using the expression result as argument.
                #
        elif token[0] == ":do":
            self._commandQueue.append(token[1] + " " + self.evalExpr(string.join(token[2:])))

        # :goto <position> | :goto +/- <offset> | :goto end | :goto @label
        #
        # Go to another part of the script.
        #
        elif token[0] == ":goto":
            nextPtr = getOffset(self, token[1])
            print "goto", nextPtr, self._state

        # :gosub <position> | :gosub +/-<offset>
        #
        # Go to another part of the script and save current position.
        # Can be returned later into this position with :return.
        #
        elif token[0] == ":gosub":
            push(self, nextPtr)
            nextPtr = getOffset(self, token[1])

        # :return
        #
        # Return to a place where a :gosub was called
        #
        elif token[0] == ":return":
            nextPtr = pop(self)

        # :delay <<seconds>>
        #
        # Delay for some time
        #
        elif token[0] == ":delay":
            if self._commandQueue:  # must wait the queue to be empty,
                # so the delay will actually happen
                return -1

            if self._delay == 0:
                self._delay = self.evalExpr(token[1]) + 1
                return -1
            else:
                self._delay = self._delay - 1
                if self._delay > 0:
                    return -1

                # :wait <event type> [from <<Mobile>>]
                #
                # Wait for an event of specified type and optionally
                # from the specified Mobile.
                #
        elif token[0] == ":wait":
            self._waitingEvent = token[1]
            if len(token) == 4:
                if token[2] == "from":
                    self._waitingEventFrom = self.evalExpr(token[3])

            return -1

        # :on <event> [from <<Mobile>>] <command>
        #
        # Set a event handler for the specified event, making it jump to
        # position when it occurs.
        #
        elif token[0] == ":on":
            event = token[1]
            if len(token) > 2:
                if token[2] == "from":
                    mob = self.evalExpr(token[3])
                    cmd = string.join(token[4:])
                else:
                    mob = None
                    cmd = string.join(token[2:])

                self._onHandlers[event] = (mob, cmd)
            else:
                self._onHandlers[event] = None

                # :set <identifier> <<expression>>
                #
                # Assign expression result into variable
                #
        elif token[0] == ":set":
            self._variables.__dict__[token[1]] = self.evalExpr(string.join(token[2:]))

        # :match <<string1>> <<string2>> <position>
        #
        # Try to match the strings and jump to position if they do.
        #
        elif token[0] == ":match":
            parts1 = string.split(string.lower(self.evalExpr(token[1])))
            parts2 = string.split(string.lower(self.evalExpr(token[2])))

            if len(parts1) == len(parts2):
                ok = 1
                for i in range(len(parts1)):
                    if parts1[i] != parts2[i]:
                        ok = 0
                        break
                if ok:
                    nextPtr = getOffset(self, token[3])

                # :speed <seconds>
                #
                # Set the speed (delay between commands) of the script to be executed.
                #
        elif token[0] == ":speed":
            self._speed = max(int(token[1]), 1)

        # :case <<expression>> <<value1>> <pos1> <<value2>> <pos2> ...

        # :if <<expression>> then <position>
        #
        # If result of expression is true, jump to position, else continue.
        #
        elif token[0] == ":if":
            i = token.index("then")
            if self.evalExpr(string.join(token[1:i])):
                nextPtr = getOffset(self, token[i + 1])

                # :label <identifier>
                #
                # Set a label. (handled on startup, so its ignored here)
                #
        elif token[0] == ":label":
            pass

        # :message <target id> <message>
        #
        # Sends a message to a target.
        #
        elif token[0] == ":message":
            event = Event(EVN_MESSAGE, self)
            event.message = token[2]

            for m in self._world._mobiles:
                if m._id == token[1]:
                    m.handleEvent(event)

        else:
            self.warning("Invalid command in mob script " + token[0])

        return nextPtr