(svn r5946) -Add: merged the TGP branch to mainline. TGP adds:
authortruelight
Sat, 19 Aug 2006 10:00:30 +0000
changeset 4300 c7e43c47a2b9
parent 4299 91f5d2bedcff
child 4301 848438a6cb16
(svn r5946) -Add: merged the TGP branch to mainline. TGP adds:
- New optional landscape generator (TerraGenesis Perlin)
- Load heightmaps (either BMP or PNG)
- Progress dialog while generating worlds (no longer a 'hanging' screen)
- New dialogs for NewGame, Create Scenario and Play Heightmap
- Easier to configure your landscape
- More things to configure (tree-placer, ..)
- Speedup of world generation
- New console command 'restart': restart the map EXACTLY as it was when you
first started it (needs a game made after or with this commit)
- New console command 'getseed': get the seed of your map and share it with
others (of course only works with generated maps)
- Many new, world generation related, things
- Many internal cleanups and rewrites
Many tnx to those people who helped making this:
Belugas, DaleStan, glx, KUDr, RichK67, Rubidium, and TrueLight (alfabetic)
Many tnx to those who helped testing:
Arnau, Bjarni, and tokai (alfabetic)
And to all other people who helped testing and sending comments / bugs
Stats: 673 lines changed, 3534 new lines, 79 new strings
Makefile
bmp.c
bmp.h
clear_cmd.c
command.c
console_cmds.c
engine.c
fios.c
fios.h
functions.h
genworld.c
genworld.h
genworld_gui.c
gfx.c
gui.h
heightmap.c
heightmap.h
industry_cmd.c
intro_gui.c
landscape.c
lang/english.txt
macros.h
main_gui.c
misc.c
misc_gui.c
network_gui.c
network_server.c
openttd.c
openttd.h
openttd.vcproj
openttd_vs80.vcproj
os/linux/openttd.spec
os/macosx/splash.c
os2.c
saveload.c
saveload.h
screenshot.c
settings.c
settings_gui.c
string.c
string.h
tgp.c
tgp.h
thread.c
thread.h
town_cmd.c
tree_cmd.c
unix.c
unmovable_cmd.c
variables.h
video/cocoa_v.m
video/dedicated_v.c
video/sdl_v.c
video/win32_v.c
win32.c
window.c
window.h
--- a/Makefile	Sat Aug 19 09:31:22 2006 +0000
+++ b/Makefile	Sat Aug 19 10:00:30 2006 +0000
@@ -639,6 +639,7 @@
 SRCS += airport.c
 SRCS += airport_gui.c
 SRCS += aystar.c
+SRCS += bmp.c
 SRCS += bridge_gui.c
 SRCS += bridge_map.c
 SRCS += callback_table.c
@@ -661,9 +662,12 @@
 SRCS += engine_gui.c
 SRCS += fileio.c
 SRCS += fios.c
+SRCS += genworld.c
+SRCS += genworld_gui.c
 SRCS += gfx.c
 SRCS += gfxinit.c
 SRCS += graph_gui.c
+SRCS += heightmap.c
 SRCS += industry_cmd.c
 SRCS += industry_gui.c
 SRCS += intro_gui.c
@@ -732,6 +736,7 @@
 SRCS += subsidy_gui.c
 SRCS += terraform_gui.c
 SRCS += texteff.c
+SRCS += tgp.c
 SRCS += thread.c
 SRCS += tile.c
 SRCS += town_cmd.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bmp.c	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,378 @@
