annotate gamelib/lab.py @ 153:a644f6b64a6d

Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
author Jeremy Thurgood <firxen@gmail.com>
date Fri, 11 May 2012 20:27:37 +0200
parents 372d886f9e70
children 4bbd4a1879f8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14
9d61abb3cfaf Better subclass handling.
Jeremy Thurgood <firxen@gmail.com>
parents: 9
diff changeset
1 # -*- test-case-name: gamelib.tests.test_lab -*-
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
2
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
3 from random import random, choice, sample
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
4
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
5 from gamelib import research, schematics
45
1e8f7e694f0c Refactor missions and sciences a bit to reduce duplication.
Jeremy Thurgood <firxen@gmail.com>
parents: 36
diff changeset
6 from gamelib.game_base import get_subclasses
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
7
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
8
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
9 class ScienceGraph(object):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
10 def __init__(self, all_science, known_science):
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
11 self._graph = {}
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
12 self.node = {}
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
13 self.all_science = all_science
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
14 self.known_science = known_science
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
15 self.add_all_science()
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
16 self.tag_known_science()
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
17
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
18 def add_all_science(self):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
19 # Add level 0 of everything to the graph.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
20 for science in self.all_science:
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
21 self.add_node((science, 0), known=False)
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
22
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
23 # Walk dependencies and fill in intermediate nodes.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
24 for science in self.all_science:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
25 for dep in science.PREREQUISITES:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
26 self.add_node_string(*dep)
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
27 self.add_edge(dep, (science, 0))
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
28
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
29 def add_node(self, node, **attrs):
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
30 self.node[node] = attrs
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
31 self._graph[node] = {}
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
32
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
33 def add_edge(self, a, b, **attrs):
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
34 if a not in self._graph:
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
35 self.add_node(a)
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
36 if b not in self._graph:
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
37 self.add_node(b)
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
38 self._graph[a][b] = attrs
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
39
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
40 def predecessors(self, node):
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
41 preds = []
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
42 for n, e in self._graph.iteritems():
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
43 if node in e:
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
44 preds.append(n)
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
45 return preds
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
46
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
47 def add_node_string(self, science, level):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
48 node = (science, level)
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
49 if node in self._graph:
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
50 return node
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
51
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
52 # We prepopulate with level 0 of eveything.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
53 assert level >= 0
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
54
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
55 self.add_node(node, known=False)
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
56 parent = self.add_node_string(science, level - 1)
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
57 self.add_edge(parent, node)
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
58 return node
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
59
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
60 def tag_known_science(self):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
61 for science in self.known_science:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
62 # We may know more of this than the graph has.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
63 self.add_node_string(type(science), science.points + 1)
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
64 for i in range(science.points + 1):
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
65 self.node[(type(science), i)]['known'] = True
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
66
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
67 def is_known(self, node):
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
68 return self.node[node]['known']
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
69
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
70 def distances_to_known(self, science):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
71 nodes = set()
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
72 nodes_to_check = [(science, 0)]
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
73
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
74 while nodes_to_check:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
75 node = nodes_to_check.pop()
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
76 if self.is_known(node) or node in nodes:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
77 continue
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
78 nodes.add(node)
153
a644f6b64a6d Implement just the tiny bit of networkx we actually need, so we can drop the extra dependency.
Jeremy Thurgood <firxen@gmail.com>
parents: 151
diff changeset
79 nodes_to_check.extend(self.predecessors(node))
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
80
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
81 distances = {}
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
82 for node in nodes:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
83 distances.setdefault(node[0], 0)
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
84 distances[node[0]] += 1
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
85
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
86 return distances
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
87
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
88 def count_unknown(self, sciences):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
89 return len([s for s in sciences if not self.is_known((s, 0))])
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
90
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
91 def find_prospects(self):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
92 prospects = {'research': [], 'schematic': []}
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
93 for science in self.all_science:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
94 distances = self.distances_to_known(science)
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
95 if not distances:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
96 # We already know this thing.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
97 continue
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
98 # Remove the thing we're trying to get from the distance.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
99 distances.pop(science)
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
100 if self.count_unknown(distances.keys()) > 0:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
101 # We only want direct breakthroughs.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
102 continue
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
103 prospects[science.SCIENCE_TYPE].append(
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
104 (sum(distances.values()), science, distances))
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
105 return dict((k, sorted(v)) for k, v in prospects.items())
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
106
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
107 def find_promising_areas(self, size=3):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
108 basic_science = False
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
109 areas_for_research = set()
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
110 areas_for_schematics = set()
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
111 prospects = self.find_prospects()
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
112
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
113 for points, target, distances in prospects['schematic']:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
114 if points > 0:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
115 # We need nonzero points in these things.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
116 areas_for_schematics.update(distances.keys())
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
117 else:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
118 # Any of these things qualify us.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
119 areas_for_schematics.update(p for p, _ in target.PREREQUISITES)
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
120
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
121 for points, target, distances in prospects['research']:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
122 if points == 0:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
123 basic_science = True
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
124 else:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
125 areas_for_research.update(distances.keys())
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
126
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
127 suggestions = []
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
128 k = min(size, len(areas_for_schematics))
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
129 suggestions.extend(sample(areas_for_schematics, k))
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
130 if len(suggestions) < size:
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
131 k = min(size - len(suggestions), len(areas_for_research))
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
132 suggestions.extend(sample(areas_for_research, k))
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
133
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
134 return basic_science, suggestions
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
135
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
136
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
137 class Lab(object):
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
138 BASIC_RESEARCH_SUCCESS_RATE = 0.05
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
139 BASIC_RESEARCH_SUCCESS_MULTIPLIER = 2
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
140
20
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
141 def __init__(self, init_data=None):
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
142 self.science = []
45
1e8f7e694f0c Refactor missions and sciences a bit to reduce duplication.
Jeremy Thurgood <firxen@gmail.com>
parents: 36
diff changeset
143 self.new_research = get_subclasses(research.ResearchArea)
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
144 self.new_schematics = get_subclasses(schematics.Schematic)
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
145 self.all_science = [s for s in self.new_research + self.new_schematics]
20
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
146
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
147 if init_data is not None:
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
148 # Load stored state.
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
149 self._load_data(init_data)
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
150 else:
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
151 # New game.
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
152 self._choose_initial_science()
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
153
718d1ec382f7 Deserialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 17
diff changeset
154 def _load_data(self, init_data):
46
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
155 sciences = init_data['science'].copy()
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
156 for science in self.new_schematics + self.new_research:
46
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
157 # Check if this science is one we should know.
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
158 points = sciences.pop(science.save_name(), None)
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
159 if points is not None:
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
160 # It is! Learn it.
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
161 self._gain_science(science(points))
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
162 if sciences:
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
163 # We're supposed to know an unknowable thing. :-(
d3d277a42ac6 Less getattr/isinstance silliness.
Jeremy Thurgood <firxen@gmail.com>
parents: 45
diff changeset
164 raise ValueError("Unknown science: %s" % (sciences.keys(),))
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
165
21
bdc6bfc34ef2 Serialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 20
diff changeset
166 def save_data(self):
47
3e3bed2ce248 Better science saving.
Jeremy Thurgood <firxen@gmail.com>
parents: 46
diff changeset
167 return {'science': dict(s.save_data() for s in self.science)}
21
bdc6bfc34ef2 Serialise lab data.
Jeremy Thurgood <firxen@gmail.com>
parents: 20
diff changeset
168
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
169 def _choose_initial_science(self):
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
170 # We always get all starting schematics.
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
171 for schematic in self.new_schematics[:]:
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
172 if schematic.STARTING_PRODUCT:
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
173 self._gain_science(schematic())
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
174
115
ef63532cac13 Rearrange SCIENCE a bit.
Jeremy Thurgood <firxen@gmail.com>
parents: 85
diff changeset
175 # We start with Physics, because it's not Philately.
ef63532cac13 Rearrange SCIENCE a bit.
Jeremy Thurgood <firxen@gmail.com>
parents: 85
diff changeset
176 physics = research.Physics()
ef63532cac13 Rearrange SCIENCE a bit.
Jeremy Thurgood <firxen@gmail.com>
parents: 85
diff changeset
177 self._gain_science(physics)
ef63532cac13 Rearrange SCIENCE a bit.
Jeremy Thurgood <firxen@gmail.com>
parents: 85
diff changeset
178 new_science = [physics]
ef63532cac13 Rearrange SCIENCE a bit.
Jeremy Thurgood <firxen@gmail.com>
parents: 85
diff changeset
179
ef63532cac13 Rearrange SCIENCE a bit.
Jeremy Thurgood <firxen@gmail.com>
parents: 85
diff changeset
180 # We get two other random sciences with no prerequisites.
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
181 for science in sample(self.find_new_research(), 2):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
182 science = science()
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
183 self._gain_science(science)
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
184 new_science.append(science)
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
185
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
186 # Add a point to each of our sciences, and see if we get schematics.
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
187 self.spend_points(new_science, 0)
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
188
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
189 def _gain_science(self, science):
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
190 self.science.append(science)
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
191 if isinstance(science, research.ResearchArea):
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
192 self.new_research.remove(type(science))
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
193 elif isinstance(science, schematics.Schematic):
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
194 self.new_schematics.remove(type(science))
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
195
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
196 def spend_points(self, things, basic_research):
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
197 breakthroughs = []
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
198
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
199 # First, allocate the points.
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
200 for thing in things:
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
201 assert thing in self.science
58
52913ba12988 Check for multiple points in can_spend
Neil Muller <drnlmuller@gmail.com>
parents: 49
diff changeset
202 assert thing.can_spend(self, 1)
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
203 thing.spend_point()
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
204
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
205 # Next, check for schematic breakthroughs and upgrades
85
182fce9f70b6 Propaganda! Also, a fix to blueprint breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 73
diff changeset
206 breakthroughs.extend(self.apply_area_research([
182fce9f70b6 Propaganda! Also, a fix to blueprint breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 73
diff changeset
207 thing for thing in things
182fce9f70b6 Propaganda! Also, a fix to blueprint breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 73
diff changeset
208 if isinstance(thing, research.ResearchArea)]))
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
209
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
210 # Finally, check for research breakthroughs.
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
211 breakthroughs.extend(self.apply_basic_research(basic_research))
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
212
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
213 return breakthroughs
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
214
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
215 def _get_science(self, science_class):
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
216 for science in self.science:
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
217 if isinstance(science, science_class):
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
218 return science
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
219 return None
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
220
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
221 def meet_requirements(self, science_class, extra=0):
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
222 total_points = 0
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
223 base_points = 0
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
224 for science, level in science_class.PREREQUISITES:
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
225 my_science = self._get_science(science)
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
226 if my_science is None:
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
227 return False
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
228 if my_science.points < level:
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
229 return False
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
230 base_points += level
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
231 total_points += my_science.points
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
232 return total_points - base_points >= extra
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
233
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
234 def find_new_schematics(self):
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
235 available_schematics = []
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
236 for schematic_class in self.new_schematics:
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
237 if self.meet_requirements(schematic_class):
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
238 available_schematics.append(schematic_class)
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
239 return available_schematics
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
240
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
241 def find_new_research(self):
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
242 available_research = []
14
9d61abb3cfaf Better subclass handling.
Jeremy Thurgood <firxen@gmail.com>
parents: 9
diff changeset
243 for research_class in self.new_research:
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
244 if self.meet_requirements(research_class):
6
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
245 available_research.append(research_class)
826b44731323 Start of basic lab implementation.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
246 return available_research
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
247
73
b503ccb0a86e Only one schematic per turn, please.
Jeremy Thurgood <firxen@gmail.com>
parents: 58
diff changeset
248 def apply_area_research(self, researches):
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
249 options = [schema for schema in self.find_new_schematics()
73
b503ccb0a86e Only one schematic per turn, please.
Jeremy Thurgood <firxen@gmail.com>
parents: 58
diff changeset
250 if schema.depends_on(researches)]
49
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
251 breakthroughs = [schematic for schematic in options
373c57ab4140 Product -> Schematic.
Jeremy Thurgood <firxen@gmail.com>
parents: 47
diff changeset
252 if random() < schematic.ACQUISITION_CHANCE]
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
253 if breakthroughs:
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
254 breakthrough = choice(breakthroughs)()
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
255 self._gain_science(breakthrough)
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
256 breakthroughs = [breakthrough]
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
257 return breakthroughs
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
258
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
259 def apply_basic_research(self, basic_research):
138
14917385a0fd Better handling of mission results and turn-end messages.
Jeremy Thurgood <firxen@gmail.com>
parents: 115
diff changeset
260 if basic_research <= 0:
17
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
261 return []
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
262
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
263 options = self.find_new_research()
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
264 success_chance = self.BASIC_RESEARCH_SUCCESS_RATE * (
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
265 self.BASIC_RESEARCH_SUCCESS_MULTIPLIER ** basic_research)
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
266 breakthroughs = [research for research in options
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
267 if random() < success_chance]
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
268 if breakthroughs:
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
269 breakthrough = choice(breakthroughs)(1)
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
270 self._gain_science(breakthrough)
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
271 breakthroughs = [breakthrough]
10d3db1f1e08 Set up initial research and rework breakthroughs.
Jeremy Thurgood <firxen@gmail.com>
parents: 14
diff changeset
272 return breakthroughs
151
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
273
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
274 def suggest_research(self):
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
275 """Suggest research areas to pursue.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
276
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
277 Return value is a tuple of (bool, list), where the first element
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
278 indicates whether basic research might pay off and the second contains
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
279 Science classes that can be profitably pursued.
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
280 """
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
281 graph = ScienceGraph(self.all_science, self.science)
372d886f9e70 New suggest_research() method on Lab.
Jeremy Thurgood <firxen@gmail.com>
parents: 138
diff changeset
282 return graph.find_promising_areas()