Source

Fat x Fast / FatxFast / tilemap / maze / content_filler.py

Full commit

# This file is part of FatxFast.
#
#    FatxFast is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    FatxFast is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with FatxFast.  If not, see <http://www.gnu.org/licenses/>.

# Versioning based on: 
# http://en.wikipedia.org/wiki/Versioning#Designating_development_stage
__author__ = "dryatu (c) 2013"
__version__ = "1.2.5"

from FatxFast.objects import triggers
from FatxFast.tilemap.maze.mazecell import CELL_ID, STARTCELL_ID, ENDCELL_ID
from FatxFast.tilemap.maze.solver import get_dead_ends, get_linear_tiles
from FatxFast.tilemap.editor import tile
from math import sqrt
import random

class MazeContentGen(object):
    
    def __init__(self, maze):
        self.maze = maze
        self.entity_ids = set([triggers.COFFEE_ID])

    def _create_item(self, x, y, **kwargs):
        self.maze.create_object(x, y, 
            tile.TILEWIDTH, tile.TILEHEIGHT, "entity", **kwargs)

    def generate_items(self, items, item_types=None):
        """Integer amount of random items
        or a dictionary of predefined items.

        item_types as a set of entity_ids

        Safe to call multiple times"""
        if item_types is not None:
            self.entity_ids = item_types
        generate = True
        if isinstance(items, int):
            self._generate_random_items(items)
        else:
            self._generate_items(items)
    
    def _generate_random_item(self):
        return random.sample(self.entity_ids, 1)[0]

    def _generate_random_items(self, item_count):
        cells = get_linear_tiles(self.maze.cellcontainer)
        for item_id in xrange(item_count, 0, -1):
            cell = random.sample(cells, 1)[0]
            item_to_create = self._generate_random_item()
            if cell.entity_id == CELL_ID:
                item_name = str(item_to_create)+"#"+str(item_id)
                self._create_item(
                    *self._generate_random_position_in_cell(cell), 
                    name=item_name,
                    entity_id=item_to_create)

    def _generate_random_position_in_cell(self, cell):
        min_x, min_y = cell.rect.x, cell.rect.y
        max_x = min_x+((self.maze.floor_width-1)*tile.TILEWIDTH)
        max_y = min_y+((self.maze.floor_height-1)*tile.TILEHEIGHT)
        x, y = random.randint(min_x, max_x), random.randint(min_y, max_y) 
        return x, y

    def _generate_items(self, items):
        for item in items.values():
            self._create_item(**item)

    def _get_random_start_pos(self, end):
        des = list(get_dead_ends(self.maze))
        random.shuffle(des)
        if des:
            for de in des:
                if (sqrt(pow((de.column-end[0]), 2)+pow((de.row-end[1]), 2)) \
                    >= sqrt(pow((end[0]), 2)+pow((end[1]), 2))/2):
                    return de
            return des[0]
        else:
            return self.maze.get_cell((0,0))

    def set_start_and_end(self, start=None, end=None):
        """Sets the start and the end cell. If start isn't
        supplied it will pick a random dead end at the minimum distance of
        half the map. Changes the tiles to S&E""" 
        if end is None:
            end = (self.maze.columns-1, self.maze.rows-1)
        endcell = self.maze.get_cell(end)
        endcell.entity_id = ENDCELL_ID

        if start:
            startcell = self.maze.get_cell(start)
        else:
            startcell = self._get_random_start_pos(end)
        
        startcell.entity_id = STARTCELL_ID
        self.maze.we.tile_map.properties["start_x"] = startcell.rect.x
        self.maze.we.tile_map.properties["start_y"] = startcell.rect.y
        self.maze.create_cell_floor_object(startcell, self.maze.tiles["start"], 
            "trigger", triggers.START_ID)
        end_x, end_y = self._generate_random_position_in_cell(endcell)
        self.maze.create_object(end_x, end_y, 
            tile.TILEWIDTH, tile.TILEHEIGHT, "trigger", invisible=0,
            imagename="nekpc.png", entity_id=triggers.END_ID)
        #self.maze.create_cell_floor_object(endcell, self.maze.tiles["end"], 
        #    "trigger", END_ID)