Archive

Posts Tagged ‘thecave’

Bucolic coding (now with video)

July 3rd, 2010 jice No comments

Source: doryen.eptalys.net

I recently posted a screenshot of a lake in the first level of the cave. After a post about ASCII water ripples on mnemonicRL’s blog, I decided to make a video to show how water ripples look with true color, real time and subcell rez ;)

On the video, you can see the player swim, throw stones in water, scare fishes and finally catch a living fish with his bare hands !

The fish shoal AI is adapted from this :

http://www.chromeexperiments.com/deta…
The water ripples are done with an old school effect like this :
http://www.gamedev.net/reference/arti…

A few remarks :

  • the zoom and big yellow arrows are done with the video recording software, not the game!
  • you can throw an item by dragging it out of the inventory window
  • there’s a bug when there are too many fishes in the shoal, it starts to display some circular patterns (you can see it a bit when the fishes are fleeing in the south-east shallow waters)

Hard and soft stacks : more item ramblings

June 10th, 2010 jice No comments

Source: doryen.eptalys.net

Even if I’m only at the first steps of the first chapter of the last doryen prototype (!…), I already need more advanced stuff in the core engine than what I had in the latest versions of TCOD… Funny how things never seem to be complex enough when you code a roguelike….

The basic item

This is always around the item core class. For a basic game like Pyromancer, items contain only the item specific data. Hell, pyro doesn’t even have an inventory. Items are used and destroyed as soon as you walk on them…

class Item {
};
class Weapon : public Item {
.. weapon specific data
};

Hard stacks of items

But as soon as you have an inventory, you have to think about item stacks. If your inventory simply display the items in a list, you can have lots of redundant items. For some complex item classes like weapons, this can be acceptable, but for basic items like ranged weapon ammunition (arrows and bolts), you certainly don’t want to list each one independently…

an arrow

an arrow

an arrow

… (repeat 100 times)

Of course, you want to see all arrows as a single stack of items :

100 arrows

Also, in term of performance and memory, it’s certainly better to have a single Item instance with a count of 100 rather than 100 instances. So you add a count member on the item class.

class Item {
   int count;
};

Then it’s only a matter of merging / splitting items when you pick up or drop one.

Picking up :

if the inventory already contains an item of the same type, increase the count and destroy the item on ground

else move the item from ground to inventory.

Dropping :

if count > 1, decrease the count and create a clone with count = 1 on ground

else move the item from inventory to ground.

But you may not want to merge all types of items. If you wear one rusted knife and you pick up an enchanted knife of diarrhoea (target suffers from diarrhoea for 5 sec on successful hit), you don’t want the magic knife to be merged and stored as a rusted one. So you need a flag on each item type that indicates if it is stackable or not.

class ItemType {
   bool stackable;
};
class Item {
   ItemType *type;
   int count;
};

Now picking/dropping operations only do the merge/split on stackable items.

Ok the count member is useless for non stackable items. You could have two inheriting classes StackableItem and NonStackableItem, but I’m not a big fan of Himalayan class hierarchies…

Soft stacks of items

This is what I was using in TCOD but it’s not sufficient. Imagine you have food depreciation. A piece of meat will give you a lot of health points when it’s fresh, but in your backpack, it losses slowly its quality until it’s really rotten and you’d better not eat it or you’ll be poisoned. Since a piece of meat has an internal timer, you can’t merge it with another one (except if their timer match perfectly). Yet, you still don’t want to see :

a piece of meat

a piece of meat

in your inventory. You want :

2 pieces of meat

and if one of them just get rotten, your inventory now contains :

a piece of meat

a rotten piece of meat

That’s what I call a soft stack. In the program memory, the items behave exactly like non stackable items, but in the inventory screen, they look exactly like the stackable ones. No merge/split operations here.

What if you want to eat the older piece of meat first ? I think a good solution is to be able to unwrap soft stacks.

+ 2 pieces of meat

click on the ‘+’ button :

- 2 pieces of meat

a piece of meat (rotten in 24min)

a piece of meat (rotten in 12 min)

