def view_ansi(key): """ fetch and view a bbs ansi. They're not often very good ... """ from x84.bbs import getterminal, echo, DBProxy, ini, getch, from_cp437 term = getterminal() ansiurl = DBProxy('bbslist')[key]['ansi'] logger = logging.getLogger() echo(u'\r\n\r\n') if ansiurl is not None and 0 != len(ansiurl) and ansiurl != 'NONE': usernm = ini.CFG.get('bbs-scene', 'user') passwd = ini.CFG.get('bbs-scene', 'pass') req = requests.get(ansiurl, auth=(usernm, passwd)) if req.status_code != 200: echo(u'\r\n\r\nrequest failed,\r\n') echo(u'%r' % (req.content, )) echo(u'\r\n\r\n(code : %s).\r\n' % (req.status_code, )) echo(u'\r\nPress any key ..') logger.warn('ansiurl request failed: %s' % (ansiurl, )) getch() return ansi_txt = from_cp437(sauce.SAUCE(data=req.content).__str__()) echo(ansi_txt) else: echo('no ansi available (%s)' % (ansiurl, )) # move to bottom of screen and getch echo(u''.join((term.move(term.height, 0), term.normal, u'\r\n\r\nPRESS ANY kEY ...'), )) getch()
def view_ansi(key): """ fetch and view a bbs ansi. They're not often very good ... """ from x84.bbs import getterminal, echo, DBProxy, ini, getch, from_cp437 term = getterminal() ansiurl = DBProxy('bbslist')[key]['ansi'] logger = logging.getLogger() echo(u'\r\n\r\n') if ansiurl is not None and 0 != len(ansiurl) and ansiurl != 'NONE': usernm = ini.CFG.get('bbs-scene', 'user') passwd = ini.CFG.get('bbs-scene', 'pass') req = requests.get(ansiurl, auth=(usernm, passwd)) if req.status_code != 200: echo(u'\r\n\r\nrequest failed,\r\n') echo(u'%r' % (req.content,)) echo(u'\r\n\r\n(code : %s).\r\n' % (req.status_code,)) echo(u'\r\nPress any key ..') logger.warn('ansiurl request failed: %s' % (ansiurl,)) getch() return ansi_txt = from_cp437(sauce.SAUCE(data=req.content).__str__()) echo(ansi_txt) else: echo('no ansi available (%s)' % (ansiurl,)) # move to bottom of screen and getch echo(u''.join(( term.move(term.height, 0), term.normal, u'\r\n\r\nPRESS ANY kEY ...'),)) getch()
def banner(): """ Return banner """ from x84.bbs import getterminal, Ansi, from_cp437 import os term = getterminal() output = u'' output += u'\r\n\r\n' if term.width >= 78: output += term.home + term.normal + term.clear # xzip's ansi is line-clean, center-align with terminal width, artfile = os.path.join(os.path.dirname(__file__), 'ol.ans') art = open(artfile).readlines() max_ans = max([len(Ansi(from_cp437(line.rstrip()))) for line in art]) for line in art: padded = Ansi(from_cp437(line.rstrip())).center(max_ans) output += term.normal + term.blue # minor fix for this art ;/ output += Ansi(padded).center(term.width).rstrip() + '\r\n' return output + term.normal
def get_icon(weather): from x84.bbs import from_cp437 # attribute 'WeatherIcon' is mapped to one of the {}.ans files icon = int(weather['WeatherIcon']) artfile = os.path.join(weather_icons, '{}.ans'.format(icon)) if not os.path.exists(artfile): warnings.warn('{} not found'.format(artfile)) art = u'[ .{:>2}. ]'.format(icon) else: art = [from_cp437(line.rstrip()) for line in open(artfile, 'r').readlines()] return art
def banner(): """ Return banner """ from x84.bbs import getterminal, from_cp437 import os term = getterminal() output = u'' output += u'\r\n\r\n' + term.normal if term.width >= 78: output += term.home + term.normal + term.clear # xzip's ansi is line-clean, center-align with terminal width, artfile = os.path.join(os.path.dirname(__file__), 'ol.ans') art = [line.rstrip() for line in from_cp437(open(artfile).read()).splitlines()] max_ans = max([term.length(line) for line in art]) for line in art: output += term.center(term.ljust(line.rstrip(), max_ans)).rstrip() + '\r\n' return output + term.normal
def display_panel(weather, column, centigrade): from x84.bbs import getterminal, echo, from_cp437 term = getterminal() # display day of week, day_txt = term.bold(weather.get('DayCode', u'').center(panel_width)) echo(term.move(top_margin, column)) echo(day_txt) # display WeatherIcon ansi art, for row_idx, art_row in enumerate(get_icon(weather)): echo(term.move(row_idx + top_margin + 1, column)) echo(art_row) echo(term.normal) degree = from_cp437(''.join([chr(248)])) # display days' high, echo(term.move(panel_height + top_margin + 1, column)) high = weather.get('High_Temperature', None) high, conv = temp_conv(high, centigrade) echo(u'High: {high:>2}{degree}{conv}'.format(high=high, degree=degree, conv=conv).rjust(panel_width - 3)) # display days' low, echo(term.move(panel_height + top_margin + 2, column)) low = weather.get('Low_Temperature', None) low, conv = temp_conv(low, centigrade) echo(u'Low: {low:>2}{degree}{conv}'.format(low=low, degree=degree, conv=conv).rjust(panel_width - 3)) # display short txt, weather_txt = unicode(weather.get('TXT_Short', '')) txt_wrapped = textwrap.wrap(weather_txt, (panel_width - 2)) for row_idx, txt_row in enumerate(txt_wrapped): row_loc = panel_height + top_margin + row_idx + 4 echo(term.move(row_loc, column + 1)) echo(txt_row.center(panel_width - 2)) return row_loc
def display_panel(weather, column, centigrade): from x84.bbs import getterminal, echo, from_cp437 term = getterminal() # display day of week, day_txt = term.bold(weather.get('DayCode', u'').center(panel_width)) echo(term.move(top_margin, column)) echo(day_txt) # display WeatherIcon ansi art, for row_idx, art_row in enumerate(get_icon(weather)): echo(term.move(row_idx + top_margin + 2, column)) echo(art_row) echo(term.normal) degree = from_cp437(''.join([chr(248)])) # display days' high, echo(term.move(panel_height + top_margin + 2, column)) high = weather.get('High_Temperature', None) high, conv = temp_conv(high, centigrade) echo(u'High: {high:>2}{degree}{conv}'.format( high=high, degree=degree, conv=conv).rjust(panel_width - 3)) # display days' low, echo(term.move(panel_height + top_margin + 3, column)) low = weather.get('Low_Temperature', None) low, conv = temp_conv(low, centigrade) echo(u'Low: {low:>2}{degree}{conv}'.format( low=low, degree=degree, conv=conv).rjust(panel_width - 3)) # display short txt, weather_txt = unicode(weather.get('TXT_Short', '')) txt_wrapped = textwrap.wrap(weather_txt, (panel_width - 2)) row_loc = panel_height + top_margin + 5 for row_idx, txt_row in enumerate(txt_wrapped): row_loc = panel_height + top_margin + row_idx + 5 echo(term.move(row_loc, column + 1)) echo(txt_row.center(panel_width - 2)) return row_loc
def redraw(pager): """ Returns string suitable for refreshing screen. """ from x84.bbs import getsession, getterminal, from_cp437 import os # pylint: disable=W0603 # Using the global statement session, term = getsession(), getterminal() output = '' output += term.home + term.normal + term.clear artfile = os.path.join(os.path.dirname(__file__), 'art', 'news.ans') art = [line.rstrip() for line in from_cp437(open(artfile).read()).splitlines()] max_ans = max([term.length(line) for line in art]) for line in art: output += term.center(term.ljust(line.rstrip(), max_ans)).rstrip() + '\r\n' title = u''.join((u']- ', term.bold_blue('PARtY NEWS'), ' [-',)) footer = u''.join((u'-[ ', term.blue_underline(u'Escape'), '/', term.blue_underline(u'q'), term.bold_blue(u'uit '), ((u'- ' + term.blue_underline(u'e') + term.bold_blue(u'dit ')) if ( 'sysop' in session.user.groups) else u''), u']-', )) return u''.join((u'', (output), u'', u''.join(( u'' * pager.height, pager.refresh(), pager.border(), pager.title(title), pager.footer(footer)) ) if pager is not None else u'',))
def display_weather(todays, weather, centigrade): """ Display weather as vertical panels. Thanks to xzip, we now have a sortof tv-weather channel art :-) """ from x84.bbs import getterminal, echo, from_cp437 term = getterminal() echo(term.height * u'\r\n') echo(term.move(1, 1)) at = term.yellow_bold('At') city = term.bold(todays.get('City', u'')) state = todays.get('State', u'') if state: state = u', {}'.format(term.bold_yellow_reverse(state)) dotdot = term.bold_black('...') echo(u'{at} {city}{state} {dotdot}'.format( at=at, city=city, state=state, dotdot=dotdot)) bottom = 2 for column in range(0, (term.width - panel_width), panel_width): try: day = weather.pop(0) except IndexError: break bottom = max(display_panel(day, column, centigrade), bottom) timenow = time.strftime('%I:%M%p', time.strptime(todays['Time'], '%H:%M')) temp, deg_conv = temp_conv(todays.get('Temperature', ''), centigrade) real_temp, deg_conv = temp_conv(todays.get('RealFeel', ''), centigrade) speed, spd_conv = speed_conv(todays.get('WindSpeed', ''), centigrade) degree = from_cp437(''.join([chr(248)])) current_0 = u'Current conditions at {timenow}'.format(timenow=timenow) current_1 = u'{w[WeatherText]}'.format(w=todays) current_2 = u'Temperature is {temp}{degree}{deg_conv}'.format( temp=temp, degree=degree, deg_conv=deg_conv) current_3 = u'' if real_temp == temp else ( u'(feels like {real_temp}{degree}{deg_conv})'.format( real_temp=real_temp, degree=degree, deg_conv=deg_conv)) current_4 = u'Winds {speed}{spd_conv} {w[WindDirection]}'.format( speed=speed, w=todays, spd_conv=spd_conv) current_5 = u'Humidity of {w[Humidity]}'.format(w=todays) wrapped = textwrap.wrap( u'{0}: {1}. {2} {3}, {4}, {5}.'.format( current_0, current_1, current_2, current_3, current_4, current_5), min(term.width - panel_width - 5, 40)) row_num = 0 art = get_icon(todays) for row_num, (row_txt, art_txt) in enumerate( itertools.izip_longest(wrapped, art)): echo(term.move(bottom + next_margin + row_num, 1)) echo(art_txt) if row_txt: echo(term.move(bottom + next_margin + row_num, panel_width + 5)) echo(term.normal) echo(row_txt + u'\r\n') else: echo(u'\r\n')
def main(): """ Main procedure. """ # pylint: disable=R0914,W0141,R0912 # Too many local variables # Used builtin function 'map' # Too many branches from x84.bbs import getsession, getterminal, Ansi, echo, getch, from_cp437 from x84.engine import __url__ as url import platform import random import sys import os session, term = getsession(), getterminal() session.activity = 'System Info' artfile = os.path.join( os.path.dirname(__file__), 'art', 'plant.ans', ) system, _node, release, _version, machine, _processor = platform.uname() body = [ u'AUthORS:', u'Johannes Lundberg', u'Jeffrey Quast', u'Wijnand Modderman-Lenstra', u'', u'ARtWORk:', u'spidy!food,', u'hellbeard!impure', u'\r\n', u'SYStEM: %s %s %s' % (system, release, machine), u'SOftWARE: X/84', url, u'\r\n', (platform.python_implementation() + u' ' + '-'.join(map(str, sys.version_info[3:]))) + u' ' + (platform.python_version() if hasattr(platform, 'python_implementation') else u'.'.join( map(str, sys.version_info[:3]))), ] melt_colors = ([term.normal] + [term.bold_blue] * 3 + [term.red] * 4 + [term.bold_red] + [term.bold_white] + [term.normal] * 6 + [term.blue] * 2 + [term.bold_blue] + [term.bold_white] + [term.normal]) art = from_cp437(open(artfile).read()) if os.path.exists(artfile) else u'' otxt = list(art.splitlines()) for num, line in enumerate(body): while num > len(otxt): otxt += [ u'', ] otxt[num] = otxt[num][:int(term.width / 2.5)] + u' ' + line width = max([len(Ansi(line)) for line in otxt]) height = len(otxt) num_stars = int((term.width * term.height) * .002) stars = dict([(n, (random.choice('\\|/-'), float(random.choice(range(term.width))), float(random.choice(range(term.height))))) for n in range(num_stars)]) melting = {} show_star = False tm_out, tm_min, tm_max, tm_step = 0.08, 0.01, 2.0, .01 wind = (0.7, 0.1, 0.01, 0.01) def refresh(): """ Refresh screen and return top-left (x, y) location. """ echo(u'\r\n\r\n') if term.width < width: echo(u''.join(( term.move(term.height, 0), u'\r\n\r\n', term.bold_red + 'screen too thin! (%s/%s)' % ( term.width, width, ), u'\r\n\r\n', u'press any key...', ))) getch() return (None, None) if term.height < height: echo(u''.join(( term.move(term.height, 0), u'\r\n\r\n', term.bold_red + 'screen too short! (%s/%s)' % (term.height, height), u'\r\n\r\n', u'press any key...', ))) getch() return (None, None) xloc = (term.width / 2) - (width / 2) yloc = (term.height / 2) - (height / 2) echo(u''.join(( term.normal, (u'\r\n' + term.clear_eol) * term.height, u''.join([ term.move(yloc + abs_y, xloc) + line for abs_y, line in enumerate(otxt) ]), ))) return xloc, yloc txt_x, txt_y = refresh() if (txt_x, txt_y) == (None, None): return def char_at_pos(yloc, xloc, txt_y, txt_x): """ Return art (y, x) for location """ return (u' ' if yloc - txt_y < 0 or yloc - txt_y >= height or xloc - txt_x < 0 or xloc - txt_x >= len(otxt[yloc - txt_y]) else otxt[yloc - txt_y][xloc - txt_x]) def iter_wind(xslope, yslope, xdir, ydir): """ An easterly Wind """ xslope += xdir yslope += ydir if xslope <= 0.5: xdir = random.choice([0.01, 0.015, 0.02]) elif xslope >= 1: xdir = random.choice([-0.01, -0.015, -0.02]) if yslope <= -0.1: ydir = random.choice([0.01, 0.015, 0.02, 0.02]) elif yslope >= 0.1: ydir = random.choice([-0.01, -0.015, -0.02]) return xslope, yslope, xdir, ydir def iter_star(char, xloc, yloc): """ Given char and current position, apply wind and return new char and new position. """ if char == '\\': char = '|' elif char == '|': char = '/' elif char == '/': char = '-' elif char == '-': char = '\\' xloc += wind[0] yloc += wind[1] if xloc < 1 or xloc > term.width: xloc = (1.0 if xloc > term.width else float(term.width)) yloc = (float(random.choice(range(term.height)))) if yloc < 1 or yloc > term.height: yloc = (1.0 if yloc > term.height else float(term.height)) xloc = (float(random.choice(range(term.width)))) return char, xloc, yloc def erase(star_idx): """ erase old star before moving .. """ if show_star: _char, xloc, yloc = stars[star_idx] echo(''.join(( term.move(int(yloc), int(xloc)), term.normal, char_at_pos(int(yloc), int(xloc), txt_y, txt_x), ))) def melt(): """ Iterate through all stars and phase through melt sequence. """ def melted(yloc, xloc): """ shift melt, delete if dissapeared. """ melting[(yloc, xloc)] -= 1 if 0 == melting[(yloc, xloc)]: del melting[(yloc, xloc)] for (yloc, xloc), phase in melting.items(): echo(''.join(( term.move(yloc, xloc), melt_colors[phase - 1], char_at_pos(yloc, xloc, txt_y, txt_x), ))) melted(yloc, xloc) def draw_star(star, xloc, yloc): """ draw star a (x, y) location """ char = char_at_pos(int(yloc), int(xloc), txt_y, txt_x) if char != ' ': melting[(int(yloc), int(xloc))] = len(melt_colors) if show_star: echo(term.move(int(yloc), int(xloc)) + melt_colors[-1] + star) with term.hidden_cursor(): while txt_x is not None and txt_y is not None: if session.poll_event('refresh'): num_stars = int(num_stars) stars = dict([(n, (random.choice('\\|/-'), float(random.choice(range(term.width))), float(random.choice(range(term.height))))) for n in range(num_stars)]) otxt = list(art.splitlines()) for num, line in enumerate(body): while num > len(otxt): otxt += [ u'', ] otxt[num] = (otxt[num][:int(term.width / 2.5)] + u' ' + line) txt_x, txt_y = refresh() continue inp = getch(tm_out) if inp in (term.KEY_UP, 'k'): if tm_out >= tm_min: tm_out -= tm_step elif inp in (term.KEY_DOWN, 'j'): if tm_out <= tm_max: tm_out += tm_step elif inp in (term.KEY_LEFT, 'h'): if num_stars > 2: num_stars = int(num_stars * .5) stars = dict([(n, (random.choice('\\|/-'), float(random.choice(range(term.width))), float(random.choice(range(term.height))))) for n in range(num_stars)]) elif inp in (term.KEY_RIGHT, 'l'): if num_stars < (term.width * term.height) / 4: num_stars = int(num_stars * 1.5) stars = dict([(n, (random.choice('\\|/-'), float(random.choice(range(term.width))), float(random.choice(range(term.height))))) for n in range(num_stars)]) elif inp in (u'*', ) and not show_star: show_star = True elif inp in (u'*', ) and show_star: for star in stars: erase(star) show_star = False elif inp is not None: echo(term.move(term.height, 0)) break melt() for star_key, star_val in stars.items(): erase(star_key) # pylint: disable=W0142 # Used * or ** magic stars[star_key] = iter_star(*star_val) draw_star(*stars[star_key]) # pylint: disable=W0142 # Used * or ** magic wind = iter_wind(*wind)
def main(host, port=None, encoding='cp437'): """ Call script with argument host and optional argument port to connect to a telnet server. ctrl-^ to disconnect. """ # pylint: disable=R0914,R0912,R0915 # Too many local variables # Too many branches # Too many statements import telnetlib import struct from x84.bbs import getsession, getterminal, echo, getch, from_cp437 import logging log = logging.getLogger() assert encoding in ('utf8', 'cp437') session, term = getsession(), getterminal() session.activity = 'connecting to %s' % (host, ) port = int(port) if port is not None else 23 telnet_client = telnetlib.Telnet() def callback_cmdopt(socket, cmd, opt): """ Callback for telnetlib.Telnet.set_option_negotiation_callback. """ if cmd == telnetlib.WILL: if opt in (telnetlib.ECHO, telnetlib.SGA): socket.sendall(telnetlib.IAC + telnetlib.DO + opt) elif cmd == telnetlib.DO: if opt == telnetlib.SGA: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) elif opt == telnetlib.TTYPE: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.TTYPE + IS + session.env.get('TERM') + chr(0) + telnetlib.IAC + telnetlib.SE) elif opt == telnetlib.NAWS: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.NAWS + struct.pack('!HH', term.width, term.height) + telnetlib.IAC + telnetlib.SE) else: socket.sendall(telnetlib.IAC + telnetlib.WONT + opt[0]) elif cmd == telnetlib.SB: if opt[0] == telnetlib.TTYPE and opt[1] == SEND: socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.TTYPE + IS + session.env.get('TERM') + chr(0) + telnetlib.IAC + telnetlib.SE) telnet_client.set_option_negotiation_callback(callback_cmdopt) echo(u"\r\n\r\nEscape character is 'ctrl-^.'") if not session.user.get('expert', False): getch(3) echo(u'\r\nTrying %s:%s... ' % ( host, port, )) # pylint: disable=W0703 # Catching too general exception Exception try: telnet_client.open(host, port) except Exception as err: echo(term.bold_red('\r\n%s\r\n' % (err, ))) echo(u'\r\n press any key ..') getch() return echo(u'\r\n... ') inp = session.read_event('input', timeout=0) echo(u'\r\nConnected to %s.' % (host, )) session.activity = 'connected to %s' % (host, ) carriage_returned = False with term.fullscreen(): while True: if encoding == 'cp437': try: unistring = from_cp437( telnet_client.read_very_eager().decode('iso8859-1')) except EOFError: break else: unistring = telnet_client.read_very_eager().decode('utf8') if 0 != len(unistring): echo(unistring) if inp is not None: if inp == chr(30): # ctrl-^ telnet_client.close() echo(u'\r\n' + term.clear_el + term.normal) break elif not carriage_returned and inp in (b'\x0d', b'\x0a'): telnet_client.write(b'\x0d') log.debug('send {!r}'.format(b'\x0d')) carriage_returned = True elif carriage_returned and inp in (b'\x0a', b'\x00'): carriage_returned = False elif inp is not None: telnet_client.write(inp) log.debug('send {!r}'.format(inp)) carriage_returned = False inp = session.read_event('input', timeout=KEY_POLL) echo(u'\r\nConnection closed.\r\n') echo(u''.join(('\r\n\r\n', term.clear_el, term.normal, 'press any key'))) echo(u'\x1b[r') # unset 'set scrolling region', sometimes set by BBS's session.flush_event('input') getch() return
def main(host, port=None, encoding="cp437"): """ Call script with argument host and optional argument port to connect to a telnet server. ctrl-^ to disconnect. """ # pylint: disable=R0914,R0912,R0915 # Too many local variables # Too many branches # Too many statements import telnetlib from functools import partial from x84.bbs import getsession, getterminal, echo, getch, from_cp437, telnet import logging log = logging.getLogger() assert encoding in ("utf8", "cp437") session, term = getsession(), getterminal() session.activity = "connecting to %s" % (host,) port = int(port) if port is not None else 23 telnet_client = telnetlib.Telnet() telnet_client.set_option_negotiation_callback( partial(telnet.callback_cmdopt, env_term=session.env["TERM"], height=term.height, width=term.width) ) echo(u"\r\n\r\nEscape character is 'ctrl-^.'") if not session.user.get("expert", False): getch(3) echo(u"\r\nTrying %s:%s... " % (host, port)) # pylint: disable=W0703 # Catching too general exception Exception try: telnet_client.open(host, port) except Exception as err: echo(term.bold_red("\r\n%s\r\n" % (err,))) echo(u"\r\n press any key ..") getch() return echo(u"\r\n... ") inp = session.read_event("input", timeout=0) echo(u"\r\nConnected to %s." % (host,)) session.activity = "connected to %s" % (host,) carriage_returned = False with term.fullscreen(): while True: if encoding == "cp437": try: unistring = from_cp437(telnet_client.read_very_eager().decode("iso8859-1")) except EOFError: break else: unistring = telnet_client.read_very_eager().decode("utf8") if 0 != len(unistring): echo(unistring) if inp is not None: if inp == chr(30): # ctrl-^ telnet_client.close() echo(u"\r\n" + term.clear_el + term.normal) break elif not carriage_returned and inp in (b"\x0d", b"\x0a"): telnet_client.write(b"\x0d") log.debug("send {!r}".format(b"\x0d")) carriage_returned = True elif carriage_returned and inp in (b"\x0a", b"\x00"): carriage_returned = False elif inp is not None: telnet_client.write(inp) log.debug("send {!r}".format(inp)) carriage_returned = False inp = session.read_event("input", timeout=KEY_POLL) echo(u"\r\nConnection closed.\r\n") echo(u"".join(("\r\n\r\n", term.clear_el, term.normal, "press any key"))) echo(u"\x1b[r") # unset 'set scrolling region', sometimes set by BBS's session.flush_event("input") getch() return
def main(host, port=None, encoding='cp437'): """ Call script with argument host and optional argument port to connect to a telnet server. ctrl-^ to disconnect. """ # pylint: disable=R0914,R0912,R0915 # Too many local variables # Too many branches # Too many statements import telnetlib from functools import partial from x84.bbs import getsession, getterminal, echo, from_cp437, telnet import logging log = logging.getLogger() assert encoding in ('utf8', 'cp437') session, term = getsession(), getterminal() session.activity = 'connecting to %s' % (host, ) port = int(port) if port is not None else 23 telnet_client = telnetlib.Telnet() telnet_client.set_option_negotiation_callback( partial(telnet.callback_cmdopt, env_term=session.env['TERM'], height=term.height, width=term.width)) echo(u"\r\n\r\nEscape character is 'ctrl-^.'") if not session.user.get('expert', False): term.inkey(3) echo(u'\r\nTrying %s:%s... ' % ( host, port, )) # pylint: disable=W0703 # Catching too general exception Exception try: telnet_client.open(host, port) except Exception as err: echo(term.bold_red('\r\n%s\r\n' % (err, ))) echo(u'\r\n press any key ..') term.inkey() return echo(u'\r\n... ') inp = session.read_event('input', timeout=0) echo(u'\r\nConnected to %s.' % (host, )) session.activity = 'connected to %s' % (host, ) carriage_returned = False with term.fullscreen(): while True: if encoding == 'cp437': try: unistring = from_cp437( telnet_client.read_very_eager().decode('iso8859-1')) except EOFError: break else: unistring = telnet_client.read_very_eager().decode('utf8') if 0 != len(unistring): echo(unistring) if inp is not None: if inp == chr(30): # ctrl-^ telnet_client.close() echo(u'\r\n' + term.clear_el + term.normal) break elif not carriage_returned and inp in (b'\x0d', b'\x0a'): telnet_client.write(b'\x0d') log.debug('send {!r}'.format(b'\x0d')) carriage_returned = True elif carriage_returned and inp in (b'\x0a', b'\x00'): carriage_returned = False elif inp: telnet_client.write(inp) log.debug('send {!r}'.format(inp)) carriage_returned = False inp = session.read_event('input', timeout=KEY_POLL) echo(u'\r\nConnection closed.\r\n') echo(u''.join(('\r\n\r\n', term.clear_el, term.normal, 'press any key'))) echo(u'\x1b[r') # unset 'set scrolling region', sometimes set by BBS's session.flush_event('input') term.inkey() return
def main(): """ Main procedure. """ # pylint: disable=R0914,W0141,R0912 # Too many local variables # Used builtin function 'map' # Too many branches from x84.bbs import getsession, getterminal, echo, getch, from_cp437 from x84.engine import __url__ as url import platform import random import sys import os session, term = getsession(), getterminal() session.activity = 'System Info' artfile = os.path.join(os.path.dirname(__file__), 'art', 'plant.ans',) system, _node, release, _version, machine, _processor = platform.uname() body = [u'AUthORS:', u'Johannes Lundberg', u'Jeffrey Quast', u'Wijnand Modderman-Lenstra', u'', u'ARtWORk:', u'spidy!food,', u'hellbeard!impure', u'\r\n', u'SYStEM: %s %s %s' % (system, release, machine), u'SOftWARE: X/84', url, u'\r\n', (platform.python_implementation() + u' ' + '-'.join(map(str, sys.version_info[3:]))) + u' ' + (platform.python_version() if hasattr(platform, 'python_implementation') else u'.'.join(map(str, sys.version_info[:3]))), ] melt_colors = ( [term.normal] + [term.bold_blue] * 3 + [term.red] * 4 + [term.bold_red] + [term.bold_white] + [term.normal] * 6 + [term.blue] * 2 + [term.bold_blue] + [term.bold_white] + [term.normal]) art = from_cp437(open(artfile).read()) if os.path.exists(artfile) else u'' otxt = list(art.splitlines()) for num, line in enumerate(body): while num > len(otxt): otxt += [u'', ] otxt[num] = otxt[num][:int(term.width / 2.5)] + u' ' + line width = max([term.length(line) for line in otxt]) height = len(otxt) num_stars = int((term.width * term.height) * .002) stars = dict([(n, (random.choice('\\|/-'), float(random.choice(range(term.width))), float(random.choice(range(term.height))))) for n in range(num_stars)]) melting = {} show_star = False tm_out, tm_min, tm_max, tm_step = 0.08, 0.01, 2.0, .01 wind = (0.7, 0.1, 0.01, 0.01) def refresh(): """ Refresh screen and return top-left (x, y) location. """ echo(u'\r\n\r\n') if term.width < width: echo(u''.join(( term.move(term.height, 0), u'\r\n\r\n', term.bold_red + 'screen too thin! (%s/%s)' % ( term.width, width,), u'\r\n\r\n', u'press any key...',))) getch() return (None, None) if term.height < height: echo(u''.join(( term.move(term.height, 0), u'\r\n\r\n', term.bold_red + 'screen too short! (%s/%s)' % ( term.height, height), u'\r\n\r\n', u'press any key...',))) getch() return (None, None) xloc = (term.width / 2) - (width / 2) yloc = (term.height / 2) - (height / 2) echo(u''.join(( term.normal, (u'\r\n' + term.clear_eol) * term.height, u''.join([term.move(yloc + abs_y, xloc) + line for abs_y, line in enumerate(otxt)]),))) return xloc, yloc txt_x, txt_y = refresh() if (txt_x, txt_y) == (None, None): return def char_at_pos(yloc, xloc, txt_y, txt_x): """ Return art (y, x) for location """ return (u' ' if yloc - txt_y < 0 or yloc - txt_y >= height or xloc - txt_x < 0 or xloc - txt_x >= len(otxt[yloc - txt_y]) else otxt[yloc - txt_y][xloc - txt_x]) def iter_wind(xslope, yslope, xdir, ydir): """ An easterly Wind """ xslope += xdir yslope += ydir if xslope <= 0.5: xdir = random.choice([0.01, 0.015, 0.02]) elif xslope >= 1: xdir = random.choice([-0.01, -0.015, -0.02]) if yslope <= -0.1: ydir = random.choice([0.01, 0.015, 0.02, 0.02]) elif yslope >= 0.1: ydir = random.choice([-0.01, -0.015, -0.02]) return xslope, yslope, xdir, ydir def iter_star(char, xloc, yloc): """ Given char and current position, apply wind and return new char and new position. """ if char == '\\': char = '|' elif char == '|': char = '/' elif char == '/': char = '-' elif char == '-': char = '\\' xloc += wind[0] yloc += wind[1] if xloc < 1 or xloc > term.width: xloc = (1.0 if xloc > term.width else float(term.width)) yloc = (float(random.choice (range(term.height)))) if yloc < 1 or yloc > term.height: yloc = (1.0 if yloc > term.height else float(term.height)) xloc = (float(random.choice (range(term.width)))) return char, xloc, yloc def erase(star_idx): """ erase old star before moving .. """ if show_star: _char, xloc, yloc = stars[star_idx] echo(u''.join((term.move(int(yloc), int(xloc)), term.normal, char_at_pos(int(yloc), int(xloc), txt_y, txt_x),))) def melt(): """ Iterate through all stars and phase through melt sequence. """ def melted(yloc, xloc): """ shift melt, delete if dissapeared. """ melting[(yloc, xloc)] -= 1 if 0 == melting[(yloc, xloc)]: del melting[(yloc, xloc)] for (yloc, xloc), phase in melting.items(): echo(u''.join((term.move(yloc, xloc), melt_colors[phase - 1], char_at_pos(yloc, xloc, txt_y, txt_x),))) melted(yloc, xloc) def draw_star(star, xloc, yloc): """ draw star a (x, y) location """ char = char_at_pos(int(yloc), int(xloc), txt_y, txt_x) if char != ' ': melting[(int(yloc), int(xloc))] = len(melt_colors) if show_star: echo(term.move(int(yloc), int(xloc)) + melt_colors[-1] + star) with term.hidden_cursor(): while txt_x is not None and txt_y is not None: if session.poll_event('refresh'): num_stars = int(num_stars) stars = dict([(n, (random.choice('\\|/-'), float(random.choice(range(term.width))), float(random.choice(range(term.height))))) for n in range(num_stars)]) otxt = list(art.splitlines()) for num, line in enumerate(body): while num > len(otxt): otxt += [u'', ] otxt[num] = (otxt[num][:int(term.width / 2.5)] + u' ' + line) txt_x, txt_y = refresh() continue inp = getch(tm_out) if inp in (term.KEY_UP, 'k'): if tm_out >= tm_min: tm_out -= tm_step elif inp in (term.KEY_DOWN, 'j'): if tm_out <= tm_max: tm_out += tm_step elif inp in (term.KEY_LEFT, 'h'): if num_stars > 2: num_stars = int(num_stars * .5) stars = dict([(n, (random.choice('\\|/-'), float(random.choice(range(term.width))), float(random.choice(range(term.height))))) for n in range(num_stars)]) elif inp in (term.KEY_RIGHT, 'l'): if num_stars < (term.width * term.height) / 4: num_stars = int(num_stars * 1.5) stars = dict([(n, (random.choice('\\|/-'), float(random.choice(range(term.width))), float(random.choice(range(term.height))))) for n in range(num_stars)]) elif inp in (u'*',) and not show_star: show_star = True elif inp in (u'*',) and show_star: for star in stars: erase(star) show_star = False elif inp is not None: echo(term.move(term.height, 0)) break melt() for star_key, star_val in stars.items(): erase(star_key) # pylint: disable=W0142 # Used * or ** magic stars[star_key] = iter_star(*star_val) draw_star(*stars[star_key]) # pylint: disable=W0142 # Used * or ** magic wind = iter_wind(*wind)
def main(host, port=None, encoding='cp437'): """ Call script with argument host and optional argument port to connect to a telnet server. ctrl-^ to disconnect. """ # pylint: disable=R0914,R0912,R0915 # Too many local variables # Too many branches # Too many statements import telnetlib import struct from x84.bbs import getsession, getterminal, echo, getch, from_cp437 import logging log = logging.getLogger() assert encoding in ('utf8', 'cp437') session, term = getsession(), getterminal() session.activity = 'connecting to %s' % (host,) port = int(port) if port is not None else 23 telnet_client = telnetlib.Telnet() def callback_cmdopt(socket, cmd, opt): """ Callback for telnetlib.Telnet.set_option_negotiation_callback. """ if cmd == telnetlib.WILL: if opt in (telnetlib.ECHO, telnetlib.SGA): socket.sendall(telnetlib.IAC + telnetlib.DO + opt) elif cmd == telnetlib.DO: if opt == telnetlib.SGA: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) elif opt == telnetlib.TTYPE: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.TTYPE + IS + session.env.get('TERM') + chr(0) + telnetlib.IAC + telnetlib.SE) elif opt == telnetlib.NAWS: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.NAWS + struct.pack('!HH', term.width, term.height) + telnetlib.IAC + telnetlib.SE) else: socket.sendall(telnetlib.IAC + telnetlib.WONT + opt[0]) elif cmd == telnetlib.SB: if opt[0] == telnetlib.TTYPE and opt[1] == SEND: socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.TTYPE + IS + session.env.get('TERM') + chr(0) + telnetlib.IAC + telnetlib.SE) telnet_client.set_option_negotiation_callback(callback_cmdopt) echo(u"\r\n\r\nEscape character is 'ctrl-^.'") if not session.user.get('expert', False): getch(3) echo(u'\r\nTrying %s:%s... ' % (host, port,)) # pylint: disable=W0703 # Catching too general exception Exception try: telnet_client.open(host, port) except Exception as err: echo(term.bold_red('\r\n%s\r\n' % (err,))) echo(u'\r\n press any key ..') getch() return echo(u'\r\n... ') inp = session.read_event('input', timeout=0) echo(u'\r\nConnected to %s.' % (host,)) session.activity = 'connected to %s' % (host,) carriage_returned = False with term.fullscreen(): while True: if encoding == 'cp437': try: unistring = from_cp437( telnet_client.read_very_eager().decode('iso8859-1')) except EOFError: break else: unistring = telnet_client.read_very_eager().decode('utf8') if 0 != len(unistring): echo(unistring) if inp is not None: if inp == chr(30): # ctrl-^ telnet_client.close() echo(u'\r\n' + term.clear_el + term.normal) break elif not carriage_returned and inp in (b'\x0d', b'\x0a'): telnet_client.write(b'\x0d') log.debug('send {!r}'.format(b'\x0d')) carriage_returned = True elif carriage_returned and inp in (b'\x0a', b'\x00'): carriage_returned = False elif inp is not None: telnet_client.write(inp) log.debug('send {!r}'.format(inp)) carriage_returned = False inp = session.read_event('input', timeout=KEY_POLL) echo(u'\r\nConnection closed.\r\n') echo(u''.join(('\r\n\r\n', term.clear_el, term.normal, 'press any key'))) echo(u'\x1b[r') # unset 'set scrolling region', sometimes set by BBS's session.flush_event('input') getch() return
def main(host, port=None, encoding='cp437'): """ Call script with argument host and optional argument port to connect to a telnet server. ctrl-^ to disconnect. """ # pylint: disable=R0914,R0912,R0915 # Too many local variables # Too many branches # Too many statements import telnetlib import struct from x84.bbs import getsession, getterminal, echo, getch, from_cp437 assert encoding in ('utf8', 'cp437') session, term = getsession(), getterminal() session.activity = 'connecting to %s' % (host,) port = int(port) if port is not None else 23 telnet_client = telnetlib.Telnet() def callback_cmdopt(socket, cmd, opt): """ Callback for telnetlib.Telnet.set_option_negotiation_callback. """ if cmd == telnetlib.WILL: if opt in (telnetlib.ECHO, telnetlib.SGA): socket.sendall(telnetlib.IAC + telnetlib.DO + opt) elif cmd == telnetlib.DO: if opt == telnetlib.SGA: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) elif opt == telnetlib.TTYPE: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.TTYPE + IS + session.env.get('TERM') + chr(0) + telnetlib.IAC + telnetlib.SE) elif opt == telnetlib.NAWS: socket.sendall(telnetlib.IAC + telnetlib.WILL + opt) socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.NAWS + struct.pack('!HH', term.width, term.height) + telnetlib.IAC + telnetlib.SE) else: socket.sendall(telnetlib.IAC + telnetlib.WONT + opt[0]) elif cmd == telnetlib.SB: if opt[0] == telnetlib.TTYPE and opt[1] == SEND: socket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.TTYPE + IS + session.env.get('TERM') + chr(0) + telnetlib.IAC + telnetlib.SE) telnet_client.set_option_negotiation_callback(callback_cmdopt) echo(u"\r\n\r\nEscape character is 'ctrl-^.'") if not session.user.get('expert', False): getch(3) echo(u'\r\nTrying %s:%s... ' % (host, port,)) # pylint: disable=W0703 # Catching too general exception Exception try: telnet_client.open(host, port) except Exception as err: echo(term.bold_red('\r\n%s\r\n' % (err,))) echo(u'\r\n press any key ..') getch() return swp = session.enable_keycodes # disable keyboard translation .. so special accomidations are # made with carriage_return to handle \r\n to just \r, for one. session.enable_keycodes = False inp = session.poll_event('input') echo(u'\r\nConnected to %s.' % (host,)) session.activity = 'connected to %s' % (host,) carriage_returned = False while True: try: unistring = (from_cp437(telnet_client.read_very_eager()) if encoding == 'cp437' else telnet_client.read_very_eager().decode('utf8')) if 0 != len(unistring): echo(unistring) if inp is not None: if inp in (unichr(30),): # ctrl-^ telnet_client.close() echo(u'\r\n' + term.clear_el + term.normal) break elif not carriage_returned and inp in (u'\r', u'\n'): telnet_client.write('\r') carriage_returned = True elif carriage_returned and inp in (u'\n', unichr(0)): carriage_returned = False elif inp is not None: telnet_client.write(inp) carriage_returned = False except Exception as err: echo(term.bold_red('%s\r\n%s\r\n' % ( term.normal, err,))) break inp = getch(timeout=KEY_POLL) echo(u'\r\nConnection closed.\r\n') echo(u''.join(('\r\n\r\n', term.clear_el, term.normal, 'press any key'))) session.flush_event('input') getch() session.enable_keycodes = swp return
def play(): import time from random import randint import os from x84.bbs import getterminal, from_cp437, AnsiWindow, syncterm_setfont from x84.bbs import echo as echo_unbuffered term = getterminal() field = [] global charcache charcache = u'' field_width = 10 field_height = 20 # Access scheme looks like this: # layout[p][r][ypox][xpos] # layoutcolor = [ 7,2,3,4,4,6,7 ] layout = [ # ## # ## [ [ [1, 1, ], [1, 1, ], ], ], # # # # # # # # [ [ [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], ], [ [0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0], ] ], # ### # # [ [ [0, 0, 0], [1, 1, 1], [0, 1, 0], ], [ [0, 1, 0], [0, 1, 1], [0, 1, 0], ], [ [0, 1, 0], [1, 1, 1], [0, 0, 0], ], [ [0, 1, 0], [1, 1, 0], [0, 1, 0], ], ], # # # # # ## [ [ [0, 1, 0], [0, 1, 0], [0, 1, 1], ], [ [0, 0, 1], [1, 1, 1], [0, 0, 0], ], [ [1, 1, 0], [0, 1, 0], [0, 1, 0], ], [ [0, 0, 0], [1, 1, 1], [1, 0, 0], ], ], # # # # # ## [ [ [0, 1, 0], [0, 1, 0], [1, 1, 0], ], [ [0, 0, 0], [1, 1, 1], [0, 0, 1], ], [ [0, 1, 1], [0, 1, 0], [0, 1, 0], ], [ [1, 0, 0], [1, 1, 1], [0, 0, 0], ], ], # ## # ## [ [ [0, 1, 0], [1, 1, 0], [1, 0, 0], ], [ [0, 0, 0], [1, 1, 0], [0, 1, 1], ], ], # ## # ## [ [ [0, 1, 0], [0, 1, 1], [0, 0, 1], ], [ [0, 0, 0], [0, 1, 1], [1, 1, 0], ], ], ] fieldx1 = 32 fieldy1 = 10 scorex1 = 11 scorey1 = 11 class RectRedraw: x1 = None y1 = None x2 = None y2 = None def max(r, val, valmax): if val > valmax: return valmax return val def min(r, val, valmin): if val < valmin: return valmin return val def merge(r, x1, y1, x2, y2): if r.x1 is None or r.x1 > x1: r.x1 = r.min(x1, 0) if r.y1 is None or r.y1 > y1: r.y1 = r.min(y1, 0) if r.x2 is None or r.x2 < x2: r.x2 = r.max(x2, field_width) if r.y2 is None or r.y2 < y2: r.y2 = r.max(y2, field_height) # print r.x1,r.y1,r.x2,r.y2 def clean(r): r.x1 = None r.y1 = None r.x2 = None r.y2 = None rr = RectRedraw() for _ in range(field_height): field.append([0] * field_width) def echo(s): global charcache charcache += s assert term.height > (field_height + 1) echo_unbuffered(u''.join(( u'\r\n\r\n', u'REAdY YOUR tERMiNAl %s ' % (term.bold_blue('(!)'),), u'\r\n\r\n', u'%s PRESS ANY kEY' % (term.bold_black('...'),), ))) term.inkey() # set syncterm font to cp437 if term.kind.startswith('ansi'): echo_unbuffered(syncterm_setfont('cp437')) artfile = os.path.join(os.path.dirname(__file__), 'art', 'tetris.ans') echo_unbuffered(u'\r\n' * term.height) # cls if os.path.exists(artfile): echo_unbuffered(from_cp437(open(artfile).read()).rstrip()) def gotoxy(x, y): echo(term.move(y, x)) def plotblock(color, lastcolor): if color: c = u'\u2588\u2588' # '\xDB\xDB' else: # both empty c = ' ' color = 0 # Output optimization if color % 8 == 0: color = color / 8 if color == lastcolor: echo(c) else: if color: fg = str(30 + color % 8) else: fg = '37' if color >= 8: bg = ';%d' % (40 + color / 8) else: bg = '' echo('\x1b[0;' + fg + bg + 'm') echo(c) lastcolor = color return lastcolor def drawfield(): lastcolor = '' for y in range(0, field_height, 2): # gotoxy(field_width,2+y/2) gotoxy(fieldx1 + 2, fieldy1 + 1 + y / 2) # Which block to show, full, half-up, half-down or empty. for x in range(field_width): color = field[y][x] + field[y + 1][x] * 8 if field[y][x] and field[y + 1][x]: c = u'\u2588' # '\xDB' if field[y][x] == field[y + 1][x]: color = color % 8 else: c = u'\u2580' # '\xDF' elif field[y][x] and not field[y + 1][x]: c = u'\u2580' # '\xDF' elif not field[y][x] and field[y + 1][x]: c = u'\u2584' # '\xDC' else: # both empty c = ' ' # Output optimization if color % 8 == 0: color = color / 8 if color == lastcolor: echo(c) else: if color: fg = str(30 + color % 8) else: fg = '37' if color >= 8: bg = ';%d' % (40 + color / 8) else: bg = '' echo('\x1b[0;' + fg + bg + 'm') echo(c) lastcolor = color echo(term.normal) layoutcolor = [7, 2, 7, 6, 3, 6, 3] # p = -1 # Current piece type nextpiece = randint(0, len(layout) - 1) p = randint(0, len(layout) - 1) p = 1 r = 0 # Current rotation xpos = 4 # X position # ypos = -2 # Y position ypos = -len(layout[p][0]) level = 1 score = 0 lines = 0 def flush(): global charcache echo_unbuffered(charcache) charcache = u'' def fillpiece(x, y, p, r, value): row = 0 for line in layout[p][r]: col = 0 for c in line: if c and (y + row) >= 0: field[y + row][x + col] = value col += 1 row += 1 def showpiece(x, y, p, r): fillpiece(x, y, p, r, layoutcolor[p]) def hidepiece(): fillpiece(xpos, ypos, p, r, 0) def testpiece(x, y, newr): hidepiece() # Space at the new location? row = 0 for line in layout[p][newr]: col = 0 for c in line: try: if c: if ((y + row) >= 0 and field[y + row][x + col] or (x + col) < 0 or (x + col) > 9): return 0 except IndexError: return 0 col += 1 row += 1 # Movement possible return 1 def movepiece(x, y, newr): if testpiece(x, y, newr): # Build redraw rectangle rr.merge(xpos, ypos, xpos + len(layout[p][0][0]), ypos + len(layout[p][0])) rr.merge(x, y, x + len(layout[p][0][0]), y + len(layout[p][0])) showpiece(x, y, p, newr) return (x, y, newr, 1) else: showpiece(xpos, ypos, p, r) return (xpos, ypos, r, 0) def shownext(p): r = 0 for y in range(4): gotoxy(26, 18 + y) echo(u' ' * 4) echo(term.color(layoutcolor[p])) yoffset = int(len(layout[p][r][0]) < 4) xoffset = int(len(layout[p][r]) < 3) for y in range(len(layout[p][r])): for x in range(len(layout[p][r][y])): val = layout[p][r][y][x] if val: gotoxy(26 + x + xoffset, 18 + y + yoffset) echo(u'\u2588\u2588') def drawstats(): echo(term.move(scorey1, scorex1) + '%d' % level) echo(term.move(scorey1 + 2, scorex1) + '%d' % lines) echo(term.move(scorey1 + 3, scorex1) + '%d' % score) drawstats() ticksize = 0.4 nexttick = time.time() + ticksize showpiece(xpos, ypos, p, r) gotoxy(26, 17) echo(term.blue_reverse('next')) shownext(nextpiece) # Full redraw first frame rr.merge(0, 0, field_width, field_height) buf = '' while True: drawfield() # gotoxy(0,0) # echo('\x1b[37mx: %d, y: %d, p: %d '%(xpos,ypos,p)) slice = nexttick - time.time() if slice < 0: slice = 0 echo(buf) buf = '' flush() key = term.inkey(slice + 0.01) now = time.time() # hidepiece() if key is not None: if key in (u'q', u'Q'): return (0, 0, 0) elif key.code == term.KEY_LEFT or key == u'h': xpos, ypos, r, m = movepiece(xpos - 1, ypos, r) elif key.code == term.KEY_RIGHT or key == u'l': xpos, ypos, r, m = movepiece(xpos + 1, ypos, r) elif key.code == term.KEY_UP or key == u'k': xpos, ypos, r, m = movepiece( xpos, ypos, (r + 1) % len(layout[p])) elif key.code == term.KEY_DOWN or key == u'j': xpos, ypos, r, m = movepiece(xpos, ypos + 1, r) elif key in (' ',): m = True c = 0 while m: xpos, ypos, r, m = movepiece(xpos, ypos + 1, r) if m: c += 1 if c: nexttick = time.time() + ticksize # New tick? if now > nexttick: nexttick += ticksize # Move down piece xpos, ypos, r, moved = movepiece(xpos, ypos + 1, r) # Piece has touched down? if not moved: # Is the player dead? if ypos <= -len(layout[p][0]): death_win = AnsiWindow(height=6, width=40, yloc=fieldy1 + 10 / 2, xloc=fieldx1 - 11) death_win.colors['border'] = term.bold_black echo_unbuffered(death_win.clear() + death_win.border()) echo_unbuffered( term.move(fieldy1 + 10 / 2 + 1, fieldx1 - 11)) echo_unbuffered(( u'!! gAME OVeR!! Score was: %i' % (score,)).center(40)) echo_unbuffered( term.move(fieldy1 + 10 / 2 + 3, fieldx1 - 11)) echo_unbuffered(u'press RETURN'.center(40)) while True: inp = term.inkey() if inp.code == term.KEY_ENTER: break return (score, level, lines) # Any complete rows to remove? complete = [] for y in range(field_height): x = 0 while x < field_width: if field[y][x] == 0: break x += 1 if x == field_width: complete.append(y) if len(complete) > 0: # Add score lines += len(complete) score += len(complete) * len(complete) * 100 # Shrink field for line in complete: del field[line] field.insert(0, [0] * field_width) if lines >= level * 10: level += 1 ticksize = 0.4 - level * 0.02 drawstats() # Redraw complete field rr.merge(0, 0, field_width, field_height) # Time for a new piece p = nextpiece nextpiece = randint(0, len(layout) - 1) r = 0 xpos = 4 ypos = -len(layout[p][0]) showpiece(xpos, ypos, p, r) shownext(nextpiece)
def play(): import time from random import randint import os from x84.bbs import getterminal, getch, from_cp437, AnsiWindow, syncterm_setfont from x84.bbs import echo as echo_unbuffered term = getterminal() field = [] global charcache charcache = u'' field_width = 10 field_height = 20 # Access scheme looks like this: # layout[p][r][ypox][xpos] # layoutcolor = [ 7,2,3,4,4,6,7 ] layout = [ # ## # ## [ [ [1, 1, ], [1, 1, ], ], ], # # # # # # # # [ [ [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], ], [ [0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0], ] ], # ### # # [ [ [0, 0, 0], [1, 1, 1], [0, 1, 0], ], [ [0, 1, 0], [0, 1, 1], [0, 1, 0], ], [ [0, 1, 0], [1, 1, 1], [0, 0, 0], ], [ [0, 1, 0], [1, 1, 0], [0, 1, 0], ], ], # # # # # ## [ [ [0, 1, 0], [0, 1, 0], [0, 1, 1], ], [ [0, 0, 1], [1, 1, 1], [0, 0, 0], ], [ [1, 1, 0], [0, 1, 0], [0, 1, 0], ], [ [0, 0, 0], [1, 1, 1], [1, 0, 0], ], ], # # # # # ## [ [ [0, 1, 0], [0, 1, 0], [1, 1, 0], ], [ [0, 0, 0], [1, 1, 1], [0, 0, 1], ], [ [0, 1, 1], [0, 1, 0], [0, 1, 0], ], [ [1, 0, 0], [1, 1, 1], [0, 0, 0], ], ], # ## # ## [ [ [0, 1, 0], [1, 1, 0], [1, 0, 0], ], [ [0, 0, 0], [1, 1, 0], [0, 1, 1], ], ], # ## # ## [ [ [0, 1, 0], [0, 1, 1], [0, 0, 1], ], [ [0, 0, 0], [0, 1, 1], [1, 1, 0], ], ], ] fieldx1 = 32 fieldy1 = 10 scorex1 = 11 scorey1 = 11 class RectRedraw: x1 = None y1 = None x2 = None y2 = None def max(r, val, valmax): if val > valmax: return valmax return val def min(r, val, valmin): if val < valmin: return valmin return val def merge(r, x1, y1, x2, y2): if r.x1 is None or r.x1 > x1: r.x1 = r.min(x1, 0) if r.y1 is None or r.y1 > y1: r.y1 = r.min(y1, 0) if r.x2 is None or r.x2 < x2: r.x2 = r.max(x2, field_width) if r.y2 is None or r.y2 < y2: r.y2 = r.max(y2, field_height) # print r.x1,r.y1,r.x2,r.y2 def clean(r): r.x1 = None r.y1 = None r.x2 = None r.y2 = None rr = RectRedraw() for _ in range(field_height): field.append([0] * field_width) def echo(s): global charcache charcache += s assert term.height > (field_height + 1) echo_unbuffered(u''.join(( u'\r\n\r\n', u'REAdY YOUR tERMiNAl %s ' % (term.bold_blue('(!)'),), u'\r\n\r\n', u'%s PRESS ANY kEY' % (term.bold_black('...'),), ))) getch() # set syncterm font to cp437 if term.kind.startswith('ansi'): echo_unbuffered(syncterm_setfont('cp437')) artfile = os.path.join(os.path.dirname(__file__), 'art', 'tetris.ans') echo_unbuffered(u'\r\n' * term.height) # cls if os.path.exists(artfile): echo_unbuffered(from_cp437(open(artfile).read()).rstrip()) def gotoxy(x, y): echo(term.move(y, x)) def plotblock(color, lastcolor): if color: c = u'\u2588\u2588' # '\xDB\xDB' else: # both empty c = ' ' color = 0 # Output optimization if color % 8 == 0: color = color / 8 if color == lastcolor: echo(c) else: if color: fg = str(30 + color % 8) else: fg = '37' if color >= 8: bg = ';%d' % (40 + color / 8) else: bg = '' echo('\x1b[0;' + fg + bg + 'm') echo(c) lastcolor = color return lastcolor def drawfield(): lastcolor = '' for y in range(0, field_height, 2): # gotoxy(field_width,2+y/2) gotoxy(fieldx1 + 2, fieldy1 + 1 + y / 2) # Which block to show, full, half-up, half-down or empty. for x in range(field_width): color = field[y][x] + field[y + 1][x] * 8 if field[y][x] and field[y + 1][x]: c = u'\u2588' # '\xDB' if field[y][x] == field[y + 1][x]: color = color % 8 else: c = u'\u2580' # '\xDF' elif field[y][x] and not field[y + 1][x]: c = u'\u2580' # '\xDF' elif not field[y][x] and field[y + 1][x]: c = u'\u2584' # '\xDC' else: # both empty c = ' ' # Output optimization if color % 8 == 0: color = color / 8 if color == lastcolor: echo(c) else: if color: fg = str(30 + color % 8) else: fg = '37' if color >= 8: bg = ';%d' % (40 + color / 8) else: bg = '' echo('\x1b[0;' + fg + bg + 'm') echo(c) lastcolor = color echo(term.normal) layoutcolor = [7, 2, 7, 6, 3, 6, 3] # p = -1 # Current piece type nextpiece = randint(0, len(layout) - 1) p = randint(0, len(layout) - 1) p = 1 r = 0 # Current rotation xpos = 4 # X position # ypos = -2 # Y position ypos = -len(layout[p][0]) level = 1 score = 0 lines = 0 def flush(): global charcache echo_unbuffered(charcache) charcache = u'' def fillpiece(x, y, p, r, value): row = 0 for line in layout[p][r]: col = 0 for c in line: if c and (y + row) >= 0: field[y + row][x + col] = value col += 1 row += 1 def showpiece(x, y, p, r): fillpiece(x, y, p, r, layoutcolor[p]) def hidepiece(): fillpiece(xpos, ypos, p, r, 0) def testpiece(x, y, newr): hidepiece() # Space at the new location? row = 0 for line in layout[p][newr]: col = 0 for c in line: try: if c: if ((y + row) >= 0 and field[y + row][x + col] or (x + col) < 0 or (x + col) > 9): return 0 except IndexError: return 0 col += 1 row += 1 # Movement possible return 1 def movepiece(x, y, newr): if testpiece(x, y, newr): # Build redraw rectangle rr.merge(xpos, ypos, xpos + len(layout[p][0][0]), ypos + len(layout[p][0])) rr.merge(x, y, x + len(layout[p][0][0]), y + len(layout[p][0])) showpiece(x, y, p, newr) return (x, y, newr, 1) else: showpiece(xpos, ypos, p, r) return (xpos, ypos, r, 0) def shownext(p): r = 0 for y in range(4): gotoxy(26, 18 + y) echo(u' ' * 4) echo(term.color(layoutcolor[p])) yoffset = int(len(layout[p][r][0]) < 4) xoffset = int(len(layout[p][r]) < 3) for y in range(len(layout[p][r])): for x in range(len(layout[p][r][y])): val = layout[p][r][y][x] if val: gotoxy(26 + x + xoffset, 18 + y + yoffset) echo(u'\u2588\u2588') def drawstats(): echo(term.move(scorey1, scorex1) + '%d' % level) echo(term.move(scorey1 + 2, scorex1) + '%d' % lines) echo(term.move(scorey1 + 3, scorex1) + '%d' % score) drawstats() ticksize = 0.4 nexttick = time.time() + ticksize showpiece(xpos, ypos, p, r) gotoxy(26, 17) echo(term.blue_reverse('next')) shownext(nextpiece) # Full redraw first frame rr.merge(0, 0, field_width, field_height) buf = '' while True: drawfield() # gotoxy(0,0) # echo('\x1b[37mx: %d, y: %d, p: %d '%(xpos,ypos,p)) slice = nexttick - time.time() if slice < 0: slice = 0 echo(buf) buf = '' flush() key = getch(slice + 0.01) now = time.time() # hidepiece() if key is not None: if key in (u'q', u'Q'): return (0, 0, 0) elif key in (term.KEY_LEFT, u'h',): xpos, ypos, r, m = movepiece(xpos - 1, ypos, r) elif key in (term.KEY_RIGHT, u'l',): xpos, ypos, r, m = movepiece(xpos + 1, ypos, r) elif key in (term.KEY_UP, u'k',): xpos, ypos, r, m = movepiece( xpos, ypos, (r + 1) % len(layout[p])) elif key in (term.KEY_DOWN, u'j',): xpos, ypos, r, m = movepiece(xpos, ypos + 1, r) elif key in (' ',): m = True c = 0 while m: xpos, ypos, r, m = movepiece(xpos, ypos + 1, r) if m: c += 1 if c: nexttick = time.time() + ticksize # New tick? if now > nexttick: nexttick += ticksize # Move down piece xpos, ypos, r, moved = movepiece(xpos, ypos + 1, r) # Piece has touched down? if not moved: # Is the player dead? if ypos <= -len(layout[p][0]): death_win = AnsiWindow(height=6, width=40, yloc=fieldy1 + 10 / 2, xloc=fieldx1 - 11) death_win.colors['border'] = term.bold_black echo_unbuffered(death_win.clear() + death_win.border()) echo_unbuffered( term.move(fieldy1 + 10 / 2 + 1, fieldx1 - 11)) echo_unbuffered(( u'!! gAME OVeR!! Score was: %i' % (score,)).center(40)) echo_unbuffered( term.move(fieldy1 + 10 / 2 + 3, fieldx1 - 11)) echo_unbuffered(u'press RETURN'.center(40)) while True: inp = getch() if inp in (u'\r', term.KEY_ENTER): break return (score, level, lines) # Any complete rows to remove? complete = [] for y in range(field_height): x = 0 while x < field_width: if field[y][x] == 0: break x += 1 if x == field_width: complete.append(y) if len(complete) > 0: # Add score lines += len(complete) score += len(complete) * len(complete) * 100 # Shrink field for line in complete: del field[line] field.insert(0, [0] * field_width) if lines >= level * 10: level += 1 ticksize = 0.4 - level * 0.02 drawstats() # Redraw complete field rr.merge(0, 0, field_width, field_height) # Time for a new piece p = nextpiece nextpiece = randint(0, len(layout) - 1) r = 0 xpos = 4 ypos = -len(layout[p][0]) showpiece(xpos, ypos, p, r) shownext(nextpiece)
def display_weather(todays, weather, centigrade): """ Display weather as vertical panels. Thanks to xzip, we now have a sortof tv-weather channel art :-) """ from x84.bbs import getterminal, echo, from_cp437, syncterm_setfont term = getterminal() # set syncterm font to cp437 if term.kind.startswith('ansi'): echo(syncterm_setfont('cp437')) echo(term.height * u'\r\n') echo(term.move(0, 0)) at = term.yellow_bold('At') city = term.bold(todays.get('City', u'')) state = todays.get('State', u'') if state: state = u', {}'.format(term.bold_yellow_reverse(state)) dotdot = term.bold_black('...') echo(u'{at} {city}{state} {dotdot}'.format( at=at, city=city, state=state, dotdot=dotdot)) bottom = 2 if weather: for column in range(0, (term.width - panel_width), panel_width): try: day = weather.pop(0) except IndexError: break bottom = max(display_panel(day, column, centigrade), bottom) timenow = time.strftime('%I:%M%p', time.strptime(todays.get('Time', '00:00'), '%H:%M')) temp, deg_conv = temp_conv(todays.get('Temperature', ''), centigrade) real_temp, deg_conv = temp_conv(todays.get('RealFeel', ''), centigrade) speed, spd_conv = speed_conv(todays.get('WindSpeed', ''), centigrade) degree = from_cp437(''.join([chr(248)])) current_0 = u'Current conditions at {timenow}'.format(timenow=timenow) current_1 = u'{0}'.format(todays.get('WeatherText', '')) current_2 = u'Temperature is {temp}{degree}{deg_conv}'.format( temp=temp, degree=degree, deg_conv=deg_conv) current_3 = u'' if real_temp == temp else ( u'(feels like {real_temp}{degree}{deg_conv})'.format( real_temp=real_temp, degree=degree, deg_conv=deg_conv)) current_4 = u'Winds {speed}{spd_conv} {wind}'.format( speed=speed, spd_conv=spd_conv, wind=todays.get('WindDirection', '')) current_5 = u'Humidity of {0}'.format(todays.get('Humidity', '')) wrapped = textwrap.wrap( u'{0}: {1}. {2} {3}, {4}, {5}.'.format( current_0, current_1, current_2, current_3, current_4, current_5), min(term.width - panel_width - 2, 40)) row_num = 0 art = get_icon(todays) joined_art_conditions = list(itertools.izip_longest(wrapped, art)) last_line = lambda row_num: row_num == len(joined_art_conditions) - 1 for row_num, (row_txt, art_txt) in enumerate(joined_art_conditions): echo(term.move(bottom + next_margin + row_num, 1)) echo(art_txt) if not row_txt and not last_line(row_num): echo(u'\r\n') elif row_txt: echo(term.move(bottom + next_margin + row_num, panel_width + 5)) echo(term.normal) echo(row_txt)
def main(): """ Main procedure. """ # pylint: disable=R0912 # Too many branches from x84.bbs import getsession, getterminal, echo, getch, Ansi, from_cp437 session, term = getsession(), getterminal() session.activity = u'Selecting chracter set' artfile = os.path.join( os.path.dirname(__file__), 'art', ( 'plant-256.ans' if term.number_of_colors == 256 else 'plant.ans')) enc_prompt = ( u'Press left/right until artwork looks best. Clients should' ' select utf8 encoding and Andale Mono font. Older clients or' ' clients with appropriate 8-bit fontsets can select cp437, though' ' some characters may appear as "?".') save_msg = u"\r\n\r\n'%s' is now your preferred encoding ..\r\n" if session.user.get('expert', False): echo(u'\r\n\r\n(U) UTF-8 encoding or (C) CP437 encoding [uc] ?\b\b') while True: inp = getch() if inp in (u'u', u'U'): session.encoding = 'utf8' break elif inp in (u'c', u'C'): session.encoding = 'cp437' break session.user['charset'] = session.encoding echo(save_msg % (session.encoding,)) getch(1.0) return art = (from_cp437(open(artfile).read()).splitlines() if os.path.exists(artfile) else [u'']) def refresh(sel): """ Refresh art and yes/no prompt, ``sel``. """ session.flush_event('refresh') session.encoding = selector.selection if sel.selection == 'utf8': # ESC %G activates UTF-8 with an unspecified implementation # level from ISO 2022 in a way that allows to go back to # ISO 2022 again. echo(unichr(27) + u'%G') elif sel.selection == 'cp437': # ESC %@ returns to ISO 2022 in case UTF-8 had been entered. # ESC ) U Sets character set G1 to codepage 437 .. usually. echo(unichr(27) + u'%@') echo(unichr(27) + u')U') else: assert False, "Only encodings 'utf8' and 'cp437' supported." # display art, banner, paragraph, refresh selector refresh buf = [line for line in art] return u''.join(( u'\r\n\r\n', u'\r\n'.join(buf), u'\r\n\r\n', Ansi(enc_prompt).wrap(int(term.width * .95)), u'\r\n\r\n', sel.refresh(),)) selector = get_selector(session.encoding) echo(refresh(selector)) while True: inp = getch(1) if inp == term.KEY_ENTER: session.user['charset'] = session.encoding echo(save_msg % (session.encoding,)) getch(1.0) return elif inp is not None: selector.process_keystroke(inp) if selector.quit: # 'escape' quits without save, though the encoding # has been temporarily set for this session. return if selector.moved: # set and refresh art in new encoding echo(refresh(selector)) if session.poll_event('refresh') is not None: # instantiate a new selector in case the window size has changed. selector = get_selector(session.encoding) echo(refresh(selector))