Category Archives: The Lonely Dwarves

Release Notes: Lonely Dwarves 1.5.1 Build 208

New Features
* When moving onto a tile that starts a conversation, suppress input for 250ms to prevent accidentally skipping.
* Added ways to get all of the secret items shhhh.
* Added several conversations.
* Added a scripted Orc encounter.
* Max Level is now 50 (but should never get close to that).
* New portraits for the Dwarves.

Bug Fixes:
* Number of Typos, spelling, grammar mistakes fixed. (Send these to me).

Procedural Map Generation In The Lonely Dwarves

The vast majority of places in the world of the Lonely Dwarves is created manually. The Minotaur’s labyrinth however, has two procedurally generated maps for the Dwarves to explore. In addition to being initially random, when they leave and re-enter, a completely new map is created for them.

When I decided to add this feature, I did some careful design work to create something modular and extensible. I hope to reuse large portions of this logic for a roguelike game in the future, while also extending it greatly.

Take a look at the diagram for the basic flow:

Screenshot 2016-03-12 21.44.54

In the Lonely Dwarves, the parameters are specified in an XML file for procedural generation. Take a look at this example, which is currently one of labyrinth levels:

<layout type="random">
  <generators>
    <generator type="maze-grow-tree">
      <size>
        <width>12</width><height>12</height>
      </size>
      <newest>50</newest>
      <random>50</random>
    </generator>
  </generators>
  <translators>
    <translator type="simple-maze">
      <block-width>1</block-width>
    </translator>
    <translator type="fill-border"/>
  </translators>
  <content-creators>
    <content-creator type="hall-treasures">
      <treasure-set id="basic_goodies"/>
    </content-creator>
    <content-creator type="stairs">
      <stair id="initial" to-map="moosecastle_1">
        <destination>
          <coord x="6" y="22"/>
        </destination>
      </stair>
      <stair id="down" to-map="moosecastle_3">
        <destination>
          <target location-id="initial"/>
        </destination>
      </stair>
    </content-creator>
  </content-creators>
  <mapper type="moose-maze"/>
</layout>

The first phase in the process is the generators. It may not surprise you that the internal representation until the very final process is a graph. The generators are responsible for creating the base graph. In the above example there is only a single generator, but they can be chained together to create interesting combinations. The Minotaur labyrinth uses the “simple-maze” generator, and as you can see from the parameters, it is defined to split how it decides what vertex to expand by choosing Prim’s Algorithm 50% of the time and the Recursive Backtracker Algorithm 50% of the time.

The second phase in the process is the translators. The translators process the graph and translate it to a graph that is a better representation of the physical world we’re trying to create. The two translators involved here space the graph so that walls have a thickness (of 1 tile), and insert a border around the graph.

The third phase in the process is the content creators. These examine a graph and add content at locations fitting the parameters. There are currently two content creators for the Labyrinth, one that adds treasures from a predefined collection: ‘basic_goodies’, and the more interesting one, the one that adds stairs. You can see that the stairs have full definitions and ids, they just need a place to go. The content creator will do a search for locations with 3 walls as potential places for stairs and place them randomly in one of the valid locations.

Screenshot 2016-03-12 22.29.32

The final phase is the mapper phase. A mapper looks at the graph and maps it to a … map, sorry for the pun. The graph has a system of identifying what a particular vertex represents, and it’s up to the mapper to make sure that the in game representation matches by using a correct tile and blocking areas that can’t be accessed.

I’m thinking about adding events that turn on lights as you step onto certain tiles to help you navigate. That will be a future enhancement, probably after play-testers get mad that it’s too difficult to traverse the mazes.

Orc Hideout Theme

New Year’s Eve goal: write some music.

Status: Success!

      Orc Hideout Theme

This track will be played when when the player infiltrates the Orc Hideout. At this point I think we’re 100% complete for music. There are 12 total tracks, and composing them I think has been the most fun part of writing my own game.

Math and Game Design: Damage Filters for Abilities

