Designing Games with Xconq - Designing the World

Go to the first, previous, next, last section, table of contents.

## Designing the World

The Xconq world/area is a two-dimensional grid of fixed shape and size. You can treat it as representing part of a planet in space, and set up parameters simulating that, or just make it be itself and not address the question of the surrounding context. The appropriate choice depends on how much realism and complexity you need. Most computer games don't bother with this detail; for instance, a game set in an underground dungeon doesn't usually need to compute daylight, weather, or seasons. However, these same details may be very useful for games set outdoors.

- World Shape and Size
- World Terrain
- Synthesizing World Terrain
- Rivers
- Roads
- Independent Units
- Altitudes and Elevations
- World Setup Miscellany

### World Shape and Size

Once you've decided whether the area is to be part of a planet or not, you can address the question of size and shape. You have two choices for shape: hexagon and cylinder. (See the players chapter for pictures of these.) The important thing for you as a designer is that the cylinder wraps around, while the hexagon is bounded on all sides. One consequence is that games involving pursuit will be quite different; on a cylinder, the chase can go 'round and 'round forever, while on a hexagon, a fleeing unit could be cornered. Cylinders have a disadvantage in that there is no obvious "starting place" for coordinates, scrolling, etc, so there is a navigation and orientation problem for players, especially if the world is randomly generated and not the familiar continents of the Earth. In fact, players will often not even realize that a world is a cylinder and will assume that the edge of the display is the edge of the world! To make a cylindrical area, set the circumference of the world equal to the width of the area. Otherwise, the area will be handled as a hexagon.

You can choose either to set a fixed size using the `area` form, or allow players to set the actual size via the `world-size` variant, in which case you can define the allowable range of sizes.

Worlds need not be really large. Larger worlds are harder for players to manage, they take longer to display, and can consume prodigious amounts of memory (since they are represented as arrays internally, for speed). The ideal range of sizes depends primarily on the size and speed of units. A 60x60 area in a game with units whose speed is 1 means that they will take 60 turns to cross, while units with a speed of 20 take only 3 turns, so they make the world "feel smaller". As another example, in the standard game, a 20x20 area allows player to come to grips quickly, but it also means that each player's units might be within attack range right from the outset, which has a drastic effect on strategy. For exploration-oriented games, larger worlds are more interesting.

### World Terrain

The best technique for designing the terrain of a world is to use the designer tools provided with Xconq. The details of how these tools work depends on the interface, but in general they resemble the tools found in paint programs. Some interfaces also give you the option of rescaling the map, so that you can fine-tune the size and positioning of the terrain.

Another technique is to write a program that translates data from another source (such as NASA satellite data) into Xconq format. However, if you take a rectangular array of data and just wrap an `area (terrain ...))` form around it, then everything will appear to be tilting to the left. To fix this, have your program map the cell at `x, y` in the rectangular array to `x - y / 2, y` before writing. You must discard values whose new `x` coordinate is negative, or else wrap them around to the right side of the area, although that is usually only reasonable for cylindrical areas.

The crudest technique is to try to build terrain by using a text editor. The coordinate system is Cartesian oblique, with the y axis tilted to form a 60-degree angle with the x axis, so it can be difficult to relate typed-in characters to the final appearance. Landforms in the file should appear to be leaning to the left, if they are to appear upright during play. However, sometimes text editing is necessary, for instance when you need to change every instance of a terrain type to something else. (Incidentally, some of the large real-world maps in the library were produced by coding all the terrain types from an atlas onto graph paper, typing them in, then fixing the tilt as described above.)

Incidentally, areas should have some distinguishing terrain around the edges; this prevents player confusion that sometimes happens when there is no other clue as to where the edge might be. However, this is not enforced by Xconq, and you can put whatever you like along the edges. Randomly generated worlds normally use the value of the global variable `edge-terrain`.

### Synthesizing World Terrain

The random way to get terrain for a world is to use one of several synthesis methods built into Xconq.

Totally random terrain is available via the synthesis method `make-random-terrain`. This just randomly chooses a terrain type for each cell, using the weights in the `occurrence` property of each type. An `occurrence` of 0 means that the type will never be placed anywhere. This method produces a sort of speckly-looking world, and is better for testing than for actual play. Still, if you have two types `vacuum` and `solar-system`, then a form like

    (add (vacuum solar-system) occurrence (20 1))

will give you a nice starfield for a space game.

The fractal world method `make-fractal-percentile-terrain` descends from the most venerable part of Xconq (it was once a piece of Atari Basic code). It uses a fractal algorithm along with percentile-based terrain classification to make realistic-looking worlds with terrain and elevations.

