changeset 23:f6a3b213857b

Fix up some game state logic, add very basic REPL game interface.
author Jeremy Thurgood <firxen@gmail.com>
date Sun, 06 May 2012 19:06:28 +0200
parents 296ce36fa7d9
children 23720d0fd9a0
files gamelib/gamestate.py gamelib/lab.py gamelib/mission.py gamelib/missions.py gamelib/tests/repl_game.py
diffstat 5 files changed, 175 insertions(+), 153 deletions(-) [+]
line wrap: on
line diff
--- a/gamelib/gamestate.py	Sun May 06 18:38:54 2012 +0200
+++ b/gamelib/gamestate.py	Sun May 06 19:06:28 2012 +0200
@@ -54,8 +54,8 @@
             result.apply(self)
         # Update the science state with result of spend_points
         for science in new_stuff:
-            self.lab.science.append(science)
-        # FIXME: Update UI
+            # FIXME: Update UI better.
+            print "You learned new stuff:", science.NAME
 
     def save_data(self):
         """Serialize the game state into a dict"""
--- a/gamelib/lab.py	Sun May 06 18:38:54 2012 +0200
+++ b/gamelib/lab.py	Sun May 06 19:06:28 2012 +0200
@@ -81,9 +81,6 @@
         # Finally, check for research breakthroughs.
         breakthroughs.extend(self.apply_basic_research(basic_research))
 
-        # Now that we have our breakthroughs, apply them.
-        print breakthroughs
-
         return breakthroughs
 
     def _get_science(self, science_class):
