Some of the feedback I received during the last tech demo includes a few complaints that when they'd hit 'a' to attack, the screen centering on the first available target was disorienting. While I personally didn't have this issue (or else I'd have coded it differently), I could see where they were coming from. Since I'm handling "low hanging fruit" early in this iteration (or procrastinating, depending on your point of view), this seemed like an easy thing to handle.
I've covered this issue with two different fixes. The first being the inclusion of "bump to attack". This is a common feature in roguelikes, where moving into the same space as an enemy invokes a melee attack. I personally don't care for it. I've lost more than one character in games without "run in direction" when I held down an arrow key for a half a second too long and melee'd myself into oblivion.
Magecrawl also has weapons with "reach" such as the spears, and bump to attack can prevent people from noticing their longer reach. In addition, some weapons either can't attack certain directions, or attack at lower strength; the attack key shows overlays making both these facts obvious, while bump to attack doesn't. Despite this, it is a convenient option, so I added it as a preference one can turn on.
The second fix is a preference to disable all "auto targeting". When you request an action that requires targeting, magecrawl will try to pick an intelligent initial targeting position. This preference just skips all this code, and all targetting starts at the player's position.
I'd like to spend a minute talking about preferences. Magecrawl isn't even a full game yet, and in addition to keyboard settings for every key, magecrawl has more than 15 preferences so far. A few are debugging settings, but most are documented in Preferences.xml. Each of these brings different behavior to magecrawl in some manner, which in theory requires additional testing and maintenance. The trick is to find a balance of providing great defaults, so people don't have to touch the preferences, and enough knobs that people can change the settings that are important to them.
Tuesday, February 9, 2010
Monday, February 8, 2010
libtcod-net 1.5.0rc1-2 released (fixes reported TCODRandom issue)
The issue reported here has been debugged and fixed. The short answer for those not interested in the details is that I was using an API in libtcod wrong and that API was doing the wrong thing and corrupting its internal state. Get the newest libtcod-net here.
For those who are more technically minded, here's the story.
In between libtcod 1.5.0b2 and 1.5.0rc1, the C API changed for creating TCOD_Random's. Previously, one could call TCOD_random_new(), however in this release they added two different RNG implementations. This function now take a paramater. The way to get the "default" RNG is to call TCOD_random_get_instance, which I did happily. I also added a new TCODRandom constructor that took the enum for those who cared, but that's beside the point.
This worked, and seemed to be all I needed to do to fix libcod-net TCODRandom for the new API. However, there was an underlying issue. Sometimes in magecrawl, monsters and players would get into long stretchs (4000+ turns) of continual misses.
After some detective work, the issue was found. TCODRandom, like all libtcod-net wrappers that handle unmanaged resources, implement IDisposable. The idea is that you, or the runtime, will call Dispose() on it to free the allocated memory. The issue is that the new api had a note that you weren't supposed to call TCOD_random_delete on the default RNG. When you did this, you free'ed the memory for the global instance, but not null it out. Due to the implementation of the RNG, it'd happily use the garbage memory giving random answer most of the time. Some times however, some of the garbage pointed to a segment of zero'ed out memory, and I'd see the long stretch of zero's.
The solution was twofold. I updated libtcod-net to follow the API's rules and not delete the default RNG if that was how we implemented it. jice updated libtcod to not internally corrupt itself if you happened to do this. The joys of maintaining libtcod-net is that sometimes you get to track down memory corruption issues, even if you're written in c#. That is the fun of interfacing with unmanaged code.
For those who are more technically minded, here's the story.
In between libtcod 1.5.0b2 and 1.5.0rc1, the C API changed for creating TCOD_Random's. Previously, one could call TCOD_random_new(), however in this release they added two different RNG implementations. This function now take a paramater. The way to get the "default" RNG is to call TCOD_random_get_instance, which I did happily. I also added a new TCODRandom constructor that took the enum for those who cared, but that's beside the point.
This worked, and seemed to be all I needed to do to fix libcod-net TCODRandom for the new API. However, there was an underlying issue. Sometimes in magecrawl, monsters and players would get into long stretchs (4000+ turns) of continual misses.
After some detective work, the issue was found. TCODRandom, like all libtcod-net wrappers that handle unmanaged resources, implement IDisposable. The idea is that you, or the runtime, will call Dispose() on it to free the allocated memory. The issue is that the new api had a note that you weren't supposed to call TCOD_random_delete on the default RNG. When you did this, you free'ed the memory for the global instance, but not null it out. Due to the implementation of the RNG, it'd happily use the garbage memory giving random answer most of the time. Some times however, some of the garbage pointed to a segment of zero'ed out memory, and I'd see the long stretch of zero's.
The solution was twofold. I updated libtcod-net to follow the API's rules and not delete the default RNG if that was how we implemented it. jice updated libtcod to not internally corrupt itself if you happened to do this. The joys of maintaining libtcod-net is that sometimes you get to track down memory corruption issues, even if you're written in c#. That is the fun of interfacing with unmanaged code.
Sunday, February 7, 2010
libtcod-net 1.5.0rc1 seems to have an issue with TCODRandom, beware.
Update: See this for a solution.
I've spent half of today debugging this issue. It appears that there is an issue I'm hitting in magecrawl where a TCODRandom gets stuck in a state where it returns 0's for every GetRandomInt call. I'm working with the maintainers of libtcod, but it appears the issue is one underlying libtcod itself.
The workaround is to use the constructor that takes an enum and pass is the MersenneTwister value.
I'll update more when we find out more. I just didn't want anyone else to try to debug into their code for a few hours looking for sensor ghosts.
I've spent half of today debugging this issue. It appears that there is an issue I'm hitting in magecrawl where a TCODRandom gets stuck in a state where it returns 0's for every GetRandomInt call. I'm working with the maintainers of libtcod, but it appears the issue is one underlying libtcod itself.
The workaround is to use the constructor that takes an enum and pass is the MersenneTwister value.
I'll update more when we find out more. I just didn't want anyone else to try to debug into their code for a few hours looking for sensor ghosts.
libtcod-net 1.5.0rc1 released!
libtcod-net 1.5.0rc1 has been released (same day as base library libtcod itself may I add :) ).
The major changes include TCODPathFinding being removed. It's been split up into TCODAStrPathFinding and TCODDijkstraPathFinding. This is obviously an API break, but one that can be replaced with a simple find a replace. Beyond that:
http://code.google.com/p/libtcod-net/
The major changes include TCODPathFinding being removed. It's been split up into TCODAStrPathFinding and TCODDijkstraPathFinding. This is obviously an API break, but one that can be replaced with a simple find a replace. Beyond that:
- TCODSystem::GetCurrentFontSize
- New random number generator type and new default (ComplementaryMultiplyWithCarry)
- New functions - GetGaussianFloat, GetGaussianInt, Save
- Removed functions - GetIntFromByteArray
- ResetCreditsAnimation, which fixes an outstanding bug in Magecrawl.
http://code.google.com/p/libtcod-net/
Saturday, February 6, 2010
Tooltip Descriptions
In the last few days, I've been knocking out a lot of the "nice to have" or refactoring issues that have appeared due to tech demo II. Some of these include:
- On "stitch" maps, doors now are placed in sane positions.
- Treasure chests now add items to your inventory when opened.
- Casting an enchantments multiple times no longer stacks them, just extends duration.
- "Tooltips" on view mode to describe the currently selected cell.
Here's an example of the new "tooltip"
Wednesday, February 3, 2010
Multiple Keybinding Presets...
The single largest source of comments on the tech demo II had to do with setting up keystroke bindings. Although I had setup what I through was a good default and provided a way to change it, people did not think this was adequate. It seems that other roguelike players are very particular about their keyboard settings.
To address this, I've split the key bindings into two sections. The first section, KeyMappings.xml, will still contain most of the keystrokes. The second section contains the settings for the 8 cardinal direction, with three sets of defaults already picked out. Preferences.xml contains a preference to choose between these default. If you don't like any of them, you can choose "Custom" and provide the location of your own xml file.
The three defaults so far are:
To address this, I've split the key bindings into two sections. The first section, KeyMappings.xml, will still contain most of the keystrokes. The second section contains the settings for the 8 cardinal direction, with three sets of defaults already picked out. Preferences.xml contains a preference to choose between these default. If you don't like any of them, you can choose "Custom" and provide the location of your own xml file.
The three defaults so far are:
- Arrows (and insert/delete/home/end)
- Keypad
- VIM
Tuesday, February 2, 2010
Crossplatform issues with MEF Preview 8
While far from perfect, Magecrawl has a decent amount of modularity. The GameEngine with all map generation and the details of the running world have a hard boundary between it and the GUI. However, I feel that the GameEngine has gotten a bit too big and I'd like to split out of parts of it into separate components.
One of my first tasks this release was to investigate MEF. MEF, to put it shortly, let's you part a part of your class as [Import] and then say, "Go find a library in this directory which implements IGameEngine, load it, and fix up this variable." I implemented the first baby steps of using it late night and things were going well. That was, until I tested in under Linux.
MEF preview 8 as it stands does not work with mono/Linux. I'm not talking about a single specific issue that my code happens to trip, the built in examples don't even work. Examples bugs can be found here and here. One of them mentions this as won't be fixed until after the end of March at the earliest (post .Net 4 release). This leaves me with the unhappy situation of either:
As a side note, this is why I test under Linux before each tech demo and whenever I'm about to make a large architectural change. If your writing something on one platform and expect it to work elsewhere, even if the library/language you're using claims to work there, testing early and often is a good idea.
One of my first tasks this release was to investigate MEF. MEF, to put it shortly, let's you part a part of your class as [Import] and then say, "Go find a library in this directory which implements IGameEngine, load it, and fix up this variable." I implemented the first baby steps of using it late night and things were going well. That was, until I tested in under Linux.
MEF preview 8 as it stands does not work with mono/Linux. I'm not talking about a single specific issue that my code happens to trip, the built in examples don't even work. Examples bugs can be found here and here. One of them mentions this as won't be fixed until after the end of March at the earliest (post .Net 4 release). This leaves me with the unhappy situation of either:
- Use MEF, and for at least the next two month have no chance of having a Linux version of Magecrawl
- Don't use MEF, and either use another IoCish framework or wait until MEF works.
As a side note, this is why I test under Linux before each tech demo and whenever I'm about to make a large architectural change. If your writing something on one platform and expect it to work elsewhere, even if the library/language you're using claims to work there, testing early and often is a good idea.
Subscribe to:
Posts (Atom)
