Shorten hint text.
[naja.git] / naja / widgets / info_area.py
index d8e77b9b8103bbbfc6df76f0672b8b8b579ac006..e6c11438cab322ca9b87c0546923d2c4e304dc5b 100644 (file)
@@ -5,32 +5,27 @@ import pygame
 import pygame.locals as pgl
 
 from naja.constants import (
-    INFO_SIZE, ACT, KEYS, EXAMINE, PALETTE,
+    INFO_SIZE, KEYS, PALETTE,
     ACTION_TEXT_OFFSET, INFO_LEFT_PADDING,
     INFO_RIGHT_PADDING, BIT_SIZE, BITS)
-from naja.events import finish_event
+from naja.events import InvalidateTheWorld, finish_event
 from naja.resources import resources
 from naja.resources.mutators import EIGHT_BIT, blender
 from naja.sound import sound
-from naja.utils import bit_glyphs
+from naja.utils import bit_glyphs, Flashlight
 
 from naja.widgets.base import Widget
 from naja.widgets.tile import BIT_MAP
-from naja.widgets.text import TextBoxWidget, TextWidget
+from naja.widgets.text import TextBoxWidget
+from naja import constants
 
 
-HINTS = {
-    ACT: ("Choose an action using the Up/Down keys.\n"
-          "Press Return to execute the action."),
-    EXAMINE: "Select a tile to examine using the arrow keys.",
-}
+HINTS = [
+    "{NORTH,SOUTH,EAST,WEST} to browse tiles.",
+    "TAB to switch actions.",
+]
 
-HINT_LEGAL_MOVE = "\nPress Return to move to this tile."
-
-TITLES = {
-    ACT: "Choose an Action",
-    EXAMINE: "Select a Tile",
-}
+HINT_LEGAL_MOVE = "\n{RETURN} to act."
 
 
 class InfoAreaWidget(Widget):
@@ -40,13 +35,10 @@ class InfoAreaWidget(Widget):
     def __init__(self, pos, state):
         super(InfoAreaWidget, self).__init__(pos, INFO_SIZE)
         self.state = state
-        self.chosen = None
-        self.card_position = state.player.position
-        self.set_position(state.player.position)
+        self.set_position(state.player.position, legal=True)
+        self.flash_light = Flashlight(constants.FPS // 2)
 
     def prepare(self):
-        if self.state.gameboard.player_mode == ACT:
-            self.set_position(self.state.player.position)
         self.surface = pygame.surface.Surface(INFO_SIZE)
         self.surface.fill((0, 0, 0))
 
@@ -54,39 +46,36 @@ class InfoAreaWidget(Widget):
         y_offset = 0
         pos = lambda: (INFO_LEFT_PADDING, y_offset)
 
-        # Top title
-        title = TextWidget(
-            pos(), TITLES[self.state.gameboard.player_mode],
-            colour=PALETTE.WHITE)
-        title.render(self.surface)
-        y_offset += title.surface.get_rect().height - 4
-
         # Bits
+        y_offset += 12
         bits_text = ''.join('1' if bit in self.card.bitwise_operand else '0'
                             for bit in reversed(range(8)))
         if self.card.bitwise_operand:
             bits_text = '%s %s' % (
                 bits_text, bit_glyphs(self.card.bitwise_operand))
         card_bits = TextBoxWidget(
-            pos(), bits_text, box_width=box_width,
-            colour=PALETTE.LIGHT_TURQUOISE, bg_colour=PALETTE.BLACK)
-        card_bits.render(self.surface)
-        y_offset += card_bits.surface.get_rect().height + 4
+            (0, 0), bits_text, padding=4, centre=True,
+            colour=PALETTE.WHITE, border=2,
+            bg_colour=PALETTE.BLACK, border_colour=PALETTE.BLUE,
+            box_width=box_width)
+        card_bits.prepare()
+        self.surface.blit(card_bits.surface, pos())
+        y_offset += card_bits.surface.get_rect().height + 12
 
         # Actions
         for choice, action in enumerate(self.card.actions):
             y_offset = self.prepare_action(choice, action, y_offset, box_width)
 
         # Hint text
-        hint_text = HINTS[self.state.gameboard.player_mode]
-        if self.state.gameboard.player_mode == EXAMINE:
-            if self.card_position in self.state.player.legal_moves():
-                hint_text += HINT_LEGAL_MOVE
+        hint_text = " ".join(HINTS)
+        if self.card_position in self.state.player.legal_moves():
+            hint_text += HINT_LEGAL_MOVE
 
         hint = TextBoxWidget(
             (0, 0), hint_text, padding=4,
-            box_width=box_width,
-            border=2, border_colour=PALETTE.GREY)
+            colour=PALETTE.WHITE, border=2,
+            bg_colour=PALETTE.BLACK, border_colour=PALETTE.BLUE,
+            box_width=box_width)
         hint.prepare()
         y_offset = (INFO_SIZE[1] - hint.surface.get_rect().height
                     - BIT_SIZE[1] - 2)
