示例#1
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
示例#2
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
示例#3
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
示例#4
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
示例#5
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)
示例#6
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()
示例#7
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)
示例#8
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)
示例#9
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)
示例#10
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()
示例#11
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
示例#12
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