Sunday, 19 January 2020

Is this... refactoring?

I think it is, but in a nice way. At least it doesn't feel that bad, and it's more like re-arranging the source code. The first step was actions as procedures, but it's also possible to create classes with an outlook at the basic data. For example today I programmed a look command to an external class Look. It takes in Level and Avatar (aka player) data and then determines different ways to look at things. The source code was largely previously both in Level and Avatar classes which increased their size and distributed functionality in lots of small member functions.

In comparison the Look class is focused and has only one public "entry point" function. This prevents confusion when you pass the data into class almost as if it was a procedure. From maintain perspective it's also easier, because when you need to fix something in looking you know where to find everything. Only low level routines are in Level and Player classes to return some atomic piece of data.

I don't know, maybe it took a good while to realize that actions should be detached from classes like Level to keep them simple, in cases where actions need two or more (large) classes in them. And also, that procedural style can be better in some situations which, undoubtebly, has been a troublesome concept for me to accept, since I have been such a fan and connoisseur of object-oriented programming.

Tuesday, 7 January 2020

Actions in action

Now that I have programmed some actions as procedures it becomes clear how nice it is. And, since they largely maintain object-oriented paradigm it doesn't even break the code that way. It's almost like calling a library function from a class. It's great how actions like kicking or digging can be reduced to one linear function which is much easier to manage than when the code is spread in classes. It's such a simple concept, but it works.

This brings back an old argument that C is "better" than C++. In this case I would say it sure seems like it, but obviously it's not the whole story. Managing data and resources in classes is certainly better than C's procedural style.

The actions.cpp has 6 functions at the moment and it's 367 lines of code. I'm planning to keep everything in one file, because it seems quite fitting when they are only functions. The final size can be anything, but I doubt it will be an impossible amount of lines. The number of lines in this project is moderate, because the excellent quality of the code.

Monday, 30 December 2019

Actions as procedures

There is one more technical thing I've tried and it actually works. The background for this "issue" is the way OOP can fragment the code if you need more than one class where any particular class doesn't have a "major" role. It can also be fragmented by inheritance.

If there is a complex action it can become quite annoying to implement in OOP fashion, but in C++ you don't have to, since it's a multi-paradigm language. A real life example is digging with pickaxe. It's happening both in Level class and Creature/Player class, but when you create a procedure (I'm trying to avoid the word 'function' here, because there are functional programmers stalking everywhere) and in this case only one procedure which takes Level, Creature, digging item and direction as parameters, it removes the confusion by unification of the code.

A procedure solves more than one problem. First it's making the code less fragmented and in this case the procedure becomes a linear collection of actions. It's also removing code from Level and Creature classes which often become large and difficult to maintain. Not only that, with C++ you can take care of a procedure not breaking OOP, because the procedure can use class code without any side effects of regular, non-functional style.

Obviously you could do this with OOP as well, using a special class to handle this the same way, but it's the exact same thing. Where this works really well are actions such as digging, but then again it does solve only a particular problem of complex structure. OOP in general is better for low level code, handling data etc.

Sunday, 15 December 2019

Year 2020 for Kaduria

Recently I've done right things and this project is going forward even it doesn't seem like it. The development is clearly shifting from technical stuff to content. I predict that 2020 will be difficult to Kaduria and also myself, because I have some real life problems. Well, the biggest problem is money as usual.

Thursday, 14 November 2019

Lighting issue

I'm working on fov and lighting as you should after 110 years of development. I have a new fov routine, but there is a problem in lighting. When each tile has independent fov and light values it will create a situation where the wall is lit from the opposite side. Imagine there is a lamp in a room and the room's door is closed. You can still see the wall lit when you are outside the room, because the lamp has to lit the "inside" walls of rooms as well. Obviously, the inside and outside walls are the same, since roguelike 2D maps usually have it that way.

I don't recall any games that have gradual lighting and how they solved it, if at all. I guess one way to try is have data for each facing of a wall, but it may get complicated. More so if the light source is on the wall itself, as some kind of wall lamp. Then things get even more complicated, unless you give the light source information about which side of the wall it is.

Whatever the solution, I have to do something about both fov and lighting finally, because in a weird way having both fov and lighting helps in dungeon design, because everything looks very different if you don't have fov on in particular.

Sunday, 13 October 2019

Progress on dungeon generation

Back in some years I ran into trouble with a large scale data-driven system developed for the dungeon generation. It seems like data-driving works best in local, isolated contex just like many other things in programming. Since then I've been breaking the data-driven system into level theme classes, using only some data-driven parts.

The good thing is that most sub-systems can be run directly from theme classes with some minor changes in the way data is passed into them.

In the past I used to think that level generation is complex, but in reality it's quite simple. As always the main point is first making a decision what the level actually contains, rather than thinking about doing it later. When you say "I'm going to do it later" you are in trouble.

Most of the building blocks are ready and about half of the themes have a basic structure. There is even a simple street generation routine for town levels where I made an observation that by storing and comparing distances from previous locations you can space the things without having to do it manually. However after all these years it's hilarious when you proceed to the next level you realize there is more to it.

I'm going to be happy if the basic structures of all themes are ready before the end of this year, because after that it's much easier to add the rest with sub-systems that mostly work by filling in the rest of the free space.

Monday, 9 September 2019

Coordinates rewrite

Each object used to store coordinate data, but for objects that don't move I thought having that data in the object itself was a waste of space. Obviously there has been complications when coordinates were removed from some object types. The way I'm storing game objects are in a list, because it's an easy way to keep them in ownership of the level. The display map is doing most of the work by having only handles to visible objects.

Since items (those items you pick up in the game) work a bit different way I have to write a unique list for them. The generic list did have some static_casts to item class for that reason and I guess it's good to remove those routines. There are some other object types that use coordinates in that context, but they are easier to fix I think.

There is also a change in the way I'm documenting issues in the source code. I used to write "note:" followed by explanation in the source code, but those seem to disappear in the code. I think it's better to create an issue list with number for each issue and then fix them the same way as bugs. That way you can see the list growing and if you don't do anything it's going to be infinitely long.