changeset 40:0e178b20e3ff

merge commit
author Rizmari Versfeld <rizziepit@gmail.com>
date Mon, 07 May 2012 00:27:59 +0200
parents d82d3e54a4ef (current diff) efc4f90cfd63 (diff)
children e285b1e31a08
files
diffstat 3 files changed, 141 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/gamelib/lab.py	Mon May 07 00:26:55 2012 +0200
+++ b/gamelib/lab.py	Mon May 07 00:27:59 2012 +0200
@@ -100,7 +100,7 @@
             total_points += my_science.points
         return total_points - base_points >= extra
 
-    def find_new_products(self, research_area):
+    def find_new_products(self):
         available_products = []
         for product_class in self.new_products:
             if self.meet_requirements(product_class):
@@ -115,7 +115,8 @@
         return available_research
 
     def apply_area_research(self, research):
-        options = self.find_new_products(research)
+        options = [product for product in self.find_new_products()
+                   if type(research) in [p[0] for p in product.PREREQUISITES]]
         breakthroughs = [product for product in options
                          if random() < product.ACQUISITION_CHANCE]
         if breakthroughs:
--- a/gamelib/missions.py	Mon May 07 00:26:55 2012 +0200
+++ b/gamelib/missions.py	Mon May 07 00:27:59 2012 +0200
@@ -1,6 +1,8 @@
 # -*- coding: utf-8 -*-
 # vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4
 
+from random import random
+
 from products import HAND_WEAPON, VEHICLE, PATHOGEN, DOOMSDAY_DEVICE
 
 MAJOR_SETBACK, FAILURE, SUCCESS, MAJOR_SUCCESS, GAME_WIN = range(5)
@@ -47,33 +49,62 @@
 
     def attempt(self, equipment, state):
         """Attempt the mission with the given equipment list.
+        Returns a result object with the results of the mission."""
 
