Random town generation
In this article I shall present two ways of creating a random town I thought about while writing UR. Bear in mind, however, that there are other splendid town generation algorithms possible, some of them bearing far better results than the ones described here.
Algorithm 1: division into cells
Let's start with an algorithm that I first thought of, but found the final results unsatisfactory.
The idea is to divide the map into square cells (in case of UR, there were 14x11 cells, 8x8 tiles each). Then, in each cell we generate a building (or not).
The good side of the algorithm is that we can define exactly how many cells need to be populated with a building, resulting in an exact number of buildings in the generated town. The size and shape of the buildings may vary, of course.
On the other hand, the generated towns look somewhat artificial due to the forced symmetry.
Algorithm 2: more randomness
The other algorithm gives more satisfactory results. For each building, a random point on the map is chosen and all potential tiles need to be checked before placing a building. If they are empty, the building is placed. If they intersect another structure, be it a building or anything else, a new random point is chosen. This is repeated until no new buildings can be placed or until the desired number of buildings has been placed.
The good side of the algorithm is its randomness. The generated towns are irregular and thus more fun to explore. Its downside is the unpredictable number of buildings. It can be limited, but it may result impossible to reach that limit as well. On my 112x90 map, between 90 and 110 buildings are usually generated (that is, then no other features are placed, further limiting the number of buildings).
Also, generating a town using this algorithm seems to take much time. Smaller settlements are generated near-instantly, but larger ones (when the max building limit cannot be reached due to the impossibility of placing a new building) seem to take a full second (approximately) to be generated on my machine (1.3GHz Celeron). This isn't much of a problem if you generate maps upon visiting them for the first time, but if you plan to pregenerate a certain amount of towns, you should be sure to indicate on the screen that something's being calculated, otherwise a player (possibly with an older computer) might think it's a hang and close the game.
Below, you can see an example of such random town. Note that the screenshot contains a road as well.
Road generation
Generating a road is a very simple task as well. The catch is that roads may turn. To correctly implement this feature, I parted from a simple assumption: if two roads going into the town, say, from the north and from the east, need to meet exactly in the same point, it is necessary to generate them from that point and not from the map's edges towards the centre.
The other problem with the typical approach to making roads (and rivers and whatever) is that they are normally drawn line by line or column by column. In other words, one "for" loop progresses through the x coordinate and at each step another "for" draws a vertical/horizontal line.
Now, if the two roads should meet at the centre and the turn should look natural, which is not the case of two roads, one drawn line by line and the other one, column by column, a different approach is needed.
I chose the following: instead of using two "for" loops, one for vertical and one for horizontal displacement, I only used one. At each step made by the loop, a CIRCLE filled with the road tile is drawn. This way, the roads look more convincing at the point where they meet. Take a look at this image.
The other features present on this image (forest surroundings, town walls and the coastline) are intuitively easy to code, therefore I shall not comment them further.
Comment
The limitation of the Roguelike genre is that the map consists of square cells in horizontal lines and vertical columns. This usually means that all architecture (buildings, mazes, dungeon rooms) is based on rectangles with a horizontal base. It would be an interesting task, however, to implement horizontal, vertical AND diagonal building walls, dungeon corridors, etc. I don't believe I will be up to the task, but maybe it might provide an idea to other RL developers.
