Esempio n. 1
0
    def zero(self, rail_h, engine, grid_height, grid_width, cb_ready_alert, cb_grid_alert, cb_mail_alert, cb_over_alert):
        self.rail_h = rail_h
        self.engine = engine
        self.grid_height = grid_height
        self.grid_width = grid_width
        self.cb_grid_alert = cb_grid_alert
        self.cb_mail_alert = cb_mail_alert
        self.cb_ready_alert = cb_ready_alert
        self.cb_over_alert = cb_over_alert

        self.turn = 0
        self.b_game_alive = False

        #
        # coordinate pools
        self.cpool_spare = None
        self.cpool_wall = None
        self.cpool_player = None
        self.cpool_weed = None

        self.supported_directives = None
        self._init_supported_directives()

        self.cgrid = Cgrid(
            height=grid_height,
            width=grid_width)
        self.q_mail_messages = deque()

        self.orb = None
        self._init_orb()

        self.bridge = self.orb.init_autobridge()
        self.bridge.nc_init(
            grid_height=self.grid_height,
            grid_width=self.grid_width)
Esempio n. 2
0
class CogToFormGrid:
    def __init__(self, cog_h, engine, orb):
        self.cog_h = cog_h
        self.engine = engine
        self.orb = orb
        #
        self.track_prime_console = orb.track(TrackPrimeConsole)
        #
        self.form_grid_console = None
        self.cgrid = None

    #
    def on_init(self):
        self.cgrid = Cgrid(width=self.track_prime_console.width,
                           height=self.track_prime_console.height)
        #
        zero_h = '%s/form_grid_console' % (self.cog_h)
        self.form_grid_console = solent_ext(
            ext='solent.ext.windows_form_grid_console',
            zero_h=zero_h,
            cb_grid_console_splat=self.cb_grid_console_splat,
            cb_grid_console_kevent=self.cb_grid_console_kevent,
            cb_grid_console_mevent=self.cb_grid_console_mevent,
            cb_grid_console_closed=self.cb_grid_console_closed,
            engine=self.engine,
            width=self.track_prime_console.width,
            height=self.track_prime_console.height)

    def on_term_clear(self):
        self.cgrid.clear()

    def on_term_put(self, drop, rest, s, cpair):
        self.cgrid.put(drop=drop, rest=rest, s=s, cpair=cpair)

    def on_term_render(self):
        self.form_grid_console.send(cgrid=self.cgrid)

    #
    def cb_grid_console_splat(self, cs_grid_console_splat):
        zero_h = cs_grid_console_splat.zero
        msg = cs_grid_console_splat.msg
        #
        self.nearcast.splat(zero_h=zero_h, msg=msg)

    def cb_grid_console_kevent(self, cs_grid_console_kevent):
        zero_h = cs_grid_console_kevent.zero_h
        keycode = cs_grid_console_kevent.keycode
        #
        log('received keycode %s' % (keycode))
        self.nearcast.keystroke(keycode=keycode)

    def cb_grid_console_mevent(self, cs_grid_console_mevent):
        zero_h = cs_grid_console_mevent.zero_h
        #
        xxx

    def cb_grid_console_closed(self, cs_grid_console_closed):
        zero_h = cs_grid_console_closed.zero_h
        #
        xxx
Esempio n. 3
0
class CogToGridConsole:
    def __init__(self, cog_h, orb, engine):
        self.cog_h = cog_h
        self.orb = orb
        self.engine = engine
        #
        self.track_prime = orb.track(TrackPrime)
        self.track_mob = orb.track(TrackMob)
        #
        self.form_grid_console = None
        self.cgrid = None

    def on_init(self):
        self.cgrid = Cgrid(width=self.track_prime.console_width,
                           height=self.track_prime.console_height)
        #
        zero_h = '%s/form_grid_console' % (self.cog_h)
        self.form_grid_console = solent_ext(
            ext='solent.ext.windows_form_grid_console',
            zero_h=zero_h,
            cb_grid_console_splat=self.cb_grid_console_splat,
            cb_grid_console_kevent=self.cb_grid_console_kevent,
            cb_grid_console_mevent=self.cb_grid_console_mevent,
            cb_grid_console_closed=self.cb_grid_console_closed,
            engine=self.engine,
            width=self.track_prime.console_width,
            height=self.track_prime.console_height)

    def on_render(self):
        self.cgrid.clear()
        for (drop, rest, mob) in self.track_mob.top_mobs():
            s = mob.c
            cpair = mob.cpair
            self.cgrid.put(drop=drop, rest=rest, s=s, cpair=cpair)
        self.form_grid_console.send(self.cgrid)

    #
    def cb_grid_console_splat(self, cs_grid_console_splat):
        zero_h = cs_grid_console_splat.zero
        msg = cs_grid_console_splat.msg
        #
        self.nearcast.splat(zero_h=zero_h, msg=msg)

    def cb_grid_console_kevent(self, cs_grid_console_kevent):
        zero_h = cs_grid_console_kevent.zero_h
        keycode = cs_grid_console_kevent.keycode
        #
        self.nearcast.grid_kevent(keycode=keycode)

    def cb_grid_console_mevent(self, cs_grid_console_mevent):
        zero_h = cs_grid_console_mevent.zero_h
        #
        xxx

    def cb_grid_console_closed(self, cs_grid_console_closed):
        zero_h = cs_grid_console_closed.zero_h
        #
        xxx
Esempio n. 4
0
 def open_console(self, width, height):
     self.width = width
     self.height = height
     self.cgrid = Cgrid(width=width, height=height)
     self.select_cgrid = Cgrid(width=width, height=height)
     self.console = Console(console_type=self.console_type,
                            width=width,
                            height=height)
     self.mode = MODE_STANDARD
Esempio n. 5
0
def should_create_two_simple_grids():
    grid_a = Cgrid(5, 5)
    cgrid_populate(grid_a, '-')
    cgrid_console_print(grid_a)
    #
    grid_b = Cgrid(3, 3)
    cgrid_populate(grid_b, '|')
    cgrid_console_print(grid_b)
    #
    return True
Esempio n. 6
0
 def __init__(self, width, height, font):
     self.width = width
     self.height = height
     self.font = font
     #
     self.internal_cgrid = Cgrid(width=width, height=height)
     (self.cwidth, self.cheight) = font.size('@')
     #
     dim = (width * self.cwidth, height * self.cheight)
     self.screen = pygame.display.set_mode(dim)
Esempio n. 7
0
 def zero(self, rail_h, height, width, cpair_new, cpair_old):
     self.rail_h = rail_h
     self.height = height
     self.width = width
     self.cpair_new = cpair_new
     self.cpair_old = cpair_old
     #
     self.cgrid = Cgrid(
         height=height,
         width=width)
     self.q_lines = deque()
