Wesnoth Evolution: 0.1

The Battle for Wesnoth has been around for some years already and its ever increasing content and artwork quality has attracted many code developers, sprite and portrait artists and musicians over time. I started playing Wesnoth on version 0.9.6 which was distributed with the SUSE Linux 10.0 operating system; I later switched to version 1.0.2 and closely followed the 1.1 release cycle.

Now that version 1.8 has been released and approx. 7 years have passed since the very first release, I felt curiosity to see exactly what has changed and what hasn't changed since the very first Wesnoth version published by David White (a.k.a. Sirp) that isn't even available in the downloads page at SourceForge.net. Yep, that's right, this is a review of Wesnoth 0.1 against current versions of Wesnoth such as 1.8 and 1.6, or even intermediate modern versions such as 1.0.

For historical reference I'm using both an actual Wesnoth 0.1 build for Windows I prepared using the Mingw32 cross-compiler environment for Linux (running on WINE), and the Battle for Wesnoth Project's SVN trunk changelog, which starts at version 0.2.1. The project's combined CVS-SVN history, on the other hand, starts on September 15th 2003, 15 days before the first CVS release tag, version 0.4.8. The first version announced since the beginning of the Wesnoth forums (which predate Wesnoth.org itself) is 0.3.7.

Scenario 1: The Outbreak of War

In the eighteenth year of Haldal, king of Wesnoth, Kiath-Nora, empress of the East has mobilized her forces for war against the peace-loving people of Wesnoth.

Konrad, a young elvish officer is keen to prove his skills and loyalty in the conflict, but he has yet to earn the trust of his superiors. His first assignment is to secure the isle of Yasmin from the Orcs.

Kiath-Nora has dispatched Usadar Q'kai, one of her finest Orcish captains, to wrest control of the isle from the elves.

You have seven days to gain control of the island and kill Usadar Q'kai.

Those readers who have played modern (0.9.x - 1.8.0) Wesnoth will immediately recognize Konrad's name from the mainline Heir to the Throne campaign...but what is this? He's an elf? And he fights for “the peace-loving people of Wesnoth”?

As you can see, this plot bears absolutely no resemblance to the first mainline campaign in current Wesnoth. But enough of this chatter — let's take a look at the actual game once and for all, shall we?

Wesnoth 0.1 main screen

In case you can't tell — since the hex map looks like a wreck — that huge sprite is Konrad, and you can take a look at his stats in the sidebar in case you are still doubtful. He is sitting on some castle tiles surrounded by villages (that vaguely look like Middle-East buildings) and he is surrounded by, hm, forest (mostly plain-green-looking tiles) and grassland (green tiles with black and light green noise on them). Those strange golden tiles are “desert” tiles, and the aquamarine tiles are “coast” tiles (known as Shallow Water since version 0.4). You can't see them here, but there are some dark-blue “ocean” (Deep Water) tiles surrounding the isle and those pretty “coast” tiles. So yeah.

Don't look at me like that. I am not making any of this up! Furthermore, this map still exists in Wesnoth 1.0 to 1.8 in the aforementioned Heir to the Throne campaign!

Wesnoth 1.8 HttT Isle of Alduin

From Wesnoth 0.1 scenario 1, the map, and the player character and the enemy orc's names survive in Heir to the Throne scenario 3, “Isle of Alduin” (known as “Isle of Anduin” before version 1.3.7). But let's make a pause now to analyze a few immediately obvious technical differences seen here.