Of course, unwrapping a 100 items soft stack would be bad. But generally, item count is inversely proportional to its “stackability”. Non stackable items are generally big and you wear only a few of them. Soft stackable items are more numerous, but generally no more than 10 per class. If you walk with 50 pieces of meat in your backpack, there’s something wrong in the game’s balance. Hard stackable items are the most numerous, the king of them being the gold coin (even though wearing 2000 gold pieces in one’s backpack is not very realistic…).

Also note that with the possibility to unwrap soft stacks, you could as well discard non stackable items and have everything soft or hard stacked. But that would represent a lot of wrap/unwrap operations while using the inventory, a bit like using windows explorer and it’s probably better to have the major items (weapons, armors, …) directly accessible as non stackable items.

For soft stacks, you just have to replace the stackable boolean by an enumeration :

class ItemType {
  enum { NO_STACK, SOFT_STACK, HARD_STACK } stackMode;
};

(longish) item gibbering

May 28th, 2010 jice No comments

Source: doryen.eptalys.net

The cave has just went through a major refactoring of the item system. Items are the core of any roguelike and any hack&slash, so you’d better think twice before starting to code their foundation classes. This is the third item system I code and I hope it will last longer than the previous ones.

µstep method (tm)

Fortunately I’ve used advanced µstep method (tm) for this refactoring and it went perfectly smoothly. It took only two evenings and the game never stopped compiling  or even running. So far, there is no visible bug. What I call µstep method is the process of moving the code by tiny steps, having everything compiling and running between every step. Steps should not be bigger than a coding session. For this refactoring, I’ve tried the extreme way and used steps of a few dozens of lines. Of course, you go through some very ugly stage where some items use the new system while the others keep using the old one, but you can stop the refactoring at any moment and work on something else. The game runs, it’s still playable, even releasable even if a nuclear blast is occurring in its core classes. You could believe that it takes longer to do all those steps than blowing everything and rewriting directly some clean new code. Well, my experience showed me that in that case, you may have the first version of the new system sooner, but debugging it will be a real pain and in the end, you’ll have spent more time than with the µstep method.

Item systems

The Chronicles Of Doryen’s system

So what about those three systems ? The first one is from the old “The Chronicles Of Doryen” codebase. I was pretty ambitious then and put all the levers to the max. Of course there is a generic Item class. Each item is associated to an ItemType that describes the item behavior. Item types are organised as a tree, the “root” item type being the, well… root of the tree. Then you have a first level of abstract types of very high level : static, material, general, shields, armors, weapons. Each of these abstract types contains several levels of abstract types before you reach the leafs, actual items. For example, under general, you have food, lights, oils. Food contains ingredient, potions. Weapon contains blades, hammers, staffs, axes. Blades contains daggers, short swords, single handed long blades, two handed long blades.

Organizing the item types in such a hierarchy has several advantages :

  • the game code can easily check if an item belongs to a category. If you want to check if an item is some food, you can simply call item->isA(ItemType::food) instead of having a long list of tests (item->type == carot || item->type == tomato …).
  • abstract types (they could be called ‘categories’) are used to filter the inventory. With this system, you can easily implement an inventory that looks like Windows Explorer, with a hierarchy of directories (abstract types) and files (actual items). In TCOD, the item types config file allows me to define which abstract type is shown in the inventory. I have a few hardcoded filters (all, food, light, armor, shield weapon), but inside a filter, items are still organized as a tree as seen on this screenshot :
  • in the config file, abstract types are not only containers. You can define properties on them that will apply to all sub-types. Maintaining the (huge) config file is easier and there is no duplicated data. Example : a part of the armor configuration :
// ********** ARMORS **********
ItemType "armors" {
abstract
inventory
ascii='['
feature "wear" {}
feature "armor" { when "is_worn" {} }
 ItemType "light armor" {
  abstract
  inventory
  ItemType "leather armor" {
  abstract
    durability=4
    feature "armor" { bonus=10 }
    ItemType "leather leggings" { feature "wear" {body_part="legs"} cost=15 }
    ItemType "leather gloves" { feature "wear" {body_part="hands"} cost=10 }
    ItemType "a leather cuirass" { feature "wear" {body_part="torso"} cost=25 }
    ItemType "a leather helmet" { feature "wear" {body_part="head"} cost=15 }
    ItemType "a leather left bracer" { feature "wear" {body_part="left wrist"} cost=5 }
    ItemType "a leather right bracer" { feature "wear" {body_part="right wrist"} cost=5 }
    ItemType "leather boots" { feature "wear" {body_part="feet"} cost=10 }
  }
}
}