+/* $Id$ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "gfx.h"
+#include "bmp.h"
+#include "macros.h"
+
+void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file) {
+	buffer->pos      = -1;
+	buffer->file     = file;
+	buffer->read     = 0;
+	buffer->real_pos = ftell(file);
+}
+
+static inline void AdvanceBuffer(BmpBuffer *buffer)
+{
+	buffer->read = fread(buffer->data, 1, BMP_BUFFER_SIZE, buffer->file);
+	buffer->pos  = 0;
+}
+
+static inline bool EndOfBuffer(BmpBuffer *buffer)
+{
+	if (buffer->pos == buffer->read || buffer->pos < 0) AdvanceBuffer(buffer);
+	return buffer->pos == buffer->read;
+}
+
+static inline byte ReadByte(BmpBuffer *buffer)
+{
+	if (buffer->pos == buffer->read || buffer->pos < 0) AdvanceBuffer(buffer);
+	buffer->real_pos++;
+	return buffer->data[buffer->pos++];
+}
+
+static inline uint16 ReadWord(BmpBuffer *buffer)
+{
+	uint16 var = ReadByte(buffer);
+	return var | (ReadByte(buffer) << 8);
+}
+
+static inline uint32 ReadDword(BmpBuffer *buffer)
+{
+	uint32 var = ReadWord(buffer);
+	return var | (ReadWord(buffer) << 16);
+}
+
+static inline void SkipBytes(BmpBuffer *buffer, int bytes)
+{
+	int i;
+	for (i = 0; i < bytes; i++) ReadByte(buffer);
+}
+
+static inline void SetStreamOffset(BmpBuffer *buffer, int offset)
+{
+	fseek(buffer->file, offset, SEEK_SET);
+	buffer->pos = -1;
+	buffer->real_pos = offset;
+	AdvanceBuffer(buffer);
+}
+
+/**
+ * Reads a 1 bpp uncompressed bitmap
+ * The bitmap is converted to a 8 bpp bitmap
+ */
+static inline bool BmpRead1(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
+{
+	uint x, y, i;
+	byte pad = GB(4 - info->width / 8, 0, 2);
+	byte *pixel_row;
+	byte b;
+	for (y = info->height; y > 0; y--) {
+		x = 0;
+		pixel_row = &data->bitmap[(y - 1) * info->width];
+		while (x < info->width) {
+			if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
+			b = ReadByte(buffer);
+			for (i = 8; i > 0; i--) {
+				if (x < info->width) *pixel_row++ = GB(b, i - 1, 1);
+				x++;
+			}
+		}
+		/* Padding for 32 bit align */
+		SkipBytes(buffer, pad);
+	}
+	return true;
+}
+
+/**
+ * Reads a 4 bpp uncompressed bitmap
+ * The bitmap is converted to a 8 bpp bitmap
+ */
+static inline bool BmpRead4(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
+{
+	uint x, y;
+	byte pad = GB(4 - info->width / 2, 0, 2);
+	byte *pixel_row;
+	byte b;
+	for (y = info->height; y > 0; y--) {
+		x = 0;
+		pixel_row = &data->bitmap[(y - 1) * info->width];
+		while (x < info->width) {
+			if (EndOfBuffer(buffer)) return false;  // the file is shorter than expected
+			b = ReadByte(buffer);
+			*pixel_row++ = GB(b, 4, 4);
+			x++;
+			if (x < info->width) {
+				*pixel_row++ = GB(b, 0, 4);
+				x++;
+			}
+		}
+		/* Padding for 32 bit align */
+		SkipBytes(buffer, pad);
+	}
+	return true;
+}
+
+/**
+ * Reads a 4-bit RLE compressed bitmap
+ * The bitmap is converted to a 8 bpp bitmap
+ */
+static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
+{
+	uint i;
+	uint x = 0;
+	uint y = info->height - 1;
+	byte n, c, b;
+	byte *pixel = &data->bitmap[y * info->width];
+	while (y != 0 || x < info->width) {
+		if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
+		n = ReadByte(buffer);
+		c = ReadByte(buffer);
+		if (n == 0) {
+			switch (c) {
+			case 0: // end of line
+				x = 0;
+				pixel = &data->bitmap[--y * info->width];
+				break;
+			case 1: // end of bitmap
+				x = info->width;
+				y = 0;
+				pixel = NULL;
+				break;
+			case 2: // delta
+				x += ReadByte(buffer);
+				i = ReadByte(buffer);
+				if (x >= info->width || (y == 0 && i > 0)) return false;
+				y -= i;
+				pixel = &data->bitmap[y * info->width + x];
+				break;
+			default: // uncompressed
+				i = 0;
+				while (i++ < c) {
+					if (EndOfBuffer(buffer) || x >= info->width) return false;
+					b = ReadByte(buffer);
+					*pixel++ = GB(b, 4, 4);
+					x++;
+					if (x < info->width && i++ < c) {
+						*pixel++ = GB(b, 0, 4);
+						x++;
+					}
+				}
+				/* Padding for 16 bit align */
+				SkipBytes(buffer, ((c + 1) / 2) % 2);
+				break;
+			}
+		} else {
+			i = 0;
+			while (i++ < n) {
+				if (EndOfBuffer(buffer) || x >= info->width) return false;
+				*pixel++ = GB(c, 4, 4);
+				x++;
+				if (x < info->width && i++ < n) {
+					*pixel++ = GB(c, 0, 4);
+					x++;
+				}
+			}
+		}
+	}
+	return true;
+}
+
+/**
+ * Reads a 8 bpp bitmap
+ */
+static inline bool BmpRead8(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
+{
+	uint i;
+	uint y;
+	byte pad = GB(4 - info->width, 0, 2);
+	byte *pixel;
+	for (y = info->height; y > 0; y--) {
+		if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
+		pixel = &data->bitmap[(y - 1) * info->width];
+		for (i = 0; i < info->width; i++) *pixel++ = ReadByte(buffer);
+		/* Padding for 32 bit align */
+		SkipBytes(buffer, pad);
+	}
+	return true;
+}
+
+/**
+ * Reads a 8-bit RLE compressed bpp bitmap
+ */
+static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
+{
+	uint i;
+	uint x = 0;
+	uint y = info->height - 1;
+	byte n, c;
+	byte *pixel = &data->bitmap[y * info->width];
+	while (y != 0 || x < info->width) {
+		if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
+		n = ReadByte(buffer);
+		c = ReadByte(buffer);
+		if (n == 0) {
+			switch (c) {
+			case 0: // end of line
+				x = 0;
+				pixel = &data->bitmap[--y * info->width];
+				break;
+			case 1: // end of bitmap
+				x = info->width;
+				y = 0;
+				pixel = NULL;
+				break;
+			case 2: // delta
+				x += ReadByte(buffer);
+				i = ReadByte(buffer);
+				if (x >= info->width || (y == 0 && i > 0)) return false;
+				y -= i;
+				pixel = &data->bitmap[y * info->width + x];
+				break;
+			default: // uncompressed
+				if ((x += c) > info->width) return false;
+				for (i = 0; i < c; i++) *pixel++ = ReadByte(buffer);
+				/* Padding for 16 bit align */
+				SkipBytes(buffer, c % 2);
+				break;
+			}
+		} else {
+			for (i = 0; i < n; i++) {
+				if (x >= info->width) return false;
+				*pixel++ = c;
+				x++;
+			}
+		}
+	}
+	return true;
+}
+
+/**
+ * Reads a 24 bpp uncompressed bitmap
+ */
+static inline bool BmpRead24(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
+{
+	uint x, y;
+	byte pad = GB(4 - info->width * 3, 0, 2);
+	byte *pixel_row;
+	for (y = info->height; y > 0; y--) {
+		pixel_row = &data->bitmap[(y - 1) * info->width * 3];
+		for (x = 0; x < info->width; x++) {
+			if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
+			*(pixel_row + 2) = ReadByte(buffer); // green
+			*(pixel_row + 1) = ReadByte(buffer); // blue
+			*pixel_row       = ReadByte(buffer); // red
+			pixel_row += 3;
+		}
+		/* Padding for 32 bit align */
+		SkipBytes(buffer, pad);
+	}
+	return true;
+}
+
+/*
+ * Reads bitmap headers, and palette (if any)
+ */
+bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
+{
+	uint32 header_size;
+	assert(info != NULL);
+
+	/* Reading BMP header */
+	if (ReadWord(buffer) != 0x4D42) return false; // signature should be 'BM'
+	SkipBytes(buffer, 8); // skip file size and reserved
+	info->offset = ReadDword(buffer);
+
+	/* Reading info header */
+	header_size = ReadDword(buffer);
+	if (header_size < 12) return false; // info header should be at least 12 bytes long
+
+	info->os2_bmp = (header_size == 12); // OS/2 1.x or windows 2.x info header is 12 bytes long
+
+	if (info->os2_bmp) {
+		info->width = ReadWord(buffer);
+		info->height = ReadWord(buffer);
+		header_size -= 8;
+	} else {
+		info->width = ReadDword(buffer);
+		info->height = ReadDword(buffer);
+		header_size -= 12;
+	}
+
+	if (ReadWord(buffer) != 1) return false; // BMP can have only 1 plane
+
+	info->bpp = ReadWord(buffer);
+	if (info->bpp != 1 && info->bpp != 4 && info->bpp != 8 && info->bpp != 24) {
+		/* Only 1 bpp, 4 bpp, 8bpp and 24 bpp bitmaps are supported */
+		return false;
+	}
+
+	/* Reads compression method if available in info header*/
+	if ((header_size -= 4) >= 4) {
+		info->compression = ReadDword(buffer);
+		header_size -= 4;
+	}
+
+	/* Only 4-bit and 8-bit rle compression is supported */
+	if (info->compression > 2 || (info->compression > 0 && !(info->bpp == 4 || info->bpp == 8))) return false;
+
+	if (info->bpp <= 8) {
+		uint i;
+
+		/* Reads number of colors if available in info header */
+		if (header_size >= 16) {
+			SkipBytes(buffer, 12);                  // skip image size and resolution
+			info->palette_size = ReadDword(buffer); // number of colors in palette
+			SkipBytes(buffer, header_size - 16);    // skip the end of info header
+		}
+		if (info->palette_size == 0) info->palette_size = 1 << info->bpp;
+
+		data->palette = calloc(info->palette_size, sizeof(*(data->palette)));
+		if (data->palette == NULL) return false;
+
+		for (i = 0; i < info->palette_size; i++) {
+			data->palette[i].b = ReadByte(buffer);
+			data->palette[i].g = ReadByte(buffer);
+			data->palette[i].r = ReadByte(buffer);
+			if (!info->os2_bmp) SkipBytes(buffer, 1); // unused
+		}
+	}
+
+	return buffer->real_pos <= info->offset;
+}
+
+/*
+ * Reads the bitmap
+ * 1 bpp and 4 bpp bitmaps are converted to 8 bpp bitmaps
+ */
+bool BmpReadBitmap(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
+{
+	assert(info != NULL && data != NULL);
+
+	data->bitmap = calloc(info->width * info->height, ((info->bpp == 24) ? 3 : 1) * sizeof(byte));
+	if (data->bitmap == NULL) return false;
+
+	/* Load image */
+	SetStreamOffset(buffer, info->offset);
+	switch (info->compression) {
+	case 0: // no compression
+		switch (info->bpp) {
+		case 1:  return BmpRead1(buffer, info, data);
+		case 4:  return BmpRead4(buffer, info, data);
+		case 8:  return BmpRead8(buffer, info, data);
+		case 24: return BmpRead24(buffer, info, data);
+		default: NOT_REACHED(); return false;
+		}
+	case 1:  return BmpRead8Rle(buffer, info, data); // 8-bit RLE compression
+	case 2:  return BmpRead4Rle(buffer, info, data); // 4-bit RLE compression
+	default: NOT_REACHED(); return false;
+	}
+}
+
+void BmpDestroyData(BmpData *data)
+{
+	assert(data != NULL);
+	free(data->palette);
+	free(data->bitmap);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bmp.h	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,36 @@
+/* $Id$ */
+
+#ifndef BMP_H
+#define BMP_H
+
+typedef struct {
+	uint32 offset;       ///< offset of bitmap data from .bmp file begining
+	uint32 width;        ///< bitmap width
+	uint32 height;       ///< bitmap height
+	bool os2_bmp;        ///< true if OS/2 1.x or windows 2.x bitmap
+	uint16 bpp;          ///< bits per pixel
+	uint32 compression;  ///< compression method (0 = none, 1 = 8-bit RLE, 2 = 4-bit RLE)
+	uint32 palette_size; ///< number of colors in palette
+} BmpInfo;
+
+typedef struct {
+	Colour *palette;
+	byte   *bitmap;
+} BmpData;
+
+#define BMP_BUFFER_SIZE 1024
+
+typedef struct {
+	byte data[BMP_BUFFER_SIZE];
+	int pos;
+	int read;
+	FILE *file;
+	uint real_pos;
+} BmpBuffer;
+
+void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file);
+bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data);
+bool BmpReadBitmap(BmpBuffer *buffer, BmpInfo *info, BmpData *data);
+void BmpDestroyData(BmpData *data);
+
+#endif /* BMP_H */
--- a/clear_cmd.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/clear_cmd.c	Sat Aug 19 10:00:30 2006 +0000
@@ -15,6 +15,7 @@
 #include "variables.h"
 #include "table/sprites.h"
 #include "unmovable_map.h"
+#include "genworld.h"
 
 typedef struct TerraformerHeightMod {
 	TileIndex tile;
@@ -693,22 +694,28 @@
 
 void GenerateClearTile(void)
 {
-	uint i;
+	uint i, gi;
 	TileIndex tile;
 
-	/* add hills */
+	/* add rough tiles */
 	i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
+	gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
+
+	SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
 	do {
+		IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
 		tile = RandomTile();
-		if (IsTileType(tile, MP_CLEAR)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
+		if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
 	} while (--i);
 
-	/* add grey squares */
-	i = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
+	/* add rocky tiles */
+	i = gi;
 	do {
 		uint32 r = Random();
 		tile = RandomTileSeed(r);
-		if (IsTileType(tile, MP_CLEAR)) {
+
+		IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
+		if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
 			uint j = GB(r, 16, 4) + 5;
 			for (;;) {
 				TileIndex tile_new;
@@ -717,7 +724,7 @@
 				do {
 					if (--j == 0) goto get_out;
 					tile_new = tile + TileOffsByDir(GB(Random(), 0, 2));
-				} while (!IsTileType(tile_new, MP_CLEAR));
+				} while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
 				tile = tile_new;
 			}
 get_out:;
--- a/command.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/command.c	Sat Aug 19 10:00:30 2006 +0000
@@ -10,6 +10,7 @@
 #include "player.h"
 #include "network.h"
 #include "variables.h"
+#include "genworld.h"
 
 const char* _cmd_text = NULL;
 
@@ -456,7 +457,7 @@
 	_docommand_recursive = 1;
 
 	// cost estimation only?
-	if (_shift_pressed && IsLocalPlayer() && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
+	if (!IsGeneratingWorld() && _shift_pressed && IsLocalPlayer() && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
 		// estimate the cost.
 		res = proc(tile, flags, p1, p2);
 		if (CmdFailed(res)) {
--- a/console_cmds.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/console_cmds.c	Sat Aug 19 10:00:30 2006 +0000
@@ -20,6 +20,7 @@
 #include "station.h"
 #include "strings.h"
 #include "screenshot.h"
+#include "genworld.h"
 #include "date.h"
 
 #ifdef ENABLE_NETWORK
@@ -871,17 +872,44 @@
 	return true;
 }
 
-extern void SwitchMode(int new_mode);
-
 DEF_CONSOLE_CMD(ConNewGame)
 {
 	if (argc == 0) {
-		IConsoleHelp("Start a new game. Usage: 'newgame'");
-		IConsoleHelp("The server can force a new game using 'newgame', any client using it will part and start a single-player game");
+		IConsoleHelp("Start a new game. Usage: 'newgame [seed]'");
+		IConsoleHelp("The server can force a new game using 'newgame'; any client joined will rejoin after the server is done generating the new game.");
 		return true;
 	}
 
-	GenRandomNewGame(Random(), InteractiveRandom());
+	StartNewGameWithoutGUI((argc == 2) ? (uint)atoi(argv[1]) : GENERATE_NEW_SEED);
+	return true;
+}
+
+extern void SwitchMode(int new_mode);
+
+DEF_CONSOLE_CMD(ConRestart)
+{
+	if (argc == 0) {
+		IConsoleHelp("Restart game. Usage: 'restart'");
+		IConsoleHelp("Restarts a game. It tries to reproduce the exact same map as the game started with.");
+		return true;
+	}
+
+	/* Don't copy the _newgame pointers to the real pointers, so call SwitchMode directly */
+	_patches.map_x = MapLogX();
+	_patches.map_y = FindFirstBit(MapSizeY());
+	SwitchMode(SM_NEWGAME);
+	return true;
+}
+
+DEF_CONSOLE_CMD(ConGetSeed)
+{
+	if (argc == 0) {
+		IConsoleHelp("Returns the seed used to create this game. Usage: 'getseed'");
+		IConsoleHelp("The seed can be used to reproduce the exact same map as the game started with.");
+		return true;
+	}
+
+	IConsolePrintF(_icolour_def, "Generation Seed: %u", _patches.generation_seed);
 	return true;
 }
 
@@ -1413,6 +1441,8 @@
 	IConsoleCmdRegister("list_vars",    ConListVariables);
 	IConsoleCmdRegister("list_aliases", ConListAliases);
 	IConsoleCmdRegister("newgame",      ConNewGame);
+	IConsoleCmdRegister("restart",      ConRestart);
+	IConsoleCmdRegister("getseed",      ConGetSeed);
 	IConsoleCmdRegister("quit",         ConExit);
 	IConsoleCmdRegister("resetengines", ConResetEngines);
 	IConsoleCmdRegister("return",       ConReturn);
--- a/engine.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/engine.c	Sat Aug 19 10:00:30 2006 +0000
@@ -30,6 +30,10 @@
 	ENGINE_PREVIEWING = 4,
 };
 
+enum {
+	YEAR_ENGINE_AGING_STOPS = 2050,
+};
+
 /** Bitmasked values of what type of cargo is refittable for the given vehicle-type.
  * This coupled with the landscape information (_landscape_global_cargo_mask) gives
  * us exactly what is refittable and what is not */
@@ -135,6 +139,8 @@
 {
 	Engine *e;
 	const EngineInfo *ei;
+	/* Aging of vehicles stops, so account for that when starting late */
+	const uint16 aging_date = min(_date, ConvertYMDToDate(YEAR_ENGINE_AGING_STOPS, 0, 1));
 
 	SetupEngineNames();
 
@@ -152,7 +158,7 @@
 		r = Random();
 		e->intro_date = ei->base_intro <= ConvertYMDToDate(1922, 0, 1) ? ei->base_intro : (Date)GB(r, 0, 9) + ei->base_intro;
 		if (e->intro_date <= _date) {
-			e->age = (_date - e->intro_date) >> 5;
+			e->age = (aging_date - e->intro_date) >> 5;
 			e->player_avail = (byte)-1;
 			e->flags |= ENGINE_AVAILABLE;
 		}
@@ -237,7 +243,7 @@
 {
 	EngineID i;
 
-	if (_cur_year >= 2050) return;
+	if (_cur_year >= YEAR_ENGINE_AGING_STOPS) return;
 
 	for (i = 0; i != lengthof(_engines); i++) {
 		Engine *e = &_engines[i];
@@ -358,7 +364,7 @@
 {
 	Engine *e;
 
-	if (_cur_year < 2050) {
+	if (_cur_year < YEAR_ENGINE_AGING_STOPS) {
 		for (e = _engines; e != endof(_engines); e++) {
 			// Age the vehicle
 			if (e->flags & ENGINE_AVAILABLE && e->age != 0xFFFF) {
--- a/fios.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/fios.c	Sat Aug 19 10:00:30 2006 +0000
@@ -10,6 +10,7 @@
 #include "string.h"
 #include "variables.h"
 #include "functions.h"
+#include "heightmap.h"
 #include "table/strings.h"
 #include "fios.h"
 #include <sys/types.h>
@@ -135,7 +136,10 @@
 	case FIOS_TYPE_FILE:
 	case FIOS_TYPE_OLDFILE:
 	case FIOS_TYPE_SCENARIO:
-	case FIOS_TYPE_OLD_SCENARIO: {
+	case FIOS_TYPE_OLD_SCENARIO:
+	case FIOS_TYPE_PNG:
+	case FIOS_TYPE_BMP:
+	{
 		static char str_buffr[512];
 
 #if defined(__MORPHOS__) || defined(__AMIGAOS__)
@@ -357,15 +361,45 @@
  */
 FiosItem *FiosGetScenarioList(int mode)
 {
-	static char *fios_scn_path = NULL;
+	static char *_fios_scn_path = NULL;
 
-	/* Copy the default path on first run or on 'New Game' */
-	if (mode == SLD_NEW_GAME || fios_scn_path == NULL) {
-		if (fios_scn_path == NULL) fios_scn_path = malloc(MAX_PATH);
-		ttd_strlcpy(fios_scn_path, _path.scenario_dir, MAX_PATH);
+	if (_fios_scn_path == NULL) {
+		_fios_scn_path = malloc(MAX_PATH);
+		ttd_strlcpy(_fios_scn_path, _path.scenario_dir, MAX_PATH);
 	}
 
-	_fios_path = fios_scn_path;
+	_fios_path = _fios_scn_path;
 
 	return FiosGetFileList(mode, &FiosGetScenarioListCallback);
 }
+
+static byte FiosGetHeightmapListCallback(int mode, const char *file, const char *ext, char *title)
+{
+	/* Show heightmap files
+	 * .PNG PNG Based heightmap files
+	 * .BMP BMP Based heightmap files
+	 */
+
+#ifdef WITH_PNG
+	if (strcasecmp(ext, ".png") == 0) return FIOS_TYPE_PNG;
+#endif /* WITH_PNG */
+
+	if (strcasecmp(ext, ".bmp") == 0) return FIOS_TYPE_BMP;
+
+	return FIOS_TYPE_INVALID;
+}
+
+// Get a list of Heightmaps
+FiosItem *FiosGetHeightmapList(int mode)
+{
+	static char *_fios_hmap_path = NULL;
+
+	if (_fios_hmap_path == NULL) {
+		_fios_hmap_path = malloc(MAX_PATH);
+		strcpy(_fios_hmap_path, _path.heightmap_dir);
+	}
+
+	_fios_path = _fios_hmap_path;
+
+	return FiosGetFileList(mode, &FiosGetHeightmapListCallback);
+}
--- a/fios.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/fios.h	Sat Aug 19 10:00:30 2006 +0000
@@ -20,6 +20,8 @@
 	FIOS_TYPE_SCENARIO = 5,
 	FIOS_TYPE_OLD_SCENARIO = 6,
 	FIOS_TYPE_DIRECT = 7,
+	FIOS_TYPE_PNG = 8,
+	FIOS_TYPE_BMP = 9,
 	FIOS_TYPE_INVALID = 255,
 };
 
@@ -32,6 +34,8 @@
 FiosItem *FiosGetSavegameList(int mode);
 // Get a list of scenarios
 FiosItem *FiosGetScenarioList(int mode);
+// Get a list of Heightmaps
+FiosItem *FiosGetHeightmapList(int mode);
 // Free the list of savegames
 void FiosFreeSavegameList(void);
 // Browse to. Returns a filename w/path if we reached a file.
--- a/functions.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/functions.h	Sat Aug 19 10:00:30 2006 +0000
@@ -204,8 +204,6 @@
 
 void AfterLoadTown(void);
 void UpdatePatches(void);
-void GenRandomNewGame(uint32 rnd1, uint32 rnd2);
-void StartScenarioEditor(uint32 rnd1, uint32 rnd2);
 void AskExitGame(void);
 void AskExitToGameMenu(void);
 
@@ -216,11 +214,12 @@
 void UpdateViewportSignPos(ViewportSign *sign, int left, int top, StringID str);
 
 enum {
-	SLD_LOAD_GAME = 0,
-	SLD_LOAD_SCENARIO = 1,
-	SLD_SAVE_GAME = 2,
-	SLD_SAVE_SCENARIO = 3,
-	SLD_NEW_GAME = 4,
+	SLD_LOAD_GAME,
+	SLD_LOAD_SCENARIO,
+	SLD_SAVE_GAME,
+	SLD_SAVE_SCENARIO,
+	SLD_LOAD_HEIGHTMAP,
+	SLD_NEW_GAME,
 };
 void ShowSaveLoadDialog(int mode);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genworld.c	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,273 @@
+/* $Id$ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "functions.h"
+#include "player.h"
+#include "table/sprites.h"
+#include "variables.h"
+#include "thread.h"
+#include "genworld.h"
+#include "gfx.h"
+#include "gfxinit.h"
+#include "gui.h"
+#include "network.h"
+#include "debug.h"
+#include "settings.h"
+#include "heightmap.h"
+
+void GenerateLandscape(byte mode);
+void GenerateClearTile(void);
+void GenerateIndustries(void);
+void GenerateUnmovables(void);
+bool GenerateTowns(void);
+void GenerateTrees(void);
+
+void StartupEconomy(void);
+void StartupPlayers(void);
+void StartupDisasters(void);
+
+void InitializeGame(int mode, uint size_x, uint size_y);
+
+void ConvertGroundTilesIntoWaterTiles(void);
+
+/* Please only use this variable in genworld.h and genworld.c and
+ *  nowhere else. For speed improvements we need it to be global, but
+ *  in no way the meaning of it is to use it anywhere else besides
+ *  in the genworld.h and genworld.c! -- TrueLight */
+gw_info _gw;
+
+/**
+ * Set the status of the Paint flag.
+ *  If it is true, the thread will hold with any futher generating till
+ *  the drawing of the screen is done. This is handled by
+ *  SetGeneratingWorldProgress(), so calling that function will stall
+ *  from time to time.
+ */
+void SetGeneratingWorldPaintStatus(bool status)
+{
+	_gw.wait_for_draw = status;
+}
+
+/**
+ * Returns true if the thread wants the main program to do a (full) paint.
+ *  If this returns false, please do not update the screen. Because we are
+ *  writing in a thread, it can cause damaged data (reading and writing the
+ *  same tile at the same time).
+ */
+bool IsGeneratingWorldReadyForPaint(void)
+{
+	/* If we are in quit_thread mode, ignore this and always return false. This
+	 *  forces the screen to not be drawn, and the GUI not to wait for a draw. */
+	if (!_gw.active || _gw.quit_thread || !_gw.threaded) return false;
+
+	return _gw.wait_for_draw;
+}
+
+/**
+ * Tells if the world generation is done in a thread or not.
+ */
+bool IsGenerateWorldThreaded(void)
+{
+	return _gw.threaded && !_gw.quit_thread;
+}
+
+/**
+ * The internal, real, generate function.
+ */
+static void *_GenerateWorld(void *arg)
+{
+	_generating_world = true;
+	if (_network_dedicated) DEBUG(net, 0)("Generating map, please wait...");
+	/* Set the Random() seed to generation_seed so we produce the same map with the same seed */
+	if (_patches.generation_seed == GENERATE_NEW_SEED) _patches.generation_seed = _patches_newgame.generation_seed = InteractiveRandom();
+	_random_seeds[0][0] = _random_seeds[0][1] = _patches.generation_seed;
+	SetGeneratingWorldProgress(GWP_MAP_INIT, 2);
+	SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0);
+
+	IncreaseGeneratingWorldProgress(GWP_MAP_INIT);
+	// Must start economy early because of the costs.
+	StartupEconomy();
+
+	// Don't generate landscape items when in the scenario editor.
+	if (_gw.mode == GW_EMPTY) {
+		SetGeneratingWorldProgress(GWP_UNMOVABLE, 1);
+
+		/* Make the map the height of the patch setting */
+		if (_game_mode != GM_MENU) FlatEmptyWorld(_patches.se_flat_world_height);
+
+		ConvertGroundTilesIntoWaterTiles();
+		IncreaseGeneratingWorldProgress(GWP_UNMOVABLE);
+	} else {
+		GenerateLandscape(_gw.mode);
+		GenerateClearTile();
+
+		// only generate towns, tree and industries in newgame mode.
+		if (_game_mode != GM_EDITOR) {
+			GenerateTowns();
+			GenerateIndustries();
+			GenerateUnmovables();
+			GenerateTrees();
+		}
+	}
+
+	// These are probably pointless when inside the scenario editor.
+	SetGeneratingWorldProgress(GWP_GAME_INIT, 3);
+	StartupPlayers();
+	IncreaseGeneratingWorldProgress(GWP_GAME_INIT);
+	StartupEngines();
+	IncreaseGeneratingWorldProgress(GWP_GAME_INIT);
+	StartupDisasters();
+	_generating_world = false;
+
+	// No need to run the tile loop in the scenario editor.
+	if (_gw.mode != GW_EMPTY) {
+		uint i;
+
+		SetGeneratingWorldProgress(GWP_RUNTILELOOP, 0x500);
+		for (i = 0; i < 0x500; i++) {
+			RunTileLoop();
+			IncreaseGeneratingWorldProgress(GWP_RUNTILELOOP);
+		}
+	}
+
+	ResetObjectToPlace();
+	_local_player = _gw.lp;
+
+	SetGeneratingWorldProgress(GWP_GAME_START, 1);
+	/* Call any callback */
+	if (_gw.proc != NULL) _gw.proc();
+	IncreaseGeneratingWorldProgress(GWP_GAME_START);
+
+	if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE);
+	/* Show all vital windows again, because we have hidden them */
+	if (_gw.threaded) ShowVitalWindows();
+	_gw.active   = false;
+	_gw.thread   = NULL;
+	_gw.proc     = NULL;
+	_gw.threaded = false;
+
+	DeleteWindowById(WC_GENERATE_PROGRESS_WINDOW, 0);
+	MarkWholeScreenDirty();
+
+	if (_network_dedicated) DEBUG(net, 0)("Map generated, starting game");
+
+	return NULL;
+}
+
+/**
+ * Set here the function, if any, that you want to be called when landscape
+ *  generation is done.
+ */
+void GenerateWorldSetCallback(gw_done_proc *proc)
+{
+	_gw.proc = proc;
+}
+
+/**
+ * This will wait for the thread to finish up his work. It will not continue
+ *  till the work is done.
+ */
+void WaitTillGeneratedWorld(void)
+{
+	if (_gw.thread == NULL) return;
+	_gw.quit_thread = true;
+	OTTDJoinThread(_gw.thread);
+	_gw.thread   = NULL;
+	_gw.threaded = false;
+}
+
+/**
+ * Initializes the abortion process
+ */
+void AbortGeneratingWorld(void)
+{
+	_gw.abort = true;
+}
+
+/**
+ * Is the generation being aborted?
+ */
+bool IsGeneratingWorldAborted(void)
+{
+	return _gw.abort;
+}
+
+/**
+ * Really handle the abortion, i.e. clean up some of the mess
+ */
+void HandleGeneratingWorldAbortion(void)
+{
+	/* Clean up - in SE create an empty map, otherwise, go to intro menu */
+	_switch_mode = (_game_mode == GM_EDITOR) ? SM_EDITOR : SM_MENU;
+
+	if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE);
+	/* Show all vital windows again, because we have hidden them */
+	if (_gw.threaded) ShowVitalWindows();
+	_gw.active   = false;
+	_gw.thread   = NULL;
+	_gw.proc     = NULL;
+	_gw.threaded = false;
+
+	DeleteWindowById(WC_GENERATE_PROGRESS_WINDOW, 0);
+	MarkWholeScreenDirty();
+
+	OTTDExitThread();
+}
+
+/**
+ * Generate a world.
+ * @param mode The mode of world generation (@see GenerateWorldModes).
+ * @param size_x The X-size of the map.
+ * @param size_y The Y-size of the map.
+ */
+void GenerateWorld(int mode, uint size_x, uint size_y)
+{
+	if (_gw.active) return;
+	_gw.mode   = mode;
+	_gw.size_x = size_x;
+	_gw.size_y = size_y;
+	_gw.active = true;
+	_gw.abort  = false;
+	_gw.lp     = _local_player;
+	_gw.wait_for_draw = false;
+	_gw.quit_thread   = false;
+	_gw.threaded      = true;
+
+	/* This disables some commands and stuff */
+	_local_player   = OWNER_SPECTATOR;
+	/* Make sure everything is done via OWNER_NONE */
+	_current_player = OWNER_NONE;
+
+	InitializeGame(IG_DATE_RESET, _gw.size_x, _gw.size_y);
+	PrepareGenerateWorldProgress();
+
+	/* Re-init the windowing system */
+	ResetWindowSystem();
+	LoadStringWidthTable();
+
+	/* Create toolbars */
+	SetupColorsAndInitialWindow();
+
+	if (_network_dedicated || (_gw.thread = OTTDCreateThread(&_GenerateWorld, (void *)"")) == NULL) {
+		_gw.threaded = false;
+		_GenerateWorld(NULL);
+	} else {
+		/* Remove any open window */
+		DeleteAllNonVitalWindows();
+
+		/* Don't show the dialog if we don't have a thread */
+		ShowGenerateWorldProgress();
+	}
+
+	/* Zoom out and center on the map (is pretty ;)) */
+	if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) {
+		while (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0) ) ) {}
+		ScrollMainWindowToTile(TileXY(MapSizeX() / 2, MapSizeY() / 2));
+	}
+
+	/* Hide vital windows, because we don't allow to use them */
+	/* XXX -- Ideal it is done after ShowGenerateWorldProgress, but stupid
+	 * enough, DoZoomInOutWindow _needs_ the toolbar to exist... */
+	if (_gw.thread != NULL) HideVitalWindows();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genworld.h	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,91 @@
+/* $Id$ */
+
+#ifndef GENWORLD_H
+#define GENWORLD_H
+
+/* If OTTDThread isn't defined, define it to a void, but make sure to undefine
+ *  it after this include. This makes including genworld.h easier, as you
+ *  don't need to include thread.h before it, while it stays possible to
+ *  include it after it, and still work.
+ */
+#ifndef OTTDThread
+#define TEMPORARY_OTTDTHREAD_DEFINITION
+#define OTTDThread void
+#endif
+
+/*
+ * Order of these enums has to be the same as in lang/english.txt
+ * Otherwise you will get inconsistent behaviour.
+ */
+enum {
+	LG_ORIGINAL     = 0,  //! The original landscape generator
+	LG_TERRAGENESIS = 1,  //! TerraGenesis Perlin landscape generator
+
+	GENERATE_NEW_SEED = (uint)-1, //! Create a new random seed
+};
+
+typedef void gw_done_proc(void);
+
+typedef struct gw_info {
+	bool active;           //! Is generating world active
+	bool abort;            //! Whether to abort the thread ASAP
+	bool wait_for_draw;    //! Are we waiting on a draw event
+	bool quit_thread;      //! Do we want to quit the active thread
+	bool threaded;         //! Whether we run _GenerateWorld threaded
+	int mode;              //! What mode are we making a world in
+	byte lp;               //! The local_player before generating
+	uint size_x;           //! X-size of the map
+	uint size_y;           //! Y-size of the map
+	gw_done_proc *proc;    //! Proc that is called when done (can be NULL)
+	OTTDThread *thread;    //! The thread we are in (can be NULL)
+} gw_info;
+
+#ifdef TEMPORARY_OTTDTHREAD_DEFINITION
+#undef OTTDThread
+#undef TEMPORARY_OTTDTHREAD_DEFINITION
+#endif
+
+typedef enum gwp_classes {
+	GWP_MAP_INIT,    /* Initialize/allocate the map, start economy */
+	GWP_LANDSCAPE,   /* Create the landscape */
+	GWP_ROUGH_ROCKY, /* Make rough and rocky areas */
+	GWP_TOWN,        /* Generate towns */
+	GWP_INDUSTRY,    /* Generate industries */
+	GWP_UNMOVABLE,   /* Generate unmovables (radio tower, light houses) */
+	GWP_TREE,        /* Generate trees */
+	GWP_GAME_INIT,   /* Initialize the game */
+	GWP_RUNTILELOOP, /* Runs the tile loop 1280 times to make snow etc */
+	GWP_GAME_START,  /* Really prepare to start the game */
+	GWP_CLASS_COUNT
+} gwp_class;
+
+/**
+ * Check if we are currently in the process of generating a world.
+ */
+static inline bool IsGeneratingWorld(void)
+{
+	extern gw_info _gw;
+
+	return _gw.active;
+}
+
+/* genworld.c */
+void SetGeneratingWorldPaintStatus(bool status);
+bool IsGeneratingWorldReadyForPaint(void);
+bool IsGenerateWorldThreaded(void);
+void GenerateWorldSetCallback(gw_done_proc *proc);
+void WaitTillGeneratedWorld(void);
+void GenerateWorld(int mode, uint size_x, uint size_y);
+void AbortGeneratingWorld(void);
+bool IsGeneratingWorldAborted(void);
+void HandleGeneratingWorldAbortion(void);
+
+/* genworld_gui.c */
+void SetGeneratingWorldProgress(gwp_class class, uint total);
+void IncreaseGeneratingWorldProgress(gwp_class class);
+void PrepareGenerateWorldProgress(void);
+void ShowGenerateWorldProgress(void);
+void StartNewGameWithoutGUI(uint seed);
+void ShowCreateScenario(void);
+
+#endif /* GENWORLD_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genworld_gui.c	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,912 @@
+/* $Id$ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "heightmap.h"
+#include "functions.h"
+#include "table/strings.h"
+#include "window.h"
+#include "gui.h"
+#include "gfx.h"
+#include "strings.h"
+#include "gfxinit.h"
+#include "player.h"
+#include "command.h"
+#include "sound.h"
+#include "variables.h"
+#include "string.h"
+#include "settings.h"
+#include "debug.h"
+#include "genworld.h"
+#include "network.h"
+#include "thread.h"
+#include "date.h"
+
+enum {
+	START_DATE_QUERY,
+	SNOW_LINE_QUERY,
+	FLAT_WORLD_HEIGHT_QUERY,
+
+	LEN_RND_SEED = 11,
+	SEED_EDIT    = 15,
+};
+
+/**
+ * In what 'mode' the GenerateLandscapeWindowProc is.
+ */
+typedef enum glwp_modes {
+	GLWP_GENERATE,
+	GLWP_HEIGHTMAP,
+	GLWP_SCENARIO,
+	GLWP_END
+} glwp_modes;
+
+static char _edit_str_buf[LEN_RND_SEED];
+static uint _heightmap_x = 0;
+static uint _heightmap_y = 0;
+static StringID _heightmap_str = STR_NULL;
+static bool _goto_editor = false;
+
+extern void SwitchMode(int new_mode);
+
+static inline void SetNewLandscapeType(byte landscape)
+{
+	_opt_newgame.landscape = landscape;
+	InvalidateWindowClasses(WC_SELECT_GAME);
+	InvalidateWindowClasses(WC_GENERATE_LANDSCAPE);
+}
+
+// no longer static to allow calling from outside module
+const Widget _generate_landscape_widgets[] = {
+{  WWT_CLOSEBOX,  RESIZE_NONE, 13,   0,  10,   0,  13, STR_00C5,                STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION, RESIZE_NONE, 13,  11, 337,   0,  13, STR_WORLD_GENERATION_CAPTION,STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 13,   0, 337,  14, 267, STR_NULL,                STR_NULL},
+
+{    WWT_PANEL_2, RESIZE_NONE, 12,  10,  86,  24,  78, 0x1312,                  STR_030E_SELECT_TEMPERATE_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12,  90, 166,  24,  78, 0x1314,                  STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12, 170, 246,  24,  78, 0x1316,                  STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12, 250, 326,  24,  78, 0x1318,                  STR_0311_SELECT_TOYLAND_LANDSCAPE},
+
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 149,  90, 101, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 150, 161,  90, 101, STR_0225,                STR_NULL}, // Mapsize X
+{      WWT_PANEL, RESIZE_NONE, 12, 180, 215,  90, 101, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 216, 227,  90, 101, STR_0225,                STR_NULL}, // Mapsize Y
+
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 163, 112, 123, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 112, 123, STR_0225,                STR_NULL}, // Number of towns
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 163, 130, 141, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 130, 141, STR_0225,                STR_NULL}, // Number of industries
+
+{     WWT_IMGBTN, RESIZE_NONE, 15, 114, 194, 152, 163, STR_NULL,                STR_RANDOM_SEED_HELP}, // Edit box for seed
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 203, 285, 152, 163, STR_RANDOM,              STR_RANDOM_HELP},
+
+{    WWT_TEXTBTN, RESIZE_NONE,  6, 243, 326, 228, 257, STR_GENERATE,            STR_NULL}, // Generate button
+
+{     WWT_IMGBTN, RESIZE_NONE, 12, 216, 227, 112, 123, SPR_ARROW_DOWN,          STR_029E_MOVE_THE_STARTING_DATE},
+{      WWT_PANEL, RESIZE_NONE, 12, 228, 314, 112, 123, 0x0,                     STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 112, 123, SPR_ARROW_UP,            STR_029F_MOVE_THE_STARTING_DATE},
+
+{     WWT_IMGBTN, RESIZE_NONE, 12, 282, 293, 130, 141, SPR_ARROW_DOWN,          STR_SNOW_LINE_DOWN},
+{      WWT_PANEL, RESIZE_NONE, 12, 294, 314, 130, 141, 0x0,                     STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 130, 141, SPR_ARROW_UP,            STR_SNOW_LINE_UP},
+
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 219, 192, 203, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 192, 203, STR_0225,                STR_NULL}, // Tree placer
+
+{      WWT_EMPTY, RESIZE_NONE, 12, 114, 231, 174, 185, STR_NULL,                STR_NULL},
+//{      WWT_PANEL, RESIZE_NONE, 12, 114, 219, 174, 185, STR_NULL,                STR_NULL},
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 231, 174, 185, STR_NULL,                STR_NULL},
+//{    WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 174, 185, STR_0225,                STR_NULL}, // Landscape generator
+//{      WWT_PANEL, RESIZE_NONE, 12, 114, 219, 210, 221, STR_NULL,                STR_NULL},
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 231, 210, 221, STR_NULL,                STR_NULL},
+//{    WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 210, 221, STR_0225,                STR_NULL}, // Terrain type
+//{      WWT_PANEL, RESIZE_NONE, 12, 114, 219, 228, 239, STR_NULL,                STR_NULL},
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 231, 228, 239, STR_NULL,                STR_NULL},
+//{    WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 228, 239, STR_0225,                STR_NULL}, // Water quantity
+{      WWT_PANEL, RESIZE_NONE, 12, 113, 219, 246, 257, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 246, 257, STR_0225,                STR_NULL}, // Map smoothness
+{   WIDGETS_END},
+};
+
+const Widget _heightmap_load_widgets[] = {
+{   WWT_CLOSEBOX, RESIZE_NONE, 13,   0,  10,   0,  13, STR_00C5,                STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION, RESIZE_NONE, 13,  11, 337,   0,  13, STR_WORLD_GENERATION_CAPTION,STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 13,   0, 337,  14, 235, STR_NULL,                STR_NULL},
+
+{    WWT_PANEL_2, RESIZE_NONE, 12,  10,  86,  24,  78, 0x1312,                  STR_030E_SELECT_TEMPERATE_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12,  90, 166,  24,  78, 0x1314,                  STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12, 170, 246,  24,  78, 0x1316,                  STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12, 250, 326,  24,  78, 0x1318,                  STR_0311_SELECT_TOYLAND_LANDSCAPE},
+
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 149, 112, 123, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 150, 161, 112, 123, STR_0225,                STR_NULL}, // Mapsize X
+{      WWT_PANEL, RESIZE_NONE, 12, 180, 215, 112, 123, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 216, 227, 112, 123, STR_0225,                STR_NULL}, // Mapsize Y
+
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 163, 134, 145, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 134, 145, STR_0225,                STR_NULL}, // Number of towns
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 163, 152, 163, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 152, 163, STR_0225,                STR_NULL}, // Number of industries
+
+{     WWT_IMGBTN, RESIZE_NONE, 15, 114, 194, 174, 185, STR_NULL,                STR_RANDOM_SEED_HELP}, // Edit box for seed
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 203, 285, 174, 185, STR_RANDOM,              STR_RANDOM_HELP},
+
+{    WWT_TEXTBTN, RESIZE_NONE,  6, 243, 326, 196, 225, STR_GENERATE,            STR_NULL}, // Generate button
+
+{     WWT_IMGBTN, RESIZE_NONE, 12, 216, 227, 134, 145, SPR_ARROW_DOWN,          STR_029E_MOVE_THE_STARTING_DATE},
+{      WWT_PANEL, RESIZE_NONE, 12, 228, 314, 134, 145, 0x0,                     STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 134, 145, SPR_ARROW_UP,            STR_029F_MOVE_THE_STARTING_DATE},
+
+{     WWT_IMGBTN, RESIZE_NONE, 12, 282, 293, 152, 163, SPR_ARROW_DOWN,          STR_SNOW_LINE_DOWN},
+{      WWT_PANEL, RESIZE_NONE, 12, 294, 314, 152, 163, 0x0,                     STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 152, 163, SPR_ARROW_UP,            STR_SNOW_LINE_UP},
+
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 219, 196, 207, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 196, 207, STR_0225,                STR_NULL}, // Tree placer
+
+{      WWT_PANEL, RESIZE_NONE, 12, 114, 219, 214, 225, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 214, 225, STR_0225,                STR_NULL}, // Heightmap rotation
+{   WIDGETS_END},
+};
+
+static void StartGeneratingLandscape(glwp_modes mode)
+{
+	/* If we want to go to the editor, and aren't yet, we need to delay
+	 *  it as long as possible, else it gives nasty side-effects (aborting
+	 *  results in ending up in the SE, which you don't want. Therefor we
+	 *  use this switch to do it at the very end.
+	 */
+	if (_goto_editor) _game_mode = GM_EDITOR;
+
+	DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
+	DeleteWindowByClass(WC_INDUSTRY_VIEW);
+	DeleteWindowByClass(WC_TOWN_VIEW);
+	DeleteWindowByClass(WC_LAND_INFO);
+
+	/* Copy all XXX_newgame to XXX */
+	UpdatePatches();
+	_opt_ptr = &_opt;
+	memcpy(_opt_ptr, &_opt_newgame, sizeof(GameOptions));
+	/* Load the right landscape stuff */
+	GfxLoadSprites();
+
+	SndPlayFx(SND_15_BEEP);
+	switch (mode) {
+	case GLWP_GENERATE:  _switch_mode = (_game_mode == GM_EDITOR) ? SM_GENRANDLAND    : SM_NEWGAME;         break;
+	case GLWP_HEIGHTMAP: _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_HEIGHTMAP : SM_START_HEIGHTMAP; break;
+	case GLWP_SCENARIO:  _switch_mode = SM_EDITOR; break;
+	default: NOT_REACHED(); return;
+	}
+}
+
+static void HeightmapScaledTooMuchCallback(bool ok_clicked)
+{
+	if (ok_clicked) {
+		Window *w;
+		glwp_modes mode = 0;
+		for (mode = 0; mode < GLWP_END; mode++) {
+			w = FindWindowById(WC_GENERATE_LANDSCAPE, mode);
+			if (w != NULL) StartGeneratingLandscape(mode);
+		}
+	}
+}
+
+void GenerateLandscapeWndProc(Window *w, WindowEvent *e)
+{
+	static const StringID mapsizes[]    = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID};
+	static const StringID elevations[]  = {STR_682A_VERY_FLAT, STR_682B_FLAT, STR_682C_HILLY, STR_682D_MOUNTAINOUS, INVALID_STRING_ID};
+	static const StringID sea_lakes[]   = {STR_VERY_LOW, STR_6820_LOW, STR_6821_MEDIUM, STR_6822_HIGH, INVALID_STRING_ID};
+	static const StringID smoothness[]  = {STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH, INVALID_STRING_ID};
+	static const StringID tree_placer[] = {STR_CONFIG_PATCHES_TREE_PLACER_NONE, STR_CONFIG_PATCHES_TREE_PLACER_ORIGINAL, STR_CONFIG_PATCHES_TREE_PLACER_IMPROVED, INVALID_STRING_ID};
+	static const StringID rotation[]    = {STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE, INVALID_STRING_ID};
+	static const StringID landscape[]   = {STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL, STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS, INVALID_STRING_ID};
+	static const StringID num_towns[]   = {STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
+	static const StringID num_inds[]    = {STR_26816_NONE, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
+
+	uint mode = w->window_number;
+	uint y;
+
+	switch (e->event) {
+	case WE_PAINT:
+		w->disabled_state = 0;
+		/* TODO -- Above and below you see some lines commented out with '//' in
+		 *  front of it. This is because currently the widget system can't handle
+		 *  more than 32 widgets per window, and we need 34. Therefor we draw
+		 *  parts of the widgets manually below, reducing the number to 32.
+		 *  Of course someone is already hard working to replace the system with
+		 *  one that can scale past the 32 limit. When this is done you should
+		 *  re-enable the lines and remove the ones that came instead. Better,
+		 *  revert revision 5817 (from TGP branch), and you should be just fine.
+		 * If you have any questions about it, bug TrueLight.
+		 */
+
+		/* You can't select smoothness if not terragenesis */
+//		if (_patches_newgame.land_generator == 0) w->disabled_state |= (1 << 32 | 1 << 33);
+		if (_patches_newgame.land_generator == 0) w->disabled_state |= (1 << 30 | 1 << 31);
+		/* Disable snowline if not hilly */
+		if (_opt_newgame.landscape != LT_HILLY)   w->disabled_state |= (1 << 21 | 1 << 22 | 1 << 23);
+		/* Disable town and industry in SE */
+		if (_game_mode == GM_EDITOR)              w->disabled_state |= (1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 24 | 1 << 25);
+
+		if (_patches_newgame.starting_year <= MIN_YEAR) SETBIT(w->disabled_state, 18);
+		if (_patches_newgame.starting_year >= MAX_YEAR) SETBIT(w->disabled_state, 20);
+		if (_patches_newgame.snow_line_height <= 2 )    SETBIT(w->disabled_state, 21);
+		if (_patches_newgame.snow_line_height >= 13)    SETBIT(w->disabled_state, 23);
+
+		w->click_state = (w->click_state & ~(0xF << 3)) | (1 << (_opt_newgame.landscape + 3));
+		DrawWindowWidgets(w);
+
+		y = (mode == GLWP_HEIGHTMAP) ? 22 : 0;
+
+		DrawString( 12,  91 + y, STR_MAPSIZE, 0);
+		DrawString(119,  91 + y, mapsizes[_patches_newgame.map_x - 6], 0x10);
+		DrawString(168,  91 + y, STR_BY, 0);
+		DrawString(182,  91 + y, mapsizes[_patches_newgame.map_y - 6], 0x10);
+
+		DrawString( 12, 113 + y, STR_NUMBER_OF_TOWNS, 0);
+		DrawString( 12, 131 + y, STR_NUMBER_OF_INDUSTRIES, 0);
+		if (_game_mode == GM_EDITOR) {
+			DrawString(118, 113 + y, STR_6836_OFF, 0x10);
+			DrawString(118, 131 + y, STR_6836_OFF, 0x10);
+		} else {
+			DrawString(118, 113 + y, num_towns[_opt_newgame.diff.number_towns], 0x10);
+			DrawString(118, 131 + y, num_inds[_opt_newgame.diff.number_industries], 0x10);
+		}
+
+		DrawString( 12, 153 + y, STR_RANDOM_SEED, 0);
+		DrawEditBox(w, &WP(w, querystr_d), SEED_EDIT);
+
+		DrawString(182, 113 + y, STR_DATE, 0);
+		SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
+		DrawStringCentered(271, 113 + y, STR_GENERATE_DATE, 0);
+
+		DrawString(182, 131 + y, STR_SNOW_LINE_HEIGHT, 0);
+		SetDParam(0, _patches_newgame.snow_line_height);
+		DrawStringCentered(303, 131 + y, STR_SNOW_LINE_HEIGHT_NUM, 0x10);
+
+		if (mode == GLWP_GENERATE) {
+			/* TODO -- Remove next 2 lines if 32 widget limit is removed */
+			DrawFrameRect(114, 174, 219, 185, 12, 0);
+			DrawString(222, 175, STR_0225, 0x10);
+			DrawString( 12, 175, STR_LAND_GENERATOR, 0);
+			DrawString(118, 175, landscape[_patches_newgame.land_generator], 0x10);
+
+			DrawString( 12, 193, STR_TREE_PLACER, 0);
+			DrawString(118, 193, tree_placer[_patches_newgame.tree_placer], 0x10);
+
+			/* TODO -- Remove next 2 lines if 32 widget limit is removed */
+			DrawFrameRect(114, 210, 219, 221, 12, 0);
+			DrawString(222, 211, STR_0225, 0x10);
+			DrawString( 12, 211, STR_TERRAIN_TYPE, 0);
+			DrawString(118, 211, elevations[_opt_newgame.diff.terrain_type], 0x10);
+
+			/* TODO -- Remove next 2 lines if 32 widget limit is removed */
+			DrawFrameRect(114, 228, 219, 239, 12, 0);
+			DrawString(222, 229, STR_0225, 0x10);
+			DrawString( 12, 229, STR_QUANTITY_OF_SEA_LAKES, 0);
+			DrawString(118, 229, sea_lakes[_opt_newgame.diff.quantity_sea_lakes], 0x10);
+
+			DrawString( 12, 247, STR_SMOOTHNESS, 0);
+			DrawString(118, 247, smoothness[_patches_newgame.tgen_smoothness], 0x10);
+		} else {
+			char buffer[512];
+
+			if (_patches_newgame.heightmap_rotation == HM_CLOCKWISE) {
+				SetDParam(0, _heightmap_y);
+				SetDParam(1, _heightmap_x);
+			} else {
+				SetDParam(0, _heightmap_x);
+				SetDParam(1, _heightmap_y);
+			}
+			GetString(buffer, STR_HEIGHTMAP_SIZE);
+			DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, 0x10);
+
+			DrawString( 12,  91, STR_HEIGHTMAP_NAME, 0x10);
+			SetDParam(0, _heightmap_str);
+			DrawStringTruncated(114,  91, STR_ORANGE, 0x10, 326 - 114 - GetStringWidth(buffer) - 5);
+
+			/* TODO -- Remove next 2 lines if 32 widget limit is removed */
+			DrawFrameRect(114, 196, 219, 207, 12, 0);
+			DrawString(222, 197, STR_0225, 0x10);
+			DrawString( 12, 197, STR_TREE_PLACER, 0);
+			DrawString(118, 197, tree_placer[_patches_newgame.tree_placer], 0x10);
+
+			DrawString( 12, 215, STR_HEIGHTMAP_ROTATION, 0);
+			DrawString(118, 215, rotation[_patches_newgame.heightmap_rotation], 0x10);
+		}
+
+		break;
+	case WE_CLICK:
+		switch (e->click.widget) {
+		case 0: DeleteWindow(w); break;
+		case 3: case 4: case 5: case 6:
+			SetNewLandscapeType(e->click.widget - 3);
+			break;
+		case 7: case 8: // Mapsize X
+			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_x - 6, 8, 0, 0);
+			break;
+		case 9: case 10: // Mapsize Y
+			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_y - 6, 10, 0, 0);
+			break;
+		case 11: case 12: // Number of towns
+			ShowDropDownMenu(w, num_towns, _opt_newgame.diff.number_towns, 12, 0, 0);
+			break;
+		case 13: case 14: // Number of industries
+			ShowDropDownMenu(w, num_inds, _opt_newgame.diff.number_industries, 14, 0, 0);
+			break;
+		case 16: // Random seed
+			_patches_newgame.generation_seed = InteractiveRandom();
+			ttd_strlcpy(_edit_str_buf, str_fmt("%u", _patches_newgame.generation_seed), lengthof(_edit_str_buf));
+			UpdateTextBufferSize(&((querystr_d *)&WP(w, querystr_d))->text);
+			SetWindowDirty(w);
+			break;
+		case 17: // Generate
+			if (mode == GLWP_HEIGHTMAP && (
+					_heightmap_x * 2 < (1U << _patches_newgame.map_x) || _heightmap_x / 2 > (1U << _patches_newgame.map_x) ||
+					_heightmap_y * 2 < (1U << _patches_newgame.map_y) || _heightmap_y / 2 > (1U << _patches_newgame.map_y))) {
+				ShowQuery(STR_HEIGHTMAP_SCALE_WARNING_CAPTION, STR_HEIGHTMAP_SCALE_WARNING_MESSAGE, HeightmapScaledTooMuchCallback, WC_GENERATE_LANDSCAPE, mode);
+			} else {
+				StartGeneratingLandscape(mode);
+			}
+			break;
+		case 18: case 20: // Year buttons
+			/* Don't allow too fast scrolling */
+			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+				HandleButtonClick(w, e->click.widget);
+				SetWindowDirty(w);
+
+				_patches_newgame.starting_year = clamp(_patches_newgame.starting_year + e->click.widget - 19, MIN_YEAR, MAX_YEAR);
+			}
+			_left_button_clicked = false;
+			break;
+		case 19: // Year text
+			WP(w, def_d).data_3 = START_DATE_QUERY;
+			SetDParam(0, _patches_newgame.starting_year);
+			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 5, 100, WC_GENERATE_LANDSCAPE, mode, CS_NUMERAL);
+			break;
+		case 21: case 23: // Snow line buttons
+			/* Don't allow too fast scrolling */
+			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+				HandleButtonClick(w, e->click.widget);
+				SetWindowDirty(w);
+
+				_patches_newgame.snow_line_height = clamp(_patches_newgame.snow_line_height + e->click.widget - 22, 2, 13);
+			}
+			_left_button_clicked = false;
+			break;
+		case 22: // Snow line text
+			WP(w, def_d).data_3 = SNOW_LINE_QUERY;
+			SetDParam(0, _patches_newgame.snow_line_height);
+			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, WC_GENERATE_LANDSCAPE, mode, CS_NUMERAL);
+			break;
+		case 24: case 25: // Tree placer
+			ShowDropDownMenu(w, tree_placer, _patches_newgame.tree_placer, 25, 0, 0);
+			break;
+//		case 26: case 27: // Landscape generator OR Heightmap rotation
+		case 27:
+			if (mode == GLWP_HEIGHTMAP) {
+				ShowDropDownMenu(w, rotation, _patches_newgame.heightmap_rotation, 27, 0, 0);
+			} else {
+				ShowDropDownMenu(w, landscape, _patches_newgame.land_generator, 27, 0, 0);
+			}
+			break;
+//		case 28: case 29: // Terrain type
+		case 28:
+//			ShowDropDownMenu(w, elevations, _opt_newgame.diff.terrain_type, 29, 0, 0);
+			ShowDropDownMenu(w, elevations, _opt_newgame.diff.terrain_type, 28, 0, 0);
+			break;
+//		case 30: case 31: // Water quantity
+		case 29:
+//			ShowDropDownMenu(w, sea_lakes, _opt_newgame.diff.quantity_sea_lakes, 31, 0, 0);
+			ShowDropDownMenu(w, sea_lakes, _opt_newgame.diff.quantity_sea_lakes, 29, 0, 0);
+			break;
+//		case 32: case 33: // Map smoothness
+		case 30: case 31:
+//			ShowDropDownMenu(w, smoothness, _patches_newgame.tgen_smoothness, 33, 0, 0);
+			ShowDropDownMenu(w, smoothness, _patches_newgame.tgen_smoothness, 31, 0, 0);
+			break;
+		}
+		break;
+
+	case WE_MESSAGE:
+		ttd_strlcpy(_edit_str_buf, str_fmt("%u", _patches_newgame.generation_seed), lengthof(_edit_str_buf));
+		DrawEditBox(w, &WP(w, querystr_d), SEED_EDIT);
+		break;
+
+	case WE_MOUSELOOP:
+		HandleEditBox(w, &WP(w, querystr_d), SEED_EDIT);
+		break;
+
+	case WE_KEYPRESS:
+		HandleEditBoxKey(w, &WP(w, querystr_d), SEED_EDIT, e, CS_NUMERAL);
+		_patches_newgame.generation_seed = atoi(_edit_str_buf);
+		break;
+
+	case WE_DROPDOWN_SELECT:
+		switch (e->dropdown.button) {
+			case 8:  _patches_newgame.map_x = e->dropdown.index + 6; break;
+			case 10: _patches_newgame.map_y = e->dropdown.index + 6; break;
+			case 12:
+				_opt_newgame.diff.number_towns = e->dropdown.index;
+				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+				DoCommandP(0, 2, _opt_newgame.diff.number_towns, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+				break;
+			case 14:
+				_opt_newgame.diff.number_industries = e->dropdown.index;
+				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+				DoCommandP(0, 3, _opt_newgame.diff.number_industries, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+				break;
+			case 25:
+				_patches_newgame.tree_placer = e->dropdown.index;
+				break;
+			case 27:
+				if (mode == GLWP_HEIGHTMAP) {
+					_patches_newgame.heightmap_rotation = e->dropdown.index;
+				} else {
+					_patches_newgame.land_generator = e->dropdown.index;
+				}
+				break;
+//			case 29:
+			case 28:
+				_opt_newgame.diff.terrain_type = e->dropdown.index;
+				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+				DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+				break;
+//			case 31:
+			case 29:
+				_opt_newgame.diff.quantity_sea_lakes = e->dropdown.index;
+				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+				DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+				break;
+//			case 33:
+			case 31:
+				_patches_newgame.tgen_smoothness = e->dropdown.index;
+				break;
+		}
+		SetWindowDirty(w);
+		break;
+
+	case WE_ON_EDIT_TEXT: {
+		if (e->edittext.str != NULL) {
+			int32 value = atoi(e->edittext.str);
+
+			switch (WP(w, def_d).data_3) {
+			case START_DATE_QUERY:
+				InvalidateWidget(w, 19);
+				_patches_newgame.starting_year = clamp(value, MIN_YEAR, MAX_YEAR);
+				break;
+			case SNOW_LINE_QUERY:
+				InvalidateWidget(w, 22);
+				_patches_newgame.snow_line_height = clamp(value, 2, 13);
+				break;
+			}
+
+			SetWindowDirty(w);
+		}
+		break;
+	}
+	}
+}
+
+const WindowDesc _generate_landscape_desc = {
+	WDP_CENTER, WDP_CENTER, 338, 268,
+	WC_GENERATE_LANDSCAPE, 0,
+	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+	_generate_landscape_widgets,
+	GenerateLandscapeWndProc,
+};
+
+const WindowDesc _heightmap_load_desc = {
+	WDP_CENTER, WDP_CENTER, 338, 236,
+	WC_GENERATE_LANDSCAPE, 0,
+	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+	_heightmap_load_widgets,
+	GenerateLandscapeWndProc,
+};
+
+static void _ShowGenerateLandscape(glwp_modes mode)
+{
+	Window *w;
+
+	/* Don't kill WC_GENERATE_LANDSCAPE:GLWP_SCENARIO, because it resets
+	 *  _goto_editor, which we maybe need later on. */
+	DeleteWindowById(WC_GENERATE_LANDSCAPE, GLWP_GENERATE);
+	DeleteWindowById(WC_GENERATE_LANDSCAPE, GLWP_HEIGHTMAP);
+
+	/* Always give a new seed if not editor */
+	if (_game_mode != GM_EDITOR) _patches_newgame.generation_seed = InteractiveRandom();
+
+	if (mode == GLWP_HEIGHTMAP) {
+		if (_heightmap_str != STR_NULL) DeleteName(_heightmap_str);
+
+		_heightmap_x = 0;
+		_heightmap_y = 0;
+		_heightmap_str = AllocateName(_file_to_saveload.title, 0);
+		/* If the function returns negative, it means there was a problem loading the heightmap */
+		if (!GetHeightmapDimensions(_file_to_saveload.name, &_heightmap_x, &_heightmap_y))
+			return;
+	}
+
+	w = AllocateWindowDescFront((mode == GLWP_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc, mode);
+
+	if (w != NULL) {
+		querystr_d *querystr = &WP(w, querystr_d);
+
+		ttd_strlcpy(_edit_str_buf, str_fmt("%u", _patches_newgame.generation_seed), lengthof(_edit_str_buf));
+
+		querystr->text.caret = true;
+		querystr->text.maxlength = lengthof(_edit_str_buf);
+		querystr->text.maxwidth = 120;
+		querystr->text.buf = _edit_str_buf;
+		querystr->caption = STR_NULL;
+		UpdateTextBufferSize(&querystr->text);
+
+		InvalidateWindow(WC_GENERATE_LANDSCAPE, mode);
+	}
+}
+
+void ShowGenerateLandscape(void)
+{
+	_ShowGenerateLandscape(GLWP_GENERATE);
+}
+
+void ShowHeightmapLoad(void)
+{
+	_ShowGenerateLandscape(GLWP_HEIGHTMAP);
+}
+
+void StartNewGameWithoutGUI(uint seed)
+{
+	/* GenerateWorld takes care of the possible GENERATE_NEW_SEED value in 'seed' */
+	_patches_newgame.generation_seed = seed;
+
+	StartGeneratingLandscape(GLWP_GENERATE);
+}
+
+
+void CreateScenarioWndProc(Window *w, WindowEvent *e)
+{
+	static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID};
+
+	switch (e->event) {
+	case WE_PAINT:
+		w->disabled_state = 0;
+		if (_patches_newgame.starting_year <= MIN_YEAR)  SETBIT(w->disabled_state, 14);
+		if (_patches_newgame.starting_year >= MAX_YEAR)  SETBIT(w->disabled_state, 16);
+		if (_patches_newgame.se_flat_world_height <= 0)  SETBIT(w->disabled_state, 17);
+		if (_patches_newgame.se_flat_world_height >= 15) SETBIT(w->disabled_state, 19);
+
+		w->click_state = (w->click_state & ~(0xF << 3)) | (1 << (_opt_newgame.landscape + 3));
+		DrawWindowWidgets(w);
+
+		DrawString( 12,  96, STR_MAPSIZE, 0);
+		DrawString( 89,  96, mapsizes[_patches_newgame.map_x - 6], 0x10);
+		DrawString(138,  96, STR_BY, 0);
+		DrawString(152,  96, mapsizes[_patches_newgame.map_y - 6], 0x10);
+
+		DrawString(162, 118, STR_DATE, 0);
+		SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
+		DrawStringCentered(271, 118, STR_GENERATE_DATE, 0);
+
+		DrawString(162, 136, STR_FLAT_WORLD_HEIGHT, 0);
+		SetDParam(0, _patches_newgame.se_flat_world_height);
+		DrawStringCentered(303, 136, STR_FLAT_WORLD_HEIGHT_NUM, 0x10);
+
+		break;
+	case WE_CLICK:
+		switch (e->click.widget) {
+		case 0: DeleteWindow(w); break;
+		case 3: case 4: case 5: case 6:
+			SetNewLandscapeType(e->click.widget - 3);
+			break;
+		case 7: case 8: // Mapsize X
+			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_x - 6, 8, 0, 0);
+			break;
+		case 9: case 10: // Mapsize Y
+			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_y - 6, 10, 0, 0);
+			break;
+		case 11: // Empty world / flat world
+			StartGeneratingLandscape(GLWP_SCENARIO);
+			break;
+		case 12: // Generate
+			_goto_editor = true;
+			ShowGenerateLandscape();
+			break;
+		case 13: // Heightmap
+			_goto_editor = true;
+			ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP);
+			break;
+		case 14: case 16: // Year buttons
+			/* Don't allow too fast scrolling */
+			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+				HandleButtonClick(w, e->click.widget);
+				SetWindowDirty(w);
+
+				_patches_newgame.starting_year = clamp(_patches_newgame.starting_year + e->click.widget - 15, MIN_YEAR, MAX_YEAR);
+			}
+			_left_button_clicked = false;
+			break;
+		case 15: // Year text
+			WP(w, def_d).data_3 = START_DATE_QUERY;
+			SetDParam(0, _patches_newgame.starting_year);
+			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 5, 100, WC_GENERATE_LANDSCAPE, GLWP_SCENARIO, CS_NUMERAL);
+			break;
+		case 17: case 19: // Height level buttons
+			/* Don't allow too fast scrolling */
+			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+				HandleButtonClick(w, e->click.widget);
+				SetWindowDirty(w);
+
+				_patches_newgame.se_flat_world_height = clamp(_patches_newgame.se_flat_world_height + e->click.widget - 18, 0, 15);
+			}
+			_left_button_clicked = false;
+			break;
+		case 18: // Height level text
+			WP(w, def_d).data_3 = FLAT_WORLD_HEIGHT_QUERY;
+			SetDParam(0, _patches_newgame.se_flat_world_height);
+			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, WC_GENERATE_LANDSCAPE, GLWP_SCENARIO, CS_NUMERAL);
+			break;
+		}
+		break;
+
+	case WE_DROPDOWN_SELECT:
+		switch (e->dropdown.button) {
+			case 8:  _patches_newgame.map_x = e->dropdown.index + 6; break;
+			case 10: _patches_newgame.map_y = e->dropdown.index + 6; break;
+		}
+		SetWindowDirty(w);
+		break;
+
+	case WE_DESTROY:
+		_goto_editor = false;
+		break;
+
+	case WE_ON_EDIT_TEXT: {
+		if (e->edittext.str != NULL) {
+			int32 value = atoi(e->edittext.str);
+
+			switch (WP(w, def_d).data_3) {
+			case START_DATE_QUERY:
+				InvalidateWidget(w, 15);
+				_patches_newgame.starting_year = clamp(value, MIN_YEAR, MAX_YEAR);
+				break;
+			case FLAT_WORLD_HEIGHT_QUERY:
+				InvalidateWidget(w, 18);
+				_patches_newgame.se_flat_world_height = clamp(value, 0, 15);
+				break;
+			}
+
+			SetWindowDirty(w);
+		}
+		break;
+	}
+	}
+}
+
+const Widget _create_scenario_widgets[] = {
+{   WWT_CLOSEBOX, RESIZE_NONE, 13,   0,  10,   0,  13, STR_00C5,                STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION, RESIZE_NONE, 13,  11, 337,   0,  13, STR_SE_CAPTION,          STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 13,   0, 337,  14, 179, STR_NULL,                STR_NULL},
+
+{    WWT_PANEL_2, RESIZE_NONE, 12,  10,  86,  24,  78, 0x1312,                  STR_030E_SELECT_TEMPERATE_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12,  90, 166,  24,  78, 0x1314,                  STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12, 170, 246,  24,  78, 0x1316,                  STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12, 250, 326,  24,  78, 0x1318,                  STR_0311_SELECT_TOYLAND_LANDSCAPE},
+
+{      WWT_PANEL, RESIZE_NONE, 12,  84, 119,  95, 106, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 120, 131,  95, 106, STR_0225,                STR_NULL}, // Mapsize X
+{      WWT_PANEL, RESIZE_NONE, 12, 150, 185,  95, 106, STR_NULL,                STR_NULL},
+{    WWT_TEXTBTN, RESIZE_NONE, 12, 186, 197,  95, 106, STR_0225,                STR_NULL}, // Mapsize Y
+
+{    WWT_TEXTBTN, RESIZE_NONE,  6,  12, 145, 117, 128, STR_SE_FLAT_WORLD,       STR_SE_FLAT_WORLD},                      // Empty (sea-level) map
+{    WWT_TEXTBTN, RESIZE_NONE,  6,  12, 145, 135, 146, STR_SE_RANDOM_LAND,      STR_022A_GENERATE_RANDOM_LAND}, // Generate
+{    WWT_TEXTBTN, RESIZE_NONE,  6,  12, 145, 153, 164, STR_LOAD_GAME_HEIGHTMAP, STR_LOAD_SCEN_HEIGHTMAP},       // Heightmap
+
+{     WWT_IMGBTN, RESIZE_NONE, 12, 216, 227, 117, 128, SPR_ARROW_DOWN,          STR_029E_MOVE_THE_STARTING_DATE},
+{      WWT_PANEL, RESIZE_NONE, 12, 228, 314, 117, 128, 0x0,                     STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 117, 128, SPR_ARROW_UP,            STR_029F_MOVE_THE_STARTING_DATE},
+
+{     WWT_IMGBTN, RESIZE_NONE, 12, 282, 293, 135, 146, SPR_ARROW_DOWN,          STR_FLAT_WORLD_HEIGHT_DOWN},
+{      WWT_PANEL, RESIZE_NONE, 12, 294, 314, 135, 146, 0x0,                     STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 135, 146, SPR_ARROW_UP,            STR_FLAT_WORLD_HEIGHT_UP},
+{   WIDGETS_END},
+};
+
+const WindowDesc _create_scenario_desc = {
+	WDP_CENTER, WDP_CENTER, 338, 180,
+	WC_GENERATE_LANDSCAPE, 0,
+	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+	_create_scenario_widgets,
+	CreateScenarioWndProc,
+};
+
+void ShowCreateScenario(void)
+{
+	DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
+	AllocateWindowDescFront(&_create_scenario_desc, GLWP_SCENARIO);
+}
+
+
+static const Widget _show_terrain_progress_widgets[] = {
+{    WWT_CAPTION,   RESIZE_NONE,    14,     0,   180,     0,    13, STR_GENERATION_WORLD,   STR_018C_WINDOW_TITLE_DRAG_THIS},
+{     WWT_IMGBTN,   RESIZE_NONE,    14,     0,   180,    14,    96, 0x0,                    STR_NULL},
+{    WWT_TEXTBTN,   RESIZE_NONE,    15,    20,   161,    74,    85, STR_GENERATION_ABORT,   STR_NULL}, // Abort button
+{   WIDGETS_END},
+};
+
+typedef struct tp_info {
+	uint percent;
+	StringID class;
+	uint current;
+	uint total;
+	int timer;
+} tp_info;
+
+static tp_info _tp;
+
+static void AbortGeneratingWorldCallback(bool ok_clicked)
+{
+	if (ok_clicked) AbortGeneratingWorld();
+	else if (IsGeneratingWorld() && !IsGeneratingWorldAborted()) SetMouseCursor(SPR_CURSOR_ZZZ);
+}
+
+static void ShowTerrainProgressProc(Window* w, WindowEvent* e)
+{
+	switch (e->event) {
+	case WE_CLICK:
+		switch (e->click.widget) {
+		case 2:
+			if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE);
+			ShowQuery(STR_GENERATION_ABORT_CAPTION, STR_GENERATION_ABORT_MESSAGE, AbortGeneratingWorldCallback, WC_GENERATE_PROGRESS_WINDOW, 0);
+			break;
+		}
+		break;
+
+	case WE_PAINT:
+		DrawWindowWidgets(w);
+
+		/* Draw the % complete with a bar and a text */
+		DrawFrameRect(19, 20, (w->width - 18), 37, 14, FR_BORDERONLY);
+		DrawFrameRect(20, 21, (int)((w->width - 40) * _tp.percent / 100) + 20, 36, 10, 0);
+		SetDParam(0, _tp.percent);
+		DrawStringCentered(90, 25, STR_PROGRESS, 0);
+
+		/* Tell which class we are generating */
+		DrawStringCentered(90, 46, _tp.class, 0);
+
+		/* And say where we are in that class */
+		SetDParam(0, _tp.current);
+		SetDParam(1, _tp.total);
+		DrawStringCentered(90, 58, STR_GENERATION_PROGRESS, 0);
+
+		SetWindowDirty(w);
+		break;
+	}
+}
+
+static const WindowDesc _show_terrain_progress_desc = {
+	WDP_CENTER, WDP_CENTER, 181, 97,
+	WC_GENERATE_PROGRESS_WINDOW, 0,
+	WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+	_show_terrain_progress_widgets,
+	ShowTerrainProgressProc
+};
+
+/**
+ * Initializes the progress counters to the starting point.
+ */
+void PrepareGenerateWorldProgress(void)
+{
+	_tp.class   = STR_WORLD_GENERATION;
+	_tp.current = 0;
+	_tp.total   = 0;
+	_tp.percent = 0;
+	_tp.timer   = 0; // Forces to paint the progress window immediatelly
+}
+
+/**
+ * Show the window where a user can follow the process of the map generation.
+ */
+void ShowGenerateWorldProgress(void)
+{
+	AllocateWindowDescFront(&_show_terrain_progress_desc, 0);
+}
+
+static void _SetGeneratingWorldProgress(gwp_class class, uint progress, uint total)
+{
+	static const int percent_table[GWP_CLASS_COUNT + 1] = {0, 5, 15, 20, 40, 60, 65, 80, 85, 99, 100 };
+	static const StringID class_table[GWP_CLASS_COUNT]  = {
+		STR_WORLD_GENERATION,
+		STR_022E_LANDSCAPE_GENERATION,
+		STR_CLEARING_TILES,
+		STR_022F_TOWN_GENERATION,
+		STR_0230_INDUSTRY_GENERATION,
+		STR_UNMOVABLE_GENERATION,
+		STR_TREE_GENERATION,
+		STR_SETTINGUP_GAME,
+		STR_PREPARING_TILELOOP,
+		STR_PREPARING_GAME
+	};
+
+	assert(class < GWP_CLASS_COUNT);
+
+	/* Do not run this function if we aren't in a thread */
+	if (!IsGenerateWorldThreaded() && !_network_dedicated) return;
+
+	if (IsGeneratingWorldAborted()) HandleGeneratingWorldAbortion();
+
+	if (total == 0) {
+		assert(_tp.class == class_table[class]);
+		_tp.current += progress;
+	} else {
+		_tp.class   = class_table[class];
+		_tp.current = progress;
+		_tp.total   = total;
+		_tp.percent = percent_table[class];
+	}
+
+	/* Don't update the screen too often. So update it once in the
+	 * _patches.progress_update_interval. However, the _tick_counter
+	 * increases with 8 every 30ms, so compensate for that. */
+	if (!_network_dedicated && _tp.timer != 0 && _timer_counter - _tp.timer < (_patches.progress_update_interval * 8 / 30)) return;
+
+	/* Percentage is about the number of completed tasks, so 'current - 1' */
+	_tp.percent = percent_table[class] + (percent_table[class + 1] - percent_table[class]) * (_tp.current == 0 ? 0 : _tp.current - 1) / _tp.total;
+	_tp.timer = _timer_counter;
+
+	if (_network_dedicated) {
+		static uint last_percent = 0;
+
+		/* Never display 0% */
+		if (_tp.percent == 0) return;
+		/* Reset if percent is lower then the last recorded */
+		if (_tp.percent < last_percent) last_percent = 0;
+		/* Display every 5%, but 6% is also very valid.. just not smaller steps then 5% */
+		if (_tp.percent % 5 != 0 && _tp.percent <= last_percent + 5) return;
+		/* Never show steps smaller then 2%, even if it is a mod 5% */
+		if (_tp.percent <= last_percent + 2) return;
+
+		DEBUG(net, 1)("Percent complete: %d", _tp.percent);
+		last_percent = _tp.percent;
+
+		/* Don't continue as dedicated never has a thread running */
+		return;
+	}
+
+	InvalidateWindow(WC_GENERATE_PROGRESS_WINDOW, 0);
+	MarkWholeScreenDirty();
+	SetGeneratingWorldPaintStatus(true);
+
+	/* We wait here till the paint is done, so we don't read and write
+	 *  on the same tile at the same moment. Nasty hack, but that happens
+	 *  if you implement threading afterwards */
+	while (IsGeneratingWorldReadyForPaint()) { CSleep(10); }
+}
+
+/**
+ * Set the total of a stage of the world generation.
+ * @param class the current class we are in.
+ * @param total Set the total expected items for this class.
+ *
+ * Warning: this function isn't clever. Don't go from class 4 to 3. Go upwards, always.
+ *  Also, progress works if total is zero, total works if progress is zero.
+ */
+void SetGeneratingWorldProgress(gwp_class class, uint total)
+{
+	if (total == 0) return;
+
+	_SetGeneratingWorldProgress(class, 0, total);
+}
+
+/**
+ * Increases the current stage of the world generation with one.
+ * @param class the current class we are in.
+ *
+ * Warning: this function isn't clever. Don't go from class 4 to 3. Go upwards, always.
+ *  Also, progress works if total is zero, total works if progress is zero.
+ */
+void IncreaseGeneratingWorldProgress(gwp_class class)
+{
+	/* In fact the param 'class' isn't needed.. but for some security reasons, we want it around */
+	_SetGeneratingWorldProgress(class, 1, 0);
+}
--- a/gfx.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/gfx.c	Sat Aug 19 10:00:30 2006 +0000
@@ -12,6 +12,7 @@
 #include "table/sprites.h"
 #include "hal.h"
 #include "variables.h"
