Saturday, 14 October 2017

Is a roguelike user interface bad?

The user interface issue is more complex than it appears. Lot of players and even developers say that when there is a key for every command it's bad design. But is it? I think the answer is somewhere between extreme solutions. Less often used keyboard commands could be moved in a menu or something like that and there are many ways to reduce keyboard commands and make the user interface easier, because in many cases you can automate tedious, repetitive tasks. A simple example is open command (o) for doors, you could make the door open when bumping into it or remove direction key question if there is only one door near the player.

If the game has lots of commands then it can have a large number of keyboard bindings to them. I think it's not "bad design", it's just how it is. I've been following ADOM's development and difficulties it has with "new" players that possibly have never even played a roguelike. It's kind of hilarious to think that you would even try to make a complex roguelike more accessible to casual players, but I guess some people try it anyway when trying to reach the maximum commercial potential. Yet it may work, because a traditional UI of a roguelike could be improved for sure.

The reason why UI is so hard to get right is that it simply is a difficult problem that requires lot of thinking and design (=work) not copied from existing games which has been a kind of trademark in roguelikes. ADOM for example is very much like Nethack so it carries the load of Nethack's ancient UI. In attempt to keep the familiar ADOM experience for old players it could end up staying in some kind of limbo where too drastic changes are discarded as a possibility.

I'm not afraid to use lots of keyboard commands in my roguelikes, but there are those repetitive tasks which could be made easier somehow or even removed in some cases. A great way to handle these issues also is make them optional for people who actually like to perform them.

Wednesday, 11 October 2017

Teemu ARRP Diary 11/3

I'm working on a new theme and found out that the room creation has to be different than it is now. At the moment room spaces are destroyed by anything created on it like corridors. It's a simple way to make sure everything is connected. But the new theme requires that rooms are preserved, so... Luckily I have lot of experience from this type of creation schemes.

The way I plan to approach this is using "path point" locations for rooms and other places. When paths are created they are outside the room area and need to be connected with doorways. The search requires stuff like checking out existing connections (to avoid stuff like several doors on the same wall) and also checking for "double wall" situations where rooms are created next to each other. This could be also avoided by checking out rooms and giving it some space between them, but I think it's better just check for double walls and punch a hole to connect two rooms that way.

Monday, 9 October 2017

Teemu ARRP Diary 10/3

Changed some things in lighthouse levels, but still not sure how to handle the terrain situation with bottom and the top levels of the lighthouse. Maybe it could be copied in dynamic way always from bottom level to top, because the bottom level exists before the top level is visited. It would also remove kind of hacky routine to copy the map to world class to store it there. The only problem are objects, but the top level could have another set of objects anyway and you couldn't "see" the objects from up the lighthouse.

Working with the ancient cave theme I was using a new routine to create caves. It's a simple "drunkard" algorithm, but it can be used in levels the same way 'small' rooms, mixed with other types of creation. It's really simple, but effective way to create natural looking caverns. And with small percentage value of coverage I think it looks even better, because when it covers less areas it's somehow nicer than trying to create more coverage, then it becomes kind of messy. So I think it works best when used with other features.

Next themes to check out are all new, so they require more work than the others. I think expanding the game world has been fun, when you try to think possible places you could still fit into the theme of the game and in the environment of the island.

Sunday, 1 October 2017

Teemu ARRP Diary 9/3

The room generation bug had a surprising source: the level was created twice. I forgot that when the level is visited first time it's created and then I also called Create() for second time. It wasn't clear even there were surprisingly lot of items created on second time. I was searching the bug from room creation for a while before figuring it out.

I'm now halfway of level themes. Some themes are easier than others. There are also shared features that could use some improving like the way 'small' rooms are created. At the moment the routine is scrolling through the entire level and creating rooms where it finds empty space for them. A better alternative is find one place at a time randomly, so you could give levels a limit for small rooms and also for their size.

