Mercurial > sypikslang
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.")) |