# The &kappname; Handbook

## Introduction

&kappname; is just a silly little game. It's based on what I remember of the Spacetaxi-game on the C64. The objective is to pick up passengers waiting on a number of platforms and to drop them where they want to go. That's basically it. Please report any problems or feature requests to the author.

## The &kappname; Story

It is the year 4017 A.D. - or rather, that's the official date, but after that terrible desaster at the temporal power plant in New New Atlantis, which still serves as a popular excuse for being late on any occasion, nobody is quite sure about that anymore. However in the year 3999, scientists agreed that the year 3999 could not be off by more than some 787.3 years in the past or 543.7 in the future with a confidence of some 94% and hence took the temporal statistical mean. Since hardly anybody has too positive memories of temporal statistics in school, that settled it for the great majority of people, even some (assumed) two centuries after the desaster experiencing enough troubles in measuring medium time-intervals to be seriously worried about the exact year.

So - it's the year 4017 A.D. and for people in our time trying to understand 41st century mentality is somewhat comparable to stone age man trying to make sense of a commercial for internet banking. This might for us be a good enough explanation, why in a time when nobody can even remember who invented teleportation there exists such an utterly useless job as a taxi-pilot.

It is noteworthy though, that even under those 41st century people that ever came to think about this, there exist at least a few thousand completely different explanations for this fact, none of which being accepted by more than a handful of people. Most people do however agree, that this must have to do something with the taxi-pilots having done something very, very bad in a past or future life to deserve such a pitiful fate (this particular view is of course only held by those believing in some flavor of reincarnation, but the general direction of thought is widely shared).

To pick out just one of the especially absurd views: While it is once again becoming more and more en vogue on the segwitch-parties of the would-be-intellectual to claim that the world is really just the thing that we see, and we can - among the dozens of virtual realities - positely and correctly perceive one as the real one, there is a few people still insisting that the whole world is just a big computer simulation and so are all live-forms in it.

When the founder of this school of thought, her name now no longer being named, one day proposed, that actually, there might be a world outside the simulating computer, with some people actually steering the simulation - and yes, even taking the role of a taxi-pilot - just for fun ... ... well, anyway, her name is no longer being named.

## Using Taxipilot

&kappname; is a game, and really you shouldn't be reading the instructions, but simply play. But then, here is a short description of how to play. At some points this description is rather vague, saying "may or may not" and the like. This is due to the fact, that much of &kappname;'s behavior is configurable.

The arrow-keys (or whichever keys you chose in the Settings) allow you to accelerate into any direction. Most levels will also have gravity, that will generally pull you downwards. You may however also be pulled to or pushed away from certain points in many ways, few of which have to do anything with real-life physics.

Some taxis have fixed landing-flaps, while other taxis can draw in and out their landing-flaps. Obviously you can not land without your landing-flaps fully lowered. But then, some taxis are not able to accelerate left or right with the landing-flaps out. The default key to toggle the landing-flaps is currently 'F'. It is inactive for taxis with fixed flaps.

Passengers will appear from time to time. Land on the platform they wait on and wait unitl they have boarded the ship. The "Destination:"-display on the bottom of the window will tell you, where the passenger wants to go. While the passenger is waiting to be delivered, you will see the "Tip"-display counting down. This is how much the passenger will give you in addition to the regular fare. If the tip is negative, the passenger will not even pay the entire regular fare. But you will never be paid less than nothing for your services.

Passengers differ both in the amount of tip they will maximally give to you and in their impatience. The tip will count down faster for very impatient passengers.

The regular fare consists of a fixed base amount, which may differ from level to level and an amount that increases every time you accelerate. Therefore the fare is fairly based on your fuel consumption for the trip. In order to make money, you should be fast however and earn some tips.

Watch your fuel! When it's empty, you will no longer be able to accelerate. Most likely this means that you will crash very soon. You may fuel your ship on special platforms, which will generally, but not necessarily be platforms where no passengers ever appear or want to go to. Fuel does have a price, though, you can't refuel without money.

Some levels will have teleporters in them. Teleporters may take you to any other teleporter or nowhere at all. Teleporters need not work both ways and not the same way. Some teleporters may cost money. You can only use them, if you have enough funds.

In order to complete a level you have to do a number of "successful" deliveries, i.e. deliveries that you do get a non-negative tip for. So this is another reason to hurry. The number of "successful" deliveries required may differ from level to level. Upon completion of some levels, you will be awarded an extra ship (life).

### More &kappname; features

Currently &kappname; contains only three levels, two of which look strangely similar. Also there are only two passengers, one of which can't really walk. &kappname; is highly configurable, though, without having to recompile. See the developers sections for details on writing your own levels.

## Command Reference

### The main &kappname; window

#### The Game Menu

Ctrl n Game New

- Starts a new game

Ctrl w File Stop

- Aborts the current game

File Pause

- Pauses the game, without leaving it

Ctrl q File Quit

- Quits &kappname;

#### The Settings Menu

Settings Select Mission

- Lets you select a mission description file

Settings Configure Key Bindings

- Lets you change the key bindings

Settings Configure Taxipilot

- Here you can specify a few options concerning the startup-behavior, where to look for your missions (useful if you design your own missions) and tune the refresh-rate, in order to make Taxipilot run as good as possible on your hardware.

## Enhancing &kappname;

&kappname; is still very limited. It only consists of three levels and about one and a half passengers - not to mention that graphics rather suck. However, &kappname; allows you to configure a whole lot of things without having to dig through the code and recompile. This chapter describes the four types of XML-based configuration-files that currently exist, explaining what you can configure already and what still is to come.

As more and more features have been added and will continue to be added over time, this documentation, too, is growing more and more complex. I try to explain all the possibilities, but chances are you will never need all of those at once. Therefore, don't get frustrated with this lengthy description - probably you can get a good start by looking at the configuration-files provided with the distribution and later check back in the documentation to find out what possibilities there are and what exactly one attribute or the other does. Comments on how to make this documentation more readable are always welcome.