0.1, 1.0 and 1.8 sprites comparison
Orcish Warrior, from left to right: version 0.1, 1.0 and 1.8.
Villages in Wesnoth 0.1
  • Unlike Wesnoth 0.6.99.1 and later (0.4.6 introduced PNG support but didn't still use alpha channels), this version uses 70x70 px images in the Windows Bitmap format instead of 72x72 px PNG files for sprites, terrains and such. As BMP images, these sprites had no alpha channel and the game used pure black #000000 as a transparency key. Team Color was not going to be implemented until Wesnoth 1.1.x.
  • Terrain tiles are 256x256 px BMP files instead of being the same size as sprites. They are apparently masked and rescaled to 100x100 px hexagons at runtime in 0.1.
  • The sprites' image files look like they were originally intended to be smaller but Dave later settled for the 70x70 px scale. Their blurriness is most likely a rescaling artifact.
  • Village ownership is indicated by different village icons with recolored roofs and a faint colored ellipse. The latter remind me of the team ellipses seen in later versions, apparently introduced in 0.7.2.
  • The minimap already works but it isn't possible to click on it to scroll to a particular location. It won't display units either.
  • The little icons on top of the HP bars indicating whether a unit has moves left or not are already implemented, but they are also displayed for enemy units during the human player's turn.
  • It is worth noting that it was already possible to zoom the map in and out in this version using the z and x keys.
  • Unit facing indicated which side a unit belonged to. In this case, units facing southwest are the human player's units, and those who face northeast are AI-controlled units (orcs). This is such a subtle feature that I didn't realize facing signified anything until Dave pointed it out after reading this review.

Interestingly, in this first version the gameplay mechanics are already pretty much “carved into stone” and there are not too many differences to the rest of the 0.x line and current stable and development versions. Unit stats are generally not the same as 1.0 or 1.8, of course — but there a few things that have never changed since then, such as the Elvish Archer and Fighter's max movement points.

Castles do not have distinct keeps, and the player can recruit units on vacant castle tiles as long as they are adjacent to the leader, regardless of what kind of tile the leader is standing on. This seems to have been replaced with the current mechanism just in Wesnoth 0.4.4, although the changelog for that version suggests that the actual keep graphics did not exist yet. Additionally, in 0.1 you can't yet choose in which castle tile your new recruit should be spawned.

Attacking in Wesnoth 0.1

The user interface in general is pretty crude, and there are no keyboard shortcuts other than Escape to quit the game, so the player must trigger actions from a little context menu that's not very mouse-friendly. At the start of every turn, the game map scrolls to the teams' starting locations, rather than their leaders' current locations.

There are no unit animations whatsoever, except for the (irritatingly slow) static unit move animations done by the engine. As a result, attack outcome is displayed on a modal dialog box instead. Zones of Control already work, and all units are at least level 1. Surprisingly, the no-ZoC convention for level 0 units is relatively new: level 0 units used to have a Zone of Control until version 0.8.9. Version 1.1.2 is the first version to allow defining whether a unit has a ZoC or not in unit type declarations using WML.

In this version, the enemy team's artificial intelligence is already pretty damn challenging and there's a good reason for this: Dave started Wesnoth with the intention of making a game with simple rules that could be played well by an AI. We could say that the plot transcribed above is simply an Excuse Plot and that this could as well have been a game about anthropomorphic bananas fighting purple dinosaurs in a land made of candy (just kidding!).

Gold is not carried over scenarios at all. Instead, after finishing a scenario you start the next one with the default amount of gold (100). Recalling units is supposed to be possible, or at least the gameplay context menu suggests so — I got to scenario 2 after, ahem, hacking my way through Isle of Alduin scenario 1 along with a horseman, an archer and a fighter, but I couldn't recall any of them later. The game seems to have forgotten about them, since it says that “there are no troops available to recall”. Good that I didn't waste my time playing fair, since scenario 1 is tedious enough with these slow movement animations, awkward attack outcome displays and ridiculously smart AI ridiculously dumb human at the keyboard. While we are at it, notice that Wesnoth was just elves vs. orcs in the beginning. In Wesnoth 1.6 and earlier, it always felt like the AI was much better at throwing orcs at elvish player units than anything else. Coincidence? I don't think so. 😉

(UPDATE: recalling units is possible according to Dave and Velensk, except that they must be at least level 2 for that.)

There's a second scenario included with Wesnoth 0.1, and it is titled “The Three Rivers”:

Scenario 2: The Three Rivers

After securing Yasmin from the orcs, Konrad is assigned a more important task. The Three Rivers region is one of the most fertile in the land, and has long been a natural border between Wesnoth and the East. Konrad must wrest the land from the hand of his enemies.

You have seven days to gain control of the region, and kill Hal'am Bel'ard.

Three Rivers' minimap

This map has Konrad fighting against another Orcish Warrior in the land between... three rivers. He starts at a castle in the NE corner while the orcish leader is in the SW.

“Three Rivers” is nowhere to be found in modern versions of Wesnoth, although it appeared for the last time in 0.9.1 as a multiplayer map, albeit missing the scenario WML required to make it playable.

Now that I think of it, the objectives display mentions “days”, not turns. What does this mean? A day in Wesnoth 0.1 is a turn sequence consisting of dawn, day, dusk, night; that is, 4 turns. Nowadays we have 6 turns in the default outdoors ToD schedule used in mainline scenarios (other than UtBS): dawn, morning, afternoon, dusk, first watch and second watch. The current convention was introduced in Wesnoth 0.4.3 due to the suggestions in this thread, and the time of day definitions weren't converted to WML and macroified until past Wesnoth 0.4.8 in CVS (SVN revision 129) for Wesnoth 0.5, which is coincidentally the first version in which wood elves are neutral rather than lawful — and also the first version that includes my favorite unit, the Elvish Shyde! 😛

Extra minimap

This version shipped with a third map, much smaller than the rest, which did not include any WML in game.cfg to make it available for regular gameplay. The extra map was tied to the first scenario in Wesnoth 0.2, most likely to ease debugging of the engine (the Isle of Alduin Yasmin is huge).

In version 0.1, WML (the language used for defining units, scenarios, etc.) resembles XML even less than it does nowadays. Both the parser and the input are much simpler than the monsters they've become with every development release cycle. Here's a 0.1 WML snippet which defines Konrad's unit type:

[unit]
name=Elvish Commander
image=elven-commander.bmp
hitpoints=45
movement_type=woodland
movement=5
experience=38
level=1
alignment=lawful
advanceto=Elvish Swordmaster
cost=17
usage=mixed fighter
[attack]
name=sword
type=blade
range=short
damage=6
number=4
[end]
[attack]
name=bow
type=pierce
range=long
damage=3
number=3
[end]
[end]

The most glaring difference is the [end] tag, which was the only mechanism before Wesnoth 0.4.2 for telling the parser where a config node ended. According to the changelogs, version 0.4.4 was the first version that didn't use [end] in config files generated by the game.

Note that unit type definitions were always put in [unit] tags until these were renamed to [unit_type] in 1.5.0 to avoid confusion with single unit WML definitions in scenarios. For an older syntax change, however, consider that attack range specifications used to be only “short” and “long” until the development version 1.1.1, which also allows definition of arbitrary attack ranges — retaliation will use any attack of the same range.

Also note that the WML indentation format displayed above — which is different to what is nowadays enforced in mainline and Wesnoth-UMC-Dev by ESR's wmlindent tool — appears to be Dave's preferred style for markup, and it can be found in modern code in Frogatto.

A few unit movetypes already existed back then and the stats are not the same as in current versions, but there's an interesting syntax difference:

[units]
[movetype]
name=smallfoot
[movement costs]
ocean=100
coast=3
grassland=1
desert=2
forest=2
hills=3
mountains=100
village=1
castle=1
[end]
[defense]
ocean=0.8
coast=0.7
grassland=0.6
desert=0.7
forest=0.5
hills=0.5
mountains=0.4
village=0.4
castle=0.4
[end]
[resistance]
blade=1.0
pierce=1.0
impact=1.0
fire=1.0
cold=1.0
[end]
[end]
[...]
[end]

Unit resistances and defenses were specified as floating-point numbers instead of integers. This was replaced with the current system in version 0.5.1+CVS (SVN revision 424) for Wesnoth 0.6, adding to several other major changes including “engine support for weapons that can reach multiple hexes”...take that as you will.

Unit races defined which unit types could be recruited by teams in this version. Besides that, unit, unit type and movetype definitions don't have anything that later versions don't. However, they don't mention the arcane damage type (known as “holy” before 1.3.2) for some reason. On the other hand, the Paladin unit already existed and dealt 9-5 short range blade damage with a sword — in 1.0 and 1.8 he deals 8-5 short range holy/arcane damage. Dave confirms that the “holy” damage type wasn't introduced until Francisco Muñoz introduced undead units in a later version.

As I mentioned above, the parser is much simpler than the one Wesnoth 0.9.0 and later use, first introduced in CVS/SVN revision 6269, March 27th 2005. Compare 165 lines in one file using fairly simple C++, to 5343 lines scattered across 16 files (Wesnoth 1.9.0+svn, but this never changes much) that use more advanced programming techniques.

One of the oldest components of the game is the main source code file game.cpp itself. While it had approximately 440 lines of code in Wesnoth 0.1, by version 1.4.0 it exceeded 2300 lines of unmanageable crap that suokko and I tried to move elsewhere during the 1.5.x development cycle, with varying results and consequences. 0.1 included part of the game and UI logic on it. However, this isn't the only code file that's existed since the Stone Age. video.cpp/video.hpp and the CVideo class are also present in version as early as 0.1 and they are even used in current SVN versions. CVideo is a low-level interface for SDL used for display output management, and presently (1.9.0+svn r42061) has the higher-level help strings feature (text displayed at the bottom of the screen on mouse-over for some GUI elements) mixed into it for some reason.

There was no audio support at all in 0.1, or sound effects to justify its implementation. In fact, audio support wasn't introduced until version 0.4.1, which shipped with a first music track from ZhayTee and sample sound effects for the elvish fighters' attacks.

A listing of this mysterious Wesnoth 0.1 package reveals that it was packaged on June 18th 2003, at 08:37 AM, just about 3 months before the CVS repository was started and what later became Wesnoth 0.4.8 checked into it. But there's something else in this distribution that caught my attention:

shadowm@bluecore:~$ tar --utc -tzvf src/wesnoth-0.1.tar.gz
drwxrwxr-x david/david 0 2003-06-18 08:37 wesnoth-0.1/
[...]
-rw-r--r-- david/david 112640 2003-06-18 08:37 wesnoth-0.1/strategy-source.tar
[...]

The file listing in strategy-source.tar indicates that it is an earlier distribution of source code that might predate Wesnoth 0.1, or possibly even the “Wesnoth” name itself:

shadowm@bluecore:~/src/wesnoth-0.1$ tar --utc -tvf strategy-source.tar
-rw-r--r-- Dave/None 5227 2003-06-14 03:25 actions.cpp
-rw-r--r-- Dave/None 9392 2003-06-14 09:43 ai.cpp
-rw-r--r-- Dave/None 3040 2003-06-14 03:25 config.cpp
-rw-r--r-- Dave/None 21197 2003-06-14 10:03 display.cpp
-rw-r--r-- Dave/None 9553 2003-06-14 09:22 game.cpp
-rw-r--r-- Dave/None 1031 2003-06-14 03:25 gamestatus.cpp
-rw-r--r-- Dave/None 666 2003-06-14 03:25 key.cpp
-rw-r--r-- Dave/None 2422 2003-06-14 03:25 map.cpp
-rw-r--r-- Dave/None 1812 2003-06-14 03:25 menu.cpp
-rw-r--r-- Dave/None 4224 2003-06-14 03:25 pathfind.cpp
-rw-r--r-- Dave/None 998 2003-06-14 03:25 team.cpp
-rw-r--r-- Dave/None 2110 2003-06-14 03:25 unit.cpp
-rw-r--r-- Dave/None 4421 2003-06-14 03:25 unit_types.cpp
-rw-r--r-- Dave/None 6011 2003-06-14 03:25 video.cpp
-rw-r--r-- Dave/None 734 2003-06-14 03:25 actions.hpp
-rw-r--r-- Dave/None 387 2003-06-14 03:25 ai.hpp
-rw-r--r-- Dave/None 438 2003-06-14 03:25 config.hpp
-rw-r--r-- Dave/None 2273 2003-06-14 03:58 display.hpp
-rw-r--r-- Dave/None 503 2003-06-14 03:25 gamestatus.hpp
-rw-r--r-- Dave/None 1736 2003-06-14 03:25 key.hpp
-rw-r--r-- Dave/None 862 2003-06-14 03:25 log.hpp
-rw-r--r-- Dave/None 1398 2003-06-14 03:25 map.hpp
-rw-r--r-- Dave/None 313 2003-06-14 03:25 menu.hpp
-rw-r--r-- Dave/None 571 2003-06-14 03:25 pathfind.hpp
-rw-r--r-- Dave/None 711 2003-06-14 03:25 team.hpp
-rw-r--r-- Dave/None 852 2003-06-14 03:25 unit.hpp
-rw-r--r-- Dave/None 1798 2003-06-14 03:25 unit_types.hpp
-rw-r--r-- Dave/None 1297 2003-06-14 03:25 video.hpp

Notice that unlike Wesnoth 0.1, not all of these files have the same timestamps — they might have been packaged directly from a working directory, whereas Wesnoth 0.1's timestamps are probably the result of a regular file copy. It's very likely that codename “strategy” wasn't even packaged in the same machine, judging by at the user and group information in the directory. Additionally, a quick MD5 sums comparison reveals that the files in both directories do differ in content, but I don't think I'm going to try to compile codename “strategy” right now. 🙂

Actually, a conversation I just had with Dave would confirm my theory. According to Dave, he only thought of the name “Wesnoth” just before releasing the game around the time the tarball was produced. Please note that the etymology mentioned in the 1.0-* mainline campaign The Rise of Wesnoth is an more recent in-story explanation for a name that did not have an actual meaning in the beginning of the project's history.

Wesnoth 0.1 is very, very different to 1.0 and later versions, yet many basic features have been kept unchanged throughout time. The artwork quality has improved a lot since 0.1, which really just lacked a dedicated artist to produce art for the game — as a result, all of the sprites and terrain graphics in 0.1 are placeholders.

According to Dave (EDIT: in this interview), the game was built in two weekends, and after he started getting regular contributions, new versions were published every week, or sometimes even more rapidly than that. That's a very impressive work if you'd ask me.

I'll soon (for certain values of “soon”) document the evolution to Wesnoth 0.2, in which Francisco Muñoz's artwork first appears and forests become masses of trees rather than plain-looking green patches.