+#include "genworld.h"
 
 #ifdef _DEBUG
 bool _dbg_screen_rect;
@@ -1753,6 +1754,8 @@
 	int x;
 	int y;
 
+	if (IsGeneratingWorld() && !IsGeneratingWorldReadyForPaint()) return;
+
 	y = 0;
 	do {
 		x = 0;
@@ -1819,6 +1822,12 @@
 	_invalid_rect.top = h;
 	_invalid_rect.right = 0;
 	_invalid_rect.bottom = 0;
+
+	/* If we are generating a world, and waiting for a paint run, mark it here
+	 *  as done painting, so we can continue generating. */
+	if (IsGeneratingWorld() && IsGeneratingWorldReadyForPaint()) {
+		SetGeneratingWorldPaintStatus(false);
+	}
 }
 
 
--- a/gui.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/gui.h	Sat Aug 19 10:00:30 2006 +0000
@@ -64,6 +64,10 @@
 /* terraform_gui.c */
 void ShowTerraformToolbar(void);
 
+/* tgp_gui.c */
+void ShowGenerateLandscape(void);
+void ShowHeightmapLoad(void);
+
 void PlaceProc_DemolishArea(TileIndex tile);
 void PlaceProc_LevelLand(TileIndex tile);
 bool GUIPlaceProcDragXY(const WindowEvent *we);
@@ -103,7 +107,6 @@
 void SetHScrollCount(Window *w, int num);
 
 void ShowCheatWindow(void);
-void AskForNewGameToStart(void);
 
 void DrawEditBox(Window *w, querystr_d *string, int wid);
 void HandleEditBox(Window *w, querystr_d *string, int wid);
@@ -138,6 +141,7 @@
 bool DoZoomInOutWindow(int how, Window *w);
 void ShowBuildIndustryWindow(void);
 void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number, CharSetFilter afilter);
+void ShowQuery(StringID caption, StringID message, void (*ok_cancel_callback)(bool ok_clicked), WindowClass window_class, WindowNumber window_number);
 void ShowMusicWindow(void);
 
 /* main_gui.c */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/heightmap.c	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,459 @@