Next I'm going to tackle lighthouse levels which are pesky ones. The top level is ridiculous, because it has to be also the bottom level. I'm trying to think could it be somehow possible to use the same level for base terrain, but only replace the lighthouse itself, because when you are at the top it should be the same level when you look at it (same objects on bottom level). I guess one way to solve this could be true 3D levels, but I really don't want to go there, at least not right now.

Friday, 29 September 2017

Teemu ARRP Diary 8/3

Working on 'cave' level theme I noticed the list of rooms is not cleared when I re-create the level. It's very strange, because the routine to clear rooms sometimes work, but not always. The problem I guess here is the way I have made portals a "static" part of each level, but I think it's possible to change them. Portals come from World class where they are determined for each level, but they could be copied back to a level instance when it's re-created. When static portals are removed I could then simply delete the level instance and make a new one, rather than trying to clear parts of it.

Cave theme was also changed in a way that 'regular dungeon rooms' are now protected, so their tiles can't be destroyed by paths or caverns which seems like a better solution. Still I try to keep things simple just to proceed to next thing whatever it is.

I think my code is "clean" so to speak, but one thing that could be improved is the way I'm naming variables in member functions. They are probably often too short and not descriptive enough. I have mixed feelings about long variable names, but other than loop variables could be longer I think.

Monday, 25 September 2017

Why this is not the year of Linux

The success of operating system is directly linked to two features or main points. They are "user experience" or how easy the OS is to use and the second feature is development. The rivals of Linux get them mostly right. OSX is (or has been, this seems to be changing recently) easy to use, no one can argue about that. But I think OSX has big problems in development which is focused on Apple's way to do things and make everything else really hard. Windows is the biggest OS, because it has good user experience and also it's very good as a programming platform.

Linux users can argue about those points, but that's all you can do actually. Numbers don't lie. The small amount of "regular" (non-hackers) users are result of GUI versions of Linux that try to implement the user experience part. Casual computer users don't care about compiling stuff from source and updating libraries or whatever. They want to use programs. I've been programming over 25 years and just I want to use programs. I don't want to compile them or figure out what is happening in the OS itself. Another part of the problem is the way open source has failed to give us programs that are on the same level with commercial software, or even better.

Linux programmers seem to live in the same kind of haze than its users. They say how programming is really easy in Linux, but they use technology from 1970's like makefile. Everything changes all the time so you need to compile everything and watch out for library versions, compiler versions etc. Open source itself is an ideology which doesn't work in reality, because most developers want to keep their source code closed and also sell programs which means they need to be compiled into an executable that works in most versions of that OS. The open source ideology is the biggest problem Linux has and it's just as ironic as it sounds.

It's human nature to make everything more complex that it has to be. We can see this in computer technology and in operating systems for sure. They are bigger and spend more resources with every new version, but give us pretty much the same features. Somehow we fail to make things simple from both user experience and development point of view. Maybe we are too smart to create simple things.

Sunday, 24 September 2017

Teemu ARRP Diary 7/3

The null bug was in Get -routine of terrain tile. You would think it's hard to make a mistake in such a small routine, but it is. I was checking the index with 0 when it should have been -1 (out of level). That's why the first (top left) tile was null, but when the debug routine was not using Get_Terrain() it didn't catch it. I tracked it back from look routine which was showing the tile as 'null tile'.

The low level routines work I guess, masks are added to searching (Place class). I'm going through level themes one by one and there are issues with room generation etc. I think there are only two themes that need more work than just simple fixing. I try to keep things simple and work through themes first on terrain level, then second run adding objects and finally creatures.

A kind of "problem" that I run into all the time is that it's "possible" to make things in smarter way, but it just takes way more time than making things work using less sophisticated code. It's important to ask yourself what do you want to achieve in gameplay context and how to do it. If it's really complex stuff then it may be easier to create a complex system for it (in a long run). But if it's not then it's faster and easier to bash some random code and try to keep it bug free at least. Creating a sophisticated engine for anything is incredibly difficult and I think it takes a certain kind of mindset and skills to succeed in creating a coherent game engine that can process everything the game requires.

