Forbidden Lore Design Diary #8: The Sidewalk Ends with FIREBALLS

Got some worrying personal information tonight. So, I buried myself in programming. Nothing like some scrolls of fireball to distract oneself from loved one suffering over a thousand miles away.

Today’s lesson: ranged attacks! Status effects! Crowd control!

In addition to Potions of Healing, the tutorial has now guided me to create a Scroll of Lightning Bolt, Scroll of Confusion, and Scroll of Fireball. Since magical shenanigans lie at the heart of the game I want to create, I was paying close attention.

Of course, if I’m adding arcane devastation to the mix, I felt like I had to beef-up the monsters a bit. Instead of randomly sticking between zero and two of them in every room, the engine now seeds the room with between zero and five of them. Only seems fair.

I was also not impressed with how the tutorial handled fireballs. To show the area of effect, it presented a simple square — even though the blast radius is very much a RADIUS. You know, a circle. So the beasties in the square may or may not have gotten tagged by the spell depending on how close to the corners they were.

Time to do some off-road coding.

    def highlight_radius(
            self, 
            center: Tuple[int, int], 
            radius: int,
            console: Console,
            bg_color: Tuple[int, int, int], 
            fg_color: Tuple[int, int, int],
        ) -> None:
        """
        Twiddle the foreground and background colors of all visible tiles within a circle
        """
        x, y = center
        max_x = min(x + radius, self.width)
        max_y = min(y + radius, self.height)
        min_x = max(x - radius, 0)
        min_y = max(y - radius, 0)
        for check_x in range (min_x, max_x + 1, 1):
            for check_y in range (min_y, max_y + 1, 1):
                if (self.distance((x, y), (check_x, check_y)) <= radius 
                        and (self.tiles['walkable'][check_x, check_y])
                        and (self.explored[check_x, check_y])):
                    
                    console.tiles_rgb["bg"][check_x, check_y] = bg_color
                    console.tiles_rgb["fg"][check_x, check_y] = fg_color
        

    def distance(self, start: Tuple[int, int], end: Tuple[int, int]) -> int:
        """
        Returns the distance between two grid points, rounded up.
        
        Might someday be enhanced to care about whether or not those two points on the grid
        can actually see each other; for now, just a Pythagorean Theorem wrapper.
        """
        x1, y1 = start
        x2, y2 = end
        return int(round(math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)))

Yup, that’s effectively the first proper Python code I’ve written myself. Results in something that looks like this:

WHO WANTS SOME

Everything highlighed in red there is gonna get hit by a fireball. How do they feel about it?

FRAGABOOOOM

They were not fans. Killed the four orcs outright, and definitely took a chunk out of both trolls.

In addition, I figured out how to update the mouseover text to show you the critter’s current health. The game needs more feedback in general, but that’s a first step towards showing you that what you did had an effect even if you foe didn’t drop.

But this iteration of the game marked another milestone. After I took that screenshot, I went back to the code for another round of fiddling. At that point, I should just escape out of the game and restart it … but I wanted to see if I could keep going. After blasting that room, I wanted to see if I could keep going, clear out the dungeon before I got overwhelmed.

And I did it. And I felt kinda like a badass.

This was the first time I had fun with this game as a GAME.

It is still, objectively, kind of a piece of shit. But it’s a piece of shit that has stretches were it’s damned interesting. This is kind of awesome.

Anyway. I’ve hit the end of this version of the tutorial. The tutorial is an update of an older version that just hasn’t gotten to all the chapters the author wanted to cover. So I can keep going, but I won’t be able to copy-paste like I used to. Now, I’m going to have to figure out a lot of the details on my own.

That feels manageable. That feels like a good exercise at this stage, really.

So, next step: figuring out how to save the game.

I wanna take a BIG ol’ detour into laying down an initial version of the magic system, one that doesn’t rely on one-shot items. But, no, saving and loading the game is super important, and I should probably figure out how that works sooner rather than later.