Esempio n. 8
0
 def __init__(self, console, cgrid, title):
     self.console = console
     self.cgrid = cgrid
     self.title = title
     #
     self.b_menu_active = True
     self.game = None
     #
     # Later on we could use something like pyfiglet for this. Better would
     # be a single distinct font, similar to what Gollop did with rebelstar.
     self.title_cgrid = Cgrid(width=len(self.title), height=1)
     self.title_cgrid.put(drop=0, rest=0, s=self.title, cpair=CPAIR_TITLE)
     #
     self.menu = menu_new()
     self.menu_cgrid = None
Esempio n. 9
0
 def on_init(self):
     self.cgrid = Cgrid(width=self.track_prime.console_width,
                        height=self.track_prime.console_height)
     #
     zero_h = '%s/form_grid_console' % (self.cog_h)
     self.form_grid_console = solent_ext(
         ext='solent.ext.windows_form_grid_console',
         zero_h=zero_h,
         cb_grid_console_splat=self.cb_grid_console_splat,
         cb_grid_console_kevent=self.cb_grid_console_kevent,
         cb_grid_console_mevent=self.cb_grid_console_mevent,
         cb_grid_console_closed=self.cb_grid_console_closed,
         engine=self.engine,
         width=self.track_prime.console_width,
         height=self.track_prime.console_height)
Esempio n. 10
0
def main():
    if '--curses' in sys.argv:
        console_type = 'curses'
    elif '--pygame' in sys.argv:
        console_type = 'pygame'
    else:
        print('ERROR: specify either --curses or --pygame')
        sys.exit(1)
    #
    console = None
    try:
        console = Console(console_type=console_type,
                          width=C_GAME_WIDTH,
                          height=C_GAME_HEIGHT)
        #
        cgrid = Cgrid(width=console.width, height=console.height)
        husk = Husk(console=console, cgrid=cgrid, title=TITLE)
        #
        # event loop
        husk.event_loop()
    except SolentQuitException:
        pass
    except:
        traceback.print_exc()
    finally:
        if None != console:
            console.close()
Esempio n. 11
0
def rogue_interaction_new(console, cursor):
    cgrid = Cgrid(width=console.width, height=console.height)
    logbook = logbook_new(capacity=100)
    ob = RogueInteraction(console=console,
                          cursor=cursor,
                          cgrid=cgrid,
                          logbook=logbook)
    return ob
Esempio n. 12
0
 def on_init(self):
     console_height = self.track_prime_console.height
     console_width = self.track_prime_console.width
     #
     if console_height < ROGUEBOX_GAMEBOX_HEIGHT:
         raise Exception("console height %s too small for game height %s."%(
             console_height, ROGUEBOX_GAMEBOX_HEIGHT))
     if console_width < ROGUEBOX_GAMEBOX_WIDTH:
         raise Exception("console width %s too small for game width %s."%(
             console_width, ROGUEBOX_GAMEBOX_WIDTH))
     #
     rail_h = '%s/roguebox'%(self.cog_h)
     self.rail_roguebox.zero(
         rail_h=rail_h,
         engine=self.engine,
         grid_height=ROGUEBOX_GAMEBOX_HEIGHT,
         grid_width=ROGUEBOX_GAMEBOX_WIDTH,
         cb_ready_alert=self._rl_ready_alert,
         cb_grid_alert=self._rl_grid_alert,
         cb_mail_alert=self._rl_mail_alert,
         cb_over_alert=self._rl_over_alert)
     #
     rail_h = '%s/message_feed'%(self.cog_h)
     self.rail_message_feed.zero(
         rail_h=rail_h,
         height=ROGUEBOX_MFEED_HEIGHT,
         width=ROGUEBOX_MFEED_WIDTH,
         cpair_new=solent_cpair('teal'),
         cpair_old=solent_cpair('blue'))
     self.cgrid_last = Cgrid(
         width=console_width,
         height=console_height)
     self.cgrid_next = Cgrid(
         width=console_width,
         height=console_height)
     #
     # sequence the possible directives in the game to the core. this will
     # give this outer core the opportunity to match directives it
     # recognises to keycodes. in the future, you could imagine being able
     # to configure user keystrokes using this data.
     for directive in self.rail_roguebox.get_supported_directives():
         self.nearcast.directive(
             directive_h=directive.h,
             description=directive.description)
Esempio n. 13
0
class GridDisplay(object):
    def __init__(self, width, height, font):
        self.width = width
        self.height = height
        self.font = font
        #
        self.internal_cgrid = Cgrid(width=width, height=height)
        (self.cwidth, self.cheight) = font.size('@')
        #
        dim = (width * self.cwidth, height * self.cheight)
        self.screen = pygame.display.set_mode(dim)

    def update(self, cgrid):
        cur_dim = (self.internal_cgrid.width, self.internal_cgrid.height)
        new_dim = (cgrid.width, cgrid.height)
        if cur_dim != new_dim:
            self.internal_cgrid.set_dimensions(width=cgrid.width,
                                               height=cgrid.height)
        updates = []
        o_spots = self.internal_cgrid.spots
        n_spots = cgrid.spots
        for idx, (o_spot, n_spot) in enumerate(zip(o_spots, n_spots)):
            if not o_spot.compare(n_spot):
                updates.append(idx)
                o_spot.mimic(n_spot)
        for idx in updates:
            spot = self.internal_cgrid.spots[idx]
            (font_fg, font_bg) = MAP_CONST_COLOURS_TO_CPAIR[spot.cpair]
            label = self.font.render(spot.c, 1, font_fg, font_bg)
            #
            drop_pixels = self.cwidth * int(idx % self.internal_cgrid.width)
            rest_pixels = self.cheight * int(idx / self.internal_cgrid.width)
            self.screen.blit(label, (drop_pixels, rest_pixels))
        pygame.display.flip()

    def coords_from_mousepos(self, xpos, ypos):
        '''
        From the supplied pixel dimensions, return the drop and rest of the
        selected grid reference.
        '''
        rest = int(xpos / self.cwidth)
        drop = int(ypos / self.cheight)
        return (drop, rest)
Esempio n. 14
0
def event_loop(console):
    cgrid = Cgrid(
        width=console.width,
        height=console.height)
    cgrid.put(
        drop=console.height-3,
        rest=1,
        s='(Escape to quit)',
        cpair=solent_cpair('white'))
    for (idx, (cpair, name)) in enumerate(solent_cpair_pairs()):
        cgrid.put(
            drop=(5+int(idx/4)),
            rest=(2+int(18*(idx%4))),
            s='%s %s'%(name, cpair),
            cpair=cpair)
    console.screen_update(
        cgrid=cgrid)
    #
    t = 0
    while True:
        keycode = console.async_get_keycode()
        if keycode != None:
            if keycode == solent_keycode('esc'):
                raise SolentQuitException()
            cgrid.put(
                drop=3,
                rest=1,
                s='key %s (%s)  '%(hex(keycode), chr(keycode)),
                cpair=solent_cpair('red'))
        else:
            time.sleep(0.05)
        cgrid.put(
            drop=1,
            rest=1,
            s='loop counter: %s'%(t),
            cpair=solent_cpair('green'))
        console.screen_update(
            cgrid=cgrid)
        t += 1