Thursday, 21 September 2017

Teemu ARRP Diary 6/3

The null tile or object is still a bit of a mystery, because I don't know what it is. Not even with a debug routine I made just to inspect tile's contents. The look routine is actually seeing it as null terrain, but the debug routine shows it's a real terrain tile. So I have to check out how the look routine is determining it's a null terrain.

Doorplace search is not working currently. The reason is that the search routine fails without mask data. To fix that I'm going to rewrite the search with mask tiles. But for that I need room masks that indicate the facing of the room, so each four main directions get a mask type. I've find this useful in Kaduria, because once you have set the direction to a wall it's easy to find it later.

I'm in a process of rewriting the room creation itself, because room has to use a special routine to determine the facing directions while it's creating the room.

Wednesday, 20 September 2017

Teemu ARRP Diary 5/3

Mask routines are now ready, but they aren't possibly yet used. The routine checking for object creation is including a check for mask. Anyway, level creation works the usual way, but there is a strange bug which has to be fixed before doing anything else. It's creating a null tile at the top left corner of every level. To find out more what it is in first place I really need to write a debug routine to show the contents of a tile.

I wrote a new debug routine to collect "togglers" which have value of true or false. The scope of this project is so small, that there are only two togglers at the moment: FOV and mask map tile, which is a routine that shows the mask tile using a color data assigned to it. That way you can make sure the mask map is correctly created.

The null tile bug can be related to place searching. I could make that better to spot by adding a debug id (for example a piece of text) to each call. You can then spot which routine called the search for list of tiles.

Tuesday, 19 September 2017

Teemu ARRP Diary 4/3

The mask data was moved to Terrain_Tile which is a tile of the terrain map in base class of Level hierarchy. It was just much better that way than storing mask data to Display_Map, because it started to get weird with access to Display_Map instance from Level class. Now the data is pretty much where is belongs. It takes more memory, but that's not an issue, because levels spend quite small amount of memory. The data is reset when the save game is loaded, but it's also not a problem, because the mask data is useful only when creating the level.

Today I could try to finish all the routines which actually use mask data. Sometimes using mask is a lot easier than finding out particular terrain tiles, but sometimes you need to find specific type of tiles to create some stuff on them. That's why both systems need to work together. The mask is set using default values for terrain and later when creating rooms etc. it's written over with new values. I find one of the hardest parts of level generation is the way you decide what can be created on a single tile, with often complex rules and special cases.

Sunday, 17 September 2017

Teemu ARRP Diary 3/3

Today I didn't get much done. I noticed that there are some problems with generation routines, because a mask data of tiles don't work. Mask value for tile is useful feature which I'm going to implement for Teemu the same way I have in Kaduria. The mask system has two types of masks, a regular type for terrain tiles and room mask which is a number given to a room or other similar type of area.

It's sometimes useful to assign mask values to tiles that aren't that tile's default type. For example in situation where you want to exclude a part of level from creation. Room masks are also useful, because then you can create stuff in a specific room, and when you have assigned only tiles of that room to a mask id it's easy to find tiles of that room later during the generation process.

I didn't have time to program that feature yet, but I'm planning to put that into Display_Map class which is re-created for each level when you enter it. That way I don't have to store mask values in each level which could be useful in some cases, but I think in this game it would just waste some memory.

Teemu ARRP Diary 2/3

It's already sunday, but I partied so hard that I forgot to report my progress. I confirmed that loading from text data works and it can also remove unwanted spaces etc. The parser is only about 20 lines of C++ code, but it can only get and store pieces of text. However it could be interesting to make it more complex, because I have been thinking about using external data.