+/* $Id$ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "variables.h"
+#include "functions.h"
+#include "heightmap.h"
+#include "clear_map.h"
+#include "table/strings.h"
+#include "void_map.h"
+#include "debug.h"
+#include "gfx.h"
+#include "gui.h"
+#include "saveload.h"
+#include "bmp.h"
+
+/**
+ * Convert RGB colors to Grayscale using 29.9% Red, 58.7% Green, 11.4% Blue
+ *  (average luminosity formula) -- Dalestan
+ * This in fact is the NTSC Color Space -- TrueLight
+ */
+static inline byte RGBToGrayscale(byte red, byte green, byte blue)
+{
+	/* To avoid doubles and stuff, multiple it with a total of 65536 (16bits), then
+	 *  divide by it to normalize the value to a byte again. */
+	return ((red * 19595) + (green * 38470) + (blue * 7471)) / 65536;
+}
+
+
+#ifdef WITH_PNG
+
+#include "png.h"
+
+/**
+ * The PNG Heightmap loader.
+ */
+static void ReadHeightmapPNGImageData(byte *map, png_structp png_ptr, png_infop info_ptr)
+{
+	uint x, y;
+	byte gray_palette[256];
+	png_bytep *row_pointers = NULL;
+
+	/* Get palette and convert it to grayscale */
+	if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
+		int i;
+		int palette_size;
+		png_color *palette;
+		bool all_gray = true;
+
+		png_get_PLTE(png_ptr, info_ptr, &palette, &palette_size);
+		for (i = 0; i < palette_size && (palette_size != 16 || all_gray); i++) {
+			all_gray &= palette[i].red == palette[i].green && palette[i].red == palette[i].blue;
+			gray_palette[i] = RGBToGrayscale(palette[i].red, palette[i].green, palette[i].blue);
+		}
+
+		/**
+		 * For a non-gray palette of size 16 we assume that
+		 * the order of the palette determines the height;
+		 * the first entry is the sea (level 0), the second one
+		 * level 1, etc.
+		 */
+		if (palette_size == 16 && !all_gray) {
+			for (i = 0; i < palette_size; i++) {
+				gray_palette[i] = 256 * i / palette_size;
+			}
+		}
+	}
+
+	row_pointers = png_get_rows(png_ptr, info_ptr);
+
+	/* Read the raw image data and convert in 8-bit grayscale */
+	for (x = 0; x < info_ptr->width; x++) {
+		for (y = 0; y < info_ptr->height; y++) {
+			byte *pixel = &map[y * info_ptr->width + x];
+			uint x_offset = x * info_ptr->channels;
+
+			if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
+				*pixel = gray_palette[row_pointers[y][x_offset]];
+			} else if (info_ptr->channels == 3) {
+				*pixel = RGBToGrayscale(row_pointers[y][x_offset + 0],
+						row_pointers[y][x_offset + 1], row_pointers[y][x_offset + 2]);
+			} else {
+				*pixel = row_pointers[y][x_offset];
+			}
+		}
+	}
+}
+
+/**
+ * Reads the heightmap and/or size of the heightmap from a PNG file.
+ * If map == NULL only the size of the PNG is read, otherwise a map
+ * with grayscale pixels is allocated and assigned to *map.
+ */
+static bool ReadHeightmapPNG(char *filename, uint *x, uint *y, byte **map)
+{
+	FILE *fp;
+	png_structp png_ptr = NULL;
+	png_infop info_ptr  = NULL;
+
+	fp = fopen(filename, "rb");
+	if (fp == NULL) {
+		ShowErrorMessage(STR_PNGMAP_ERR_FILE_NOT_FOUND, STR_PNGMAP_ERROR, 0, 0);
+		return false;
+	}
+
+	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+	if (png_ptr == NULL) {
+		ShowErrorMessage(STR_PNGMAP_ERR_MISC, STR_PNGMAP_ERROR, 0, 0);
+		fclose(fp);
+		return false;
+	}
+
+	info_ptr = png_create_info_struct(png_ptr);
+	if (info_ptr == NULL || setjmp(png_jmpbuf(png_ptr))) {
+		ShowErrorMessage(STR_PNGMAP_ERR_MISC, STR_PNGMAP_ERROR, 0, 0);
+		fclose(fp);
+		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+		return false;
+	}
+
+	png_init_io(png_ptr, fp);
+
+	/* Allocate memory and read image, without alpha or 16-bit samples
+	* (result is either 8-bit indexed/grayscale or 24-bit RGB) */
+	png_set_packing(png_ptr);
+	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_STRIP_16, NULL);
+
+	/* Maps of wrong color-depth are not used.
+	 * (this should have been taken care of by stripping alpha and 16-bit samples on load) */
+	if ((info_ptr->channels != 1) && (info_ptr->channels != 3) && (info_ptr->bit_depth != 8)) {
+		ShowErrorMessage(STR_PNGMAP_ERR_IMAGE_TYPE, STR_PNGMAP_ERROR, 0, 0);
+		fclose(fp);
+		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+		return false;
+	}
+
+	if (map != NULL) {
+		*map = malloc(info_ptr->width * info_ptr->height * sizeof(byte));
+
+		if (*map == NULL) {
+			ShowErrorMessage(STR_PNGMAP_ERR_MISC, STR_PNGMAP_ERROR, 0, 0);
+			fclose(fp);
+			png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+			return false;
+		}
+
+		ReadHeightmapPNGImageData(*map, png_ptr, info_ptr);
+	}
+
+	*x = info_ptr->width;
+	*y = info_ptr->height;
+
+	fclose(fp);
+	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+	return true;
+}
+
+#endif /* WITH_PNG */
+
+
+/**
+ * The BMP Heightmap loader.
+ */
+static void ReadHeightmapBMPImageData(byte *map, BmpInfo *info, BmpData *data)
+{
+	uint x, y;
+	byte gray_palette[256];
+
+	if (data->palette != NULL) {
+		uint i;
+		bool all_gray = true;
+
+		if (info->palette_size != 2) {
+			for (i = 0; i < info->palette_size && (info->palette_size != 16 || all_gray); i++) {
+				all_gray &= data->palette[i].r == data->palette[i].g && data->palette[i].r == data->palette[i].b;
+				gray_palette[i] = RGBToGrayscale(data->palette[i].r, data->palette[i].g, data->palette[i].b);
+			}
+
+			/**
+			 * For a non-gray palette of size 16 we assume that
+			 * the order of the palette determines the height;
+			 * the first entry is the sea (level 0), the second one
+			 * level 1, etc.
+			 */
+			if (info->palette_size == 16 && !all_gray) {
+				for (i = 0; i < info->palette_size; i++) {
+					gray_palette[i] = 256 * i / info->palette_size;
+				}
+			}
+		} else {
+			/**
+			 * For a palette of size 2 we assume that the order of the palette determines the height;
+			 * the first entry is the sea (level 0), the second one is the land (level 1)
+			 */
+			gray_palette[0] = 0;
+			gray_palette[1] = 16;
+		}
+	}
+
+	/* Read the raw image data and convert in 8-bit grayscale */
+	for (y = 0; y < info->height; y++) {
+		byte *pixel = &map[y * info->width];
+		byte *bitmap = &data->bitmap[y * info->width * (info->bpp == 24 ? 3 : 1)];
+
+		for (x = 0; x < info->width; x++) {
+			if (info->bpp != 24) {
+				*pixel++ = gray_palette[*bitmap++];
+			} else {
+				*pixel++ = RGBToGrayscale(*bitmap, *(bitmap + 1), *(bitmap + 2));
+				bitmap += 3;
+			}
+		}
+	}
+}
+
+/**
+ * Reads the heightmap and/or size of the heightmap from a BMP file.
+ * If map == NULL only the size of the BMP is read, otherwise a map
+ * with grayscale pixels is allocated and assigned to *map.
+ */
+static bool ReadHeightmapBMP(char *filename, uint *x, uint *y, byte **map)
+{
+	FILE *f;
+	BmpInfo info;
+	BmpData data;
+	BmpBuffer buffer;
+
+	f = fopen(filename, "rb");
+	if (f == NULL) {
+		ShowErrorMessage(STR_PNGMAP_ERR_FILE_NOT_FOUND, STR_BMPMAP_ERROR, 0, 0);
+		return false;
+	}
+
+	BmpInitializeBuffer(&buffer, f);
+
+	if (!BmpReadHeader(&buffer, &info, &data)) {
+		ShowErrorMessage(STR_BMPMAP_ERR_IMAGE_TYPE, STR_BMPMAP_ERROR, 0, 0);
+		fclose(f);
+		BmpDestroyData(&data);
+		return false;
+	}
+
+	if (map != NULL) {
+		if (!BmpReadBitmap(&buffer, &info, &data)) {
+			ShowErrorMessage(STR_BMPMAP_ERR_IMAGE_TYPE, STR_BMPMAP_ERROR, 0, 0);
+			fclose(f);
+			BmpDestroyData(&data);
+			return false;
+		}
+
+		*map = malloc(info.width * info.height * sizeof(byte));
+		if (*map == NULL) {
+			ShowErrorMessage(STR_PNGMAP_ERR_MISC, STR_BMPMAP_ERROR, 0, 0);
+			fclose(f);
+			BmpDestroyData(&data);
+			return false;
+		}
+
+		ReadHeightmapBMPImageData(*map, &info, &data);
+
+	}
+
+	BmpDestroyData(&data);
+
+	*x = info.width;
+	*y = info.height;
+
+	fclose(f);
+	return true;
+}
+
+static void GrayscaleToMapHeights(uint img_width, uint img_height, byte *map)
+{
+	/* Defines the detail of the aspect ratio (to avoid doubles) */
+	const uint num_div = 16384;
+
+	uint width, height;
+	uint row, col;
+	uint row_pad = 0, col_pad = 0;
+	uint img_scale;
+	uint img_row, img_col;
+	TileIndex tile;
+
+	/* Get map size and calculate scale and padding values */
+	switch (_patches.heightmap_rotation) {
+	case HM_COUNTER_CLOCKWISE:
+		width   = MapSizeX();
+		height  = MapSizeY();
+		break;
+	case HM_CLOCKWISE:
+		width   = MapSizeY();
+		height  = MapSizeX();
+		break;
+	default:
+		NOT_REACHED();
+		/* Avoids compiler warnings */
+		return;
+	}
+
+	if ((img_width * num_div) / img_height > ((width * num_div) / height)) {
+		/* Image is wider than map - center vertically */
+		img_scale = (width * num_div) / img_width;
+		row_pad = (height - ((img_height * img_scale) / num_div)) / 2;
+	} else {
+		/* Image is taller than map - center horizontally */
+		img_scale = (height * num_div) / img_height;
+		col_pad = (width - ((img_width * img_scale) / num_div)) / 2;
+	}
+
+	/* Form the landscape */
+	for (row = 0; row < height - 1; row++) {
+		for (col = 0; col < width - 1; col++) {
+			switch (_patches.heightmap_rotation) {
+			case HM_COUNTER_CLOCKWISE: tile = TileXY(col, row); break;
+			case HM_CLOCKWISE:         tile = TileXY(row, col); break;
+			default:                   NOT_REACHED(); return;
+			}
+
+			/* Check if current tile is within the 1-pixel map edge or padding regions */
+			if ((DistanceFromEdge(tile) <= 1) ||
+					(row < row_pad) || (row >= (height - row_pad)) ||
+					(col < col_pad) || (col >= (width - col_pad))) {
+				SetTileHeight(tile, 0);
+			} else {
+				/* Use nearest neighbor resizing to scale map data.
+				 *  We rotate the map 45 degrees (counter)clockwise */
+				img_row = (((row - row_pad) * num_div) / img_scale);
+				switch (_patches.heightmap_rotation) {
+				case HM_COUNTER_CLOCKWISE:
+					img_col = (((width - 1 - col - col_pad) * num_div) / img_scale);
+					break;
+				case HM_CLOCKWISE:
+					img_col = (((col - col_pad) * num_div) / img_scale);
+					break;
+				default:
+					NOT_REACHED();
+					/* Avoids compiler warnings */
+					return;
+				}
+
+				assert(img_row < img_height);
+				assert(img_col < img_width);
+
+				/* Color scales from 0 to 255, OpenTTD height scales from 0 to 15 */
+				SetTileHeight(tile, map[img_row * img_width + img_col] / 16);
+			}
+			MakeClear(tile, CLEAR_GRASS, 3);
+		}
+	}
+}
+
+/**
+ * This function takes care of the fact that land in OpenTTD can never differ
+ * more than 1 in height
+ */
+static void FixSlopes(void)
+{
+	uint width, height;
+	uint row, col;
+	byte current_tile;
+
+	/* Adjust height difference to maximum one horizontal/vertical change. */
+	width   = MapSizeX();
+	height  = MapSizeY();
+
+	/* Top and left edge */
+	for (row = 1; row < height - 2; row++) {
+		for (col = 1; col < width - 2; col++) {
+			/* Find lowest tile; either the top or left one */
+			current_tile = TileHeight(TileXY(col - 1, row)); // top edge
+			if (TileHeight(TileXY(col, row - 1)) < current_tile) {
+				current_tile = TileHeight(TileXY(col, row - 1)); // left edge
+			}
+
+			/* Does the height differ more than one? */
+			if (TileHeight(TileXY(col, row)) >= (uint)current_tile + 2) {
+				/* Then change the height to be no more than one */
+				SetTileHeight(TileXY(col, row), current_tile + 1);
+			}
+		}
+	}
+
+	/* Bottom and right edge */
+	for (row = height - 2; row > 0; row--) {
+		for (col = width - 2; col > 0; col--) {
+			/* Find lowest tile; either the bottom and right one */
+			current_tile = TileHeight(TileXY(col + 1, row)); // bottom edge
+			if (TileHeight(TileXY(col, row + 1)) < current_tile) {
+				current_tile = TileHeight(TileXY(col, row + 1)); // right edge
+			}
+
+			/* Does the height differ more than one? */
+			if (TileHeight(TileXY(col, row)) >= (uint)current_tile + 2) {
+				/* Then change the height to be no more than one */
+				SetTileHeight(TileXY(col, row), current_tile + 1);
+			}
+		}
+	}
+}
+
+/**
+ * Reads the heightmap with the correct file reader
+ */
+static bool ReadHeightMap(char *filename, uint *x, uint *y, byte **map)
+{
+	switch (_file_to_saveload.mode) {
+#ifdef WITH_PNG
+		case SL_PNG:
+			return ReadHeightmapPNG(filename, x, y, map);
+#endif /* WITH_PNG */
+		case SL_BMP:
+			return ReadHeightmapBMP(filename, x, y, map);
+
+		default:
+			NOT_REACHED();
+			/* Avoids compiler warnings */
+			return false;
+	}
+}
+
+bool GetHeightmapDimensions(char *filename, uint *x, uint *y)
+{
+	return ReadHeightMap(filename, x, y, NULL);
+}
+
+void LoadHeightmap(char *filename)
+{
+	uint x, y;
+	byte *map = NULL;
+
+	if (!ReadHeightMap(filename, &x, &y, &map)) {
+		free(map);
+		return;
+	}
+
+	GrayscaleToMapHeights(x, y, map);
+	free(map);
+
+	FixSlopes();
+	MarkWholeScreenDirty();
+}
+
+void FlatEmptyWorld(byte tile_height)
+{
+	uint width, height;
+	uint row, col;
+
+	width  = MapSizeX();
+	height = MapSizeY();
+
+	for (row = 2; row < height - 2; row++) {
+		for (col = 2; col < width - 2; col++) {
+			SetTileHeight(TileXY(col, row), tile_height);
+		}
+	}
+
+	FixSlopes();
+	MarkWholeScreenDirty();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/heightmap.h	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,33 @@
+/* $Id$ */
+
+#ifndef HEIGHTMAP_H
+#define HEIGHTMAP_H
+
+/*
+ * Order of these enums has to be the same as in lang/english.txt
+ * Otherwise you will get inconsistent behaviour.
+ */
+enum {
+	HM_COUNTER_CLOCKWISE, //! Rotate the map counter clockwise 45 degrees
+	HM_CLOCKWISE,         //! Rotate the map clockwise 45 degrees
+};
+
+/**
+ * Get the dimensions of a heightmap.
+ * @return Returns false if loading of the image failed.
+ */
+bool GetHeightmapDimensions(char *filename, uint *x, uint *y);
+
+/**
+ * Load a heightmap from file and change the map in his current dimensions
+ *  to a landscape representing the heightmap.
+ * It converts pixels to height. The brighter, the higher.
+ */
+void LoadHeightmap(char *filename);
+
+/**
+ * Make an empty world where all tiles are of height 'tile_height'.
+ */
+void FlatEmptyWorld(byte tile_height);
+
+#endif /* HEIGHTMAP_H */
--- a/industry_cmd.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/industry_cmd.c	Sat Aug 19 10:00:30 2006 +0000
@@ -22,6 +22,7 @@
 #include "variables.h"
 #include "table/industry_land.h"
 #include "table/build_industry.h"
+#include "genworld.h"
 #include "date.h"
 
 enum {
@@ -1026,7 +1027,7 @@
 static bool CheckNewIndustry_OilRefinery(TileIndex tile)
 {
 	if (_game_mode == GM_EDITOR) return true;
-	if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < 16) return true;
+	if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _patches.oil_refinery_limit) return true;
 
 	_error_message = STR_483B_CAN_ONLY_BE_POSITIONED;
 	return false;
@@ -1038,7 +1039,7 @@
 {
 	if (_game_mode == GM_EDITOR && _ignore_restrictions) return true;
 	if (TileHeight(tile) == 0 &&
-			DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < 16)   return true;
+			DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _patches.oil_refinery_limit) return true;
 
 	_error_message = STR_483B_CAN_ONLY_BE_POSITIONED;
 	return false;
@@ -1161,7 +1162,7 @@
 	16, 16, 16, 16, 16, 16, 16,
 };
 
-static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, int type, const Town *t)
+static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, int type)
 {
 	_error_message = STR_0239_SITE_UNSUITABLE;
 
@@ -1191,22 +1192,27 @@
 				tileh = GetTileSlope(cur_tile, NULL);
 				if (IsSteepSlope(tileh)) return false;
 
-				if (tileh != SLOPE_FLAT) {
-					Slope t;
-					byte bits = _industry_section_bits[it->gfx];
-
-					if (bits & 0x10) return false;
+				if (_patches.land_generator == LG_TERRAGENESIS || !_generating_world) {
+					/* It is almost impossible to have a fully flat land in TG, so what we
+					 *  do is that we check if we can make the land flat later on. See
+					 *  CheckIfCanLevelIndustryPlatform(). */
+					if (tileh != SLOPE_FLAT) {
+						Slope t;
+						byte bits = _industry_section_bits[it->gfx];
 
-					t = ComplementSlope(tileh);
+						if (bits & 0x10) return false;
 
-					if (bits & 1 && (t & SLOPE_NW)) return false;
-					if (bits & 2 && (t & SLOPE_NE)) return false;
-					if (bits & 4 && (t & SLOPE_SW)) return false;
-					if (bits & 8 && (t & SLOPE_SE)) return false;
+						t = ComplementSlope(tileh);
+
+						if (bits & 1 && (t & SLOPE_NW)) return false;
+						if (bits & 2 && (t & SLOPE_NE)) return false;
+						if (bits & 4 && (t & SLOPE_SW)) return false;
+						if (bits & 8 && (t & SLOPE_SE)) return false;
+					}
 				}
 
 				if (type == IT_BANK_TEMP) {
-					if (!IsTileType(cur_tile, MP_HOUSE) || t->population < 1200) {
+					if (!IsTileType(cur_tile, MP_HOUSE)) {
 						_error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS;
 						return false;
 					}
@@ -1216,7 +1222,6 @@
 						return false;
 					}
 				} else if (type == IT_TOY_SHOP) {
-					if (DistanceMax(t->xy, cur_tile) > 9) return false;
 					if (!IsTileType(cur_tile, MP_HOUSE)) goto do_clear;
 				} else if (type == IT_WATER_TOWER) {
 					if (!IsTileType(cur_tile, MP_HOUSE)) {
@@ -1235,6 +1240,115 @@
 	return true;
 }
 
+static bool CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
+{
+	if (type == IT_BANK_TEMP && t->population < 1200) {
+		_error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS;
+		return false;
+	}
+
+	if (type == IT_TOY_SHOP && DistanceMax(t->xy, tile) > 9) {
+		_error_message = STR_0239_SITE_UNSUITABLE;
+		return false;
+	}
+
+	return true;
+}
+
+static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
+{
+	int size_x, size_y;
+	uint curh;
+
+	size_x = 2;
+	size_y = 2;
+
+	/* Check if we don't leave the map */
+	if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
+
+	tile += TileDiffXY(-1, -1);
+	BEGIN_TILE_LOOP(tile_walk, size_x, size_y, tile) {
+		curh = TileHeight(tile_walk);
+		/* Is the tile clear? */
+		if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES))
+			return false;
+
+		/* Don't allow too big of a change if this is the sub-tile check */
+		if (internal != 0 && myabs(curh - height) > 1) return false;
+
+		/* Different height, so the surrounding tiles of this tile
+		 *  has to be correct too (in level, or almost in level)
+		 *  else you get a chain-reaction of terraforming. */
+		if (internal == 0 && curh != height) {
+			if (!CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1))
+				return false;
+		}
+	} END_TILE_LOOP(tile_walk, size_x, size_y, tile);
+
+	return true;
+}
+
+/**
+ * This function tries to flatten out the land below an industry, without
+ *  damaging the surroundings too much.
+ */
+static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, uint32 flags, const IndustryTileTable* it, int type)
+{
+	const int MKEND = -0x80;   // used for last element in an IndustryTileTable (see build_industry.h)
+	int max_x = 0;
+	int max_y = 0;
+	TileIndex cur_tile;
+	uint size_x, size_y;
+	uint h, curh;
+
+	/* Finds dimensions of largest variant of this industry */
+	do {
+		if (it->ti.x > max_x) max_x = it->ti.x;
+		if (it->ti.y > max_y) max_y = it->ti.y;
+	} while ((++it)->ti.x != MKEND);
+
+	/* Remember level height */
+	h = TileHeight(tile);
+
+	/* Check that all tiles in area and surrounding are clear
+	 * this determines that there are no obstructing items */
+	cur_tile = tile + TileDiffXY(-1, -1);
+	size_x = max_x + 4;
+	size_y = max_y + 4;
+
+	/* Check if we don't leave the map */
+	if (TileX(cur_tile) == 0 || TileY(cur_tile) == 0 || GetTileType(cur_tile) == MP_VOID) return false;
+
+	BEGIN_TILE_LOOP(tile_walk, size_x, size_y, cur_tile) {
+		curh = TileHeight(tile_walk);
+		if (curh != h) {
+			/* This tile needs terraforming. Check if we can do that without
+			 *  damaging the surroundings too much. */
+			if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) return false;
+			/* This is not 100% correct check, but the best we can do without modifying the map.
+			 *  What is missing, is if the difference in height is more than 1.. */
+			if (CmdFailed(DoCommand(tile_walk, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND))) return false;
+		}
+	} END_TILE_LOOP(tile_walk, size_x, size_y, cur_tile)
+
+	if (flags & DC_EXEC) {
+		/* Terraform the land under the industry */
+		BEGIN_TILE_LOOP(tile_walk, size_x, size_y, cur_tile) {
+			curh = TileHeight(tile_walk);
+			while (curh != h) {
+				/* We give the terraforming for free here, because we can't calculate
+				 *  exact cost in the test-round, and as we all know, that will cause
+				 *  a nice assert if they don't match ;) */
+				DoCommand(tile_walk, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
+				curh += (curh > h) ? -1 : 1;
+			}
+		} END_TILE_LOOP(tile_walk, size_x, size_y, cur_tile)
+	}
+
+	return true;
+}
+
+
 static bool CheckIfTooCloseToIndustry(TileIndex tile, int type)
 {
 	const IndustrySpec *indspec = GetIndustrySpec(type);
@@ -1373,6 +1487,33 @@
 	InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
 }
 
+static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, const IndustryTileTable *it)
+{
+	const Town *t;
+	Industry *i;
+
+	if (!CheckIfIndustryTilesAreFree(tile, it, type)) return NULL;
+	if (_patches.land_generator == LG_TERRAGENESIS && _generating_world && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL;
+	if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
+	if (!CheckIfTooCloseToIndustry(tile, type)) return NULL;
+
+	t = CheckMultipleIndustryInTown(tile, type);
+	if (t == NULL) return NULL;
+
+	if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL;
+	if (!CheckSuitableIndustryPos(tile)) return NULL;
+
+	i = AllocateIndustry();
+	if (i == NULL) return NULL;
+
+	if (flags & DC_EXEC) {
+		CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type);
+		DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE);
+	}
+
+	return i;
+}
+
 /** Build/Fund an industry
  * @param tile tile where industry is built
  * @param p1 industry type @see build_industry.h and @see industry.h
@@ -1380,8 +1521,6 @@
  */
 int32 CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	const Town *t;
-	Industry *i;
 	int num;
 	const IndustryTileTable * const *itt;
 	const IndustryTileTable *it;
@@ -1389,8 +1528,6 @@
 
 	SET_EXPENSES_TYPE(EXPENSES_OTHER);
 
-	if (!CheckSuitableIndustryPos(tile)) return CMD_ERROR;
-
 	/* Check if the to-be built/founded industry is available for this climate.
 	 * Unfortunately we have no easy way of checking, except for looping the table */
 	{
@@ -1418,25 +1555,14 @@
 		return CMD_ERROR;
 	}
 
-	if (!_check_new_industry_procs[indspec->check_proc](tile)) return CMD_ERROR;
-
-	t = CheckMultipleIndustryInTown(tile, p1);
-	if (t == NULL) return CMD_ERROR;
-
 	num = indspec->num_table;
 	itt = indspec->table;
 
 	do {
 		if (--num < 0) return_cmd_error(STR_0239_SITE_UNSUITABLE);
-	} while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1, t));
-
+	} while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1));
 
-	if (!CheckIfTooCloseToIndustry(tile, p1)) return CMD_ERROR;
-
-	i = AllocateIndustry();
-	if (i == NULL) return CMD_ERROR;
-
-	if (flags & DC_EXEC) DoCreateNewIndustry(i, tile, p1, it, t, OWNER_NONE);
+	if (CreateNewIndustryHelper(tile, p1, flags, indspec, it) == NULL) return CMD_ERROR;
 
 	return (_price.build_industry >> 5) * indspec->cost_multiplier;
 }
@@ -1444,33 +1570,10 @@
 
 Industry *CreateNewIndustry(TileIndex tile, IndustryType type)
 {
-	const Town *t;
-	const IndustryTileTable *it;
-	Industry *i;
-
-	const IndustrySpec *indspec;
-
-	if (!CheckSuitableIndustryPos(tile)) return NULL;
-
-	indspec =  GetIndustrySpec(type);
-
-	if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
+	const IndustrySpec *indspec = GetIndustrySpec(type);
+	const IndustryTileTable *it = indspec->table[RandomRange(indspec->num_table)];
 
-	t = CheckMultipleIndustryInTown(tile, type);
-	if (t == NULL) return NULL;
-
-	/* pick a random layout */
-	it = indspec->table[RandomRange(indspec->num_table)];
-
-	if (!CheckIfIndustryTilesAreFree(tile, it, type, t)) return NULL;
-	if (!CheckIfTooCloseToIndustry(tile, type)) return NULL;
-
-	i = AllocateIndustry();
-	if (i == NULL) return NULL;
-
-	DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE);
-
-	return i;
+	return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, it);
 }
 
 static const byte _numof_industry_table[4][12] = {
@@ -1500,6 +1603,8 @@
 		do {
 			uint i;
 
+			IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
+
 			for (i = 0; i < 2000; i++) {
 				if (CreateNewIndustry(RandomTile(), type) != NULL) break;
 			}
@@ -1512,6 +1617,23 @@
 void GenerateIndustries(void)
 {
 	const byte *b;
+	uint i = 0;
+
+	/* Find the total amount of industries */
+	b = _industry_create_table[_opt.landscape];
+	do {
+		int num = _numof_industry_table[_opt.diff.number_industries][b[0]];
+
+		if (b[1] == IT_OIL_REFINERY || b[1] == IT_OIL_RIG) {
+			/* These are always placed next to the coastline, so we scale by the perimeter instead. */
+			num = ScaleByMapSize1D(num);
+		} else {
+			num = ScaleByMapSize(num);
+		}
+
+		i += num;
+	} while ( (b+=2)[0] != 0);
+	SetGeneratingWorldProgress(GWP_INDUSTRY, i);
 
 	b = _industry_create_table[_opt.landscape];
 	do {
--- a/intro_gui.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/intro_gui.c	Sat Aug 19 10:00:30 2006 +0000
@@ -11,40 +11,34 @@
 #include "network.h"
 #include "variables.h"
 #include "settings.h"
-
-extern void SwitchMode(int new_mode);
+#include "heightmap.h"
+#include "genworld.h"
 
 static const Widget _select_game_widgets[] = {
 {    WWT_CAPTION, RESIZE_NONE, 13,   0, 335,   0,  13, STR_0307_OPENTTD,       STR_NULL},
-{     WWT_IMGBTN, RESIZE_NONE, 13,   0, 335,  14, 196, STR_NULL,               STR_NULL},
+{     WWT_IMGBTN, RESIZE_NONE, 13,   0, 335,  14, 176, STR_NULL,               STR_NULL},
 { WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167,  22,  33, STR_0140_NEW_GAME,      STR_02FB_START_A_NEW_GAME},
 { WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325,  22,  33, STR_0141_LOAD_GAME,     STR_02FC_LOAD_A_SAVED_GAME},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167,  40,  51, STR_0220_CREATE_SCENARIO,STR_02FE_CREATE_A_CUSTOMIZED_GAME},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325,  40,  51, STR_029A_PLAY_SCENARIO, STR_0303_START_A_NEW_GAME_USING},
-{    WWT_PANEL_2, RESIZE_NONE, 12,  10,  86,  59, 113, 0x1312,                 STR_030E_SELECT_TEMPERATE_LANDSCAPE},
-{    WWT_PANEL_2, RESIZE_NONE, 12,  90, 166,  59, 113, 0x1314,                 STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
-{    WWT_PANEL_2, RESIZE_NONE, 12, 170, 246,  59, 113, 0x1316,                 STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
-{    WWT_PANEL_2, RESIZE_NONE, 12, 250, 326,  59, 113, 0x1318,                 STR_0311_SELECT_TOYLAND_LANDSCAPE},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167,  40,  51, STR_029A_PLAY_SCENARIO, STR_0303_START_A_NEW_GAME_USING},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325,  40,  51, STR_PLAY_HEIGHTMAP,     STR_PLAY_HEIGHTMAP_HINT},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167,  58,  69, STR_0220_CREATE_SCENARIO,STR_02FE_CREATE_A_CUSTOMIZED_GAME},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325,  58,  69, STR_MULTIPLAYER,        STR_0300_SELECT_MULTIPLAYER_GAME},
 
-{      WWT_PANEL, RESIZE_NONE, 12, 219, 254, 120, 131, STR_NULL,               STR_NULL},
-{    WWT_TEXTBTN, RESIZE_NONE, 12, 255, 266, 120, 131, STR_0225,               STR_NULL},
-{      WWT_PANEL, RESIZE_NONE, 12, 279, 314, 120, 131, STR_NULL,               STR_NULL},
-{    WWT_TEXTBTN, RESIZE_NONE, 12, 315, 326, 120, 131, STR_0225,               STR_NULL},
+{    WWT_PANEL_2, RESIZE_NONE, 12,  10,  86,  77, 131, 0x1312,                 STR_030E_SELECT_TEMPERATE_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12,  90, 166,  77, 131, 0x1314,                 STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12, 170, 246,  77, 131, 0x1316,                 STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
+{    WWT_PANEL_2, RESIZE_NONE, 12, 250, 326,  77, 131, 0x1318,                 STR_0311_SELECT_TOYLAND_LANDSCAPE},
 
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167, 138, 149, STR_SINGLE_PLAYER,      STR_02FF_SELECT_SINGLE_PLAYER_GAME},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 138, 149, STR_MULTIPLAYER,        STR_0300_SELECT_MULTIPLAYER_GAME},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167, 159, 170, STR_0148_GAME_OPTIONS,  STR_0301_DISPLAY_GAME_OPTIONS},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 159, 170, STR_01FE_DIFFICULTY,    STR_0302_DISPLAY_DIFFICULTY_OPTIONS},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167, 177, 188, STR_CONFIG_PATCHES,     STR_CONFIG_PATCHES_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 177, 188, STR_0304_QUIT,          STR_0305_QUIT_OPENTTD},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167, 139, 150, STR_0148_GAME_OPTIONS,  STR_0301_DISPLAY_GAME_OPTIONS},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 139, 150, STR_01FE_DIFFICULTY,    STR_0302_DISPLAY_DIFFICULTY_OPTIONS},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 12,  10, 167, 157, 168, STR_CONFIG_PATCHES,     STR_CONFIG_PATCHES_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 157, 168, STR_0304_QUIT,          STR_0305_QUIT_OPENTTD},
 {    WIDGETS_END },
 };
 
 extern void HandleOnEditText(WindowEvent *e);
 extern void HandleOnEditTextCancel(void);
 