Esempio n. 15
0
 def zero(self, zero_h, cb_grid_console_splat, cb_grid_console_kevent,
          cb_grid_console_mevent, cb_grid_console_closed, engine, width,
          height):
     self.zero_h = zero_h
     self.cb_grid_console_splat = cb_grid_console_splat
     self.cb_grid_console_kevent = cb_grid_console_kevent
     self.cb_grid_console_mevent = cb_grid_console_mevent
     self.cb_grid_console_closed = cb_grid_console_closed
     self.engine = engine
     self.width = width
     self.height = height
     #
     if self.width > 200 or self.height > 100:
         # Note that width and height are by character, not by screen
         # dimension.
         log("Warning. Have seen crashes as screen dimensions become vast.")
         log('width %s %s' % (self.width, type(self.width)))
         log('height %s %s' % (self.height, type(self.height)))
     #
     self.cgrid = Cgrid(width=width, height=height)
     #
     # Emphasis: do not use named parameters for this, or the variable
     # holding the logger will get garbage-collected. You must directly
     # refer to cc_log.
     # xxx rename api to c_api
     self.api.set_cc_log(cc_log)
     #
     log('impl_grid_console w:%s h:%s' % (self.width, self.height))
     self.api.create_screen(self.width, self.height)
     self.api.process_windows_events()
     #
     self.spin_windows_events = self.engine.init_spin(
         construct=SpinWindowsEvents,
         cb_windows_event_quit=self.cb_windows_event_quit,
         cb_windows_event_kevent=self.cb_windows_event_kevent,
         api=self.api)
Esempio n. 16
0
 def _allocate_menu_cgrid(self):
     '''
     xxx it's garbagey to repreatedly recreate this. create an issue.
     better solution: plot the menu directly to the main cgrid, rather than
     having separate cgrids for title and menu.
     '''
     lines = self.menu.get_lines()
     longest_line = 0
     for l in lines:
         longest_line = max([longest_line, len(l)])
     #
     # prepare the menu border
     self.menu_cgrid = Cgrid(width=longest_line + 4, height=len(lines) + 2)
     horiz = ' ' * (longest_line + 4)
     menu_border_height = len(lines) + 2
     for idx in range(menu_border_height):
         if idx in (0, menu_border_height - 1):
             self.menu_cgrid.put(drop=idx,
                                 rest=0,
                                 s=horiz,
                                 cpair=CPAIR_MENU_BORDER)
         else:
             line = lines[idx - 1]
             self.menu_cgrid.put(drop=idx,
                                 rest=0,
                                 s=' ',
                                 cpair=CPAIR_MENU_BORDER)
             self.menu_cgrid.put(drop=idx,
                                 rest=1,
                                 s=' %s%s ' % (line, ' ' *
                                               (longest_line - len(line))),
                                 cpair=CPAIR_MENU_TEXT)
             self.menu_cgrid.put(drop=idx,
                                 rest=longest_line + 3,
                                 s=' ',
                                 cpair=CPAIR_MENU_BORDER)
Esempio n. 17
0
def create(width, height):
    global CONSOLE
    if None != CONSOLE:
        raise Exception(
            'curses console is singleton. (cannot run more than one)')
    cgrid = Cgrid(width=width, height=height)
    #
    # Weird: it looks like you need to declare the keystroke source before
    # you do screen init. These kind of bizarre ordering problems are the
    # reason that it's good to have this stuff wrapped up in a library:
    # solve the nasty problem, and then facade things so your user doesn't
    # have to think about it.
    keystream = keystream_new(cb_async_get_keycode=curses_async_get_keycode,
                              cb_block_get_keycode=curses_block_get_keycode)
    grid_display = GridDisplay(internal_cgrid=cgrid)
    #
    # Emphasis: see note about regarding keystream: ordering is significant.
    screen_curses_init()

    #
    def on_close():
        screen_curses_exit()
        #
        global CONSOLE
        CONSOLE = None

    CONSOLE = iconsole_new(keystream=keystream,
                           grid_display=grid_display,
                           width=width,
                           height=height,
                           cb_last_lmouseup=lambda: None,
                           cb_last_lmousedown=lambda: None,
                           cb_last_rmouseup=lambda: None,
                           cb_last_rmousedown=lambda: None,
                           cb_close=on_close)
    return CONSOLE
Esempio n. 18
0
def should_copy_fine_despite_us_not_supplying_a_nail_param_to_blit():
    grid_a = Cgrid(5, 5)
    zyx = [chr(i + 65) for i in range(26)]
    zyx.reverse()
    for i in range(25):
        l = zyx[i]
        drop = i / 5
        rest = i % 5
        grid_a.put(drop=drop, rest=rest, s=l.lower(), cpair=DEFAULT_CPAIR)
    #
    grid_b = Cgrid(3, 3)
    grid_b.put(0, 0, '0', DEFAULT_CPAIR)
    grid_b.put(0, 1, '1', DEFAULT_CPAIR)
    grid_b.put(0, 2, '2', DEFAULT_CPAIR)
    grid_b.put(1, 0, '3', DEFAULT_CPAIR)
    grid_b.put(1, 1, '4', DEFAULT_CPAIR)
    grid_b.put(1, 2, '5', DEFAULT_CPAIR)
    grid_b.put(2, 0, '6', DEFAULT_CPAIR)
    grid_b.put(2, 1, '7', DEFAULT_CPAIR)
    grid_b.put(2, 2, '8', DEFAULT_CPAIR)
    #
    grid_a.blit(src_cgrid=grid_b)
    cgrid_console_print(grid_a)
    #
    return True