To use this method, you first specify how many, what size, and what height of blobs to splash onto the world, and how many times to average cells with their neighbors. Then you specify the subdivision of all the possible altitudes and moisture levels into different kinds of terrain. For instance, desert in the standard terrain ranges from sea level (`alt-percentile-min` = 70%) to high elevations (`alt-percentile-max` = 93%) but only in the lowest percentiles of moisture (`wet-percentile-min` = 0%, `wet-percentile-max` = 20%). It is important that all percentiles be assigned to some terrain type, or the map generator will complain and subsitute terrain type 0 (the first-defined type); when designing terrain percentiles, it is helpful to make a chart with altitude percentiles 0-100 on one axis and moisture percentiles on the other. Note that overlapping on this chart is OK, and the terrain generator will pick the lowest-numbered terrain. Also note that you don't have to include every terrain type.

The `alt` numbers are also used to compute elevations for games that need them, but the `wet` numbers need not have anything to do with water at all; they could just as easily represent smog levels or vegetation densities. If you only want to use one of the two layers, just set the percentiles for the other to be 0 - 100 for all terrain types.

[should have an example]

The method `make-maze-terrain` produces a maze consisting of a mix of "solid", "passageway", and "room" terrain. It uses the `maze-room-density` and `maze-passage-density` properties of each terrain type to decide how much of each to use for rooms and passages. The method first does random terrain generation, using the `occurrence` property to decide how much of each terrain to put down (remember that `occurrence` defaults to 1 for all terrain types). Then it carves out rooms, and passageways between them. The passages and rooms are guaranteed to be completely connected.

The method `make-earth-like-terrain` attempts to model the natural processes and generate terrain as similar as possible to what is observed on Earth today.

You should note that at least one method for synthesizing terrain must be available, unless you can guarantee that terrain will be loaded from a file. The following subsections describe optional additional synthesis methods that you can include.

### Rivers

You can use the `make-rivers` method to add rivers to the world. Rivers are basically water features that depend on terrain elevations, so they won't be generated unless both a river terrain type (either border or connection) and elevation data is available. You get them by specifying a nonzero chance for some type of terrain to be the location of a headwater (`river-chance`).

Xconq doesn't have any intuition about the behavior of water; it will happily trace rivers all the the way down to the bottom of the sea. Use the `liquid` property to tell `make-rivers` what types that rivers cannot touch. The method still traces the river's course, and resumes modifying terrain when possible, which means that the river can appear as both the inlet and outlet from a lake.

### Roads

The `make-roads` method is a fairly generic method. It just picks pairs of units randomly and runs a road between them, attempting to share road segments and route through favorable terrain. Although simplistic, the results look pretty good.

You can make short bridges by tweaking the road density appropriately. Just allow roads from land to water, and water to land, but not from water to water.

Note that this method is only useful if there are actually units for the roads to connect.

### Independent Units

For many games, it is useful to have independent units scattered randomly across the world. For instance, gold mines and treasure hoards would be good for an exploration game, and independent castles for a medieval game. You can set this up with the `make-independent-units` method.

### Altitudes and Elevations

Xconq is basically a 2-dimensional game, but you can emulate a third dimension by defining elevations for terrain and altitudes for units above and below the terrain.

The main use of altitudes is to control interactions between certain kinds of units, particularly aircraft. For instance, a high-altitude bomber should be able to pass over a ship and under a satellite with impunity. In general, you define the "operating altitudes" of a unit, so in the example above, you could say that a ship is always at the surface, bombers operate at 1-10 km, and satellites at 100-10,000 km. If a unit has more than one operating level, then it can move up and down by normal movement actions.

Also, most details such as speed and material consumption are the same for a unit at any altitude. (Yes, such things vary in real life, but the effects are usually minor within the unit's normal operating range.) Altitudes have a significant effect on combat. A unit at some altitude can only attack units at a specific range of altitudes up and down. Using the example again, you could define fighter aircraft to operate at 0-20km and be able to attack up and down 5km, while bombers can attack up to 10km down (i.e. down to the ground), but not up. Satellites remain invulnerable.

All this applies equally to units underground and undersea.

[need info about setting up other layers]

### World Setup Miscellany

For additional flavor, with no effect on game play, you can identify and name geographical features in the world.

For predefined areas, just add the `features` layer and either fill in manually, or with a design tool. I find that the most efficient approach is to make a list of all the features that I want to be in the world, set up the list manually along with layer data saying that all parts of the area are unnamed (all 0s), then read in the world + feature layer and use the online feature painting to define the shape of the feature.

For random areas, the synthesis method `name-geographical-features` does the work. You can use a side property `feature-namers` and a global variable, also called `feature-namers`. Both of these map feature types to namers (for "namers", see below). The list of types of features to try to identify is in the global `feature-types`. The basic idea is that the synthesizer looks for the types of features requested, then names them using the appropriate namer.

Here is what the standard game does to generate funny names for lakes, but the more-anonymous "Peak 4532" for mountain tops:

    (set feature-types (("peak") ("lake")))

    (set feature-namers (("lake" "generic-lake-names")))

    (namer generic-lake-names (grammar root 10
      (root (or 5 (foo "Lake " generic-names)
                1 (generic-names " Lake")
                ))
      (foo "")  ; works around a bug
      ))

    (include "ng-weird")

Go to the first, previous, next, last section, table of contents.