From eccb327f1260b9aa981755840e097d5b23af05a9 Mon Sep 17 00:00:00 2001 From: Jeremy Thurgood Date: Sun, 11 May 2014 16:17:51 +0200 Subject: [PATCH] Start of some game board stuff. --- naja/attrdict.py | 4 ++ naja/constants.py | 25 ++++++---- naja/gameboard.py | 92 ++++++++++++++++++++++++++++++++++++ naja/options.py | 7 +-- naja/tests/test_gameboard.py | 22 +++++++++ naja/tests/test_player.py | 43 +++++++++-------- 6 files changed, 158 insertions(+), 35 deletions(-) create mode 100644 naja/attrdict.py create mode 100644 naja/gameboard.py create mode 100644 naja/tests/test_gameboard.py diff --git a/naja/attrdict.py b/naja/attrdict.py new file mode 100644 index 0000000..3bdae4e --- /dev/null +++ b/naja/attrdict.py @@ -0,0 +1,4 @@ +class AttrDict(dict): + '''A dict with attribute access''' + def __getattr__(self, attr): + return self[attr] diff --git a/naja/constants.py b/naja/constants.py index 0dc6b84..25a8cfc 100644 --- a/naja/constants.py +++ b/naja/constants.py @@ -1,3 +1,6 @@ +from naja.attrdict import AttrDict + + SCREEN = (800, 600) FPS = 40 FONT = 'DejaVuSans.ttf' @@ -18,11 +21,17 @@ DEFAULT_SOUND_VOLUME = 1.0 # sound volume DEFAULT_MUSIC_VOLUME = 0.3 # music volume # Player bits -NORTH = 0 -SOUTH = 1 -EAST = 2 -WEST = 3 -CYAN = 4 -MAGENTA = 5 -YELLOW = 6 -MSB = 7 +BITS = AttrDict({ + # Direction bits + 'NORTH': 0, + 'SOUTH': 1, + 'EAST': 2, + 'WEST': 3, + # Condition bits + 'CYAN': 4, + 'MAGENTA': 5, + 'YELLOW': 6, + 'MSB': 7, +}) +DIRECTION_BITS = AttrDict((k, v) for k, v in BITS.items() if v < 4) +CONDITION_BITS = AttrDict((k, v) for k, v in BITS.items() if v >= 4) diff --git a/naja/gameboard.py b/naja/gameboard.py new file mode 100644 index 0000000..a107b16 --- /dev/null +++ b/naja/gameboard.py @@ -0,0 +1,92 @@ +from random import choice + +from naja.constants import BITS, DIRECTION_BITS, CONDITION_BITS + + +class GameBoard(object): + """ + A representation of the game board. + """ + + def __init__(self, player, health, wins, locations=None, state=None): + self.player = player + self.max_health = health + self.wins_required = wins + + if locations is None: + locations = self.generate_locations() + self.locations = locations + + if state is None: + state = self.generate_state() + self.update_state(state) + + @classmethod + def generate_locations(cls): + raise NotImplementedError("TODO") + + def generate_state(self): + return { + 'health': self.max_health, + 'wins': 0, + } + + +class LocationCard(object): + """ + A particular set of options available on a location. + """ + + def __init__(self, bitwise_operation, bitwise_operand, actions): + self.bitwise_operation = bitwise_operation + self.bitwise_operand = bitwise_operand + self.actions = actions + + @staticmethod + def generate_location(): + raise NotImplementedError("TODO") + + @staticmethod + def generate_bitwise_operand(): + """ + Generate a set of two or three bits. At least one direction and one + condition bit will be included. There is a low probability of choosing + a third bit from the complete set. + """ + bits = set() + bits.add(choice(DIRECTION_BITS.values())) + bits.add(choice(CONDITION_BITS.values())) + # One in three chance of adding a third bit, with a further one in four + # chance that it will match a bit already chosen. + if choice(range(3)) == 0: + bits.add(choice(BITS.values())) + return frozenset(bits) + + @staticmethod + def generate_location_actions(): + raise NotImplementedError("TODO") + + def apply_bitwise_operation(self, player): + operator = { + 'SET': player.bits.set_bits, + 'CLEAR': player.bits.clear_bits, + 'TOGGLE': player.bits.toggle_bits, + }[self.bitwise_operation] + operator(self.bitwise_operand) + + +class LocationAction(object): + """ + An action that may be performed on a location. + """ + + REQUIRED_BITS = frozenset() + + def __init__(self, **data): + self.data = data + + def check_available(self, player): + return player.bits.check_bits(self.REQUIRED_BITS) + + def perform_action(self, player, board): + raise NotImplementedError("TODO") diff --git a/naja/options.py b/naja/options.py index cf5715d..816d91c 100644 --- a/naja/options.py +++ b/naja/options.py @@ -1,15 +1,10 @@ import optparse import os +from naja.attrdict import AttrDict from naja.constants import DEFAULTS -class AttrDict(dict): - '''A dict with attribute access''' - def __getattr__(self, attr): - return self[attr] - - options = AttrDict() diff --git a/naja/tests/test_gameboard.py b/naja/tests/test_gameboard.py new file mode 100644 index 0000000..a895e18 --- /dev/null +++ b/naja/tests/test_gameboard.py @@ -0,0 +1,22 @@ +from unittest import TestCase + +from naja.constants import BITS +from naja.gameboard import LocationCard + + +class TestLocationCard(TestCase): + def test_generate_bitwise_operand(self): + # This is testing a random process, so it may fail occasionally. + operand_sets = [] + for _ in range(100): + operand_sets.append(LocationCard.generate_bitwise_operand()) + sizes = {2: 0, 3: 0} + bits = set() + for operand_set in operand_sets: + sizes[len(operand_set)] += 1 + bits.update(operand_set) + # TODO: Test that there's at least one condition and one direction. + self.assertTrue(sizes[2] > 0) + self.assertTrue(sizes[3] > 0) + self.assertTrue(sizes[2] > sizes[3]) + self.assertEqual(bits, set(BITS.values())) diff --git a/naja/tests/test_player.py b/naja/tests/test_player.py index 48b2ef8..8373eee 100644 --- a/naja/tests/test_player.py +++ b/naja/tests/test_player.py @@ -1,6 +1,6 @@ from unittest import TestCase -from naja.constants import NORTH, SOUTH, CYAN, MSB +from naja.constants import BITS from naja.player import PlayerBits @@ -23,63 +23,64 @@ class TestPlayerBits(TestCase): def test_check_bit(self): bits = PlayerBits(0x01) - self.assertEqual(bits.check_bit(NORTH), True) - self.assertEqual(bits.check_bit(SOUTH), False) + self.assertEqual(bits.check_bit(BITS.NORTH), True) + self.assertEqual(bits.check_bit(BITS.SOUTH), False) def test_set_bit(self): bits = PlayerBits(0x00) self.assertEqual(bits._bits, 0x00) - bits.set_bit(NORTH) + bits.set_bit(BITS.NORTH) self.assertEqual(bits._bits, 0x01) - bits.set_bit(NORTH) + bits.set_bit(BITS.NORTH) self.assertEqual(bits._bits, 0x01) def test_clear_bit(self): bits = PlayerBits(0x01) self.assertEqual(bits._bits, 0x01) - bits.clear_bit(NORTH) + bits.clear_bit(BITS.NORTH) self.assertEqual(bits._bits, 0x00) - bits.clear_bit(NORTH) + bits.clear_bit(BITS.NORTH) self.assertEqual(bits._bits, 0x00) def test_toggle_bit(self): bits = PlayerBits(0x00) self.assertEqual(bits._bits, 0x00) - bits.toggle_bit(NORTH) + bits.toggle_bit(BITS.NORTH) self.assertEqual(bits._bits, 0x01) - bits.toggle_bit(NORTH) + bits.toggle_bit(BITS.NORTH) self.assertEqual(bits._bits, 0x00) def test_check_bits(self): bits = PlayerBits(0x03) - self.assertEqual(bits.check_bits(NORTH), True) - self.assertEqual(bits.check_bits(NORTH, SOUTH), True) - self.assertEqual(bits.check_bits(CYAN), False) - self.assertEqual(bits.check_bits(CYAN, MSB), False) - self.assertEqual(bits.check_bits(NORTH, SOUTH, CYAN), False) + self.assertEqual(bits.check_bits(BITS.NORTH), True) + self.assertEqual(bits.check_bits(BITS.NORTH, BITS.SOUTH), True) + self.assertEqual(bits.check_bits(BITS.CYAN), False) + self.assertEqual(bits.check_bits(BITS.CYAN, BITS.MSB), False) + self.assertEqual( + bits.check_bits(BITS.NORTH, BITS.SOUTH, BITS.CYAN), False) def test_set_bits(self): bits = PlayerBits(0x03) self.assertEqual(bits._bits, 0x03) - bits.set_bits(NORTH, CYAN) + bits.set_bits(BITS.NORTH, BITS.CYAN) self.assertEqual(bits._bits, 0x13) - bits.set_bits(NORTH, CYAN, MSB) + bits.set_bits(BITS.NORTH, BITS.CYAN, BITS.MSB) self.assertEqual(bits._bits, 0x93) def test_clear_bits(self): bits = PlayerBits(0x03) self.assertEqual(bits._bits, 0x03) - bits.clear_bits(NORTH, CYAN) + bits.clear_bits(BITS.NORTH, BITS.CYAN) self.assertEqual(bits._bits, 0x02) - bits.clear_bits(NORTH, CYAN, MSB) + bits.clear_bits(BITS.NORTH, BITS.CYAN, BITS.MSB) self.assertEqual(bits._bits, 0x02) def test_toggle_bits(self): bits = PlayerBits(0x03) self.assertEqual(bits._bits, 0x03) - bits.toggle_bits(NORTH, CYAN) + bits.toggle_bits(BITS.NORTH, BITS.CYAN) self.assertEqual(bits._bits, 0x12) - bits.toggle_bits(NORTH, CYAN) + bits.toggle_bits(BITS.NORTH, BITS.CYAN) self.assertEqual(bits._bits, 0x03) - bits.toggle_bits(NORTH, CYAN, MSB) + bits.toggle_bits(BITS.NORTH, BITS.CYAN, BITS.MSB) self.assertEqual(bits._bits, 0x92) -- 2.34.1