After I tried to write an ascii gui or engine (called "Knights") I started to have more motivation for Kaduria again. At least it seems to work for me. I realized that even Kaduria's source code is quite messy, it still has lot of stuff ready or almost ready while programming Knights I got a feeling that "here we go again..."
Item identification is one of features not yet present, because the current implementation of frame displaying (frame is static data) makes it difficult to do, yet not impossible. The main problem is the decision to use identification in first place. It's not mandatory in a roguelike game, but at least for some item groups it could be nice.
And by nice I mean annoying. I think magic items could benefit from identification, because then they would include an extra risk when using them, before they have been identified. There absolutely will not be cursed items in Kaduria and weapons will probably not have any magical properties. That way there would be a clear distinction between regular and magic objects.
Friday, 21 August 2015
Thursday, 23 July 2015
Evolution of diggers
In still unfinished Teemu 1.3 I was experimenting with so called 'diggers' which are corridor creating "robots" that can create clones of themselves which simply are the branching corridors of a labyrinth. I realized that diggers can be evolved to do much more than just labyrinths if you create a set of rules for them.
Currently I need diggers to create corridor systems for a 'catacomb' theme. They can be as simple as a straight corridor with branching corridors to both sides of the main corridor. This can be expressed in rules of having zero curvature, more than one branching rate and 100 percent double clone probability.
If you want regular labyrinths it's simple to give more curvature for both original digger and clones. The amount of curvature and changes in other data can be used to create different kind of labyrinth styles and I like the idea of just having extra corridor systems with more or less curvature. Those can be created to otherwise unoccupied areas of the level after the main structure creation has been done.
While this is all exciting I've had trouble implementing the new digger system, because there is a strange bug with searching of so called tile masks. When searching an entry point for diggers one way to do it is find mask values of tiles. So I can for example find water areas and start diggers from there. But for some reason the routine doesn't find room walls, even they do exist and I can even confirm the proper mask values are there by looking at the automap in debug mode.
So I guess I'll spend this day searching for that bug.
ps. Well, that was quick. The bug happened, because 'small rooms' were created after the level theme creation in where I was calling the digger routine, so those rooms weren't even there at the moment the digger routine was called. That also seems to be true for some other routines, because I get some debug error messages of the search routine trying to look for parts of rooms.
Currently I need diggers to create corridor systems for a 'catacomb' theme. They can be as simple as a straight corridor with branching corridors to both sides of the main corridor. This can be expressed in rules of having zero curvature, more than one branching rate and 100 percent double clone probability.
If you want regular labyrinths it's simple to give more curvature for both original digger and clones. The amount of curvature and changes in other data can be used to create different kind of labyrinth styles and I like the idea of just having extra corridor systems with more or less curvature. Those can be created to otherwise unoccupied areas of the level after the main structure creation has been done.
While this is all exciting I've had trouble implementing the new digger system, because there is a strange bug with searching of so called tile masks. When searching an entry point for diggers one way to do it is find mask values of tiles. So I can for example find water areas and start diggers from there. But for some reason the routine doesn't find room walls, even they do exist and I can even confirm the proper mask values are there by looking at the automap in debug mode.
So I guess I'll spend this day searching for that bug.
ps. Well, that was quick. The bug happened, because 'small rooms' were created after the level theme creation in where I was calling the digger routine, so those rooms weren't even there at the moment the digger routine was called. That also seems to be true for some other routines, because I get some debug error messages of the search routine trying to look for parts of rooms.
Saturday, 4 July 2015
Realistic gameplay and torches
The current equipment has a slot for light sources. It's kind of "third" hand to hold the torch or whatever. You still have left and right hand slots where you can equip weapons and shields.
However if you want to be realistic you should have only two hands to hold things. But is it worth it? If you need one hand for the light source you would not be able to hold a shield when fighting in poor lighted places, not to mention two-handed weapons. You could always drop the light source on ground (in Kaduria it's possible, the item will still work as a light source) before fighting, but it would be quite annoying I guess.
The way to make it less annoying would be lot of lights around the dungeon in most places. This is actually what I'm planning to do anyway and it could be a nice way to reduce the need for a personal light source. But then again, dungeon wall torches are the great role-playing example of unrealistic light sources, because they never go out. If they did, they would be always burnt out, unless there is an army of goblins replacing them all the time.
I like the idea of "more" realistic gameplay, but you have to be really careful or it will create some tedious tasks for the player who start to hate it after a while. I know I would.
However if you want to be realistic you should have only two hands to hold things. But is it worth it? If you need one hand for the light source you would not be able to hold a shield when fighting in poor lighted places, not to mention two-handed weapons. You could always drop the light source on ground (in Kaduria it's possible, the item will still work as a light source) before fighting, but it would be quite annoying I guess.
The way to make it less annoying would be lot of lights around the dungeon in most places. This is actually what I'm planning to do anyway and it could be a nice way to reduce the need for a personal light source. But then again, dungeon wall torches are the great role-playing example of unrealistic light sources, because they never go out. If they did, they would be always burnt out, unless there is an army of goblins replacing them all the time.
I like the idea of "more" realistic gameplay, but you have to be really careful or it will create some tedious tasks for the player who start to hate it after a while. I know I would.
Friday, 26 June 2015
Refactoring - that was it
I had to refactor the Spawner class. It's creating lists of items (or any object types) for later creation, because you need somehow determine which items are created in various places. The hard work is done in the initialization where lists are created, by going through object data for each object type.
The way I programmed Spawner class was somewhat dumb, because I used raw std::vectors to hold items. Nothing wrong with that, but it makes internal bookkeeping impossible, since there is no way to know what are actually stored in those lists.
Refactoring was quite simple. I made a Spawner_Item class which holds that std::vector with the name of the list. For some reason I thought it was a good idea to create a function for each item type, such as Spawner::Get_Land_Trap() which then returned a trap that can be created on dungeon floor. The problem is that after a while the number of functions increase. So in the refactored version there is one function to get a random item from a pool, in this case Get_Random_Item(spaw::Land_Traps) where spaw is the namespace for spawning applications.
There are quite lot of functions to replace with new implementation, but I was able to rewrite the new one on top of the old one so they are working at the same time. It's what you always hope that happens when you have to refactor something, that way you can still run the game without problems and slowly replace the old implementation.
The bookkeeping feature was useful right away when I noticed there were no traps for containers. They didn't exist so the spawner list was empty for them. Later it's also possible to write a debug function to watch the list of items, not just the amount of items per list and you can check out if somehow the list contains something it should not have.
Now, as I said something has changed in the development and I think it may be refactoring (or rewriting, it's the same thing). When I was rewriting Spawner class I had a funny feeling it was something I had been doing all these years and only recently I've been programming new stuff as well.
The way I programmed Spawner class was somewhat dumb, because I used raw std::vectors to hold items. Nothing wrong with that, but it makes internal bookkeeping impossible, since there is no way to know what are actually stored in those lists.
Refactoring was quite simple. I made a Spawner_Item class which holds that std::vector with the name of the list. For some reason I thought it was a good idea to create a function for each item type, such as Spawner::Get_Land_Trap() which then returned a trap that can be created on dungeon floor. The problem is that after a while the number of functions increase. So in the refactored version there is one function to get a random item from a pool, in this case Get_Random_Item(spaw::Land_Traps) where spaw is the namespace for spawning applications.
There are quite lot of functions to replace with new implementation, but I was able to rewrite the new one on top of the old one so they are working at the same time. It's what you always hope that happens when you have to refactor something, that way you can still run the game without problems and slowly replace the old implementation.
The bookkeeping feature was useful right away when I noticed there were no traps for containers. They didn't exist so the spawner list was empty for them. Later it's also possible to write a debug function to watch the list of items, not just the amount of items per list and you can check out if somehow the list contains something it should not have.
Now, as I said something has changed in the development and I think it may be refactoring (or rewriting, it's the same thing). When I was rewriting Spawner class I had a funny feeling it was something I had been doing all these years and only recently I've been programming new stuff as well.
Sunday, 21 June 2015
New style
Back a while I was talking about how non-monospace fonts are really cool for editor fonts, but I've since then moved back to monospace. I have also moved the output window to left side of the screen and class browser to right side. That way there is no window at the bottom and the code window can be as tall as possible with more lines of code. I guess power users would use two monitors, but I've never felt it was the solution for me and also I don't even have space for that in my small desk. First world problems!
Then I changed colors to dark background theme with dark grey background and some colors for different stuff like keywords, strings, etc. I've used light (white) background theme for a long time. Somehow I feel the new style is doing something, if nothing else it's just good to see something different when you spend days, months and years programming.
ps. While watching more closely that function I realized it doesn't need that Coords parameter and it's also shadowed in the routine. It's already fixed so I don't need to be embarrassed about it.
Then I changed colors to dark background theme with dark grey background and some colors for different stuff like keywords, strings, etc. I've used light (white) background theme for a long time. Somehow I feel the new style is doing something, if nothing else it's just good to see something different when you spend days, months and years programming.
ps. While watching more closely that function I realized it doesn't need that Coords parameter and it's also shadowed in the routine. It's already fixed so I don't need to be embarrassed about it.
Tuesday, 16 June 2015
The Mountain of Doom
I have a clever and original analogy for creating a roguelike which is climbing a mountain, or maybe more like building a mountain. When you start the project there is lot of stuff to create at the base of the mountain and it's quite easy to add that stuff, but as you climb higher it becomes harder even the amount of features you still need are few. What makes the mountain steeper near the top is the realization that you need more details for some things than you expected when you started the project.
I want to convince myself that I'm now climbing at the steep part of the mountain, because I can feel a change in the way I'm programming the project. Each feature I'm able to remove from the todo list feels like one step closer to the top. But as I said the mountain is becoming steeper when I think of new ways to add more complexity to the gameplay. The top of the mountain is covered in clouds so it's impossible to see it from where I am now.
I want to convince myself that I'm now climbing at the steep part of the mountain, because I can feel a change in the way I'm programming the project. Each feature I'm able to remove from the todo list feels like one step closer to the top. But as I said the mountain is becoming steeper when I think of new ways to add more complexity to the gameplay. The top of the mountain is covered in clouds so it's impossible to see it from where I am now.
Wednesday, 20 May 2015
Level map save
As usual the save/load routine has involved more work than I thought. I've reduced it to the hardest part which is saving the level map. The old map with individual 'byte' maps for each layer was easy to save, because the byte map had a built in RLE (run-length encoding) packing. The estimation for 50 levels each average size of 100x100 tiles is 3,5Mb of space unpacked. How much is it compared to modern save files I don't know (I don't play PC games (other than roguelikes)), but it would be much less when compressed.
As expected the compression routine must be custom created to be compatible for both the save file format and map format which contains four mandatory variables to be saved: the tile itself (terrain), fov value (known tiles), mask and room id. These four variables can't be reproduced from any other data. The mask value is mostly used in the level's creation process, but it might just be used during the game in pathfinding situations.
RLE in theory is easy to implement, but the custom data structure and save format makes it somewhat more complicated. RLE also works quite nicely with typical dungeon levels of rooms and other areas with mostly 'empty' space (walls) between them.
As expected the compression routine must be custom created to be compatible for both the save file format and map format which contains four mandatory variables to be saved: the tile itself (terrain), fov value (known tiles), mask and room id. These four variables can't be reproduced from any other data. The mask value is mostly used in the level's creation process, but it might just be used during the game in pathfinding situations.
RLE in theory is easy to implement, but the custom data structure and save format makes it somewhat more complicated. RLE also works quite nicely with typical dungeon levels of rooms and other areas with mostly 'empty' space (walls) between them.
Subscribe to:
Posts (Atom)
