comparison gamelib/missions.py @ 36:efc4f90cfd63

Mission refactoring and research fix.
author Jeremy Thurgood <firxen@gmail.com>
date Mon, 07 May 2012 00:18:16 +0200
parents 2754c453b39b
children e285b1e31a08
comparison
equal deleted inserted replaced
35:2754c453b39b 36:efc4f90cfd63
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 # vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4 2 # vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4
3
4 from random import random
3 5
4 from products import HAND_WEAPON, VEHICLE, PATHOGEN, DOOMSDAY_DEVICE 6 from products import HAND_WEAPON, VEHICLE, PATHOGEN, DOOMSDAY_DEVICE
5 7
6 MAJOR_SETBACK, FAILURE, SUCCESS, MAJOR_SUCCESS, GAME_WIN = range(5) 8 MAJOR_SETBACK, FAILURE, SUCCESS, MAJOR_SUCCESS, GAME_WIN = range(5)
7 9
45 """Serialize the mission state for saving, etc.""" 47 """Serialize the mission state for saving, etc."""
46 return [] 48 return []
47 49
48 def attempt(self, equipment, state): 50 def attempt(self, equipment, state):
49 """Attempt the mission with the given equipment list. 51 """Attempt the mission with the given equipment list.
50 52 Returns a result object with the results of the mission."""
51 Returns a result object with the results of the mission.""" 53
52 return Result(FAILURE, 0, 0, "You can't succceed at this mission") 54 # No equipment is usually a special case.
55 if not equipment:
56 return self.attempt_no_equipment(state)
57
58 # Categorise equipment for easier decision-making.
59 categorised = {}
60 for item in equipment:
61 for category in item.CATEGORIES:
62 categorised.setdefault(category, []).append(item)
63 result = self.attempt_with(categorised, state)
64
65 if result is not None:
66 # We have a mission result.
67 return result
68
69 # Generic fallback result.
70 return Result(FAILURE, 0, 0, (
71 "You fail to inspire sufficient fear."))
72
73 def attempt_no_equipment(self, state):
74 return Result(FAILURE, 0, 0, (
75 "Really? You're going in completely unequipped?"
76 " How brave. And foolish. And ultimately unsuccessful."))
77
78 def attempt_with(self, categorised, state):
79 return Result(FAILURE, 0, 0, "You can't succceed at this mission.")
53 80
54 81
55 class PlaygroundBully(Mission): 82 class PlaygroundBully(Mission):
56 83
57 NAME = "Rob kids in the playground" 84 NAME = "Rob kids in the playground"
58 SHORT_DESCRIPTION = "Steal from those significantly weaker than yourself" 85 SHORT_DESCRIPTION = "Steal from those significantly weaker than yourself."
59 LONG_DESCRIPTION = ("It's not menancing, or lucrative, but when the bills" 86 LONG_DESCRIPTION = (
60 " are due, no one cares how you earn the money") 87 "It's not menancing, or lucrative, but when the bills are due, no one"
88 " cares how you earn the money.")
61 89
62 def attempt(self, equipment, state): 90 def attempt(self, equipment, state):
63 return Result(SUCCESS, 100, -1, "You devote your resources to" 91 haul = 90 + int(random() * 20)
64 " robbing kids in a playpark. It's not the finest moment" 92 return Result(SUCCESS, haul, -1, (
65 " in your reign of terror, but at least you walked away" 93 "You devote your resources to robbing kids in a playpark."
66 " with a surprising amount of small change.") 94 " It's not the finest moment in your reign of terror, but at"
95 " least you walked away with a surprising amount of small"
96 " change."))
67 97
68 98
69 class RansomChina(Mission): 99 class RansomChina(Mission):
70 100
71 NAME = "Hold China to ransom" 101 NAME = "Hold China to ransom"
72 SHORT_DESCRIPTION = "Surely a path to riches and fame" 102 SHORT_DESCRIPTION = "Surely a path to riches and fame."
73 LONG_DESCRIPTION = "Holding China to ransom. The rewards for" \ 103 LONG_DESCRIPTION = (
74 " successfully threatening the largest country in the world" \ 104 "Holding China to ransom. The rewards for successfully threatening"
75 " are great, but the risks are significant. Without " \ 105 " the largest country in the world are great, but the risks are"
76 "some serious firepower, the chances of success are small." 106 " significant. Without some serious firepower, the chances of success"
107 " are small.")
77 MINIMUM_REPUTATION = 100 108 MINIMUM_REPUTATION = 100
78 109
79 def __init__(self, init_data=None): 110 def __init__(self, init_data=None):
80 # Track prior approaches to this mission 111 # Track prior approaches to this mission
81 self._prior_attempts = set() 112 self._prior_attempts = set()
83 self._prior_attempts = set(init_data) 114 self._prior_attempts = set(init_data)
84 115
85 def save_data(self): 116 def save_data(self):
86 return self._prior_attempts 117 return self._prior_attempts
87 118
88 def attempt(self, equipment, state): 119 def attempt_no_equipment(self, state):
89 failures = [] 120 return Result(FAILURE, 0, -10, (
90 reputation = 0 121 "It takes three different interpreters before the Chinese"
91 for item in equipment: 122 " government finally understand that you're trying to hold"
92 if item.is_a(DOOMSDAY_DEVICE): 123 " them ransom with... well... nothing. Nothing at all. This"
93 if item.NAME not in self._prior_attempts: 124 " one will probably make a good anecdote at diplomatic"
94 self._prior_attempts.add(item.NAME) 125 " cocktail parties. But not for you. No, not for you at all."))
95 return Result(SUCCESS, 1000000, 1, ( 126
96 "Trembling at the threat of your doomsday virus," 127 def attempt_with(self, categorised, state):
97 " the chinese government pays the ransom.")) 128 dooms = categorised.get(DOOMSDAY_DEVICE, [])
98 elif item.is_a(PATHOGEN): 129
99 reputation = -1 130 if not dooms:
100 failures.append( 131 return Result(FAILURE, 0, -1, (
101 "'Hah, we've developed an antidote to your" 132 "You completely fail to inspire the requisite level of"
102 " pathogen, doctor. You cannot threaten us with that" 133 " terror. Maybe a more impressive threat will fare"
103 " again.'") 134 " better."))
104 else: 135
105 reputation = -1 136 if len(dooms) > 1:
106 failures.append( 137 return Result(FAILURE, 0, 0, (
107 "'Hah, we know how to deal with that particular" 138 "Everyone seems confused as to how you actually plan"
108 " threat, doctor.'") 139 " to cause widepsread distruction and mayhem, and"
109 else: 140 " negotiations break down. Perhaps it's better to stick"
110 failures.append("You fail to inspire fear with your %s" 141 " to one weapon of mass destruction at a time."))
111 % item.NAME) 142
112 return Result(FAILURE, 0, reputation, "\n".join(failures)) 143 [doom] = dooms
144 if doom.NAME in self._prior_attempts:
145 return Result(FAILURE, 0, 0, (
146 "'We have devised countermeasures since last time, doctor."
147 " You cannot threaten us with that again.'"))
148
149 self._prior_attempts.add(doom.NAME)
150 return Result(SUCCESS, 1000000, 10, (
151 "Trembling at you threat of certain doom, the Chinese"
152 " government pays the ransom."))
113 153
114 154
115 class ToppleThirdWorldGovernment(Mission): 155 class ToppleThirdWorldGovernment(Mission):
116 156
117 NAME = "Topple a third-world government" 157 NAME = "Topple a third-world government"
118 SHORT_DESCRIPTION = "We could use a more amenable despot there" 158 SHORT_DESCRIPTION = "We could use a more amenable dictator there."
119 LONG_DESCRIPTION = ( 159 LONG_DESCRIPTION = (
120 "It's a small and fairly useless country, but it's still an actual" 160 "It's a small and fairly useless country, but it's still an actual"
121 " government that can be toppled. A good test bed for some of the" 161 " government that can be toppled. A good test bed for some of the"
122 " larger toys in the armory.") 162 " larger toys in the armory.")
123 MINIMUM_REPUTATION = 50 163 MINIMUM_REPUTATION = 50
124 164
125 def attempt(self, equipment, state): 165 def attempt_no_equipment(self, state):
126 failures = [] 166 return Result(FAILURE, 0, 0, (
127 if not equipment: 167 "The border post may be poorly guarded, but you need to"
128 return Result(FAILURE, 0, 0, ( 168 " bring *some* kind of weaponry along. Your troops sulk"
129 "The border post may be poorly guarded, but you need to" 169 " on the way home."))
130 " bring *some* kind of weaponry along. Your troops sulk" 170
131 " on the way home.")) 171 def attempt_with(self, categorised, state):
132 for item in equipment: 172 if any(c in categorised for c in (VEHICLE, HAND_WEAPON)):
133 if any(item.is_a(cat) for cat in (VEHICLE, HAND_WEAPON)): 173 return Result(SUCCESS, 5000 + int(random() * 10000), 5, (
134 return Result(SUCCESS, 10000, 5, ( 174 "The corruption and oppression continue, but at least"
135 "The corruption and oppression continue, but at least" 175 " the proceeds are making their way into *your*"
136 " the proceeds are making their way into *your*" 176 " pockets. And you don't even have to dirty your own"
137 " pockets. And you don't even have to dirty your own" 177 " jackboots."))
138 " jackboots.")) 178
179 if DOOMSDAY_DEVICE in categorised:
180 return Result(FAILURE, 0, 0, (
181 "Nobody seems to quite understand what it is you're"
182 " threatening them with. Eventually you have to give up"
183 " and go home."))
184
185
186 class RobBank(Mission):
187
188 NAME = "Rob the local bank"
189 SHORT_DESCRIPTION = "A trivial challenge, but easy money."
190 LONG_DESCRIPTION = (
191 "The security guards and local police are of minor concern. Walk in,"
192 " clean out the vault, walk out. Couldn't be simpler.")
193
194 def attempt_no_equipment(self, state):
195 return Result(FAILURE, 0, 0, (
196 "Your attempt to rob the bank barehanded is unsuccessful."
197 " Fortunately, everyone is too stunned to impede your"
198 " escape."))
199
200 def attempt_with(self, categorised, state):
201 loot = 500 + int(random() * 1000)
202
203 if VEHICLE in categorised:
204 return Result(FAILURE, 0, 0, (
205 "Your vehicles are impressively doom-laden, but not really"
206 " suitable for city traffic. You intimidate the traffic"
207 " wardens into letting you off without a fine, but by the"
208 " time you get to the bank it's already closed."))
209
210 if HAND_WEAPON in categorised:
211 return Result(SUCCESS, loot, 0, (
212 "The threat of your weapons is enough to inspire an"
213 " impressive level of cooperation. You make off with the"
214 " loot."))
215
216 if PATHOGEN in categorised:
217 if state.reputation < 10:
218 return Result(FAILURE, 0, 0, (
219 "The clerk doesn't realise the threat of"
220 " the vial you hold, and, although watching him"
221 " die in agony would be statisfying, you decide"
222 " it's not worth wasting this on something so"
223 " trivial"))
139 else: 224 else:
140 failures.append("You fail to inspire fear with your %s" 225 return Result(SUCCESS, loot, 1, (
141 % item.NAME) 226 "Holding up a bank with only a small vial of clear"
142 return Result(FAILURE, 0, 0, "\n".join(failures)) 227 " liquid. Now that is power."))
143
144
145 class RobBank(Mission):
146
147 NAME = "Rob the local bank"
148 SHORT_DESCRIPTION = "A trivial challenge, but easy money"
149 LONG_DESCRIPTION = "The security guards and local police are of minor" \
150 " concern. Walk in, clean out the vault, walk out. Couldn't be" \
151 " simpler."
152
153 def attempt(self, equipment, state):
154 failures = []
155 if not equipment:
156 return Result(FAILURE, 0, 0, "Your attempt to rob the bank"
157 " barehanded is unsuccessful. Fortunately, everyone is"
158 " too stunned to impede your escape.")
159 for item in equipment:
160 if item.is_a(PATHOGEN):
161 if state.reputation < 10:
162 failures.append("The clerk doesn't realise the threat of"
163 " the vial you hold, and, although watching him"
164 " die in agony would be statisfying, you decide"
165 " it's not worth wasting this on something so"
166 " trivial")
167 else:
168 return Result(SUCCESS, 1000, 0, "Holding up a bank with"
169 " only a small vial of clear liquid. Now that"
170 " is power.")
171 elif item.is_a(HAND_WEAPON):
172 return Result(SUCCESS, 1000, 0, "The threat of your weapons is"
173 " enough to inspire an impressive level of cooperation")
174 else:
175 failures.append("You fail to inspire fear with your %s"
176 % item.NAME)
177 return Result(FAILURE, 0, 0, "\n".join(failures))
178 228
179 229
180 class DestroyMountRushmore(Mission): 230 class DestroyMountRushmore(Mission):
181 231
182 NAME = "Destroy Mount Rushmore" 232 NAME = "Destroy Mount Rushmore"
187 237
188 def attempt(self, equipment, state): 238 def attempt(self, equipment, state):
189 if not self.available: 239 if not self.available:
190 raise RuntimeError('Cannot attempt an unavailable mission') 240 raise RuntimeError('Cannot attempt an unavailable mission')
191 self.available = False 241 self.available = False
192 return Result(SUCCESS, 0, 100, 242 return Result(SUCCESS, 0, 50, (
193 "Mount Rushmore is remarkably easy to destroy.") 243 "Mount Rushmore is remarkably easy to destroy."))