-static inline void CreateScenario(void) {_switch_mode = SM_EDITOR;}
-
 static inline void SetNewLandscapeType(byte landscape)
 {
 	_opt_newgame.landscape = landscape;
@@ -53,37 +47,21 @@
 
 static void SelectGameWndProc(Window *w, WindowEvent *e)
 {
-	/* We do +/- 6 for the map_xy because 64 is 2^6, but it is the lowest available element */
-	static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID};
-
 	switch (e->event) {
 	case WE_PAINT:
-		w->click_state = (w->click_state & ~(1 << 14) & ~(0xF << 6)) | (1 << (_opt_newgame.landscape + 6)) | (1 << 14);
+		w->click_state = (w->click_state & ~(0xF << 8)) | (1 << (_opt_newgame.landscape + 8));
 		SetDParam(0, STR_6801_EASY + _opt_newgame.diff_level);
 		DrawWindowWidgets(w);
-
-		DrawStringRightAligned(216, 121, STR_MAPSIZE, 0);
-		DrawString(223, 121, mapsizes[_patches_newgame.map_x - 6], 0x10);
-		DrawString(270, 121, STR_BY, 0);
-		DrawString(283, 121, mapsizes[_patches_newgame.map_y - 6], 0x10);
 		break;
 
 	case WE_CLICK:
 		switch (e->click.widget) {
-		case 2: AskForNewGameToStart(); break;
+		case 2: ShowGenerateLandscape(); break;
 		case 3: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
-		case 4: CreateScenario(); break;
-		case 5: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
-		case 6: case 7: case 8: case 9:
-			SetNewLandscapeType(e->click.widget - 6);
-			break;
-		case 10: case 11: /* Mapsize X */
-			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_x - 6, 11, 0, 0);
-			break;
-		case 12: case 13: /* Mapsize Y */
-			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_y - 6, 13, 0, 0);
-			break;
-		case 15:
+		case 4: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
+		case 5: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
+		case 6: ShowCreateScenario(); break;
+		case 7:
 #ifdef ENABLE_NETWORK
 			if (!_network_available) {
 				ShowErrorMessage(INVALID_STRING_ID, STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
@@ -94,32 +72,20 @@
 			ShowErrorMessage(INVALID_STRING_ID ,STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
 #endif
 			break;
-		case 16: ShowGameOptions(); break;
-		case 17: ShowGameDifficulty(); break;
-		case 18: ShowPatchesSelection(); break;
-		case 19: AskExitGame(); break;
+		case 8: case 9: case 10: case 11:
+			SetNewLandscapeType(e->click.widget - 8);
+			break;
+		case 12: ShowGameOptions(); break;
+		case 13: ShowGameDifficulty(); break;
+		case 14: ShowPatchesSelection(); break;
+		case 15: AskExitGame(); break;
 		}
 		break;
-
-	case WE_ON_EDIT_TEXT: HandleOnEditText(e); break;
-	case WE_ON_EDIT_TEXT_CANCEL: HandleOnEditTextCancel(); break;
-
-	case WE_DROPDOWN_SELECT: /* Mapsize selection */
-		switch (e->dropdown.button) {
-			/* We need a *hacky* here because generateworld is called with _patches
-			 * but it only gets the new value INSIDE generateworld so not setting it would
-			 * break generating a new game on the run (eg MP) */
-			case 11: _patches.map_x = _patches_newgame.map_x = e->dropdown.index + 6; break;
-			case 13: _patches.map_y = _patches_newgame.map_y = e->dropdown.index + 6; break;
-		}
-		SetWindowDirty(w);
-		break;
 	}
-
 }
 
 static const WindowDesc _select_game_desc = {
-	WDP_CENTER, WDP_CENTER, 336, 197,
+	WDP_CENTER, WDP_CENTER, 336, 177,
 	WC_SELECT_GAME,0,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_select_game_widgets,
@@ -131,22 +97,6 @@
 	AllocateWindowDesc(&_select_game_desc);
 }
 
-void GenRandomNewGame(uint32 rnd1, uint32 rnd2)
-{
-	_random_seeds[0][0] = rnd1;
-	_random_seeds[0][1] = rnd2;
-
-	SwitchMode(SM_NEWGAME);
-}
-
-void StartScenarioEditor(uint32 rnd1, uint32 rnd2)
-{
-	_random_seeds[0][0] = rnd1;
-	_random_seeds[0][1] = rnd2;
-
-	SwitchMode(SM_START_SCENARIO);
-}
-
 static const Widget _ask_abandon_game_widgets[] = {
 { WWT_CLOSEBOX, RESIZE_NONE,  4,   0,  10,   0,  13, STR_00C5,      STR_018B_CLOSE_WINDOW},
 {  WWT_CAPTION, RESIZE_NONE,  4,  11, 179,   0,  13, STR_00C7_QUIT, STR_NULL},
--- a/landscape.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/landscape.c	Sat Aug 19 10:00:30 2006 +0000
@@ -2,6 +2,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "heightmap.h"
 #include "clear_map.h"
 #include "functions.h"
 #include "map.h"
@@ -16,6 +17,9 @@
 #include "variables.h"
 #include "void_map.h"
 #include "water_map.h"
+#include "tgp.h"
+#include "genworld.h"
+#include "heightmap.h"
 
 extern const TileTypeProcs
 	_tile_type_clear_procs,
@@ -409,10 +413,34 @@
 void ConvertGroundTilesIntoWaterTiles(void)
 {
 	TileIndex tile;
+	uint z;
+	Slope slope;
 
 	for (tile = 0; tile < MapSize(); ++tile) {
-		if (IsTileType(tile, MP_CLEAR) && GetTileMaxZ(tile) == 0) {
-			MakeWater(tile);
+		slope = GetTileSlope(tile, &z);
+		if (IsTileType(tile, MP_CLEAR) && z == 0) {
+			/* Make both water for tiles at level 0
+			 * and make shore, as that looks much better
+			 * during the generation. */
+			switch (slope) {
+				case SLOPE_FLAT:
+					MakeWater(tile);
+					break;
+
+				case SLOPE_N:
+				case SLOPE_E:
+				case SLOPE_S:
+				case SLOPE_W:
+				case SLOPE_NW:
+				case SLOPE_SW:
+				case SLOPE_SE:
+				case SLOPE_NE:
+					MakeShore(tile);
+					break;
+
+				default:
+					break;
+			}
 		}
 	}
 }
@@ -547,10 +575,13 @@
 static void CreateDesertOrRainForest(void)
 {
 	TileIndex tile;
+	TileIndex update_freq = MapSize() / 4;
 	const TileIndexDiffC *data;
 	uint i;
 
 	for (tile = 0; tile != MapSize(); ++tile) {
+		if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
 		for (data = _make_desert_or_rainforest_data;
 				data != endof(_make_desert_or_rainforest_data); ++data) {
 			TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data));
@@ -560,10 +591,15 @@
 			SetTropicZone(tile, TROPICZONE_DESERT);
 	}
 
-	for (i = 0; i != 256; i++)
+	for (i = 0; i != 256; i++) {
+		if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
 		RunTileLoop();
+	}
 
 	for (tile = 0; tile != MapSize(); ++tile) {
+		if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
 		for (data = _make_desert_or_rainforest_data;
 				data != endof(_make_desert_or_rainforest_data); ++data) {
 			TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data));
@@ -574,49 +610,71 @@
 	}
 }
 
-void GenerateLandscape(void)
+void GenerateLandscape(byte mode)
 {
+	const int gwp_desert_amount = 4 + 8;
 	uint i;
 	uint flag;
 	uint32 r;
 
-	switch (_opt.landscape) {
-		case LT_HILLY:
-			for (i = ScaleByMapSize((Random() & 0x7F) + 950); i != 0; --i) {
-				GenerateTerrain(2, 0);
-			}
-
-			r = Random();
-			flag = GB(r, 0, 2) | 4;
-			for (i = ScaleByMapSize(GB(r, 16, 7) + 450); i != 0; --i) {
-				GenerateTerrain(4, flag);
-			}
-			break;
-
-		case LT_DESERT:
-			for (i = ScaleByMapSize((Random() & 0x7F) + 170); i != 0; --i) {
-				GenerateTerrain(0, 0);
-			}
+	if (mode == GW_HEIGHTMAP) {
+		SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_DESERT) ? 1 + gwp_desert_amount : 1);
+		LoadHeightmap(_file_to_saveload.name);
+		IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+	} else if (_patches.land_generator == LG_TERRAGENESIS) {
+		SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_DESERT) ? 3 + gwp_desert_amount : 3);
+		GenerateTerrainPerlin();
+	} else {
+		switch (_opt.landscape) {
+			case LT_HILLY:
+				SetGeneratingWorldProgress(GWP_LANDSCAPE, 2);
 
-			r = Random();
-			flag = GB(r, 0, 2) | 4;
-			for (i = ScaleByMapSize(GB(r, 16, 8) + 1700); i != 0; --i) {
-				GenerateTerrain(0, flag);
-			}
-
-			flag ^= 2;
+				for (i = ScaleByMapSize((Random() & 0x7F) + 950); i != 0; --i) {
+					GenerateTerrain(2, 0);
+				}
+				IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
 
-			for (i = ScaleByMapSize((Random() & 0x7F) + 410); i != 0; --i) {
-				GenerateTerrain(3, flag);
-			}
-			break;
+				r = Random();
+				flag = GB(r, 0, 2) | 4;
+				for (i = ScaleByMapSize(GB(r, 16, 7) + 450); i != 0; --i) {
+					GenerateTerrain(4, flag);
+				}
+				IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+				break;
 
-		default:
-			i = ScaleByMapSize((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100);
-			for (; i != 0; --i) {
-				GenerateTerrain(_opt.diff.terrain_type, 0);
-			}
-			break;
+			case LT_DESERT:
+				SetGeneratingWorldProgress(GWP_LANDSCAPE, 3 + gwp_desert_amount);
+
+				for (i = ScaleByMapSize((Random() & 0x7F) + 170); i != 0; --i) {
+					GenerateTerrain(0, 0);
+				}
+				IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
+				r = Random();
+				flag = GB(r, 0, 2) | 4;
+				for (i = ScaleByMapSize(GB(r, 16, 8) + 1700); i != 0; --i) {
+					GenerateTerrain(0, flag);
+				}
+				IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
+				flag ^= 2;
+
+				for (i = ScaleByMapSize((Random() & 0x7F) + 410); i != 0; --i) {
+					GenerateTerrain(3, flag);
+				}
+				IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+				break;
+
+			default:
+				SetGeneratingWorldProgress(GWP_LANDSCAPE, 1);
+
+				i = ScaleByMapSize((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100);
+				for (; i != 0; --i) {
+					GenerateTerrain(_opt.diff.terrain_type, 0);
+				}
+				IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+				break;
+		}
 	}
 
 	ConvertGroundTilesIntoWaterTiles();
--- a/lang/english.txt	Sat Aug 19 09:31:22 2006 +0000
+++ b/lang/english.txt	Sat Aug 19 10:00:30 2006 +0000
@@ -604,6 +604,8 @@
 STR_022A_GENERATE_RANDOM_LAND                                   :{BLACK}Generate random land
 STR_022B_RESET_LANDSCAPE                                        :{BLACK}Reset landscape
 STR_022C_RESET_LANDSCAPE                                        :{WHITE}Reset Landscape
+STR_LOAD_GAME_HEIGHTMAP                                         :{WHITE}Use Heightmap
+STR_LOAD_SCEN_HEIGHTMAP                                         :{BLACK}Use Heightmap
 STR_022D_ARE_YOU_SURE_YOU_WANT_TO                               :{WHITE}Are you sure you want to reset the landscape?
 STR_022E_LANDSCAPE_GENERATION                                   :{BLACK}Landscape generation
 STR_022F_TOWN_GENERATION                                        :{BLACK}Town generation
@@ -716,6 +718,8 @@
 STR_0298_LOAD_SCENARIO                                          :{WHITE}Load Scenario
 STR_0299_SAVE_SCENARIO                                          :{WHITE}Save Scenario
 STR_029A_PLAY_SCENARIO                                          :{BLACK}Play Scenario
+STR_PLAY_HEIGHTMAP                                              :{BLACK}Play Heightmap
+STR_PLAY_HEIGHTMAP_HINT                                         :{BLACK}Start a new game, using a heightmap as landscape
 STR_029B_ARE_YOU_SURE_YOU_WANT_TO                               :{YELLOW}Are you sure you want to quit this scenario ?
 STR_029C_QUIT_EDITOR                                            :{WHITE}Quit Editor
 STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS                             :{WHITE}...can only be built in towns with a population of at least 1200
@@ -1039,7 +1043,27 @@
 STR_CONFIG_PATCHES_ERRMSG_DURATION                              :{LTBLUE}Duration of error message: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_POPULATION_IN_LABEL                          :{LTBLUE}Show town population in the town name label: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_INVISIBLE_TREES                              :{LTBLUE}Invisible trees (with transparent buildings): {ORANGE}{STRING1}
+
+STR_CONFIG_PATCHES_LAND_GENERATOR                               :{LTBLUE}Land generator: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL                      :Original
+STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS                 :TerraGenesis
+STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Max distance from edge for Oil Refineries {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_SNOWLINE_HEIGHT                              :{LTBLUE}Snow line height: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN                         :{LTBLUE}Roughness of terrain (TerraGenesis only) : {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH             :Very Smooth
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH                  :Smooth
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH                   :Rough
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH              :Very Rough
+STR_CONFIG_PATCHES_TREE_PLACER                                  :{LTBLUE}Tree placer algorithm: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_TREE_PLACER_NONE                             :None
+STR_CONFIG_PATCHES_TREE_PLACER_ORIGINAL                         :Original
+STR_CONFIG_PATCHES_TREE_PLACER_IMPROVED                         :Improved
+STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION                           :{LTBLUE}Heightmap rotation: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE         :Counter clockwise
+STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE                 :Clockwise
+STR_CONFIG_PATCHES_PROGRESS_UPDATE_INTERVAL                     :{LTBLUE}Progress update interval: {ORANGE}{STRING1} ms
+STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT                         :{LTBLUE}The height level a flat scenario map gets: {ORANGE}{STRING1}
+
 STR_CONFIG_PATCHES_STATION_SPREAD                               :{LTBLUE}Max station spread: {ORANGE}{STRING1} {RED}Warning: High setting slows game
 STR_CONFIG_PATCHES_SERVICEATHELIPAD                             :{LTBLUE}Service helicopters at helipads automatically: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR                       :{LTBLUE}Link landscape toolbar to rail/road/water/airport toolbars: {ORANGE}{STRING1}
@@ -1434,6 +1458,17 @@
 STR_CONFIG_PATCHES_MAP_X                                        :{LTBLUE}X-size of map: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_MAP_Y                                        :{LTBLUE}Y-size of map: {ORANGE}{STRING1}
 
+
+##### PNG-MAP-Loader
+
+STR_PNGMAP_ERROR                                                :{WHITE}Cannot load landscape from PNG...
+STR_PNGMAP_ERR_FILE_NOT_FOUND                                   :{WHITE}...file not found.
+STR_PNGMAP_ERR_IMAGE_TYPE                                       :{WHITE}...could not convert image type. 8 or 24-bit PNG image needed.
+STR_PNGMAP_ERR_MISC                                             :{WHITE}...something just went wrong. Sorry. (probably corrupted file)
+
+STR_BMPMAP_ERROR                                                :{WHITE}Cannot load landscape from BMP...
+STR_BMPMAP_ERR_IMAGE_TYPE                                       :{WHITE}...could not convert image type.
+
 ##id 0x0800
 STR_0800_COST                                                   :{TINYFONT}{RED}Cost: {CURRENCY}
 STR_0801_COST                                                   :{RED}Cost: {CURRENCY}
@@ -1757,6 +1792,7 @@
 STR_400E_SELECT_NEW_GAME_TYPE                                   :{WHITE}Select New Game Type
 STR_400F_SELECT_SCENARIO_GREEN_PRE                              :{BLACK}Select scenario (green), pre-set game (blue), or random new game
 STR_4010_GENERATE_RANDOM_NEW_GAME                               :Generate random new game
+STR_4011_LOAD_HEIGHTMAP                                         :{WHITE}Load Heightmap
 
 ##id 0x4800
 STR_4800_IN_THE_WAY                                             :{WHITE}{STRING} in the way
@@ -2863,6 +2899,58 @@
 STR_PURCHASE_INFO_AIRCRAFT_CAPACITY                             :{BLACK}Capacity: {GOLD}{COMMA} passengers, {COMMA} bags of mail
 STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT                          :{BLACK}Powered Wagons: {GOLD}+{POWER}{BLACK} Weight: {GOLD}+{WEIGHT_S}
 
+########### String for New Landscape Generator
+
+STR_GENERATE                                                    :{WHITE}Generate
+STR_RANDOM                                                      :{BLACK}Randomise
+STR_RANDOM_HELP                                                 :{BLACK}Change the random seed used for Terrain Generation
+STR_WORLD_GENERATION_CAPTION                                    :{WHITE}World generation
+STR_RANDOM_SEED                                                 :{BLACK}Random Seed:
+STR_RANDOM_SEED_HELP                                            :{BLACK}Click to enter a random seed
+STR_LAND_GENERATOR                                              :{BLACK}Land generator:
+STR_TREE_PLACER                                                 :{BLACK}Tree algorithm:
+STR_HEIGHTMAP_ROTATION                                          :{BLACK}Heightmap rotation:
+STR_TERRAIN_TYPE                                                :{BLACK}Terrain type:
+STR_QUANTITY_OF_SEA_LAKES                                       :{BLACK}Sea level:
+STR_SMOOTHNESS                                                  :{BLACK}Smoothness:
+STR_SNOW_LINE_HEIGHT                                            :{BLACK}Snow line height:
+STR_DATE                                                        :{BLACK}Date:
+STR_NUMBER_OF_TOWNS                                             :{BLACK}No. of towns:
+STR_NUMBER_OF_INDUSTRIES                                        :{BLACK}No. of industries:
+STR_GENERATE_DATE                                               :{BLACK}{DATE_LONG}
+STR_SNOW_LINE_UP                                                :{BLACK}Move the snow line height one up
+STR_SNOW_LINE_DOWN                                              :{BLACK}Move the snow line height one down
+STR_SNOW_LINE_QUERY_CAPT                                        :{WHITE}Change snow line height
+STR_START_DATE_QUERY_CAPT                                       :{WHITE}Change starting year
+STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}Scale warning
+STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}Resizing source map too much is not recommended. Continue with the generation?
+STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
+STR_HEIGHTMAP_NAME                                              :{BLACK}Heightmap name:
+STR_HEIGHTMAP_SIZE                                              :{BLACK}Size: {ORANGE}{NUM} x {NUM}
+STR_GENERATION_WORLD                                            :{WHITE}Generating world...
+STR_GENERATION_ABORT                                            :{BLACK}Abort
+STR_GENERATION_ABORT_CAPTION                                    :{WHITE}Abort World Generation
+STR_GENERATION_ABORT_MESSAGE                                    :{YELLOW}Do you really want to abort the generation?
+STR_PROGRESS                                                    :{WHITE}{NUM}% complete
+STR_GENERATION_PROGRESS                                         :{BLACK}{NUM} / {NUM}
+STR_WORLD_GENERATION                                            :{BLACK}World generation
+STR_TREE_GENERATION                                             :{BLACK}Tree generation
+STR_UNMOVABLE_GENERATION                                        :{BLACK}Unmovable generation
+STR_CLEARING_TILES                                              :{BLACK}Rough and rocky area generation
+STR_SETTINGUP_GAME                                              :{BLACK}Setting up game
+STR_PREPARING_TILELOOP                                          :{BLACK}Running tile-loop
+STR_PREPARING_GAME                                              :{BLACK}Preparing game
+STR_DIFFICULTY_TO_CUSTOM                                        :{WHITE}This action changed the difficulty level to custom
+STR_SE_FLAT_WORLD                                               :{WHITE}Flat land
+STR_SE_RANDOM_LAND                                              :{WHITE}Random land
+STR_SE_NEW_WORLD                                                :{BLACK}Create new scenario
+STR_SE_CAPTION                                                  :{WHITE}Scenario type
+STR_FLAT_WORLD_HEIGHT_DOWN                                      :{BLACK}Move the height of flat land one down
+STR_FLAT_WORLD_HEIGHT_UP                                        :{BLACK}Move the height of flat land one up
+STR_FLAT_WORLD_HEIGHT_QUERY_CAPT                                :{WHITE}Change height of flat land
+STR_FLAT_WORLD_HEIGHT                                           :{BLACK}Height of flat land:
+STR_FLAT_WORLD_HEIGHT_NUM                                       :{NUM}
+
 ########### String for new airports
 STR_SMALL_AIRPORT                                               :{BLACK}Small
 STR_CITY_AIRPORT                                                :{BLACK}City
--- a/macros.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/macros.h	Sat Aug 19 10:00:30 2006 +0000
@@ -180,4 +180,10 @@
  */
 #define ALIGN(x, n) (((x) + (n) - 1) & ~((n) - 1))
 
+/** return the largest value that can be entered in a variable.
+ *  known to work for uint32.
+ *  used by TGP to set the max value of the _patches.generation_seed in its definition
+ */
+#define MAX_UVALUE(type) ((type)~(type)0)
+
 #endif /* MACROS_H */
--- a/main_gui.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/main_gui.c	Sat Aug 19 10:00:30 2006 +0000
@@ -2,6 +2,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "heightmap.h"
 #include "currency.h"
 #include "functions.h"
 #include "spritecache.h"
@@ -29,22 +30,19 @@
 #include "train.h"
 #include "unmovable_map.h"
 #include "screenshot.h"
+#include "genworld.h"
+#include "settings.h"
 #include "date.h"
 
 #include "network_data.h"
 #include "network_client.h"
 #include "network_server.h"
 
-/* Min/Max date for scenario editor */
-static const Date MinDate = 0;     // 1920-01-01 (MAX_YEAR_BEGIN_REAL)
-static const Date MaxDate = 29220; // 2000-01-01
-
 static int _rename_id;
 static int _rename_what;
 
 static byte _terraform_size = 1;
 static RailType _last_built_railtype;
-extern void GenerateWorld(int mode, uint size_x, uint size_y);
 
 extern void GenerateIndustries(void);
 extern bool GenerateTowns(void);
@@ -1002,9 +1000,10 @@
 	// don't allow too fast scrolling
 	if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 		HandleButtonClick(w, 6);
-		InvalidateWidget(w, 5);
+		SetWindowDirty(w);
 
-		if (_date > MinDate) SetDate(ConvertYMDToDate(_cur_year - 1, 0, 1));
+		_patches_newgame.starting_year = clamp(_patches_newgame.starting_year - 1, MIN_YEAR, MAX_YEAR);
+		SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
 	}
 	_left_button_clicked = false;
 }
@@ -1014,9 +1013,10 @@
 	// don't allow too fast scrolling
 	if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 		HandleButtonClick(w, 7);
-		InvalidateWidget(w, 5);
+		SetWindowDirty(w);
 
-		if (_date < MaxDate) SetDate(ConvertYMDToDate(_cur_year + 1, 0, 1));
+		_patches_newgame.starting_year = clamp(_patches_newgame.starting_year + 1, MIN_YEAR, MAX_YEAR);
+		SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
 	}
 	_left_button_clicked = false;
 }
@@ -1051,7 +1051,7 @@
 
 	vp = w->viewport;
 
-	if (_game_mode != GM_MENU) {
+	if (_game_mode != GM_MENU && !IsGeneratingWorld()) {
 		if ((in && vp->zoom == 0) || (!in && vp->zoom == 2))
 			return;
 
@@ -1064,74 +1064,6 @@
 	}
 }
 
-static void ResetLandscape(void)
-{
-	_random_seeds[0][0] = InteractiveRandom();
-	_random_seeds[0][1] = InteractiveRandom();
-
-	GenerateWorld(GW_EMPTY, 1 << _patches.map_x, 1 << _patches.map_y);
-	MarkWholeScreenDirty();
-}
-
-static const Widget _ask_reset_landscape_widgets[] = {
-{   WWT_CLOSEBOX,   RESIZE_NONE,     4,     0,    10,     0,    13, STR_00C5,									STR_018B_CLOSE_WINDOW},
-{    WWT_CAPTION,   RESIZE_NONE,     4,    11,   179,     0,    13, STR_022C_RESET_LANDSCAPE,	STR_NULL},
-{     WWT_IMGBTN,   RESIZE_NONE,     4,     0,   179,    14,    91, 0x0,												STR_NULL},
-{    WWT_TEXTBTN,   RESIZE_NONE,    12,    25,    84,    72,    83, STR_00C9_NO,								STR_NULL},
-{    WWT_TEXTBTN,   RESIZE_NONE,    12,    95,   154,    72,    83, STR_00C8_YES,							STR_NULL},
-{   WIDGETS_END},
-};
-
-// Ask first to reset landscape or to make a random landscape
-static void AskResetLandscapeWndProc(Window *w, WindowEvent *e)
-{
-	uint mode = w->window_number;
-
-	switch (e->event) {
-	case WE_PAINT:
-		DrawWindowWidgets(w);
-		DrawStringMultiCenter(
-			90, 38,
-			mode ? STR_022D_ARE_YOU_SURE_YOU_WANT_TO : STR_GENERATE_RANDOM_LANDSCAPE,
-			168
-		);
-		break;
-	case WE_CLICK:
-		switch (e->click.widget) {
-		case 3:
-			DeleteWindow(w);
-			break;
-		case 4:
-			DeleteWindow(w);
-			DeleteWindowByClass(WC_INDUSTRY_VIEW);
-			DeleteWindowByClass(WC_TOWN_VIEW);
-			DeleteWindowByClass(WC_LAND_INFO);
-
-			if (mode) { // reset landscape
-				ResetLandscape();
-			} else { // make random landscape
-				SndPlayFx(SND_15_BEEP);
-				_switch_mode = SM_GENRANDLAND;
-			}
-			break;
-		}
-		break;
-	}
-}
-
-static const WindowDesc _ask_reset_landscape_desc = {
-	230,205, 180, 92,
-	WC_ASK_RESET_LANDSCAPE,0,
-	WDF_STD_BTN | WDF_DEF_WIDGET,
-	_ask_reset_landscape_widgets,
-	AskResetLandscapeWndProc,
-};
-
-static void AskResetLandscape(uint mode)
-{
-	AllocateWindowDescFront(&_ask_reset_landscape_desc, mode);
-}
-
 // TODO - Incorporate into game itself to allow for ingame raising/lowering of
 // larger chunks at the same time OR remove altogether, as we have 'level land' ?
 /**
@@ -1238,8 +1170,7 @@
 {  WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                  STR_018B_CLOSE_WINDOW},
 {   WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0223_LAND_GENERATION,  STR_018C_WINDOW_TITLE_DRAG_THIS},
 { WWT_STICKYBOX,   RESIZE_NONE,     7,   170,   181,     0,    13, STR_NULL,                  STR_STICKY_BUTTON},
-{    WWT_IMGBTN,   RESIZE_NONE,     7,     0,   181,    14,   101, STR_NULL,                  STR_NULL},
-
+{    WWT_IMGBTN,   RESIZE_NONE,     7,     0,   181,    14,    95, STR_NULL,                  STR_NULL},
 {    WWT_IMGBTN,   RESIZE_NONE,    14,     2,    23,    14,    35, SPR_IMG_DYNAMITE,          STR_018D_DEMOLISH_BUILDINGS_ETC},
 {    WWT_IMGBTN,   RESIZE_NONE,    14,    24,    45,    14,    35, SPR_IMG_TERRAFORM_DOWN,    STR_018E_LOWER_A_CORNER_OF_LAND},
 {    WWT_IMGBTN,   RESIZE_NONE,    14,    46,    67,    14,    35, SPR_IMG_TERRAFORM_UP,      STR_018F_RAISE_A_CORNER_OF_LAND},
@@ -1250,8 +1181,7 @@
 {    WWT_IMGBTN,   RESIZE_NONE,    14,   158,   179,    14,    35, SPR_IMG_TRANSMITTER,       STR_028E_PLACE_TRANSMITTER},
 {   WWT_TEXTBTN,   RESIZE_NONE,    14,   139,   149,    43,    54, STR_0224,                  STR_0228_INCREASE_SIZE_OF_LAND_AREA},
 {   WWT_TEXTBTN,   RESIZE_NONE,    14,   139,   149,    56,    67, STR_0225,                  STR_0229_DECREASE_SIZE_OF_LAND_AREA},
-{   WWT_TEXTBTN,   RESIZE_NONE,    14,    34,   149,    75,    86, STR_0226_RANDOM_LAND,      STR_022A_GENERATE_RANDOM_LAND},
-{   WWT_TEXTBTN,   RESIZE_NONE,    14,    34,   149,    88,    99, STR_0227_RESET_LAND,       STR_022B_RESET_LANDSCAPE},
+{   WWT_TEXTBTN,   RESIZE_NONE,    14,    34,   149,    75,    86, STR_SE_NEW_WORLD,          STR_022A_GENERATE_RANDOM_LAND},
 {   WIDGETS_END},
 };
 
@@ -1388,11 +1318,7 @@
 		} break;
 		case 14: /* gen random land */
 			HandleButtonClick(w, 14);
-			AskResetLandscape(0);
-			break;
-		case 15: /* reset landscape */
-			HandleButtonClick(w,15);
-			AskResetLandscape(1);
+			ShowCreateScenario();
 			break;
 		}
 		break;
