action_class: 'GenericBits'
required_bits: []
data:
+ message: "In this board, tiles didn't change. In the random games, after taking an action (or the timer expires) the tile will be replaced by another one."
set: [NORTH]
clear: [SOUTH, EAST, WEST]
description: "Kasparov to F3"
puzzle: true
+# This field is ignored, but it's a useful place to put some action definitions
+# we can reference later.
+_action_defitions:
+ - &PYRRHIC-VICTORY
+ action_class: GenericBits
+ required_bits: [RED, GREEN, BLUE]
+ data:
+ clear: [NORTH, SOUTH, EAST, WEST, RED, GREEN, BLUE, MSB]
+ acquire_win: true
+ lose_health: true
+ once: true
+
# This field is ignored, but it's a useful place to put some card definitions
# we can reference later.
_card_definitions:
required_bits: []
data:
chesspiece: BISHOP
- - action_class: GenericBits
- required_bits: [RED, GREEN, BLUE]
- data:
- clear: [NORTH, SOUTH, EAST, WEST, RED, GREEN, BLUE, MSB]
- acquire_win: true
- lose_health: true
- once: true
+ - *PYRRHIC-VICTORY
- &CHESS-WIN-CARD-CASTLE
card_name: 'chess-win-rook'
actions:
required_bits: []
data:
chesspiece: CASTLE
- - action_class: AcquireWinToken
- required_bits: [RED, GREEN, BLUE]
- data:
- once: true
+ - *PYRRHIC-VICTORY
- &CHESS-WIN-CARD-KNIGHT
card_name: 'chess-win-knight'
actions:
required_bits: []
data:
chesspiece: KNIGHT
- - action_class: AcquireWinToken
- required_bits: [RED, GREEN, BLUE]
- data:
- once: true
+ - *PYRRHIC-VICTORY
- &CHESS-WIN-CARD-SEPPUKU
card_name: 'chess-win-seppuku'
actions:
- action_class: LoseHealthOrMSB
required_bits: []
- - action_class: AcquireWinToken
- required_bits: [RED, GREEN, BLUE]
- data:
- once: true
+ - *PYRRHIC-VICTORY
- &TEST-BORING
card_name: 'test-boring'
actions:
data:
toggle: [RED]
clear: [NORTH, EAST, WEST]
+ set: [SOUTH]
- &CHESS-SOUTH
card_name: 'chess-south'
bits: [SOUTH, EAST, WEST, RED, GREEN]
data:
toggle: [RED, GREEN]
clear: [SOUTH, EAST, WEST]
+ set: [NORTH]
- &CHESS-EAST
card_name: 'chess-east'
bits: [NORTH, SOUTH, EAST, RED, BLUE]
data:
toggle: [RED, BLUE]
clear: [NORTH, SOUTH, EAST]
-
+ set: [WEST]
- &CHESS-WEST
card_name: 'chess-west'
bits: [NORTH, SOUTH, WEST, BLUE, MSB]
data:
toggle: [BLUE, MSB]
clear: [NORTH, SOUTH, WEST]
+ set: [EAST]
cards:
- *CHESS-WIN-CARD-BISHOP
parts.append("Lose {HEALTH}.")
for template, bits in [
('Set %s.', self.set_bits), ('Clear %s.', self.clear_bits),
- ('Toggle %s', self.toggle_bits)]:
+ ('Toggle %s.', self.toggle_bits)]:
if bits:
parts.append(template % (bit_glyphs(bits)))
if self.once:
if wins_required is None:
wins_required = defaults['wins_required']
+ assert wins_required + max_health == 8
+
# Overriden by command line
if options.initial_bits:
initial_bits = options.initial_bits
'''
from naja.gamestate import GameState
try:
- state = GameState.new(deck=deck, max_health=4, wins_required=4)
+ state = GameState.new(deck=deck)
except:
if options.debug:
raise
box_width=740, view_port=(780, 540)))
def handle_scene_event(self, ev):
- from naja.scenes.menu import MenuScene
+ from naja.scenes.introduction import IntroductionScene
if ev.type == pgl.KEYDOWN and ev.key in KEYS.QUIT:
- SceneChangeEvent.post(MenuScene)
+ SceneChangeEvent.post(IntroductionScene)
return
--- /dev/null
+"""
+Load and save scenes.
+"""
+
+import pygame.locals as pgl
+
+from naja.constants import KEYS
+from naja.events import SceneChangeEvent, LoadGameEvent
+from naja.gamestate import GameState
+from naja.scenes.scene import Scene
+from naja.scenes.howto import HowtoScene
+from naja.widgets.image_box import ImageBox
+from naja.widgets.selector import SelectorWidget
+from naja.widgets.text import TextWidget
+
+
+class IntroductionScene(Scene):
+ def __init__(self, state):
+ super(IntroductionScene, self).__init__(state)
+
+ background = ImageBox(
+ (0, 0), "screens/splash.png")
+ self.add(background)
+
+ selector = SelectorWidget()
+ self.add(selector)
+
+ y_offset, y_diff = 270, 40
+ x_offset = 400
+
+ y_offset += y_diff
+ title = TextWidget(
+ (x_offset, y_offset), 'Getting started', colour='white',
+ centre=True)
+ self.add(title)
+
+ y_offset += y_diff
+ howto = TextWidget(
+ (x_offset, y_offset), 'How to play', colour='white', centre=True)
+ howto.add_callback('click', self.howto_scene)
+ selector.add(howto)
+
+ y_offset += y_diff
+ intro = TextWidget(
+ (x_offset, y_offset), 'Introductory Level', colour='white',
+ centre=True)
+ intro.add_callback('click', self.introduction_level)
+ selector.add(intro)
+
+ y_offset += 2*y_diff
+ back = TextWidget(
+ (x_offset, y_offset), 'Press ESC to return to the main menu.',
+ colour='white', centre=True)
+ self.add(back)
+
+ def howto_scene(self, event):
+ SceneChangeEvent.post(HowtoScene)
+
+ def introduction_level(self, event):
+ from naja.scenes.game import GameScene
+ LoadGameEvent.post(state=GameState.new(deck='introduction'))
+ SceneChangeEvent.post(GameScene)
+
+ def handle_scene_event(self, ev):
+ if ev.type == pgl.KEYDOWN and ev.key in KEYS.QUIT:
+ from naja.scenes.menu import MenuScene
+ SceneChangeEvent.post(MenuScene)
+ return
from naja.scenes.scene import Scene
from naja.scenes.credits import CreditsScene
from naja.scenes.game import GameScene
-from naja.scenes.howto import HowtoScene
+from naja.scenes.introduction import IntroductionScene
from naja.scenes.load_save import LoadGameScene, SaveGameScene
from naja.scenes.new_game import NewGameScene
from naja.scenes.puzzlelist import PuzzleListScene
y_offset, y_diff = 270, 36
x_offset = 400
+ y_offset += y_diff
+ intro = TextWidget(
+ (x_offset, y_offset), 'Introduction', colour=PALETTE.WHITE,
+ centre=True)
+ intro.add_callback('click', self.scene_callback(IntroductionScene))
+ selector.add(intro)
+
y_offset += y_diff
resume = TextWidget(
(x_offset, y_offset), 'Resume Game', colour=PALETTE.WHITE,
resume.set_selectable_callback(lambda: state is not None)
selector.add(resume)
+ if state is None:
+ selector.position = 2
+ else:
+ selector.position = 1
+
y_offset += y_diff
new = TextWidget(
(x_offset, y_offset), 'New Random Game', colour=PALETTE.WHITE,
save.set_selectable_callback(lambda: state is not None)
selector.add(save)
- y_offset += y_diff
- howto = TextWidget(
- (x_offset, y_offset), 'How To Play', colour=PALETTE.WHITE,
- centre=True)
- howto.add_callback('click', self.scene_callback(HowtoScene))
- selector.add(howto)
-
y_offset += y_diff
credits = TextWidget(
(x_offset, y_offset), 'Credits', colour=PALETTE.WHITE,
(x_offset, y_offset), deck['description'], fontsize=32,
colour='white', centre=True)
callback = functools.partial(self.start_puzzle_game,
- puzzle=puzzle, deck=deck)
+ puzzle=puzzle)
puzzle_but.add_callback('click', callback)
selector.add(puzzle_but)
- def start_puzzle_game(self, event, puzzle=None, deck=None):
+ def start_puzzle_game(self, event, puzzle=None):
from naja.scenes.game import GameScene
- max_health = deck.get('max_health', 4)
- wins_required = deck.get('wins_required', 4)
level = 'puzzles/%s' % puzzle
- state = GameState.new(deck=level, max_health=max_health,
- wins_required=wins_required)
+ state = GameState.new(deck=level)
LoadGameEvent.post(state=state)
SceneChangeEvent.post(GameScene)
from naja.constants import (
INFO_SIZE, ACT, KEYS, EXAMINE, PALETTE,
ACTION_TEXT_OFFSET, INFO_LEFT_PADDING,
- INFO_RIGHT_PADDING, BIT_SIZE)
+ INFO_RIGHT_PADDING, BIT_SIZE, BITS)
from naja.events import finish_event
from naja.resources import resources
from naja.resources.mutators import EIGHT_BIT, blender
[(x_offset, y_offset), (right, y_offset),
(right, bottom), (x_offset, bottom)], 4)
- if action.required_bits in BIT_MAP:
- img_name = BIT_MAP[action.required_bits].replace(
+ required_keys = action.required_bits & frozenset([
+ BITS.RED, BITS.GREEN, BITS.BLUE])
+ if required_keys in BIT_MAP:
+ img_name = BIT_MAP[required_keys].replace(
'.png', '_small.png')
img = resources.get_image(img_name,
transforms=(EIGHT_BIT,))
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)))
self.surface.blit(img, (TILE_SIZE[0] - 20, 0))
def _prepare_lock(self, action, y_offset):
- if action.required_bits not in BIT_MAP:
+ required_keys = action.required_bits & frozenset([
+ BITS.RED, BITS.GREEN, BITS.BLUE])
+ if required_keys not in BIT_MAP:
return 4
- img_name = BIT_MAP[action.required_bits]
+ img_name = BIT_MAP[required_keys]
if self.board_pos != self.state.player.position:
x_offset = 0
y_offset += LOCK_HEIGHT - SMALL_LOCK_HEIGHT - 2
img = resources.get_image(img_name, transforms=(EIGHT_BIT,))
+ img_rect = img.get_rect()
self.surface.blit(img, (x_offset, y_offset))
- return x_offset + img.get_width() + 2
+
+ 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, (x_offset + img_rect.width - msb_rect.width, y_offset)
+ )
+
+ return x_offset + img_rect.width + 2
def _prepare_action(self, action, y_offset):
x_offset = self._prepare_lock(action, y_offset)
mkdir build
(cd build; tar xzf ../dist/${BUILD_NAME}.tar.gz)
-echo "[${BUILD_FOLDER}]"
cd ${BUILD_FOLDER}
-echo "$PWD"
echo ""
echo "=== Running python setup.py ==="
cd ${BASEDIR}
-pwd
rm dist/${DMG_NAME} > /dev/null
-echo -e "For some reason the game starts without a foreground window. Click on the icon in the dock (or minimize and restore from the menu) to get it back.\n\nIf this doesn't work, please let me (<firxen@gmail.com>) know, especially if you have any ideas about how to fix it.\n\nYou should also be able to use the unix tarball available at the same place you got this dmg.\n\nThanks." > ${BUILD_FOLDER}/dist/IMPORTANT\ NOTE.txt
+cat > ${BUILD_FOLDER}/dist/IMPORTANT\ NOTE.txt <<EOF
+For some reason the game starts without a foreground window. Click on the icon in the dock (or minimize and restore from the menu) to get it back.
+
+If this doesn't work, please let me (<firxen@gmail.com>) know, especially if you have any ideas about how to fix it.
+
+You should also be able to use the unix tarball available at the same place you got this dmg.
+
+Thanks.
+EOF
hdiutil create -volname ${GAME_NAME} -srcfolder ${BUILD_FOLDER}/dist/*.app/ -srcfolder ${BUILD_FOLDER}/dist/IMPORTANT\ NOTE.txt dist/${DMG_NAME}