Esempio n. 19
0
class CogToRoguebox:
    '''
    Contains a roguelike game, and offers controls. The roguelike itself
    is contained to a 23x23 box in the top-left sector.
    Logging is offered in a box next to that.
    '''
    def __init__(self, cog_h, engine, orb):
        self.cog_h = cog_h
        self.engine = engine
        self.orb = orb
        #
        self.track_prime_console = orb.track(TrackPrimeConsole)
        self.track_containment_mode = orb.track(TrackContainmentMode)
        #
        self.rail_roguebox = RailRoguebox()
        self.rail_message_feed = RailMessageFeed()
        self.cgrid_last = None
        self.cgrid_next = None
        self.d_keycode_to_directive = {}
        self.d_control_scheme = {} # (control_scheme_h, directive_h) = keycode
        #
        self.b_game_started = False
        self.b_mail_waiting = False
        self.b_refresh_needed = False
    def orb_turn(self, activity):
        if None == self.rail_roguebox:
            return
        if not self.track_containment_mode.is_focus_on_game():
            return
        if self.b_mail_waiting:
            activity.mark(
                l=self,
                s='mail processing')
            for message in self.rail_roguebox.retrieve_mail():
                self.rail_message_feed.accept(
                    message=message,
                    turn=self.rail_roguebox.get_turn())
            self.b_mail_waiting = False
            self.b_refresh_needed = True
        #
        if self.b_refresh_needed:
            self._diff_display_refresh()
            self.b_refresh_needed = False
    #
    def on_init(self):
        console_height = self.track_prime_console.height
        console_width = self.track_prime_console.width
        #
        if console_height < ROGUEBOX_GAMEBOX_HEIGHT:
            raise Exception("console height %s too small for game height %s."%(
                console_height, ROGUEBOX_GAMEBOX_HEIGHT))
        if console_width < ROGUEBOX_GAMEBOX_WIDTH:
            raise Exception("console width %s too small for game width %s."%(
                console_width, ROGUEBOX_GAMEBOX_WIDTH))
        #
        rail_h = '%s/roguebox'%(self.cog_h)
        self.rail_roguebox.zero(
            rail_h=rail_h,
            engine=self.engine,
            grid_height=ROGUEBOX_GAMEBOX_HEIGHT,
            grid_width=ROGUEBOX_GAMEBOX_WIDTH,
            cb_ready_alert=self._rl_ready_alert,
            cb_grid_alert=self._rl_grid_alert,
            cb_mail_alert=self._rl_mail_alert,
            cb_over_alert=self._rl_over_alert)
        #
        rail_h = '%s/message_feed'%(self.cog_h)
        self.rail_message_feed.zero(
            rail_h=rail_h,
            height=ROGUEBOX_MFEED_HEIGHT,
            width=ROGUEBOX_MFEED_WIDTH,
            cpair_new=solent_cpair('teal'),
            cpair_old=solent_cpair('blue'))
        self.cgrid_last = Cgrid(
            width=console_width,
            height=console_height)
        self.cgrid_next = Cgrid(
            width=console_width,
            height=console_height)
        #
        # sequence the possible directives in the game to the core. this will
        # give this outer core the opportunity to match directives it
        # recognises to keycodes. in the future, you could imagine being able
        # to configure user keystrokes using this data.
        for directive in self.rail_roguebox.get_supported_directives():
            self.nearcast.directive(
                directive_h=directive.h,
                description=directive.description)
    def on_keycode_to_directive(self, control_scheme_h, keycode, directive_h):
        self.d_keycode_to_directive[keycode] = directive_h
        self.d_control_scheme[ (control_scheme_h, directive_h) ] = keycode
    def on_x_game_ready(self):
        self.b_game_started = True
        self.nearcast.o_game_focus()
    def on_o_game_new(self):
        self.rail_message_feed.clear()
        self.rail_roguebox.new_game()
    def on_x_game_mail(self):
        self.b_mail_waiting = True
    def on_x_game_grid(self):
        self.b_refresh_needed = True
    def on_game_input(self, keycode):
        if keycode not in self.d_keycode_to_directive:
            return
        directive_h = self.d_keycode_to_directive[keycode]
        self.rail_roguebox.directive(
            directive_h=directive_h)
        self.rail_message_feed.scroll_past(
            turn=self.rail_roguebox.get_turn()-3)
        self.b_refresh_needed = True
    def on_o_game_focus(self):
        if not self.b_game_started:
            self.nearcast.menu_focus()
            return
        self._full_display_refresh()
    #
    def _rl_ready_alert(self):
        self.nearcast.x_game_ready()
    def _rl_grid_alert(self):
        self.nearcast.x_game_grid()
    def _rl_mail_alert(self):
        self.nearcast.x_game_mail()
    def _rl_over_alert(self):
        self.nearcast.x_game_over()
    #
    def _full_display_refresh(self):
        self.nearcast.term_clear()
        self.cgrid_last.clear()
        self._diff_display_refresh()
    def _diff_display_refresh(self):
        self.rail_roguebox.get_cgrid(
            cgrid=self.cgrid_next,
            nail=ROGUEBOX_GAMEBOX_NAIL,
            peri=ROGUEBOX_GAMEBOX_PERI)
        for idx, message in enumerate(self.rail_message_feed.list_messages()):
            self.cgrid_next.put(
                drop=idx,
                rest=0,
                s=message,
                cpair=solent_cpair('white'))
        #
        for drop in range(self.track_prime_console.height):
            for rest in range(self.track_prime_console.width):
                (old_c, old_cpair) = self.cgrid_last.get(
                    drop=drop,
                    rest=rest)
                (c, cpair) = self.cgrid_next.get(
                    drop=drop,
                    rest=rest)
                if c == old_c and cpair == old_cpair:
                    continue
                self.nearcast.term_write(
                    drop=drop,
                    rest=rest,
                    s=c,
                    cpair=cpair)
        #
        self.cgrid_last.blit(
            src_cgrid=self.cgrid_next)
Esempio n. 20
0
def should_copy_one_grid_onto_another():
    grid_a = Cgrid(5, 5)
    cgrid_populate(grid_a, '*')
    #
    grid_b = Cgrid(3, 3)
    grid_b.put(0, 0, 'a', DEFAULT_CPAIR)
    grid_b.put(0, 1, 'b', DEFAULT_CPAIR)
    grid_b.put(0, 2, 'c', DEFAULT_CPAIR)
    grid_b.put(1, 0, 'd', DEFAULT_CPAIR)
    grid_b.put(1, 1, 'e', DEFAULT_CPAIR)
    grid_b.put(1, 2, 'f', DEFAULT_CPAIR)
    grid_b.put(2, 0, 'g', DEFAULT_CPAIR)
    grid_b.put(2, 1, 'h', DEFAULT_CPAIR)
    grid_b.put(2, 2, 'i', DEFAULT_CPAIR)
    #
    grid_a.blit(grid_b)
    cgrid_console_print(grid_a)
    #
    return True
Esempio n. 21
0
class RailMessageFeed:
    '''
    This accepts text messages, and then renders them to a cgrid. Imagine text
    as it is coming out of an old-fashioned printer, on a feed of paper.

    There are two general use-cases for retrieving data from this:
    * You can call list_messages, and get back a list of current messages
    * You can call get_cgrid, and it will populate your supplied grid
    '''

    def __init__(self):
        pass
    def zero(self, rail_h, height, width, cpair_new, cpair_old):
        self.rail_h = rail_h
        self.height = height
        self.width = width
        self.cpair_new = cpair_new
        self.cpair_old = cpair_old
        #
        self.cgrid = Cgrid(
            height=height,
            width=width)
        self.q_lines = deque()
    def clear(self):
        while self.q_lines:
            self.scroll()
    def accept(self, message, turn):
        nail = 0
        peri = nail+self.width
        while len(message) > peri:
            self._write(
                text=message[nail:peri],
                turn=turn)
            nail = peri
            peri = peri + self.width
        self._write(
            text=message[nail:peri],
            turn=turn)
    def scroll(self):
        self.q_lines.popleft()
    def scroll_past(self, turn):
        while self.q_lines:
            first_pair = self.q_lines[0]
            message_turn = first_pair[1]
            if message_turn <= turn:
                self.scroll()
            else:
                break
    def get_height(self):
        return len(self.q_lines)
    def list_messages(self):
        sb = []
        for (message, turn) in self.q_lines:
            sb.append(message)
        return sb
    def get_cgrid(self, cgrid, nail, peri, turn):
        self.cgrid.clear()
        for idx, (line, mturn) in enumerate(self.q_lines):
            if mturn == turn:
                cpair = self.cpair_new
            else:
                cpair = self.cpair_old
            self.cgrid.put(
                drop=idx,
                rest=0,
                s=line,
                cpair=cpair)
        cgrid.blit(
            self.cgrid,
            nail=nail,
            peri=peri)
    def _write(self, text, turn):
        self.q_lines.append( (text, turn) )
        while len(self.q_lines) > self.height:
            self.q_lines.popleft()
