Showing posts with label ighalsk. Show all posts
Showing posts with label ighalsk. Show all posts

Thursday, August 2, 2012

Ighalsk - release 0.1.16

I released v0.1.16 of Ighalsk last night. It can be downloaded from its SourceForge project page here. These are the changes since v0.1.15:

* Attack Powers can now have a radius: that is, they can explode (with a circular area).
* Heroes now gain Powers as they gain levels (currently this process is automatic: a Hero gains every possible new Power as e gains a level).
* Added new Powers: Terrifying Roar and Hurl Rock for Mighty Heroes, Willpower and Divine Light for Blessed Heroes, and Argumentum and Profunde Cogitare for Philosophical Heroes.  These are gained at higher levels.
* Can now enter the final level of the Tunnels of Lost Dreams quest.  (However, there will be more monsters added later.)
* Can now see the damages and damage types of weapons, and the main resistances of armour, while shopping.
* Can now browse ('consider') the definition of a Power.

It's been more than 2 years since the last release, in which time I've been working on From Bear to Phoenix. Something I have to think about going forward is which game to focus on, or somehow try to develop both.

For the next release of Ighalsk, I'd like to add in final levels for the other two (current) quests.  It may or may not also include a major new feature.

Monday, May 24, 2010

Ighalsk - release 0.1.15

I released v0.1.15 of Ighalsk some 2 weeks ago. It can be downloaded from its SourceForge project page here. These are the changes since v0.1.14:

