view gamelib/schematics.py @ 216:ec97f80feae0

Capitilize schmatic names
author Neil Muller <drnlmuller@gmail.com>
date Sat, 12 May 2012 20:42:17 +0200
parents d378459567bb
children 837c51ebdbc8
line wrap: on
line source

# -*- test-case-name: gamelib.tests.test_schematics -*-

from gamelib import research
from gamelib.game_base import Science


class SchematicCategorySet(object):
    def __init__(self, *categories):
        for cat in categories:
            setattr(self, cat, cat.lower().replace('_', ' '))

cat = SchematicCategorySet(
    'HAND_WEAPON',
    'VEHICLE',
    'DOOMSDAY_DEVICE',
    'PATHOGEN',
    'MIND_CONTROL',
    'BEAST',
    'AQUATIC',
    'INTELLIGENCE',
    'AI',
    'COUNTERMEASURE',
    'SPACE',
    'WEATHER_MACHINE',
    'CLONE',
    )

K = 1000
M = 1000 * K


class Schematic(Science):
    # For all Schematics
    SCIENCE_TYPE = 'schematic'

    # Acquisition
    STARTING_PRODUCT = False
    ACQUISITION_CHANCE = 0.8
    CATEGORIES = ()

    # Costs
    UPGRADE_REQUIREMENT = 1
    COST = None
    MAX_UPGRADE = 5

    # Power and reliability
    PROTOTYPE_RELIABILITY = 0.4
    PRODUCTION_RELIABILITY = 0.8
    BASE_POWER = None
    POWER_INCREMENT = None

    # FIXME: Icons for equipment.
    IMAGE_NAME = "physics"

    FAILURE_TEXT = "Your equipment failed in an excitingly disastrous manner."

    def can_spend(self, lab, spend):
        if self.points + spend > self.MAX_UPGRADE:
            return False
        extra = self.UPGRADE_REQUIREMENT * (self.points + spend)
        return lab.meet_requirements(self, extra)

    def is_a(self, category):
        return category in self.CATEGORIES

    def reliability(self):
        if self.points:
            exp = 1 + 0.5 * (self.points - 1)
            return 1.0 - ((1.0 - self.PRODUCTION_RELIABILITY) ** exp)
        return self.PROTOTYPE_RELIABILITY

    def power(self):
        power = self.BASE_POWER
        if None not in (power, self.POWER_INCREMENT):
            power += self.POWER_INCREMENT * self.points
        return power

    @classmethod
    def sanity_check(cls):
        for science, points in cls.PREREQUISITES:
            assert issubclass(science, Science)
            assert isinstance(points, int)
        assert isinstance(cls.CATEGORIES, tuple)


class MachineGun(Schematic):
    NAME = "Machine gun"
    COST = 100
    IMAGE_NAME = "schematics/handgun"
    CATEGORIES = (cat.HAND_WEAPON,)
    STARTING_PRODUCT = True

    BASE_POWER = 10
    PRODUCTION_RELIABILITY = 1.0

    def __init__(self, points=0):
        self.points = 1


class LightningGun(Schematic):
    NAME = "Lightning gun"
    COST = 300
    IMAGE_NAME = "schematics/handgun"
    CATEGORIES = (cat.HAND_WEAPON,)
    PREREQUISITES = (
        (research.Electrickery, 1),
        )

    BASE_POWER = 15
    POWER_INCREMENT = 3
    PRODUCTION_RELIABILITY = 0.7

    FAILURE_TEXT = (
        "Your lightning gun dropped an insulator, leaking volts and coulombs"
        " all over the place.")


class TeslaTank(Schematic):
    NAME = "Tesla tank"
    COST = 40 * K
    CATEGORIES = (cat.VEHICLE,)
    PREREQUISITES = (
        (research.Electrickery, 5),
        (research.Robotics, 1),
        )

    BASE_POWER = 100
    POWER_INCREMENT = 10

    FAILURE_TEXT = (
        "The cheap knock-off capacitors in the primary charge module of the"
        " Tesla tank knocked off, leading to much excitement.")