As you can see, the actual item types only use one line because most of the properties are defined on higher level abstract types.

There are no hardcoded item types (like Weapon, Food and so on). ItemType is also a generic class. Distinct behavior in the game come from another class : item features. The item type defines some standard properties of the item : what character is used to represent it, is it stackable and so on. But the most important properties are in the features. Exemple of features are whether the item can be worn or wielded, eaten, can it be de/activated (like a torch), does it deal damages when used, or does it protect it's owner. Each item type contains a list of features and the game checks for known features to implement the correct behaviour.

You can see on the config sample above that armors have two features : "armor" and "wear". Armor means that the owner's armor bonus is increased. "wear" means that it can be worn by the player.

Now TCOD doesn't stop there with a list of hardcoded features like Armor, Wear, Edible, ... No, no. Ambitious I said... Features are also generic! Here is the third level of abstraction. The Feature class defines a generic feature with an id, a name and a list of parameters. That means I can add a new feature in the config file, let's say "BlowIfHit" with some parameters (blowRadius, blowColor) and without changing a line of code (except the config file parser), the feature is available in the game. Of course you have to add some code to actually implement this feature (if item->hasFeature("BlowIfHit") then trigger explosion), but you don't need to code the BlowIfHit class.

Now generic Feature is pretty complex to implements, because a feature has static parameters (defined on the item type) and dynamic parameters (defined on the item because they change over time). For example, a torch light radius is defined on the torch item type, but it has also to be stored on the torch item because it will decrease over time until the torch is burnt away.

Features also have conditions. For example an armor has "armor" and "wear" features, but both features are linked with a condition (when "is_worn"). That means the armor bonus is only active if the item is worn.

This whole stack of generic classes really works pretty well, but that's a lot of code with high level of abstraction. Leave it a few months and you don't understand it anymore. Read it for the first time and you're completely lost.

Pyromancer ! system

Pyromancer ! is a 7DRL so I took the exact opposite direction : straightforward approach with everything hardcoded. A class for each item. For small size projects, you can't make simpler. Of course, you probably still need an Item base class to avoid duplicating all the code.

The cave's items

The cave is based on pyromancer! source code, so it started with the same design. But it reached the size where this design cannot stand the requirements anymore, hence the refactoring. I didn't reimplement the whole TCOD stuff though. I still use Item, ItemType and ItemFeature classes, but now features are hardcoded, with a class for each feature. I also dropped the item type hierarchy is favor of something simpler and more powerful : tags.

The main inconvient with TCOD's hierarchy is that an item belongs only to one branch of the tree. For example, an item can be an ingredient (food branch) or a material, but not both. Tags are more versatile :

  • You can apply any number of tags to each non abstract item type.
  • Tags are used in the config file like preprocessor macros in C. All of the tag's properties are copied into any item type containing the tag.
  • Tags are not necessarily linked to each other. Getting the properties of a blade does not mean that you have to get the properties of a weapon.
  • But you can still organize tags in hierarchy. In that case, you get the same behavior as TCOD's type hierarchy.
  • In the game engine, tags are reduced to a bitfield used to classify the items with a TCOD-like isA() function, but you can now have overlapping hierarchies instead of a single one.

With tags, TCOD armor config file would look like this :

// ********** ARMORS **********

ItemTag "armor" {

    inventory

    ascii='['

    feature "wear" {}

    feature "armor" { when "is_worn" {} }

	ItemTag "light armor" {

        inventory

		ItemTag "leather armor" {

		    durability=4

		    feature "armor" { bonus=10 }
		}
	}
}

ItemType "leather leggings" { tags=["leather armor"] feature "wear" {body_part="legs"} cost=15 }
Or like that :
// ********** ARMORS **********

ItemTag "armor" {

    inventory

    ascii='['

    feature "wear" {}

    feature "armor" { when "is_worn" {} }
}

ItemTag "light armor" {

      inventory
}

ItemTag "leather armor" {

    durability=4

    feature "armor" { bonus=10 }
}

