Wednesday 31 July 2013

What I think about bugs

Good old captain told me "there will always be bugs". Those words ring in my ears. I think not, captain. In reality bugs are always a result of what you do. There are rare compiler bugs, but they are also often caused by stretching the limits of the language by using unneccessary complex programming style.

Programmers are egoistic people. They don't want to admit their own errors, but instead use excuses like "there will always be bugs". Programming languages like C have played a big role in this mess, because it lets you write poor quality code. However it's still you who suck, not the language.

When I look at some open source projects I can already tell why there are lots of bugs and developers spend huge amount of time trying to fix them. The problem is always how you could tell these people to learn better programming practices? It never works that way. It's always up to personal interest to learn more and try not to pretend like you know everything better which you don't if you produce large number of bugs.

Kaduria has four open bugs at the moment. Yes. Four, as in 4. I want to keep the number of bugs low, but also prevent them with strict programming rules. You can never rely on yourself as some kind of machine who never make mistakes, so it's important to follow rules that, if not always prevent, at least reduces errors. What those rules are depend on personal programming style and language, because some languages have features which almost always explain bugs.

I find it easier to become a better programmer, because then you spend far less time hunting those bugs you could have prevented. So keep this in mind: if your project has lots of bugs you suck.

Monday 29 July 2013

It's a trap

There was this bug I wanted to fix. When you looked at a trap it was telling the name of the trap, like poison gas trap. But how could the player know that before stepping onto it? I had to fix that by adding "identified" flag in Trap class and returning a generic name like "pressure plate" if the trap was not identified.

Following the new std::string message style I wanted to make the generic name const. In C++ const is a immutable variable, something that can't be changed once it's set. The problem was that Get_Name() returned plain char* and it is a virtual function of 15 total game object classes. So there was some of that good old const correctness when I changed all those routines to return const char*. It wasn't that bad and at least now it's done.

I've had my personal issues with const correctness, because it's sometimes difficult to grasp the concept of const. It's not that I don't use const. I'm using it almost always when setting up local pre-calculated variables etc. because it really eliminates one way (a subtle one) to create bugs. But when using const in data it can create a long chain where everything else must also be const. However lately I've started to use const in my framework routines etc. so it's becoming easier to be correct.

The bug was fixed, but I started to think about how messages work in Creature class and I guess there are some things to consider. Sometimes messages are constructed for all creatures when in fact only player can generate the message. The message output can be limited to the player, but the message itself can be constructed for all actors and it can slow down the game when there is a large number of creatures in the level. It's something I have to remember when I get into details of the Creature class routines.

Saturday 27 July 2013

The palace

Small room item creation bug was fixed. Rooms are now in a list which also means I can create the interior later. It's an idea I've had for rooms to form "houses" by checking out where a room is connected and then determining the room interior.

There was also a bug in a return value of one routine. I used int return value with -1 as failure and 0 as success. It doesn't sound bad, but it can be since I was thinking zero was failure when I called the routine. It's easy to make that mistake since I'm using zero for failure in routines that return object handle. In cases like this it's much safer to use bool as return value. This bug was only telling that there was no room to create item in a small room. It didn't do anything else.

The actual bug was in the search routine which had no room mask id included so the area of search could include tiles outside the room. In theory, because the room rectangle should be good enough. So this is one of the few bugs that were fixed by an accident. I don't know what happened.

I'm reading a booklet The Oxford Handbook of The Bronze Age Aegean. The famous Knossos palace is interesting, because it was kind of a labyrinth with no clear floor plan. Maybe it was also a castle of some sort, planned to make it easier to defend and confuse enemies. Or maybe it was built like that for religious reasons. Who knows, but the important thing is that it's like made for a roguelike level theme. What could be better than random placement of rooms without apparent logic? An ancient palace with hidden rooms, long corridors, mazes and stuff. And it's an idea from the real life.

Friday 26 July 2013

Junk

It's often important to know exactly what is going on with routines, but it's also tedious to add debug information. I guess I need it now when I'm fixing a bug with room item creation. For some unknown reason the search is including areas outside the room. The bug has been there for a while and I noticed it only when removing all item creation other than when it creates junk items in "small" rooms.

Bugs like this are annoying, because you know the room is made into that spot. You can see it in the mask map and in the level. Nevertheless something is wrong. Maybe the room rectangle is stored incorrectly. Since small rooms are temporary objects I have to change it and store them in a list to view the data later and compare it to the actual level.

Monday 22 July 2013

Paper Mario

This project has some features that have been unfinished for a long time - for various reasons. I thought this message count thing was going to be the next one, but in just a few minutes ago it was fixed. What I now often do when I get a difficult problem is that I close my computer and get some paper to plan how to fix it. Surprisingly it works often than it doesn't. Planning on paper is free from any distractions and you can literally visualize the problem by drawing it if it's something you need to do.

When I look at the list of unfinished features I have to evaluate them again. And again.. but it's difficult to make a decision to delay the feature or even worse - remove it.

Friday 19 July 2013

Ducks & Barrels

Refactoring the message routine was easier than I thought. I had already changed old c-style msg()-function to use message "event", a list where messages per turn were stored. It was essential, because there are zillions of calls to msg(). In fact, I'm not even planning to replace them, unless a part of code is refactored for other reason.

I made a clever choice to create a dedicated class for messages that are displayed and stored in the list. It's storing the message itself, color (for future use) and amount of repeats. Everything else went well, but there is a bug or more like logic error in the repeat or count of a message.

So, when you get messages like this:
Duck.
Duck.
Barrel.

It's convenient to display first two messages like this:
Duck. [2]
Barrel.

But when you store messages in the list there are only two actual messages, not three. This wouldn't be a problem during a turn, but the glitch happens between turns: if there is no new message added to the list, the message is not displayed at all.

I was in shower when I had an idea that might work. It could be possible to store the count of the last message and check if it's different than before and display the message as an extra one before the messages that were added in the list during the turn.

Tuesday 16 July 2013

Leaving a message

For some time I have planned to refactor the way message routine works. Since the data was largely centralized to the message class I had difficult time figuring out how to proceed. Then suddenly I had an idea while I was doing deadlifts in the gym. Who said weight training and roguelike programming can't co-exist?

It would be extremely hard to discard everything done this far. Rather than that I'll try to slowly include the new routine inside the message class so it can work at the same time with the old routine. I think it can be done and it's not even that difficult. However it may be somewhat difficult to distribute the centralized data, but in return it will give better modular structure for the message data as well.

I'm also trying to replace C-style variable parameter routine with std::string. I don't yet know how hard it will be, but I think it's worth a try.

What I hope to achieve with the rewrite is more flexible message routine which is less responsible for creating complex messages, but at the same time taking care of things that could be tedious to handle in the routine which is displaying messages.

Sunday 7 July 2013

Puzzle adventure

As the source code has grown and also the scope of the project it looks like all I have to do is solve puzzles. They are unfinished features or some part of source code I've marked.

These days I try to find some kind of quick solution to these puzzles, just to get somewhere. It's also tempting to simply remove the feature for now, but then you go back to simpler gameplay and finally reach a game that has complexity of a 7DRL. All that in 30 years of development.