Tales of Jornica: The Lonely Dwarves will have many weapons, magic spells, and abilities that you can use to vanquish your foes. In order for things to be interesting I have been attempting to design interactions that can be utilized in complex ways. Suppose you have an ability that does damage to a monster. The direct damage is represented by an object that breaks up the potential damage by element and each element has a Calculated Expression associated with it. A Calculated Expression, as described in a previous blog posting, combines dice rolls and custom formulae. Each time an ability is used to cause damage, a roll is invoked on this object and a RolledDamage object is created.

Now suppose your character is wielding a Flame Sword – It does some Physical damage, and a great deal of Fire damage. We are in an environment that magnifies fire damage making it an awesome weapon. The magnification of Fire Damage is accomplished with a Damage Filter – this one in particular is due to an environmental effect. The effect can be described as “Fire Damage is increased by 50%”

Now what happens when we come across a Fire Elemental? Fire damage actually heals those things, we are in trouble! Or are we? We just happen to have a Ring of Bad Imperial to Metric Temperature Conversion. Wearing bestows a damage filter described as “Fire Damage is decreased by 30% and converted to Ice Damage” Awesome! We lose some total damage in the process, but we now can hit the Fire Elemental with an element it is weak against. Victory! Interesting item synergies achieved! Order is important – if we convert all the Fire damage to Ice damage first, then the environmental Fire damage boost is useless. A well defined order of filters is still being thought out.


Example:
Attack the Fire Elemental with our Fire Sword
RolledDamage object shows 100 Fire damage and 20 Physical Damage
Apply the Environment Filter
RolledDamage is now 150 Fire Damage and 20 Physical Damage
Apply the Ring's Filter
RolledDamage is now 0 Fire Damage, 20 Physical Damage, and 105 Ice Damage

So – how do we implement Damage Filters? We need to take the rolled result and in order, apply each filter to it to get the final result. Again, order is important. If we treat the damage roll as a vector, we can use linear algebra to solve this ultra simply, and using Apple’s Accelerate Framework, efficiently. Each filter is a linear transformation that acts on the damage vector – and a very simple representation of a linear transformation is…. a matrix! Once we get our list of filters they can be multiplied in order, and the resulting matrix combines all the filters in one structure. Then we multiply the damage vector and that final matrix and get a new damage vector that is our final result.

Let’s take a look at the matrix representation:

The identity matrix returns the exact same values when multiplied by the vector:
 | 1.0 0.0 0.0 | | Physical |   | 1.0 * Physical  |
 | 0.0 1.0 0.0 | |   Fire   | = |   1.0 * Fire    |
 | 0.0 0.0 1.0 | |   Ice    |   |   1.0 * Ice     |

Each row of the matrix represents the result of an element.
Each column is how one element will affect all other elements.

Example:
Convert all physical damage to ice and increase by 50%
 | 0.0 0.0 0.0 | | Physical |   |      0.0 * Physical        |
 | 0.0 1.0 0.0 | |   Fire   | = |         1.0 * Fire         |
 | 1.5 0.0 1.0 | |   Ice    |   | 1.5 * Physical + 1.0 * Ice |

Notice the first row is all zeros, this results in a zero value for physical.
The 1.5 is in the first column which is the Physical Source column, being in the last row means it will affect the last element, Ice.

In order to create a filter I devised a serialized form consisting of an XML Element for each operation that changes the filter matrix from the identity matrix.

If you look at the example above, “Convert all physical damage to ice and increase by 50%”, we can break this down to two steps. First, the result has to have physical reduced to zero and second, the result has to have 1.5 times the original physical added to ice. We can represent that using this XML:

<damage-filter>
   <!-- Convert all physical damage to ice and increase by 50% -->
   <set source="physical" target="physical" value="0.0"/>
   <set source="physical" target="ice" value="1.5"/>
</damage-filter>

Another example that requires 3 operations is “Convert all physical damage to 50% Poison and 65% Ice.” Let’s look at the XML representation:

