[WIP] Traditional tilebased roguelike


#1

I’ve been working on a roguelike for the past couple of months and now it’s gotten to a point where’s it’s actually playable, although just barely.

A short GIF of the current state:
rogue_01_11_18_1

The main functionality I’ve implemented so far is random map generation, movement, melee combat and stats, weapons, some enemy logic, and tiles. I’m currently working on the menus and inventory, after that the game should be a bare-bones roguelike!

The maps are generated using binary space partitioning. I’ve decided for rectangular maps so there’s no “empty space” like in cave based maps since memory is scarce. The combat is loosely based on D&D style dice throws, just something that works for now. Pathfinding is done with IDA* because of memory restrictions. It works well but takes a lot of tries when the path is “complex” (eg. other room). I’ve limited the range quite a lot because of that, it’s ok though since the screen is small you come in range a bit after the enemies are visible on the screen. To fit the UI on the screen I’m using this great 3x5 font: https://community.arduboy.com/t/3x5-font-for-those-with-good-eyesight/4920

Not sure what the story is going to be like yet, but most likely “climb to the tower’s n-th floor and defeat the necromancer and return with his item.”

I’ll be posting updates as I go along!


(Simon) #2

Looks great so far. Gld you found a use for this little font!


(Matt) #3

Agreed, looks good so far. Looking forward to trying it.

I like how you did the walls. It’s hard to convey depth with such small space and only two colors.


#4

@filmote Thanks. Yeah I much prefer it over the default font, thanks for making it!

@city41Thanks!


#5

Got around to implementing some menus. You can now pick up, drop and equip items. Figuring out how the menus should be structured, since there’s only two buttons available. I think I’m going with a “context” menu that displays all the actions possible on the current tile and also has options to enter other menus.

basic_menus

Also switched to using PlatformIO and Clion for development, I’m happy with it and am able to develop faster. Now only if I could debug better. Wanted to check out gdb since I think it should be possible to use it with sim-avr but didn’t get around to it yet.


(Stephane C) #6

Man, this game is so close to what I wanted to work on… I wish you the best to complete that project.


(Boti Kis) #7

Work together on it. <3


#8

Thanks @Vampirics! Didn’t have much time the last few months but got back around to it now.

Implemented the stairs and the “game over” screen, and cleaned up the code a bit. Started to run out of run RAM at around 70% used at compile time :scream: Which is not a bad thing actually, forces me to scope down a bit. Pathfinding is a bit stack intensive I think. Does anyone have any tips on debugging the memory usage at runtime?

climb_stairs

death


(Josh Goebel) #9

What is the path finding where you lay down numbers on the grid and just count how far you are from where you want to be and then just pick the smallest number? Seems like if you used the buffer between turns you’d have MORE than enough RAM without needing the stack at all. You’d lay down the numbers in iterative passes (no recursion needed). With 1024 bytes you can plot a 32x32 grid, meaning monsters up to 32 squares away from you could “smell” you (assuming the entire route wasn’t blocked - in which case you’d need to move closer).

Or up to 16 away if you just centered the square on the player’s current position. And monsters any further away just wouldn’t be aware of the player yet and would move randomly.


#11

You mean if I used the screen buffer for the pathfinding?

Right now I’m just using IDA* with very short max paths (5 or 6 tiles aways I think). I’ve thought this would be a limitation but it’s actually better to limit the NPC vision since the levels are 16 by 16 atm. So if the NPCs could detect you from further away they would all just gang on you the moment you enter the level.

But I do want to save on RAM definitely, so it is possible to reuse the screen buffer for whatever between draws?


(Josh Goebel) #12

But I do want to save on RAM definitely, so it is possible to reuse the screen buffer for whatever between draws?

Yes, it’s not doing anything BETWEEN draws. :wink: I mean that presumes you have to repaint the WHOLE buffer each time, but that’s what most games already do anyways.


(Josh Goebel) #13

You said you were having issues with the stack. The solution I’m proposing doesn’t put any pressure on the stack… just because you have 32x32 available doesn’t mean you’d have to use it all. Monster more than x distance from the player could just ignore the player - even if the pathing COULD lead them to the player.

Example:

@ = player

567898765
4*******4
432111234
4321@1234
432111234
432222234

If a monster is on top of 9 it needs to move to 8 (or less), etc.


#14

Great, I’ll look into repurposing it then, thanks! I do repaint every frame yes.


#15

Yeah, that it a great solution and could make other things possible like you said - smell, or maybe sleeping enemies that wake with sound. I’ll try to move the current implementation to use the display buffer first since I got that working now. Thanks for the nice example :slightly_smiling_face:


(Josh Goebel) #16

Well really all the pathing gives you is “distance”/direction. So you can invent as mean random reasons as you like to why the monster might follow you… it hears you, smells you, senses you telepathically, etc. They are really all the same thing - unless you add other levers in your game that change your stinkiness/loudness/mental activity, etc… like if you ate a smelly fish, or had iron armor (noisy) vs leather (quiet), or had a magic wizard hat (no brainwaves leaking out of that). Etc. :slight_smile:


(Pharap) #17

You can use this to check stack size:

(In case you’re wondering, “ptrdiff_t is the signed integer type of the result of subtracting two pointers”.)

It’s best used in places where you’re expecting the stack to fall over, like in a recursive function, or where there’s a lot of depth,
and you’re probably best sending the result over serial rather than trying to print it on screen.

This function is more for debugging, diagnosing and locating existing problems than it is for anything else,
so you’d be best off leaving it out of the release version.

Also you’ll know if the stack overflows because the Arduboy will reset.
(This was a problem encountered in @filmote and @Vampirics’s Space Taxi, which I helped debug.)


(Josh Goebel) #18

I think on tiny embedded platforms (like Arduboy) it’s probably best to simply avoid deep recursion anywhere you possibly can.


(Pharap) #19

It is, but for algorithms like path finding the alternative to recursion is to use corecursion and maintain a separate stack,
at which point you have to decide on either a maximum size for the stack or use dynamic memory to allocate more memory as needed.

Corecursion is generally a better solution than recursion for both embedded systems and desktops, but it takes a bit of extra effort to figure out.