Next I wanted to fix re-making of level for testing. The problem was and is that for some reason I have a "static" list for stairs which are copied to each level instance. That's why I can't just delete the level instance and make a new one, which would be the best solution. So I spent some time writing some routines that clear some things from each level class from the hierarchy. It probably works ok, other than the first level size will be always same. This could be changed, but some level themes should keep the size, because there are multiple layers of that same level. The lighthouse for example, it has multiple levels with the same base level stored in World class. There is also a bug related to that, because when you go at the top level it's a copy of the beach. This means you could change something in the beach and it wouldn't show in top level. Copying terrain tiles to top level every time the player enters there could be easy, but game objects are more difficult, because if they are copies it could create some interesting problems. That's why the interaction must be limited when you are on top of the lighthouse.

Friday, 15 September 2017

Teemu ARRP Diary 1/3

This weekend is ARRP, annual roguelike release party. I'm not going to be releasing Teemu 1.3 just yet, but in the spirit of the party I'm going to program Teemu for these three days and see what happens. Today I have cleaned up some namespace issues and I have a plan to write a text parser for external text data (from a file).

The parser a big deal, because I haven't used external data other than pixel based data for tiles. But it makes a lot of sense to create text based raw data which is then parsed into form that the program can use. I already have that functionality, but when the "raw" data is inside the source code it creates a duplicate of that data. It's not a problem with text data as resource, but it would be neat to use external text data, also for the reason that changing that data doesn't require building the project.

The gameview is also a big mess, but it should be easy to fix. In any case I have learned to concentrate on one problem at a time and today it could be the text parser.

Sunday, 10 September 2017

Recover from rage quit

After problems with gdb not catching simple crashes of a program I went back to Visual Studio. Microsoft had already released 2017 version (I had 2015). I like the installer of 2017, you can select only those parts you need, from programming languages to technology pieces. With regular C++ I also installed Linux tools, because it made me giggle. I don't know what they are, but I guess there were some talk about Windows trying to emulate the linux style command line workflow. It would be cool if it was possible to build projects just like in linux, but I doubt it.

The double account issue was also fixed, I went to msdn forums to ask about it and there is a special console for Visual Studio where you can reset the account. Seems like that another account went away, it could have been some kind of glitch and no one in reality was able to create an actual account to download my source code. Which is a fear I have, because VS has all that connectivity to clouds and team systems. I have obviously turned those features off.

Teemu's level system is more or less ready, but I realized there is no need to store object handles to level's map, because they are not owned by it. I could just make one "global" map and use it, that way a big amount of data would be removed from save game and memory. That map already exists in form of gameview class which has dynamic stuff like fov and lighting. Other than that the "map tile as object" broke some things from level generation. For example shallow water is no longer created. I hope it's fixed by itself when I go back to map that has only raw data and no objects.

Monday, 14 August 2017

Line-of-sight problem description

The line-of-sight problem or LOSP can be compared to Nth Prime Number problem with difference that prime numbers are easier, yet I think no solution has been found to Nth problem for 2300 years. Like Nth the LOSP is seemingly easy, but still impossible to solve. In theory line-of-sight always works in infinite precision, but in 2D map of a roguelike it's not infinite, but an approximation that can "flip" the location of line to "wrong" tile depending on floating point calculations in that particular processor.

This image shows the problem in action. The red line is line-of-sight in infinite theoretic space and the blue line is an approximation in 2D map (green is wall). The black tile is often called an artifact of the result where line drawing stops before it reaches the required wall tile. In finite space the line simply stops in walls before that one artifact location.

There are number of ways to fix this problem, but none of them actually can do anything about the finite precision conversion. One of the solutions is find those artifacts and fix them using a simple routine to check their location in context to origin point of the FOV calculation. The issue with fixes are that they make the FOV routine often about two times slower, or even more. So is it a problem in modern computers? I think it is. If you want to keep the speed of game loop at least somewhere in 20-50ms (using one core) then you need a fast FOV routine.

FOV becomes critical in situation where other than player character have it, similar to more advanced path finding routines. It's possible to make the game very slow very easily with slow routines. That's why finding a solution to this problem could be nice.

Saturday, 15 July 2017

New plans for Teemu