<damage-filter>
   <!-- Convert all physical damage to 50% Poison and 65% Ice -->
   <set source="physical" target="physical" value="0.0"/>
   <set source="physical" target="poison" value="0.5"/>
   <set source="physical" target="ice" value="0.65"/>
</damage-filter>

The DamageFilter object is initialized by this block of XML which will first load the identity matrix as it’s model, then run each operation.

The RolledDamage object has a method that will take an array of filters and return a new RolledDamage representing the filtered damage.

Here is a unit test to confirm everything is working:

// Rolled Damage 1 (Physical: 50.0, Poison: 10.0)
SKElementValues values1;
memset(&values1, 0, sizeof(values1));
values1.elementValue[SKElementTypePhysical] = 50.0;
values1.elementValue[SKElementTypePoison] = 10.0;
_rolledDamage1 = [[SKRolledDamage alloc] initWithDamages: values1];



// Given:	Rolled Damage with (Physical: 50.0, Poison: 10.0)
// When:	Filter of "Convert 50% of physical and double to Fire"
// Then:	Final Damage is Physical: 25.0 Fire: 50.0, Poison: 10.0
NSString *filterString = @"<damage-filter>"
@"<set source=\"physical\" target=\"fire\" value=\"1.0\"/>"		// All of physical goes to Fire
@"<set source=\"physical\" target=\"physical\" value=\"0.5\"/>"	// Reduce physical by 50%
@"</damage-filter>";
PSXMLDocument *doc = [[PSXMLDocument alloc] initWithXMLString: filterString enableXPath: NO];
SKDamageFilter *filter = [[SKDamageFilter alloc] initWithXML: [doc root]];
[doc release];
SKRolledDamage *finalDamage = [_rolledDamage1 filterWith: @[ filter ]];
XCTAssertEqualWithAccuracy([finalDamage damageForType: SKElementTypePhysical], 25.0, 0.01);
XCTAssertEqualWithAccuracy([finalDamage damageForType: SKElementTypeFire], 50.0, 0.01);
XCTAssertEqualWithAccuracy([finalDamage damageForType: SKElementTypePoison], 10.0, 0.01);
XCTAssertEqualWithAccuracy([finalDamage damageForType: SKElementTypeIce], 0.0, 0.01);
XCTAssertEqualWithAccuracy([finalDamage damageForType: SKElementTypeHoly], 0.0, 0.01);
XCTAssertEqualWithAccuracy([finalDamage damageForType: SKElementTypeElec], 0.0, 0.01);

The key line being:

SKRolledDamage *finalDamage = [_rolledDamage1 filterWith: @[ filter ]];

That’s how easy it is to use! Now how difficult was it to implement?

Here is the code to RolledDamage – filterWith:

-(SKRolledDamage*)filterWith:(NSArray*)filters {
	if([filters count] == 0) {
		// No filters then just return the same object
		return self;
	}
	
	const SKElementMatrix *a = [(SKDamageFilter*)[filters objectAtIndex: 0] matrix];
	for(NSInteger i = 1; i < [filters count]; ++i) {
		// If there is more than one filter, continue to multiply them together until we get the final matrix.
		SKElementMatrix res;
		SKDamageFilter *filter = [filters objectAtIndex: i];
		const SKElementMatrix *b = [filter matrix];
		vDSP_mmulD(b->matrix, 1, a->matrix, 1, res.matrix, 1, SKElementTypeCount, SKElementTypeCount, SKElementTypeCount);
		vDSP_mmovD(res.matrix, tmp.matrix, SKElementTypeCount, SKElementTypeCount, SKElementTypeCount, SKElementTypeCount);
		a = &tmp;
	}
	
	SKElementValues vals;
	// Multiply the final matrix by our original damage vector and return a new immutable object representing the filtered results.
	vDSP_mmulD(a->matrix, 1, _damages.elementValue, 1, vals.elementValue, 1, SKElementTypeCount, 1, SKElementTypeCount);

	
	return [[[SKRolledDamage alloc] initWithDamages: vals] autorelease];
}