class PropagandaMachine(Schematic):
    NAME = "Propaganda machine"
    COST = 1000
    IMAGE_NAME = "schematics/mindcontrol"
    CATEGORIES = (cat.MIND_CONTROL,)
    PREREQUISITES = (
        (research.Psychology, 2),
        )

    BASE_POWER = 10
    POWER_INCREMENT = 2

    FAILURE_TEXT = (
        "The propaganda machine printed reams of carefully structured"
        " nonsense, which the proofreaders didn't catch until too late.")


class MindControlRay(Schematic):
    NAME = "Mind control ray"
    COST = 4 * K
    CATEGORIES = (cat.MIND_CONTROL,)
    IMAGE_NAME = "schematics/mindcontrol"
    PREREQUISITES = (
        (research.Psychology, 6),
        (research.MedicalExperiments, 6),
        )

    BASE_POWER = 40
    POWER_INCREMENT = 6

    FAILURE_TEXT = (
        "The frequency tuner on the mind control ray was slightly"
        " miscalibrated. A new genre of glitterpop was born, but this"
        " entirely fails to advance your shadowy agenda.")


class GiantSquid(Schematic):
    NAME = "Giant squid"
    COST = 50 * K
    CATEGORIES = (cat.BEAST, cat.AQUATIC)
    PREREQUISITES = (
        (research.MarineBiology, 20),
        (research.Biogenetics, 15),
        )

    BASE_POWER = 200
    POWER_INCREMENT = 20


class SpiderGrenade(Schematic):
    NAME = "Spider grenade"
    COST = 500
    CATEGORIES = (cat.HAND_WEAPON,)
    PREREQUISITES = (
        (research.Biogenetics, 3),
        (research.Physics, 2),
        )

    BASE_POWER = 22
    POWER_INCREMENT = 2

    PRODUCTION_RELIABILITY = 0.6

    FAILURE_TEXT = (
        "Explosions full of spiders. What could possibly go wrong? Oh god!"
        " They're everywhere! EVERYWHERE! Get them off me!")


class CyberneticImplants(Schematic):
    NAME = "Cybernetic implants"
    COST = 1500
    CATEGORIES = (cat.HAND_WEAPON, cat.INTELLIGENCE)
    PREREQUISITES = (
        (research.MedicalExperiments, 5),
        (research.Robotics, 5),
        )

    BASE_POWER = 25
    POWER_INCREMENT = 5

    PRODUCTION_RELIABILITY = 0.9

    FAILURE_TEXT = (
        "Exciting buffer overflows in your neural interface. I'll spare you"
        " the gruesome details.")


class TornadoMachine(Schematic):
    NAME = "Tornado machine"
    COST = 7 * K
    CATEGORIES = (cat.VEHICLE, cat.WEATHER_MACHINE)
    IMAGE_NAME = "schematics/weathermachine"
    PREREQUISITES = (
        (research.Meteorology, 6),
        (research.Physics, 5),
        )

    BASE_POWER = 40
    POWER_INCREMENT = 8

    FAILURE_TEXT = (
        "Tornados! Dropping cows on you! Hardly conducive to mission success.")


class MonsterBear(Schematic):
    NAME = "Giant bear"
    COST = 10 * K
    CATEGORIES = (cat.BEAST,)
    PREREQUISITES = (
        (research.Biogenetics, 3),
        )

    BASE_POWER = 50
    POWER_INCREMENT = 5


class SharksWithFrickinLasers(Schematic):
    NAME = "Sharks with frickin' lasers"
    COST = 15 * K
    CATEGORIES = (cat.BEAST, cat.AQUATIC)
    PREREQUISITES = (
        (research.MarineBiology, 10),
        (research.Lasers, 7),
        )

    BASE_POWER = 75
    POWER_INCREMENT = 10


class ObservationDrone(Schematic):
    NAME = "Observation drone"
    COST = 6000
    CATEGORIES = (cat.INTELLIGENCE,)
    PREREQUISITES = (
        (research.Robotics, 3),
        )

    BASE_POWER = 25
    POWER_INCREMENT = 5


