51c565a0 by Barry Ruffner

Added better colors and bug fixes

1 parent 9b22a762
...@@ -16,6 +16,7 @@ global_aliases = { ...@@ -16,6 +16,7 @@ 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):
...@@ -53,7 +54,7 @@ class CommandHandler(object): ...@@ -53,7 +54,7 @@ class CommandHandler(object):
53 command_text = f.read() 54 command_text = f.read()
54 exec(command_text, globals(), ldict) 55 exec(command_text, globals(), ldict)
55 del command_text 56 del command_text
56 if ldict['next_command'] != None: 57 if ldict['next_command'] is not None:
57 locals()['tokens'] = [] 58 locals()['tokens'] = []
58 tokens = [] 59 tokens = []
59 with open('commands/{}.txt'.format(ldict['next_command']), 'r', encoding='utf-8') as f: 60 with open('commands/{}.txt'.format(ldict['next_command']), 'r', encoding='utf-8') as f:
...@@ -62,8 +63,11 @@ class CommandHandler(object): ...@@ -62,8 +63,11 @@ class CommandHandler(object):
62 return True 63 return True
63 except Exception as e: 64 except Exception as e:
64 print('Something happened...') 65 print('Something happened...')
66 import sys
67 if 'esp' not in sys.platform:
68 import traceback
69 traceback.print_exc()
70 else:
65 print(e) 71 print(e)
66 mud.send_message(id, "Unknown command '{}'".format(cmd)) 72 mud.send_message(id, "Unknown command '{}'".format(cmd))
67 return False 73 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
...@@ -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,6 +236,10 @@ class MudServer(object): ...@@ -233,6 +236,10 @@ 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:
239 if 'esp' not in sys.platform:
240 import traceback
241 traceback.print_exc()
242 else:
236 sys.print_exception(e) 243 sys.print_exception(e)
237 self._handle_disconnect(clid) 244 self._handle_disconnect(clid)
238 245
...@@ -334,6 +341,10 @@ class MudServer(object): ...@@ -334,6 +341,10 @@ 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:
344 if 'esp' not in sys.platform:
345 import traceback
346 traceback.print_exc()
347 else:
337 sys.print_exception(e) 348 sys.print_exception(e)
338 self._handle_disconnect(id) 349 self._handle_disconnect(id)
339 350
......
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
3 4
5 if 'esp' in sys.platform:
6 from urandom import getrandbits
7 else:
8 from random import getrandbits
4 9
5 def get_color(name): 10 codes = {'resetall': 0, 'bold': 1, 'underline': 4,
6 CODES = {'resetall': 0, 'bold': 1, 'underline': 4,
7 'blink': 5, 'reverse': 7, 'boldoff': 22, 11 'blink': 5, 'reverse': 7, 'boldoff': 22,
8 'blinkoff': 25, 'underlineoff': 24, 'reverseoff': 27, 12 'blinkoff': 25, 'underlineoff': 24, 'reverseoff': 27,
9 'reset': 0, 'black': 30, 'red': 31, 'green': 32, 13 'reset': 0, 'black': 30, 'red': 31, 'green': 32,
10 'yellow': 33, 'blue': 34, 'magenta': 35, 'cyan': 36, 14 'yellow': 33, 'blue': 34, 'magenta': 35, 'cyan': 36,
11 'white':37} 15 'white': 37}
12 if name not in CODES: 16
17
18 def get_color_list():
19 res = {}
20 for c in codes:
21 res['%' + c] = c
22 return res
23
24
25 def get_color(name):
26 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))
20 42
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:
...@@ -27,6 +50,7 @@ def load_object_from_file(filename): ...@@ -27,6 +50,7 @@ def load_object_from_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 102 return att, bank
......