@@ -1422,7 +1348,7 @@
 }
 
 static const WindowDesc _scen_edit_land_gen_desc = {
-	-1,-1, 182, 102,
+	-1,-1, 182, 96,
 	WC_SCEN_LAND_GEN,0,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_scen_edit_land_gen_widgets,
@@ -1879,6 +1805,8 @@
 	case WE_KEYPRESS: {
 		PlayerID local = (_local_player != OWNER_SPECTATOR) ? _local_player : 0;
 
+		if (IsGeneratingWorld()) break;
+
 		switch (e->keypress.keycode) {
 		case WKC_F1: case WKC_PAUSE:
 			ToolbarPauseClick(w);
@@ -2062,13 +1990,12 @@
 {
 	switch (e->event) {
 	case WE_PAINT:
-		/* XXX look for better place for these */
-		if (_date <= MinDate) {
+		if (_patches_newgame.starting_year <= MIN_YEAR) {
 			SETBIT(w->disabled_state, 6);
 		} else {
 			CLRBIT(w->disabled_state, 6);
 		}
-		if (_date >= MaxDate) {
+		if (_patches_newgame.starting_year >= MAX_YEAR) {
 			SETBIT(w->disabled_state, 7);
 		} else {
 			CLRBIT(w->disabled_state, 7);
@@ -2080,10 +2007,10 @@
 
 		DrawWindowWidgets(w);
 
-		SetDParam(0, _date);
+		SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
 		DrawStringCentered(298, 6, STR_00AF, 0);
 
-		SetDParam(0, _date);
+		SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
 		DrawStringCentered(161, 1, STR_0221_OPENTTD, 0);
 		DrawStringCentered(161, 11,STR_0222_SCENARIO_EDITOR, 0);
 
@@ -2207,7 +2134,7 @@
 			70, 1, (_pause || _patches.status_long_date) ? STR_00AF : STR_00AE, 0
 		);
 
-		if (p != NULL) {
+		if (p != NULL && !IsGeneratingWorld()) {
 			// Draw player money
 			SetDParam64(0, p->money64);
 			DrawStringCentered(570, 1, p->player_money >= 0 ? STR_0004 : STR_0005, 0);
@@ -2225,7 +2152,7 @@
 			if (!DrawScrollingStatusText(&_statusbar_news_item, WP(w,def_d).data_1))
 				WP(w,def_d).data_1 = -1280;
 		} else {
-			if (p != NULL) {
+			if (p != NULL && !IsGeneratingWorld()) {
 				// This is the default text
 				SetDParam(0, p->name_1);
 				SetDParam(1, p->name_2);
@@ -2327,7 +2254,7 @@
 
 	case WE_KEYPRESS:
 		if (e->keypress.keycode == WKC_BACKQUOTE) {
-			IConsoleSwitch();
+			if (!IsGeneratingWorld()) IConsoleSwitch();
 			e->keypress.cont = false;
 			break;
 		}
@@ -2339,7 +2266,7 @@
 				break;
 		}
 
-		if (_game_mode == GM_MENU) break;
+		if (_game_mode == GM_MENU || IsGeneratingWorld()) break;
 
 		switch (e->keypress.keycode) {
 			case 'C':
@@ -2435,11 +2362,7 @@
 		w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
 		AssignWindowViewport(w, 0, 0, width, height, 0, 0);
 
-		w = AllocateWindowDesc(&_toolb_scen_desc);
-		w->disabled_state = 1 << 9;
-		CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
-
-		PositionMainToolbar(w); // already WC_MAIN_TOOLBAR passed (&_toolb_scen_desc)
+		ShowVitalWindows();
 		break;
 	default:
 		NOT_REACHED();
@@ -2450,17 +2373,31 @@
 {
 	Window *w;
 
-	w = AllocateWindowDesc(&_toolb_normal_desc);
-	w->disabled_state = 1 << 17; // disable zoom-in button (by default game is zoomed in)
+	if (_game_mode != GM_EDITOR) {
+		w = AllocateWindowDesc(&_toolb_normal_desc);
+		/* Disable zoom-in for normal things, and zoom-out if we come
+		 *  from world-generating. */
+		w->disabled_state = IsGeneratingWorld() ? (1 << 18) : (1 << 17);
+	} else {
+		w = AllocateWindowDesc(&_toolb_scen_desc);
+		/* Disable zoom-in for normal things, and zoom-out if we come
+		 *  from world-generating. */
+		w->disabled_state = IsGeneratingWorld() ? (1 << 10) : (1 << 9);
+	}
 	CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
 
-	if (_networking) { // if networking, disable fast-forward button
+	if (_networking) {
+		/* If networking, disable fast-forward button */
 		SETBIT(w->disabled_state, 1);
-		if (!_network_server) // if not server, disable pause button
-			SETBIT(w->disabled_state, 0);
+		/* If not server, disable pause button */
+		if (!_network_server) SETBIT(w->disabled_state, 0);
 	}
 
-	PositionMainToolbar(w); // already WC_MAIN_TOOLBAR passed (&_toolb_normal_desc)
+	/* 'w' is for sure a WC_MAIN_TOOLBAR */
+	PositionMainToolbar(w);
+
+	/* Status bad only for normal games */
+	if (_game_mode == GM_EDITOR) return;
 
 	_main_status_desc.top = _screen.height - 12;
 	w = AllocateWindowDesc(&_main_status_desc);
--- a/misc.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/misc.c	Sat Aug 19 10:00:30 2006 +0000
@@ -19,8 +19,6 @@
 #include "table/landscape_const.h"
 #include "date.h"
 
-extern void StartupEconomy(void);
-
 char _name_array[512][32];
 
 #ifndef MERSENNE_TWISTER
@@ -96,19 +94,6 @@
 static void InitializeCheats(void);
 void InitializeNPF(void);
 
-void GenerateLandscape(void);
-void GenerateClearTile(void);
-
-void GenerateIndustries(void);
-void GenerateUnmovables(void);
-bool GenerateTowns(void);
-
-void StartupPlayers(void);
-void StartupDisasters(void);
-void GenerateTrees(void);
-
-void ConvertGroundTilesIntoWaterTiles(void);
-
 void InitializeGame(int mode, uint size_x, uint size_y)
 {
 	AllocateMap(size_x, size_y);
@@ -165,53 +150,6 @@
 	ResetObjectToPlace();
 }
 
-void GenerateWorld(int mode, uint size_x, uint size_y)
-{
-	// Make sure everything is done via OWNER_NONE
-	_current_player = OWNER_NONE;
-
-	UpdatePatches();
-
-	_generating_world = true;
-	InitializeGame(mode == GW_RANDOM ? 0 : IG_DATE_RESET, size_x, size_y);
-	SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0);
-
-	// Must start economy early because of the costs.
-	StartupEconomy();
-
-	// Don't generate landscape items when in the scenario editor.
-	if (mode == GW_EMPTY) {
-		// empty world in scenario editor
-		ConvertGroundTilesIntoWaterTiles();
-	} else {
-		GenerateLandscape();
-		GenerateClearTile();
-
-		// only generate towns, tree and industries in newgame mode.
-		if (mode == GW_NEWGAME) {
-			GenerateTowns();
-			GenerateTrees();
-			GenerateIndustries();
-			GenerateUnmovables();
-		}
-	}
-
-	// These are probably pointless when inside the scenario editor.
-	StartupPlayers();
-	StartupEngines();
-	StartupDisasters();
-	_generating_world = false;
-
-	// No need to run the tile loop in the scenario editor.
-	if (mode != GW_EMPTY) {
-		uint i;
-
-		for (i = 0; i < 0x500; i++) RunTileLoop();
-	}
-
-	ResetObjectToPlace();
-}
-
 void DeleteName(StringID id)
 {
 	if ((id & 0xF800) == 0x7800) {
--- a/misc_gui.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/misc_gui.c	Sat Aug 19 10:00:30 2006 +0000
@@ -3,6 +3,7 @@
 #include "stdafx.h"
 #include "openttd.h"
 #include "hal.h"
+#include "heightmap.h"
 #include "debug.h"
 #include "functions.h"
 #include "gfxinit.h"
@@ -26,6 +27,8 @@
 #include "variables.h"
 #include "vehicle.h"
 #include "train.h"
+#include "tgp.h"
+#include "settings.h"
 #include "date.h"
 
 #include "fios.h"
@@ -33,6 +36,9 @@
 FiosItem *_fios_list;
 int _saveload_mode;
 
+extern void GenerateLandscape(byte mode);
+extern void SwitchMode(int new_mode);
+
 static bool _fios_path_changed;
 static bool _savegame_sort_dirty;
 
@@ -1094,6 +1100,72 @@
 	UpdateTextBufferSize(&WP(w, querystr_d).text);
 }
 
+static void QueryWndProc(Window *w, WindowEvent *e)
+{
+	switch (e->event) {
+	case WE_PAINT:
+		SetDParam(0, WP(w, query_d).caption);
+		DrawWindowWidgets(w);
+
+		DrawStringMultiCenter(90, 38, WP(w, query_d).message, 178);
+		break;
+
+	case WE_CLICK:
+		switch (e->click.widget) {
+		case 3:
+		case 4:
+			WP(w, query_d).calledback = true;
+			if (WP(w, query_d).ok_cancel_callback != NULL) WP(w, query_d).ok_cancel_callback(e->click.widget == 4);
+			DeleteWindow(w);
+			break;
+		}
+		break;
+
+	case WE_MOUSELOOP:
+		if (!FindWindowById(WP(w, query_d).wnd_class, WP(w, query_d).wnd_num)) DeleteWindow(w);
+		break;
+
+	case WE_DESTROY:
+		if (!WP(w, query_d).calledback && WP(w, query_d).ok_cancel_callback != NULL) WP(w, query_d).ok_cancel_callback(false);
+		break;
+	}
+}
+
+static const Widget _query_widgets[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE,  4,   0,  10,   0,  13, STR_00C5,        STR_018B_CLOSE_WINDOW},
+{  WWT_CAPTION, RESIZE_NONE,  4,  11, 179,   0,  13, STR_012D,        STR_NULL},
+{   WWT_IMGBTN, RESIZE_NONE,  4,   0, 179,  14,  91, 0x0,             STR_NULL},
+{  WWT_TEXTBTN, RESIZE_NONE, 12,  25,  84,  72,  83, STR_012E_CANCEL, STR_NULL},
+{  WWT_TEXTBTN, RESIZE_NONE, 12,  95, 154,  72,  83, STR_012F_OK,     STR_NULL},
+{  WIDGETS_END },
+};
+
+static const WindowDesc _query_desc = {
+	WDP_CENTER, WDP_CENTER, 180, 92,
+	WC_OK_CANCEL_QUERY, 0,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
+	_query_widgets,
+	QueryWndProc
+};
+
+void ShowQuery(StringID caption, StringID message, void (*ok_cancel_callback)(bool ok_clicked), WindowClass window_class, WindowNumber window_number)
+{
+	Window *w;
+
+	DeleteWindowById(WC_OK_CANCEL_QUERY, 0);
+
+	w = AllocateWindowDesc(&_query_desc);
+
+	w->click_state = 1 << 5;
+	WP(w, query_d).caption            = caption;
+	WP(w, query_d).message            = message;
+	WP(w, query_d).wnd_class          = window_class;
+	WP(w, query_d).wnd_num            = window_number;
+	WP(w, query_d).ok_cancel_callback = ok_cancel_callback;
+	WP(w, query_d).calledback         = false;
+}
+
+
 static const Widget _load_dialog_1_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,						STR_018B_CLOSE_WINDOW},
 {    WWT_CAPTION,  RESIZE_RIGHT,    14,    11,   256,     0,    13, STR_4001_LOAD_GAME,	STR_018C_WINDOW_TITLE_DRAG_THIS},
@@ -1122,6 +1194,20 @@
 {   WIDGETS_END},
 };
 
+static const Widget _load_dialog_3_widgets[] = {
+{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13,  STR_00C5,           STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION,  RESIZE_RIGHT,    14,    11,   256,     0,    13,  STR_4011_LOAD_HEIGHTMAP,STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,   127,    14,    25,  STR_SORT_BY_NAME,   STR_SORT_ORDER_TIP},
+{ WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   128,   256,    14,    25,  STR_SORT_BY_DATE,   STR_SORT_ORDER_TIP},
+{     WWT_IMGBTN,  RESIZE_RIGHT,    14,     0,   256,    26,    47,  0x0,                STR_NULL},
+{     WWT_IMGBTN,     RESIZE_RB,    14,     0,   256,    48,   293,  0x0,                STR_NULL},
+{ WWT_PUSHIMGBTN,     RESIZE_LR,    14,   245,   256,    48,    59,  SPR_HOUSE_ICON,     STR_SAVELOAD_HOME_BUTTON},
+{          WWT_6,     RESIZE_RB,    14,     2,   243,    50,   291,  0x0,                STR_400A_LIST_OF_DRIVES_DIRECTORIES},
+{  WWT_SCROLLBAR,    RESIZE_LRB,    14,   245,   256,    60,   281,  0x0,                STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{  WWT_RESIZEBOX,   RESIZE_LRTB,    14,   245,   256,   282,   293,  0x0,                STR_RESIZE_BUTTON},
+{   WIDGETS_END},
+};
+
 static const Widget _save_dialog_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,						STR_018B_CLOSE_WINDOW},
 {    WWT_CAPTION,  RESIZE_RIGHT,    14,    11,   256,     0,    13, STR_4000_SAVE_GAME,	STR_018C_WINDOW_TITLE_DRAG_THIS},
@@ -1158,9 +1244,8 @@
 {   WIDGETS_END},
 };
 
-
 // Colors for fios types
-const byte _fios_colors[] = {13, 9, 9, 6, 5, 6, 5};
+const byte _fios_colors[] = {13, 9, 9, 6, 5, 6, 5, 6, 6, 8};
 
 void BuildFileList(void)
 {
@@ -1172,6 +1257,8 @@
 		case SLD_LOAD_SCENARIO:
 		case SLD_SAVE_SCENARIO:
 			_fios_list = FiosGetScenarioList(_saveload_mode); break;
+		case SLD_LOAD_HEIGHTMAP:
+			_fios_list = FiosGetHeightmapList(_saveload_mode); break;
 
 		default: _fios_list = FiosGetSavegameList(_saveload_mode); break;
 	}
@@ -1249,6 +1336,10 @@
 				ttd_strlcpy(&o_dir.name[0], _path.scenario_dir, sizeof(o_dir.name));
 				break;
 
+			case SLD_LOAD_HEIGHTMAP:
+				ttd_strlcpy(&o_dir.name[0], _path.heightmap_dir, sizeof(o_dir.name));
+				break;
+
 			default:
 				ttd_strlcpy(&o_dir.name[0], _path.personal_dir, sizeof(o_dir.name));
 		}
@@ -1331,6 +1422,13 @@
 					ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
 
 					DeleteWindow(w);
+				} else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
+					SetFiosType(file->type);
+					ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+					ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
+
+					DeleteWindow(w);
+					ShowHeightmapLoad();
 				} else {
 					// SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox
 					ttd_strlcpy(WP(w, querystr_d).text.buf, file->title, WP(w, querystr_d).text.maxlength);
@@ -1442,11 +1540,20 @@
 	SaveLoadDlgWndProc,
 };
 
+static const WindowDesc _load_dialog_heightmap_desc = {
+	WDP_CENTER, WDP_CENTER, 257, 294,
+	WC_SAVELOAD,0,
+	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
+	_load_dialog_3_widgets,
+	SaveLoadDlgWndProc,
+};
+
 static const WindowDesc * const _saveload_dialogs[] = {
 	&_load_dialog_desc,
 	&_load_dialog_scen_desc,
 	&_save_dialog_desc,
 	&_save_dialog_scen_desc,
+	&_load_dialog_heightmap_desc,
 };
 
 void ShowSaveLoadDialog(int mode)
@@ -1493,107 +1600,6 @@
 	SetWindowDirty(FindWindowById(WC_STATUS_BAR, 0));
 }
 
-static const Widget _select_scenario_widgets[] = {
-{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,						STR_018B_CLOSE_WINDOW},
-{    WWT_CAPTION,  RESIZE_RIGHT,     7,    11,   256,     0,    13, STR_400E_SELECT_NEW_GAME_TYPE, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{     WWT_IMGBTN,  RESIZE_RIGHT,     7,     0,   256,    14,    25, 0x0,								STR_NULL},
-{ WWT_PUSHTXTBTN,   RESIZE_NONE,     7,     0,   127,    14,    25, STR_SORT_BY_NAME,		STR_SORT_ORDER_TIP},
-{ WWT_PUSHTXTBTN,   RESIZE_NONE,     7,   128,   256,    14,    25, STR_SORT_BY_DATE,		STR_SORT_ORDER_TIP},
-{     WWT_IMGBTN,     RESIZE_RB,     7,     0,   244,    26,   319, 0x0,								STR_NULL},
-{          WWT_6,     RESIZE_RB,     7,     2,   243,    28,   317, 0x0,								STR_400F_SELECT_SCENARIO_GREEN_PRE},
-{  WWT_SCROLLBAR,    RESIZE_LRB,     7,   245,   256,    26,   307, 0x0,								STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{  WWT_RESIZEBOX,   RESIZE_LRTB,     7,   245,   256,   308,   319, 0x0,								STR_RESIZE_BUTTON},
-{   WIDGETS_END},
-};
-
-static void SelectScenarioWndProc(Window *w, WindowEvent *e)
-{
-	const int list_start = 45;
-
-	switch (e->event) {
-	case WE_PAINT: {
-		int y,pos;
-		const FiosItem *item;
-
-		if (_savegame_sort_dirty) {
-			_savegame_sort_dirty = false;
-			MakeSortedSaveGameList();
-		}
-
-		SetVScrollCount(w, _fios_num);
-
-		DrawWindowWidgets(w);
-		DoDrawString(
-			_savegame_sort_order & SORT_DESCENDING ? DOWNARROW : UPARROW,
-			_savegame_sort_order & SORT_BY_NAME ? w->widget[3].right - 9 : w->widget[4].right - 9,
-			15, 16
-		);
-		DrawString(4, 32, STR_4010_GENERATE_RANDOM_NEW_GAME, 9);
-
-		y = list_start;
-		pos = w->vscroll.pos;
-		while (pos < _fios_num) {
-			item = _fios_list + pos;
-			DoDrawString(item->title, 4, y, _fios_colors[item->type]);
-			pos++;
-			y += 10;
-			if (y >= w->vscroll.cap * 10 + list_start) break;
-		}
-	}
-		break;
-
-	case WE_CLICK:
-		switch (e->click.widget) {
-		case 3: /* Sort scenario names by name */
-			_savegame_sort_order = (_savegame_sort_order == SORT_BY_NAME) ?
-				SORT_BY_NAME | SORT_DESCENDING : SORT_BY_NAME;
-			_savegame_sort_dirty = true;
-			SetWindowDirty(w);
-			break;
-
-		case 4: /* Sort scenario names by date */
-			_savegame_sort_order = (_savegame_sort_order == SORT_BY_DATE) ?
-				SORT_BY_DATE | SORT_DESCENDING : SORT_BY_DATE;
-			_savegame_sort_dirty = true;
-			SetWindowDirty(w);
-			break;
-
-		case 6: /* Click the listbox */
-			if (e->click.pt.y < list_start) {
-				GenRandomNewGame(Random(), InteractiveRandom());
-			} else {
-				int y = (e->click.pt.y - list_start) / 10;
-				const char *name;
-				const FiosItem *file;
-
-				if (y < 0 || (y += w->vscroll.pos) >= w->vscroll.count) return;
-
-				file = _fios_list + y;
-
-				name = FiosBrowseTo(file);
-				if (name != NULL) {
-					SetFiosType(file->type);
-					strcpy(_file_to_saveload.name, name);
-					DeleteWindow(w);
-					StartScenarioEditor(Random(), InteractiveRandom());
-				}
-			}
-			break;
-		}
-		break;
-
-	case WE_RESIZE: {
-		/* Widget 3 and 4 have to go with halve speed, make it so obiwan */
-		uint diff = e->sizing.diff.x / 2;
-		w->widget[3].right += diff;
-		w->widget[4].left  += diff;
-		w->widget[4].right += e->sizing.diff.x;
-
-		w->vscroll.cap += e->sizing.diff.y / 10;
-		} break;
-	}
-}
-
 void SetFiosType(const byte fiostype)
 {
 	switch (fiostype) {
@@ -1607,37 +1613,22 @@
 			_file_to_saveload.mode = SL_OLD_LOAD;
 			break;
 
+#ifdef WITH_PNG
+		case FIOS_TYPE_PNG:
+			_file_to_saveload.mode = SL_PNG;
+			break;
+#endif /* WITH_PNG */
+
+		case FIOS_TYPE_BMP:
+			_file_to_saveload.mode = SL_BMP;
+			break;
+
 		default:
 			_file_to_saveload.mode = SL_INVALID;
 			break;
 	}
 }
 
-static const WindowDesc _select_scenario_desc = {
-	WDP_CENTER, WDP_CENTER, 257, 320,
-	WC_SAVELOAD,0,
-	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
-	_select_scenario_widgets,
-	SelectScenarioWndProc
-};
-
-void AskForNewGameToStart(void)
-{
-	Window *w;
-
-	DeleteWindowById(WC_QUERY_STRING, 0);
-	DeleteWindowById(WC_SAVELOAD, 0);
-
-	_saveload_mode = SLD_NEW_GAME;
-	BuildFileList();
-
-	w = AllocateWindowDesc(&_select_scenario_desc);
-	w->vscroll.cap = 27;
-	w->resize.step_width = 2;
-	w->resize.step_height = 10;
-	w->resize.height = w->height - 10 * 17; // Minimum of 10 in the list
-}
-
 static int32 ClickMoneyCheat(int32 p1, int32 p2)
 {
 		DoCommandP(0, -10000000, 0, NULL, CMD_MONEY_CHEAT);
--- a/network_gui.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/network_gui.c	Sat Aug 19 10:00:30 2006 +0000
@@ -24,6 +24,7 @@
 #include "variables.h"
 #include "network_server.h"
 #include "network_udp.h"
+#include "settings.h"
 #include "string.h"
 
 #define BGC 5
@@ -57,6 +58,7 @@
 
 static void ShowNetworkStartServerWindow(void);
 static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
+extern void SwitchMode(int new_mode);
 
 static const StringID _connection_types_dropdown[] = {
 	STR_NETWORK_LAN_INTERNET,
@@ -683,7 +685,7 @@
 			_is_network_server = true;
 
 			if (nd->map == NULL) { // start random new game
-				GenRandomNewGame(Random(), InteractiveRandom());
+				ShowGenerateLandscape();
 			} else { // load a scenario
 				char *name = FiosBrowseTo(nd->map);
 				if (name != NULL) {
@@ -692,7 +694,7 @@
 					ttd_strlcpy(_file_to_saveload.title, nd->map->title, sizeof(_file_to_saveload.title));
 
 					DeleteWindow(w);
-					StartScenarioEditor(Random(), InteractiveRandom());
+					SwitchMode(SM_START_SCENARIO);
 				}
 			}
 			break;
@@ -1392,8 +1394,6 @@
 	if (w != NULL) w->window_number = 0;
 }
 
-extern void SwitchMode(int new_mode);
-
 static void NetworkJoinStatusWindowWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
--- a/network_server.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/network_server.c	Sat Aug 19 10:00:30 2006 +0000
@@ -21,6 +21,7 @@
 #include "vehicle.h"
 #include "station.h"
 #include "variables.h"
+#include "genworld.h"
 
 // This file handles all the server-commands
 
@@ -1308,18 +1309,13 @@
 	}
 }
 
-extern void SwitchMode(int new_mode);
-
 /* Check if we want to restart the map */
 static void NetworkCheckRestartMap(void)
 {
 	if (_network_restart_game_year != 0 && _cur_year >= _network_restart_game_year) {
 		DEBUG(net, 0)("Auto-restarting map. Year %d reached.", _cur_year);
 
-		_random_seeds[0][0] = Random();
-		_random_seeds[0][1] = InteractiveRandom();
-
-		SwitchMode(SM_NEWGAME);
+		StartNewGameWithoutGUI(GENERATE_NEW_SEED);
 	}
 }
 
--- a/openttd.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/openttd.c	Sat Aug 19 10:00:30 2006 +0000
@@ -48,11 +48,11 @@
 #include "train.h"
 #include "yapf/yapf.h"
 #include "settings.h"
+#include "genworld.h"
 #include "date.h"
 
 #include <stdarg.h>
 
-void GenerateWorld(int mode, uint size_x, uint size_y);
 void CallLandscapeTick(void);
 void IncreaseDate(void);
 void DoPaletteAnimations(void);
@@ -295,6 +295,7 @@
 #endif
 	if (SaveOrLoad(filename, SL_LOAD) != SL_OK) {
 		GenerateWorld(GW_EMPTY, 64, 64); // if failed loading, make empty world.
+		WaitTillGeneratedWorld();
 	}
 
 	_pause = 0;
@@ -317,7 +318,7 @@
 	char musicdriver[16], sounddriver[16], videodriver[16];
 	int resolution[2] = {0,0};
 	Year startyear = INVALID_YEAR;
-
+	uint generation_seed = GENERATE_NEW_SEED;
 	bool dedicated = false;
 	bool network   = false;
 	char *network_conn = NULL;
@@ -376,7 +377,7 @@
 				_switch_mode = SM_NEWGAME;
 			}
 			break;
-		case 'G': _random_seeds[0][0] = atoi(mgo.opt); break;
+		case 'G': generation_seed = atoi(mgo.opt); break;
 		case 'c': _config_file = strdup(mgo.opt); break;
 		case -2:
 		case 'h':
@@ -409,6 +410,7 @@
 	if (videodriver[0]) ttd_strlcpy(_ini_videodriver, videodriver, sizeof(_ini_videodriver));
 	if (resolution[0]) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; }
 	if (startyear != INVALID_YEAR) _patches_newgame.starting_year = startyear;
+	if (generation_seed != GENERATE_NEW_SEED) _patches_newgame.generation_seed = generation_seed;
 
 	if (_dedicated_forks && !dedicated) _dedicated_forks = false;
 
@@ -457,6 +459,13 @@
 	/* XXX - ugly hack, if diff_level is 9, it means we got no setting from the config file */
 	if (_opt_newgame.diff_level == 9) SetDifficultyLevel(0, &_opt_newgame);
 
+	/* Make sure _patches is filled with _patches_newgame if we switch to a game directly */
+	if (_switch_mode != SM_NONE) {
+		memcpy(&_opt, &_opt_newgame, sizeof(_opt));
+		GfxLoadSprites();
+		UpdatePatches();
+	}
+
 	// initialize the ingame console
 	IConsoleInit();
 	_cursor.in_window = true;
@@ -464,6 +473,7 @@
 	IConsoleCmdExec("exec scripts/autoexec.scr 0");
 
 	GenerateWorld(GW_EMPTY, 64, 64); // Make the viewport initialization happy
+	WaitTillGeneratedWorld();
 
 #ifdef ENABLE_NETWORK
 	if (network && _network_available) {
@@ -567,36 +577,35 @@
 
 }
 
-static void MakeNewGame(void)
+static void MakeNewGameDone(void)
+{
+	/* In a dedicated server, the server does not play */
+	if (_network_dedicated) {
+		_local_player = OWNER_SPECTATOR;
+		return;
+	}
+
+	/* Create a single player */
+	DoStartupNewPlayer(false);
+
+	_local_player = 0;
+	_current_player = _local_player;
+	DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_REPLACE_VEHICLE);
+
+	MarkWholeScreenDirty();
+}
+
+static void MakeNewGame(bool from_heightmap)
 {
 	_game_mode = GM_NORMAL;
 
-	// Copy in game options
-	_opt_ptr = &_opt;
-	memcpy(_opt_ptr, &_opt_newgame, sizeof(*_opt_ptr));
-
-	GfxLoadSprites();
-
-	// Reinitialize windows
-	ResetWindowSystem();
-	LoadStringWidthTable();
-
-	SetupColorsAndInitialWindow();
+	GenerateWorldSetCallback(&MakeNewGameDone);
+	GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _patches.map_x, 1 << _patches.map_y);
+}
 
-	// Randomize world
-	GenerateWorld(GW_NEWGAME, 1<<_patches.map_x, 1<<_patches.map_y);
-
-	// In a dedicated server, the server does not play
-	if (_network_dedicated) {
-		_local_player = OWNER_SPECTATOR;
-	} else {
-		// Create a single player
-		DoStartupNewPlayer(false);
-
-		_local_player = 0;
-		_current_player = _local_player;
-		DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_REPLACE_VEHICLE);
-	}
+static void MakeNewEditorWorldDone(void)
+{
+	_local_player = OWNER_NONE;
 
 	MarkWholeScreenDirty();
 }
@@ -605,23 +614,8 @@
 {
 	_game_mode = GM_EDITOR;
 
-	// Copy in game options
-	_opt_ptr = &_opt;
-	memcpy(_opt_ptr, &_opt_newgame, sizeof(GameOptions));
-
-	GfxLoadSprites();
-
-	// Re-init the windowing system
-	ResetWindowSystem();
-
-	// Create toolbars
-	SetupColorsAndInitialWindow();
-
-	// Startup the game system
+	GenerateWorldSetCallback(&MakeNewEditorWorldDone);
 	GenerateWorld(GW_EMPTY, 1 << _patches.map_x, 1 << _patches.map_y);
-
-	_local_player = OWNER_NONE;
-	MarkWholeScreenDirty();
 }
 
 void StartupPlayers(void);
@@ -688,7 +682,7 @@
 			switch (ogm) {
 				case GM_MENU:   LoadIntroGame();      break;
 				case GM_EDITOR: MakeNewEditorWorld(); break;
-				default:        MakeNewGame();        break;
+				default:        MakeNewGame(false);   break;
 			}
 			return false;
 
@@ -738,7 +732,7 @@
 			snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "Random Map");
 		}
 #endif /* ENABLE_NETWORK */
-		MakeNewGame();
+		MakeNewGame(false);
 		break;
 
 	case SM_START_SCENARIO: /* New Game --> Choose one of the preset scenarios */
@@ -768,6 +762,22 @@
 		break;
 	}
 
+	case SM_START_HEIGHTMAP: /* Load a heightmap and start a new game from it */
+#ifdef ENABLE_NETWORK
+		if (_network_server) {
+			snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Heightmap)", _file_to_saveload.title);
+		}
+#endif /* ENABLE_NETWORK */
+		MakeNewGame(true);
+		break;
+
+	case SM_LOAD_HEIGHTMAP: /* Load heightmap from scenario editor */
+		_local_player = OWNER_NONE;
+
+		GenerateWorld(GW_HEIGHTMAP, 1 << _patches.map_x, 1 << _patches.map_y);
+		MarkWholeScreenDirty();
+		break;
+
 	case SM_LOAD_SCENARIO: { /* Load scenario from scenario editor */
 		if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR)) {
 			Player *p;
@@ -784,6 +794,7 @@
 				}
 			}
 			_generating_world = false;
+			_patches_newgame.starting_year = BASE_YEAR + _cur_year;
 			// delete all stations owned by a player
 			DeleteAllPlayerStations();
 		} else {
@@ -805,9 +816,9 @@
 		break;
 
 	case SM_GENRANDLAND: /* Generate random land within scenario editor */
+		_local_player = OWNER_NONE;
 		GenerateWorld(GW_RANDOM, 1 << _patches.map_x, 1 << _patches.map_y);
 		// XXX: set date
-		_local_player = OWNER_NONE;
 		MarkWholeScreenDirty();
 		break;
 	}