ItemType "leather leggings" { tags=["armor","light armor","leather armor"] feature "wear" {body_part="legs"} cost=15 }
I find this system more powerful, and it has a simpler data structure.

If you’re still reading, you earn a free phoenix flying mount usable in the first release of TCOD, to be released Q3 2046. :D

Roguelike meets Navier-Stokes…

May 24th, 2010 jice No comments

Source: doryen.eptalys.net

Crazy, uh ? Someone said recently I was completely insane… Maybe…

Improved lakes

May 21st, 2010 jice No comments

Source: doryen.eptalys.net

I’ve been quite productive on my next prototype recently. I’m trying to set up a small sandbox where you can experiment various game mechanisms, mostly around items.

Even though I try to focus on those mechanisms, I can’t help but spent a lot of time on visual fluff… This is a lake with reflected clouds. The small dots near the two characters is a shoal of fishes. This is the prelude chapter, before you enter the cave and I try to give it a daydream aspect, where everything’s quite and beautiful and nothing bad can happen. I hope to be able to setup some sound atmosphere to enforce this. Right now all I have is a intro screen music.

Bucolic coding

April 2nd, 2010 jice 1 comment

Source: doryen.eptalys.net

Various experiments, bugs and crashes on the road to good looking forests… Now turn on Beethoven’s 6th symphony and check that picture :D

The final (bottom right) is the result of two years of work on libtcod and doryen prototypes (obviously, pyromancer! subcell engine), but also third party projects using libtcod, like  ”The Way Of Fallen” (look at the way the fov is handled in this picture), “Umbrarum Regnum” (flexible ground system as seen in this picture) and “Aviel’s Stand” (oh my god ! check those trees). This says a lot about how much I owe to people using libtcod…

The cave’s title screen – first attempt

March 8th, 2010 jice No comments

Source: The Chronicles Of Doryen

I’ve been working on the cave, polishing the title screen. I’m still not fully satisfied with the forest picture though, but I did two nice improvements :

  • 3d smoke fx ripped from pyromancer is now much faster. Instead of computing a full screen picture each frame (one 3D simplex noise call for each subcell, 30 times per second => 480 000 calls per second), I compute it only 4 times per second and linearly interpolate the pictures (=> 64 000 calls per second). At 30 fps, this leaves a lot of free CPU, which brings me to the second improvement…
  • the lengthy world generation (around 7 seconds on my Athlon Phenom 9650) is now computed by a background thread during the title screen. If you spend a few seconds staring at it, you can almost switch to the school selection screen without any delay. And I have plans to make you stare at it not only the first time you run the game ;)

Disco time

January 30th, 2010 jice No comments

Source: The Chronicles Of Doryen

And here are some free colorful psychedelic posters for people in love with meteorology graphs :)

For some weird reason I can’t help but stare at them from time to time, imagining all the adventures and the dungeons that must exist in those worlds… Erm… I think I need to go out more often…

RRT rivers (until I get something better)

January 30th, 2010 jice No comments

Source: The Chronicles Of Doryen

Here is the current state of the world shaded as it appears in the school selection screen. Now the ground renderer takes biomes into account, the ice floe is a bit more natural and there are RRT rivers and a cartoon-like map border. Since Mingos just finished polishing the djikstra module in libtcod, I think I’ll try to use it to get better looking rivers.

And here is how it appears inside the game :

Biomes balancing and rivers

January 28th, 2010 jice No comments

Source: The Chronicles Of Doryen

I’ve replaced the simple sinus function for latitude temperature with a bit more complex one :

sqrt(0.5*(1+sin(x-1.6)^5))

Go there and copy/paste the function to see it. Put 0 and 6.28 in the x min and max.

The result is that there is more temperate climate, tundra and desert bands are thiner as seen on this biome map.

I think it’s better for the gameplay. We have a bit of tundra, a bit of desert, some tropical zones, but the main part of the land is Tolkienish temperate climate.

I spent also a good amount of time breaking my teeth against river algorithms… I tried slope based simulation, A* and dijkstra path finding using slope or altitude as movement cost and finally rapidly-exploring random trees. None of them gave a good result… I’ll probably fall back to a more pragmatic, less simulationistic solution…