Esempio n. 22
0
def should_do_a_truncated_copy_on_the_right_side():
    grid_a = Cgrid(5, 5)
    zyx = [chr(i + 65) for i in range(26)]
    zyx.reverse()
    for i in range(25):
        l = zyx[i]
        drop = int(i / 5)
        rest = i % 5
        grid_a.put(drop=drop, rest=rest, s=l.lower(), cpair=DEFAULT_CPAIR)
    #
    grid_b = Cgrid(3, 3)
    grid_b.put(0, 0, '0', DEFAULT_CPAIR)
    grid_b.put(0, 1, '1', DEFAULT_CPAIR)
    grid_b.put(0, 2, '2', DEFAULT_CPAIR)
    grid_b.put(1, 0, '3', DEFAULT_CPAIR)
    grid_b.put(1, 1, '4', DEFAULT_CPAIR)
    grid_b.put(1, 2, '5', DEFAULT_CPAIR)
    grid_b.put(2, 0, '6', DEFAULT_CPAIR)
    grid_b.put(2, 1, '7', DEFAULT_CPAIR)
    grid_b.put(2, 2, '8', DEFAULT_CPAIR)
    #
    grid_a.blit(src_cgrid=grid_b, nail=(1, 3))
    cgrid_console_print(grid_a)
    #
    return True
Esempio n. 23
0
class RailRoguebox:
    def __init__(self):
        pass
    def zero(self, rail_h, engine, grid_height, grid_width, cb_ready_alert, cb_grid_alert, cb_mail_alert, cb_over_alert):
        self.rail_h = rail_h
        self.engine = engine
        self.grid_height = grid_height
        self.grid_width = grid_width
        self.cb_grid_alert = cb_grid_alert
        self.cb_mail_alert = cb_mail_alert
        self.cb_ready_alert = cb_ready_alert
        self.cb_over_alert = cb_over_alert

        self.turn = 0
        self.b_game_alive = False

        #
        # coordinate pools
        self.cpool_spare = None
        self.cpool_wall = None
        self.cpool_player = None
        self.cpool_weed = None

        self.supported_directives = None
        self._init_supported_directives()

        self.cgrid = Cgrid(
            height=grid_height,
            width=grid_width)
        self.q_mail_messages = deque()

        self.orb = None
        self._init_orb()

        self.bridge = self.orb.init_autobridge()
        self.bridge.nc_init(
            grid_height=self.grid_height,
            grid_width=self.grid_width)

    def _init_supported_directives(self):
        self.supported_directives = [
            globals()[key] for key
            in globals().keys()
            if key.startswith('DIRECTIVE_')]

    def _init_orb(self):
        i_nearcast = '''
            i message h
                i field h

            message init
                field grid_height
                field grid_width
        '''
        self.orb = self.engine.init_orb(
            i_nearcast=i_nearcast)
        self.orb.set_spin_h('swamp_monster_orb')
        #self.orb.add_log_snoop()

    def get_supported_directives(self):
        '''
        Returns list of instances of solent.rogue.directive representing
        the directives that this instance cares about. The reason for this
        design is that it allows the container to handle input configuration.
        For example, if you want the number 7 to mean north-east, you will
        want to be able to configure that. And it would be a distraction from
        the game engine itself.
        '''
        return self.supported_directives[:]

    def new_game(self):
        self.turn = 0
        self.b_game_alive = True

        self._zero_coord_pools()
        self._create_board()

        self.cb_ready_alert()

        self._announce("You are in the garden. Eliminate those evil weeds!")
        self._announce("[Press ? for help]")

    def _zero_coord_pools(self):
        self.cpool_spare = []
        self.cpool_wall = []
        self.cpool_player = []
        self.cpool_weed = []

        room_width = 10
        room_height = 10
        nail_drop = int( (self.grid_height / 2) - (room_height / 2) )
        nail_rest = int( (self.grid_width / 2) - (room_width / 2) )
        peri_drop = nail_drop + room_width + 1
        peri_rest = nail_rest + room_height + 1
        for drop in range(nail_drop, peri_drop):
            for rest in range(nail_rest, peri_rest):
                self.cpool_spare.append( (drop, rest) )

    def get_turn(self):
        return self.turn

    def get_cgrid(self, cgrid, nail, peri):
        self._render_cgrid()
        cgrid.blit(
            src_cgrid=self.cgrid,
            nail=nail,
            peri=peri)

    def retrieve_mail(self):
        l = []
        while self.q_mail_messages:
            l.append(self.q_mail_messages.popleft())
        return l

    def directive(self, directive_h):
        if directive_h == 'help':
            for line in HELP.split('\n'):
                self._announce(line)
            return
        if False == self.b_game_alive:
            return
        else:
            self.turn += 1

            player_spot = self.cpool_player[0]
            target_spot = list(player_spot)
            if directive_h in 'nw|ww|sw'.split('|'):
                target_spot[1] -= 1
            if directive_h in 'ne|ee|se'.split('|'):
                target_spot[1] += 1
            if directive_h in 'nw|nn|ne'.split('|'):
                target_spot[0] -= 1
            if directive_h in 'sw|ss|se'.split('|'):
                target_spot[0] += 1
            self._player_move(
                player_spot=player_spot,
                target_spot=tuple(target_spot))
            if 0 == len(self.cpool_weed):
                self._announce('You win!')
                self._game_over()

    def _player_move(self, player_spot, target_spot):
        if target_spot in self.cpool_spare:
            self.cpool_player.remove(player_spot)
            self.cpool_spare.append(player_spot)
            self.cpool_spare.remove(target_spot)
            self.cpool_player.append(target_spot)
            self.cb_grid_alert()
            return
        elif target_spot in self.cpool_weed:
            self._announce(
                message='You slash angrily at the weed!')
            self.cpool_player.remove(player_spot)
            self.cpool_spare.append(player_spot)
            self.cpool_weed.remove(target_spot)
            self.cpool_player.append(target_spot)
            self.cb_grid_alert()

    def _announce(self, message):
        self.q_mail_messages.append(message)
        self.cb_mail_alert()

    def _game_over(self):
        self.b_game_alive = False
        self.cb_over_alert()

    def _create_board(self):
        coord = ( int(self.grid_height/2), int(self.grid_width/2) )
        self.cpool_spare.remove(coord)
        self.cpool_player.append(coord)
        #
        # create the walls
        room_width = 10
        room_height = 10
        nail_drop = int( (self.grid_height / 2) - (room_height / 2) )
        nail_rest = int( (self.grid_width / 2) - (room_width / 2) )
        peri_drop = nail_drop + room_width + 1
        peri_rest = nail_rest + room_height + 1
        # horizontal walls, including corners
        for rest in range(nail_rest, peri_rest):
            coord = (nail_drop, rest)
            self.cpool_spare.remove(coord)
            self.cpool_wall.append(coord)
            coord = (nail_drop+room_height, rest)
            self.cpool_spare.remove(coord)
            self.cpool_wall.append(coord)
        # vertical walls, except corners
        for drop in range(nail_drop+1, peri_drop-1):
            coord = (drop, nail_rest)
            self.cpool_spare.remove(coord)
            self.cpool_wall.append(coord)
            coord = (drop, nail_rest+room_width)
            self.cpool_spare.remove(coord)
            self.cpool_wall.append(coord)
        #
        # place weeds
        # (we need at least one.)
        while not self.cpool_weed:
            for coord in self.cpool_spare:
                (drop, rest) = coord
                if drop < 8 or drop > 16:
                    continue
                if rest < 34 or rest > 46:
                    continue
                if random.random() > 0.98:
                    self.cpool_spare.remove(coord)
                    self.cpool_weed.append(coord)

    def _render_cgrid(self):
        self.cgrid.clear()
        for coord in self.cpool_spare:
            (drop, rest) = coord
            (c, cpair) = (' ', solent_cpair('teal'))
            self.cgrid.put(
                drop=drop,
                rest=rest,
                s=c,
                cpair=cpair)
        for coord in self.cpool_wall:
            (drop, rest) = coord
            (c, cpair) = PAIR_WALL
            self.cgrid.put(
                drop=drop,
                rest=rest,
                s=c,
                cpair=cpair)
        for coord in self.cpool_player:
            (drop, rest) = coord
            (c, cpair) = PAIR_PLAYER
            if not self.b_game_alive:
                cpair = solent_cpair('blue')
            self.cgrid.put(
                drop=drop,
                rest=rest,
                s=c,
                cpair=cpair)
        for coord in self.cpool_weed:
            (drop, rest) = coord
            (c, cpair) = PAIR_WEED
            self.cgrid.put(
                drop=drop,
                rest=rest,
                s=c,
                cpair=cpair)