class SpySatellite(Schematic):
    NAME = "Spy satellite"
    COST = 100 * K
    CATEGORIES = (cat.INTELLIGENCE, cat.SPACE)
    PREREQUISITES = (
        (research.Rocketry, 5),
        (research.Space, 1),
        )

    BASE_POWER = 250
    POWER_INCREMENT = 50


class TacticalAI(Schematic):
    NAME = "Tactical AI"
    COST = 10 * K
    CATEGORIES = (cat.AI, cat.INTELLIGENCE)
    PREREQUISITES = (
        (research.ArtificialIntelligence, 3),
        )

    FAILURE_TEXT = (
        "Everything seems to be going smoothly until the AI decides it"
        " needs to rule the world itself. Fortuantely, you are able to purge"
        " it from the system before it becomes a legitimate rival.")


class LaserGun(Schematic):
    NAME = "Laser gun"
    COST = 300
    CATEGORIES = (cat.HAND_WEAPON,)
    IMAGE_NAME = "schematics/handgun"
    PREREQUISITES = (
        (research.Lasers, 2),
        )
    BASE_POWER = 20
    POWER_INCREMENT = 2
    PRODUCTION_RELIABILITY = 0.6

    FAILURE_TEXT = (
        "The carefully crafted electronics of the laser fail in a spectacular"
        " shower of sparks and bangs.")


class EmpMissile(Schematic):
    NAME = "EMP missile"
    COST = 1500
    CATEGORIES = (cat.COUNTERMEASURE,)
    PREREQUISITES = (
        (research.Electrickery, 5),
        (research.Rocketry, 2),
        )


class DoomsdayVirus(Schematic):
    NAME = "Doomsday virus"
    COST = 100 * K
    CATEGORIES = (cat.DOOMSDAY_DEVICE, cat.PATHOGEN)
    IMAGE_NAME = "schematics/pathogen"
    PREREQUISITES = (
        (research.Biogenetics, 5),
        )

    BASE_POWER = 1000
    POWER_INCREMENT = 500

    PRODUCTION_RELIABILITY = 0.6


class GiantRobot(Schematic):
    NAME = "Giant robot"
    COST = int(1.5 * M)
    CATEGORIES = (cat.DOOMSDAY_DEVICE, cat.AI)
    PREREQUISITES = (
        (research.Robotics, 15),
        (research.ArtificialIntelligence, 10),
        )

    BASE_POWER = 700
    POWER_INCREMENT = 300

    PRODUCTION_RELIABILITY = 0.7


class OrbitalLaserPlatform(Schematic):
    NAME = "Orbital laser platform"
    COST = 10 * M
    CATEGORIES = (cat.DOOMSDAY_DEVICE, cat.SPACE)
    IMAGE_NAME = "schematics/doomsdaydevice"
    PREREQUISITES = (
        (SpySatellite, 3),
        (research.Lasers, 15),
        (research.Space, 5),
        )

    BASE_POWER = 1500
    POWER_INCREMENT = 200


class WeatherControlStation(Schematic):
    NAME = "Weather control station"
    COST = 15 * M
    CATEGORIES = (cat.DOOMSDAY_DEVICE, cat.SPACE, cat.WEATHER_MACHINE)
    IMAGE_NAME = "schematics/weathermachine"
    PREREQUISITES = (
        (SpySatellite, 3),
        (research.Lasers, 5),
        (research.Space, 8),
        (research.Meteorology, 15),
        )

    BASE_POWER = 2200
    POWER_INCREMENT = 150


class Android(Schematic):
    NAME = "Lifelike android"
    COST = 50 * K
    CATEGORIES = (cat.INTELLIGENCE, cat.AI, cat.CLONE)
    PREREQUISITES = (
        (research.ArtificialIntelligence, 5),
        (research.Robotics, 5),
        )

    BASE_POWER = 10
    POWER_INCREMENT = 1

    PRODUCTION_RELIABILITY = 0.6

    FAILURE_TEXT = (
        "The sudden stuttering speech and sparks from the joints are the first"
        " signs that things have gone horribly wrong. The ensuing explosion"
        " of the android is merely the inevitable conclusion of the diaster.")