diff gamelib/lab.py @ 17:10d3db1f1e08

Set up initial research and rework breakthroughs.
author Jeremy Thurgood <firxen@gmail.com>
date Sun, 06 May 2012 17:39:37 +0200
parents 9d61abb3cfaf
children 718d1ec382f7
line wrap: on
line diff
--- a/gamelib/lab.py	Sun May 06 17:12:40 2012 +0200
+++ b/gamelib/lab.py	Sun May 06 17:39:37 2012 +0200
@@ -1,23 +1,64 @@
 # -*- test-case-name: gamelib.tests.test_lab -*-
 
+from random import random, choice
+
 from gamelib import research, products
 
 
 class Lab(object):
+    BASIC_RESEARCH_SUCCESS_RATE = 0.05
+    BASIC_RESEARCH_SUCCESS_MULTIPLIER = 2
+
     def __init__(self):
         self.science = []
         self.new_research = research.ResearchArea.__subclasses__()
         self.new_products = products.Product.__subclasses__()
+        self._choose_initial_science()
+
+    def _choose_initial_science(self):
+        # We always get all starting products.
+        for product in self.new_products[:]:
+            if product.STARTING_PRODUCT:
+                self._gain_science(product())
+
+        # We get three random sciences with no prerequisites.
+        new_science = []
+        for _ in range(3):
+            science = choice(self.find_new_research())()
+            self._gain_science(science)
+            new_science.append(science)
+
+        # Add a point to each of our sciences, and see if we get products.
+        self.spend_points(new_science, 0)
+
+    def _gain_science(self, science):
+        self.science.append(science)
+        if isinstance(science, research.ResearchArea):
+            self.new_research.remove(type(science))
+        elif isinstance(science, products.Product):
+            self.new_products.remove(type(science))
 
     def spend_points(self, things, basic_research):
-        new_stuff = []
+        breakthroughs = []
+
+        # First, allocate the points.
         for thing in things:
             assert thing in self.science
-            thing.spend_points(1)
+            assert thing.can_spend(self)
+            thing.spend_point()
+
+        # Next, check for product breakthroughs and upgrades
+        for thing in things:
             if isinstance(thing, research.ResearchArea):
-                new_stuff.extend(self.find_new_product(thing)[:1])
-        new_stuff.extend(self.try_basic_research(basic_research)[:1])
-        return new_stuff
+                breakthroughs.extend(self.apply_area_research(thing))
+
+        # 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):
         for science in self.science:
@@ -25,25 +66,54 @@
                 return science
         return None
 
-    def _meet_requirements(self, science_class):
+    def meet_requirements(self, science_class, extra=0):
+        total_points = 0
+        base_points = 0
         for science, level in science_class.PREREQUISITES:
             my_science = self._get_science(science)
             if my_science is None:
                 return False
             if my_science.points < level:
                 return False
-        return True
+            base_points += level
+            total_points += my_science.points
+        return total_points - base_points >= extra
 
     def find_new_products(self, research_area):
         available_products = []
         for product_class in self.new_products:
-            if self._meet_requirements(product_class):
+            if self.meet_requirements(product_class):
                 available_products.append(product_class)
         return available_products
 
-    def find_new_research(self, basic_research):
+    def find_new_research(self):
         available_research = []
         for research_class in self.new_research:
-            if self._meet_requirements(research_class):
+            if self.meet_requirements(research_class):
                 available_research.append(research_class)
         return available_research
+
+    def apply_area_research(self, research):
+        options = self.find_new_products(research)
+        breakthroughs = [product for product in options
+                         if random() < product.ACQUISITION_CHANCE]
+        if breakthroughs:
+            breakthrough = choice(breakthroughs)()
+            self._gain_science(breakthrough)
+            breakthroughs = [breakthrough]
+        return breakthroughs
+
+    def apply_basic_research(self, basic_research):
+        if basic_research <= 1:
+            return []
+
+        options = self.find_new_research()
+        success_chance = self.BASIC_RESEARCH_SUCCESS_RATE * (
+            self.BASIC_RESEARCH_SUCCESS_MULTIPLIER ** basic_research)
+        breakthroughs = [research for research in options
+                         if random() < success_chance]
+        if breakthroughs:
+            breakthrough = choice(breakthroughs)(1)
+            self._gain_science(breakthrough)
+            breakthroughs = [breakthrough]
+        return breakthroughs