Esempio n. 24
0
class SpinSelectionUi:
    def __init__(self, spin_h, engine, console_type, cb_selui_keycode,
                 cb_selui_lselect):
        self.spin_h = spin_h
        self.engine = engine
        self.console_type = console_type
        self.cb_selui_keycode = cb_selui_keycode
        self.cb_selui_lselect = cb_selui_lselect
        #
        self.cs_selui_keycode = CsSeluiKeycode()
        self.cs_selui_lselect = CsSeluiLselect()
        #
        self.width = None
        self.height = None
        self.cgrid = None
        self.mode = MODE_NONE
        self.console = None
        self.select_cursor_on = True
        self.select_cursor_t100 = time.time() * 100
        self.select_drop = 0
        self.select_rest = 0
        self.select_cgrid = None
        #
        self.lmousedown_coords = None

    #
    def eng_turn(self, activity):
        if self.mode == MODE_NONE:
            return
        #
        keycode = self.console.async_get_keycode()
        if keycode:
            activity.mark(l=self, s='received keystroke %s' % keycode)
            if keycode == solent_keycode('lmousedown'):
                self.lmousedown_coords = self.console.get_last_lmousedown()
            elif keycode == solent_keycode('lmouseup'):
                self.lmouseup_coords = self.console.get_last_lmouseup()
            elif keycode == solent_keycode('rmousedown'):
                self.rmousedown_coords = self.console.get_last_rmousedown()
            elif keycode == solent_keycode('rmouseup'):
                self.rmouseup_coords = self.console.get_last_rmouseup()
            self.accept_key(keycode=keycode)
        #
        self.refresh_console()

    def eng_close(self):
        if None != self.console:
            self.console.close()

    #
    def open_console(self, width, height):
        self.width = width
        self.height = height
        self.cgrid = Cgrid(width=width, height=height)
        self.select_cgrid = Cgrid(width=width, height=height)
        self.console = Console(console_type=self.console_type,
                               width=width,
                               height=height)
        self.mode = MODE_STANDARD

    def close_console(self):
        if not self.console:
            return
        self.console.close()
        self.mode = MODE_NONE
        self.select_drop = 0
        self.select_rest = 0

    def to_mode_standard(self):
        if None == self.console:
            raise Exception("No console open")
        self.mode = MODE_STANDARD

    def to_mode_select(self):
        if None == self.console:
            raise Exception("No console open")
        self.mode = MODE_SELECT
        self.select_cursor_on = True
        self.select_cursor_t100 = time.time() * 100

    def scroll(self):
        self.cgrid.scroll()

    def clear(self):
        self.cgrid.clear()

    def write(self, drop, rest, s, cpair):
        self.cgrid.put(drop=drop, rest=rest, s=s, cpair=cpair)

    def accept_key(self, keycode):
        '''
        By making this an exposed command, we can allow the console to be used
        as a display with input coming from elsewhere.
        '''
        if self.mode == MODE_SELECT:
            if keycode == solent_keycode('esc'):
                self.to_mode_standard()
            elif keycode in (solent_keycode('newline'), solent_keycode('s')):
                (c, cpair) = self.cgrid.get(drop=self.select_drop,
                                            rest=self.select_rest)
                self._call_selui_lselect(drop=self.select_drop,
                                         rest=self.select_rest,
                                         c=c,
                                         cpair=cpair)
                self.to_mode_standard()
            else:
                # we let the user navigate the cursor using arrow keys, vi
                # keys, gollop keys.
                b_moved = False
                # standard navigation
                if keycode in (solent_keycode('q'), solent_keycode('a'),
                               solent_keycode('z'), solent_keycode('y'),
                               solent_keycode('h'), solent_keycode('b')):
                    if self.select_rest > 0:
                        self.select_rest -= 1
                    b_moved = True
                if keycode in (solent_keycode('e'), solent_keycode('d'),
                               solent_keycode('c'), solent_keycode('u'),
                               solent_keycode('l'), solent_keycode('n')):
                    if self.select_rest < self.width - 1:
                        self.select_rest += 1
                    b_moved = True
                if keycode in (solent_keycode('q'), solent_keycode('w'),
                               solent_keycode('e'), solent_keycode('y'),
                               solent_keycode('k'), solent_keycode('u')):
                    if self.select_drop > 0:
                        self.select_drop -= 1
                    b_moved = True
                if keycode in (solent_keycode('z'), solent_keycode('x'),
                               solent_keycode('c'), solent_keycode('b'),
                               solent_keycode('j'), solent_keycode('n')):
                    if self.select_drop < self.height - 1:
                        self.select_drop += 1
                    b_moved = True
                # shift navigation
                if keycode in (solent_keycode('Q'), solent_keycode('A'),
                               solent_keycode('Z'), solent_keycode('Y'),
                               solent_keycode('H'), solent_keycode('B')):
                    self.select_rest = 0
                    b_moved = True
                if keycode in (solent_keycode('E'), solent_keycode('D'),
                               solent_keycode('C'), solent_keycode('U'),
                               solent_keycode('L'), solent_keycode('N')):
                    self.select_rest = self.width - 1
                    b_moved = True
                if keycode in (solent_keycode('Q'), solent_keycode('W'),
                               solent_keycode('E'), solent_keycode('Y'),
                               solent_keycode('K'), solent_keycode('U')):
                    self.select_drop = 0
                    b_moved = True
                if keycode in (solent_keycode('Z'), solent_keycode('X'),
                               solent_keycode('C'), solent_keycode('B'),
                               solent_keycode('J'), solent_keycode('N')):
                    self.select_drop = self.height - 1
                    b_moved = True
                #
                if b_moved:
                    self.select_cursor_on = True
                    self.select_cursor_t100 = time.time() * 100
        elif self.mode == MODE_STANDARD:
            if keycode == solent_keycode('esc'):
                self.to_mode_select()
            else:
                if keycode == solent_keycode('lmouseup'):
                    # We check to see that the coords were the same as
                    # when the mouse was depressed. If they weren't, this
                    # usually implies the user has rethought their
                    # decision, and we abort. From memory, this is how FTL
                    # works, and it's super-useful.
                    (ddrop, drest) = self.lmousedown_coords
                    (udrop, urest) = self.lmouseup_coords
                    if (ddrop, drest) == (udrop, urest):
                        (c, cpair) = self.cgrid.get(drop=udrop, rest=urest)
                        self._call_selui_lselect(drop=udrop,
                                                 rest=urest,
                                                 c=c,
                                                 cpair=cpair)
                elif keycode in MOUSE_EVENTS:
                    pass
                else:
                    # we pass the keystroke back in a callback
                    self._call_selui_keycode(keycode=keycode)

    def refresh_console(self):
        if self.mode == MODE_NONE:
            pass
        elif self.mode == MODE_SELECT:
            # cursor flipping
            t100 = time.time() * 100
            if t100 - self.select_cursor_t100 > 53:
                self.select_cursor_t100 = t100
                if self.select_cursor_on:
                    self.select_cursor_on = False
                else:
                    self.select_cursor_on = True
            # cursor display
            self.select_cgrid.blit(src_cgrid=self.cgrid)
            if self.select_cursor_on:
                self.select_cgrid.put(drop=self.select_drop,
                                      rest=self.select_rest,
                                      s='@',
                                      cpair=solent_cpair('red'))
            self.console.screen_update(cgrid=self.select_cgrid)
        elif self.mode == MODE_STANDARD:
            self.console.screen_update(cgrid=self.cgrid)

    #
    def _call_selui_keycode(self, keycode):
        self.cs_selui_keycode.keycode = keycode
        self.cb_selui_keycode(cs_selui_keycode=self.cs_selui_keycode)

    def _call_selui_lselect(self, drop, rest, c, cpair):
        self.cs_selui_lselect.drop = drop
        self.cs_selui_lselect.rest = rest
        self.cs_selui_lselect.c = c
        self.cs_selui_lselect.cpair = cpair
        self.cb_selui_lselect(cs_selui_lselect=self.cs_selui_lselect)
