main.py 6.51 KB
#!/usr/bin/env python

"""A simple Multi-User Dungeon (MUD) game. Players can talk to each
other, examine their surroundings and move between rooms.

Some ideas for things to try adding:
    * More rooms to explore
    * An 'emote' command e.g. 'emote laughs out loud' -> 'Mark laughs
        out loud'
    * A 'whisper' command for talking to individual players
    * A 'shout' command for yelling to players in all rooms
    * Items to look at in rooms e.g. 'look fireplace' -> 'You see a
        roaring, glowing fire'
    * Items to pick up e.g. 'take rock' -> 'You pick up the rock'
    * Monsters to fight
    * Loot to collect
    * Saving players accounts between sessions
    * A password login
    * A shop from which to buy items

author: Mark Frimston - mfrimston@gmail.com
"""

import time
import sys
if 'esp' in sys.platform:
    import gc
    import machine
# import the MUD server class
from mudserver import MudServer

import utils

print('STARTING MUD\r\n\r\n\r\n')

if 'esp' in sys.platform:
    flash_button = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)

# stores the players in the game
players = {}

# start the server
globals()['mud'] = MudServer()

def show_prompt(pid):
    if "prompt" not in players[pid]:
        players[pid]["prompt"] = "> "
    if 'hp' not in players[pid]:
        players[pid]["hp"] = 100
    if 'mp' not in players[pid]:
        players[pid]["mp"] = 100
    if 'sta' not in players[pid]:
        players[pid]["sta"] = 10

    prompt = players[pid]["prompt"].replace('%hp', str(players[pid]["hp"])).replace('%mp', str(players[pid]["mp"]))
    mud.send_message(pid, "\r\n" + prompt, '')

tick = 0.0
spawn = 0.0
# main game loop. We loop forever (i.e. until the program is terminated)
while True:
    if 'esp' in sys.platform:
        gc.collect()
        if flash_button.value() == 0:
            break
    # pause for 1/5 of a second on each loop, so that we don't constantly
    # use 100% CPU time
    time.sleep(0.001)
    tick += 0.001
    if spawn >= 30:
        spawn = 0
        try:
            ldict = {}
            with open('spawner.txt', 'r', encoding='utf-8') as f:
                exec(f.read(), globals(), ldict)
        except Exception as e:
            print('spawner error:')
            print(e)
    if tick >= 1:
        spawn += tick
        tick = 0
        # try:
        ldict = {}
        with open('mobs.txt', 'r', encoding='utf-8') as f:
            exec(f.read(), globals(), ldict)
        # except Exception as e:
        #     print('mob error:')
        #     print(e)
    # 'update' must be called in the loop to keep the game running and give
    # us up-to-date information
    mud.update()

    # go through any newly connected players
    for id in mud.get_new_players():

        # add the new player to the dictionary, noting that they've not been
        # named yet.
        # The dictionary key is the player's id number. We set their room to
        # None initially until they have entered a name
        # Try adding more player stats - level, gold, inventory, etc
        players[id] = utils.load_object_from_file("defaultplayer.json")
        with open('welcome.txt', 'r', encoding='utf-8') as f:
            for line in f:
                mud.send_message(id, line, "\r")
        # send the new player a prompt for their name
        mud.send_message(id, "What is your name?")

    # go through any recently disconnected players
    for id in mud.get_disconnected_players():

        # if for any reason the player isn't in the player map, skip them and
        # move on to the next one
        if id not in players:
            continue

        # go through all the players in the game
        for pid, pl in players.items():
            # send each player a message to tell them about the diconnected
            # player
            if players[pid]["name"] != None:
                mud.send_message(pid, "{} quit the game".format(
                                                        players[pid]["name"]))

        # remove the player's entry in the player dictionary
        if players[id]["name"] != None:
            utils.save_object_to_file(players[id], "players/{}.json".format(players[id]["name"]))
        del(players[id])

    # go through any new commands sent from players
    for id, command, params in mud.get_commands():

        # if for any reason the player isn't in the player map, skip them and
        # move on to the next one
        if id not in players:
            continue

        # if the player hasn't given their name yet, use this first command as
        # their name and move them to the starting room.
        if players[id]["name"] is None:
            if command.strip() == '' or command is None:
                mud.send_message(id, "Invalid Name")
                continue
            already_logged_in = False
            for pid, pl in players.items():
                if players[pid]["name"] == command:
                     mud.send_message(id, "{} is already logged in.".format(command))
                     mud.disconnect_player(id)
                     already_logged_in = True
            if already_logged_in:
                continue
            loaded_player = utils.load_object_from_file("players/{}.json".format(command))
            if loaded_player is None:            
                players[id]["name"] = command
                players[id]["room"] = "Tavern"
            else:
                players[id] = loaded_player

            # go through all the players in the game
            for pid, pl in players.items():
                # send each player a message to tell them about the new player
                mud.send_message(pid, "{} entered the game".format(
                                                        players[id]["name"]))

            # send the new player a welcome message
            mud.send_message(id, "\r\n\r\nWelcome to the game, {}. ".format(
                                                           players[id]["name"])
                             + "\r\nType 'help' for a list of commands. Have fun!\r\n\r\n")

            # send the new player the description of their current room

            mud.send_message(id, utils.load_object_from_file('rooms/' + players[id]["room"] + '.txt')['description'])

        else:
            from commandhandler import CommandHandler
            cmd_handler = CommandHandler()

            handler_results = cmd_handler.parse(id, command, params, mud, players)

        show_prompt(id)

# Start WIFI Setup
if 'esp' in sys.platform:
    if flash_button.value() == 0:
        print('Starting WIFIWeb')
        import wifiweb