@@ -826,6 +837,7 @@
 {
 	// dont execute the state loop during pause
 	if (_pause) return;
+	if (IsGeneratingWorld()) return;
 
 	if (_game_mode == GM_EDITOR) {
 		RunTileLoop();
@@ -884,7 +896,7 @@
 
 static void ScrollMainViewport(int x, int y)
 {
-	if (_game_mode != GM_MENU) {
+	if (_game_mode != GM_MENU && !IsGeneratingWorld()) {
 		Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
 		assert(w);
 
@@ -963,7 +975,7 @@
 	if (_network_available)
 		NetworkUDPGameLoop();
 
-	if (_networking) {
+	if (_networking && !IsGeneratingWorld()) {
 		// Multiplayer
 		NetworkGameLoop();
 	} else {
--- a/openttd.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/openttd.h	Sat Aug 19 10:00:30 2006 +0000
@@ -77,14 +77,17 @@
 	SM_GENRANDLAND = 6,
 	SM_LOAD_SCENARIO = 9,
 	SM_START_SCENARIO = 10,
+	SM_START_HEIGHTMAP = 11,
+	SM_LOAD_HEIGHTMAP = 12,
 };
 
 
 /* Modes for GenerateWorld */
 enum GenerateWorldModes {
-	GW_NEWGAME  = 0,    /* Generate a map for a new game */
-	GW_EMPTY    = 1,    /* Generate an empty map (sea-level) */
-	GW_RANDOM   = 2,    /* Generate a random map for SE */
+	GW_NEWGAME   = 0,    /* Generate a map for a new game */
+	GW_EMPTY     = 1,    /* Generate an empty map (sea-level) */
+	GW_RANDOM    = 2,    /* Generate a random map for SE */
+	GW_HEIGHTMAP = 3,    /* Generate a newgame from a heightmap */
 };
 
 /* Modes for InitializeGame, those are _bits_! */
@@ -410,6 +413,9 @@
 	WC_HIGHSCORE = 0x4D,
 	WC_ENDSCREEN = 0x4E,
 	WC_SIGN_LIST = 0x4F,
+	WC_GENERATE_LANDSCAPE = 0x50,
+	WC_GENERATE_PROGRESS_WINDOW = 0x51,
+	WC_OK_CANCEL_QUERY = 0x52,
 };
 
 
--- a/openttd.vcproj	Sat Aug 19 09:31:22 2006 +0000
+++ b/openttd.vcproj	Sat Aug 19 10:00:30 2006 +0000
@@ -169,6 +169,9 @@
 				RelativePath=".\aystar.c">
 			</File>
 			<File
+				RelativePath=".\bmp.c">
+			</File>
+			<File
 				RelativePath=".\callback_table.c">
 			</File>
 			<File
@@ -232,12 +235,18 @@
 				RelativePath=".\fios.c">
 			</File>
 			<File
+				RelativePath=".\genworld.c">
+			</File>
+			<File
 				RelativePath=".\gfx.c">
 			</File>
 			<File
 				RelativePath=".\gfxinit.c">
 			</File>
 			<File
+				RelativePath=".\heightmap.c">
+			</File>
+			<File
 				RelativePath=".\landscape.c">
 			</File>
 			<File
@@ -379,6 +388,9 @@
 				RelativePath=".\texteff.c">
 			</File>
 			<File
+				RelativePath=".\tgp.c">
+			</File>
+			<File
 				RelativePath=".\thread.c">
 			</File>
 			<File
@@ -425,6 +437,9 @@
 				RelativePath=".\aystar.h">
 			</File>
 			<File
+				RelativePath=".\bmp.h">
+			</File>
+			<File
 				RelativePath=".\command.h">
 			</File>
 			<File
@@ -464,6 +479,10 @@
 				RelativePath=".\functions.h">
 			</File>
 			<File
+				RelativePath=".\genworld.h"
+				>
+			</File>
+			<File
 				RelativePath=".\gfx.h">
 			</File>
 			<File
@@ -476,6 +495,9 @@
 				RelativePath=".\hal.h">
 			</File>
 			<File
+				RelativePath=".\heightmap.h">
+			</File>
+			<File
 				RelativePath=".\industry.h">
 			</File>
 			<File
@@ -605,6 +627,9 @@
 				RelativePath=".\string.h">
 			</File>
 			<File
+				RelativePath=".\tgp.h">
+			</File>
+			<File
 				RelativePath=".\thread.h">
 			</File>
 			<File
@@ -663,6 +688,9 @@
 				RelativePath=".\engine_gui.c">
 			</File>
 			<File
+				RelativePath=".\genworld_gui.c">
+			</File>
+			<File
 				RelativePath=".\graph_gui.c">
 			</File>
 			<File
--- a/openttd_vs80.vcproj	Sat Aug 19 09:31:22 2006 +0000
+++ b/openttd_vs80.vcproj	Sat Aug 19 10:00:30 2006 +0000
@@ -455,6 +455,9 @@
 			<File
 				RelativePath=".\aystar.c"
 				>
+			<File
+				RelativePath=".\bmp.c"
+				>
 			</File>
 			<File
 				RelativePath=".\callback_table.c"
@@ -557,6 +560,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\genworld.c"
+				>
+			</File>
+			<File
 				RelativePath=".\gfx.c"
 				>
 			</File>
@@ -565,6 +572,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\heightmap.c"
+				>
+			</File>
+			<File
 				RelativePath=".\landscape.c"
 				>
 			</File>
@@ -753,6 +764,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\tgp.c"
+				>
+			</File>
+			<File
 				RelativePath=".\thread.c"
 				>
 			</File>
@@ -850,6 +865,9 @@
 			<File
 				RelativePath=".\aystar.h"
 				>
+			<File
+				RelativePath=".\bmp.h"
+				>
 			</File>
 			<File
 				RelativePath=".\clear.h"
@@ -912,6 +930,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\genworld.h"
+				>
+			</File>
+			<File
 				RelativePath=".\gfx.h"
 				>
 			</File>
@@ -928,6 +950,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\heightmap.h"
+				>
+			</File>
+			<File
 				RelativePath=".\industry.h"
 				>
 			</File>
@@ -1104,6 +1130,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\tgp.h"
+				>
+			</File>
+			<File
 				RelativePath=".\thread.h"
 				>
 			</File>
@@ -1184,6 +1214,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\genworld_gui.c"
+				>
+			</File>
+			<File
 				RelativePath=".\graph_gui.c"
 				>
 			</File>
--- a/os/linux/openttd.spec	Sat Aug 19 09:31:22 2006 +0000
+++ b/os/linux/openttd.spec	Sat Aug 19 10:00:30 2006 +0000
@@ -143,4 +143,4 @@
 - Upgraded to 0.3.4
 
 * Wed Jul 31 2004 Dominik Scherer <> 0.3.3-1mdk
-- Initial release
\ No newline at end of file
+- Initial release
--- a/os/macosx/splash.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/os/macosx/splash.c	Sat Aug 19 10:00:30 2006 +0000
@@ -137,8 +137,8 @@
 
 
 
-#else // WITH_PNG
+#else /* WITH_PNG */
 
 void DisplaySplashImage(void) {}
 
-#endif // WITH_PNG
+#endif /* WITH_PNG */
--- a/os2.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/os2.c	Sat Aug 19 10:00:30 2006 +0000
@@ -180,6 +180,7 @@
 	_path.save_dir = str_fmt("%ssave", _path.personal_dir);
 	_path.autosave_dir = str_fmt("%s\\autosave", _path.save_dir);
 	_path.scenario_dir = str_fmt("%sscenario", _path.personal_dir);
+	_path.heightmap_dir = str_fmt("%sscenario\\heightmap", _path.personal_dir);
 	_path.gm_dir = str_fmt("%sgm\\", _path.game_data_dir);
 	_path.data_dir = str_fmt("%sdata\\", _path.game_data_dir);
 
@@ -202,6 +203,7 @@
 	mkdir(_path.save_dir);
 	mkdir(_path.autosave_dir);
 	mkdir(_path.scenario_dir);
+	mkdir(_path.heightmap_dir);
 }
 
 /**
--- a/saveload.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/saveload.c	Sat Aug 19 10:00:30 2006 +0000
@@ -30,7 +30,7 @@
 #include "variables.h"
 #include <setjmp.h>
 
-const uint16 SAVEGAME_VERSION = 29;
+const uint16 SAVEGAME_VERSION = 30;
 uint16 _sl_version;       /// the major savegame version identifier
 byte   _sl_minor_version; /// the minor savegame version, DO NOT USE!
 
--- a/saveload.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/saveload.h	Sat Aug 19 10:00:30 2006 +0000
@@ -14,6 +14,8 @@
 	SL_LOAD     =  0,
 	SL_SAVE     =  1,
 	SL_OLD_LOAD =  2,
+	SL_PNG      =  3,
+	SL_BMP      =  4,
 } SaveOrLoadMode;
 
 SaveOrLoadResult SaveOrLoad(const char *filename, int mode);
--- a/screenshot.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/screenshot.c	Sat Aug 19 10:00:30 2006 +0000
@@ -254,7 +254,7 @@
 	fclose(f);
 	return true;
 }
-#endif // WITH_PNG
+#endif /* WITH_PNG */
 
 
 //************************************************
--- a/settings.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/settings.c	Sat Aug 19 10:00:30 2006 +0000
@@ -36,6 +36,7 @@
 #include "npf.h"
 #include "yapf/yapf.h"
 #include "newgrf.h"
+#include "genworld.h"
 #include "date.h"
 
 /** The patch values that are used for new games and/or modified in config file */
@@ -1435,6 +1436,17 @@
 	SDT_CONDVAR (Patches, yapf.road_slope_penalty                    , SLE_UINT, 28, SL_MAX_VERSION,NS, 0,   2 * YAPF_TILE_LENGTH,        0, 1000000, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.road_crossing_penalty                 , SLE_UINT, 28, SL_MAX_VERSION,NS, 0,   3 * YAPF_TILE_LENGTH,        0, 1000000, STR_NULL, NULL),
 
+	/***************************************************************************/
+	/* Terrain genation related patch options */
+	SDT_CONDVAR(Patches,      land_generator,           SLE_UINT8,  30, SL_MAX_VERSION, 0, MS,   1,                   0,    1,               STR_CONFIG_PATCHES_LAND_GENERATOR,           NULL),
+	SDT_CONDVAR(Patches,      oil_refinery_limit,       SLE_UINT8,  30, SL_MAX_VERSION, 0, 0,   16,                  12,   48,               STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE,    NULL),
+	SDT_CONDVAR(Patches,      tgen_smoothness,          SLE_UINT8,  30, SL_MAX_VERSION, 0, MS,   1,                   0,    3,               STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN,     NULL),
+	SDT_CONDVAR(Patches,      generation_seed,          SLE_UINT32, 30, SL_MAX_VERSION, 0, 0,    GENERATE_NEW_SEED,   0, MAX_UVALUE(uint32), STR_NULL,                                    NULL),
+	SDT_CONDVAR(Patches,      tree_placer,              SLE_UINT8,  30, SL_MAX_VERSION, 0, MS,   2,                   0,    2,               STR_CONFIG_PATCHES_TREE_PLACER,              NULL),
+	SDT_VAR    (Patches,      heightmap_rotation,       SLE_UINT8,                      S, MS,   0,                   0,    1,               STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION,       NULL),
+	SDT_VAR    (Patches,      progress_update_interval, SLE_UINT16,                     S, 0,  200,                   0, 5000,               STR_CONFIG_PATCHES_PROGRESS_UPDATE_INTERVAL, NULL),
+	SDT_VAR    (Patches,      se_flat_world_height,     SLE_UINT8,                      S, 0,    0,                   0,   15,               STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT,     NULL),
+
 	SDT_END()
 };
 
--- a/settings_gui.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/settings_gui.c	Sat Aug 19 10:00:30 2006 +0000
@@ -568,9 +568,8 @@
 	"window_snap_radius",
 	"invisible_trees",
 	"population_in_label",
-	"map_x",
-	"map_y",
 	"link_terraform_toolbar",
+	"progress_update_interval",
 };
 
 static const char *_patches_construction[] = {
@@ -580,6 +579,7 @@
 	"signal_side",
 	"always_small_airport",
 	"drag_signals_density",
+	"oil_refinery_limit",
 };
 
 static const char *_patches_stations[] = {
@@ -600,9 +600,7 @@
 	"multiple_industry_per_town",
 	"same_industry_close",
 	"bribe",
-	"snow_line_height",
 	"colored_news_year",
-	"starting_year",
 	"ending_year",
 	"smooth_economy",
 	"allow_shares",
--- a/string.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/string.c	Sat Aug 19 10:00:30 2006 +0000
@@ -65,18 +65,15 @@
 		if (!IsValidAsciiChar(*str, CS_ALPHANUMERAL)) *str = '?';
 }
 
-void strtolower(char *str)
-{
-	for (; *str != '\0'; str++) *str = tolower(*str);
-}
-
-/** Only allow valid ascii-function codes. Filter special codes like BELL and
- * so on [we need a special filter here later]
+/**
+ * Only allow certain keys. You can define the filter to be used. This makes
+ *  sure no invalid keys can get into an editbox, like BELL.
  * @param key character to be checked
- * @return true or false depending if the character is printable/valid or not */
+ * @param afilter the filter to use
+ * @return true or false depending if the character is printable/valid or not
+ */
 bool IsValidAsciiChar(byte key, CharSetFilter afilter)
 {
-	// XXX This filter stops certain crashes, but may be too restrictive.
 	bool firsttest = false;
 
 	switch (afilter) {
@@ -84,8 +81,9 @@
 			firsttest = (key >= ' ' && key < 127);
 			break;
 
-		case CS_NUMERAL://we are quite strict, here
-			return (key >= 48 && key <= 57);
+		/* We are very strict here */
+		case CS_NUMERAL:
+			return (key >= '0' && key <= '9');
 
 		case CS_ALPHA:
 		default:
@@ -93,7 +91,13 @@
 			break;
 	}
 
+	/* Allow some special chars too that are non-ASCII but still valid (like '^' above 'a') */
 	return (firsttest || (key >= 160 &&
 		key != 0xAA && key != 0xAC && key != 0xAD && key != 0xAF &&
 		key != 0xB5 && key != 0xB6 && key != 0xB7 && key != 0xB9));
 }
+
+void strtolower(char *str)
+{
+	for (; *str != '\0'; str++) *str = tolower(*str);
+}
--- a/string.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/string.h	Sat Aug 19 10:00:30 2006 +0000
@@ -29,19 +29,25 @@
  * replaces them with a question mark '?' */
 void str_validate(char *str);
 
+/**
+ * Valid filter types for IsValidAsciiChar.
+ */
+typedef enum CharSetFilter {
+	CS_ALPHANUMERAL,      //! Both numeric and alphabetic and spaces and stuff
+	CS_NUMERAL,           //! Only numeric ones
+	CS_ALPHA,             //! Only alphabetic values
+} CharSetFilter;
+
+/**
+ * Only allow certain keys. You can define the filter to be used. This makes
+ *  sure no invalid keys can get into an editbox, like BELL.
+ * @param key character to be checked
+ * @param afilter the filter to use
+ * @return true or false depending if the character is printable/valid or not
+ */
+bool IsValidAsciiChar(byte key, CharSetFilter afilter);
+
 /** Convert the given string to lowercase */
 void strtolower(char *str);
 
-typedef enum CharSetFilter {  //valid char filtering
-	CS_ALPHANUMERAL,   //both numeric and alphabetic
-	CS_NUMERAL,        //only numeric ones.
-	CS_ALPHA,          //only alphabetic values
-} CharSetFilter;
-
-/** Only allow valid ascii-function codes. Filter special codes like BELL and
- * so on [we need a special filter here later]
- * @param key character to be checked
- * @return true or false depending if the character is printable/valid or not */
-bool IsValidAsciiChar(byte key, CharSetFilter afilter);
-
 #endif /* STRING_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tgp.c	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,826 @@
+/* $Id$ */
+
+#include "stdafx.h"
+#include <math.h>
+#include "openttd.h"
+#include "clear_map.h"
+#include "functions.h"
+#include "map.h"
+#include "table/strings.h"
+#include "clear_map.h"
+#include "tile.h"
+#include "variables.h"
+#include "void_map.h"
+#include "tgp.h"
+#include "console.h"
+#include "genworld.h"
+
+/*
+ * OTTD Perlin Noise Landscape Generator, aka TerraGenesis Perlin
+ *
+ * Quickie guide to Perlin Noise
+ * Perlin noise is a predictable pseudo random number sequence. By generating
+ * it in 2 dimensions, it becomes a useful random map, that for a given seed
+ * and starting X & Y is entirely predictable. On the face of it, that may not
+ * be useful. However, it means that if you want to replay a map in a different
+ * terrain, or just vary the sea level, you just re-run the generator with the
+ * same seed. The seed is an int32, and is randomised on each run of New Game.
+ * The Scenario Generator does not randomise the value, so that you can
+ * experiment with one terrain until you are happy, or click "Random" for a new
+ * random seed.
+ *
+ * Perlin Noise is a series of "octaves" of random noise added together. By
+ * reducing the amplitude of the noise with each octave, the first octave of
+ * noise defines the main terrain sweep, the next the ripples on that, and the
+ * next the ripples on that. I use 6 octaves, with the amplitude controlled by
+ * a power ratio, usually known as a persistence or p value. This I vary by the
+ * smoothness selection, as can be seen in the table below. The closer to 1,
+ * the more of that octave is added. Each octave is however raised to the power
+ * of its position in the list, so the last entry in the "smooth" row, 0.35, is
+ * raised to the power of 6, so can only add 0.001838...  of the amplitude to
+ * the running total.
+ *
+ * In other words; the first p value sets the general shape of the terrain, the
+ * second sets the major variations to that, ... until finally the smallest
+ * bumps are added.
+ *
+ * Usefully, this routine is totally scaleable; so when 32bpp comes along, the
+ * terrain can be as bumpy as you like! It is also infinitely expandable; a
+ * single random seed terrain continues in X & Y as far as you care to
+ * calculate. In theory, we could use just one seed value, but randomly select
+ * where in the Perlin XY space we use for the terrain. Personally I prefer
+ * using a simple (0, 0) to (X, Y), with a varying seed.
+ *
+ *
+ * Other things i have had to do: mountainous wasnt mountainous enough, and
+ * since we only have 0..15 heights available, I add a second generated map
+ * (with a modified seed), onto the original. This generally raises the
+ * terrain, which then needs scaling back down. Overall effect is a general
+ * uplift.
+ *
+ * However, the values on the top of mountains are then almost guaranteed to go
+ * too high, so large flat plateaus appeared at height 15. To counter this, I
+ * scale all heights above 12 to proportion up to 15. It still makes the
+ * mountains have flatish tops, rather than craggy peaks, but at least they
+ * arent smooth as glass.
+ *
+ *
+ * For a full discussion of Perlin Noise, please visit:
+ * http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
+ *
+ *
+ * Evolution II
+ *
+ * The algorithm as described in the above link suggests to compute each tile height
+ * as composition of several noise waves. Some of them are computed directly by
+ * noise(x, y) function, some are calculated using linear approximation. Our
+ * first implementation of perlin_noise_2D() used 4 noise(x, y) calls plus
+ * 3 linear interpolations. It was called 6 times for each tile. This was a bit
+ * CPU expensive.
+ *
+ * The following implementation uses optimized algorithm that should produce
+ * the same quality result with much less computations, but more memory accesses.
+ * The overal speedup should be 300% to 800% depending on CPU and memory speed.
+ *
+ * I will try to explain it on the example below:
+ *
+ * Have a map of 4 x 4 tiles, our simplifiead noise generator produces only two
+ * values -1 and +1, use 3 octaves with wave lenght 1, 2 and 4, with amplitudes
+ * 3, 2, 1. Original algorithm produces:
+ *
+ * h00 = lerp(lerp(-3, 3, 0/4), lerp(3, -3, 0/4), 0/4) + lerp(lerp(-2,  2, 0/2), lerp( 2, -2, 0/2), 0/2) + -1 = lerp(-3.0,  3.0, 0/4) + lerp(-2,  2, 0/2) + -1 = -3.0  + -2 + -1 = -6.0
+ * h01 = lerp(lerp(-3, 3, 1/4), lerp(3, -3, 1/4), 0/4) + lerp(lerp(-2,  2, 1/2), lerp( 2, -2, 1/2), 0/2) +  1 = lerp(-1.5,  1.5, 0/4) + lerp( 0,  0, 0/2) +  1 = -1.5  +  0 +  1 = -0.5
+ * h02 = lerp(lerp(-3, 3, 2/4), lerp(3, -3, 2/4), 0/4) + lerp(lerp( 2, -2, 0/2), lerp(-2,  2, 0/2), 0/2) + -1 = lerp(   0,    0, 0/4) + lerp( 2, -2, 0/2) + -1 =    0  +  2 + -1 =  1.0
+ * h03 = lerp(lerp(-3, 3, 3/4), lerp(3, -3, 3/4), 0/4) + lerp(lerp( 2, -2, 1/2), lerp(-2,  2, 1/2), 0/2) +  1 = lerp( 1.5, -1.5, 0/4) + lerp( 0,  0, 0/2) +  1 =  1.5  +  0 +  1 =  2.5
+ *
+ * h10 = lerp(lerp(-3, 3, 0/4), lerp(3, -3, 0/4), 1/4) + lerp(lerp(-2,  2, 0/2), lerp( 2, -2, 0/2), 1/2) +  1 = lerp(-3.0,  3.0, 1/4) + lerp(-2,  2, 1/2) +  1 = -1.5  +  0 +  1 = -0.5
+ * h11 = lerp(lerp(-3, 3, 1/4), lerp(3, -3, 1/4), 1/4) + lerp(lerp(-2,  2, 1/2), lerp( 2, -2, 1/2), 1/2) + -1 = lerp(-1.5,  1.5, 1/4) + lerp( 0,  0, 1/2) + -1 = -0.75 +  0 + -1 = -1.75
+ * h12 = lerp(lerp(-3, 3, 2/4), lerp(3, -3, 2/4), 1/4) + lerp(lerp( 2, -2, 0/2), lerp(-2,  2, 0/2), 1/2) +  1 = lerp(   0,    0, 1/4) + lerp( 2, -2, 1/2) +  1 =    0  +  0 +  1 =  1.0
+ * h13 = lerp(lerp(-3, 3, 3/4), lerp(3, -3, 3/4), 1/4) + lerp(lerp( 2, -2, 1/2), lerp(-2,  2, 1/2), 1/2) + -1 = lerp( 1.5, -1.5, 1/4) + lerp( 0,  0, 1/2) + -1 =  0.75 +  0 + -1 = -0.25
+ *
+ *
+ * Optimization 1:
+ *
+ * 1) we need to allocate a bit more tiles: (size_x + 1) * (size_y + 1) = (5 * 5):
+ *
+ * 2) setup corner values using amplitude 3
+ * {    -3.0        X          X          X          3.0   }
+ * {     X          X          X          X          X     }
+ * {     X          X          X          X          X     }
+ * {     X          X          X          X          X     }
+ * {     3.0        X          X          X         -3.0   }
+ *
+ * 3a) interpolate values in the middle
+ * {    -3.0        X          0.0        X          3.0   }
+ * {     X          X          X          X          X     }
+ * {     0.0        X          0.0        X          0.0   }
+ * {     X          X          X          X          X     }
+ * {     3.0        X          0.0        X         -3.0   }
+ *
+ * 3b) add patches with amplitude 2 to them
+ * {    -5.0        X          2.0        X          1.0   }
+ * {     X          X          X          X          X     }
+ * {     2.0        X         -2.0        X          2.0   }
+ * {     X          X          X          X          X     }
+ * {     1.0        X          2.0        X         -5.0   }
+ *
+ * 4a) interpolate values in the middle
+ * {    -5.0       -1.5        2.0        1.5        1.0   }
+ * {    -1.5       -0.75       0.0        0.75       1.5   }
+ * {     2.0        0.0       -2.0        0.0        2.0   }
+ * {     1.5        0.75       0.0       -0.75      -1.5   }
+ * {     1.0        1.5        2.0       -1.5       -5.0   }
+ *
+ * 4b) add patches with amplitude 1 to them
+ * {    -6.0       -0.5        1.0        2.5        0.0   }
+ * {    -0.5       -1.75       1.0       -0.25       2.5   }
+ * {     1.0        1.0       -3.0        1.0        1.0   }
+ * {     2.5       -0.25       1.0       -1.75      -0.5   }
+ * {     0.0        2.5        1.0       -0.5       -6.0   }
+ *
+ *
+ *
+ * Optimization 2:
+ *
+ * As you can see above, each noise function was called just once. Therefore
+ * we don't need to use noise function that calculates the noise from x, y and
+ * some prime. The same quality result we can obtain using standard Random()
+ * function instead.
+ *
+ */
+
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923
+#define M_PI   3.14159265358979323846
+#endif /* M_PI_2 */
+
+/** Fixed point type for heights */
+typedef int16 height_t;
+static const int height_decimal_bits = 4;
+static const height_t _invalid_height = -32768;
+
+/** Fixed point array for amplitudes (and percent values) */
+typedef int amplitude_t;
+static const int amplitude_decimal_bits = 10;
+
+/** Height map - allocated array of heights (MapSizeX() + 1) x (MapSizeY() + 1) */
+typedef struct HeightMap
+{
+	height_t *h;         //! array of heights
+	uint     dim_x;      //! height map size_x MapSizeX() + 1
+	uint     total_size; //! height map total size
+	uint     size_x;     //! MapSizeX()
+	uint     size_y;     //! MapSizeY()
+} HeightMap;
+
+/** Global height map instance */
+static HeightMap _height_map = {NULL, 0, 0, 0, 0};
+
+/** Height map accessors */
+#define HeightMapXY(x, y) _height_map.h[(x) + (y) * _height_map.dim_x]
+
+/** Conversion: int to height_t */
+#define I2H(i) ((i) << height_decimal_bits)
+/** Conversion: height_t to int */
+#define H2I(i) ((i) >> height_decimal_bits)
+
+/** Conversion: int to amplitude_t */
+#define I2A(i) ((i) << amplitude_decimal_bits)
+/** Conversion: amplitude_t to int */
+#define A2I(i) ((i) >> amplitude_decimal_bits)
+
+/** Conversion: amplitude_t to height_t */
+#define A2H(a) ((height_decimal_bits < amplitude_decimal_bits) \
+	? ((a) >> (amplitude_decimal_bits - height_decimal_bits)) \
+	: ((a) << (height_decimal_bits - amplitude_decimal_bits)))
+
+/** Walk through all items of _height_map.h */
+#define FOR_ALL_TILES_IN_HEIGHT(h) for (h = _height_map.h; h < &_height_map.h[_height_map.total_size]; h++)
+
+/** Noise amplitudes (multiplied by 1024)
+ *	- indexed by "smoothness setting" and log2(frequency) */
+static const amplitude_t _amplitudes_by_smoothness_and_frequency[4][12] = {
+	// Very smooth
+	{1000,  350,  123,   43,   15,    1,     1,    0,    0,    0,    0,    0},
+	// Smooth
+	{1000, 1000,  403,  200,   64,    8,     1,    0,    0,    0,    0,    0},
+	// Rough
+	{1000, 1200,  800,  500,  200,   16,     4,    0,    0,    0,    0,    0},
+	// Very Rough
+	{1500, 1000, 1200, 1000,  500,   32,    20,    0,    0,    0,    0,    0},
+};
+
+/** Desired water percentage (100% == 1024) - indexed by _opt.diff.quantity_sea_lakes */
+static const amplitude_t _water_percent[4] = {20, 80, 250, 400};
+
+/** Desired maximum height - indexed by _opt.diff.terrain_type */
+static const int8 _max_height[4] = {
+	6,       // Very flat
+	9,       // Flat
+	12,      // Hilly
+	15       // Mountainous
+};
+
+/** Check if a X/Y set are within the map. */
+static inline bool IsValidXY(uint x, uint y)
+{
+	return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y;
+}
+
+
+/** Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members */
+static inline bool AllocHeightMap(void)
+{
+	height_t *h;
+
+	_height_map.size_x = MapSizeX();
+	_height_map.size_y = MapSizeY();
+
+	/* Allocate memory block for height map row pointers */
+	_height_map.total_size = (_height_map.size_x + 1) * (_height_map.size_y + 1);
+	_height_map.dim_x = _height_map.size_x + 1;
+	_height_map.h = calloc(_height_map.total_size, sizeof(*_height_map.h));
+	if (_height_map.h == NULL) return false;
+
+	/* Iterate through height map initialize values */
+	FOR_ALL_TILES_IN_HEIGHT(h) *h = _invalid_height;
+
+	return true;
+}
+
+/** Free height map */
+static inline void FreeHeightMap(void)
+{
+	if (_height_map.h == NULL) return;
+	free(_height_map.h);
+	_height_map.h = NULL;
+}
+
+/** RandomHeight() generator */
+static inline height_t RandomHeight(amplitude_t rMax)
+{
+	amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF);
+	height_t rh;
+	/* Scale the amplitude for better resolution */
+	rMax *= 16;
+	/* Spread height into range -rMax..+rMax */
+	rh = A2H(ra % (2 * rMax + 1) - rMax);
+	return rh;
+}
+
+/** One interpolation and noise round */
+static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
+{
+	uint size_min = min(_height_map.size_x, _height_map.size_y);
+	uint step = size_min >> log_frequency;
+	uint x, y;
+
+	assert(_height_map.h != NULL);
+
+	/* Are we finished? */
+	if (step == 0) return false;
+
+	if (log_frequency == 0) {
+		/* This is first round, we need to establish base heights with step = size_min */
+		for (y = 0; y <= _height_map.size_y; y += step) {
+			for (x = 0; x <= _height_map.size_x; x += step) {
+				height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
+				HeightMapXY(x, y) = height;
+			}
+		}
+		return true;
+	}
+
+	/* It is regular iteration round.
+	 * Interpolate height values at odd x, even y tiles */
+	for (y = 0; y <= _height_map.size_y; y += 2 * step) {
+		for (x = 0; x < _height_map.size_x; x += 2 * step) {
+			height_t h00 = HeightMapXY(x + 0 * step, y);
+			height_t h02 = HeightMapXY(x + 2 * step, y);
+			height_t h01 = (h00 + h02) / 2;
+			HeightMapXY(x + 1 * step, y) = h01;
+		}
+	}
+
+	/* Interpolate height values at odd y tiles */
+	for (y = 0; y < _height_map.size_y; y += 2 * step) {
+		for (x = 0; x <= _height_map.size_x; x += step) {
+			height_t h00 = HeightMapXY(x, y + 0 * step);
+			height_t h20 = HeightMapXY(x, y + 2 * step);
+			height_t h10 = (h00 + h20) / 2;
+			HeightMapXY(x, y + 1 * step) = h10;
+		}
+	}
+
+	for (y = 0; y <= _height_map.size_y; y += step) {
+		for (x = 0; x <= _height_map.size_x; x += step) {
+			HeightMapXY(x, y) += RandomHeight(amplitude);
+		}
+	}
+	return (step > 1);
+}
+
+/** Base Perlin noise generator - fills height map with raw Perlin noise */
+static void HeightMapGenerate(void)
+{
+	uint size_min = min(_height_map.size_x, _height_map.size_y);
+	uint iteration_round = 0;
+	amplitude_t amplitude;
+	bool continue_iteration;
+	uint log_size_min, log_frequency_min;
+	int log_frequency;
+
+	/* Find first power of two that fits */
+	for (log_size_min = 6; (1U << log_size_min) < size_min; log_size_min++) { }
+	log_frequency_min = log_size_min - 6;
+
+	do {
+		log_frequency = iteration_round - log_frequency_min;
+		if (log_frequency >= 0) {
+			amplitude = _amplitudes_by_smoothness_and_frequency[_patches.tgen_smoothness][log_frequency];
+		} else {
+			amplitude = 0;
+		}
+		continue_iteration = ApplyNoise(iteration_round, amplitude);
+		iteration_round++;
+	} while(continue_iteration);
+}
+
+/** Returns min, max and average height from height map */
+static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr)
+{
+	height_t h_min, h_max, h_avg, *h;
+	int64 h_accu = 0;
+	h_min = h_max = HeightMapXY(0, 0);
+
+	/* Get h_min, h_max and accumulate heights into h_accu */
+	FOR_ALL_TILES_IN_HEIGHT(h) {
+		if (*h < h_min) h_min = *h;
+		if (*h > h_max) h_max = *h;
+		h_accu += *h;
+	}
+
+	/* Get average height */
+	h_avg = (height_t)(h_accu / (_height_map.size_x * _height_map.size_y));
+
+	/* Return required results */
+	if (min_ptr != NULL) *min_ptr = h_min;
+	if (max_ptr != NULL) *max_ptr = h_max;
+	if (avg_ptr != NULL) *avg_ptr = h_avg;
+}
+
+/** Dill histogram and return pointer to its base point - to the count of zero heights */
+static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf)
+{
+	int *hist = hist_buf - h_min;
+	height_t *h;
+
+	/* Fill histogram */
+	FOR_ALL_TILES_IN_HEIGHT(h) {
+		assert(*h >= h_min);
+		assert(*h <= h_max);
+		hist[*h]++;
+	}
+	return hist;
+}
+
+/** Applies sine wave redistribution onto height map */
+static void HeightMapSineTransform(height_t h_min, height_t h_max)
+{
+	height_t *h;
+
+	FOR_ALL_TILES_IN_HEIGHT(h) {
+		double fheight;
+
+		if (*h < h_min) continue;
+
+		/* Transform height into 0..1 space */
+		fheight = (double)(*h - h_min) / (double)(h_max - h_min);
+		/* Apply sine transform depending on landscape type */
+		switch(_opt.landscape) {
+			case LT_CANDY:
+			case LT_NORMAL:
+				/* Move and scale 0..1 into -1..+1 */
+				fheight = 2 * fheight - 1;
+				/* Sine transform */
+				fheight = sin(fheight * M_PI_2);
+				/* Transform it back from -1..1 into 0..1 space */
+				fheight = 0.5 * (fheight + 1);
+				break;
+
+			case LT_HILLY:
+				{
+					/* Arctic terrain needs special height distribution.
+					 * Redistribute heights to have more tiles at highest (75%..100%) range */
+					double sine_upper_limit = 0.75;
+					double linear_compression = 2;
+					if (fheight >= sine_upper_limit) {
+						/* Over the limit we do linear compression up */
+						fheight = 1.0 - (1.0 - fheight) / linear_compression;
+					} else {
+						double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
+						/* Get 0..sine_upper_limit into -1..1 */
+						fheight = 2.0 * fheight / sine_upper_limit - 1.0;
+						/* Sine wave transform */
+						fheight = sin(fheight * M_PI_2);
+						/* Get -1..1 back to 0..(1 - (1 - sine_upper_limit) / linear_compression) == 0.0..m */
+						fheight = 0.5 * (fheight + 1.0) * m;
+					}
+				}
+				break;
+
+			case LT_DESERT:
+				{
+					/* Desert terrain needs special height distribution.
+					 * Half of tiles should be at lowest (0..25%) heights */
+					double sine_lower_limit = 0.5;
+					double linear_compression = 2;
+					if (fheight <= sine_lower_limit) {
+						/* Under the limit we do linear compression down */
+						fheight = fheight / linear_compression;
+					} else {
+						double m = sine_lower_limit / linear_compression;
+						/* Get sine_lower_limit..1 into -1..1 */
+						fheight = 2.0 * ((fheight - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
+						/* Sine wave transform */
+						fheight = sin(fheight * M_PI_2);
+						/* Get -1..1 back to (sine_lower_limit / linear_compression)..1.0 */
+						fheight = 0.5 * ((1.0 - m) * fheight + (1.0 + m));
+					}
+				}
+				break;
+
+			default:
+				NOT_REACHED();
+				break;
+		}
+		/* Transform it back into h_min..h_max space */
+		*h = fheight * (h_max - h_min) + h_min;
+		if (*h < 0) *h = I2H(0);
+		if (*h >= h_max) *h = h_max - 1;
+	}
+}
+
+/** Adjusts heights in height map to contain required amount of water tiles */
+static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new)
+{
+	height_t h_min, h_max, h_avg, h_water_level;
+	int water_tiles, desired_water_tiles;
+	height_t *h;
+	int *hist_buf, *hist;
+
+	HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg);
+
+	/* Allocate histogram buffer and clear its cells */
+	hist_buf = calloc(h_max - h_min + 1, sizeof(*hist_buf));
+	/* Fill histogram */
+	hist = HeightMapMakeHistogram(h_min, h_max, hist_buf);
+
+	/* How many water tiles do we want? */
+	desired_water_tiles = (int)(((int64)water_percent) * (int64)(_height_map.size_x * _height_map.size_y)) >> amplitude_decimal_bits;
+
+	/* Raise water_level and accumulate values from histogram until we reach required number of water tiles */
+	for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) {
+		water_tiles += hist[h_water_level];
+		if (water_tiles >= desired_water_tiles) break;
+	}
+
+	/* We now have the proper water level value.
+	 * Transform the height map into new (normalized) height map:
+	 *   values from range: h_min..h_water_level will become negative so it will be clamped to 0
+	 *   values from range: h_water_level..h_max are transformed into 0..h_max_new
+	 * , where h_max_new is 4, 8, 12 or 16 depending on terrain type (very flat, flat, hilly, mountains)
+	 */
+	FOR_ALL_TILES_IN_HEIGHT(h) {
+		/* Transform height from range h_water_level..h_max into 0..h_max_new range */
+		*h = (height_t)(((int)h_max_new) * (*h - h_water_level) / (h_max - h_water_level)) + I2H(1);
+		/* Make sure all values are in the proper range (0..h_max_new) */
+		if (*h < 0) *h = I2H(0);
+		if (*h >= h_max_new) *h = h_max_new - 1;
+	}
+
+	free(hist_buf);
+}
+
+static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime);
+
+/**
+* This routine sculpts in from the edge a random amount, again a Perlin
+* sequence, to avoid the rigid flat-edge slopes that were present before. The
+* Perlin noise map doesnt know where we are going to slice across, and so we
+* often cut straight through high terrain. the smoothing routine makes it
+* legal, gradually increasing up from the edge to the original terrain height.
+* By cutting parts of this away, it gives a far more irregular edge to the
+* map-edge. Sometimes it works beautifully with the existing sea & lakes, and
+* creates a very realistic coastline. Other times the variation is less, and
+* the map-edge shows its cliff-like roots.
+*
+* This routine may be extended to randomly sculpt the height of the terrain
+* near the edge. This will have the coast edge at low level (1-3), rising in
+* smoothed steps inland to about 15 tiles in. This should make it look as
+* though the map has been built for the map size, rather than a slice through
+* a larger map.
+*
+* Please note that all the small numbers; 53, 101, 167, etc. are small primes
+* to help give the perlin noise a bit more of a random feel.
+*/
+static void HeightMapCoastLines(void)
+{
+	int smallest_size = min(_patches.map_x, _patches.map_y);
+	const int margin = 4;
+	uint y, x;
+	uint max_x;
+	uint max_y;
+
+	/* Lower to sea level */
+	for (y = 0; y <= _height_map.size_y; y++) {
+		/* Top right */
+		max_x = myabs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.9, 53) + 0.25) * 5 + (perlin_coast_noise_2D(y, y, 0.35, 179) + 1) * 12);
+		max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
+		if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
+		for (x = 0; x < max_x; x++) {
+			HeightMapXY(x, y) = 0;
+		}
+
+		/* Bottom left */
+		max_x = myabs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.85, 101) + 0.3) * 6 + (perlin_coast_noise_2D(y, y, 0.45,  67) + 0.75) * 8);
+		max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
+		if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
+		for (x = _height_map.size_x; x > (_height_map.size_x - 1 - max_x); x--) {
+			HeightMapXY(x, y) = 0;
+		}
+	}
+
+	/* Lower to sea level */
+	for (x = 0; x <= _height_map.size_x; x++) {
+		/* Top left */
+		max_y = myabs((perlin_coast_noise_2D(x, _height_map.size_y / 2, 0.9, 167) + 0.4) * 5 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.4, 211) + 0.7) * 9);
+		max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
+		if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
+		for (y = 0; y < max_y; y++) {
+			HeightMapXY(x, y) = 0;
+		}
+
+
+		/* Bottom right */
+		max_y = myabs((perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.85, 71) + 0.25) * 6 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.35, 193) + 0.75) * 12);
+		max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
+		if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
+		for (y = _height_map.size_y; y > (_height_map.size_y - 1 - max_y); y--) {
+			HeightMapXY(x, y) = 0;
+		}
+	}
+}
+
+/** Start at given point, move in given direction, find and Smooth coast in that direction */
+static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y)
+{
+	const int max_coast_dist_from_edge = 35;
+	const int max_coast_Smooth_depth = 35;
+
+	int x, y;
+	int ed; // coast distance from edge
+	int depth;
+
+	height_t h_prev = 16;
+	height_t h;
+
+	assert(IsValidXY(org_x, org_y));
+
+	/* Search for the coast (first non-water tile) */
+	for (x = org_x, y = org_y, ed = 0; IsValidXY(x, y) && ed < max_coast_dist_from_edge; x += dir_x, y += dir_y, ed++) {
+		/* Coast found? */
+		if (HeightMapXY(x, y) > 15) break;
+
+		/* Coast found in the neighborhood? */
+		if (IsValidXY(x + dir_y, y + dir_x) && HeightMapXY(x + dir_y, y + dir_x) > 0) break;
+
+		/* Coast found in the neighborhood on the other side */
+		if (IsValidXY(x - dir_y, y - dir_x) && HeightMapXY(x - dir_y, y - dir_x) > 0) break;
+	}
+
+	/* Coast found or max_coast_dist_from_edge has been reached.
+	 * Soften the coast slope */
+	for (depth = 0; IsValidXY(x, y) && depth <= max_coast_Smooth_depth; depth++, x += dir_x, y += dir_y) {
+		h = HeightMapXY(x, y);
+		h = min(h, h_prev + (4 + depth)); // coast softening formula
+		HeightMapXY(x, y) = h;
+		h_prev = h;
+	}
+}
+
+/** Smooth coasts by modulating height of tiles close to map edges with cosine of distance from edge */
+static void HeightMapSmoothCoasts(void)
+{
+	uint x, y;
+	/* First Smooth NW and SE coasts (y close to 0 and y close to size_y) */
+	for (x = 0; x < _height_map.size_x; x++) {
+		HeightMapSmoothCoastInDirection(x, 0, 0, 1);
+		HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1);
+	}
+	/* First Smooth NE and SW coasts (x close to 0 and x close to size_x) */
+	for (y = 0; y < _height_map.size_y; y++) {
+		HeightMapSmoothCoastInDirection(0, y, 1, 0);
+		HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0);
+	}
+}
+
+/**
+* This routine provides the essential cleanup necessary before OTTD can
+* display the terrain. When generated, the terrain heights can jump more than
+* one level between tiles. This routine smooths out those differences so that
+* the most it can change is one level. When OTTD can support cliffs, this
+* routine may not be necessary.
+*/
+static void HeightMapSmoothSlopes(height_t dh_max)
+{
+	int x, y;
+	for (y = 1; y <= (int)_height_map.size_y; y++) {
+		for (x = 1; x <= (int)_height_map.size_x; x++) {
+			height_t h_max = min(HeightMapXY(x - 1, y), HeightMapXY(x, y - 1)) + dh_max;
+			if (HeightMapXY(x, y) > h_max) HeightMapXY(x, y) = h_max;
+		}
+	}
+	for (y = _height_map.size_y - 1; y >= 0; y--) {
+		for (x = _height_map.size_x - 1; x >= 0; x--) {
+			height_t h_max = min(HeightMapXY(x + 1, y), HeightMapXY(x, y + 1)) + dh_max;
+			if (HeightMapXY(x, y) > h_max) HeightMapXY(x, y) = h_max;
+		}
+	}
+}
+
+/** Height map terraform post processing:
+ *  - water level adjusting
+ *  - coast Smoothing
+ *  - slope Smoothing
+ *  - height histogram redistribution by sine wave transform */
+static void HeightMapNormalize(void)
+{
+	const amplitude_t water_percent = _water_percent[_opt.diff.quantity_sea_lakes];
+	const height_t h_max_new = I2H(_max_height[_opt.diff.terrain_type]);
+	const height_t roughness = 7 + 3 * _patches.tgen_smoothness;
+
+	HeightMapAdjustWaterLevel(water_percent, h_max_new);
+
+	HeightMapCoastLines();
+	HeightMapSmoothSlopes(roughness);
+
+	HeightMapSmoothCoasts();
+	HeightMapSmoothSlopes(roughness);
+
+	HeightMapSineTransform(12, h_max_new);
+	HeightMapSmoothSlopes(16);
+}
+
+static inline int perlin_landXY(uint x, uint y)
+{
+	return HeightMapXY(x, y);
+}
+
+
+/* The following decimals are the octave power modifiers for the Perlin noise */
+static const double _perlin_p_values[][7] = {    // perlin frequency per power
+	{ 0.35, 0.35, 0.35, 0.35, 0.35, 0.25, 0.539 }, // Very smooth
+	{ 0.45, 0.55, 0.45, 0.45, 0.35, 0.25, 0.89  }, // Smooth
+	{ 0.85, 0.80, 0.70, 0.45, 0.45, 0.35, 1.825 }, // Rough 1.825
+	{ 0.95, 0.85, 0.80, 0.55, 0.55, 0.45, 2.245 }  // Very Rough 2.25
+};
+
+/**
+ * The Perlin Noise calculation using large primes
+ * The initial number is adjusted by two values; the generation_seed, and the
+ * passed parameter; prime.
+ * prime is used to allow the perlin noise generator to create useful random
+ * numbers from slightly different series.
+ */
+static double int_noise(const long x, const long y, const int prime)
+{
+	long n = x + y * prime + _patches.generation_seed;
+
+	n = (n << 13) ^ n;
+
+	/* Pseudo-random number generator, using several large primes */
+	return 1.0 - (double)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0;
+}
+
+
+/**
+ * Hj. Malthaner's routine included 2 different noise smoothing methods.
+ * We now use the "raw" int_noise one.
+ * However, it may be useful to move to the other routine in future.
+ * So it is included too.
+ */
+static double smoothed_noise(const int x, const int y, const int prime)
+{
+#if 0
+	/* A hilly world (four corner smooth) */
+	const double sides = int_noise(x - 1, y) + int_noise(x + 1, y) + int_noise(x, y - 1) + int_noise(x, y + 1);
+	const double center  =  int_noise(x, y);
+	return (sides + sides + center * 4) / 8.0;
+#endif
+
+	/* This gives very hilly world */
+	return int_noise(x, y, prime);
+}
+
+
+/**
+ * This routine determines the interpolated value between a and b
+ */
+static inline double linear_interpolate(const double a, const double b, const double x)
+{
+	return a + x * (b - a);
+}
+
+
+/**
+ * This routine returns the smoothed interpolated noise for an x and y, using
+ * the values from the surrounding positions.
+ */
+static double interpolated_noise(const double x, const double y, const int prime)
+{
+	const int integer_X = (int)x;
+	const int integer_Y = (int)y;
+
+	const double fractional_X = x - (double)integer_X;
+	const double fractional_Y = y - (double)integer_Y;
+
+	const double v1 = smoothed_noise(integer_X,     integer_Y,     prime);
+	const double v2 = smoothed_noise(integer_X + 1, integer_Y,     prime);
+	const double v3 = smoothed_noise(integer_X,     integer_Y + 1, prime);
+	const double v4 = smoothed_noise(integer_X + 1, integer_Y + 1, prime);
+
+	const double i1 = linear_interpolate(v1, v2, fractional_X);
+	const double i2 = linear_interpolate(v3, v4, fractional_X);
+
+	return linear_interpolate(i1, i2, fractional_Y);
+}
+
+
+/**
+ * This is a similar function to the main perlin noise calculation, but uses
+ * the value p passed as a parameter rather than selected from the predefined
+ * sequences. as you can guess by its title, i use this to create the indented
+ * coastline, which is just another perlin sequence.
+ */
+static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime)
+{
+	double total = 0.0;
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		const double frequency = (double)(1 << i);
+		const double amplitude = pow(p, (double)i);
+
+		total += interpolated_noise((x * frequency) / 64.0, (y * frequency) / 64.0, prime) * amplitude;
+	}
+
+	return total;
+}
+
+
+/** A small helper function */
+static void TgenSetTileHeight(TileIndex tile, int height)
+{
+	SetTileHeight(tile, height);
+	MakeClear(tile, CLEAR_GRASS, 3);
+}
+
+/**
+ * The main new land generator using Perlin noise. Desert landscape is handled
+ * different to all others to give a desert valley between two high mountains.
+ * Clearly if a low height terrain (flat/very flat) is chosen, then the tropic
+ * areas wont be high enough, and there will be very little tropic on the map.
+ * Thus Tropic works best on Hilly or Mountainous.
+ */
+void GenerateTerrainPerlin(void)
+{
+	uint x, y;
+
+	if (!AllocHeightMap()) return;
+	HeightMapGenerate();
+
+	IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
+	HeightMapNormalize();
+
+	IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
+	/* Transfer height map into OTTD map */
+	for (y = 2; y < _height_map.size_y - 2; y++) {
+		for (x = 2; x < _height_map.size_x - 2; x++) {
+			int height = H2I(HeightMapXY(x, y));
+			if (height < 0) height = 0;
+			if (height > 15) height = 15;
+			TgenSetTileHeight(TileXY(x, y), height);
+		}
+	}
+
+	IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
+	/* Recreate void tiles at the border in case they have been affected by generation */
+	for (y = 0; y < _height_map.size_y - 1; y++) MakeVoid(_height_map.size_x * y + _height_map.size_x - 1);
+	for (x = 0; x < _height_map.size_x;     x++) MakeVoid(_height_map.size_x * y + x);
+
+	FreeHeightMap();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tgp.h	Sat Aug 19 10:00:30 2006 +0000
@@ -0,0 +1,8 @@
+/* $Id$ */
+
+#ifndef TGP_H
+#define TGP_H
+
+void GenerateTerrainPerlin(void);
+
+#endif
--- a/thread.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/thread.c	Sat Aug 19 10:00:30 2006 +0000
@@ -7,7 +7,7 @@
 #if defined(__AMIGA__) || defined(__MORPHOS__)
 OTTDThread* OTTDCreateThread(OTTDThreadFunc function, void* arg) { return NULL; }
 void* OTTDJoinThread(OTTDThread* t) { return NULL; }
-
+void OTTDExitThread() { NOT_REACHED(); };
 
 #elif defined(__OS2__)
 
@@ -57,6 +57,10 @@
 	return ret;
 }
 