Esempio n. 25
0
def husk_new(console):
    cgrid = Cgrid(width=console.width, height=console.height)
    ob = Husk(console=console, cgrid=cgrid, title=TITLE)
    return ob
Esempio n. 26
0
class ImplGridConsole:
    def __init__(self):
        self.form = FormGridConsole(self)
        #
        clib = load_clib(self)
        #
        self.api = Ns()
        self.api.set_cc_log = init_ext_fn(None, clib.set_cc_log, [CC_LOG_T])
        self.api.create_screen = init_ext_fn(None, clib.create_screen,
                                             [c_int, c_int])
        self.api.process_windows_events = init_ext_fn(
            c_int, clib.process_windows_events, [])
        self.api.get_next_event = init_ext_fn(None, clib.get_next_event,
                                              [c_uint64_p])
        self.api.set = init_ext_fn(None, clib.set,
                                   [c_int, c_int, c_int, c_int])
        self.api.redraw = init_ext_fn(None, clib.redraw, [])
        self.api.close = init_ext_fn(None, clib.close, [])

    def zero(self, zero_h, cb_grid_console_splat, cb_grid_console_kevent,
             cb_grid_console_mevent, cb_grid_console_closed, engine, width,
             height):
        self.zero_h = zero_h
        self.cb_grid_console_splat = cb_grid_console_splat
        self.cb_grid_console_kevent = cb_grid_console_kevent
        self.cb_grid_console_mevent = cb_grid_console_mevent
        self.cb_grid_console_closed = cb_grid_console_closed
        self.engine = engine
        self.width = width
        self.height = height
        #
        if self.width > 200 or self.height > 100:
            # Note that width and height are by character, not by screen
            # dimension.
            log("Warning. Have seen crashes as screen dimensions become vast.")
            log('width %s %s' % (self.width, type(self.width)))
            log('height %s %s' % (self.height, type(self.height)))
        #
        self.cgrid = Cgrid(width=width, height=height)
        #
        # Emphasis: do not use named parameters for this, or the variable
        # holding the logger will get garbage-collected. You must directly
        # refer to cc_log.
        # xxx rename api to c_api
        self.api.set_cc_log(cc_log)
        #
        log('impl_grid_console w:%s h:%s' % (self.width, self.height))
        self.api.create_screen(self.width, self.height)
        self.api.process_windows_events()
        #
        self.spin_windows_events = self.engine.init_spin(
            construct=SpinWindowsEvents,
            cb_windows_event_quit=self.cb_windows_event_quit,
            cb_windows_event_kevent=self.cb_windows_event_kevent,
            api=self.api)

    def cb_windows_event_quit(self, cs_windows_event_quit):
        zero_h = cs_windows_event_quit.zero_h
        #
        raise SolentQuitException()

    def cb_windows_event_kevent(self, cs_windows_event_kevent):
        zero_h = cs_windows_event_kevent.zero_h
        k = cs_windows_event_kevent.k
        #
        # xxx we will need to do some translation here from windows-style
        # keycodes to solent style. for the moment I am just passing back the
        # raw values.
        keycode = k
        self.form.call_grid_console_kevent(zero_h=self.zero_h, keycode=keycode)

    #
    def send(self, cgrid):
        cur_dim = (self.cgrid.width, self.cgrid.height)
        new_dim = (cgrid.width, cgrid.height)
        if cur_dim != new_dim:
            self.cgrid.set_dimensions(width=cgrid.width, height=cgrid.height)
        updates = []
        o_spots = self.cgrid.spots
        n_spots = cgrid.spots
        for cgrid_idx, (o_spot, n_spot) in enumerate(zip(o_spots, n_spots)):
            if not o_spot.compare(n_spot):
                updates.append(cgrid_idx)
                o_spot.mimic(n_spot)
        log('send')
        for cgrid_idx in updates:
            spot = self.cgrid.spots[cgrid_idx]
            #
            drop = int(cgrid_idx / self.cgrid.width)
            rest = int(cgrid_idx % self.cgrid.width)
            c = ord(spot.c)
            o = 0  # xxx
            log('update %s %s %s %s' % (drop, rest, c, o))
            self.api.set(drop, rest, c, o)
        self.api.redraw()

    def close(self):
        log('close')
        return self.api.close()
