51c565a0 by Barry Ruffner

Added better colors and bug fixes

1 parent 9b22a762
...@@ -16,54 +16,58 @@ global_aliases = { ...@@ -16,54 +16,58 @@ global_aliases = {
16 'social': 'emote' 16 'social': 'emote'
17 } 17 }
18 18
19
19 class CommandHandler(object): 20 class CommandHandler(object):
20 21
21 def parse(self, id, cmd, params, mud, players): 22 def parse(self, id, cmd, params, mud, players):
22 if cmd in global_aliases: 23 if cmd in global_aliases:
23 cmd = global_aliases[cmd] 24 cmd = global_aliases[cmd]
24 else: 25 else:
25 if 'aliases' not in players[id]: 26 if 'aliases' not in players[id]:
26 players[id]["aliases"] = {} 27 players[id]["aliases"] = {}
27 if cmd in players[id]["aliases"]: 28 if cmd in players[id]["aliases"]:
28 cmd = players[id]["aliases"][cmd] 29 cmd = players[id]["aliases"][cmd]
29 30
30 tokens = [] 31 tokens = []
31 for token in params.lower().strip().split(' '): 32 for token in params.lower().strip().split(' '):
32 token = token.strip() 33 token = token.strip()
33 if len(token) > 0: 34 if len(token) > 0:
34 tokens.append(token) 35 tokens.append(token)
35 locals()['tokens'] = tokens 36 locals()['tokens'] = tokens
36 37
37 locals()['next_command'] = None 38 locals()['next_command'] = None
38 try: 39 try:
39 if cmd in utils.load_object_from_file('rooms/' + players[id]["room"] + '.json').get('exits'): 40 if cmd in utils.load_object_from_file('rooms/' + players[id]["room"] + '.json').get('exits'):
40 params = cmd + " " + params.lower().strip() 41 params = cmd + " " + params.lower().strip()
41 cmd = "go" 42 cmd = "go"
42 if cmd in players[id]["sp"]: 43 if cmd in players[id]["sp"]:
43 params = cmd + " " + params.lower().strip() 44 params = cmd + " " + params.lower().strip()
44 cmd = "cast" 45 cmd = "cast"
45 if cmd in players[id]["at"]: 46 if cmd in players[id]["at"]:
46 params = cmd + " " + params.lower().strip() 47 params = cmd + " " + params.lower().strip()
47 cmd = "perform" 48 cmd = "perform"
48 if cmd == '': 49 if cmd == '':
50 return True
51 command = cmd
52 ldict = locals()
53 with open('commands/{}.txt'.format(cmd), 'r', encoding='utf-8') as f:
54 command_text = f.read()
55 exec(command_text, globals(), ldict)
56 del command_text
57 if ldict['next_command'] is not None:
58 locals()['tokens'] = []
59 tokens = []
60 with open('commands/{}.txt'.format(ldict['next_command']), 'r', encoding='utf-8') as f:
61 exec(f.read())
62 del ldict
49 return True 63 return True
50 command = cmd 64 except Exception as e:
51 ldict = locals() 65 print('Something happened...')
52 with open('commands/{}.txt'.format(cmd), 'r', encoding='utf-8') as f: 66 import sys
53 command_text = f.read() 67 if 'esp' not in sys.platform:
54 exec(command_text, globals(), ldict) 68 import traceback
55 del command_text 69 traceback.print_exc()
56 if ldict['next_command'] != None: 70 else:
57 locals()['tokens'] = [] 71 print(e)
58 tokens = [] 72 mud.send_message(id, "Unknown command '{}'".format(cmd))
59 with open('commands/{}.txt'.format(ldict['next_command']), 'r', encoding='utf-8') as f: 73 return False
60 exec(f.read())
61 del ldict
62 return True
63 except Exception as e:
64 print('Something happened...')
65 print(e)
66 mud.send_message(id, "Unknown command '{}'".format(cmd))
67 return False
68
69
......
...@@ -6,7 +6,8 @@ def look(id, mud, players, tokens): ...@@ -6,7 +6,8 @@ def look(id, mud, players, tokens):
6 if len(tokens) > 0 and tokens[0] == 'at': 6 if len(tokens) > 0 and tokens[0] == 'at':
7 del tokens[0] 7 del tokens[0]
8 if len(tokens) == 0: 8 if len(tokens) == 0:
9 mud.send_message(id, room_data.get('description')) 9 mud.send_message(id, room_data.get('title'), color=['bold', 'green'])
10 mud.send_message(id, room_data.get('description'), color='green')
10 else: 11 else:
11 subject = tokens[0] 12 subject = tokens[0]
12 items = room_data.get('look_items') 13 items = room_data.get('look_items')
...@@ -43,14 +44,14 @@ def look(id, mud, players, tokens): ...@@ -43,14 +44,14 @@ def look(id, mud, players, tokens):
43 44
44 # send player a message containing the list of players in the room 45 # send player a message containing the list of players in the room
45 if len(playershere) > 0: 46 if len(playershere) > 0:
46 mud.send_message(id, "Players here: {}".format(", ".join(playershere))) 47 mud.send_message(id, "%boldPlayers here:%reset {}".format(", ".join(playershere)))
47 48
48 # send player a message containing the list of exits from this room 49 # send player a message containing the list of exits from this room
49 mud.send_message(id, "Exits are: {}".format(", ".join(room_data.get('exits')))) 50 mud.send_message(id, "%boldObvious Exits:%reset {}".format(", ".join(room_data.get('exits'))))
50 51
51 # send player a message containing the list of exits from this room 52 # send player a message containing the list of exits from this room
52 if len(room_data.get('inventory')) > 0: 53 if len(room_data.get('inventory')) > 0:
53 mud.send_message(id, "Items here: {}".format(", ".join(room_data.get('inventory').keys()))) 54 mud.send_message(id, "%boldItems here:%reset {}".format(", ".join(room_data.get('inventory').keys())))
54 55
55 # send player a message containing the list of players in the room 56 # send player a message containing the list of players in the room
56 for mon_name, monster in room_monsters.items(): 57 for mon_name, monster in room_monsters.items():
......
...@@ -6,30 +6,22 @@ MudServer author: Mark Frimston - mfrimston@gmail.com ...@@ -6,30 +6,22 @@ MudServer author: Mark Frimston - mfrimston@gmail.com
6 Micropython port and expansion author: Barry Ruffner - barryruffner@gmail.com 6 Micropython port and expansion author: Barry Ruffner - barryruffner@gmail.com
7 """ 7 """
8 8
9 from time import sleep
10 from math import floor
9 from sys import platform 11 from sys import platform
12
13 from mudserver import MudServer
14 from utils import load_object_from_file, save_object_to_file
15
10 if 'esp' in platform: 16 if 'esp' in platform:
11 from gc import collect, mem_free 17 from gc import collect, mem_free
12 from machine import Pin 18 from machine import Pin
13 if 'esp' in platform:
14 collect()
15 from time import sleep
16 if 'esp' in platform:
17 collect()
18 # import the MUD server class 19 # import the MUD server class
19 from mudserver import MudServer
20 if 'esp' in platform:
21 collect()
22 20
23 from utils import load_object_from_file, save_object_to_file 21
24 if 'esp' in platform:
25 collect()
26 from math import floor
27 if 'esp' in platform:
28 collect()
29 import micropython
30 micropython.mem_info(1)
31 print('STARTING MUD\r\n\r\n\r\n') 22 print('STARTING MUD\r\n\r\n\r\n')
32 23
24 # Setup button so when pressed the mud goes in to wifi hotspot mode on 192.168.4.1
33 if 'esp' in platform: 25 if 'esp' in platform:
34 flash_button = Pin(0, Pin.IN, Pin.PULL_UP) 26 flash_button = Pin(0, Pin.IN, Pin.PULL_UP)
35 27
...@@ -39,6 +31,7 @@ players = {} ...@@ -39,6 +31,7 @@ players = {}
39 # start the server 31 # start the server
40 globals()['mud'] = MudServer() 32 globals()['mud'] = MudServer()
41 33
34
42 def show_prompt(pid): 35 def show_prompt(pid):
43 if "prompt" not in players[pid]: 36 if "prompt" not in players[pid]:
44 players[pid]["prompt"] = "> " 37 players[pid]["prompt"] = "> "
...@@ -61,7 +54,7 @@ while True: ...@@ -61,7 +54,7 @@ while True:
61 if flash_button.value() == 0: 54 if flash_button.value() == 0:
62 break 55 break
63 # pause for 1/5 of a second on each loop, so that we don't constantly 56 # pause for 1/5 of a second on each loop, so that we don't constantly
64 sleep(0.001) 57 sleep(0.002)
65 if 'esp' in platform: 58 if 'esp' in platform:
66 tick += 0.001 59 tick += 0.001
67 else: 60 else:
...@@ -125,11 +118,11 @@ while True: ...@@ -125,11 +118,11 @@ while True:
125 for pid, pl in players.items(): 118 for pid, pl in players.items():
126 # send each player a message to tell them about the diconnected 119 # send each player a message to tell them about the diconnected
127 # player 120 # player
128 if players[pid]["name"] != None: 121 if players[pid]["name"] is not None:
129 mud.send_message(pid, "{} quit the game".format(players[pid]["name"])) 122 mud.send_message(pid, "{} quit the game".format(players[pid]["name"]))
130 123
131 # remove the player's entry in the player dictionary 124 # remove the player's entry in the player dictionary
132 if players[id]["name"] != None: 125 if players[id]["name"] is not None:
133 save_object_to_file(players[id], "players/{}.json".format(players[id]["name"])) 126 save_object_to_file(players[id], "players/{}.json".format(players[id]["name"]))
134 del(players[id]) 127 del(players[id])
135 128
...@@ -150,13 +143,13 @@ while True: ...@@ -150,13 +143,13 @@ while True:
150 already_logged_in = False 143 already_logged_in = False
151 for pid, pl in players.items(): 144 for pid, pl in players.items():
152 if players[pid]["name"] == command: 145 if players[pid]["name"] == command:
153 mud.send_message(id, "{} is already logged in.".format(command)) 146 mud.send_message(id, "{} is already logged in.".format(command))
154 mud.disconnect_player(id) 147 mud.disconnect_player(id)
155 already_logged_in = True 148 already_logged_in = True
156 if already_logged_in: 149 if already_logged_in:
157 continue 150 continue
158 loaded_player = load_object_from_file("players/{}.json".format(command)) 151 loaded_player = load_object_from_file("players/{}.json".format(command))
159 if loaded_player is None: 152 if loaded_player is None:
160 players[id]["name"] = command 153 players[id]["name"] = command
161 players[id]["room"] = "Tavern" 154 players[id]["room"] = "Tavern"
162 else: 155 else:
...@@ -165,13 +158,11 @@ while True: ...@@ -165,13 +158,11 @@ while True:
165 # go through all the players in the game 158 # go through all the players in the game
166 for pid, pl in players.items(): 159 for pid, pl in players.items():
167 # send each player a message to tell them about the new player 160 # send each player a message to tell them about the new player
168 mud.send_message(pid, "{} entered the game".format( 161 mud.send_message(pid, "{} entered the game".format(players[id]["name"]))
169 players[id]["name"]))
170 162
171 # send the new player a welcome message 163 # send the new player a welcome message
172 mud.send_message(id, "\r\n\r\nWelcome to the game, {}. ".format( 164 mud.send_message(id, "\r\n\r\nWelcome to the game, {}. ".format(players[id]["name"]) +
173 players[id]["name"]) 165 "\r\nType 'help' for a list of commands. Have fun!\r\n\r\n")
174 + "\r\nType 'help' for a list of commands. Have fun!\r\n\r\n")
175 166
176 # send the new player the description of their current room 167 # send the new player the description of their current room
177 168
...@@ -184,7 +175,6 @@ while True: ...@@ -184,7 +175,6 @@ while True:
184 cmd_handler = CommandHandler() 175 cmd_handler = CommandHandler()
185 176
186 handler_results = cmd_handler.parse(id, command, params, mud, players) 177 handler_results = cmd_handler.parse(id, command, params, mud, players)
187
188 show_prompt(id) 178 show_prompt(id)
189 179
190 # Start WIFI Setup 180 # Start WIFI Setup
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 "mpr": 0.25, 5 "mpr": 0.25,
6 "star": 0.4, 6 "star": 0.4,
7 "spawn": { 7 "spawn": {
8 "hp": "2d2", 8 "hp": "2d16",
9 "mp": "10", 9 "mp": "10",
10 "sta": "10" 10 "sta": "10"
11 }, 11 },
......
...@@ -12,7 +12,9 @@ import socket ...@@ -12,7 +12,9 @@ import socket
12 import select 12 import select
13 import time 13 import time
14 import sys 14 import sys
15 from utils import get_color 15
16 from utils import get_color, get_color_list, multiple_replace
17
16 18
17 class MudServer(object): 19 class MudServer(object):
18 """A basic server for text-based Multi-User Dungeon (MUD) games. 20 """A basic server for text-based Multi-User Dungeon (MUD) games.
...@@ -188,8 +190,9 @@ class MudServer(object): ...@@ -188,8 +190,9 @@ class MudServer(object):
188 """ 190 """
189 # we make sure to put a newline on the end so the client receives the 191 # we make sure to put a newline on the end so the client receives the
190 # message on its own line 192 # message on its own line
193 message = multiple_replace(message, get_color_list())
191 chunks, chunk_size = len(message), 80 #len(x)/4 194 chunks, chunk_size = len(message), 80 #len(x)/4
192 lines = [ message[i:i+chunk_size] for i in range(0, chunks, chunk_size) ] 195 lines = [message[i:i + chunk_size] for i in range(0, chunks, chunk_size)]
193 if color: 196 if color:
194 if isinstance(color, list): 197 if isinstance(color, list):
195 colors = ''.join([get_color(c) for c in color]) 198 colors = ''.join([get_color(c) for c in color])
...@@ -197,7 +200,7 @@ class MudServer(object): ...@@ -197,7 +200,7 @@ class MudServer(object):
197 else: 200 else:
198 self._attempt_send(to, get_color(color) + '\r\n'.join(lines) + line_ending + get_color('reset')) 201 self._attempt_send(to, get_color(color) + '\r\n'.join(lines) + line_ending + get_color('reset'))
199 else: 202 else:
200 self._attempt_send(to, '\r\n'.join(lines) + line_ending) 203 self._attempt_send(to, '\r\n'.join(lines) + line_ending + get_color('reset'))
201 204
202 def shutdown(self): 205 def shutdown(self):
203 """Closes down the server, disconnecting all clients and 206 """Closes down the server, disconnecting all clients and
...@@ -233,7 +236,11 @@ class MudServer(object): ...@@ -233,7 +236,11 @@ class MudServer(object):
233 # If there is a connection problem with the client (e.g. they have 236 # If there is a connection problem with the client (e.g. they have
234 # disconnected) a socket error will be raised 237 # disconnected) a socket error will be raised
235 except Exception as e: 238 except Exception as e:
236 sys.print_exception(e) 239 if 'esp' not in sys.platform:
240 import traceback
241 traceback.print_exc()
242 else:
243 sys.print_exception(e)
237 self._handle_disconnect(clid) 244 self._handle_disconnect(clid)
238 245
239 def _check_for_new_connections(self): 246 def _check_for_new_connections(self):
...@@ -334,7 +341,11 @@ class MudServer(object): ...@@ -334,7 +341,11 @@ class MudServer(object):
334 # if there is a problem reading from the socket (e.g. the client 341 # if there is a problem reading from the socket (e.g. the client
335 # has disconnected) a socket error will be raised 342 # has disconnected) a socket error will be raised
336 except Exception as e: 343 except Exception as e:
337 sys.print_exception(e) 344 if 'esp' not in sys.platform:
345 import traceback
346 traceback.print_exc()
347 else:
348 sys.print_exception(e)
338 self._handle_disconnect(id) 349 self._handle_disconnect(id)
339 350
340 def _handle_disconnect(self, clid): 351 def _handle_disconnect(self, clid):
......
1 {"name": "test", "room": "Room001", "inventory": {"candle": 1}, "prompt": "h %hp m %mp s %st> ", "aliases": {}, "hp": 100, "mp": 10.0, "sta": 10.200000000000031, "aa": "1d2", "mpr": 0.25, "star": 0.4, "maxhp": 953, "maxmp": 10, "maxsta": 10, "weapon": "sword", "sp": {"fireball": {"cost": 5, "dmg": "2d4", "desc": "A fireball blasts from your fingertips striking the target"}}, "at": {"kick": {"cost": 5, "dmg": "2d4", "desc": "You unleash a powerful kick"}}}
...\ No newline at end of file ...\ No newline at end of file
1 {"name": "test", "room": "Room001", "inventory": {"candle": 1}, "prompt": "h %hp m %mp s %st> ", "aliases": {}, "hp": 74, "mp": 5.0, "sta": 1.2000000000000361, "aa": "1d2", "mpr": 0.25, "star": 0.4, "maxhp": 953, "maxmp": 10, "maxsta": 10, "weapon": "sword", "sp": {"fireball": {"cost": 5, "dmg": "2d4", "desc": "A fireball blasts from your fingertips striking the target"}}, "at": {"kick": {"cost": 5, "dmg": "2d4", "desc": "You unleash a powerful kick"}}}
...\ No newline at end of file ...\ No newline at end of file
......
1 {"cricket": {"max": 1, "active": [{"mp": 10, "maxhp": 3, "hp": 3, "sta": 10, "maxmp": 10, "target": "", "action": "attack", "maxsta": 10}]}}
...\ No newline at end of file ...\ No newline at end of file
1 {"cricket": {"max": 1, "active": [{"mp": 10, "maxhp": 15, "hp": 15, "sta": 10, "maxmp": 10, "target": "", "action": "attack", "maxsta": 10}]}}
...\ No newline at end of file ...\ No newline at end of file
......
1 {"cricket": {"max": 2, "active": [{"mp": 10, "maxhp": 3, "hp": 3, "sta": 10, "maxmp": 10, "target": "", "action": "attack", "maxsta": 10}, {"mp": 10, "maxhp": 3, "hp": 3, "sta": 10, "maxmp": 10, "target": "", "action": "attack", "maxsta": 10}]}}
...\ No newline at end of file ...\ No newline at end of file
1 {"cricket": {"max": 2, "active": [{"mp": 10, "maxhp": 20, "hp": 20, "sta": 10, "maxmp": 10, "target": "", "action": "attack", "maxsta": 10}, {"mp": 10, "maxhp": 23, "hp": 23, "sta": 10, "maxmp": 10, "target": "", "action": "attack", "maxsta": 10}]}}
...\ No newline at end of file ...\ No newline at end of file
......
1 import json 1 import json
2 from urandom import getrandbits 2 import sys
3 import re
4
5 if 'esp' in sys.platform:
6 from urandom import getrandbits
7 else:
8 from random import getrandbits
9
10 codes = {'resetall': 0, 'bold': 1, 'underline': 4,
11 'blink': 5, 'reverse': 7, 'boldoff': 22,
12 'blinkoff': 25, 'underlineoff': 24, 'reverseoff': 27,
13 'reset': 0, 'black': 30, 'red': 31, 'green': 32,
14 'yellow': 33, 'blue': 34, 'magenta': 35, 'cyan': 36,
15 'white': 37}
16
17
18 def get_color_list():
19 res = {}
20 for c in codes:
21 res['%' + c] = c
22 return res
3 23
4 24
5 def get_color(name): 25 def get_color(name):
6 CODES = {'resetall': 0, 'bold': 1, 'underline': 4, 26 if name not in codes:
7 'blink': 5, 'reverse': 7, 'boldoff': 22,
8 'blinkoff': 25, 'underlineoff': 24, 'reverseoff': 27,
9 'reset': 0, 'black': 30, 'red': 31, 'green': 32,
10 'yellow': 33, 'blue': 34, 'magenta': 35, 'cyan': 36,
11 'white':37}
12 if name not in CODES:
13 return '' 27 return ''
14 return '\x1b[{}m'.format(CODES.get(name, 0)) 28 return '\x1b[{}m'.format(codes.get(name, 0))
29
30
31 def multiple_replace(text, adict):
32 rx = re.compile('|'.join(map(re.escape, adict)))
33
34 def one_xlat(match):
35 return get_color(adict[match.group(0)])
36 return rx.sub(one_xlat, text)
15 37
16 38
17 def save_object_to_file(obj, filename): 39 def save_object_to_file(obj, filename):
18 with open(filename, 'w', encoding='utf-8') as f: 40 with open(filename, 'w', encoding='utf-8') as f:
19 f.write(json.dumps(obj)) 41 f.write(json.dumps(obj))
42
20 43
21 def load_object_from_file(filename): 44 def load_object_from_file(filename):
22 try: 45 try:
23 with open(filename, 'r', encoding='utf-8') as f: 46 with open(filename, 'r', encoding='utf-8') as f:
24 return json.loads(f.read()) 47 return json.loads(f.read())
25 except Exception as e: 48 except Exception as e:
26 print('Error opening file: ' + filename) 49 print('Error opening file: ' + filename)
27 print(e) 50 print(e)
28 return None 51 return None
29 52
53
30 def randrange(start, stop=None): 54 def randrange(start, stop=None):
31 if start == 1: 55 if start == 1:
32 return 0 56 return 0
...@@ -45,6 +69,7 @@ def randrange(start, stop=None): ...@@ -45,6 +69,7 @@ def randrange(start, stop=None):
45 break 69 break
46 return r + start 70 return r + start
47 71
72
48 def get_att(d): 73 def get_att(d):
49 att = 0 74 att = 0
50 if 'd' in d: 75 if 'd' in d:
...@@ -54,12 +79,16 @@ def get_att(d): ...@@ -54,12 +79,16 @@ def get_att(d):
54 else: 79 else:
55 att = int(d) 80 att = int(d)
56 return att 81 return att
82
83
57 def calc_att(mud, pid, attacks, bank, attack=None): 84 def calc_att(mud, pid, attacks, bank, attack=None):
58 v_att = [] 85 v_att = []
59 att = 0 86 att = 0
60 if attack: 87 if attack:
88 colors = ['bold', 'yellow']
61 v_att.append(attack) 89 v_att.append(attack)
62 else: 90 else:
91 colors = ['bold', 'magenta']
63 for attack in attacks: 92 for attack in attacks:
64 if attack['cost'] < bank: 93 if attack['cost'] < bank:
65 v_att.append(attack) 94 v_att.append(attack)
...@@ -67,10 +96,7 @@ def calc_att(mud, pid, attacks, bank, attack=None): ...@@ -67,10 +96,7 @@ def calc_att(mud, pid, attacks, bank, attack=None):
67 if len(v_att) > 0: 96 if len(v_att) > 0:
68 attack = v_att[randrange(len(v_att))] 97 attack = v_att[randrange(len(v_att))]
69 att = get_att(attack['dmg']) 98 att = get_att(attack['dmg'])
70 if attack: 99 mud.send_message(pid, "%s for %d" % (attack['desc'], att,), color=colors)
71 mud.send_message(pid, "%s for %d" % (attack['desc'], att,), color=['bold', 'yellow'])
72 else:
73 mud.send_message(pid, "%s for %d" % (attack['desc'], att,), color=['bold', 'magenta'])
74 100
75 bank -= attack['cost'] 101 bank -= attack['cost']
76 return att, bank
...\ No newline at end of file ...\ No newline at end of file
102 return att, bank
......