Hello, loves!

I have a small idea that might help. Let’s see if it does. Interrupted by Tornado Warning.

We’d like to compute a room’s floor just once and then never revise it. Recomputing it now is harmless, because we don’t exert any control over it, but if we did do any special layout, we’d lose it, or have to rerun the special floor allocation code, which seems difficult.

So what if when we go to assign flooring, we just don’t assign it if it is already assigned? Might be just the thing.

When stepping, we allocate flooring on every step. If we didn’t do that, nothing would be visible: the dungeon IS its flooring, in essence.

class BuildStepper:
    def _do_one_step(self, view):
        self.table[self.index](self.layout, self.dungeon)
        if view:
            sub = view.dungeon.layout.subregion
            view.dungeon.layout.clear_subregions()
            maker = KeyedSpriteListMaker(self.dungeon)
            maker.update(view)
            view.dungeon.layout.subregion = sub
        self.index += 1

So lets see how the KeyedSpriteListMaker works:

    def __init__(self, dungeon):
        self.setup_assets()
        self._keyed_sprites = self.setup(dungeon)

    def setup(self, dungeon):
        keyed_sprites = KeyedSpriteList()
        self.create_room_sprites(dungeon, keyed_sprites)
        self.create_content_lists(dungeon, keyed_sprites)
        return keyed_sprites

    def update(self, view):
        view.keyed_sprites = self._keyed_sprites

    def create_room_sprites(self, dungeon, keyed_sprites):
        for room in dungeon.rooms:
            view = RoomView(room)
            for cell, sprite in view.generate_sprites(dungeon.layout):
                keyed_sprites.add(cell, sprite)

    def create_content_lists(self, dungeon, keyed_sprites):
        for cell, content in dungeon.layout.contents.items():
            for item in content:
                keyed_sprites.make_visible_content_sprite(item, cell)
                for contained_item in item.contained_items():
                    sprite = ContentSpriteMaker(contained_item.resources, contained_item.scale / 16).sprite
                    sprite.visible = False
                    keyed_sprites.add_content(contained_item, None, sprite)

class RoomView:
    def generate_sprites(self, layout):
        for cell in self.room:
            sprite = self.make_sprite(layout, cell)
            self.cell_sprites[cell] = sprite
            yield cell, sprite

    def make_sprite(self, layout, cell):
        texture = self._choose_flooring_texture(layout, cell)
        sprite = params.make_adjusted_sprite(cell, texture)
        return sprite

class KeyedSpriteList:
    def __init__(self, floor_list=SpriteList(), content_list=SpriteList()):
        self.content_by_cell = defaultdict(list)
        self.sprite_dict = dict()
        self.floor_sprite_list = floor_list
        self.content_sprite_list = content_list

    def add(self, cell_or_item, sprite):
        self.sprite_dict[cell_or_item] = sprite
        self.floor_sprite_list.append(sprite)

    def add_content(self, item, cell, sprite):
        self.content_by_cell[cell].append(sprite)
        self.content_sprite_list.append(sprite)
        self.sprite_dict[item] = sprite
        
    ...

If we were to change Room so that if cell_sprites already contained a sprite, we didn’t generate a new on or yield anything, wouldn’t that do what we need? No. The RoomView is generated dynamically. We need to keep the information in the Room itself, or get it from the Layout. Grr.

In fact, the cell_sprites member is useless. Remove it.

OK, who’s using the generate and how? Again:

class KeyedSpriteListMaker:
    def __init__(self, dungeon):
        self.setup_assets()
        self._keyed_sprites = self.setup(dungeon)

    def setup(self, dungeon):
        keyed_sprites = KeyedSpriteList()
        self.create_room_sprites(dungeon, keyed_sprites)
        self.create_content_lists(dungeon, keyed_sprites)
        return keyed_sprites

    def update(self, view):
        view.keyed_sprites = self._keyed_sprites

    def create_room_sprites(self, dungeon, keyed_sprites):
        for room in dungeon.rooms:
            view = RoomView(room)
            for cell, sprite in view.generate_sprites(dungeon.layout):
                keyed_sprites.add(cell, sprite)

OK, since we just jam our list back into the view, what if we first fetch the existing list from the view, update it, not changing existing flooring, and then put it back?

As things stand, we can’t do that because we don’t have the view at the right time. Let’s pass it in. Change Signature.

class KeyedSpriteListMaker:
    def __init__(self, view, dungeon):
        self.setup_assets()
        self._keyed_sprites = self.setup(dungeon)

Tornado Warning

So that ended that session when the phones and V and the big siren went off. Was very stormy. Now we have no damage, no power (but generator is running), no internet. Very distracted. Rolled back my experiments, will try again.

It wasn’t going badly but it was getting more intricate than I’d have liked. I did get to the point where the rooms were only updating their floors once, but I didn’t like how I had to do it. Thus the reset.

Friday AM

We have been running on generator for 15 hours or so, no internet, cell coverage nil, living like some kind of barbarians. I guess I’ll try to code. While I did manage to get the flooring computed only once yesterday, it seemed like the wrong way to do it. I’m not sure why, might just have been the fumbling it took but it seemed wrong. Let’s explore the process as it currently works in the non-stepping mode.

I’ll continue in the next article. See you there!