If there is no filter, just return the exact same value. If there is only one filter, multiply the filter matrix and the damage vector, which results in the result vector – return a new object based on the result vector. If there are multiple filters, multiply them together to create the final filter, then multiply by the damage vector.

Jornica Lore

I’ve been getting nonstop requests for more information on Jornica Lore!  Fear not, over the next few weeks I’ll be doing a series of blog posts on history, languages, geography, and other topics relating to the land known as Jornica.  Stay tuned!

Lonely Dwarves Development Journal – 3/2/2014

March! We’re finally approaching Spring. Thinking about our calendar reminds me that dwarves have their own calendar. And whole world for that matter. Astronomy in the world of Jornica is simplified from that in our world. There are two moons, months and seasons relate to their orbits (synodic orbits I suppose for simplicity, I’m sure at some point I’ll take an astronomy course for lulz and then be furious at myself for this blog post). So Moon A’s synodic month is a Jornica Calendar month and Moon B’s synodic month is a Jornica season. Solar orbit is 360 days exactly, Moon A’s synodic month is 30 days and Moon B’s synodic month is 90 days exactly.

These concepts are culturally global – except for names of things.

“That’s awful, use some imagination!”

“This is what it is. Because reasons.”

Names of these moons are obviously in flux right now. The dwarves have different names for them than other beings. I’ve been considering how to procedurally generate languages for the Dwarves and assorted other races and have some ideas but nothing on paper. I have a great deal of respect for what Tolkien was able to do with the languages of Middle Earth and while those types of ideas would be interesting to explore, it’s way outside of the current scope of creating Jornica and I would also like to try out something new, at least to me. Defining a bunch of rules and probabilities and letting a program create a language from permutations and stochastic processes is interesting.

“What about the game?”

Oh I’m sorry, were you here to learn about this week’s actual Lonely Dwarves progress?

I finally added a sort of “Locked Door” concept to add to maps. Basically a block that acts a barrier unless the player has a way to get past. This can be anything you can get to through my scripting language, obvious things are an item in the inventory (like a key?!) or a global property that basically represents the same thing… but could be something like “has and consumes 50 gold!”, or “Level > 20” or whatever.

I also have been coding and enhancing magic spells and effects. Some of the cleric spells were implemented and should be working pretty well.

THIS WEEK: More spells. I really want at least the player character’s spells to be functional, if not balanced.

Lonely Dwarves Development Journal – 2/17/2014

This was a tough week for development due to sick babby occupying most of my time. It was a content creation week rather than a code writing week. New monsters were designed, Lore is being written, etc. I made some updates to my map editor software to support some of the features and started mapping out the caverns and doing some preliminary work on the Gnome Village.

I thought the soundtrack was complete previously but I was upset that the Gnome Village didn’t get it’s own theme song so I wrote one! I think the style of this song goes well with the personality of a gnome, I hope you agree. It ends abruptly because it’s meant to be looped…

Gnome Village Theme Song Preview:

      Gnomes

If the player doesn’t work your browser can probably play the file if you put this in the address bar:

      Gnomes

Lonely Dwarves Development Journal – 1/5/2014

Hi Dwarfers!  Happy New Year!  On this New Year’s week we made a lot of dwarf progress towards a 2014 release.  I just put the finishing touches on the Boss Theme.  I could probably spend a week touching it up, but progress must continue on the rest of The Lonely Dwarves.  With the new Boss Theme, the sound track is complete.  There are 10 songs that will play throughout the game.  I am considering extending the tracks and releasing a Soundtrack.  If anyone is interested tweet to “@spazcosoft”!

As for Coding – this week I did a lot of project refactor.  The project has grown quite a bit and honestly exceeds the amount of code I expected to write.  I’m trying to extend my Unit Test coverage and do some Test Driven Development.  Quality is very important here at Spazcosoft and TDD is a great way to prove that many of the formulas and algorithms are working correctly.

