Пример #1
0
    def __draw_geology(self, item):
        ###########################################################################
        draw_mode = curr_draw_mode()
        prequire(is_geological(draw_mode), "Bad draw mode ", draw_mode)

        self._draw_with_offset("geology",
                               item.__class__.__name__.lower() + ".jpg",
                               (100, 100))

        # Figure out what string to print and what color it should be
        if (draw_mode == DrawMode.GEOLOGY):
            pass  # already drawn
        elif (draw_mode in [DrawMode.TENSION, DrawMode.MAGMA]):
            value = item.tension() if draw_mode == DrawMode.TENSION \
                else item.magma()
            to_draw = ("%.3f" % value)

            if (value < .333):
                color = _GREEN
            elif (value < .666):
                color = _YELLOW
            else:
                color = _RED

            self._print_with_offset(to_draw, color, (30, 40))
        else:
            prequire(False, "Should not draw geology in mode: ", draw_mode)
Пример #2
0
    def __gain_exp_impl(self, exp):
        ###########################################################################
        check_access(self.ALLOW_GAIN_EXP)

        self.__exp += exp

        # Check for level-up
        while (self.__exp >= self.__next_level_cost):
            self.__level += 1

            old_max = self.__max_mana
            self.__max_mana = self.__MANA_POOL_FUNC(self.level())
            self.__mana_regen = self.__max_mana * self.__MANA_REGEN_RATE
            increase = self.__max_mana - old_max
            self.__mana += increase

            self.__exp -= self.__next_level_cost
            self.__next_level_cost = self.__EXP_LEVEL_COST_FUNC(self.level())

        # Check exp invariant
        prequire(self.__exp < self.__next_level_cost, "exp(", self.__exp,
                 ") > ", "next_level_cost(", self.__next_level_cost, ")")

        # Check mana invariant
        prequire(self.__mana <= self.__max_mana, "mana(", self.__mana,
                 ") > max_mana(", self.__max_mana, ")")
Пример #3
0
def exp_growth(base, value, threshold=0, diminishing_returns=None):
    ###############################################################################
    prequire(base > 1, "Invalid base: ", base)

    x = value - threshold

    if (x < 0.0):
        # We're more aggressive on the penalty side. We want to reward
        # the player for having all of the ingredients in place, so
        # being weak in a certain ingrediant is heavily penalized.
        return pow(base + ((base - 1.0) * 2), x)
    elif (diminishing_returns is None or x <= diminishing_returns):
        return pow(base, x)
    else:
        beyond_dim = x - diminishing_returns

        # Compute divisor of exponent based on base; IE divisor of 2 would
        # give sqrt behavior. The idea is for the more-slowly growing functions
        # to plateou faster.
        divisor = 2.0
        if (base <= 1.02):
            divisor = 5.0
        elif (base <= 1.03):
            divisor = 4.0
        elif (base <= 1.05):
            divisor = 3.0

        additional = pow(beyond_dim, 1.0 / divisor) - 1  # root
        if (additional < 0.0):
            additional = 0.0

        return pow(base, diminishing_returns) + additional
Пример #4
0
    def __destroy_defense(self, levels):
        ###########################################################################
        check_access(self.ALLOW_DESTROY_DEFENSE)

        prequire(self.defense() >= levels, "Invalid destroy levels: ", levels)

        self.__defense -= levels
Пример #5
0
def _compute_nearby_food_and_prod_tiles(location,
                                        filter_tiles_near_other_cities=False):
    ###############################################################################
    """
    Returns a 2-ple of (food-tiles, production-tiles); both lists are sorted
    from highest to lowest based on yield. Only unworked tiles are added.
    """
    world = engine().world()
    food_tiles = []  # sorted highest to lowest
    prod_tiles = []  # sorted highest to lowest
    row, col = location.unpack()
    for row_delta in xrange(-1, 2):
        for col_delta in xrange(-1, 2):
            # Cannot work tile that has city
            if (row_delta != 0 or col_delta != 0):
                loc_delta = Location(row + row_delta, col + col_delta)
                if (world.in_bounds(loc_delta)
                        and not (filter_tiles_near_other_cities
                                 and _is_too_close_to_any_city(loc_delta, 1))):
                    tile = world.tile(loc_delta)
                    prequire(
                        not (filter_tiles_near_other_cities and tile.worked()),
                        "How can tile be worked if it's not near a city")
                    if (not tile.worked()):
                        if (tile.yield_().food > 0):
                            _ordered_insert(food_tiles, tile)
                        else:
                            _ordered_insert(prod_tiles, tile)

    return food_tiles, prod_tiles