@@ -108,17 +97,18 @@ class InfoAreaWidget(Widget):
         if gameboard.puzzle:
             return "PUZZLE"
         return {
-            0: "DEATH", 1: "LUDICROUS",
-            2: "RAMBO", 3: "HARD",
+            0: "DEATH", 1: "NINTENDO HARD",
+            2: "VERY HARD", 3: "HARD",
             4: "STANDARD", 5: "EASY",
         }.get(gameboard.max_health, "UNKNOWN")
 
     def prepare_action(self, choice, action, y_offset, box_width):
         x_offset = INFO_LEFT_PADDING
-        glyphs_x_offset = 0
+        glyphs_x_offset = 2
         glyphs_y_offset = y_offset
         y_offset += ACTION_TEXT_OFFSET
-        action_viable = action.check_available(self.state.player)
+        action_viable = (
+            action.check_available(self.state.player) and self.legal)
         text_colour = PALETTE.BLACK if action_viable else PALETTE.GREY
 
         text = TextBoxWidget(
@@ -130,7 +120,13 @@ class InfoAreaWidget(Widget):
 
         border_colour = None
         if choice == self.chosen:
-            border_colour = PALETTE.GREEN if action_viable else PALETTE.ORANGE
+            if self.flash_light.on:
+                border_colour = (PALETTE.GREEN if action_viable else
+                                 PALETTE.ORANGE)
+            else:
+                border_colour = (PALETTE.DARK_GREEN if action_viable else
+                                 PALETTE.DARK_RED)
+
         if border_colour:
             bottom = y_offset + text.surface.get_rect().height
             right = text.surface.get_rect().width + x_offset
@@ -150,6 +146,14 @@ class InfoAreaWidget(Widget):
         else:
             glyphs_x_offset = INFO_LEFT_PADDING
 
+        if BITS.MSB in action.required_bits:
+            msb = resources.get_image('board/msb_lock_decoration.png',
+                                      transforms=(EIGHT_BIT,))
+            msb_rect = msb.get_rect()
+            self.surface.blit(
+                msb, (glyphs_x_offset - msb_rect.width - 4, glyphs_y_offset)
+            )
+
         for glyph in action.get_glyphs():
             img = resources.get_image(
                 glyph, transforms=(EIGHT_BIT, blender(PALETTE.GREY)))
@@ -163,16 +167,16 @@ class InfoAreaWidget(Widget):
 
         return y_offset + text.surface.get_rect().height + 16
 
-    def set_position(self, position):
+    def set_position(self, position, legal):
+        self.legal = legal
         self.card_position = position
         self.card = self.state.board_locations[self.card_position]
-        if self.state.gameboard.player_mode == ACT:
-            if self.chosen is None:
-                self.chosen = 0
-        else:
-            self.chosen = None
+        self.chosen = None
+        self.next_action(viable_only=True)
 
     def draw(self, surface):
+        if self.flash_light.tick():
+            self.prepare()
         surface.blit(self.surface, self.pos)
 
     def next_action(self, viable_only=False, step=1):
@@ -180,44 +184,44 @@ class InfoAreaWidget(Widget):
         if num_actions == 0:
             return
         player = self.state.player
-        chosen = self.chosen
-        for i in range(num_actions - 1):
+        chosen = self.chosen if self.chosen is not None else -step
+        for i in range(num_actions):
             # loop through each action at most once.
             chosen = (chosen + step) % num_actions
             action = self.card.actions[chosen]
             if not viable_only or action.check_available(player):
                 sound.play_sound('zoop.ogg', volume=0.05)
                 self.chosen = chosen
+                break
 
     def prev_action(self, viable_only=False):
         return self.next_action(viable_only=viable_only, step=-1)
 
     def try_perform_action(self):
         player = self.state.player
-        action = self.card.actions[self.chosen]
-        if not action.check_available(player):
+        if self.chosen is None or not self.legal:
+            action = None
+        else:
+            action = self.card.actions[self.chosen]
+        if action is None or not action.check_available(player):
             sound.play_sound('error.ogg')
+            return False
         else:
             sound.play_sound('chirp.ogg', volume=0.5)
+            player.set_position(self.card_position)
             action.perform_action(self.state.gameboard, self.card)
-            self.state.gameboard.card_used(player.position)
-            self.state.gameboard.change_mode(EXAMINE)
-            self.set_position(player.position)
+            self.state.gameboard.card_used(self.card_position)
+            self.set_position(self.card_position, legal=True)
+            return True
 
     def handle_event(self, ev):
-        if self.state.gameboard.player_mode == EXAMINE:
-            return super(InfoAreaWidget, self).handle_event(ev)
+        if InvalidateTheWorld.matches(ev):
+            self.flash_light.reset()
         if ev.type == pgl.KEYDOWN:
-            if ev.key in KEYS.SELECT:
-                self.try_perform_action()
-                return finish_event()
-            if ev.key in KEYS.UP:
-                self.next_action()
-                return finish_event()
-            if ev.key in KEYS.DOWN:
-                self.prev_action()
-                return finish_event()
             if ev.key in KEYS.SWITCH:
                 self.next_action(viable_only=True)
                 return finish_event()
+            elif ev.key in KEYS.SELECT:
+                self.try_perform_action()
+                return finish_event()
         return super(InfoAreaWidget, self).handle_event(ev)