Well, same old actually, because I'm refactoring Level class hierarchy with the same idea I had for Kaduria. It's such a great way to handle the biggest class structure roguelikes will probably always have which is the random level generation and other stuff happening in levels.

This time it's easier, because classes in Teemu are way smaller than they are in Kaduria. Another new idea for Teemu is that terrain tiles become containers of objects. Yet I think there will be lists to handle things like monster movement, but those will be a copy of the map container's objects (pointers of course, not real copies).

I hope this new system will also push the release date of 1.3 closer. It's annoying situation, because I know there is not that much to do, unless I want to make Teemu more complex which should be the plan anyways. I'm one of those developers who want roguelikes to be complex and not simple commercial action games everyone is making for mobile game market. I'm laughing at Biskup's attempts to simplify ADOM's UI. I want to make them more complex, because it's fun. It's the reason why we are creating these games.

Friday, 16 June 2017

C# Pihlaja engine

Started to write an engine in C# for a roguelike game. The engine was named 'Pihlaja' (it's a plant). So the way I approached it was a blank Form1 with a picture box control. It's a simple area that you can display a bitmap image. This bitmap image is then filled with ascii tiles which also are bitmaps. It's quite easy, because you can print font data on image as pixels and use that as faster way to draw ascii fonts. It seems to be quite fast even without any hardware acceleration (I guess it doesn't have it?).

There were some problems as always. First one was that I copy-pasted the Load method of Form1 which you don't want to do, because C# doesn't know it's there! You have to double-click the header of Form1 to generate a method. Even stranger if there is a manual Load method the new one is named Load_1, so it adds _1 in the name and that's the only working version. You can't rename it Load, in fact you can't remove the code that's generated by Visual Studio or the Form1 breaks! There is some kind of internal version of that code and whatever VS generates should not be deleted or renamed, or copy-pasted to another project.

The second issue was that when you get font metrics you can only get the height of the font in pixels even with monospace fonts. And it contains a lot of empty pixels around the font, but you can adjust the pixel rectangle size manually for that bitmap version. The font's 0,0 position is also quite far away from the edge, but you can print the font in negative location, in this case -1, -2 was the right location. I determined the font width from height, but it was width=height-9 so you can remove a lot of pixels from that. The font must be installed on computer I guess (dynamic resource), but I think you can also use font family (generic monospace).

Third problem is that AutoSize of Form1 doesn't work properly and this seems to be a common problem. It means you can't resize the form (or window) to match the size of the content (picture box in this case). There is randomly some kind of margin at the bottom and right sides of the window. Could try to give the picture box some top and left margins to see if it behaves better.

Thursday, 15 June 2017

C# language experiences

I've programmed something with C#, a loader for .wst tiles to test how easy it could be. To be honest it was kind of easy. C# has a large library of stuff which makes trivial things let's say somewhat easier than in C++. C# in Windows at least is closely tied to Windows APIs (or whatever they are called these days) and programs with GUI has that part in them. I'm not too happy about working with Windows form designer etc. but that's life for you.

As a language C# is quite close to C++, but the main difference is automatic value/reference system similar to Visual Basic. Another easy to spot difference is that you write code directly to classes, there are no header files or declarations of classes. Namespaces are an essential part of programming as they should be. Other than that the syntax is very close to C++ which makes it a lot easier to approach than let's say Visual Basic.

After writing the loader I've started to think about trying to write a simple roguelike engine for C#. It's sad that I can't think of any other game types, but maybe roguelikes are the only games I want to play? In my opinion C# doesn't make everything that much easier, because the hardest part of a program is always the content and actions of the program. But it could make some GUI stuff easier to implement.

Sunday, 4 June 2017

Font ligatures and Space Mono

Ligatures connect two letters to one unicode character to represent something "better". This is a new feature in programming which I feel is useless twiddling. Recently I tried a monospace font 'Space Mono' which actually is a great font for programming. But for some comical reasons it has a ligature with f and i letters, forming a 'fi'. It's not even that it has any "programming" ligatures, it seems to have just that one.

