-[location:101]
-pickproof_n = yes
-name = East Sixth Avenue
-closeable_n = yes
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the North.
-terrain = city
-link_e = location:102
-keywords_n = ['booth']
-description_n = This is a simple merchant's booth.
-link_w = location:161
-link_n = location:159
-
-[location:106]
-keywords_e = ['shop']
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a storefront beckons to the East.
+[location:127]
+keywords_e = ['booth']
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a merchant's booth lies to the East.
closeable_e = yes
pickproof_e = yes
terrain = city
-link_e = location:152
-name = North Fifth Street
-description_e = This is the entrance to a shop.
-link_s = location:105
-link_n = location:107
+link_e = location:143
+link_n = location:128
+description_e = This is a simple merchant's booth.
+link_s = location:126
+name = South First Street
-[location:118]
-pickproof_n = yes
-name = East Fourth Avenue
-closeable_n = yes
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a merchant's booth lies to the North.
+[location:120]
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West lies Fourth Avenue while Fifth Street leads North.
terrain = city
-link_e = location:119
-keywords_n = ['booth']
-description_n = This is a simple merchant's booth.
-link_w = location:116
-link_n = location:147
+name = The Corner of Fifth and Fourth
+link_w = location:119
+link_n = location:121
+
+[location:143]
+link_w = location:127
+terrain = inside
+name = New BuildWalk Room
+description = This unfinished room was created by Imp.
+
+[location:132]
+keywords_e = ['booth']
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a merchant's booth lies to the East.
+closeable_e = yes
+pickproof_e = yes
+terrain = city
+link_e = location:141
+link_n = location:133
+description_e = This is a simple merchant's booth.
+link_s = location:131
+name = North First Street
[location:159]
link_s = location:101
pickproof_s = yes
description = Shoes, shoes and more shoes... You need footwear, we have footwear. Look around, see what you like. Best prices in town! So you gonna buy something, stranger?
-[location:104]
-keywords_e = ['gate']
-name = East Market Gate
+[location:122]
+keywords_e = ['shop']
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a storefront beckons to the East.
closeable_e = yes
pickproof_e = yes
terrain = city
-link_e = location:0
-description_e = This gate leads from the market to the city proper.
-link_w = location:103
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West, Sixth Avenue heads into the market while the rest of the city lies trough the gate to the East.
+link_e = location:150
+link_n = location:103
+description_e = This is the entrance to a shop.
+link_s = location:121
+name = South Fifth Street
[location:151]
terrain = inside
description = This unfinished room was created by Imp.
[location:150]
-terrain = inside
link_w = location:122
+terrain = inside
name = New BuildWalk Room
description = This unfinished room was created by Imp.
[location:153]
-link_n = location:108
terrain = inside
-description = This unfinished room was created by Imp.
+link_n = location:108
name = New BuildWalk Room
+description = This unfinished room was created by Imp.
[location:152]
-terrain = inside
link_w = location:106
+terrain = inside
name = New BuildWalk Room
description = This unfinished room was created by Imp.
[location:155]
-terrain = inside
link_w = location:114
+terrain = inside
name = New BuildWalk Room
description = This unfinished room was created by Imp.
description = This unfinished room was created by Imp.
[location:157]
-link_n = location:130
terrain = inside
-description = This booth sells cloth garments of every description. Fine silks and linens line the walls, draped from every protrusion and stacked on every surface.
+link_n = location:130
name = Tailor's Booth
+description = This booth sells cloth garments of every description. Fine silks and linens line the walls, draped from every protrusion and stacked on every surface.
[location:156]
terrain = inside
[location:115]
link_n = location:114
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Seventh Street runs North and South here while a merchant's booth lies to the West.
terrain = city
-name = South Seventh Street
keywords_w = ['booth']
closeable_w = yes
description_w = This is a simple merchant's booth.
link_s = location:116
pickproof_w = yes
link_w = location:156
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Seventh Street runs North and South here while a merchant's booth lies to the West.
+name = South Seventh Street
[location:114]
keywords_e = ['booth']
pickproof_e = yes
terrain = city
link_e = location:155
-name = South Seventh Street
+link_n = location:161
description_e = This is a simple merchant's booth.
link_s = location:115
-link_n = location:161
+name = South Seventh Street
[location:117]
description_s = This gate leads from the market to the city proper.
+link_n = location:116
description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the North, Seventh Street heads into the market while the rest of the city lies trough the gate to the South.
terrain = city
-name = South Market Gate
closeable_s = yes
keywords_s = ['gate']
link_s = location:0
pickproof_s = yes
-link_n = location:116
+name = South Market Gate
[location:116]
link_n = location:115
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Fourth Avenue while Seventh Street runs North and South.
terrain = city
link_e = location:118
-name = South Seventh and Fourth
link_s = location:117
link_w = location:123
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Fourth Avenue while Seventh Street runs North and South.
+name = South Seventh and Fourth
[location:111]
pickproof_n = yes
name = North Market Gate
closeable_n = yes
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the South, Seventh Street heads into the market while the rest of the city lies trough the gate to the North.
terrain = city
+link_n = location:0
keywords_n = ['gate']
link_s = location:110
description_n = This gate leads from the market to the city proper.
-link_n = location:0
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the South, Seventh Street heads into the market while the rest of the city lies trough the gate to the North.
[location:110]
link_n = location:111
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Third Avenue while Seventh Street runs North and South.
terrain = city
link_e = location:109
-name = North Seventh and Third
link_s = location:112
link_w = location:135
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Third Avenue while Seventh Street runs North and South.
+name = North Seventh and Third
[location:113]
link_n = location:112
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Seventh Street runs North and South here while a merchant's booth lies to the West.
terrain = city
-name = North Seventh Street
keywords_w = ['booth']
closeable_w = yes
description_w = This is a simple merchant's booth.
link_s = location:161
pickproof_w = yes
link_w = location:137
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Seventh Street runs North and South here while a merchant's booth lies to the West.
+name = North Seventh Street
[location:112]
keywords_e = ['booth']
pickproof_e = yes
terrain = city
link_e = location:138
-name = North Seventh Street
+link_n = location:110
description_e = This is a simple merchant's booth.
link_s = location:113
-link_n = location:110
+name = North Seventh Street
[location:137]
terrain = inside
[location:136]
description_w = This gate leads from the market to the city proper.
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East, Sixth Avenue heads into the market while the rest of the city lies trough the gate to the West.
terrain = city
link_e = location:128
-name = West Market Gate
keywords_w = ['gate']
closeable_w = yes
pickproof_w = yes
link_w = location:0
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East, Sixth Avenue heads into the market while the rest of the city lies trough the gate to the West.
+name = West Market Gate
[location:135]
description_s = This is a simple merchant's booth.
pickproof_n = yes
name = West Third Avenue
closeable_n = yes
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Third Avenue runs East and West here while a storefront beckons to the North.
terrain = city
link_e = location:135
+link_n = location:140
keywords_n = ['shop']
description_n = This is the entrance to a shop.
link_w = location:133
-link_n = location:140
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Third Avenue runs East and West here while a storefront beckons to the North.
[location:119]
description_s = This is the entrance to a shop.
pickproof_s = yes
description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a storefront beckons to the South.
-[location:132]
-keywords_e = ['booth']
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a merchant's booth lies to the East.
-closeable_e = yes
-pickproof_e = yes
+[location:118]
+pickproof_n = yes
+name = East Fourth Avenue
+closeable_n = yes
terrain = city
-link_e = location:141
-name = North First Street
-description_e = This is a simple merchant's booth.
-link_s = location:131
-link_n = location:133
+link_e = location:119
+link_n = location:147
+keywords_n = ['booth']
+description_n = This is a simple merchant's booth.
+link_w = location:116
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a merchant's booth lies to the North.
[location:131]
link_n = location:132
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a storefront beckons to the West.
terrain = city
-name = North First Street
keywords_w = ['shop']
closeable_w = yes
description_w = This is the entrance to a shop.
link_s = location:128
pickproof_w = yes
link_w = location:142
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a storefront beckons to the West.
+name = North First Street
[location:130]
description_s = This is a simple merchant's booth.
pickproof_s = yes
description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the South.
-[location:105]
-link_n = location:106
+[location:123]
+description_s = This is the entrance to a shop.
+name = West Fourth Avenue
terrain = city
-name = North Fifth Street
-keywords_w = ['booth']
-closeable_w = yes
-description_w = This is a simple merchant's booth.
-link_s = location:103
-pickproof_w = yes
-link_w = location:151
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a merchant's booth lies to the West.
-
-[location:138]
-terrain = inside
-link_w = location:112
-name = New BuildWalk Room
-description = This unfinished room was created by Imp.
+link_e = location:116
+closeable_s = yes
+keywords_s = ['shop']
+link_s = location:146
+link_w = location:124
+pickproof_s = yes
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a storefront beckons to the South.
[location:148]
-link_n = location:119
terrain = inside
-description = This unfinished room was created by Imp.
+link_n = location:119
name = New BuildWalk Room
+description = This unfinished room was created by Imp.
[location:149]
terrain = inside
description = This unfinished room was created by Imp.
[location:146]
-link_n = location:123
terrain = inside
-description = This unfinished room was created by Imp.
+link_n = location:123
name = New BuildWalk Room
+description = This unfinished room was created by Imp.
[location:147]
link_s = location:118
link_e = location:131
description = This unfinished room was created by Imp.
-[location:143]
+[location:138]
+link_w = location:112
terrain = inside
-link_w = location:127
name = New BuildWalk Room
description = This unfinished room was created by Imp.
description = This unfinished room was created by Imp.
[location:141]
-terrain = inside
link_w = location:132
+terrain = inside
name = New BuildWalk Room
description = This unfinished room was created by Imp.
[location:160]
-link_n = location:102
terrain = inside
-description = You find yourself amidst cold, hard steel and iron equipment of every possible description. A slight breeze brings tinkle and clank sounds from all around you.
+link_n = location:102
name = Blacksmith's Booth
+description = You find yourself amidst cold, hard steel and iron equipment of every possible description. A slight breeze brings tinkle and clank sounds from all around you.
[location:161]
link_n = location:113
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while Seventh Street runs North and South. A short flight of stairs leads up to the bandstand.
terrain = city
link_e = location:101
-name = Second Square
link_s = location:114
link_w = location:130
link_u = location:100
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while Seventh Street runs North and South. A short flight of stairs leads up to the bandstand.
+name = Second Square
[location:108]
description_s = This is a simple merchant's booth.
pickproof_n = yes
name = East Third Avenue
closeable_n = yes
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Third Avenue runs East and West here while a storefront beckons to the North.
terrain = city
link_e = location:108
+link_n = location:154
keywords_n = ['shop']
description_n = This is the entrance to a shop.
link_w = location:110
-link_n = location:154
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Third Avenue runs East and West here while a storefront beckons to the North.
[location:128]
link_n = location:131
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while First Street runs North and South.
terrain = city
link_e = location:129
-name = First and West Sixth
link_s = location:127
link_w = location:136
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while First Street runs North and South.
+name = First and West Sixth
[location:139]
-link_n = location:135
terrain = inside
-description = This unfinished room was created by Imp.
+link_n = location:135
name = New BuildWalk Room
+description = This unfinished room was created by Imp.
[location:102]
description_s = This is a simple merchant's booth.
[location:103]
link_n = location:105
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while Fifth Street runs North and South.
terrain = city
link_e = location:104
-name = Fifth and East Sixth
link_s = location:122
link_w = location:102
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while Fifth Street runs North and South.
+name = Fifth and East Sixth
[location:100]
+link_d = location:161
terrain = inside
description = The stand is currently not in use for a performance, but shoppers gather here to rest and chat with one another. A pleasantly cool breeze coupled with a nice view of the market make this a good place to relax and recover energy.
name = The Bandstand
-link_d = location:161
-[location:127]
-keywords_e = ['booth']
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a merchant's booth lies to the East.
-closeable_e = yes
-pickproof_e = yes
+[location:101]
+pickproof_n = yes
+name = East Sixth Avenue
+closeable_n = yes
terrain = city
-link_e = location:143
-name = South First Street
-description_e = This is a simple merchant's booth.
-link_s = location:126
-link_n = location:128
+link_e = location:102
+link_n = location:159
+keywords_n = ['booth']
+description_n = This is a simple merchant's booth.
+link_w = location:161
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the North.
-[location:120]
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West lies Fourth Avenue while Fifth Street leads North.
+[location:106]
+keywords_e = ['shop']
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a storefront beckons to the East.
+closeable_e = yes
+pickproof_e = yes
terrain = city
-name = The Corner of Fifth and Fourth
-link_w = location:119
-link_n = location:121
+link_e = location:152
+link_n = location:107
+description_e = This is the entrance to a shop.
+link_s = location:105
+name = North Fifth Street
[location:121]
link_n = location:122
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a merchant's booth lies to the West.
terrain = city
-name = South Fifth Street
keywords_w = ['booth']
closeable_w = yes
description_w = This is a simple merchant's booth.
link_s = location:120
pickproof_w = yes
link_w = location:149
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a merchant's booth lies to the West.
+name = South Fifth Street
-[location:122]
-keywords_e = ['shop']
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a storefront beckons to the East.
+[location:104]
+keywords_e = ['gate']
+name = East Market Gate
closeable_e = yes
pickproof_e = yes
terrain = city
-link_e = location:150
-name = South Fifth Street
-description_e = This is the entrance to a shop.
-link_s = location:121
-link_n = location:103
+link_e = location:0
+description_e = This gate leads from the market to the city proper.
+link_w = location:103
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West, Sixth Avenue heads into the market while the rest of the city lies trough the gate to the East.
-[location:123]
-description_s = This is the entrance to a shop.
-name = West Fourth Avenue
+[location:105]
+link_n = location:106
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a merchant's booth lies to the West.
terrain = city
-link_e = location:116
-closeable_s = yes
-keywords_s = ['shop']
-link_s = location:146
-link_w = location:124
-pickproof_s = yes
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a storefront beckons to the South.
+keywords_w = ['booth']
+closeable_w = yes
+description_w = This is a simple merchant's booth.
+link_s = location:103
+pickproof_w = yes
+link_w = location:151
+name = North Fifth Street
[location:124]
pickproof_n = yes
name = West Fourth Avenue
closeable_n = yes
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a merchant's booth lies to the North.
terrain = city
link_e = location:123
+link_n = location:145
keywords_n = ['booth']
description_n = This is a simple merchant's booth.
link_w = location:125
-link_n = location:145
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a merchant's booth lies to the North.
[location:133]
name = The Corner of First and Third
pickproof_n = yes
name = West Sixth Avenue
closeable_n = yes
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the North.
terrain = city
link_e = location:130
+link_n = location:158
keywords_n = ['booth']
description_n = This is a simple merchant's booth.
link_w = location:128
-link_n = location:158
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the North.
[location:125]
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East lies Fourth Avenue while First Street leads North.
+link_n = location:126
terrain = city
link_e = location:124
name = The Corner of First and Fourth
-link_n = location:126
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East lies Fourth Avenue while First Street leads North.
[location:107]
name = The Corner of Fifth and Third
[location:126]
link_n = location:127
+description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a storefront beckons to the West.
terrain = city
-name = South First Street
keywords_w = ['shop']
closeable_w = yes
description_w = This is the entrance to a shop.
link_s = location:125
pickproof_w = yes
link_w = location:144
-description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a storefront beckons to the West.
+name = South First Street
from random import choice, randrange
from socket import AF_INET, SO_REUSEADDR, SOCK_STREAM, SOL_SOCKET, socket
from stat import S_IMODE, ST_MODE
-from telnetlib import DO, DONT, ECHO, EOR, IAC, WILL, WONT
+from syslog import LOG_PID, LOG_INFO, LOG_DAEMON, closelog, openlog, syslog
+from telnetlib import DO, DONT, ECHO, EOR, GA, IAC, LINEMODE, SB, SE, SGA, WILL, WONT
from time import asctime, sleep
class Element:
self.connection = None
self.authenticated = False
self.password_tries = 0
- self.state = "entering_account_name"
+ self.state = "initial"
self.menu_seen = False
self.error = ""
self.input_queue = []
self.output_queue = []
self.partial_input = ""
self.echoing = True
+ self.terminator = IAC+GA
+ self.negotiation_pause = 0
self.avatar = None
self.account = None
"""Send the user their current menu."""
if not self.menu_seen:
self.menu_choices = get_menu_choices(self)
- self.send(get_menu(self.state, self.error, self.echoing, self.menu_choices), "")
+ self.send(get_menu(self.state, self.error, self.echoing, self.terminator, self.menu_choices), "")
self.menu_seen = True
self.error = False
self.adjust_echoing()
"""Remove a user from the list of connected users."""
universe.userlist.remove(self)
- def send(self, output, eol="$(eol)"):
+ def send(self, output, eol="$(eol)", raw=False):
"""Send arbitrary text to a connected user."""
- # start with a newline, append the message, then end
- # with the optional eol string passed to this function
- # and the ansi escape to return to normal text
- output = "\r\n" + output + eol + chr(27) + "[0m"
+ # unless raw mode is on, clean it up all nice and pretty
+ if not raw:
- # find and replace macros in the output
- output = replace_macros(self, output)
+ # we'll take out GA or EOR and add them back on the end
+ if output.endswith(IAC+GA) or output.endswith(IAC+EOR):
+ terminate = True
+ output = output[:-2]
+ else: terminate = False
- # wrap the text at 80 characters
- output = wrap_ansi_text(output, 80)
+ # start with a newline, append the message, then end
+ # with the optional eol string passed to this function
+ # and the ansi escape to return to normal text
+ output = "\r\n" + output + eol + chr(27) + "[0m"
- # drop the formatted output into the output queue
- self.output_queue.append(output)
+ # find and replace macros in the output
+ output = replace_macros(self, output)
- # try to send the last item in the queue and remove it
- try:
- self.connection.send(self.output_queue[0])
- del self.output_queue[0]
+ # wrap the text at 80 characters
+ output = wrap_ansi_text(output, 80)
- # but if we can't, that's okay too
- except:
- pass
+ # tack the terminator back on
+ if terminate: output += self.terminator
+
+ # drop the output into the user's output queue
+ self.output_queue.append(output)
def pulse(self):
"""All the things to do to the user per increment."""
self.state = "disconnecting"
self.menu_seen = False
+ # if output is paused, decrement the counter
+ if self.state == "initial":
+ if self.negotiation_pause: self.negotiation_pause -= 1
+ else: self.state = "entering_account_name"
+
# show the user a menu as needed
- self.show_menu()
+ else: self.show_menu()
# disconnect users with the appropriate state
if self.state == "disconnecting": self.quit()
# the user is unique and not flagged to disconnect
else:
+ # try to send the last item in the queue and remove it
+ if self.output_queue:
+ try:
+ self.connection.send(self.output_queue[0])
+ del self.output_queue[0]
+
+ # but if we can't, that's okay too
+ except:
+ pass
+
# check for input and add it to the queue
self.enqueue_input()
# if there wasn't an IAC in the input, skip to the end
if position < 0: position = len(text)
- # replace a double (literal) IAC and move on
+ # replace a double (literal) IAC if there's an LF later
elif len(text) > position+1 and text[position+1] == IAC:
- text = text.replace(IAC+IAC, IAC)
+ if text.find("\n", position) > 0: text = text.replace(IAC+IAC, IAC)
+ else: position += 1
position += 1
# this must be an option negotiation
elif len(text) > position+2 and text[position+1] in (DO, DONT, WILL, WONT):
+ negotiation = text[position+1:position+3]
+
# if we turned echo off, ignore the confirmation
- if not self.echoing and text[position+1:position+3] == DO+ECHO: pass
+ if not self.echoing and negotiation == DO+ECHO: pass
+
+ # allow LINEMODE
+ elif negotiation == WILL+LINEMODE: self.send(IAC+DO+LINEMODE, raw=True)
+
+ # if the client likes EOR instead of GA, make a note of it
+ elif negotiation == DO+EOR: self.terminator = IAC+EOR
+ elif negotiation == DONT+EOR and self.terminator == IAC+EOR:
+ self.terminator = IAC+GA
+
+ # if the client doesn't want GA, oblige
+ elif negotiation == DO+SGA and self.terminator == IAC+GA:
+ self.terminator = ""
+ self.send(IAC+WILL+SGA, raw=True)
# we don't want to allow anything else
- elif text[position+1] in (DO, WILL): self.send(IAC+WONT+text[position+2])
+ elif text[position+1] == DO: self.send(IAC+WONT+text[position+2], raw=True)
+ elif text[position+1] == WILL: self.send(IAC+DONT+text[position+2], raw=True)
# strip the negotiation from the input
text = text.replace(text[position:position+3], "")
+ # get rid of IAC SB .* IAC SE
+ elif len(text) > position+4 and text[position:position+2] == IAC+SB:
+ end_subnegotiation = text.find(IAC+SE, position)
+ if end_subnegotiation > 0: text = text[:position] + text[end_subnegotiation+2:]
+ else: position += 1
+
# otherwise, strip out a two-byte IAC command
- else: text = text.replace(text[position:position+2], "")
+ elif len(text) > position+2: text = text.replace(text[position:position+2], "")
+
+ # and this means we got the begining of an IAC
+ else: position += 1
# replace the input with our cleaned-up text
self.partial_input = text
# send the timestamp and message to standard output
print(timestamp + " " + message)
+ # send the message to the system log
+ openlog("mudpy", LOG_PID, LOG_INFO | LOG_DAEMON)
+ syslog(message)
+ closelog()
+
def wrap_ansi_text(text, width):
"""Wrap text with arbitrary width while ignoring ANSI colors."""
# set the user's ipa from the connection's ipa
user.address = address[0]
+ # let the client know we WILL EOR
+ user.send(IAC+WILL+EOR, raw=True)
+ user.negotiation_pause = 2
+
# return the new user object
return user
-def get_menu(state, error=None, echoing=True, choices={}):
+def get_menu(state, error=None, echoing=True, terminator="", choices=None):
"""Show the correct menu text to a user."""
+ # make sure we don't reuse a mutable sequence by default
+ if choices is None: choices = {}
+
# begin with a telnet echo command sequence if needed
message = get_echo_sequence(state, echoing)
# display a message indicating if echo is off
message += get_echo_message(state)
- # tack on IAC EOR to indicate the prompt will not be followed by CRLF
- message += IAC+EOR
+ # tack on EOR or GA to indicate the prompt will not be followed by CRLF
+ message += terminator
# return the assembly of various strings defined above
return message