Esempio n. 27
0
class RailMessageFeed:
    def __init__(self):
        pass
    def zero(self, rail_h, height, width, cpair_new, cpair_old):
        self.rail_h = rail_h
        self.height = height
        self.width = width
        self.cpair_new = cpair_new
        self.cpair_old = cpair_old
        #
        self.cgrid = Cgrid(
            height=height,
            width=width)
        self.q_lines = deque()
    def clear(self):
        while self.q_lines:
            self.scroll()
    def accept(self, message, turn):
        nail = 0
        peri = nail+self.width
        while len(message) > peri:
            self._write(
                text=message[nail:peri],
                turn=turn)
            nail = peri
            peri = peri + self.width
        self._write(
            text=message[nail:peri],
            turn=turn)
    def scroll(self):
        self.q_lines.popleft()
    def scroll_past(self, turn):
        while self.q_lines:
            first_pair = self.q_lines[0]
            message_turn = first_pair[1]
            if message_turn <= turn:
                self.scroll()
            else:
                break
    def get_height(self):
        return len(self.q_lines)
    def list_messages(self):
        sb = []
        for (message, turn) in self.q_lines:
            sb.append(message)
        return sb
    def get_cgrid(self, cgrid, nail, peri, turn):
        self.cgrid.clear()
        for idx, (line, mturn) in enumerate(self.q_lines):
            if mturn == turn:
                cpair = self.cpair_new
            else:
                cpair = self.cpair_old
            self.cgrid.put(
                drop=idx,
                rest=0,
                s=line,
                cpair=cpair)
        cgrid.blit(
            self.cgrid,
            nail=nail,
            peri=peri)
    def _write(self, text, turn):
        self.q_lines.append( (text, turn) )
        while len(self.q_lines) > self.height:
            self.q_lines.popleft()
Esempio n. 28
0
class Husk(object):
    def __init__(self, console, cgrid, title):
        self.console = console
        self.cgrid = cgrid
        self.title = title
        #
        self.b_menu_active = True
        self.game = None
        #
        # Later on we could use something like pyfiglet for this. Better would
        # be a single distinct font, similar to what Gollop did with rebelstar.
        self.title_cgrid = Cgrid(width=len(self.title), height=1)
        self.title_cgrid.put(drop=0, rest=0, s=self.title, cpair=CPAIR_TITLE)
        #
        self.menu = menu_new()
        self.menu_cgrid = None

    #
    def _generate_menu_content(self):
        def mi_new_game():
            print('xxx new game')
            self.game = game_new(console=self.console)
            self.b_menu_active = False

        def mi_load_game():
            print('xxx __mi_load_game')

        def mi_continue_game():
            print('xxx continue game')
            self.b_menu_active = False

        def mi_save_game():
            print('xxx __mi_save_game')

        def mi_quit():
            raise SolentQuitException()

        self.menu.clear()
        if None != self.game:
            self.menu.add('c', 'continue', mi_continue_game)
            self.menu.add('s', 'save', mi_save_game)
        self.menu.add('l', 'load', mi_load_game)
        self.menu.add('n', 'new', mi_new_game)
        self.menu.add('q', 'quit', mi_quit)

    def _allocate_menu_cgrid(self):
        '''
        xxx it's garbagey to repreatedly recreate this. create an issue.
        better solution: plot the menu directly to the main cgrid, rather than
        having separate cgrids for title and menu.
        '''
        lines = self.menu.get_lines()
        longest_line = 0
        for l in lines:
            longest_line = max([longest_line, len(l)])
        #
        # prepare the menu border
        self.menu_cgrid = Cgrid(width=longest_line + 4, height=len(lines) + 2)
        horiz = ' ' * (longest_line + 4)
        menu_border_height = len(lines) + 2
        for idx in range(menu_border_height):
            if idx in (0, menu_border_height - 1):
                self.menu_cgrid.put(drop=idx,
                                    rest=0,
                                    s=horiz,
                                    cpair=CPAIR_MENU_BORDER)
            else:
                line = lines[idx - 1]
                self.menu_cgrid.put(drop=idx,
                                    rest=0,
                                    s=' ',
                                    cpair=CPAIR_MENU_BORDER)
                self.menu_cgrid.put(drop=idx,
                                    rest=1,
                                    s=' %s%s ' % (line, ' ' *
                                                  (longest_line - len(line))),
                                    cpair=CPAIR_MENU_TEXT)
                self.menu_cgrid.put(drop=idx,
                                    rest=longest_line + 3,
                                    s=' ',
                                    cpair=CPAIR_MENU_BORDER)

    def _render_title(self):
        self.cgrid.blit(src_cgrid=self.title_cgrid, nail=(0, 0))

    def _render_menu(self):
        menu_drop = int((self.cgrid.height / 2) - (self.menu_cgrid.height / 2))
        menu_rest = int((self.cgrid.width / 2) - (self.menu_cgrid.width / 2))
        nail = (menu_drop, menu_rest)
        self.cgrid.blit(src_cgrid=self.menu_cgrid, nail=nail)

    def _render(self):
        self._generate_menu_content()
        self._allocate_menu_cgrid()
        self._render_title()
        self._render_menu()
        self.console.screen_update(cgrid=self.cgrid)

    #
    def event_loop(self):
        self._render()
        while True:
            #
            # Defensive
            if self.game == None:
                self.b_menu_active = True
            #
            # Input
            if self.b_menu_active:
                keycode = self.console.block_get_keycode()
            elif self.game != None and self.game.player_mind.is_blocking():
                keycode = self.console.block_get_keycode()
            else:
                keycode = self.console.async_get_keycode()
            b_key = True
            if keycode == None:
                b_key = False
            #
            # Menu
            if self.b_menu_active:
                if b_key:
                    if keycode == solent_keycode('tab') and self.game != None:
                        self.b_menu_active = False
                        keycode = None
                    elif self.menu.has_key(chr(keycode)):
                        fn = self.menu.get_callback(chr(keycode))
                        fn()
                        keycode = None
            else:
                if b_key:
                    if keycode == solent_keycode('tab'):
                        self.b_menu_active = True
                        keycode = None
                        self._render()
                        continue
                    else:
                        self.game.accept_key(key=chr(keycode))
                        keycode = None
            #
            # Update display.
            if self.b_menu_active:
                self._render()
            else:
                activity = self.game.turn()
                if activity:
                    time.sleep(0.05)
                if not activity:
                    time.sleep(0.1)