* Fixed bug in Monster Editor where the resists weren't updated after changing the monster's family. (The new values were present, but the recalculation wasn't occurring in the correct place.)
* Switched to black background and white text, which is a more traditional roguelike design (and has more of an underground feel). Black monsters are now a dark grey colour.
* Can now add monsters to a level using the Level Editor (and delete them if they're in the wrong place!).
* Can now add circular rooms in the Level Editor. (This was something I wanted for the Tunnels of Lost Dreams in particular.)
* Now need to specify a width and height when creating a new level in the Level Editor. (Now tests can use small levels for speed.)
* Added initial (incomplete) version of the final level of the Tunnels of Lost Dreams - can't yet be entered in the game. A screenshot is here.

There was almost 3 months between v0.1.14 and v0.1.15, and there may well be a similar time until the next release, if not longer. I'd like to work on a game that inspires me more and that I'm more passionate about; I feel with Ighalsk like there's a lot of work to do before it achieves even close to the functionality that other roguelikes have. The next game will be an RPG, and will reuse a lot of Ighalsk's code, but will have a much more graphical interface. It will also be written in Python, and be open-source (GPL-licensed). If you'd like to know any more, there will be sneak previews and further discussion on this blog and/or on my Twitter feed.

Thursday, April 15, 2010

Ighalsk - sneak peak of Tunnels of Lost Dreams final level

So the Ighalsk Level Editor is coming along nicely - recently added options to add circular rooms and monsters. I've posted a screenshot of the final level of the Tunnels of Lost Dreams here. The level is incomplete as yet - though since Lord Apathy is the architect, the final version will be incomplete as well.

Tuesday, March 16, 2010

Ighalsk - release 0.1.14

I released Ighalsk v0.1.14 a couple weeks ago; it can be downloaded from its SourceForge project page here.

Here are the changes since v0.1.13:
* Simplified controller/viewer swapping for different screens to make it easier (in fact, possible) to generate a Windows executable. I haven't figured out the best way to host this exe yet, since it seems to be too large to upload using the SourceForge File Manager (and SFTP isn't working for me). If you'd like a copy, please email me.
* Added Stealth for Monsters; stealthy monsters will now only be noticed when they are closer to the Hero. There are a couple stealthy monsters to look out for.
* Refactored Monster Editor to simplify it further (separate classes for separate states). This made the next change a whole lot easier.
* Monsters can now have multiple attacks (weapons) instead of just one; this is also supported by the Monster Editor. This is most important right now for the uniques at the end of the first set of quests ...
* Fixed a bug where the keys to move through pages in the Monster Editor (left and right) were the wrong way around. (For a long time, I've been using the buttons instead, and had to look in the code to work out the keys again, only to find that they were wrong.)
* Can now add rectangular rooms in the Level Editor. I plan to also have an option of adding circular rooms, and maybe octagonal, and then there's adding a rectangle and circle of solid walls ...

The next release may be in 6 weeks from now and/or may have a small number of extra features, since I've starting working on a new game ...

Friday, February 12, 2010

Ighalsk - Thanks for the Downloads

This short post is mostly to say, thanks for the downloads. I've said before how I struggle with motivation when working on my own projects, and knowing that there are people out there downloading Ighalsk releases every month does make a difference.

Thanks even more to everyone who's given feedback, both on this blog and in email. It all helps make Ighalsk better one way or another.

Onwards to version 1.0!

Sunday, February 7, 2010

Ighalsk - The Nature of a Hero

I claimed recently in an online conversation that I was taking a slightly different slant on the Hero in Ighalsk. I was asked for more details, and gave the following response (slightly edited for blog format and where I felt the need for improvement):

I'm imagining the Hero as someone more than mortal, with extraordinary gifts and abilities. They are called to fight evil and complete quests. So far this is just expressed in the game as a series of speeches by the Queen who needs the Hero's help, by the replacement of "the dungeon" with a choice of quest dungeons, and by the extra powers that a Hero has that normal warriors (for example) don't have. (As opposed to say Angband, where my Priest might meet a Novice Priest in the dungeon and think hmmm, that priest is almost the same as me ...)

The end of this post has got my take on the different types of Hero, though this text isn't in the game yet.

At some stage I'd like to link in the history of other Heroes who tried and failed to complete all the quests: to have the Queen refer to them, to have their entries in the high score table, to be able to find the weapons or armour they owned and maybe even their journals.

I'd also like the game to show the reactions of townsfolk to the Hero, and to have these reactions change as the Hero grows in power ...

This is something that I'm still struggling with and would like to express more clearly in the game. A roguelike in its usual form doesn't offer a lot of opportunities for roleplaying, but there is all the freedom of text (as seen in interactive fiction games) - so I aim to take advantage of that.

Tuesday, January 26, 2010

Ighalsk - Doom Merchants

Where there has been a concentration of undead for several years, a strange, inky black substance can sometimes be found, pooled in hollows in the ground. If you picked it up, you would find that it pours and moves like a dark, viscous liquid - but it doesn't feel wet. At first it feels cold, then your hands become numb, then strength begins to ebb from your limbs. The solitary adventurer may be overcome at this point, but if you have friends (or at least companions) with you, a healing potion or power will restore you to health.

The unscrupulous soon discovered that this substance, when suitably processed, makes an effective and deadly poison. They called it "raw doom" and set up Workshops of Doom, sometimes even Factories of Doom, to refine and mould it into a more convenient form. A drop or two in a cup of wine induces death while the drinker is sleeping that night. A weapon coated with it strikes through armour and is only stopped by certain white fabrics which have been blessed by sacred rites.

The gathering, processing, selling, buying and owning of both raw and processed doom is illegal in all human, elvish, dwarven and goblin dominions. Nonetheless, there are some desperate souls who traffic in it. They call themselves Doom Merchants, or sometimes Merchants of Doom. The Doom Merchants venture deep into necropoleis, cemeteries and ghost towns, wherever they can find undead, and gather large quantities of raw doom. This they carry in large black bags - Bags of Doom. Their customary costume includes thick white gloves and masks for protection, though the black and white vests they also wear are thought to be ornamental.

By all accounts they make substantial sums of money plying their trade, but slowly lose all colour in their skin and hair, then within a few years become weaker and weaker until they collapse. Rumour also says that after death, they themselves turn into undead, with a shadowed, striped, spotted form that breathes out thick clouds of doom.

Saturday, January 23, 2010

Ighalsk - release 0.1.13

I released Ighalsk v0.1.13 last night; it can be downloaded from its SourceForge project page here.

Here are the changes since v0.1.12:
* Can now add up stairs and corridors in the Level Editor. Corridors in particular were tricky since the editor (or some other class) needed to store the start point until the end point had been selected. In fact you can add corridors between any 2 points; the editor will add two corridors (one vertical and one horizontal) between those points.
* Walls are now only shown if seen nearby or remembered (if they have been seen before). In the previous release, monsters were only shown if they were nearby; this release is now more consistent between monsters and walls, though all treasures and stairs in a level are visible at all times ...
* Visibility (the Hero's map) is saved to file, so that a loaded game will have the same memory of walls as when it was saved.
* Refactored Monster Editor and Monster to simplify both by removing duplication - Monster Editor now uses the underlying dict that holds monster definitions more directly. Editing a monster's attack and resists are still special cases.
* Started moving methods from LevelViewer to LevelFormatter so that they can be tested.
* Added 15 new monsters, including Doom Merchant, Gloomhound, Lesser Mook, Huntsman Professor and Wool Golem. Renamed Zombie to Zythar Feeder; added Zythar Axeman and Zythar Deathbringer. I picture Zythar as semi-undead, crazed beings with gleaming green eyes; the Axemen wear black ribbons attached to their helmets.
* Added Monsters for level 4 of each quest. There are some monsters in this new batch of 15 that can't be encountered yet - I'm saving them for level 5 of the quests.

I've got a few features that I'd still like to add in before v0.2.0, as follows:
* Add functionality to the Level Editor to add rectangular rooms, circular rooms and their inverses (filled-in rectangles and circles of walls), zig-zag corridors and a shortcut out of the quest dungeon;
* Refactor the Monster Editor further to simplify the code, and extract editing attacks and resists to a new screen; then adding multiple attacks and possibly descriptions to a Monster;
* Add new damage types, in particular cold, lightning and poison - at this stage, poison wouldn't have the slow draining of health effect, but would be like any other damage type;
* Add Awareness and Stealth attributes and interaction, as a friend of mine suggested, so that some monsters can creep up on you if they've got high enough Stealth and you've got low enough Awareness ...

The Awareness and Stealth functionality would also allow invisible monsters, though I'd prefer to wait to introduce them until I've also added some kind of Detect Invisible power, which would have the effect of increasing Awareness for a time - it's only fair to the Heroes.

Wednesday, January 13, 2010

Ighalsk - Three User Stories

I've been trying to write a decent introduction to user stories, and it hasn't been working. Instead I'll just summarise them as follows:
* User stories describe what the software should do.
* User stories are written from a user's point of view.
* User stories are often used in agile software development (see e.g. here or here).

Here are 3 user stories for Ighalsk.

User Story A.

Tom feels the need for more, bigger and better monsters. He fires up the Ighalsk Monster Editor and creates a Plaid Dragon and a Blue Orc (starting from existing monsters and modifying stats appropriately). He tries them out and decides that yes, they add something to the game. Maybe Melissa would like them? He knows that she's already got the other monsters that he's created, so he just exports these two using the Monster Editor to a separate text file and emails it to her.

Melissa (a friend of Tom's and a fellow Ighalsk player) reads the email, saves the file, and imports the monsters - again using the Monster Editor. Next time she plays Ighalsk, Plaid Dragons and Blue Orcs might be lurking in one of the dungeons ...

User Story B

The Ighalsk website includes a page for uploading and downloading monsters. Each monster has a summary, a description written by its creator, and reviews posted by others. The Ighalsk community votes regularly on which monsters should be included in the next release, or the next bonus pack of monsters (downloadable separately).

User Story C

Cass stares blankly at the screen. YASD - those stupid Plaid Dragons of Tom's! Ah well, they're not official - she'll remove them before she plays again. Now, what sort of Hero to play this time? How about a Mighty Hero for a change? The good thing about starting a new game, she thinks, is that all Heroes have plenty of powers right from the start, which gives them lots of options in dealing with monsters. Though they can still die if they make the wrong choices ... And each sort of Hero calls for a completely different playing style, and a different choice of quests.

Saturday, January 2, 2010

Ighalsk - release 0.1.12 (and 0.1.11)

So I released Ighalsk v0.1.12 a few weeks ago (mid-December) but have only just got around to writing a blog post about it. And yes, I messed up again and needed to jump from release 0.1.11 to 0.1.12 almost instantly. (So 0.1.11 appears in the Subversion repository, but there's no separate download - the Level Editor doesn't work for that release.)

Here are the changes since release 0.1.10:

v0.1.12:
* Added an empty file in data/quests so that this directory will be included in a zip file. :/

v0.1.11:
* Updated the Monster Editor to allow deleting when entering names of Monsters, filenames for Monster Dictionaries, Monster comments and weapon damages (dice descriptions). There are different characters allowed for each type of data, with the loosest constraints for comments (where punctuation is allowed) and strictest for dice descriptions (where 0-9, d, and + are the only characters allowed).
* Monsters are now only visible when they are near the Hero, though with no line-of-sight; I'm assuming that the Hero has limited telepathy. Line-of-sight looks hard :/ so will come later. (Need to do more background reading on RogueBasin ...)
* Added lit squares - this shows the limits of the Hero's sight (telepathy), hence the areas of uncertainty (where the Monsters could be hiding). Needs tweaking a little ... Currently all walls on a level are visible - this will change as well.
* Added 9 new, more powerful and more expensive items of Armour - all are available in the Armour Shop. My current favourite is probably the "Hat of Serenity", which increases resistance to fear.
* Removed the dungeon not associated with any quest; this meant that Habitat is no longer used, so removed it as well. Hooray for simpler code!
* Added a basic Level Editor: currently this allows removing and adding walls, saving and loading levels.
* Characters saved with release v0.1.9 *can* be loaded using this release. (Yes, I have tested this.)

EDIT: The latest version can be downloaded from here.

Sunday, December 13, 2009

Ighalsk - The Nature of Illusions

Lord Apathy has a number of different types of illusions serving him - some on loan from other Lords of Illusion. These include "Embarrassment" illusions, so called not because they embody embarrassment themselves (and somehow infect those they encounter), but because they induce embarrassment in others. With disparaging comments, a haughty stare, and eye-rolling, such an illusion conveys a strong impression that your appearance, actions and indeed thoughts and plans are ridiculous, inappropriate and just plain wrong. It is an illusion, but the feelings of embarrassment that it causes are real.

Another type of illusion at Lord Apathy's command is "Paranoia". Again, it is not itself paranoid, though it may pretend to be. Instead, it induces paranoia in others. With whispered words, raised eyebrows and significant pauses, it insinuates that you have been betrayed and everyone is plotting against you, waiting for your slightest mistake to pounce.

These illusions can be destroyed (unraveled) in several ways; they are resistant to physical weapons, but most vulnerable to a Philosopher's use of reason.

Monday, November 30, 2009

Ighalsk - Tests and Time

At a recent checkin, there were 486 tests defined for Ighalsk, which took 31.8 seconds to run (on my old laptop: 500 MHz, Win98). I'm happy with the number of tests, but would like to decrease the time somewhat (still too many file accesses).

A Google spreadsheet showing some numbers and times for different revisions is available here. I don't know why the time went down to 9 seconds and back up again almost immediately, but I think the dip from 23.3 seconds to 20.9 seconds was just after some test refactoring to speed up tests - probably replacing file I/O with StringIO (see previous post).

Also, I now have a Twitter account here - any updates to these numbers/this spreadsheet will probably be posted on Twitter first (and possibly only). I'm working on increasing the popularity of #roguelike ...

Thursday, November 26, 2009

Ighalsk and Motivation

Ighalsk is not the first software project that I've worked on at home, or even the first game. But it is easily the most mature and furthest along. With earlier projects, I've had a great idea, started working on it, got a few things done, and then my enthusiasm has slowly worn off and I've given up.

With all my projects, I've only had an hour or two to spend on them in a night, and some nights that dropped to zero. Often in this time I'd get started on a task, but wouldn't have time to finish it - I might find a bug, or the task might be more complex than I'd planned for. Then I'd need to wait a day or more before I could work on it again. This was frustrating, and it made me feel like I was going very slowly.

With Ighalsk, I've generally been able to get something finished each night. Part of the reason is that I'm using Test-Driven Development (TDD) almost all the time. This means that my work cycle is usually: write a new test, run it to check that it fails, write just enough code for it to pass, check the changes in. A lot of the comments that I make when I check in changes start with "Added test + implementation of ..." Similarly when I refactor, each refactoring is small and I test it before I go further, so that when I do make a mistake, I can go back and fix it easily. It helps that the full set of tests runs in less than a minute (though I still want to speed them up further over time).

TDD has meant less bugs - or more to the point, that it's quicker and easier to fix bugs - and frequent refactoring (not to mention using Python!) has meant simpler code. Both of these factors have also helped me finish tasks more quickly and feel like I'm making progress.

Motivation has been less of a problem lately; I've got to the point that I have a playable game, where it's easy to see how any new functionality can fit in and will be usable immediately.

Doubtless it's also helped that I don't have any new games that I want to play at the moment - though often ProgressQuest is running in the background while I work on Ighalsk, and I've started playing FreeCol years and years after I last played Colonization ...

Friday, November 20, 2009

Ighalsk - releases 0.1.9 and 0.1.10

I've just released Ighalsk v0.1.10: you can download the source code here. This blog post also covers the changes in v0.1.9, since I didn't write a separate blog post about those.

Changes in v0.1.9:
* Weapons, attack powers and monsters now all do random damage (using a new Dice class). As discussed in the previous post, a Dice object can be created with a string such as "4d5+6". There's a little bit more to it than that; for example, when returning the string (which is used in the character screen or when examining a weapon), zeroes are dropped: "2d3" looks much nicer than "2d3+0".
* Savefiles now use compressed versions of the Hero and the current level. This reduces the size of the savefiles by a factor of about 8, and should improve savefile stability between releases (e.g. changes to methods in a class shouldn't affect the savefile). More savings are possible: currently (in v0.1.10, I should say) the walls in a level are saved as a list of booleans, which takes a number of characters per wall. They could instead be packed into 16-bit integers (just for saving and restoring - for speed, they'd still be a list of booleans during play).

Changes in v0.1.10:
* Refactored Level to use a list of booleans for walls. This speeds up level generation and also simplifies the code: there was a Square object for each square, doing nothing but holding and making available a boolean (whether or not that square contained a wall).
* Printing level to screen is now done in 2 passes for speed: the first for walls, the second for everything else. This is because everything else is sparse: that is, stored as a list of objects with positions, while the walls have one value per position. (Checking the list of monsters in a level for each square to see if it has a monster in it was taking some time.)
* Extracted resists of Beings, Families and Armour to a separate Resists class for ease of adding resists and returning the resist for a given damage type. This removed duplicate code between Being and Adventurer, and also simplified the size of both classes.
* Added BoostPowers which improve resistances temporarily, and Boosts to hold current improvements. Any Being can have boosts theoretically, though in practice only the Hero can, if she or he uses a boost power on herself or himself.
* Blessed and Mighty Heroes can now use a boost power: "Tenacity" and "Courage" respectively.
* Fixed bug 2889190 where up and down were reversed when using keys on the numeric keypad: thanks to Genosha for raising this bug.
* Added 7 new Monsters: Lesser Haunt, Paranoia, Zombie, Ivy, Flatworm, Ghost Spider, and Greater Huntsman. (The Zombie here is a common, stock-standard zombie; variants will be added later.)
* Added Monsters for level 3 of each quest.
* Characters saved with release v0.1.9 *can* be loaded using this release! (I've only tested this for one character, but I don't expect any problems for special cases.)

I've now implemented most major pieces of functionality that I was planning to add before releasing v0.2.0. The exceptions are adding a Level Editor and special levels (level 5 of each quest) - the plan is to use the Level Editor to generate the special levels :). Of course, there's a bunch of tidying up and refactoring to do, plenty of minor functionality that could be added, content to add (new armour and monsters are the most critical parts) and no doubt bugs to fix.

Tuesday, September 29, 2009

Ighalsk - release 0.1.8

I've just released Ighalsk v0.1.8: you can download the source code here.

Changes since the last release include:
* Throughout the code, Profession has now been replaced with Epithet. That is, Heroes now have an Epithet, which summarises their powers. This brings out more clearly that the powers and abilities of a Hero are inherent rather than the result of training. It also implies (at least in my mind) that the Hero is unique, and shouldn't expect to run into opponents with similar powers and strengths when following Quests.
* The available Epithets for Heroes are now "Mighty", "Philosophical", and "Blessed" (as described here). That is, instead of "Joni the Warrior", a Hero would now be called "Joni the Mighty".
* When generating a level, corridors are now checked whether they overlap with existing open spaces before they are placed (and won't be placed if they do overlap). This makes evading monsters considerably easier - previously, the corridors were too tightly packed together and often did overlap; now, monsters often get stuck and have to wait until the Hero comes closer. (Yes, I guess I could implement path-finding (or at least a look-ahead of a few moves) when I get a spare couple of months, but I'm concerned that that would also slow down the game, which seems to have slowed down already over the last release or two for some reason.)
* Increased the size and number of rooms and corridors in levels, while keeping the number of monsters the same. This goes with the above change - now there can be more rooms and corridors without them being tightly clustered together. Reducing the monster density also means that there's not such a desperate scramble for survival when the Hero first enters the level. I'm still not altogether happy with how the rooms look on a level - the BSP algorithm mentioned on Roguebasin looks like it would generate better-looking levels.
* A Hero now has different physical, mental and spiritual strengths, depending on their epithet; a strength may add to the weapon damage, depending on the weapon. In particular, Mighty Heroes have physical strength of 4 and other strengths of 0; Philosophical Heroes have mental strength of 3 and other strengths of 0; Blessed Heroes have spiritual strength of 2, physical strength of 1 and mental strength of 0. So for example, a Mighty Hero using any bladed, blunt or piercing weapon will get 4 extra damage with that weapon; a Blessed Hero with such a weapon would get 1 extra damage, and a Philosophical Hero would get 0 extra damage. The exact values, as with so much else, will get balanced later, when the combat system is stable.
* Added a Character screen which displays the Hero's attributes, including the total resists (due to armour worn) for different weapon (damage) types such as fire, blade, or blunt, and the damage that the current wielded weapon will do, due to both the weapon itself and the Hero's strengths. This screen also displays the gold that the Hero is carrying; previously, the only way to know how much gold the Hero had was to try to buy something from a shop.
* Added descriptions of quests, which can be accessed from the Palace screen. This involved a few unexpected fixes, in that the description is read in from a text file and reformatted - but then spaces have to occur in the right places, I wanted to be able to have paragraphs in a description, and a couple other minor problems. Still, hopefully I'll be able to reuse the same format in other places (like monster and epithet descriptions).
* I also replaced one system test with a unit test for speed and simplicity - the unit test should still catch the same bug that the system test was designed to catch.
* Similarly, I refactored the Movement class to simplify it: it now only sends messages to one viewer object, where previously it also sent them to each viewer object in a list. (In the current implementation, there was only ever one viewer object in that list.) If necessary, with the refactoring, the sole viewer object could always forward messages to other viewers on a list - but I doubt that that will be necessary for this game.

Next I might focus on monsters again. I'd also like to introduce variable damage for weapons, probably using a Dice class. The constructor method for this class would take a string of the form "4d5+6", which would represent 4 dice, each with 5 sides, with 6 added to the result. (Or if you'd prefer, each die could have 20 sides, and each number could be repeated 4 times.) Each dice object would then have a "roll" method to randomly generate a value.

I would like to also introduce monster memory sometime soon - that's memory that the Hero has of monsters, not memory the monsters have of the Hero. It might be helpful to know what a Bladeworm or Nightcat looks like, though hopefully a Vampire Moth is self-explanatory ...

Tuesday, September 1, 2009

Ighalsk - release 0.1.7

I've just released Ighalsk v0.1.7 (you can download the source code from here). A lot of little things have changed since the last release:

  • The Monster Editor can now be navigated using buttons as well as keys; it also supports more than 12 monsters.

  • The Hero (PC) can now die - yes, this is a necessary feature - perhaps unfortunately; I've been playing "Lego Star Wars" with my son, and it is refreshing that characters in that game just fall apart and quickly come back together again after dying. There have been some interesting discussions of permadeath in roguelikes recently here and here.

  • After examining an item, the next screen is either the Inventory or the Equipment screen (whichever screen the item was examined from). Previously the next screen had been the map of the current level; I've now implemented a stack of states, pushing the old state onto it every time the state changes, and popping off states after examining an item. This should be useful for other screen transitions as well.

  • Treasures are now generated and placed randomly on quest levels, and can even be picked up by the Hero.

  • There's also more to buy with treasure: I've added 3 new, more powerful and more expensive weapons in the Weapon Shop, one for each type of Hero (profession).

  • I've added 9 new monsters, using the Monster Editor, and 2 new families of monsters (worm and plant).

  • This gave me enough monsters to fill in level 2 of each of the 3 quests.


There were also a couple of small refactorings that shouldn't affect game play but will make the code easier to maintain and extend.

These aren't present in v0.1.7, but here are some draft descriptions of the different types of Hero (originally mentioned here):

*Mighty*
You were born with strength and athleticism far surpassing those of ordinary men and women. You are trained in the use of an incredible variety of weapons, and in the tactics of war. You have wrestled bears to the ground, defeated a squad of enemy soldiers single-handed, and executed flawless tactical retreats.

*Blessed*
You are divinely blessed. You have been given the gifts of healing and protection. You are called on to fight evil and bring peace to the land. At your approach, flowers blossom, birds sing more sweetly, and undead gibber in terror.

*Philosophical*
You have spent many hours studying books and in the company of your own thoughts, and thereby learnt many mysteries. You can influence the universe and shape matter and energy using only the power of your mind. You have also practised the arts of argumentation, and can use them to reduce untrained and unshielded interlocutors to a state of helpless confusion. You know the names of stars, the greater and lesser syllogisms, and the secret delights of pyromania.

A friend also suggested another type of Hero, which I'm thinking of calling *Cunning*, but this type needs more features to support it and so might not make it into Ighalsk for a few releases yet ...

Wednesday, July 22, 2009

Ighalsk - release 0.1.6

I've just released v0.1.6 of Ighalsk here. (Yes, I skipped v0.1.5 - I actually made a tag for it in Subversion, but then discovered when I tested the zip file that I'd forgotten to check in a new file ... so it got superseded by v0.1.6 immediately.)

As planned, Ighalsk now has quests. True, each quest has only one level at the moment (there will eventually be 5 for each), but it's a start. One of the quests is to "defeat Lord Apathy in the Tunnels of Lost Dreams". For those who lack motivation for this quest, here's some background.

Lord Apathy is the least powerful of the Lords of Illusion. He sits (or, more often, sleeps) in a half-completed maze of tunnels filled with lost dreams, brooding, bitter and unkempt. From here, he spreads despair, hopelessness and, yes, apathy across the countryside. He should probably be stopped.

Another quest is "Defeat Elannonen the Lost in the Necropolis of Zezun". Queen Miala points out (will point out), "Why do we keep on building these cemetaries and tombs and graveyards if they just fill up with undead? Why don't we start cremating our dead?"

The final quest present in this release is "Defeat the Witch-Spider Skkshryx in Arachnaxos", about which I have little to say except that the witch-spider is not fond of vowels.

Tuesday, July 7, 2009

Ighalsk - in which I discover StringIO

The suite of unit (more or less) tests that I run for Ighalsk currently takes about 11 seconds to run 281 tests (for the current version with Subversion revision number 58). This is not too bad, but I've read about projects running more than 1000 tests in less than 10 seconds, perhaps even less than 1 second. In particular, the suggestion is to avoid file accesses in unit tests (see for example Michael Feathers here).

When using Java, I think the idea is to accept an abstract Reader object as a parameter, which can be a FileReader object in the actual program, and can be mocked as a StringReader (or is it ByteArrayInputStream? so many choices!) in test code for speed. (On checking, I found that the example I was thinking of is actually for .NET ...)

I was planning to implement my own FileReader and StringReader objects in Python, but then I'd have to unit test those as well ... when, reading through the Python manual, I discovered a class called StringIO!

Its description begins, "This module implements a file-like class, StringIO, that reads and writes a string buffer (also known as memory files). See the description of file objects for operations ..." - which is exactly what I wanted!

I've started using this approach (mocking file objects using StringIO) in new classes, but I still need to switch to it for existing classes. In most cases, it should be a matter of opening a file and passing in the file object before calling a function instead of passing in a filename and opening the file inside the function, though this still means that there'll be at least one class somewhere that will still have to open some files ... but separating out this functionality should mean that file I/O only needs to happen in a small number of unit tests. Yet another treasure hidden away in the depths of the standard Python libraries!

Tuesday, June 23, 2009

Ighalsk - Adding a List of Buttons

Disclaimer: All code discussed in this post is covered by the GPL. It can be browsed through this link (to the latest release).

About a month ago, I decided to move away from a strict interpretation of "roguelike" for Ighalsk, and add a window with buttons that can be pressed to carry out actions. A friend had pointed out that it was hard to remember which keys did what - something which I've found true for many of the roguelikes that I've played over the years. I'll say a bit about my solution, but first some background.

In Ighalsk, I've taken a perhaps overly literal interpretation of the "Model-View-Controller" pattern. The source code is organised into directories called "Model", "View" and "Controller" (there's also a "Common" directory for classes used by both Model and Controller classes). For each screen of Ighalsk (each state of the controller), there are corresponding View and Controller classes. For example, there are ShopViewer and ShopController classes which handle viewing items on display in a shop and buying an item. (There's also a Shop class, in the "Model" directory, which holds item names and prices and can return an item if it is bought.)

Which View class is active (displaying text on the screen) at any given time is handled by a high-level class called IghalskViewer; similarly, which Controller class is called is handled by IghalskController.

Back to my recent changes. Stating the obvious, I called the class implementing the window with the buttons "ListOfButtons". All it really does is display a list of labeled buttons, and call methods when the buttons are pressed; but what the buttons say and do changes as the controller state changes throughout the game.

Each Controller class now has a "getEvents" method which returns a list of strings. The ListOfButtons class takes this list and adds a button to its window for each string. Each button is configured so that when it is pressed, the "sendEvent" method of the currently active Controller will be called, with that string as a parameter to the method.

(Rather than add the full functionality to each Controller class at once, in a huge, big-bang mountain of coding, I did it step by step. I started by creating an AbstractController class and made each Controller class a subclass of it: the AbstractController has a default getEvents method which returns an empty list, and a sendEvent method which does nothing. Thus at this stage, there was a window for the list of buttons, but there were no buttons on it. I then filled in the details of getEvents and sendEvent one class at a time, so that gradually more and more of them supported the list of buttons, and the list of buttons was populated more and more often while playing the game. As I went, I added a unit test for the class I was modifying.)

Each Controller also needs to respond to keys being pressed, by implementing a "processKey" method. This method now calls "sendEvent" with an appropriate event description. (This is to reduce duplication, following the "Don't repeat yourself" principle - see the Ighalsk Coding Guidelines.)

The game should be able to change screens (display a different view of the character, their possessions, or the world around them) as requested by the player, either through pressing a key or clicking on a button. In the source code I've called this "changing the state" of the controller and the view, and it happens through calling the "changeState" method of IghalskController. (I'm of the view that it's impossible to be too obvious with names.) This is done through a call-back type thing.

So there's a connection between events and states, in that for some events (buttons), the game (controller) should change to a different state. There's also a connection between keys and events, in that pressing a key is equivalent to sending a particular event.

Again exercising my gift for stating the obvious, I wrote a class called "KeyEventStateDict" to hold these connections, available to all controller classes. It's initialised with a list of tuples [(key, event, state)] and stores these internally. It then provides a "getEvent" method which is passed a key, and a "getState" method which is passed an event. It also provides a "getEvents" method, which returns a list of events in the same order as the initial list of tuples. (Internally it holds two dicts, hence the "Dict" suffix to its name.)

These methods abstract away a lot of the code needed to handle both pressing keys and clicking on buttons. But not all of it: several of the controller classes still need some code to handle special cases - to take actions, move, change what the character is wearing and so on. Otherwise, all the player would be able to do would be to change from one screen to another.

Adding a list of buttons to each state (screen) was not only adding a useful piece of functionality; it also gave me the chance to simplify the controller classes and to add unit tests for each, thus setting up infrastructure to make refactoring easier in future.

This was the biggest change between release 0.1.3 and 0.1.4. Next will come a Palace holding a Queen who asks our Hero to perform Quests ...

Thursday, May 28, 2009

Ighalsk - Invisibility and Awesomeness

I've just discovered "Fluent Self", an amazing and inspirational blog. Some of the posts got me thinking about my approach to Ighalsk, including "Visibility. Invisibility. Power. More pirates."

I was happy to be developing Ighalsk on my laptop for a long time, keeping an archive (using CVS archive) but not exposing it to the outside world or talking about it to other people (OK, maybe I mentioned it in broad terms to 2 friends and my wife). So I was running in stealth mode, lights off, invisible - which meant that no-one could criticise my work, *but* no-one could comment on it or praise it either. And acknowledgement and respect are big motivators for me. I'd always intended making Ighalsk open-source, it was just a question of when.

Even after releasing it (and I'm up to release 0.1.3 now), I've been keeping a lot of my plans under wraps for fear of Ighalsk being labelled "vapourware". *But* that always means that others can't know how awesome it's going to be, *and* can't help me make it more awesome. So here goes.

I'd always planned (well, since a couple weeks after deciding to write a roguelike), to have special levels throughout the dungeon. Each with its own name, theme, coherent selection of monsters, carefully designed layout presenting tactical challenges and opportunities, and of course a unique monster to defeat. The list I came up with early on was:
  • tunnels of lost dreams (dwelling place of Lord Apathy);
  • spider caves;
  • ogre halls;
  • necropolis;
  • caverns of night;
  • pits of chaos;
  • corrupted temple; and
  • imperial palace.

The original plan was to have these at every 5th level, but I recently changed my mind. Now I plan to have a series of dungeons which can be entered separately, with a hand-crafted level, including the chosen unique, at the bottom of each dungeon. Each dungeon will be a quest, described by the young queen in a royal audience.

Similarly the plan was to have increasing difficulty as the Hero descended, but now I'm thinking I'd like to mix monsters of all difficulties, presenting a different set of tactical and strategic challenges.

The Hero will start out tougher and more powerful, though my plan has always (almost always) been to have plenty of options (powers) available from the start, with quite different mixes for each type of Hero. This is something else that will change: instead of choosing their Hero's "Profession", a player will choose their "Primary Gift". "Warrior" will be replaced with "Mighty", "Priest" with "Blessed", and "Scholar" with "Philosophical".

Finally, something that I've also planned to do for a long time but have been thinking about again recently is Food that gives a small, short-duration bonus when eaten. What I have so far is Bread (or Potatoes) to restore Hit Points, some sort of vegetable (maybe Cauliflower or Cabbage) to restore Power Points, Spinach to temporarily boost Physical Strength, Fish for Mental Strength, and Wine for Spiritual. Then there's Beef and Chicken, which may well decrease and increase susceptibility to Fear.