Пример #6
0
    def help(cls, extra_args=None):
    ###########################################################################
        if (_is_text_interface()):
            full_usage = "%s  Learnable spells:\n" % cls._TEXT_USAGE

            # Add info on learnable spells to usage string
            for spell_name, spell_level in engine().player().learnable():
                full_usage += "    %s%s\n" % (spell_name,
                                          "" if spell_level == 1 else " (new)")

            return _create_text_help_str(cls, full_usage)
        else:
            prequire(extra_args is not None and len(extra_args) == 1,
                     "Expect spell name in extra_args")

            spell_name = extra_args[0]
            spell = SpellFactory.create_spell(spell_name)

            help_str = cls._GRAPHICAL_USAGE
            help_str += "\nDescription of %s spell:\n" % spell_name
            help_str += spell.info() + "\n"
            help_str += "Player has skill level %d in this spell\n" % \
                engine().player().spell_skill(spell_name)

            return help_str
Пример #7
0
    def __cycle_turn_impl(self):
        ###########################################################################
        check_access(self.ALLOW_CYCLE_TURN)

        cls = self.__class__
        world = engine().world()
        cities_orig = list(world.cities())

        # Manage cities. Note that this may cause additional cities to
        # be created, which is why we needed the list copy above
        for city in cities_orig:
            city.cycle_turn()

        # Adjust tech based on population
        tech_points = cls.__TECH_POINT_FUNC(self.population())
        self.__tech_points += tech_points

        # Check if level-up in tech
        while (self.__tech_points >= self.__next_tech_level_cost):
            self.__tech_level += 1
            self.__tech_points -= self.__next_tech_level_cost  # rollover points
            self.__next_tech_level_cost = \
                cls.__TECH_NEXT_LEVEL_COST_FUNC(self.tech_level())

        # Tech invariants
        prequire(self.__tech_points < self.__next_tech_level_cost,
                 "Expect tech-points(", self.__tech_points, ") < tech-cost(",
                 self.__next_tech_level_cost, ")")
Пример #8
0
    def __compute_atmos_color(self, draw_mode, field_value):
    ###########################################################################
        for upper_bound, color in self._ATMOS_FIELD_COLOR_MAP[draw_mode]:
            if (field_value < upper_bound):
                return color

        prequire(False,
                 "Failed to find color for ", draw_mode, ", val ", field_value)
Пример #9
0
    def __compute_color(self, draw_mode, field_value, color_map):
        ###########################################################################
        for upper_bound, color in color_map[draw_mode]:
            if (field_value < upper_bound):
                return color

        prequire(False, "Failed to find color for ", draw_mode, ", val ",
                 field_value)
Пример #10
0
 def instance(cls):
     """
     Retrieve singleton instance. Note this does *not* construct the
     singleton if it does not exist; the private creation class method
     needs to be called to create the singleton.
     """
     prequire(cls.__instance is not None, "Uninitialized global instance")
     return cls.__instance
Пример #11
0
    def _base_tension_buildup(cls): prequire(False, "Must override")

    #
    # ==== Implementation ====
    #

    ###########################################################################
    def __init_impl(self, plate_movement):
Пример #12
0
    def __cast_impl(self, spell):
        ###########################################################################
        check_access(self.ALLOW_CAST)

        self.__mana -= spell.cost()

        # Maintain mana invariant (m_mana is unsigned, so going below zero will
        # cause it to become enormous).
        prequire(self.__mana <= self.__max_mana, "mana(", self.__mana,
                 ") > max_mana(", self.__max_mana, ")")
Пример #13
0
def create_interface():
    ###############################################################################
    interface = _get_inteface_config_str()

    if (Interfaces.TEXT == interface):
        return TextInterface()
    elif (Interfaces.PYGAME == interface):
        return PygameInterface()
    else:
        prequire(False, "Missing support for ", interface)
Пример #14
0
    def __cycle_turn_impl(self):
    ###########################################################################
        check_access(self.ALLOW_CYCLE_TURN)

        # Tension/magma build up more slowly as they reach 100%
        self.__tension += (1 - self.__tension) * self.__tension_buildup
        self.__magma   += (1 - self.__magma)   * self.__magma_buildup

        prequire(self.__tension < 1.0, "Invariant violated: ", self.__tension)
        prequire(self.__magma   < 1.0, "Invariant violated: ", self.__magma)
