You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
13 KiB
Python

#!/usr/bin/env python
"""A simple Multi-User Dungeon (MUD) game. Players can talk to each
other, examine their surroundings and move between rooms.
author: Mark Frimston - mfrimston@gmail.com
"""
import time
import json
# import the MUD server class
from mudserver import MudServer
with open('rooms.json', 'r') as f:
rooms = json.load(f)
# stores the players and npcs in the game
players = {}
# start the server
mud = MudServer()
# main game loop. We loop forever (i.e. until the program is terminated)
while True:
# pause for 1/5 of a second on each loop, so that we don't constantly
# use 100% CPU time
time.sleep(0.2)
# '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] = {
"name": None,
"room": None,
}
# send the new player a prompt for their name
mud.send_message(id, """\r
_ _ _ \r
| |_ _____ _| |_ _ __ _ _| |__ \r
| __/ _ \ \/ / __| '_ \| | | | '_ \ \r
| || __/> <| |_| |_) | |_| | |_) |\r
\__\___/_/\_\ __| .__/ \__,_|_.__/ \r
|_| \r
\r\r
Hi there! This is the multiplayer, text-based version of the Experimental Publishing masters at PZI. How about you begin by letting us know what you want to be called? Then press enter.
""")
# 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
mud.send_message(pid, "\r{} quit the game".format(
players[id]["name"]))
# remove the player's entry in the player dictionary
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:
players[id]["name"] = command
players[id]["room"] = "Corridor"
# 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, "{} has logged in.".format(
players[id]["name"]))
# send the new player a welcome message, and a description of the starting room
mud.send_message(id, "Welcome to textpub, " +players[id]["name"]+ ". " + rooms[players[id]["room"]]["description"] + " Type 'help' for a list of commands. Have fun!")
# each of the possible commands is handled below. Try adding new
# commands to the game!
# 'help' command
elif command == "help":
# send the player back the list of possible commands
mud.send_message(id, "Commands:")
mud.send_message(id, " say <message> - Says something out loud, "
+ "e.g. 'say Hello'")
mud.send_message(id, " look - Examines the "
+ "surroundings, e.g. 'look'")
mud.send_message(id, " go <exit> - Moves through the exit "
+ "specified, e.g. 'go outside'")
mud.send_message(id, " create <exit> <new roomname> - Creates a new exit and room")
mud.send_message(id, " describe <description> - Change the description of the current room")
# 'say' command
elif command == "say":
# go through every player in the game
for pid, pl in players.items():
# if they're in the same room as the player
if players[pid]["room"] == players[id]["room"]:
# send them a message telling them what the player said
mud.send_message(pid, "{} says: {}".format(
players[id]["name"], params))
# 'look' command
elif command == "look":
# store the player's current room
rm = rooms[players[id]["room"]]
# send the player back the description of their current room
mud.send_message(id, rm["description"])
playershere = []
# go through every player in the game
for pid, pl in players.items():
# if they're in the same room as the player
if players[pid]["room"] == players[id]["room"]:
# ... and they have a name to be shown
if players[pid]["name"] is not None:
# add their name to the list
playershere.append(players[pid]["name"])
# go through every npc in the game
for pid in mud.npcs.keys():
# if they're in the same room as the player
if mud.npcs[pid].room == players[id]["room"]:
# ... and they have a name to be shown
if mud.npcs[pid].name is not None:
# add their name to the list
playershere.append(mud.npcs[pid].name)
# send player a message containing the list of players in the room
mud.send_message(id, "Players here: {}".format(
", ".join(playershere)))
# send player a message containing the list of exits from this room
mud.send_message(id, "Exits are: {}".format(
", ".join(rm["exits"])))
# 'go' command
elif command == "go":
# store the exit name
ex = params.lower()
# store the player's current room
rm = rooms[players[id]["room"]]
# if the specified exit is found in the room's exits list
if ex in rm["exits"]:
# go through all the players in the game
for pid, pl in players.items():
# if player is in the same room and isn't the player
# sending the command
if players[pid]["room"] == players[id]["room"] \
and pid != id:
# send them a message telling them that the player
# left the room
mud.send_message(pid, "{} left via exit '{}'".format(
players[id]["name"], ex))
# update the player's current room to the one the exit leads to
players[id]["room"] = rm["exits"][ex]
rm = rooms[players[id]["room"]]
# print(players[id]["name"] + " moved to the " + players[id]["room"])
# go through all the players in the game
for pid, pl in players.items():
# if player is in the same (new) room and isn't the player
# sending the command
if players[pid]["room"] == players[id]["room"] \
and pid != id:
# send them a message telling them that the player
# entered the room
mud.send_message(pid,
"{} arrived via exit '{}'".format(
players[id]["name"], ex))
# send the player a message telling them where they are now
mud.send_message(id, "You have entered the {}".format(
players[id]["room"]))
# the specified exit wasn't found in the current room
else:
# send back an 'unknown exit' message
mud.send_message(id, "Unknown exit '{}'".format(ex))
# Item commands, to be completed
# get command
elif command == "get":
mud.send_message(id, "You got it")
# drop command
elif command == "drop":
mud.send_message(id, "You dropped it")
# make command
elif command == "make":
mud.send_message(id, "You made a ")
# 'create' command
elif command == "create":
# store the exit or room that will be created
parameters = params.lower()
parameters_list = parameters.split()
print("[INSPECT] parameters: ", parameters_list)
if len(parameters_list) >= 1:
# store the new exit name
new_exit = parameters_list[0]
print("[INSPECT] new exit: ", new_exit)
else:
new_exit = None
if len(parameters_list) >= 2:
# store the new room name
new_room = " ".join(parameters_list[1:])
print("[INSPECT] new room: ", new_room)
else:
new_exit = None
# store the player's current room
current_room_name = players[id]["room"]
print("[INSPECT] current room: ", current_room_name)
# store information about the player's current room
current_room = rooms[players[id]["room"]]
print("[INSPECT] current room dict: ", current_room)
# if both the new exit and new room are given
if new_exit is not None and new_room is not None:
# send player a message when the exit already exists
if new_exit in current_room["exits"]:
mud.send_message(id, "This exit already exist.")
# create new room
else:
print(f"[INSPECT] Make new room: { new_room }, in the direction: { new_exit }")
# add the new exit to the current room
rooms[current_room_name]["exits"][new_exit] = new_room
# store information about the new room
rooms[new_room] = {}
rooms[new_room]["description"] = ""
rooms[new_room]["exits"] = {}
# add the opposite exit direction to the exits of the new room
if new_exit == "west":
exit_to_add = "east"
elif new_exit == "east":
exit_to_add = "east"
if new_exit == "north":
exit_to_add = "south"
elif new_exit == "south":
exit_to_add = "north"
# store this exit to the new room
rooms[new_room]["exits"][exit_to_add] = current_room_name
# announce the new room to the player
mud.send_message(id, f"A new room is added: { new_room } (in the { new_exit })")
# invite the player to write a description for the room
mud.send_message(id, "The room is not described yet. When you are in the room, you can use 'describe' to add a description. For example: 'describe This is the XML! It smells a bit muffy here.'")
with open("rooms.json", "w") as jsonFile:
json.dump(rooms, jsonFile)
# warn the player when the "create" command is not used in the right way
else:
mud.send_message(id, f"Sorry you cannot create a new room in that way. Try: 'create direction roomname'")
# 'describe' command
elif command == "describe":
# store the exit or room that will be created
description = params.lower()
print("[INSPECT] description: ", description)
# store the player's current room
current_room_name = players[id]["room"]
print("[INSPECT] current room: ", current_room_name)
rooms[new_room]["description"] = description
with open("rooms.json", "w") as jsonFile:
json.dump(rooms, jsonFile)
# some other, unrecognised command
else:
# send back an 'unknown command' message
mud.send_message(id, "Unknown command '{}'".format(command))