Mercurial > sypikslang
view gamelib/missions.py @ 228:3955d126ca26
merge
author | Rizmari Versfeld <rizziepit@gmail.com> |
---|---|
date | Sat, 12 May 2012 23:09:33 +0200 |
parents | 53e78cddb9a4 |
children | d7285d65c668 |
line wrap: on
line source
# -*- coding: utf-8 -*- # vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4 from random import randint, random, choice from gamelib.constants import SUCCESS, FAILURE, GAME_WIN, M_VALS from gamelib.schematics import cat from gamelib.research import Biogenetics class Result(Exception): """Results of a mission. This is an exception so we can throw it from inside helper methods. """ def __init__(self, outcome, msg, money=0, rep=0, **special): self.outcome = outcome self.money = money self.reputation = rep self.text = msg self.special = special self.applied = False @property def loot(self): loot = {} if self.money != 0: loot['money'] = self.money if self.reputation != 0: loot['rep'] = self.reputation loot.update(self.special) loot.pop('new_milestone', None) # This one's special. return loot def apply(self, state): if not self.applied: state.money += self.money state.reputation += self.reputation state.apply_mission_special(**self.special) self.applied = True else: raise RuntimeError('attempted to apply result twice') class Mission(object): """Base class for the mission objects. Missions have a name, short description (for list displays) and long description (which may contain clues about approaches)""" NAME = "Generic Mission" SHORT_DESCRIPTION = None LONG_DESCRIPTION = None MINIMUM_REPUTATION = None MINIMUM_MILESTONE = "neighbourhood" MINIONS_REQUIRED = 1 GENERIC_FAILURE = "You fail to inspire sufficient fear." GENERIC_SUCCESS = "Victory is sweet." NO_EQUIP_FAILURE = ( "Really? You're going in completely unequipped? How brave. And " " foolish. And ultimately unsuccessful.") def __init__(self, init_data=None): self.data = {} if init_data is not None: # Load stored state. self._load_data(init_data) else: # New instance. self._new_data() def _new_data(self): pass def _load_data(self, init_data): # Note: this does not deep-copy. self.data = init_data.copy() def save_data(self): # Note: this does not deep-copy. return self.data.copy() def get_data(self, key): return self.data.get(key, None) def get_description(self): return self.LONG_DESCRIPTION @classmethod def sanity_check(cls): pass def can_attempt(self, state): """Can we currently attempt the mission""" if (M_VALS[self.MINIMUM_MILESTONE] > M_VALS[state.milestone]): # Our base of operations is too small return False if self.get_data('completed'): return False if (self.MINIMUM_REPUTATION is not None and self.MINIMUM_REPUTATION > state.reputation): # Don't have the reputation required return False if self.MINIONS_REQUIRED > state.minions: # Need more minions! return False return True def fail(self, msg=None, money=0, rep=0, **special): if msg is None: msg = self.GENERIC_FAILURE raise Result(FAILURE, msg, money=money, rep=rep, **special) def succeed(self, msg=None, money=0, rep=0, **special): if msg is None: msg = self.GENERIC_SUCCESS raise Result(SUCCESS, msg, money=money, rep=rep, **special) def categorise_equipment(self, equipment): # Categorise equipment for easier decision-making. categorised = {} for item in equipment: for category in item.CATEGORIES: categorised.setdefault(category, []).append(item) return categorised def attempt_mission(self, equipment, state): """Attempt the mission with the given equipment list. Returns a result object with the results of the mission.""" # Handle error case if self.get_data('completed'): raise RuntimeError('Cannot attempt a completed mission') try: self.attempt(equipment, state) except Result, e: return e def attempt(self, equipment, state): # No equipment is usually a special case. if not equipment: return self.attempt_no_equipment(state) # Try with some equipment. self.attempt_with(self.categorise_equipment(equipment), state) # No result, so generic failure. self.fail() def attempt_no_equipment(self, state): self.fail(self.NO_EQUIP_FAILURE) def attempt_with(self, categorised, state): self.fail("You can't succceed at this mission.") def combat_power(self, categorised, cats=None): if cats is None: cats = [cat.HAND_WEAPON, cat.VEHICLE, cat.COUNTERMEASURE, cat.INTELLIGENCE] combat_equipment = set() for category in cats: combat_equipment.update(categorised.get(category, [])) power = 0 for equipment in combat_equipment: power += equipment.power() return power def check_failure(self, categorised): equipment = set() for items in categorised.values(): equipment.update(items) for item in equipment: if item.reliability() < random(): return item.FAILURE_TEXT return None def use_equipment(self, categorised, msg="Disaster strikes! %s", **loot): failure = self.check_failure(categorised) if failure is not None: self.fail(msg % (failure,), **loot) def use_equipment_category(self, categorised, category): self.use_equipment({category: categorised[category]}) 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.") MINIMUM_MILESTONE = "basement" GENERIC_SUCCESS = ( "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.") def attempt(self, equipment, state): self.succeed(money=randint(90, 110), rep=-1) 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.") MINIMUM_REPUTATION = 100 MINIMUM_MILESTONE = "city" def _new_data(self): self.data['prior_attempts'] = [] def attempt_no_equipment(self, state): self.fail( "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.", rep=-10) def attempt_with(self, categorised, state): dooms = categorised.get(cat.DOOMSDAY_DEVICE, []) if not dooms: self.fail( "You completely fail to inspire the requisite level of" " terror. Maybe a more impressive threat will fare better.", rep=-1) if len(dooms) > 1: self.fail( "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.data['prior_attempts']: self.fail( "'We have devised countermeasures since last time, doctor." " You cannot threaten us with that again.'") self.use_equipment(categorised, rep=randint(-5, -2)) self.data['prior_attempts'].add(doom.NAME) self.succeed( "Trembling at you threat of certain doom, the Chinese" " government pays the ransom.", money=randint(800000, 1200000), rep=10) class ToppleThirdWorldGovernment(Mission): NAME = "Topple a third-world government" 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 GENERIC_FAILURE = ( "Your invasion force was outclassed by the incumbent military, Not" " surprising, since it turns out they've had a lot of practice in the" " recent series of revolutions.") NO_EQUIP_FAILURE = ( "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): self.use_equipment(categorised) if self.combat_power(categorised) > randint(60, 120): self.succeed( "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.", money=randint(5000, 15000), rep=randint(3, 7)) 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.") MINIMUM_MILESTONE = "basement" GENERIC_FAILURE = ( "The bank's security arrangements are rather more impressive than you" " were led to believe. Bring bigger guns next time.") NO_EQUIP_FAILURE = ( "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 = randint(500, 1500) self.use_equipment(categorised) if cat.VEHICLE in categorised: self.fail( "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 cat.PATHOGEN in categorised: if randint(5, 15) < state.reputation: self.fail( "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.") self.succeed( "Holding up a bank with only a small vial of clear liquid. Now" " that is power.", money=loot, rep=1) if cat.AI in categorised: self.success( "Your cunning AI easily penetrates the bank's computing" " systems and transfers the money to you account.", money=loot) if self.combat_power(categorised) > randint(5, 20): self.succeed( "The threat of your weapons is enough to inspire an impressive" " level of cooperation. You make off with the loot.", money=loot) class DestroyMountRushmore(Mission): NAME = "Destroy Mount Rushmore" SHORT_DESCRIPTION = "Monuments to other people? Intolerable" LONG_DESCRIPTION = ( "While potentially expensive, destroying a major monument is a" " good way to secure your reputation.") MINIMUM_REPUTATION = 20 def attempt(self, equipment, state): self.data['completed'] = True self.succeed("Mount Rushmore is remarkably easy to destroy.", rep=50) class DistributePamphlets(Mission): NAME = "Distribute pamphlets" SHORT_DESCRIPTION = "The populace need to be told the truth!" LONG_DESCRIPTION = ( "A focused pamphlet distribution campaign will combat the lies being" " spread about you. Replacing them with better lies, of course.") MINIMUM_MILESTONE = "basement" SUCCESS_MESSAGE = ( "A small army of urchins delivers thousands of cheaply printed" " pamphlets. %s") def _succ(self, message, rep): self.succeed(self.SUCCESS_MESSAGE % (message,), rep=rep) def attempt_no_equipment(self, state): rep = randint(-2, 5) if rep < 0: self._succ( "Sadly, the populace was so annoyed by the flood of flyers" " that nobody took any notice of the content.", rep) if rep == 0: self._succ("Nobody seems to have noticed.", rep) self._succ( "The public seemed mildly receptive to your propaganda.", rep) def attempt_with(self, categorised, state): if cat.MIND_CONTROL in categorised: self.use_equipment_category(categorised, cat.MIND_CONTROL) self._succ("Your creative use of science has paid off nicely.", randint(5, 10)) return self.attempt_no_equipment(state) class TakeOverTheWorld(Mission): NAME = "Take over the world!" SHORT_DESCRIPTION = "It's for their own good." LONG_DESCRIPTION = ( "Someone has to rule the world and if it's not you it'd just be" " someone less well qualified -- and that would be worse for" " everyone.") MINIMUM_REPUTATION = 200 MINIMUM_MILESTONE = "city" NO_EQUIP_FAILURE = ( "It's going to take more than your bare hands to take over the world!") def attempt_with(self, categorised, state): if cat.MIND_CONTROL not in categorised: self.fail( "If you're going to take over the world, first you must" " control key elements within the populace.", rep=-5) raise Result(GAME_WIN, "The world is yours!", rep=100) class TakeOverTheNeighbourhood(Mission): NAME = "Take over the neighbourhood!" SHORT_DESCRIPTION = "First step toward greatness." LONG_DESCRIPTION = ( "A basement lab is a good starting point, but it's getting a bit" " cramped in here. You need to expand, but don't quite have the" " resources to take the whole world yet. Or even the city. But the" " neighbourhood... that's quite feasible.") MINIMUM_REPUTATION = 20 MINIMUM_MILESTONE = "basement" NO_EQUIP_FAILURE = ( "The neighbourhood isn't very big, but you're still not going to take" " it over bare-handed.") GENERIC_FAILURE = ( "Well, that didn't work. Maybe a better equipment selection is in" " order.") def attempt_with(self, categorised, state): if all(c in categorised for c in (cat.MIND_CONTROL, cat.HAND_WEAPON)): self.data['completed'] = True self.succeed( "Guns and persuasion, that's all you need. It's early days" " still, but you're finally out of that pokey basement and" " have some elbow room to work with. Next step: the city!", money=randint(1000, 2000), rep=randint(5, 15), new_milestone="neighbourhood", income=100) if cat.HAND_WEAPON in categorised: self.succeed( "You'll need more than guns to win the people over. But until" " then, you can take their cash.", money=randint(100, 200)) if cat.MIND_CONTROL in categorised: self.succeed( "Propaganda and persuasion are good tools, but you'll need" " some force to back them up.", rep=randint(2, 4)) class TakeOverTheCity(Mission): NAME = "Take over the city" SHORT_DESCRIPTION = "Time to grow" LONG_DESCRIPTION = ( "It's time to spread your wings and take your rightful place as" " a major player. And what better way than by securing your base" " of operations?") MINIMUM_REPUTATION = 100 MINIMUM_MILESTONE = "neighbourhood" NO_EQUIP_FAILURE = ( "You are thrown out of city hall for making a scene. The fools will" " pay for this when you return with more firepower.") GENERIC_FAILURE = ( "Well, that didn't work. Maybe a better equipment selection is in" " order.") def attempt_with(self, categorised, state): if cat.DOOMSDAY_DEVICE in categorised: self.data['completed'] = True self.succeed( "Overwhelming force! It works for governments, and it works" " for you. The city cowers before you, and you finally" " feel like you're getting somewhere. Soon, the world will" " be yours.", money=randint(10000, 20000), rep=randint(10, 20), new_milestone='city', income=1000) if cat.AI in categorised: self.use_equipment_category(categorised, cat.AI) self.succeed( "While the AI can't control the entire city, you can at" " least ensure the budget is well spent", money=randint(10000, 30000)) if cat.MIND_CONTROL in categorised: self.use_equipment_category(categorised, cat.MIND_CONTROL) self.succeed( "Running a city requires controlling more than just a few" " key people. Still, making the mayor dance to your tune" " is not without it's benefits", money=randint(3000, 7000), rep=randint(3, 7)) if cat.VEHICLE in categorised: self.fail( "While you can muster a significant force, you don't want" " to destroy the city in the inevitable fighting. You need" " to ensure no-one tries to resist.") if cat.HAND_WEAPON in categorised: self.fail( "You'll need more than a handful of guns, no matter" " how powerful, to subdue a city") class ShowThemAll(Mission): NAME = "And they called me mad!" SHORT_DESCRIPTION = "Time for revenge." LONG_DESCRIPTION = ( "You've outgrown the chains of convention your teachers tried" " to force you into. It's time to show the world what true" " genius can accomplish. And what better way than with a small" " slice of revenge?") MINIMUM_REPUTATION = 20 MINIMUM_MILESTONE = "neighbourhood" NO_EQUIP_FAILURE = ( "A security guard escorts you off campus after finding you clawing" " at the science building with your bare hands. He doesn't say" " anything, but you can already hear the gossip.") def attempt_no_equipment(self, state): self.fail(self.NO_EQUIP_FAILURE, rep=-5) def attempt_with(self, categorised, state): self.use_equipment(categorised) if cat.DOOMSDAY_DEVICE in categorised: self.data['completed'] = True self.succeed( "The fools cower in terror at your display of power. Finally" " they are forced to acknowledge your genius.", rep=randint(10, 15)) if cat.BEAST in categorised: if all(cat.AQUATIC in x.CATEGORIES for x in categorised[cat.BEAST]): self.fail( "While the beast is terrifying, the effect is" " unfortuantely significantly lessened the need for a " " large water tank, and the it's inability to move " " independantly. Perhaps you need to rethink your plan?") else: self.data['completed'] = True self.succeed( "Your monstrous creation rampages through campus in a" " most statisfying way. They will not forgot this.", rep=randint(5, 12)) if cat.HAND_WEAPON in categorised: self.fail( "Mere crude force is not the answer. You need some more" " fitting demonstration of your power.") class SubvertNews(Mission): NAME = "Subvert the news network" SHORT_DESCRIPTION = "Stop the lies!" LONG_DESCRIPTION = ( "Worringly, people appear to be easily duped by the lies broadcast" " about you. Time to fight fire with fire!") MINIMUM_REPUTATION = 15 MINIMUM_MILESTONE = "neighbourhood" NO_EQUIP_FAILURE = ( "You fail to even get into the building. Perhaps you need to" " rethink your approach") def attempt_with(self, categorised, state): self.use_equipment(categorised) if cat.MIND_CONTROL in categorised: self.succeed( "With the proper equipment, it's a simple matter to" " convince people of the correctness of your point" " of view. If only everything were so simple", rep=randint(5, 15)) if cat.AI in categorised: self.succeed( "Your AI has complete control of the broadcasters computer" " system. After all, it's not censorship if you're stopping" " them broadcasting blatant lies, now is it?", rep=randint(5, 10)) if any(c in categorised for c in (cat.VEHICLE, cat.DOOMSDAY_DEVICE, cat.BEAST)): self.succeed( "Cowering in fear, the broadcaster agrees to change the" " tone of their stories.", rep=randint(2, 5)) if cat.HAND_WEAPON in categorised: self.fail( "The news station's security is surprisingly well prepared." " Perhaps you should rethink your approach?", rep=-randint(5, 10)) class RaidLab(Mission): NAME = "Raid Rival Lab" SHORT_DESCRIPTION = "Why not let other people work for you?" LONG_DESCRIPTION = ( "While clearly no match for your genius, sometimes your rivals stumble" " onto something interesting. Surely their results can be put to" " better use helping your plans?") MINIMUM_MILESTONE = "neighbourhood" NO_EQUIP_FAILURE = ( "Your rival may not be the sharpest tool in the shed, but even a" " fool invests in some defenses. You'll need to be better prepared" " in the future.") def _succ(self, msg, state): reward = choice(('schematic', 'science', 'money', 'money', 'money', 'money', 'money', 'nothing', 'nothing', 'nothing')) if reward == 'nothing': self.succeed("%s Unfortunately, not only are these people working" " on ideas you've already covered, they're flat broke." % msg, money=0, rep=1) elif reward == 'money': self.succeed("%s While their research yields nothing of interest," " you can repurpose their funding to more worthy causes." % msg, money=randint(1000, 2000), rep=1) elif reward == 'schematic': self.succeed("%s You find the plans for a new device. How did" " these fools stumble upon this?" % msg, money=0, rep=randint(2, 5), new_schematic=choice(state.lab.new_schematics)) # New science self.succeed("%s Their notes are most illuminating. You realise you" " have sadly neglected research into this field." % msg, money=0, rep=randint(2, 5), new_science=choice(state.lab.new_research)) def attempt_with(self, categorised, state): self.use_equipment(categorised) if cat.DOOMSDAY_DEVICE in categorised: self.fail( "While overwhelming force is always a tempting choice," " total destruction of the lab will not help you cause.") if cat.AI in categorised: self.use_equipment_category(categorised, cat.AI) self._succ("Your AI easily takes control of the lab's network.", state) if cat.INTELLIGENCE in categorised: self.use_equipment_category(categorised, cat.INTELLIGENCE) self._succ("You are able to gather all the information needed" " to completely survert the lab defenses, making the actual" " takeover trivial", state) if self.combat_power(categorised) > randint(20, 40): self._succ( "The resistance is stiff, but your forces prevail" " thanks to your superior technology.", state) else: self.fail( "The lab is surprisingly well defended for an operation" " run by a total fool. You vow to return with a better" " prepared force.") class TerroriseCity(Mission): NAME = "Invade nearby city" SHORT_DESCRIPTION = "Need more resources" LONG_DESCRIPTION = ( "Sometimes it's nessecary to remind people of what you can do." " And why not do so close to home?") MINIMUM_MILESTONE = "city" NO_EQUIP_FAILURE = ( "Attacking a city with your bare hands. Perhaps not the best" " thought out scheme in the world. Fortunately, only your" " pride was hurt by this failure.") GENERIC_FAILURE = ( "You fail to accomplish your goal. A different approach seems" " called for.") def attempt_no_equipment(self, state): self.fail(self.NO_EQUIP_FAILURE, rep=-randint(10, 15)) def attempt_with(self, categorised, state): self.use_equipment(categorised) if cat.DOOMSDAY_DEVICE in categorised: self.succeed( "Destroying the city is a simple exercies with the right" " tools. People will tremble at the mention of your name", rep=randint(15, 25)) if cat.AI in categorised: self.succeed("Your AI easily takes control of the central" " network. It's not that scary, but it is profitable", money=randint(3000, 10000)) if cat.BEAST in categorised: if any(cat.AQUATIC in x.CATEGORIES for x in categorised[cat.BEAST]): rampage = 'harbour' else: rampage = 'streets' self.succeed( "Your creature's rampage through the city's %s terrifies" " the city's inhabitants. The city council are eager to" " pay you to rein it in. A most statisfying outcome" % rampage, money=randint(2000, 5000), rep=randint(5, 15)) if cat.VEHICLE in categorised: if self.combat_power(categorised) > randint(50, 70): self.succeed("Your overwhelming display of force cowers" " the city. Fear of you spreads.", rep=randint(10, 20)) else: self.fail( "Your forces prove unable to overcome the city's" " defenses. This is an annoying setback, but you" " vow to return.", rep=-randint(3, 7)) if cat.HAND_WEAPONS in categorised: self.fail("A sprinkling of small arms can't overcome the city's" " defenses. Something more impressive is required.") class SecureLair(Mission): NAME = "Secure island base" SHORT_DESCRIPTION = "A nice safe base of operations" LONG_DESCRIPTION = ( "It's a cliche, but there's a lot to be said for an isolated" " and secure base of operations. You can still control your" " city from afar. You just have to deal with the local inhabitants" " of your chosen location, but they should not present a problem") MINIONS_REQUIRED = 4 MINIMUM_MILESTONE = "city" MINIMUM_REPUTATION = 50 NO_EQUIP_FAILURE = ( "While the local defenses are weak, even they can deal with" " a few unarmed men. Something more suitable is required") GENERIC_FAILURE = ( "Your chosen tools aren't up to the task of securing the" " island. Perhaps you need to rethink your approach") def attempt_no_equipment(self, state): self.fail(self.NO_EQUIP_FAILURE, rep=-randint(10, 15)) def attempt_with(self, categorised, state): self.use_equipment(categorised) if cat.DOOMSDAY_DEVICE in categorised: self.fail( "You want to use the island afterward, and the local" " population can provide basic labour. Something less" " destructive is required.") if cat.AI in categorised: self.fail( "Your AI complains about the limited bandwidth and" " inadequate computing resources of the target, then" " goes off to sulk. A more physical approach may" " be required.") msg = ( " Afraid of the repurcusions, the people quickly build a base" " to your specifications") if (cat.BEAST in categorised and self.combat_power(categorised) > randint(20, 30)): self.data['completed'] = True self.succeed( "Your creature's terrifying rampage destroys all" " resistance, and you quickly conquer the island. %s" % msg, rep=randint(10, 15)) if cat.VEHICLE in categorised: if self.combat_power(categorised) > randint(20, 30): self.data['completed'] = True self.succeed("Your overwhelming display of force cowers" " the local population. The island is yours. %s" % msg, rep=randint(10, 15)) else: self.fail( "Your forces prove unable to overcome the local" " defenses.") class EliminateRival(Mission): NAME = "Eliminate Dr. X." SHORT_DESCRIPTION = "A rival. Inconcievable" LONG_DESCRIPTION = None # We handle this one specially MINIONS_REQUIRED = 3 MINIMUM_MILESTONE = "city" MINIMUM_REPUTATION = 50 NO_EQUIP_FAILURE = ( "While you'd like to tear Dr. X apart with your bare hands, you" " do need to deal with his pathetic defenses first.") GENERIC_FAILURE = ( "Somehow, Dr. X has thwarted your attack. You are quite surprised.") def _new_data(self): # How many times has Dr. X been beaten? self.data['times'] = 0 self.data['turn'] = 0 self.data['seen'] = False def get_description(self): if self.get_data('times') == 0: return ( "Recently, Dr. X has made some serious claims abut his" " capabilities. While it's laughable to believe he can" " actually back up his boasts, such statements cannot go" " unpunished.") elif self.get_data('times') == 1: return ( "Dr. X has returned. Hasn't he learnt from your previous" " encounter? This cannot go unpunished.") return ( "Dr. X has once again appeared on the scene. You suspect" " he's mixed his DNA with that of a cockroach, but, " " regardless of the cause, this cannot be ignored.") def can_attempt(self, state): if self.get_data('completed'): # does Dr. X return? if (state.turn > self.get_data('turn') + 2 and randint(0, 5) < (state.turn - self.get_data('turn'))): self.data['completed'] = False return True else: return False elif self.get_data('seen'): # Once he's appeared, he doesn't go unless completed return True if super(EliminateRival, self).can_attempt(state): self.data['seen'] = True # flag as seen return True return False def attempt_no_equipment(self, state): self.fail(self.NO_EQUIP_FAILURE, rep=-randint(10, 15)) def attempt_with(self, categorised, state): self.use_equipment(categorised) if cat.DOOMSDAY_DEVICE in categorised: self.data['completed'] = True self.data['times'] += 1 self.data['turn'] = state.turn self.succeed( "You crush Dr. X with your superior technology. He will" " not forgot this lesson anytime soon.", rep=randint(10, 20)) if cat.AI in categorised: self.fail( "Subverting Dr. X's network is simple enough for your AI," " but you are annoyed to discover that the doctor places" " little faith in computers, and there is nothing you can" " do to foil his plans this way") if (cat.BEAST in categorised and self.combat_power(categorised) > randint(40, 60)): self.data['completed'] = True self.data['times'] += 1 self.data['turn'] = state.turn self.succeed( "Your creature destroys Dr. X's lab. He will not quickly" " recover this setback", rep=randint(10, 20)) if cat.VEHICLE in categorised: if self.combat_power(categorised) > randint(40, 60): self.data['completed'] = True self.data['times'] += 1 self.data['turn'] = state.turn self.succeed( "Your forces easily overcome the doctor's defenses," " but Dr. X himself escapes. You are sure, however," " he will present no further threat to your plans.", rep=randint(10, 20)) else: self.succeed("Dr. X's defenses are better than you" " anticipated. You'll have to return with more" " firepower.", rep=-randint(3, 7)) class Publish(Mission): NAME = "Publish your results" SHORT_DESCRIPTION = "The world must know of your genius" LONG_DESCRIPTION = ( "You've seen further than others. Surely you can open their" " eyes to the truth (and secure your place in history)?") MINIMUM_REPUTATION = 5 MINIMUM_MILESTONE = "basement" NO_EQUIP_FAILURE = ( "The review board rejects your paper, clearly failing to" " realise the significant of your results") GENERIC_FAILURE = ( "You fail to persuade the review board of the need to publish" " your results. Perhaps a different appraoch is required?") def attempt_with(self, categorised, state): if cat.MIND_CONTROL in categorised: self.use_equipment_category(categorised, cat.MIND_CONTROL) self.data['completed'] = True self.succeed("With the correct persuasion, the review board" " recognises the significance of your work.", rep=randint(10, 15)) if cat.HAND_WEAPON in categorised: self.use_equipment_category(categorised, cat.HAND_WEAPON) self.data['completed'] = True self.succeed("The review board respond favourably to a little" " light intidimation, and your paper is accepted.", rep=randint(10, 15)) class DisruptMarkets(Mission): NAME = "Disrupt local enconomy" SHORT_DESCRIPTION = "Creating chaos and fear." LONG_DESCRIPTION = ( "People place far too much value on their money. This is a weakness" " that just begs to be exploited. And, in the chaos and fear, " " there's almost certainly and opportunity to profit.") MINIMUM_MILESTONE = "neighbourhood" MINIMUM_MONEY = 2000 NO_EQUIP_FAILURE = ( "You cannot beat the game just with your mind, doctor. You'll need" " to have some extra toys") GENERIC_FAILURE = ( "No-one notices your efforts. Back to the drawing board") def can_attempt(self, state): if state.money < self.MINIMUM_MONEY: # You need to be in the game to cheat at it return False return super(DisruptMarkets, self).can_attempt(state) def attempt_with(self, categorised, state): if cat.DOOMSDAY_DEVICE in categorised: return self.fail( "While destroying the area is certainly within your" " capabilities, and would cause wide-spread panic," " there seems little prospect of exploiting the" " confusion usefully at this time. You decide to" " shelve this plan for now.") if cat.WEATHER_MACHINE in categorised: self.use_equipment_category(categorised, cat.WEATHER_MACHINE) self.succeed( "You cunningly use your device to disrupt the nearby farmers." " The ensuing panic buyng of supplies is easy to exploit for" " profit.", money=randint(5000, 10000), rep=randint(5, 15)) if cat.AI in categorised: self.use_equipment_category(categorised, cat.AI) self.succeed( "You easily survert the local exchange's computer systems." " It hardly seems fair to profit off such a trivial challenge" " but there are always bills to pay", money=randint(5000, 10000), rep=randint(2, 5)) if cat.BEAST in categorised: self.use_equipment_category(categorised, cat.BEAST) self.succeed( "Releasing the monster into the exchange certainly created" " a stir, and there was much running and screaming, but, with" " the exchange closing it's doors until the creature was" " contained, there wasn't much opportunity to make a profit.", money=0, rep=randint(2, 5)) class ControlMayor(Mission): NAME = "Control the Mayor" SHORT_DESCRIPTION = "Minions in high places." LONG_DESCRIPTION = ( "While the mayor powers are limited, it's a step towards controlling" " the entire city") MINIMUM_MILESTONE = "neighbourhood" def attempt_with(self, categorised, state): if cat.CLONE in categorised: self.use_equipment_category(categorised, cat.CLONE) self.data['completed'] = True self.succeed( "Replacing the mayor with a copy under your control. Such" " a genius scheme could only come from a brain as brillant" " as yours.", rep=randint(10, 15)) if cat.MIND_CONTROL in categorised: self.use_equipment_category(categorised, cat.MIND_CONTROL) self.data['completed'] = True self.succeed( "Mind control. It's hardly a novel approach to the problem" " but who can argue with the results.", rep=randint(7, 15)) if cat.HAND_WEAPONS in categorised: self.fail( "Brute force. It seems such a crude approach. You decide" " this is unworthy of you and abandon the plan.") if cat.BEAST in categorised: self.fail( "In retrospect, unleashing a monster into the downtown streets" " was a great way to cause panic, but not a reliable method" " for securing the loyalties of the mayor. You return to" " the drawing board") class DisruptCityServices(Mission): NAME = "Disrupt city services" SHORT_DESCRIPTION = "Keep your name in the news" LONG_DESCRIPTION = ( "You're not being talked about in the news. This cannot be allowed" " to continue. Spreading chaos and fear will remind people about" " your presence.") MINIMUM_MILESTONE = "neighbourhood" MAXIMUM_REPUTATION = 10 NO_EQUIP_FAILURE = ( "There's little one unarmed man can do to disrupt the city. You'd" " better rethink this plan.") def can_attempt(self, state): if state.reputation > self.MAXIMUM_REPUTATION: return False return super(DisruptCityServices, self).can_attempt(state) def attempt_no_equipment(self, state): self.fail(self.NO_EQUIP_FAILURE, rep=-1) def attempt_with(self, categorised, state): if cat.DOOMSDAY_DEVICE in categorised: self.fail( "If there's no-one left alive, there'll be no-one to" " report on your genius. Prehaps less overkill is more" " suited to the task at hand") if cat.BEAST in categorised: self.use_equipment_catefory(categorised, cat.BEAST) if any(cat.AQUATIC in x.CATEGORIES for x in categorised[cat.BEAST]): self.succeed( "You release the beast into the city sewer system." " The resulting destruction is both expensive to" " repair and very visible to the inhabitants.", rep=randint(5, 10)) else: self.succeed( "The beast causes considerable property damage, and" " takes out a local substation. It's not a stunning" " victory, but it's enough to get you name in the" " news again", rep=randint(2, 5)) if cat.VEHICLE in categorised: self.use_equipment_catefory(categorised, cat.VEHICLE) self.succeed( "Your mobile platforms of destruction cause severe" " traffic chaos, and tie up the local traffic services" " for hours. The resulting traffic jams headline the" " evening news. It's not quite the what you were going" " for, but it's publicity", rep=randint(0, 3)) if cat.HAND_WEAPON in categorised: self.fail( "You want to be known as more than just a local gangster." " Guns are an efficient tool, but hardly the means to" " securing your reputation.") class RatArmy(Mission): NAME = "Breed Rat Burglars" SHORT_DESCRIPTION = "Your furry money source" LONG_DESCRIPTION = ( "Small and easy to breed. An army of rat burgulars will provide" " a useful supply of steady income") def can_attempt(self, state): if self.get_data('completed'): return False if state.lab.meet_requirements(Biogenetics, 1): return True return False def attempt_no_equipment(self, state): self.data['completed'] = True self.succeed( "You breed an army of small rats, engineered to steal small" " change. The resulting income is not much, but still useful", money=0, rep=0, income=randint(10, 15)) def attempt_with(self, categorised, state): self.fail( "You're overthinking this doctor. Perhaps a simpler approach" " will work better?")