Пример #15
0
    def __validate_invariants_impl(self):
    ###########################################################################
        level_sum = 0
        for spell_name, spell_level in self.__learned_spells.iteritems():
            prequire(spell_level >= 1 and spell_level <= self._MAX_SPELL_LEVEL,
                     "Bad spell level: ", spell_level)
            level_sum += spell_level

        prequire(self.__num_learned == level_sum,
                 "Num-learned invariant failed")
Пример #16
0
    def __contains_impl(self, spell_spec):
    ###########################################################################
        if (isinstance(spell_spec, Spell)):
            spell_tuple = (spell_spec.name(), spell_spec.level())
        else:
            prequire(type(spell_spec) == tuple)
            spell_tuple = spell_spec

        spell_name, spell_level = spell_tuple
        return spell_name in self.__learned_spells and \
            spell_level <= self.__learned_spells[spell_name]
Пример #17
0
    def __cycle_turn_impl(self):
        ###########################################################################
        check_access(self.ALLOW_CYCLE_TURN)

        self.__mana += self.__mana_regen
        if (self.__mana > self.__max_mana):
            self.__mana = self.__max_mana

        # Maintain mana invariant
        prequire(self.__mana <= self.__max_mana, "m_mana(", self.__mana,
                 ") > m_max_mana(", self.__max_mana, ")")
Пример #18
0
    def __init__(self): prequire(False, "Do not instantiate Command")

    #
    # ==== Public API ====
    #

    #
    # Instance API
    #

    def apply(self):
Пример #19
0
    def parse_command(cls, text):
    ###########################################################################
        """
        Given some command text, create a Command object
        """
        # Get command name
        tokens = text.split()
        prequire(tokens, "Empty string made it into CommandFactory")
        name = tokens[0]

        # Instantiate and return new Command object
        return cls.get(name)(tokens[1:])
Пример #20
0
    def _instance(cls):
        ###########################################################################
        """
        Do not call. Use free function to get a handle to an Engine
        """
        if (cls.__instance is None):
            prequire(not cls.__initializing,
                     "Engine instantiation has re-entered itself")
            cls.__initializing = True
            cls.__instance = Engine()
            cls.__initializing = False

        return cls.__instance
Пример #21
0
    def __build_infra(self, tile):
        ###########################################################################
        prequire(tile.can_build_infra(), "Error in build eval")

        infra_level = tile.infra_level()
        next_infra_level = infra_level + 1
        prod_cost = next_infra_level * City._INFRA_PROD_COST
        if (prod_cost < self.__prod_bank):
            self.__prod_bank -= prod_cost
            tile.build_infra()
            return True

        return False
Пример #22
0
    def __kill_impl(self, killed):
        ###########################################################################
        check_access(self.ALLOW_KILL)

        prequire(self.__population >= killed, "Invalid killed: ", killed)

        self.__population -= killed

        while (self.__population <
               self.__next_rank_pop / City._CITY_RANK_UP_MULTIPLIER
               and self.__rank > 1):
            self.__rank -= 1
            self.__next_rank_pop /= City._CITY_RANK_UP_MULTIPLIER
Пример #23
0
    def help(cls, extra_args=None):
    ###########################################################################
        if (_is_text_interface()):
            return _create_text_help_str(cls, cls._TEXT_USAGE)
        else:
            prequire(extra_args is not None and len(extra_args) == 1,
                     "Expect draw_mode in extra_args")
            draw_mode = extra_args[0]

            help_str =  cls._GRAPHICAL_USAGE
            help_str += "\nDescription of draw-mode %s:\n" % draw_mode
            help_str += explain_draw_mode(draw_mode)

            return help_str
Пример #24
0
 def __get_field_for_draw_mode(self, item, draw_mode):
     ###########################################################################
     if (draw_mode == DrawMode.WIND):
         return item.wind().speed()
     elif (draw_mode == DrawMode.DEWPOINT):
         return item.dewpoint()
     elif (draw_mode == DrawMode.TEMPERATURE):
         return item.temperature()
     elif (draw_mode == DrawMode.PRESSURE):
         return item.pressure()
     elif (draw_mode == DrawMode.PRECIP):
         return item.precip()
     else:
         prequire(False, "Bad draw mode: ", draw_mode)