--- a/gamelib/mission.py	Sun May 06 18:38:54 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4
-
-from product import DoomsdayVirus, MachineGun, TeslaGun
-
-MAJOR_SETBACK, FAILURE, SUCCESS, MAJOR_SUCCESS, GAME_WIN = range(5)
-
-
-class Result(object):
-    """Results of a mission"""
-
-    def __init__(self, outcome, money, reputation, msg):
-        self.outcome = outcome
-        self.money = money
-        self.reputation = reputation
-        self.message = msg
-        self.applied = False
-
-    def apply(self, state):
-        if not self.applied:
-            state.money += self.money
-            state.reputation += self.reputation
-            self.applied = True
-        else:
-            raise RuntimeError('attempted to apply result twice')
-
-
-class Mission(object):
-    """Base class for the mission objects.
-       Missions have a name, short description (for list displays) and
-       long description (which may contain clues about approaches)"""
-
-    NAME = "Generic Mission"
-    SHORT_DESCRIPTION = None
-    LONG_DESCRIPTION = None
-    available = True
-
-    def __init__(self, init_data=None):
-        pass
-
-    def save_data(self):
-        """Serialize the mission state for saving, etc."""
-        return []
-
-    def attempt(self, equipment, state):
-        """Attempt the mission with the given equipment list.
-
-          Returns a result object with the results of the mission."""
-        return Result(FAILURE, 0, 0, "You can't succceed at this mission")
-
-
-class PlaygroundBully(Mission):
-
-    NAME = "Rob kids in the playground"
-    SHORT_DESCRIPTION = "Steal from those significantly weaker than yourself"
-    LONG_DESCRIPTION = ("It's not menancing, or lucrative, but when the bills"
-            " are due, no one cares how you earn the money")
-
-    def attempt(sefl, equipment, state):
-        return Result(SUCCESS, 100, -1, "You devote your resources to"
-                " robbing kids in a playpark. It's not the finest moment"
-                " in your reign of terror, but at least you walked away"
-                " with a surprising amount of small change.")
-
-
-class RansomChina(Mission):
-
-    NAME = "Hold China to ransom"
-    SHORT_DESCRIPTION = "Surely a path to riches and fame"
-    LONG_DESCRIPTION = "Holding China to ransom. The rewards for" \
-          " successfully threatening the largest country in the world" \
-          " are great, but the risks are significant. Without " \
-          "some serious firepower, the chances of success are small."
-
-    def __init__(self, init_data=None):
-        # Track prior approaches to this mission
-        self._prior_attempts = []
-        if init_data:
-            self._prior_attempts = init_data
-
-    def save_data(self):
-        return self._prior_attempts
-
-    def attempt(self, equipment, state):
-        failures = []
-        reputation = 0
-        for item in equipment:
-            if isinstance(item, DoomsdayVirus) and \
-                    item.NAME not in self._prior_attempts:
-                self._prior_attempts.add(item.NAME)
-                return Result(SUCCESS, 1000000, 1, "Trembling at the threat of"
-                    " your doomsday virus, the chinese government pays the"
-                    " ransom")
-            elif isinstance(item, DoomsdayVirus):
-                reputation = -1
-                failures.append("'Hah, we've developed an antidote to your"
-                        " virus, doctor'. You cannot threaten us with that"
-                        " again'")
-            else:
-                failures.append("You fail to inspire fear with your %s"
-                        % item.name)
-        return Result(FAILURE, 0, reputation, "\n".join(failures))
-
-
-class RobBank(Mission):
-
-    NAME = "Rob the local bank"
-    SHORT_DESCRIPTION = "A trivial challenge, but easy money"
-    LONG_DESCRIPTION = "The security guards and local police are of minor" \
-          " concern. Walk in, clean out the vault, walk out. Couldn't be" \
-          " simpler."
-
-    def attempt(self, equipment, state):
-        failures = []
-        for item in equipment:
-            if isinstance(item, DoomsdayVirus):
-                if state.reputation < 10:
-                    failures.append("The clerk doesn't realise the threat of"
-                            " the vial you hold, and, although watching him"
-                            " die in agony would be statisfying, you decide"
-                            " it's not worth wasting this on something so"
-                            " trivial")
-                else:
-                    return Result(SUCCESS, 1000, 0, "Holding up a bank with"
-                            " only a small vial of clear liquid. Now that"
-                            " is power.")
-            elif isinstance(item, MachineGun) or isinstance(item, TeslaGun):
-                return Result(SUCCESS, 1000, 0, "The threat of your weapons is"
-                    " enough to inspire an impressive level of cooperation")
-            else:
-                failures.append("You fail to inspire fear with your %s"
-                        % item.name)
-        return Result(FAILURE, 0, 0, "\n".join(failures))
-
-
-class DestroyMountRushmore(Mission):
-
-    NAME = "Destroy Mount Rushmore"
-    SHORT_DESCRIPTION = "Monuments to other people? Intolerable"
-    LONG_DESCRIPTION = "While potentially expensive, destroying" \
-            " major monument is a good way to secure your reputation."
-
-    def attempt(self, equipment, state):
-        if not self.available:
-            raise RuntimeError('Cannot attempt an unavailable mission')
-        self.available = False
-        return Result(SUCCESS, 0, 100,
-            "Mount Rushmore is remarkably easy to destroy.")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gamelib/missions.py	Sun May 06 19:06:28 2012 +0200
@@ -0,0 +1,148 @@
+# -*- coding: utf-8 -*-
+# vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4
+
+from products import DoomsdayVirus, MachineGun, LightningGun
+
+MAJOR_SETBACK, FAILURE, SUCCESS, MAJOR_SUCCESS, GAME_WIN = range(5)
+
+
+class Result(object):
+    """Results of a mission"""
+
+    def __init__(self, outcome, money, reputation, msg):
+        self.outcome = outcome
+        self.money = money
+        self.reputation = reputation
+        self.message = msg
+        self.applied = False
+
+    def apply(self, state):
+        if not self.applied:
+            state.money += self.money
+            state.reputation += self.reputation
+            self.applied = True
+        else:
+            raise RuntimeError('attempted to apply result twice')
+
+
+class Mission(object):
+    """Base class for the mission objects.
+       Missions have a name, short description (for list displays) and
+       long description (which may contain clues about approaches)"""
+
+    NAME = "Generic Mission"
+    SHORT_DESCRIPTION = None
+    LONG_DESCRIPTION = None
+    available = True
+
+    def __init__(self, init_data=None):
+        pass
+
+    def save_data(self):
+        """Serialize the mission state for saving, etc."""
+        return []
+
+    def attempt(self, equipment, state):
+        """Attempt the mission with the given equipment list.
+
+          Returns a result object with the results of the mission."""
+        return Result(FAILURE, 0, 0, "You can't succceed at this mission")
+
+
+class PlaygroundBully(Mission):
+
+    NAME = "Rob kids in the playground"
+    SHORT_DESCRIPTION = "Steal from those significantly weaker than yourself"
+    LONG_DESCRIPTION = ("It's not menancing, or lucrative, but when the bills"
+            " are due, no one cares how you earn the money")
+
+    def attempt(sefl, equipment, state):
+        return Result(SUCCESS, 100, -1, "You devote your resources to"
+                " robbing kids in a playpark. It's not the finest moment"
+                " in your reign of terror, but at least you walked away"
+                " with a surprising amount of small change.")
+
+
+class RansomChina(Mission):
+
+    NAME = "Hold China to ransom"
+    SHORT_DESCRIPTION = "Surely a path to riches and fame"
+    LONG_DESCRIPTION = "Holding China to ransom. The rewards for" \
+          " successfully threatening the largest country in the world" \
+          " are great, but the risks are significant. Without " \
+          "some serious firepower, the chances of success are small."
+
+    def __init__(self, init_data=None):
+        # Track prior approaches to this mission
+        self._prior_attempts = []
+        if init_data:
+            self._prior_attempts = init_data
+
+    def save_data(self):
+        return self._prior_attempts
+
+    def attempt(self, equipment, state):
+        failures = []
+        reputation = 0
+        for item in equipment:
+            if isinstance(item, DoomsdayVirus) and \
+                    item.NAME not in self._prior_attempts:
+                self._prior_attempts.add(item.NAME)
+                return Result(SUCCESS, 1000000, 1, "Trembling at the threat of"
+                    " your doomsday virus, the chinese government pays the"
+                    " ransom")
+            elif isinstance(item, DoomsdayVirus):
+                reputation = -1
+                failures.append("'Hah, we've developed an antidote to your"
+                        " virus, doctor'. You cannot threaten us with that"
+                        " again'")
+            else:
+                failures.append("You fail to inspire fear with your %s"
+                        % item.name)
+        return Result(FAILURE, 0, reputation, "\n".join(failures))
+
+
+class RobBank(Mission):
+
+    NAME = "Rob the local bank"
+    SHORT_DESCRIPTION = "A trivial challenge, but easy money"
+    LONG_DESCRIPTION = "The security guards and local police are of minor" \
+          " concern. Walk in, clean out the vault, walk out. Couldn't be" \
+          " simpler."
+
+    def attempt(self, equipment, state):
+        failures = []
+        for item in equipment:
+            if isinstance(item, DoomsdayVirus):
+                if state.reputation < 10:
+                    failures.append("The clerk doesn't realise the threat of"
+                            " the vial you hold, and, although watching him"
+                            " die in agony would be statisfying, you decide"
+                            " it's not worth wasting this on something so"
+                            " trivial")
+                else:
+                    return Result(SUCCESS, 1000, 0, "Holding up a bank with"
+                            " only a small vial of clear liquid. Now that"
+                            " is power.")
+            elif isinstance(item, (MachineGun, LightningGun)):
+                return Result(SUCCESS, 1000, 0, "The threat of your weapons is"
+                    " enough to inspire an impressive level of cooperation")
+            else:
+                failures.append("You fail to inspire fear with your %s"
+                        % item.name)
+        return Result(FAILURE, 0, 0, "\n".join(failures))
+
+
+class DestroyMountRushmore(Mission):
+
+    NAME = "Destroy Mount Rushmore"
+    SHORT_DESCRIPTION = "Monuments to other people? Intolerable"
+    LONG_DESCRIPTION = "While potentially expensive, destroying" \
+            " major monument is a good way to secure your reputation."
+
+    def attempt(self, equipment, state):
+        if not self.available:
+            raise RuntimeError('Cannot attempt an unavailable mission')
+        self.available = False
+        return Result(SUCCESS, 0, 100,
+            "Mount Rushmore is remarkably easy to destroy.")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gamelib/tests/repl_game.py	Sun May 06 19:06:28 2012 +0200
@@ -0,0 +1,25 @@
+from gamelib.gamestate import Game
+
+
+class ReplGame(object):
+    def __init__(self, init_data=None):
+        self.game = Game(init_data=init_data)
+        self._begin_turn()
+
+    def _begin_turn(self):
+        self.game.start_turn()
+        self.display_state()
+
+    def display_state(self):
+        print "Game:", self.game
+        print "Science:"
+        for science in self.game.lab.science:
+            print " %s %s (%s)" % (
+                "*" if science.can_spend(self.game.lab) else "-",
+                science.NAME, science.points)
+
+    def next_turn(self, research_list, missions):
+        self.game.cur_allocation.extend(research_list)
+        self.game.cur_missions.extend(missions)
+        self.game.end_turn()
+        self._begin_turn()