Visual Studio supports ligatures, but that's the problem, you can't turn it off. It's almost as if the designer of that font knew it and included 'fi' ligature as a joke. Strangely (or is it supposed to do that?) VS still takes fi as separate letters in data (compiling), but when displaying it breaks monospacing. You thought fonts were the last thing that humanity could possibly not fuck up, but they sure did it with ligatures.

I don't know if you can somehow turn ligatures off in VS, but that's not the point. It's just plain harassing using that 'fi' ligature in a monospace (programming) font. Even it was possible to turn it off the brief moment of joy finding a good font has passed. Let's get back to Consolas or something else and hope they don't ruin it as well.

Friday, 14 April 2017

Namespacing 1.3

Notations for enums are in process to be turned to namespaces. I think about 1/3 of them is reprogrammed, but in most cases it's easy. When you remove special notation from the beginning it may sometimes create a name clash, especially when you open the namespace. But namespaces are better solution for other reasons like for functions tied to namespaces. It's also easy to find namespace instances from the entire source code.

This is probably not a healthy way to develop the game itself, but with this I'm planning for bigger changes to content and also to the RPG system. The key to success is keeping things simple for this one. I know very well what happens if you plan something major in context of roguelikes. Even now with actual RPG system the development has moved on to harder difficulty level from a simple 7DRL that Teemu was before.

Saturday, 11 March 2017

Planning the source code release of Teemu 1.3

I think the source code of Teemu 1.3 is going to be more important than the game itself, but it's just an opinion I guess. The game is also released with the source code, so there is no need to compile it in Windows environment at least.

Since last time I have learned some new tricks which are better use of namespace and functions. Namespaces have two main purposes in my thinking. The first one is replace notation additions to enums etc. using a module type name for stuff. Like for example door::Wooden, rather than use notation doorWooden in enums. Namespace is safer, and you can remove the door:: when using in some places. Also, what I find great is searching by using door:: namespace, you can quickly find all places where it's used outside of the namespace itself. The second use is with functions as a kind of module.

Functions are another funny thing, because when you learn OOP you may want to make "everything" a class which in some cases is clumsy, because you have to create an instance of a class to get some trivial data etc. Functions are even better with namespaces, because you can then create sort of static "namespace class" or module with C-style functions as member functions of it. The nice thing in C functions is that there is no need to create an instance so there is no problems with memory management in that case (unless of course you use memory management in those functions which I never do). Writing pure functions is really nice I think and they are very useful when generalized, because you can use them in any place of the source code without so called side effects.

Those are the two main improvements, but there are others like smaller classes with more focused tasks and so on. The reason why I think this is important is that I've been talking a lot about C++ programming and why you should do certain things. But when I only talk about it no one is listening. So I think it's far better to lead with an example. I want to show how you can write large-ish projects with zero bugs when you concentrate on creating a set of rigid rules in programming.

The release of Teemu 1.3 is not very far away I believe. Depending on how well I'm able to allocate the time for this project.

Wednesday, 25 January 2017

Blown away by Visual Basic

I've been in a stuck phase with my regular projects so I thought it could be funny to write a roguelike (what else?) using Visual Basic, you know, as a joke.

The current version of VB is something I did not expect. It's no longer that old, dumb language where you wrote code for Windows forms. It's a cool programming language built on top of a procedural past, but somehow seamlessly includes modern features (class being possibly the most important). Everything seems to work smoothly so you start to wonder why C++ can't be like this.

The only strange thing is how VB is managing resources. The reference/value system is automatic, some things are always references and others are value types. I guess it works somehow.

There is a problem with Windows console project which is that it's really slow. I think debug mode has something to do with it, but it should be faster. However I've found out that when you set the color of a character it's possibly the slowest thing you can do, so when you draw the level you can set the color (character and/or background) only when it changes.

The syntax of VB is quite verbose which I like personally. It's easy to write code that doesn't really need comments to understand what it is. The language doesn't seem to have ambiquity that C++ has. For example Sub never returns anything, but Function always does.