+void OTTDExitThread(void)
+{
+	_endthread();
+}
 
 #elif defined(UNIX)
 
@@ -91,6 +95,10 @@
 	return ret;
 }
 
+void OTTDExitThread(void)
+{
+	pthread_exit(NULL);
+}
 
 #elif defined(WIN32)
 
@@ -141,4 +149,9 @@
 	free(t);
 	return ret;
 }
+
+void OTTDExitThread(void)
+{
+	ExitThread(0);
+}
 #endif
--- a/thread.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/thread.h	Sat Aug 19 10:00:30 2006 +0000
@@ -8,6 +8,7 @@
 typedef void* (*OTTDThreadFunc)(void*);
 
 OTTDThread* OTTDCreateThread(OTTDThreadFunc, void*);
-void*   OTTDJoinThread(OTTDThread*);
+void*       OTTDJoinThread(OTTDThread*);
+void        OTTDExitThread(void);
 
 #endif /* THREAD_H */
--- a/town_cmd.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/town_cmd.c	Sat Aug 19 10:00:30 2006 +0000
@@ -28,6 +28,7 @@
 #include "bridge.h"
 #include "date.h"
 #include "table/town_land.h"
+#include "genworld.h"
 
 enum {
 	/* Max towns: 64000 (8 * 8000) */
@@ -1054,7 +1055,10 @@
 	uint num = 0;
 	uint n = ScaleByMapSize(_num_initial_towns[_opt.diff.number_towns] + (Random() & 7));
 
+	SetGeneratingWorldProgress(GWP_TOWN, n);
+
 	do {
+		IncreaseGeneratingWorldProgress(GWP_TOWN);
 		// try 20 times to create a random-sized town for the first loop.
 		if (CreateRandomTown(20, 0) != NULL) num++;
 	} while (--n);
--- a/tree_cmd.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/tree_cmd.c	Sat Aug 19 10:00:30 2006 +0000
@@ -15,6 +15,13 @@
 #include "town.h"
 #include "sound.h"
 #include "variables.h"
+#include "genworld.h"
+
+enum TreePlacer {
+	TP_NONE,
+	TP_ORIGINAL,
+	TP_IMPROVED,
+};
 
 static TreeType GetRandomTreeType(TileIndex tile, uint seed)
 {
@@ -83,18 +90,70 @@
 	} while (--i);
 }
 
+/**
+ * Place a tree at the same height as an existing tree.
+ *  This gives cool effects to the map.
+ */
+void PlaceTreeAtSameHeight(TileIndex tile, uint height)
+{
+	uint i;
+
+	for (i = 0; i < 1000; i++) {
+		uint32 r = Random();
+		int x = GB(r, 0, 5) - 16;
+		int y = GB(r, 8, 5) - 16;
+		TileIndex cur_tile = TILE_MASK(tile + TileDiffXY(x, y));
+
+		/* Keep in range of the existing tree */
+		if (myabs(x) + myabs(y) > 16) continue;
+
+		/* Clear tile, no farm-tiles or rocks */
+		if (!IsTileType(cur_tile, MP_CLEAR) ||
+				IsClearGround(cur_tile, CLEAR_FIELDS) ||
+				IsClearGround(cur_tile, CLEAR_ROCKS))
+			continue;
+
+		/* Not too much height difference */
+		if (myabs(GetTileZ(cur_tile) - height) > 2) continue;
+
+		/* Place one tree and quit */
+		PlaceTree(cur_tile, r);
+		break;
+	}
+}
+
 void PlaceTreesRandomly(void)
 {
-	uint i;
+	uint i, j, ht;
 
 	i = ScaleByMapSize(1000);
 	do {
 		uint32 r = Random();
 		TileIndex tile = RandomTileSeed(r);
+
+		IncreaseGeneratingWorldProgress(GWP_TREE);
+
 		if (IsTileType(tile, MP_CLEAR) &&
 				!IsClearGround(tile, CLEAR_FIELDS) &&
 				!IsClearGround(tile, CLEAR_ROCKS)) {
 			PlaceTree(tile, r);
+			if (_patches.tree_placer != TP_IMPROVED) continue;
+
+			/* Place a number of trees based on the tile height.
+			 *  This gives a cool effect of multiple trees close together.
+			 *  It is almost real life ;) */
+			ht = GetTileZ(tile);
+			/* The higher we get, the more trees we plant */
+			j = GetTileZ(tile) / TILE_HEIGHT * 2;
+			while (j--) {
+				/* Above snowline more trees! */
+				if (_opt.landscape == LT_HILLY && ht > _opt.snow_line) {
+					PlaceTreeAtSameHeight(tile, ht);
+					PlaceTreeAtSameHeight(tile, ht);
+				};
+
+				PlaceTreeAtSameHeight(tile, ht);
+			}
 		}
 	} while (--i);
 
@@ -105,7 +164,10 @@
 		do {
 			uint32 r = Random();
 			TileIndex tile = RandomTileSeed(r);
-			if (IsTileType(tile, MP_CLEAR) && GetTropicZone(tile) == TROPICZONE_RAINFOREST) {
+
+			IncreaseGeneratingWorldProgress(GWP_TREE);
+
+			if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_FIELDS) && GetTropicZone(tile) == TROPICZONE_RAINFOREST) {
 				PlaceTree(tile, r);
 			}
 		} while (--i);
@@ -114,11 +176,24 @@
 
 void GenerateTrees(void)
 {
-	uint i;
+	uint i, total;
+
+	if (_patches.tree_placer == TP_NONE) return;
 
 	if (_opt.landscape != LT_CANDY) PlaceMoreTrees();
 
-	for (i = _opt.landscape == LT_HILLY ? 15 : 6; i != 0; i--) {
+	switch (_patches.tree_placer) {
+		case TP_ORIGINAL: i = _opt.landscape == LT_HILLY ? 15 : 6; break;
+		case TP_IMPROVED: i = _opt.landscape == LT_HILLY ?  4 : 2; break;
+		default: NOT_REACHED(); return;
+	}
+
+	total = ScaleByMapSize(1000);
+	if (_opt.landscape == LT_DESERT) total += ScaleByMapSize(15000);
+	total *= i;
+	SetGeneratingWorldProgress(GWP_TREE, total);
+
+	for (; i != 0; i--) {
 		PlaceTreesRandomly();
 	}
 }
--- a/unix.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/unix.c	Sat Aug 19 10:00:30 2006 +0000
@@ -214,6 +214,7 @@
 	_path.save_dir = str_fmt("%ssave", _path.personal_dir);
 	_path.autosave_dir = str_fmt("%s/autosave", _path.save_dir);
 	_path.scenario_dir = str_fmt("%sscenario", _path.personal_dir);
+	_path.heightmap_dir = str_fmt("%sscenario/heightmap", _path.personal_dir);
 	_path.gm_dir = str_fmt("%sgm/", _path.game_data_dir);
 	_path.data_dir = str_fmt("%sdata/", _path.game_data_dir);
 
@@ -236,6 +237,7 @@
 	mkdir(_path.save_dir, 0755);
 	mkdir(_path.autosave_dir, 0755);
 	mkdir(_path.scenario_dir, 0755);
+	mkdir(_path.heightmap_dir, 0755);
 }
 
 bool InsertTextBufferClipboard(Textbuf *tb)
--- a/unmovable_cmd.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/unmovable_cmd.c	Sat Aug 19 10:00:30 2006 +0000
@@ -18,6 +18,7 @@
 #include "unmovable_map.h"
 #include "variables.h"
 #include "table/unmovable_land.h"
+#include "genworld.h"
 
 /** Destroy a HQ.
  * During normal gameplay you can only implicitely destroy a HQ when you are
@@ -309,12 +310,13 @@
 	BEGIN_TILE_LOOP(tile, 9, 9, tile_s)
 		if (IsTransmitterTile(tile)) return true;
 	END_TILE_LOOP(tile, 9, 9, tile_s)
+
 	return false;
 }
 
 void GenerateUnmovables(void)
 {
-	int i,j;
+	int i, li, j, loop_count;
 	TileIndex tile;
 	uint h;
 	uint maxx;
@@ -324,12 +326,16 @@
 
 	/* add radio tower */
 	i = ScaleByMapSize(1000);
-	j = ScaleByMapSize(40); // maximum number of radio towers on the map
+	j = ScaleByMapSize(15); // maximum number of radio towers on the map
+	li = ScaleByMapSize1D((Random() & 3) + 7);
+	SetGeneratingWorldProgress(GWP_UNMOVABLE, j + li);
+
 	do {
 		tile = RandomTile();
 		if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == SLOPE_FLAT && h >= TILE_HEIGHT * 4) {
 			if (IsRadioTowerNearby(tile)) continue;
 			MakeTransmitter(tile);
+			IncreaseGeneratingWorldProgress(GWP_UNMOVABLE);
 			if (--j == 0) break;
 		}
 	} while (--i);
@@ -337,16 +343,27 @@
 	if (_opt.landscape == LT_DESERT) return;
 
 	/* add lighthouses */
-	i = ScaleByMapSize1D((Random() & 3) + 7);
+	i = li;
 	maxx = MapMaxX();
 	maxy = MapMaxY();
+	loop_count = 0;
 	do {
 		uint32 r;
 		DiagDirection dir;
+		int perimeter;
 
 restart:
+		/* Avoid infinite loops */
+		if (++loop_count > 1000) break;
+
 		r = Random();
-		dir = GB(r, 30, 2);
+
+		/* Scatter the lighthouses more evenly around the perimeter */
+		perimeter = (GB(r, 16, 16) % (2 * (maxx + maxy))) - maxy;
+		for (dir = DIAGDIR_NE; perimeter > 0; dir++) {
+			perimeter -= (DiagDirToAxis(dir) == AXIS_X) ? maxx : maxy;
+		}
+
 		switch (dir) {
 			default:
 			case DIAGDIR_NE: tile = TileXY(maxx,     r % maxy); break;
@@ -363,6 +380,7 @@
 		assert(tile == TILE_MASK(tile));
 
 		MakeLighthouse(tile);
+		IncreaseGeneratingWorldProgress(GWP_UNMOVABLE);
 	} while (--i);
 }
 
--- a/variables.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/variables.h	Sat Aug 19 10:00:30 2006 +0000
@@ -107,7 +107,15 @@
 	bool roadveh_queue;			// buggy road vehicle queueing
 	bool autoscroll;				// scroll when moving mouse to the edge.
 	byte errmsg_duration;		// duration of error message
+	byte land_generator;		// the landscape generator
+	byte oil_refinery_limit;	// distance oil refineries allowed from map edge
 	byte snow_line_height;	// a number 0-15 that configured snow line height
+	byte tgen_smoothness;		// how rough is the terrain from 0-3
+	uint32 generation_seed;	// noise seed for world generation
+	byte tree_placer;				// the tree placer algorithm
+	byte heightmap_rotation;// rotation director for the heightmap
+	uint16 progress_update_interval;// interval between two updates of the progress in hundreds of milliseconds
+	byte se_flat_world_height;	// land height a flat world gets in SE
 	bool bribe;							// enable bribing the local authority
 	bool nonuniform_stations;// allow nonuniform train stations
 	bool always_small_airport; // always allow small airports
@@ -244,6 +252,7 @@
 	char *save_dir;
 	char *autosave_dir;
 	char *scenario_dir;
+	char *heightmap_dir;
 	char *second_data_dir;
 } Paths;
 
--- a/video/cocoa_v.m	Sat Aug 19 09:31:22 2006 +0000
+++ b/video/cocoa_v.m	Sat Aug 19 10:00:30 2006 +0000
@@ -56,6 +56,7 @@
 #include "../window.h"
 #include "../network.h"
 #include "../variables.h"
+#include "../genworld.h"
 #include "../os/macosx/splash.h"
 
 #include "cocoa_v.h"
@@ -709,7 +710,7 @@
 #endif
 		{
 			if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
-		} else if (_fast_forward & 2) {
+		} else if (_fast_forward & 2 && !IsGeneratingWorld()) {
 			_fast_forward = 0;
 		}
 
--- a/video/dedicated_v.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/video/dedicated_v.c	Sat Aug 19 10:00:30 2006 +0000
@@ -12,6 +12,7 @@
 #include "../window.h"
 #include "../console.h"
 #include "../variables.h"
+#include "../genworld.h"
 #include "dedicated_v.h"
 
 #ifdef BEOS_NET_SERVER
@@ -240,8 +241,9 @@
 
 	/* If SwitchMode is SM_LOAD, it means that the user used the '-g' options */
 	if (_switch_mode != SM_LOAD) {
+		StartNewGameWithoutGUI(GENERATE_NEW_SEED);
+		SwitchMode(_switch_mode);
 		_switch_mode = SM_NONE;
-		GenRandomNewGame(Random(), InteractiveRandom());
 	} else {
 		_switch_mode = SM_NONE;
 		/* First we need to test if the savegame can be loaded, else we will end up playing the
--- a/video/sdl_v.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/video/sdl_v.c	Sat Aug 19 10:00:30 2006 +0000
@@ -13,6 +13,7 @@
 #include "../window.h"
 #include "../network.h"
 #include "../variables.h"
+#include "../genworld.h"
 #include "sdl_v.h"
 #include <SDL.h>
 
@@ -461,7 +462,7 @@
 		if (keys[SDLK_TAB])
 #endif
 		{
-			if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
+			if (!_networking && _game_mode != GM_MENU && !IsGeneratingWorld()) _fast_forward |= 2;
 		} else if (_fast_forward & 2) {
 			_fast_forward = 0;
 		}
--- a/video/win32_v.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/video/win32_v.c	Sat Aug 19 10:00:30 2006 +0000
@@ -9,6 +9,7 @@
 #include "../variables.h"
 #include "../win32.h"
 #include "../window.h"
+#include "../genworld.h"
 #include "win32_v.h"
 #include <windows.h>
 
@@ -792,7 +793,7 @@
 			 * real key is in the upper 16 bits (see WM_SYSKEYDOWN in WndProcGdi()) */
 			if ((_pressed_key >> 16) & WKC_TAB &&
 #endif
-			    !_networking && _game_mode != GM_MENU)
+			    !_networking && _game_mode != GM_MENU && !IsGeneratingWorld())
 				_fast_forward |= 2;
 		} else if (_fast_forward & 2) {
 			_fast_forward = 0;
--- a/win32.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/win32.c	Sat Aug 19 10:00:30 2006 +0000
@@ -899,6 +899,7 @@
 	_path.save_dir = str_fmt("%ssave", cfg);
 	_path.autosave_dir = str_fmt("%s\\autosave", _path.save_dir);
 	_path.scenario_dir = str_fmt("%sscenario", cfg);
+	_path.heightmap_dir = str_fmt("%sscenario\\heightmap", cfg);
 	_path.gm_dir = str_fmt("%sgm\\", cfg);
 	_path.data_dir = str_fmt("%sdata\\", cfg);
 	_path.lang_dir = str_fmt("%slang\\", cfg);
@@ -913,6 +914,7 @@
 	CreateDirectory(_path.save_dir, NULL);
 	CreateDirectory(_path.autosave_dir, NULL);
 	CreateDirectory(_path.scenario_dir, NULL);
+	CreateDirectory(_path.heightmap_dir, NULL);
 }
 
 int CDECL snprintf(char *str, size_t size, const char *format, ...)
--- a/window.c	Sat Aug 19 09:31:22 2006 +0000
+++ b/window.c	Sat Aug 19 10:00:30 2006 +0000
@@ -12,6 +12,7 @@
 #include "console.h"
 #include "variables.h"
 #include "table/sprites.h"
+#include "genworld.h"
 
 // delta between mouse cursor and upper left corner of dragged window
 static Point _drag_delta;
@@ -1323,10 +1324,11 @@
 	we.keypress.cont = true;
 
 	// check if we have a query string window open before allowing hotkeys
-	if (FindWindowById(WC_QUERY_STRING,     0) != NULL ||
-			FindWindowById(WC_SEND_NETWORK_MSG, 0) != NULL ||
-			FindWindowById(WC_CONSOLE,          0) != NULL ||
-			FindWindowById(WC_SAVELOAD,         0) != NULL) {
+	if (FindWindowById(WC_QUERY_STRING,       0) != NULL ||
+			FindWindowById(WC_SEND_NETWORK_MSG,   0) != NULL ||
+			FindWindowById(WC_GENERATE_LANDSCAPE, 0) != NULL ||
+			FindWindowById(WC_CONSOLE,            0) != NULL ||
+			FindWindowById(WC_SAVELOAD,           0) != NULL) {
 		query_open = true;
 	}
 
@@ -1337,6 +1339,7 @@
 		if (query_open &&
 				w->window_class != WC_QUERY_STRING &&
 				w->window_class != WC_SEND_NETWORK_MSG &&
+				w->window_class != WC_GENERATE_LANDSCAPE &&
 				w->window_class != WC_CONSOLE &&
 				w->window_class != WC_SAVELOAD) {
 			continue;
@@ -1376,7 +1379,7 @@
 	y = _cursor.pos.y;
 
 	if (click == 0 && mousewheel == 0) {
-		if (_patches.autoscroll && _game_mode != GM_MENU) {
+		if (_patches.autoscroll && _game_mode != GM_MENU && !IsGeneratingWorld()) {
 			w = FindWindowFromPt(x, y);
 			if (w == NULL || w->flags4 & WF_DISABLE_VP_SCROLL) return;
 			vp = IsPtInWindowViewport(w, x, y);
@@ -1406,7 +1409,7 @@
 	w = MaybeBringWindowToFront(w);
 	vp = IsPtInWindowViewport(w, x, y);
 	if (vp != NULL) {
-		if (_game_mode == GM_MENU) return;
+		if (_game_mode == GM_MENU || IsGeneratingWorld()) return;
 
 		// only allow zooming in-out in main window, or in viewports
 		if (mousewheel &&
@@ -1455,7 +1458,16 @@
 	int click;
 	int mousewheel;
 
-	_current_player = _local_player;
+	/*
+	 * During the generation of the world, there might be
+	 * another thread that is currently building for example
+	 * a road. To not interfere with those tasks, we should
+	 * NOT change the _current_player here.
+	 *
+	 * This is not necessary either, as the only events that
+	 * can be handled are the 'close application' events
+	 */
+	if (!IsGeneratingWorld()) _current_player = _local_player;
 
 	// Handle pressed keys
 	if (_pressed_key != 0) {
--- a/window.h	Sat Aug 19 09:31:22 2006 +0000
+++ b/window.h	Sat Aug 19 10:00:30 2006 +0000
@@ -304,6 +304,16 @@
 } querystr_d;
 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(querystr_d));
 
+typedef struct query_d {
+	StringID caption;
+	StringID message;
+	WindowClass wnd_class;
+	WindowNumber wnd_num;
+	void (*ok_cancel_callback)(bool ok_clicked);
+	bool calledback;
+} query_d;
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(query_d));
+
 typedef struct {
 	byte item_count;      /* follow_vehicle */
 	byte sel_index;       /* scrollpos_x */