view gamelib/gamestate.py @ 42:47c7e96cf9c8

Change initial mission creation logic to look for leaf classes
author Neil Muller <drnlmuller@gmail.com>
date Mon, 07 May 2012 14:00:18 +0200
parents e285b1e31a08
children 1e8f7e694f0c
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 gamelib import missions, lab, products


class Game(object):

    def __init__(self, init_data=None):
        self.money = 1000
        # Will be updated on the next turn
        self.points = 0
        self.reputation = 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 missions.Mission.__subclasses__():
                if cls.__subclasses__():
                    # Not a leaf class, so base class for other missions
                    continue
                # Add mission to the list
                self.missions.append(cls())

    def start_turn(self):
        # Make more flexible?
        self.points += 3
        self.cur_missions = []
        self.cur_allocation = []

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

    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 end_turn(self):
        # Attempt the missions
        mission_results = []
        for mission, equipment in self.cur_missions:
            mission_results.append(mission.attempt(equipment, self))
        # 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
        # Process mission results
        for result in mission_results:
            result.apply(self)
        for science in new_stuff:
            # FIXME: Update UI better.
            print "You learned new stuff:", science.NAME

    def save_data(self):
        """Serialize the game state into a dict"""
        data = {}
        data['money'] = self.money
        data['reputation'] = self.reputation
        data['points'] = self.points
        data['lab'] = self.lab.serialize()
        # 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.reputation = data['reputation']
        self.points = data['points']
        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]))