Пример #25
0
    def __draw_time(self, item):
    ###########################################################################
        # Compute color
        if (item.season() == Season.WINTER):
            color = BLUE
        elif (item.season() == Season.SPRING):
            color = GREEN
        elif (item.season() == Season.SUMMER):
            color = RED
        elif (item.season() == Season.FALL):
            color = YELLOW
        else:
            prequire(False, "Unhandled season ", item.season())

        cprint(color, item.season(), ", Year ", item.year())
Пример #26
0
    def __init_impl(self, width, height, tiles):
    ###########################################################################
        self.__width  = width
        self.__height = height
        self.__time   = Time()

        self.__rows = []
        total = 0
        for idx, tile in enumerate(tiles):
            if (idx % width == 0):
                self.__rows.append([])
            self.__rows[-1].append(tile)
            total += 1

        prequire(total == width * height, "Wrong number of tiles")

        self.__recent_anomalies = []
        self.__cities           = []
Пример #27
0
 def draw(self, item):
     ###########################################################################
     if (isinstance(item, Time)):
         self.__draw_time(item)
     elif (isinstance(item, Geology)):
         self.__draw_geology(item)
     elif (isinstance(item, Player)):
         self.__draw_player(item)
     elif (isinstance(item, PlayerAI)):
         self.__draw_player_ai(item)
     elif (isinstance(item, Atmosphere)):
         self.__draw_atmosphere(item)
     elif (isinstance(item, Anomaly)):
         self.__draw_anomaly(item)
     elif (isinstance(item, World)):
         self.__draw_world(item)
     elif (isinstance(item, WorldTile)):
         self.__draw_world_tile(item)
     else:
         prequire(False, "Class not drawable: ", item.__class__)
Пример #28
0
    def __draw_time(self, item):
        ###########################################################################
        # Compute color
        if (item.season() == Season.WINTER):
            color = _BLUE
        elif (item.season() == Season.SPRING):
            color = _GREEN
        elif (item.season() == Season.SUMMER):
            color = _RED
        elif (item.season() == Season.FALL):
            color = _YELLOW
        else:
            prequire(False, "Unhandled season ", item.season())

        self._print_with_offset("%s, Year: %s" % (item.season(), item.year()),
                                color, (200, 5),
                                font=self._LARGE_FONT)

        self.__y_pos += 30
        self.__x_pos = 0
Пример #29
0
    def __draw_geology(self, item):
    ###########################################################################
        draw_mode = curr_draw_mode()
        prequire(is_geological(draw_mode), "Bad draw mode ", draw_mode)
        expected_length = self.TILE_TEXT_WIDTH

        # Figure out what string to print and what color it should be
        if (draw_mode == DrawMode.GEOLOGY):
            color, symbol = self._GEOLOGY_MAP[item.__class__]

            to_draw = symbol.center(expected_length)
        elif (draw_mode in [DrawMode.TENSION, DrawMode.MAGMA]):
            value = item.tension() if draw_mode == DrawMode.TENSION \
               else item.magma()
            to_draw = ("%.3f" % value).center(expected_length)

            if (value < .333):
                color = GREEN
            elif (value < .666):
                color = YELLOW
            else:
                color = RED
        else:
            prequire(False, "Should not draw geology in mode: ", draw_mode)

        prequire(len(to_draw) == self.TILE_TEXT_WIDTH,
                 "Symbol '", to_draw, "' is wrong length")

        cprint(color, to_draw)
Пример #30
0
    def __draw_land_property(self, draw_mode, tile):
        ###########################################################################
        self.__draw_land(tile)

        if (draw_mode == DrawMode.MOISTURE):
            field = tile.soil_moisture()
        elif (draw_mode == DrawMode.YIELD):
            field = tile.yield_()
        elif (draw_mode == DrawMode.ELEVATION):
            field = tile.elevation()
        elif (draw_mode == DrawMode.SNOWPACK):
            field = tile.snowpack()
        elif (draw_mode == DrawMode.SEASURFACETEMP):
            field = tile.sea_surface_temp()
        else:
            prequire(False, "Unknown draw mode ", draw_mode)

        if (field is not None):
            color = self.__compute_color(draw_mode, field,
                                         self._LAND_COLOR_MAP)
            to_draw = self.__determine_precision(field)

            self._print_with_offset(to_draw, color, (30, 40))