d0765ef5a788708790a0bc780ce11e8b93c9b96f
[mudpy.git] / lib / muff / muffmisc.py
1 """Miscellaneous objects for the MUFF Engine"""
2
3 # Copyright (c) 2005 mudpy, Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
4 # Licensed per terms in the LICENSE file distributed with this software.
5
6 # used by several functions for random calls
7 import random
8
9 # random_name uses string.strip
10 import string
11
12 # the log function uses time.asctime for creating timestamps
13 import time
14
15 # hack to load all modules in the muff package
16 import muff
17 for module in muff.__all__:
18         exec("import " + module)
19
20 def broadcast(message):
21         """Send a message to all connected users."""
22         for each_user in muffvars.userlist: each_user.send(message)
23
24 def log(message):
25         """Log a message."""
26
27         # the time in posix log timestamp format
28         timestamp = time.asctime()[4:19]
29
30         # send the timestamp and message to standard output
31         print(timestamp + " " + message)
32
33 def wrap_ansi_text(text, width):
34         """Wrap text with arbitrary width while ignoring ANSI colors."""
35
36         # the current position in the entire text string, including all
37         # characters, printable or otherwise
38         absolute_position = 0
39
40         # the current text position relative to the begining of the line,
41         # ignoring color escape sequences
42         relative_position = 0
43
44         # whether the current character is part of a color escape sequence
45         escape = False
46
47         # iterate over each character from the begining of the text
48         for each_character in text:
49
50                 # the current character is the escape character
51                 if each_character == chr(27):
52                         escape = True
53
54                 # the current character is within an escape sequence
55                 elif escape:
56
57                         # the current character is m, which terminates the
58                         # current escape sequence
59                         if each_character == "m":
60                                 escape = False
61
62                 # the current character is a newline, so reset the relative
63                 # position (start a new line)
64                 elif each_character == "\n":
65                         relative_position = 0
66
67                 # the current character meets the requested maximum line width,
68                 # so we need to backtrack and find a space at which to wrap
69                 elif relative_position == width:
70
71                         # distance of the current character examined from the
72                         # relative position
73                         wrap_offset = 0
74
75                         # count backwards until we find a space
76                         while text[absolute_position - wrap_offset] != " ":
77                                 wrap_offset += 1
78
79                         # insert an eol in place of the space
80                         text = text[:absolute_position - wrap_offset] + "\r\n" + text[absolute_position - wrap_offset + 1:]
81
82                         # increase the absolute position because an eol is two
83                         # characters but the space it replaced was only one
84                         absolute_position += 1
85
86                         # now we're at the begining of a new line, plus the
87                         # number of characters wrapped from the previous line
88                         relative_position = wrap_offset
89
90                 # as long as the character is not a carriage return and the
91                 # other above conditions haven't been met, count it as a
92                 # printable character
93                 elif each_character != "\r":
94                         relative_position += 1
95
96                 # increase the absolute position for every character
97                 absolute_position += 1
98
99         # return the newly-wrapped text
100         return text
101
102 def weighted_choice(data):
103         """Takes a dict weighted by value and returns a random key."""
104
105         # this will hold our expanded list of keys from the data
106         expanded = []
107
108         # create thee expanded list of keys
109         for key in data.keys():
110                 for count in range(data[key]):
111                         expanded.append(key)
112
113         # return one at random
114         return random.choice(expanded)
115
116 def random_name():
117         """Returns a random character name."""
118
119         # the vowels and consonants needed to create romaji syllables
120         vowels = [ "a", "i", "u", "e", "o" ]
121         consonants = ["'", "k", "z", "s", "sh", "z", "j", "t", "ch", "ts", "d", "n", "h", "f", "m", "y", "r", "w" ]
122
123         # this dict will hold our weighted list of syllables
124         syllables = {}
125
126         # generate the list with an even weighting
127         for consonant in consonants:
128                 for vowel in vowels:
129                         syllables[consonant + vowel] = 1
130
131         # we'll build the name into this string
132         name = ""
133
134         # create a name of random length from the syllables
135         for syllable in range(random.randrange(2, 6)):
136                 name += weighted_choice(syllables)
137
138         # strip any leading quotemark, capitalize and return the name
139         return string.strip(name, "'").capitalize()
140