Version 0.3.0 introduced some sanity-checks on the configuration-files you write. Image-files are checked for being existent and readable (but not for being in the correct format!), the parameters you can specify have been assigned upper and lower limits (for numeric attributes), that should be wide enough to allow everything that might make sense (please let me know, if they aren't) but hopefully catch a few mistakes. Default values will be assigned for missing or invalid parameters. These default values sometimes make sense, sometimes they probably don't - so look for debugging messages. Debugging messages are printed to stderr, using 5 levels:

    0: Error		These are critical errors that would cause &kappname; to crash.
    						&kappname; might exit on those errors.
    1: Serious Warning  	A default value was inserted that probably doesn't make a lot of sense
    2: Warning 		(default level) A default value was inserted that probably makes sense,
    						but you should still better fix this.
    3: Info			A default value was inserted where you are explicitly allowed to omit
    						parameters, or other harmless messages.
    4: Translations		A string was translated, a string could not be translated, a translations-file was not found...
    						may generate a LOT of output, that will generally only be useful for translators.

You may change the debug-level using the commandline option --debug-level (level) to change the verbosity. If your configuration does not work and you can't figure out the reason, try setting debug-level to 3. The default debug-level is 2, and I'd consider it good style for the configuration files, that no debug messages are generated at this level.

Before distributing a (large) mission, you may want to start Taxipilot with the --thorough_check -option, which will make it parse all configuration-files belonging to the mission thoroughly once the mission is selected. This should output any errors, without having to go through all the levels.

All files install to the subdir "taxipilot/game_data/" (config-files) or "taxipilot/game_data/images/" (images) of the KDE-Standard-data-directory (for me that's "/opt/kde2/share/apps/"). Whenever you put in a non-absoulte path in your configuration files, &kappname; will first try to find those files in (or rather relative to) the directory where the selected mission-configuration files resides (sub-dir images for image-files). If the files can't be found there, &kappname; will check in the above-named installation-directories.

What this means practically is, that you should state the file-names of your configuration-files as relative to the directory your mission-file (and as a matter of fact, I'd recommend placing them in the same directory). All image-files should be located in a subdirectory "images" of the directory of you mission-file. Do not specify the "images/"-path in your file-names. You might want to have a look at the configuration-files provided to see what I mean.

Now, if you want to use some configuration- or image-files of the distribution (e.g. you want to create an own level, but want to use the passengers and taxi provided), you specify those file-names relative to the installation-directories. Therefore, &kappname; will first check in your mission's directory and then fall back to the files provided with the distribution. What you can not do, however, is to have some files of one single animation in your mission-directory and some other files of the same animation in the installation-directory!

You may also use absolute paths in your configuration files. These will be left untouched, but I'd recommend to do so only for testing purposes.

Hopefully, things will get clearer, when you read on. Otherwise, please contact me.

Starting with version 0.3.0, you may use "true" and "false" instead of "yes" and "no" for all attributes taking yes/no-parameters. "yes" and "no" still work, though.

### Configuration of missions

A mission is a succession of levels, using a number of passengers and a particular taxi. To illustrate what I'm trying to say, you might define two missions, which differ in the sets of passenger-sprites they use (like one with aliens, one with normal human beings, one with your favorite cartoon-characters). More importantly, you can define which levels (see below) the player will have to go through and in which order, so you can easily reuse a level you or somebody else already created for a different mission. Furthermore you may specify a particular taxi, that will be used in the mission.

Let's have a walk through an example mission:

    <!DOCTYPE mission_data >
    <document author="Thomas Friedrichsmeier" title="Mission 1" startscreen="mission1_start_screen.png">

The "author" and "title"-attributes should be self-explanatory. The values in those attributes are shown in the credits on the start-screen (see below).

The startscreen-attribute specifies an image file that will be used as a sort of welcome screen to your mission. Note that if you omit this attribute, a default screen will be used. This is only to ensure backwards-compatibility, please do specify some kind of startscreen. Also make sure, you leave some blank space (preferrably some dark color) on the bottom of this picture, since this is, where the credits will be shown.

    	<initials ships="5" />

This simply specifies, how many ships the player will start out with.

    	<levels>
    		<data file="level1.level" />
    		<data file="level2.level" />
    		<data file="level3.level" />
    	</levels>

The levels-section simply lists all levels in the oder they are to be played. These are just plain filenames (see above) for the level-description-files explained below.

    	<passengers>
    		<data file="passenger1.passenger" on_start_screen="yes" start_screen_x="55" start_screen_y="420" />
    	</passengers>

The passenger-section is basically the same. Passengers will be selected at random, however.

The additional parameters specify whether the passenger will appear on the startscreen and - if so - where. If you omit those parameters, the passenger will not appear on the startscreen. The passenger will always show up in the credits, though.

    	<taxi file="taxi1.taxi" on_start_screen="yes" start_screen_x="55" start_screen_y="55" />

Not much to be explained on this one either. Note that this is different from the 0.3.x-versions. The taxi can now be animated and therefore has a configuration file of its own.

The "start_screen"-related attributes work the same way as for the passenger.

    </document>

### Configuration of passengers

Passengers are the creatures you have to transport around. They are easy to configure, but a lot of work to draw.

Let's look at the configuration:

    <!DOCTYPE passenger_data >
    <document author="Thomas Friedrichsmeier" title="Mr. Right" >

The "author"- and "title"-attributes will again be shown in the credits for the missions this passenger appears in.

    	<idle>
    		<data frames="4" file_pattern="passenger1_idle1_%1.png" repetitions="5" />
    		<data frames="4" file_pattern="passenger1_idle2_%1.png" repetitions="8" />
    	</idle>

Passengers may do different stuff while waiting on you to pick them up. Let's call these idle-animations. For each animation you have to specify the number of frames, it contains (make sure you really have all these frames, of &kappname; will abort with an error). The frames are stored in seperate files, that you have to name like this: your_file_name0000.png your_file_name_0001.png ... your_file_name[frames-1].png . For certain idle-animations (like waving) it makes sense to get repeated several times to form an "action". That's what the "repetitions"-paramter is used for.

You may define as many idle-animations as you like, but at least one. If you create more than one, the animation will be picked at random. Use frames="1" and a static image, if you don't want any idle animations. Likely a parameter sound="filename" will be implemented some day.

Additionally, all passenger-animations (including those described below) take a paramenter "anim_frame_period". So, for example

    		<data frames="4" file_pattern="passenger1_idle1_%1.png" repetitions="5" anim_frame_period="100" />

would make the specified animation run at half the default speed (50 msec per frame).

    	<walking speed="0.6" />

This specifies, how many pixels the passenger moves per advancement frame. Note that the time period for an advancement frame is different from that of the animation-frames, which you may configure. The advancement-frame-period is currently 50 msec (i.e. 20 fps) fixed divided by passenger impatience. This is admittedly rather awkward, and will hopefully be changed some day.

    	<walking_left frames="14" file_pattern="passenger1_walking%1.png" />
    	<walking_right frames="14" file_pattern="passenger1_walking%1.png" />

The format is basically the same as above. Obviously there is no repetions-parameter and you can only specify one animation for walking left and one for walking right.

    	<teleporting frames="10" file_pattern="passenger1_teleporting%1.png" />

Just like above, there is only one teleportation-animation. It will be reversed for reappearing.

    	<still frames="1" file_pattern="passenger1_still0000.png" />

I hardly need to explain the syntax. It's the animation (or in this case still image) you see, when the passenger is neither performing idle-actions, nor walking, nor teleporting. Warning: As of version 0.4.0, animations are not yet supported in this section. Only the first picture of the series you specify will ever be used, so for now, you'll probably want to save the drawing and put frames to "1".

    </document>

You may not omit any of these sections. You may always use frames="1" and a constant "file_pattern", in order to create a very simple passenger, however.

### Configuration of the taxi

The taxi is the central sprite on the screen. It is - so to speak - you, the player. The reason I'm introducing it's configuration after that of the passenger is, that it's rather similar.

An here it is:

    <!DOCTYPE taxi_data >
    <document author="Thomas Friedrichsmeier" title="AirCab 301" >

Once again, the "author"- and "title"-attributes will be shown in the credits for any mission that uses this taxi.

    	<fuel max="800" initial="800" />

Specifies how much fuel the taxi starts out with and how much it can have at maximum. 800 is a good value, I think, but you can make your missions harder or easier by changing it to lower or higher values.

    	<still frames="1" file_pattern="taxi1/still0000.png" />

This is the animation (or in this case still image) the taxi is doing all of the time (if not doing idle-actions or teleporting).

    	<idle>
    		<data frames="6" file_pattern="taxi1/idle1_%1.png" repetitions="2" />
    	</idle>

Even while flying, the taxi may do "idle"-animations. So obviously this term is not quite correct, but it's in analogy to the passengers' idle-animations (See there for the explanation).

You may define as many idle-animations as you like, but at least one. If you create more than one, the animation will be picked at random. Use frames="1" and a static image, if you don't want any idle animations. Likely a parameter sound="filename" will be implemented some day.

    	<flying_left frames="2" file_pattern="taxi1/flying_left%1.png" />
    	<flying_right frames="2" file_pattern="taxi1/flying_right%1.png" />
    	<flying_up frames="2" file_pattern="taxi1/flying_up%1.png" />
    	<flying_down frames="2" file_pattern="taxi1/flying_down%1.png" />

The meaning of these should be easy to guess. They change your taxi's appearance when you accelerate with the cursor keys. These are not independend images however, but really these images are just draw over the taxi image (so it can continue doing it's idle-stuff). Technically these are a different sprite. Have a look at the animations provided in the distribution, if you can't see, what I'm trying to say.

By the way, hitting something with these "flying-animations" doesn't crash your taxi, that means they are not to be understood as part of the taxi itself. They are however harmful to the passenger.

    	<teleporting frames="10" file_pattern="taxi1/teleporting%1.png" />

This is really the same as for the passenger. See there for details.

    	<landing_flaps offset_x1="3" offset_x2="30" />

This tag was introduced in Version 0.4.2, and specifies the x-positions of the taxi's landing-flaps (Is this the correct term? The poles, you stand on when landed, is what I mean) relative to the left corner of the taxi-sprite. If you omit this tag, the very left and right pixels of your taxi will be assumed as the position of the landing-flaps. This may result in the taxi crashing, when landing close to the platforms edges, while it actually looks to the player like the taxi is properly standing on the platform. So you should really specify these attributes.

Starting with Version 0.4.3 you may also create taxis with moveable landing-flaps. For those, the landing_flaps-tag would look like this:

    	<landing_flaps offset_x1="3" offset_x2="30" moveable="true" frames="6" file_pattern="taxi2/flaps%1.png" blocking="false" />

Note that the offset-attributes do NOT change their meaning in this context. The flaps-image is always aligned top-left with the taxi-image. Have a look at taxi2 and its images. The boolean attribute "blocking" specifies, whether you can still accelearte left/right with the landing-flaps out (false, default, if you are able to do so), or whether left/right-acceleration is blocked with the flaps out.

    </document>

You may not omit any of these sections. You may always use frames="1" and a constant "file_pattern", in order to create a very simple taxi, however.

Version 0.4.4 introduces the possibility to specify different animations dependent on whether the taxi is heading (or has last accelerated) to the left or to the right. I'm discussing this seperately, as this is probably less confusing. And here is how you can get that to work:

Whereever you can specify an attribute "file_pattern" in the taxi-config, you may instead specify the two attributes "file_pattern_left" and "file_pattern_right" for different animations when heading left or right. Note that you can not specify "frames" seperately for such a pair of animations - so they must always have the same number of frames.

You need not specify direction-dependent pairs of animations in all of the tags. You may well have, say, direction-dependent animations for the still-image and the idle-animations but not for the teleportation-animation, or you may even have direction-dependency on one idle-animation but not on a different one. Likely however, this would look rather strange.

Of course the flying-animations may also change with direction. Obviously, however, that makes little sense for the flying_left and flying_right-animations (you may still specify that, though). And of course, the landing-flaps may also be direction-dependent. For the landing-flaps, you may also specify seperate "offset_x1_left", "offset_x1_right" and "offset_x2_left", "offset_x2_right" instead of "offset_x1" and "offset_x2", if the x-position of your landing-flaps changes.

Note that although it would be functionally equivalent to specify "file_pattern_left" and "file_pattern_right" with the same value or to specify "file_pattern", if you do not want direction-dependency on an animation, the latter form is not only shorter, but also saves some memory.

Finally, starting with version 0.6.0 you can use the "anim_frame_period"-parameter as described for the passenger. Same as with the "frames"-parameter, you can only specify this attribute once, even if you have different animations for going left and going right.

As always, having a look at the configuration-files provided will probably help making this clear.

### Configuration of levels

A level is... well, I don't think I have to explain this. Let's have a walk through a sample config-file.

    <!DOCTYPE level_data >
    <document author="Thomas Friedrichsmeier" caption="Plain Level 1">

The "author"- and "caption"-attributes should be self-explanatory by now. Only thing is, that here you have to specify "caption" instead of "title" for historical reasons. The "caption" is also shown in &kappname;'s window-caption when the level is on.

    	<completion deliveries="5" extra_life="no" />

This specifies, that you will have to complete 5 deliveries successfully (get a tip for the delivery) in order to compelete this level. Upon completion of this level you will not be awarded an extra life.

    	<image background="testbackgr2.png" level="testlevel3.png" />

I'm not quite sure, whether this is such a good idea, but every level may have a unique background. Choose .png or any other file-format, QT supports. The background image is not solid/harmful, you can fly right over it. Make sure it doesn't look too much like the real level.

The level itself is first of all a simple image with transparancies. You can fly over the transparency, you can crash into everything else (+ land on the designated platforms, see below). For right now, the level-image has to have a solid frame. Currently there is not other mechanism of keeping the taxi inside the visible area.

You may want to have a look at the background- and level-images provided. It's really not that complicated. The only restrictions on the size of level- and background-images is that they should have the same size and should not be too large for a user with, say 800x600-screen-resolution to display (take into account the space the game-displays take up).

Starting with version 0.4.2 you may however also create oversized levels. The syntax is as follows:

    	<oversize visible_width="640" visible_height="480" initial_offset_x="0" initial_offset_y="0" margin="80" />

This specifies that the portion of the level that will be visible to the player is 640x480 pixels (your level should of course be bigger than that, if you use this option), you will initially see the top-left corner of the level, and finally "margin"-means the distance the taxi may have to any side of the visible area, before the level is scrolled.

    	<platforms>
    		<data y="265" passengers="yes" has_fuel="no" x1="94" passenger_base_x="190" x2="194" />
    		<data y="265" passengers="yes" has_fuel="no" x1="236" passenger_base_x="240" x2="356" />
    		<data y="355" passengers="yes" has_fuel="no" x1="116" passenger_base_x="120" x2="195" />
    		<data y="355" passengers="yes" has_fuel="no" x1="234" passenger_base_x="240" x2="337" />
    		<data y="389" passengers="yes" has_fuel="no" x1="420" passenger_base_x="425" x2="585" label="Residential area" />
    		<data y="71" passengers="no" has_fuel="yes" fuel_price="0.1000" fuel_step="3" x1="440" x2="540" />
    	</platforms>

This section defines, where you can land in this level. Note that you can't land in the void. &kappname; first checks, whether you collided yith the level-image, and only after that, whether this means you're landed. Make sure the landing-areas are really even, otherwise you might get "stuck" on them. The "label"-Attribute allows you to specify, what Spacetaxi will call the platform. If you omit the label-Attribute, the Platforms will will be numbered in the order of their definition, starting with 1 (and called "Platform <number>". It's your job to provided the user with information (in the level-image), which platform is which. Also don't forget to provide valid information about where the pilot can land. Therefore I'd recommend to explicitely label all platform in the level image.

You have to measure (2 or 3 pixels error won't harm) the y-coordinates of the surface of the platforms (y), and the x-coordinates of the left (x1) and right (x2) boundaries of the platform. Make sure the platform is large engouh to land on it (the taxi has to be compeletely within the boundaries). Of course you should be careful with these measures, to make sure the player can land everywhere, they expect to.

You may find the command-line-option "--highlight" useful during development. What it does is draw a (yellow) horizontal line from "x1" to "x2" at height "y". So this allows you to see, whether you really specified the platform-coordinates correctly.

The remaining parameters specify, whether there are passengers waiting on this platform (or demanding to be taken there) (passenger, default is "no"), if so, where exactly they appear / disappear on (passenger_base_x) (y coordinates are always right on top of the platform).

Furthermore, you can specify, whether you will get fuel on this platform (has_fuel, default is "no") and what the price of a unit of fuel is. I guess it is generally a good idea to keep passenger- and fuel-paltforms separate, but you don't have to.

"fuel_step" specifies, how fast the taxi will be fueled, i. e. how many units of fuel (see taxi-configuration) will be fueled up per unit of time (50 msec). "fuel_step" can take integer values from 1 (pretty slow) to 8000 (should amount to instant fueling to max for about any taxi). Personally I'd think values from 2 through 6 to be reasonable, as long as you don't want this "instant"-fueling effect.

    	<gravity base_gravity="0.0" horiz_gravity="0.0">
    		<data x="640" y="480" gravity="100" potential="2" />
    		<data x="0" y="0" gravity="100" potential="2" />
    		<data x="640" y="0" gravity="100" potential="2" />
    		<data x="0" y="480" gravity="100" potential="2" />
    	</gravity>

You have control over gravity far more than physics would allow. The simple parameters "base_gravity" and "horiz_gravity" specify the simple downward / sideward pull, you would expect in any game like this (independend of you current position). Start exprimenting with values around 0.005. Of course you may use negative values in order to reverse direction.

The following tags are "centers of gravity". Those allow you to make the force acting on the taxi depend on it's current position on the screen. Obviously you need to specify the location of the center of gravity. Next is a constant of gravity. Reasonable values (double) for this constant may vary dramatically depending on the following parameter. Use negative values to achieve a "pushing away". The parameter "potential" affords you a lot of control.

The allowed values and their effects are:

0: force does not depend on distance (but direction of force depends on direction)

1: force depends on plain distance

2: "physical gravity" - force is reverse of distance squared

4: "dangerous spot" - force is reverse of distance to the fourth power

There is no value "3"! You may have as many centers of gravity as you like, but I'm afraid, having real lots of them could slow down the game on old machines. You may of course omit specifying centers of gravity.

    	<teleporters>
    		<data x="100" y="100" destination="2" fare="0" factor_x="1" factor_y="1" image="teleporter1.png" />
    		<data x="200" y="200" destination="3" fare="0" factor_x="-2.5" factor_y="-2.5" image="teleporter1.png" />
    		<data x="400" y="200" destination="1" fare="1.50" factor_x="0" factor_y="0" image="teleporter1.png" />
    	</teleporters>

Have a look at level 3 of the current distribution, if you want to know, what teleporters do. They may have unique images, and of course they need to be placed on some coordinates. The other parameters are as follows:

"destination": Teleporters are numbered in the order of definition starting with 1. You can only teleport from a TP and only to another TP. This specifies the number of the TP, you will arrive at. If you want a TP to serve as an arrival-point only, set this value to "0".

"fare": Teleporting may cost money. This parameter specifies how much. If you don't have engouh money, the TP will be inactive. So make sure, vital TPs don't cost anything.

"factor_x", "factor_y": These parameters might be very nasty, they change the speed (and direction) when you arrive. Putting these values to 0 will obiviously stop the taxi. Putting them to large values might be very dangerous to the pilot.

Since generally, the active-region of a teleporter is determined by whether the taxi touches the teleporter, if you want to have an invisible teleporter (or one where the active-region does not correspond to the image), you will have to additionally specify the parameters "width" and "height" (in pixels). For an invisible teleporter, you could then specify a transparent 1x1-image. You may not omit the image-parameter, however. As a matter of fact, specifying a "width" and "height" for your teleporter, may save some resources, since in this case no collision-detection needs to be performed.

You may of course omit the teleporters-section, if you don't want any teleporters.

    	<tips min="10.00" max="30.00" />

This simply specifies the range of tips, passengers may start out with...

    	<fare base="5.40" step="0.050000" />

... while this parameter is used to control the taxi-pricing. "base" is the base-fare, "step" determines, how fast the fare will increase.

    	<initial_position x="50" y="50" />

Finally, this is, where the taxi starts out at in the level.

    </document>

#### Bringing life to your levels: Moving objects

Version 0.5.0 finally introduced support for moving objects in the levels. As of this version, there is still a lot to do, but also, a lot of flexibility is implemented already. And here is how that works:

    	<objects>
    		<object class="background" frames="5" file_pattern="some_object%1.png"
    				z="90" anim_frame_period="50" looping="yes" initial_vx="10" initial_vy="10" >
    			<path x="100" y="100" time="500" accel="linear" />
    			<path x="110" y="100" time="500" accel="abrupt" />
    			<path x="130" y="100" time="500" accel="linear" />
    			<path x="140" y="100" time="500" accel="linear" />
    			<path x="170" y="100" time="1500" accel="linear" visible="no" />
    		</object>
    		<object class="harmful" frames="10" file_pattern="another_object%1.png" looping="no" z="90" >
    			<path x="100" y="100" time="5000" accel="linear" />
    			<path x="100" y="300" time="5000" accel="linear" frames="5" file_pattern"animation_override%1.png" />
    			<path x="100" y="400" time="5000" accel="linear" />
    		</object>
    	</objects>

So first of all an objects may belong to different classes. Two basic classes are supported: Either the object is "harmful" i.e. you crash when you collide with it, or "background" i.e. it does not do anything to you, and is merely decoration. There is a number of special classes, which will be dealt with in the next section. Then of course, an object has an image or animation with the well-known parameters "frames" and "file_pattern". The (optional) parameter "anim_frame_period" will probably soon be implemented for other animations, too, and specifies how fast the animation is running or rather, the time in msecs needed for one frame. A higher value gives a slower animation. The movement-frame-rate is independend of this parameter. It only deals with the animation.

Further, you may specify the z-Position of the object. The higher the value, the closer is the object, i.e. it will cover objects with a lower z, when the two overlap. BTW, the taxi is at z="75", the level at z="50", passengers at z=40". Of course the object can not be behind the level's background, however.

An object may either be "looping" (going from A to B to C to A) or "bouncing" (going from A to B to C to B to A and then back). Note that this also affects the way that the last path-segment is treated. For looping objects, it will be taken as the way back, i.e. the first object above will be invisible for 1.5 seconds and return to the position 100/100 during that time. For bouncing objects, the way is the same in both directions, so here the last path-segment describes the way the object takes starting from the last key-position, until it reaches that same key-position again. So it will spend 5 seconds in the third path-segment and then go back to the second.

You may specify an inital speed for the object. This only has an effect, if the first segment of the path has accel="linear" given. See below.

Next we will have to specify the path of the object: Therefore we define key-frames, with starting-coordinates, time needed to reach next key-point (milliseconds), mode of acceleration, and whether it will be visible on the way (while invisible it is never harmful).

There are three possible modes of acceleration:

accel="abrupt": The object moves from the starting-coordinates of the current path-segment to the startin-coordinates of the next at a constant speed on a straight line. Therefore the speed and direction of the object may change abruptly with respect to the previous path-segment.

accel="linear": The object starts out with the speed and direction it had on the last frame of the previous segment of the path (or with initial_vx and initial_vy). It then uses just that constant acceleration that will make it arrive at the next key-position in the specified time. Most of the time this should give nice smooth movements.

accel="custom": The tough way, but of course the one with the most flexibility. If you specify accel="custom", you may also specify the parameters "vx" and "vy" (starting velocity (in pixels per second)), "ax" and "ay" (starting acceleration in pixels per second squared) and "dax" and "day" (change in acceleartion over time in pixels per second cube). Of course you don't have to specify all these. Any parameter you omit will be assumed to be zero. Therefore, if you omit "ax", "ay", "day", and "dax", you will get a movement with a constant velocity "vx" and "vy". Using this mode, it is entirely your responsibility to make sure that using these parameters, the object will reach the next key-frame in the specified time. If it does not, it will simply be put there, making the object jump. So this is for those who love maths. Even in this mode, if you specify a "bouncing" object, the way back will be exactly the reverse of the way forth.

Finally you can otherride the following parameters on a per path-segment basis: "z", "frames", "file_pattern", "anim_frame_period".

I admit, this is quite complex already, but as always, you can start out with simple objects and slowly experiment with more difficult ones.

Version 0.6.1 introduces the possibility to create textual moving objects. Of course you can always put text in an image-file and this would not even cause a loss in performance + allow you more flexibility, but of course it would make life even harder for potential translators. So whenever you want to display text in a level, I suggest you create a textual moving object. Actually this is a completely normal moving object, except for that you don't specify the image-/animation-specific attributes, but the following ones:

    		<object text="Sorry, this is it, this is the last level!" align="left" font="helvetica" size="24"
    				r="10" g="255" b="150" anim_frame_period="10000" class="background" z="90"
    				looping ="true">
    ...

Actually you can specify a different text for each path-segment, and you can even have text on one path-segment and an animation on the next. Since text can not be animated, however, you will probably only define a global text. The "r", "g", and "b"-attributes define the color of the text, the other attributes should be self-explanatory. The "align"-attribute takes "left", "center" or "right" as values, and obviously only has an effect, when there is more than one line of text. To insert a newline into your text, put in a "\n". I.e. : text="This is the first line\nThis is the second line". Technically, if Taxipilot finds a "text"-attribute in any path-segment, it will assume that there is to be a text, and will ignore any image-/animation-specific attributes such as "frames".

Note that although textual objects could theoretically also be platforms, this probably isn't a good idea.

#### Everything's moving now: Special moving objects

Version 0.5.1 greatly extends the support for moving objects in the levels. You can now also define platforms, teleporters and centers of gravity to be moving objects. In order to do so, first of all you assign an identification label to the platform/teleporter/center of gravity (example for a moving teleporter):

    		<data ident="tp1" destination="2" fare="0" factor_x="1" factor_y="1" />

Of course now, you do not need to specify a (static) x- and y-position and also, you don't have to specify a (static) image. After all, the teleporter now is a moving object, that may change it's position and appearance.

Note: You may of course mix "normal" and "moving" teleporters in the teleporters' section.

Next, the teleporter needs to be tied to a moving object. You do this simply by declaring an object to be of class "teleporter" and having the same idenification label you used when defining the teleporter:

    		<object class="teleporter" frames="5" file_pattern="some_object%1.png"
    				z="90" anim_frame_period="50" looping="yes" ident="tp1" >
    			<path x="100" y="100" time="500" accel="linear" />
    			...
    		</object>

Everything else works the usual way. So, to sum it up, you define the parameters specific to a teleporter in the teleporters' section and those specific to a moving object in the object's section, then you tie both sections together with the "ident"-paramenter.

Note: The one thing that is different is, that x- and y-position-parameters for a (normal) static teleporter are interpreted to be the center of the image, objects' positions always refer to the top-left corner of the image!

For moving platforms and centers of gravity, the procedure is basically the same. What is left to be said is that objects tied to centers of gravity may either be defined with class="harmful center" or class="harmless center". Obviously, the two differ in whether the taxi can crash into them. Also obviously, the x- and y-position-parameters (in the definition of the center of gravity) are not interpreted for moving centers.

Moving platforms still take the "x1", "x2", "passenger_base_x" and "y"-paramenters. For moving platforms, those parameters are interpreted as relative to the top left of the image of the platform. The belonging moving object has to be classified as class="platform".

Finally, it needs to be said, that the "tying up" of platforms/teleporters/centers of gravity with moving objects fails, the object does not have the same "ident"-parameter, or if it is not classified appopriately. You can only ever tie up one of these functions with a single moving object, and you cannot tie several moving objects to one function.

As always, having a look at the configuration-files provided might help understanding the procedure.

#### Advanced level programming: Events and States

An arcade game of this sort, without doors and switches? Of course not! Version 0.7.0 introduces a framework for creating doors and switches and eventually many other things. Not everything that this framework allows for has been implemented yet, but new features are soon to follow.

Let me start by giving you a general overview of "events" and "states": A "state" is basically a variable which may either be on or off. E.g. you might have a state labled "door_open", which may either be on or off, and of course a door (a moving object) which will act according to this state (how to accomplish this will be described some paragraphs below).

The whole thing would of course be pointless, if the "door_open"-state would never change. Changing states is accomplished by events. Think of events as actions, which may be triggered when something happens. As of version 0.7.0, there is only one sort of objects, the "hot_area", which can fire events, but eventually platforms will be able to trigger events, when you land on them, when a passenger appears on them, teleporters, when you arrive at them...

So actually, opening a door is not all that easy to do: You need a moving object, that depends on a state, a state, which it depends on, an event, that changes the state and finally something to trigger the event. This framework does however allow for a maximum of flexibility. Let's have a more detailed look:

##### Syntax of "States"

The syntax for declaring a state is relatively straightforward. All state-declarations are grouped together in a "states"-tag and individual "states" are given a label ("ident") and initial value ("initial"):

    	<states>
    		<state ident="door_open" initial="off"/>
    		<state ident="some_other_state" initial="on"/>
    	</states>

##### Syntax of "Events"

Similarily events are grouped in an "events"-tag and of course also need a label. Events, generally, also change some state(s), which is accomplished via a "change"-tag:

    	<events>
    		<event ident="toggle_door">
    			<change state="door_open" to="toggle"/>
    		</event>
    	</events>

What happens in this example is, that the event, when triggered, changes the state "door_open" to is opposite value, i.e. to "on" when it was "off" and vice versa. Of course you may also specify to="on" (or to="off"), if you want your event to only open (close) the door.

This, however, isn't all there is to events. You may make the execution of your event depend on a condition. E.g. you might have a state "door_can_be_opened", which is to control, whether your "toggle_door"-event takes any effect. In the following example, if "door_can_be_opened" is "off", and the event "toggle_door" is triggered, nothing wil happen, because the condition is not met:

    		<event ident="toggle_door">
    			<condition>
    				<requires state="door_can_be_opened" to_be="on"/>
    			</condition>
    			<change state="door_open" to="toggle"/>
    		</event>

The "condition"-syntax is described in more detail, below. There may be only one condition-tag per event, but it may involve several states.

Another thing, that can be done in events is to trigger some further events. E.g. you could have two doors, A and B, and you want door B to get shut, whenever door A gets opened, but not necessarily the other way around. You could accomplish this using the following two events:

    	<events>
    		<event ident="open_door_a">
    			<change state="door_a_open" to="on"/>
    			<child_event ident="close_door_b"/>
    		</event>
    		<event ident="close_door_b">
    			<change state="door_b_open" to="off"/>
    		</event>
    	</events>

What's left to say is that each event may have only one condition-tag and any number of "change"- and "child_event"-tags. When the event gets triggered, first the condition (if any) will be checked. If the condition fails, nothing will happen. If the condition is fulfilled, the event will process all "change"-tags in the order they are specified. Only after that all "child_event"s will be triggered in the order the appear in the config. Triggering means, that the "child_events" will each be processed fully one at a time. I.e. if you have an event A with child-events B, C and D, and C has child-event E, first A will be triggered, then B, then C, then E and only then D. (This is just to confuse you, probably you'll never need to know about it).

Note that events perform strict checking for recursions. If an event notices, that it is called again (from some child_event), before it has finished all its actions, it will ignore that call and output an error message. Whenever timers do get implemented, you will however be able to have a recursion with a certain delay between each cycle.

##### A closer look on conditions

Conditions are not all that complicated, but since they may appear in several places, they deserve a section of their own. A condition is really a sequence of "requires"-tags with all the specified "state"s required to be in the specified state. All "requires"-statements have to be fulfilled at once. They therefore constitue a logical AND.

    			<condition>
    				<requires state="has_key" to_be="on"/>
    				<requires state="can_handle_key" to_be="on"/>
    				<requires state="key_broken" to_be="off"/>
    			</condition>

##### Hot Areas

Starting with version 0.7.2 there are a number of other ways to trigger events besides "hot_areas". Those other ways will be discussed later, since "hot_areas" probably the most important way. Hot "area"s are rectangular regions on the screen (invisible by themselves) which can trigger events, if the taxi touches ("touch_event", stops to touch ("untouch_event"), enters ("enter_event") or leaves ("leave_event") this region. Note that hot-areas currently don't perform an exact check for these events, i.e. do no real collision-detection, but merely check, whether the bounding-rectangle of the taxi-sprite touches, enters, ... the area. I believe this is a reasonable compromise with performance. One helpful thing when creating levels with hot-areas is the commandline-option --highlight, which not only hightlights the platforms as mentioned above, but also oultines the hot_areas, so you can see, whether they are positioned correctly.

The following example should illustrate the syntax. Note that all hot-areas in a level are grouped in a single "hot_areas"-tag (analogous to events and states).

    	<hot_areas>
    		<area x1="558" x2="640" y1="0" y2="68" enter_event="unlock"/>
    		<area x1="0" x2="78" y1="320" y2="340" touch_event="toggle_left_door" untouch_event="toggle_left_door"/>
    		<area x1="0" x2="78" y1="354" y2="375" leave_event="close_all_doors"/>
    	<hot_areas>

##### Conditional behavior in Moving Objects

So far events and states have remained dry theory, wth no visible results. The ultimate purpose of "states" is of course that they affect the behavior of objects in the game. Moving Objects are the first kind of objects that can have conditional behavior. You can add special actions to each path-segment, that will be processed at the end of that path-segment. Lets have a look at a concrete example:

    		<object frames="1" file_pattern="objects/door.png" class="harmful" z="1" looping ="true">
    			<path x="84" y="343" time="500" accel="abrupt"/>
    			<path x="0" y="343" time="50" accel="abrupt">
    				<stop>
    					<condition>
    						<requires state="door_open" to_be="off"/>
    					</condition>
    				</stop>
    			</path>
    			<path x="0" y="343" time="500" accel="abrupt"/>
    			<path x="84" y="343" time="50" accel="abrupt">
    				<stop>
    					<condition>
    						<requires state="door_open" to_be="on"/>
    					</condition>
    				</stop>
    			</path>
    		</object>

What this example is meant to accomplish is to have a door that will be in x-position 0 when the state "door_open" is "off", and in position 84 when the state is "on". In the example, the door will start out opened (at x 84) and move to closed from the first to the second-path-segment. Next, it will move all the way of the second path-segment, which actually simply tells the door to remain in place for a brief period of time. At the end of the second path-segment, however a "stop" is to be processed. This "stop" tells the object to simply wait without moving as long as the given condition is fullfilled, i.e. as long as "door_open" is "off".

If "door_open" happens to be "on" when the object finishes the path-segment, it simply moves on to the next segment, like it normally would. If "door_open" is "off" however, it will not continue to move until "door_open" changes to "on". It is important to understand, that the object will only ever stop at the end of a path-segment, never in between.

There are three more tag besides "stop" that version 0.7.2 supports: "freeze", "trigger" and "jump". "freeze" is used in exactly the same way as "stop" and does almost exactly the same thing (stop the object), but also stops any animation the object might have. "trigger" and "jump" will be discussed below.

A few things remain to be said about conditional movements. First, you may have wondered, why I specified four path-segments for really only two positions. The reason is that at the end of a path-segment, the object is generally some way before reaching it's target position. The next key-position will only be reached at the start of the new path-segment. Therefore, if you want very exact control over where the object stops, you should insert "dummy-path-segments", where no movement occurs. Second, you should note, that the "linear"-accel mode does not work as might be expected over a "stop". Rather, the object will come to an abrupt halt if it is to stop, and when released, starts with the speed it would have had, if there had been no "stop"-tag in between. This is because the movement-velocities are calculated beforehand, not during the game. Therefore, you should make sure not to introduce stops at points where the object would normally be moving very fast - that would simply look awkward. "jump"s, discussed below give you a neat way to circumvent this limitation.

The syntax for "jump"s is basically the same as for "stop"s:

    			<path x="0" y="343" time="50" accel="abrupt">
    				<jump target="5">
    					<condition>
    						<requires state="go_somewhere" to_be="on"/>
    					</condition>
    				</stop>
    			</path>
    			...

What a "jump" does, is that - if the condition is met - the object will continue it's movement at the specified "target". Target is the number of a path-segment for this object (path-segments are counted starting with 1). So in the above example, if the state "go_somewhere" is "on", instead of proceeding to the next path-segment, the object will continue it's movement at the fifth path-segment. Any further actions like "stop"s or other "jump"s that follow the "jump"-tag will be ignored, if the jump-condition is met. If it is not met, the "jump"-tag will simply be ignored.

It might not be easy to understand the "jump"-tag, but it is indeed very powerful, giving you the option of not only stopping an object, but making it move entirely differently. If you are familiar with a programming language that has GOTO-statements, it will probably help, thinking of "jump"s as GOTO-statements.

Two things remain to the said about jumps. First, &kappname; will not take them into account when doing path-calculations (when putting meaning to accel="linear" or accel="abrupt"), and instead calculate acceleration-rates as though the path would continue normally. In many situations it will therefore be adviseable to use accel="custom" for best results.

Second, when using "bouncing" objects, there will internally be twice as many path-segments than you specified (for the way back). You are allowed to address those in the "target"-attribute, making your object jump to a position on the way back. E.g. you might have an object going for A to B (path-segment 1) to C (2) to D (3) to E (4), then bouncing back to D (internal segment 5) to C (6) to B (7) to A (8). Now you could insert a jump between after 2 (when the object has arrived at C) with target="7". Then if the jump-condition is met, the object will jump to the path-segment taking it back form C to B, i.e. effectively return back before going to E.

Finally the "trigger"-action can be used to trigger an event, when the object arrives at a certain key-posiiton:

    			<path x="0" y="343" time="50" accel="abrupt">
    				<trigger event="do_something">
    					<condition>
    						<requires state="inform" to_be="on"/>
    					</condition>
    				</stop>
    			</path>
    			...

Here, after teh object finishes the path-segment, the event "do_something" will be triggered. This might be useful for syncing the movement of several objects. As with all other types of actions, the "condition"-tag is mandatory.

As always, having a look at the level-files in the distribution might be more instructive than this document. Go ahead and try, e-mail me, if you experience problems or find bugs!

##### Further ways to trigger events

Version 0.7.2 of &kappname; introduced a number of additional ways of firing events.

###### Platforms

Platforms may single four different events: (1) The taxis has landed on the platform (2) the taxis has taken off (3) a passenger appeared on the platform (3) a passenger has left the platform. Using these events is really rather straight-forward:

    	<platforms>
    		<data y="100" passengers="yes" has_fuel="no" x1="100" passenger_base_x="110" x2="140" label="Special platform"
    				land_event="do_something" take_off_event="do_something_else"
    				arrive_event="yet_another_event" leave_event="and_another_one" />
    		...
    	</platforms>

So this platform would fire four different events in the four above-mentioned cases.

###### Teleporters

Teleporters can trigger event, when (1) the taxi gets teleported away from this teleporter and (2) the taxi gets teleported to this teleporter:

    	<teleporters>
    		<data x="461" y="273" destination="2" fare="0" factor_x="0" factor_y="0" image="teleporter.png"
    				arrive_event="open_door" leave_event="close_door" />
    		...
    	<teleporters>

###### Timers: Delayed events

Timers essentially behave like events and are defined and used in much the same way. The difference being that when triggered, the timer will not immediately do it's stuff (checking it's condition, then changing states and firing child-events), but rather wait for a specified period of time before doing so. Let's have a look at the definition of a timer:

    	<timers>
    		<timer ident="timer1" period="500" triggered_while_active="restart" loop_state="some_state" trigger_initially="true" >
    			<condition>
    				<requires state="door_can_be_opened" to_be="on"/>
    			</condition>
    			<change state="door_open" to="toggle"/>
    			<child_event ident="some_event_or_timer"/>
    		</timer>
    	</timers>

So first of all, you should note, that a timer takes all the attributes and tags that a normal event does. In fact it internally is an event, and whereever you are allowed to specify an event to be triggered, you could specify a timer in exactly the same way. The additional parameters for a timer are:

"period": The duration of the delay in msecs.

"triggered_while_active": Specifies, what will happen, when the timer is triggered, while it is already actively counting down. Possible values are (1) "ignore" (default), the timer will simply ignore the triggering and continue counting down (2) "restart", the timer will start over with the count-down (3) "stop", the timer will be stopped.

"loop_state": Here you may specify the name of a state, that controls, whether the timer behaves as a single-shot-timer, i.e. stops after it has finished it's countdown and done its actions or whether the timer starts over automatically. The default is to behave as a single-shot-timer, but if you specify a valid state, each time the timer finishes it's countdown, it will check the specified state and restart itself if the state is set to "on".

"trigger_initially": Controls, whether the timer will be triggered initially (when the level is started). Default is false/no.

##### Further ways to use states

Besides affecting the movement of moving objects, states may control a few other things:

###### Teleporters

States can be used to (de)activate teleporters, i.e. to control (1) whether the teleporter will take the taxi anywhere and (2), whether a taxi can be teleported to the teleporter:

    	<teleporters>
    		<data x="461" y="273" destination="2" fare="0" factor_x="0" factor_y="0" image="teleporter.png"
    				arrive_state="state1" leave_state="state2" />
    		...
    	<teleporters>

So, if "state1" is "off", you can not teleport to this teleporter, i.e. all teleporters that have this teleporter a their destination will be blocked. If "state2" is "off", the teleporter itself is blocked, i.e. will not take you anywhere (but depending on "state1" you can still arrive on it).

###### Centers of Gravity

The attribute "active_state" allows you to specify a state that controls, whether the center-of-gravity is active (i.e. attracting or pushing away the taxi). This way, you can turn on and off centers-of-gravity:

    	<gravity>
    		<data x="320" y="240" gravity="200" potential="2" active_state="has_gravity"/<
    		...
    	</gravity>

## How to translate &kappname;

Translating the actual application should not be different from compiling any other application. However, since all the levels are defined in seperate file that are read at runtime (and may contain language-specific strings), you should provide translations for the strings in those files, too. Here's how to do so (version 0.7.1 and above):

Somewhere in cdp.cpp there is an i18n()ed string "en_US", that you will have "translate" to your language code (e.g. "fi" or "de"). Now, whenever &kappname; starts parsing a configuration file, it will try to find a translations-file with the language code as a filename-extension. I.e. when &kappname; reads the file "level1.level", and your language code is "fr" it will look for a file called "level1.level.fr" (in the same directory). If it doesn't find this file, all strings in "level1.level" will be used untranslated.

If &kappname; does find the translations file, it expects it to look like this:

    some string to be translated:::::translated version of the string
    another string that should be translated:::::translation for that one
    ...

I.e. you simply list those strings that should be translated, five colons and then the translated version. Order of the strings is irrelevant, but be sure to copy the left-hand-side (i.e. the not yet translated strings) exactly as they are, since otherwise &kappname; will not be able to match them to their translations. There is no need to translate strings, that are not shown to the user, or are the same in your language. If the translations-file does not contain a certain string of the configuration-file on the left-hand-side, the string will be used untranslated.

Although this is not exactly good style, there are a number of images that contain language-specific information (i.e. strings that are realized as graphics). Although of course, it's a lot harder to translate those, you can do so, by simply "translating" the filename of the image. I.e if the file "levelx.png" contains text, you could edit that image, save it as "levelx.fr.png" (leave the extension ".png" untouched!) and add a line

    levelx.png:::::levelx.fr.png

in the translations-file.

When done, you should test your translations, and especially have &kappname; parse all config-file thoroughly, to make sure you did not break anything (command-line option --thorough_check). In case you get unexpected results, try the command-line option --debug-level 4 , which will generate a lot of output, among other things listing all the strings &kappname; translated (or failed to find a translation for). A basic understanding of &kappname;s configuration files (see previous chapter) will probably help in deciding, which strings should be translated and which should not.

## Questions and Answers

&reporting.bugs; &updating.documentation;

Why aren't there any questions in this faq?

'Cause I haven't yet been asked any. Go ahead and contact me in person.

## Credits and License

&kappname;

Program copyright 2001, 2002 Thomas Friedrichsmeier thomas.friedrichsmeier@ruhr-uni-bochum.de

Documentation copyright 2001, 2002 Thomas Friedrichsmeier thomas.friedrichsmeier@ruhr-uni-bochum.de

&underFDL; &underGPL;

## A note to anybody who read the code

This is my first KDE-App. As a matter of fact, it is my first C++ or even object-oriented program. Actually it is my first program to ever really see the light of the world (although some small programs and scripts do good deeds in their niches).

So if you look at the code, there's probably a whole lot of silly things in there, not to mention, that the documentation could be better. Please don't blame me for it - give me a hand, show me how to do it right. I'd really appreciate your comments.

Some three months after I wrote the above two paragraphs, I might add that as the code keeps growing, inconsistencies keep creeping into the API. Also, while I trie to documentate each new function I create, I'm afraid some functions have changed in lots of little ways, without the API-documentation reflecting those changes. I've even been playing with the thought of rewriting some classes entirely. But then, if I had that time...

## Acknowledgments

I'd like to thank:

- Josef Spillner for several helpful comments and suggestions

- Stefan Bruens for a number of bug-reports and useful suggestions, and for being the first person to contribute a level

&documentation.index;