A while back I made a design decision and code change:  Your characters have both individual inventory and a “gear bag”.  The individual inventory is limited in size so the player will have to choose what and how many items to take on a particular expedition.  Surviving the journey is more important than winning a single battle.  I didn’t want to limit the gear options players had by making gear fill up useful item slots so anything that can be worn is stored separately and unlimitedly. Well this added complexity to many in game system and as of yesterday Stores were still broken, crashing the game if you tried to sell an item.  Store are now working with no known crashes.  Buy and Sell all you want!  The UI needs some aesthetic work, but I’m saving that for after I’m satisfied with the gameplay, balance, and stability.

I implemented an expression language that allows the effectiveness of many in game systems to be defined (for example, amount of damage that a weapon does).  I just applied that to weapons today and tested it out in the basic case.  This allows me to have some fairly complex item definitions without a ton of code or mess of config files.  As a gameplay idea we’ll have an Axe that does some bonus lightning damage based on the wielder’s intelligence.  The extra damage is significantly affected by the intelligence score so it opens up a gameplay question: Do I give an int boosting item to the berserker or the wizard?  What other item combinations are available?  I’m hoping to offer interesting gameplay choices and complex item interactions that make the game more interesting than a typical grind-fest.  Another option is for bonuses to max out – a lower tier sword might stop giving a larger damage bonus at Strength 20 for example, making it that more attractive to use a better sword as your character improves.

Interactions are defined by an original scripting language that I’m not particularly proud of, but it gets the job done.  I made enhancements to allow variable substitutions and some new conditional logic.  What this means for gameplay right now is that when you stay at the inn not only will the innkeeper tell you how much it is to stay there, but also deny you a room if you lack funds, and actually take your money when you do stay.  Due to wrapping all of these around new scripting language features, it amazes me how long it took to get that up and running at production quality.

This coming week looks like continuing down this path of defining and balancing weapons.  There are several effects that need to get working as well.  Hopefully I’ll have some tests up that can prove the correctness of these in game systems.  Each player found bug is a failure on my part!

Lonely Dwarves 2014 Goals

Hi Dwarfers!  I started to write what is now known as The Lonely Dwarves in 2008, right when Apple released the iOS SDK.  “How cool would it be to write the first RPG on the iPhone?” I thought.  I think I missed that goal…  The amount of time that has gone by is equivalent to a console generation and the iPhone of today barely resembles the original.  I’ve thrown out a lot of code because it became irrelevant as time progressed.  This has also been a hobby rather than a full-time job, which has slowed me down considerably.

Given that, I believe I have a game in mind that I can release this year, that will provide 10-15 hours of fun (and require 30-40 hours to complete) (Just Kidding!) and will be interesting to veteran gamers as well as novices.  2014 will be the SHIP IT year!

Every Sunday I will post a “This Week’s Progress” style blog entry.  It may contain spoilers (if you care about that sort of thing), but I will avoid any major story spoilers.

I also launched our official Twitter late last month – you can follow us at @Spazcosoft.  I will stick to topic and post about our games and development.  I also have a personal twitter @KirkSpaziani if you’d like to see pictures of my lunch, the baby, and hear me whine about things.

I am also going to make an effort to post more programming related blog entries but we’ll see how much success I have given everything else I’m trying to accomplish.

Happy 2014!!!

Magic Potions!

Potions

Here are some magic potions I just added.  The item engine I wrote allows for having several “item components” that can be combined to show your final item image.  In the case of the potions, the bottle, liquid, bubbles, and cork are all different components.  When each component is added to the image, there are several filtering options.  The liquid has a red filter applied for example.  This makes it easy to create different items from the same group of graphics.  You can substitute different components, one example might be a liquid with a cool pattern or a different cork.  That particular feature shines a bit more with weapons.

Axes

Take a look at these axes for example:

The hilt is the same in each axe, but they have different color filters applied.  There are two different axe blades that are separate components and the second axe gives off a glow, which is also a component with a color filter.