-          Returns a result object with the results of the mission."""
-        return Result(FAILURE, 0, 0, "You can't succceed at this mission")
+        # No equipment is usually a special case.
+        if not equipment:
+            return self.attempt_no_equipment(state)
+
+        # Categorise equipment for easier decision-making.
+        categorised = {}
+        for item in equipment:
+            for category in item.CATEGORIES:
+                categorised.setdefault(category, []).append(item)
+        result = self.attempt_with(categorised, state)
+
+        if result is not None:
+            # We have a mission result.
+            return result
+
+        # Generic fallback result.
+        return Result(FAILURE, 0, 0, (
+                "You fail to inspire sufficient fear."))
+
+    def attempt_no_equipment(self, state):
+        return Result(FAILURE, 0, 0, (
+                "Really? You're going in completely unequipped?"
+                " How brave. And foolish. And ultimately unsuccessful."))
+
+    def attempt_with(self, categorised, state):
+        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")
+    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(self, 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.")
+        haul = 90 + int(random() * 20)
+        return Result(SUCCESS, haul, -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."
+    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.")
     MINIMUM_REPUTATION = 100
 
     def __init__(self, init_data=None):
@@ -85,96 +116,115 @@
     def save_data(self):
         return self._prior_attempts
 
-    def attempt(self, equipment, state):
-        failures = []
-        reputation = 0
-        for item in equipment:
-            if item.is_a(DOOMSDAY_DEVICE):
-                if 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 item.is_a(PATHOGEN):
-                    reputation = -1
-                    failures.append(
-                        "'Hah, we've developed an antidote to your"
-                        " pathogen, doctor. You cannot threaten us with that"
-                        " again.'")
-                else:
-                    reputation = -1
-                    failures.append(
-                        "'Hah, we know how to deal with that particular"
-                        " threat, doctor.'")
-            else:
-                failures.append("You fail to inspire fear with your %s"
-                        % item.NAME)
-        return Result(FAILURE, 0, reputation, "\n".join(failures))
+    def attempt_no_equipment(self, state):
+        return Result(FAILURE, 0, -10, (
+                "It takes three different interpreters before the Chinese"
+                " government finally understand that you're trying to hold"
+                " them ransom with... well... nothing. Nothing at all. This"
+                " one will probably make a good anecdote at diplomatic"
+                " cocktail parties. But not for you. No, not for you at all."))
+
+    def attempt_with(self, categorised, state):
+        dooms = categorised.get(DOOMSDAY_DEVICE, [])
+
+        if not dooms:
+            return Result(FAILURE, 0, -1, (
+                    "You completely fail to inspire the requisite level of"
+                    " terror. Maybe a more impressive threat will fare"
+                    " better."))
+
+        if len(dooms) > 1:
+            return Result(FAILURE, 0, 0, (
+                    "Everyone seems confused as to how you actually plan"
+                    " to cause widepsread distruction and mayhem, and"
+                    " negotiations break down. Perhaps it's better to stick"
+                    " to one weapon of mass destruction at a time."))
+
+        [doom] = dooms
+        if doom.NAME in self._prior_attempts:
+            return Result(FAILURE, 0, 0, (
+                    "'We have devised countermeasures since last time, doctor."
+                    " You cannot threaten us with that again.'"))
+
+        self._prior_attempts.add(doom.NAME)
+        return Result(SUCCESS, 1000000, 10, (
+                "Trembling at you threat of certain doom, the Chinese"
+                " government pays the ransom."))
 
 
 class ToppleThirdWorldGovernment(Mission):
 
     NAME = "Topple a third-world government"
-    SHORT_DESCRIPTION = "We could use a more amenable despot there"
+    SHORT_DESCRIPTION = "We could use a more amenable dictator there."
     LONG_DESCRIPTION = (
         "It's a small and fairly useless country, but it's still an actual"
         " government that can be toppled. A good test bed for some of the"
         " larger toys in the armory.")
     MINIMUM_REPUTATION = 50
 
-    def attempt(self, equipment, state):
-        failures = []
-        if not equipment:
+    def attempt_no_equipment(self, state):
+        return Result(FAILURE, 0, 0, (
+                "The border post may be poorly guarded, but you need to"
+                " bring *some* kind of weaponry along. Your troops sulk"
+                " on the way home."))
+
+    def attempt_with(self, categorised, state):
+        if any(c in categorised for c in (VEHICLE, HAND_WEAPON)):
+            return Result(SUCCESS, 5000 + int(random() * 10000), 5, (
+                    "The corruption and oppression continue, but at least"
+                    " the proceeds are making their way into *your*"
+                    " pockets. And you don't even have to dirty your own"
+                    " jackboots."))
+
+        if DOOMSDAY_DEVICE in categorised:
             return Result(FAILURE, 0, 0, (
-                    "The border post may be poorly guarded, but you need to"
-                    " bring *some* kind of weaponry along. Your troops sulk"
-                    " on the way home."))
-        for item in equipment:
-            if any(item.is_a(cat) for cat in (VEHICLE, HAND_WEAPON)):
-                return Result(SUCCESS, 10000, 5, (
-                        "The corruption and oppression continue, but at least"
-                        " the proceeds are making their way into *your*"
-                        " pockets. And you don't even have to dirty your own"
-                        " jackboots."))
-            else:
-                failures.append("You fail to inspire fear with your %s"
-                        % item.NAME)
-        return Result(FAILURE, 0, 0, "\n".join(failures))
+                    "Nobody seems to quite understand what it is you're"
+                    " threatening them with. Eventually you have to give up"
+                    " and go home."))
 
 
 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."
+    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_no_equipment(self, state):
+        return Result(FAILURE, 0, 0, (
+                "Your attempt to rob the bank barehanded is unsuccessful."
+                " Fortunately, everyone is too stunned to impede your"
+                " escape."))
+
+    def attempt_with(self, categorised, state):
+        loot = 500 + int(random() * 1000)
 
-    def attempt(self, equipment, state):
-        failures = []
-        if not equipment:
-            return Result(FAILURE, 0, 0, "Your attempt to rob the bank"
-                    " barehanded is unsuccessful. Fortunately, everyone is"
-                    " too stunned to impede your escape.")
-        for item in equipment:
-            if item.is_a(PATHOGEN):
-                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 item.is_a(HAND_WEAPON):
-                return Result(SUCCESS, 1000, 0, "The threat of your weapons is"
-                    " enough to inspire an impressive level of cooperation")
+        if VEHICLE in categorised:
+            return Result(FAILURE, 0, 0, (
+                    "Your vehicles are impressively doom-laden, but not really"
+                    " suitable for city traffic. You intimidate the traffic"
+                    " wardens into letting you off without a fine, but by the"
+                    " time you get to the bank it's already closed."))
+
+        if HAND_WEAPON in categorised:
+            return Result(SUCCESS, loot, 0, (
+                    "The threat of your weapons is enough to inspire an"
+                    " impressive level of cooperation. You make off with the"
+                    " loot."))
+
+        if PATHOGEN in categorised:
+            if state.reputation < 10:
+                return Result(FAILURE, 0, 0, (
+                        "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:
-                failures.append("You fail to inspire fear with your %s"
-                        % item.NAME)
-        return Result(FAILURE, 0, 0, "\n".join(failures))
+                return Result(SUCCESS, loot, 1, (
+                        "Holding up a bank with only a small vial of clear"
+                        " liquid. Now that is power."))
 
 
 class DestroyMountRushmore(Mission):
@@ -189,5 +239,5 @@
         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.")
+        return Result(SUCCESS, 0, 50, (
+                "Mount Rushmore is remarkably easy to destroy."))
--- a/gamelib/tests/test_lab.py	Mon May 07 00:26:55 2012 +0200
+++ b/gamelib/tests/test_lab.py	Mon May 07 00:27:59 2012 +0200
@@ -27,7 +27,7 @@
 
     def test_find_new_products(self):
         lab = Lab(LAB_DATA)
-        new_products = lab.find_new_products(None)
+        new_products = lab.find_new_products()
         self.assertTrue(products.TeslaTank in new_products)
         self.assertTrue(products.DoomsdayVirus not in new_products)