view gamelib/gamestate.py @ 161:6fdc985429a7

Display research advice.
author Jeremy Thurgood <firxen@gmail.com>
date Fri, 11 May 2012 22:29:23 +0200
parents f4601492020b
children 4bbd4a1879f8
line wrap: on
line source

# -*- coding: utf-8 -*-
# vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4

"""The actual game state object"""

from random import choice

from gamelib import missions, lab
from gamelib.game_base import get_subclasses
from gamelib.constants import M_VALS, INFO


class Game(object):

    def __init__(self, init_data=None):
        self.money = 1000
        self.milestone = "basement"
        # Will be updated on the next turn
        self.minions = 0
        self.points = 0
        self.reputation = 0
        self.turn = 0
        # Missions being attempted
        self.cur_missions = []
        # Science allocation for the current turn
        self.cur_allocation = []
        self.lab = None
        self.missions = []
        if init_data:
            self._load_data(init_data)
        else:
            self.lab = lab.Lab()
            # instantiate all the available missions
            for cls in get_subclasses(missions.Mission):
                self.missions.append(cls())

    def start_turn(self):
        # Make more flexible?
        self.points += 1 + M_VALS[self.milestone] * 2
        self.minions += 1 + M_VALS[self.milestone] * 2
        self.turn += 1
        self.cur_missions = []
        self.cur_allocation = []
        # Suggest research
        basic_research, suggestions = self.lab.suggest_research()
        if basic_research:
            suggestions.append(None)
        self.advice = choice(suggestions)
        if self.advice is None:
            self.advice = ("Leave some researchers unassigned."
                           " They might turn up something cool.")
        else:
            self.advice = "Our work in %s is looking promising." % (
                self.advice.NAME,)

    def get_available_equipment(self):
        """Return a list of equipment we can produce and afford"""
        available = [x for x in self.lab.science
                     if x.SCIENCE_TYPE == 'schematic' and x.COST <= self.money]
        return available

    def get_all_equipment(self):
        """Return a list of equipment we could produce, regardless of cost"""
        equipment = [x for x in self.lab.science
                     if x.SCIENCE_TYPE == 'schematic']
        return equipment

    def get_available_missions(self):
        """Return a list of missions we can feasibly attempt"""
        available = [x for x in self.missions if x.can_attempt(self)]
        return available

    def get_available_points(self):
        return self.points - len(self.cur_allocation)

    def apply_mission_special(self, new_milestone=None):
        if new_milestone:
            self.milestone = new_milestone

    def end_turn(self):
        # Attempt the missions
        mission_results = []
        for mission, equipment in self.cur_missions:
            mission_results.append(mission.attempt_mission(equipment, self))
        if not self.cur_missions and self.reputation > 0:
            # If you're not doing stuff, you're not in the news
            self.reputation -= M_VALS[self.milestone]
        # Do the science
        self.points -= len(self.cur_allocation)
        if self.points < 0:
            raise RuntimeError('Spent too many points')
        new_stuff = self.lab.spend_points(self.cur_allocation, self.points)
        self.points = 0
        self.minions = 0
        # Process mission results
        messages = []
        for result in mission_results:
            result.apply(self)
            messages.append((result.outcome, result.text, result.loot))
        for science in new_stuff:
            # FIXME: Update UI better.
            messages.append((INFO, "SCIENCE breakthrough!", {
                        science.SCIENCE_TYPE: science}))
        return messages

    def save_data(self):
        """Serialize the game state into a dict"""
        data = {}
        data['money'] = self.money
        data['minions'] = self.minions
        data['reputation'] = self.reputation
        data['milestone'] = self.milestone
        data['points'] = self.points
        data['lab'] = self.lab.save_data()
        data['turn'] = self.turn
        # Save mission state
        data['missions'] = {}
        for mission in self.missions:
            miss_name = type(mission).__name__
            data['missions'][miss_name] = mission.save_data()
        return data

    def _load_data(self, data):
        """Restore the game state"""
        self.money = data['money']
        self.minions = data['minions']
        self.reputation = data['reputation']
        self.points = data['points']
        self.turn = data['turn']
        self.milestone = data['milestone']
        self.lab = lab.Lab(data['lab'])
        for mis_class in missions.Mission.__subclasses__():
            miss_name = mis_class.__name__
            if miss_name in data['missions']:
                self.missions.append(mis_class(data['missions'][miss_name]))