From 7e292b36e4cec68e45a98c8bb8500fe3a72e8aa3 Mon Sep 17 00:00:00 2001
From: johns <>
Date: Sun, 13 Aug 2000 15:23:02 +0000
Subject: [PATCH] Tileset structure changed, many hardcoded stuff removed.

---
 src/include/tileset.h      |  59 +++-
 src/map/Makefile           |   2 +-
 src/map/map.cpp            |  16 +-
 src/map/map_draw.cpp       |   6 +-
 src/map/map_rock.cpp       |  25 +-
 src/map/map_wall.cpp       |  17 +-
 src/map/map_wood.cpp       |  20 +-
 src/map/script_map.cpp     |  83 ++---
 src/map/script_tileset.cpp | 138 ++++++++
 src/map/tileset.cpp        | 637 +++++++++++++++++++++++++++----------
 src/stratagus/script.cpp   |   4 +-
 11 files changed, 720 insertions(+), 287 deletions(-)
 create mode 100644 src/map/script_tileset.cpp

diff --git a/src/include/tileset.h b/src/include/tileset.h
index 343c65617..1cc9f0345 100644
--- a/src/include/tileset.h
+++ b/src/include/tileset.h
@@ -9,11 +9,10 @@
 //	   FreeCraft - A free fantasy real time strategy game engine
 //
 /**@name tileset.h	-	The tileset headerfile. */
-/*
-**	(c) Copyright 1998-2000 by Lutz Sammer
-**
-**	$Id$
-*/
+//
+//	(c) Copyright 1998-2000 by Lutz Sammer
+//
+//	$Id$
 
 #ifndef __TILESET_H__
 #define __TILESET_H__
@@ -27,26 +26,34 @@
 #define TileSizeX	32		/// Size of a tile in X
 #define TileSizeY	32		/// Size of a tile in Y
 
+//#define MaxTilesInTileset	1024	/// Current limit of tiles in tileset
+#define MaxTilesInTileset	3072	/// Current limit of tiles in tileset
+
+#if 0
+
 #define TILE_PER_ROW	16		/// tiles stored in an image row
 #define TILE_ROWS	24		/// tiles rows in the image
 #define TILE_COUNT	(TILE_PER_ROW*TILE_ROWS)
 
+#endif
+
+
 /**
 **   These are used for lookup tiles types
 **   mainly used for the FOW implementation of the seen woods/rocks
 */
 enum _tile_type_ {
     TileTypeUnknown,			/// unknown tile type
-    TileTypeNoWood,			/// no wood tile
+    TileTypeNoWood,			/// UNUSED: no wood tile
     TileTypeWood,			/// any wood tile
     TileTypeGrass,			/// any grass tile
-    TileTypeNoRock,			/// no rock tile
+    TileTypeNoRock,			/// UNUSED: no rock tile
     TileTypeRock,			/// any rock tile
     TileTypeCoast,			/// any coast tile
-    TileTypeHWall,			/// any human wall tile
-    TileTypeOWall,			/// any orc wall tile
-    TileTypeNoWall,			/// no wall tile
-    TileTypeWater			/// any water tile
+    TileTypeHumanWall,			/// any human wall tile
+    TileTypeOrcWall,			/// any orc wall tile
+    TileTypeNoWall,			/// UNUSED: no wall tile
+    TileTypeWater,			/// any water tile
 };
 
 /**
@@ -56,18 +63,33 @@ typedef struct _tileset_ {
     char*	Ident;			/// tileset identifier
     char*	Name;			/// name for future extensions
     char*	File;			/// file containing image data
+
     const unsigned short* Table;	/// pud to internal conversion table
-    unsigned char* TileTypeTable;	/// lookup tile type
-    unsigned	FirstWoodTile;		/// first wood tile
-    unsigned	NoWoodTile;		/// tile placed where wood is gone
-    unsigned	FirstRockTile;		/// first rock tile :)
-    unsigned	NoRockTile;		/// tile placed where rocks are gone
+    unsigned char* TileTypeTable;	/// for fast lookup of tile type
+    unsigned short* AnimationTable;	/// Tile Animation sequences
+
+#if 1
+    // FIXME: old code should be complete removed.
     unsigned	HumanWall100Tile;	/// 100% wall
     unsigned	HumanWall50Tile;	/// 100% wall
     unsigned	HumanNoWallTile;	/// tile placed where walls are gone
     unsigned	OrcWall100Tile;		/// 100% wall
     unsigned	OrcWall50Tile;		/// 100% wall
     unsigned	OrcNoWallTile;		/// tile placed where walls are gone
+#endif
+
+    unsigned	ExtraTrees[6];		/// extra tree tiles for removed
+    unsigned	TopOneTree;		/// tile for one tree top
+    unsigned	MidOneTree;		/// tile for one tree middle
+    unsigned	BotOneTree;		/// tile for one tree bottom
+    unsigned	RemovedTree;		/// tile placed where trees are gone
+    unsigned	GrowingTree[2];		/// Growing tree tiles
+
+    unsigned	ExtraRocks[6];		/// extra rock tiles for removed
+    unsigned	TopOneRock;		/// tile for one rock top
+    unsigned	MidOneRock;		/// tile for one rock middle
+    unsigned	BotOneRock;		/// tile for one rock bottom
+    unsigned	RemovedRock;		/// tile placed where rocks are gone
 } Tileset;
 
 // FIXME: this #define's should be removed
@@ -85,6 +107,7 @@ typedef struct _tileset_ {
 --	Variables
 ----------------------------------------------------------------------------*/
 
+extern char** TilesetWcNames;		/// Mapping wc-number 2 symbol
 extern Tileset Tilesets[TilesetMax];	/// Tileset information
 
 /*----------------------------------------------------------------------------
@@ -92,6 +115,10 @@ extern Tileset Tilesets[TilesetMax];	/// Tileset information
 ----------------------------------------------------------------------------*/
 
 extern void LoadTileset(void);		/// Load tileset definition
+extern void SaveTileset(FILE*);		/// Save the tileset configuration
+extern void CleanTileset(void);		/// Cleanup the tileset module
+
+extern void TilesetCclRegister(void);	/// Register CCL features for tileset
 
 /*----------------------------------------------------------------------------
 --	Predicates
diff --git a/src/map/Makefile b/src/map/Makefile
index 85470e5c4..aef7e78fc 100644
--- a/src/map/Makefile
+++ b/src/map/Makefile
@@ -23,6 +23,6 @@ MODULE  = map
 
 OBJS	= map.$(OE) map_draw.$(OE) ccl_map.$(OE) \
 	  map_fog.$(OE) map_rock.$(OE) map_wood.$(OE) map_wall.$(OE) \
-	  minimap.$(OE) tileset.$(OE)
+	  minimap.$(OE) tileset.$(OE) ccl_tileset.$(OE)
 
 include $(TOPDIR)/Common.mk
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 4b607576b..fc44c23bd 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -80,11 +80,11 @@ global void MapMarkSeenTile( int x, int y )
 
     // handle WOODs
 
-    if ( st != TheMap.Tileset->NoWoodTile
-	    && t == TheMap.Tileset->NoWoodTile ) {
+    if ( st != TheMap.Tileset->RemovedTree
+	    && t == TheMap.Tileset->RemovedTree ) {
 	MapFixWood( x, y );
-    } else if ( st == TheMap.Tileset->NoWoodTile
-	    && t != TheMap.Tileset->NoWoodTile ) {
+    } else if ( st == TheMap.Tileset->RemovedTree
+	    && t != TheMap.Tileset->RemovedTree ) {
 	FixWood( x, y );
     } else if ( MapWoodChk( x, y ) ) {
 	FixWood( x, y );
@@ -94,12 +94,12 @@ global void MapMarkSeenTile( int x, int y )
     // handle WALLs
 
 #define ISTILEWALL(tile) \
-    (TheMap.Tileset->TileTypeTable[(tile)] == TileTypeHWall	\
-	|| TheMap.Tileset->TileTypeTable[(tile)] == TileTypeOWall)
+    (TheMap.Tileset->TileTypeTable[(tile)] == TileTypeHumanWall	\
+	|| TheMap.Tileset->TileTypeTable[(tile)] == TileTypeOrcWall)
 
-    if ( ISTILEWALL(st) && !ISTILEWALL(st) )
+    if ( ISTILEWALL(st) && !ISTILEWALL(t) )
 	MapFixWall( x, y );
-    else if ( !ISTILEWALL(st) && ISTILEWALL(st) )
+    else if ( !ISTILEWALL(st) && ISTILEWALL(t) )
 	FixWall( x, y );
     else if ( MapWallChk( x, y, -1 ) ) {
 	FixWall( x, y );
diff --git a/src/map/map_draw.cpp b/src/map/map_draw.cpp
index a7df7d238..4a50db02d 100644
--- a/src/map/map_draw.cpp
+++ b/src/map/map_draw.cpp
@@ -67,7 +67,7 @@ typedef struct _tile_cache {
 **	Contains pointer, if the tile is cached.
 **	FIXME: could save memory here and only use how many tiles exits.
 */
-local TileCache* TileCached[TILE_COUNT];
+local TileCache* TileCached[MaxTilesInTileset];
 
 /**
 **	Number of tile caches.
@@ -92,7 +92,7 @@ local struct dl_head TileCacheLRU[1] = {
 **	Contains pointer, to last video position, where this tile was drawn.
 **	FIXME: could save memory here and only use how many tiles exits.
 */
-local void* TileCached[TILE_COUNT];
+local void* TileCached[MaxTilesInTileset];
 
 #endif
 
@@ -1259,7 +1259,7 @@ global void MapColorCycle(void)
     TileCache* cache;
 
     // FIXME: the easy version just remove color cycling tiles from cache.
-    for( i=0; i<TILE_COUNT; ++i ) {
+    for( i=0; i<TheMap.TileCount; ++i ) {
 	if( TheMap.Tileset->TileTypeTable[i]==TileTypeWater ) {
 	    if( (cache=TileCached[i]) ) {
 		DebugLevel3("Flush\n");
diff --git a/src/map/map_rock.cpp b/src/map/map_rock.cpp
index 8a4a35e3a..76f8f94c1 100644
--- a/src/map/map_rock.cpp
+++ b/src/map/map_rock.cpp
@@ -32,16 +32,17 @@
 --	Declarations
 ----------------------------------------------------------------------------*/
 
- // FIXME: -1 is hack should be fixed later
-#define FIRST_ROCK_TILE  (TheMap.Tileset->FirstRockTile-1)
-
 /*----------------------------------------------------------------------------
 --	Variables
 ----------------------------------------------------------------------------*/
 
-local const int RockTable[16] = {
+/**
+**	Table for rock removable.
+*/
+global int RockTable[20] = {
 //  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A,  B,  C,  D,  E,  F
    -1, 22, -1,  1, 20, 21,  3,  2, -1,  9, -1, 23,  6,  8,  5, 36
+   ,7, 10, 11, 4
 };
 
 /*----------------------------------------------------------------------------
@@ -93,16 +94,14 @@ local int FixRock(int x,int y) // used by MapRemoveRock and PreprocessMap
     // Vladi: still to filter tiles w. corner empties -- note: the original
     // tiles and order are not perfect either. It's a hack but is enough and
     // looks almost fine.
-	    if (MapRockChk(x+1,y-1) == 0) tile =  7; else
-	    if (MapRockChk(x+1,y+1) == 0) tile = 10; else
-	    if (MapRockChk(x-1,y+1) == 0) tile = 11; else
-	    if (MapRockChk(x-1,y-1) == 0) tile =  4; else
-				tile = RockTable[15]; // not required really
+	    if (MapRockChk(x+1,y-1) == 0) tile = RockTable[16]; else
+	    if (MapRockChk(x+1,y+1) == 0) tile = RockTable[17]; else
+	    if (MapRockChk(x-1,y+1) == 0) tile = RockTable[18]; else
+	    if (MapRockChk(x-1,y-1) == 0) tile = RockTable[19]; else
+			    tile = RockTable[15]; // not required really
 	}
 
-	tile += FIRST_ROCK_TILE;
 	mf=TheMap.Fields+x+y*TheMap.Width;
-
 	if ( mf->SeenTile == tile) {
 	    return 0;
 	}
@@ -134,7 +133,7 @@ global void MapRemoveRock(unsigned x,unsigned y)
 
     mf=TheMap.Fields+x+y*TheMap.Width;
 
-    mf->Tile=TheMap.Tileset->NoRockTile;
+    mf->Tile=TheMap.Tileset->RemovedRock;
     mf->Flags &= ~(MapFieldRocks|MapFieldUnpassable);
 
     UpdateMinimapXY(x,y);		// FIXME: should be done if visible?
@@ -146,7 +145,7 @@ global void MapRemoveRock(unsigned x,unsigned y)
     if( mf->Flags&MapFieldVisible ) {
 #endif
 	MustRedraw|=RedrawMaps;
-	// FIXME: Should we do this? MapMarkSeenTile(x,y);
+	// FIXME: didn't make it better MapMarkSeenTile(x,y);
     }
 }
 
diff --git a/src/map/map_wall.cpp b/src/map/map_wall.cpp
index 23433f614..3a5cfe2a2 100644
--- a/src/map/map_wall.cpp
+++ b/src/map/map_wall.cpp
@@ -46,6 +46,12 @@
 local int WallTable[16] = {
 //   0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A,  B,  C,  D,  E,  F
      0,  4,  2,  7,  1,  5,  3,  8,  9, 14, 11, 16, 10, 15, 13, 17
+/*
+    0x90
+    0x92
+    0xA0
+    0x94
+*/
 };
 
 /*----------------------------------------------------------------------------
@@ -76,7 +82,7 @@ global int MapWallChk(int x,int y,int walltype) // used by FixWall, walltype==-1
     t=TheMap.Tileset->TileTypeTable[
 	    TheMap.Fields[(x)+(y)*TheMap.Width].SeenTile];
     if (walltype == -1) {
-	return t == TileTypeHWall || t == TileTypeOWall ;
+	return t == TileTypeHumanWall || t == TileTypeOrcWall ;
     }
     return t == walltype;
 }
@@ -87,12 +93,17 @@ global int FixWall(int x,int y) // used by MapRemoveWall and PreprocessMap
   int walltype;
   MapField* mf;
 
+  //
+  //	Outside the map
+  //
   if( x<0 || y<0 || x>=TheMap.Width || y>=TheMap.Height ) {
       return 0;
   }
   mf=TheMap.Fields+(x)+(y)*TheMap.Width;
   walltype = TheMap.Tileset->TileTypeTable[mf->SeenTile];
-  if ( walltype != TileTypeHWall && walltype != TileTypeOWall ) return 0;
+  if ( walltype != TileTypeHumanWall && walltype != TileTypeOrcWall ) {
+      return 0;
+  }
 
   #define WALL(xx,yy) (MapWallChk(xx,yy,walltype) != 0)
   tile = 0;
@@ -103,7 +114,7 @@ global int FixWall(int x,int y) // used by MapRemoveWall and PreprocessMap
 
   tile = WallTable[tile];
 
-  if (walltype == TileTypeHWall)
+  if (walltype == TileTypeHumanWall)
      {
      if (mf->Value < WALL_50HP)
         tile += TheMap.Tileset->HumanWall50Tile;
diff --git a/src/map/map_wood.cpp b/src/map/map_wood.cpp
index 622e577bf..57320c6ce 100644
--- a/src/map/map_wood.cpp
+++ b/src/map/map_wood.cpp
@@ -35,12 +35,9 @@
 global int ForestRegeneration;		/// Forest regeneration
 
 /**
-**	Table for wood removable
+**	Table for wood removable.
 */
-local int WoodTable[16] = {
-//  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A,  B,  C,  D,  E,  F
-   -1, 22, -1,  1, 20, 21,  3,  2, -1,  9, -1, 23,  6,  8,  5,  4
-};
+global int WoodTable[16];
 
 /*----------------------------------------------------------------------------
 --	Functions
@@ -88,9 +85,6 @@ global int FixWood(int x,int y) // used by MapRemoveWood2 and PreprocessMap
     if (tile == -1) {
 	MapRemoveWood(x,y);
     } else {
-    // DON'T work EGCC failure tile += TheMap.Tileset->FirstWoodTile;
-	tile += 0x65;
-	DebugLevel3(__FUNCTION__":%x\n", TheMap.Tileset->FirstWoodTile);
 	mf=TheMap.Fields+x+y*TheMap.Width;
 	if ( mf->SeenTile == tile) {
 	    return 0;
@@ -123,7 +117,7 @@ global void MapRemoveWood(unsigned x,unsigned y)
 
     mf=TheMap.Fields+x+y*TheMap.Width;
 
-    mf->Tile=TheMap.Tileset->NoWoodTile;
+    mf->Tile=TheMap.Tileset->RemovedTree;
     mf->Flags &= ~(MapFieldForest|MapFieldUnpassable);
     mf->Value=0;
 
@@ -160,23 +154,23 @@ global void RegenerateForest(void)
     for( x=0; x<TheMap.Width; ++x ) {
 	for( y=0; y<TheMap.Height; ++y ) {
 	    mf=TheMap.Fields+x+y*TheMap.Width;
-	    if( mf->Tile==TheMap.Tileset->NoWoodTile ) {
+	    if( mf->Tile==TheMap.Tileset->RemovedTree ) {
 		if( mf->Value>=ForestRegeneration
 			|| ++mf->Value==ForestRegeneration )  {
 		    if( x && !(mf->Flags&(MapFieldWall|MapFieldUnpassable
 				    |MapFieldLandUnit|MapFieldBuilding)) ) {
 			tmp=mf-TheMap.Width;
-			if( tmp->Tile==TheMap.Tileset->NoWoodTile 
+			if( tmp->Tile==TheMap.Tileset->RemovedTree 
 				&& tmp->Value>=ForestRegeneration
 				&& !(tmp->Flags&(MapFieldWall|MapFieldUnpassable
 				    |MapFieldLandUnit|MapFieldBuilding)) ) {
 
 			    DebugLevel0("Real place wood\n");
-			    tmp->Tile=121;
+			    tmp->Tile=TheMap.Tileset->TopOneTree;
 			    tmp->Value=0;
 			    tmp->Flags|=MapFieldForest|MapFieldUnpassable;
 
-			    mf->Tile=123;
+			    mf->Tile=TheMap.Tileset->BotOneTree;
 			    mf->Value=0;
 			    mf->Flags|=MapFieldForest|MapFieldUnpassable;
 #ifdef NEW_FOW
diff --git a/src/map/script_map.cpp b/src/map/script_map.cpp
index a777da70d..b52b035cf 100644
--- a/src/map/script_map.cpp
+++ b/src/map/script_map.cpp
@@ -9,11 +9,10 @@
 //	   FreeCraft - A free fantasy real time strategy game engine
 //
 /**@name ccl_map.c	-	The map ccl functions. */
-/*
-**	(c) Copyright 1999,2000 by Lutz Sammer
-**
-**	$Id$
-*/
+//
+//	(c) Copyright 1999,2000 by Lutz Sammer
+//
+//	$Id$
 
 //@{
 
@@ -29,7 +28,6 @@
 #if defined(USE_CCL) || defined(USE_CCL2)	// {
 
 #include "ccl.h"
-#include "tileset.h"
 #include "map.h"
 #include "minimap.h"
 
@@ -51,6 +49,23 @@ local SCM CclRevealMap(void)
     return SCM_UNSPECIFIED;
 }
 
+/**
+**	Set fog of war on/off.
+**
+**	@param flag	True = turning fog of war on, false = off.
+**
+**	@returns	The old state of fog of war.
+*/
+local SCM CclSetFogOfWar(SCM flag)
+{
+    int old;
+
+    old=TheMap.NoFogOfWar;
+    TheMap.NoFogOfWar=gh_scm2bool(flag);
+
+    return gh_int2scm(old);
+}
+
 /**
 **	Enable fog of war.
 */
@@ -199,57 +214,6 @@ local SCM CclForestRegeneration(SCM speed)
     return SCM_UNSPECIFIED;
 }
 
-//.............................................................................
-//.	Tables
-//.............................................................................
-
-/**
-**	Parse tileset definition.
-**
-**	@param slot	Slot name
-**	@param name	Reference name
-**	@param file	Graphic file
-**	@param table	Conversion table
-*/
-local SCM CclTileset(SCM slot,SCM name,SCM file,SCM table)
-{
-    int type;
-    int i;
-    unsigned short* wp;
-
-    if( !gh_symbol_p(slot) ) {
-	fprintf(stderr,"Illegal tileset slot name\n");
-	return SCM_UNSPECIFIED;
-    }
-    if( slot==gh_symbol2scm("tileset-summer") ) {
-	type=TilesetSummer;
-    } else if( slot==gh_symbol2scm("tileset-winter") ) {
-	type=TilesetWinter;
-    } else if( slot==gh_symbol2scm("tileset-wasteland") ) {
-	type=TilesetWasteland;
-    } else if( slot==gh_symbol2scm("tileset-swamp") ) {
-	type=TilesetSwamp;
-    } else {
-	fprintf(stderr,"Wrong tileset slot name\n");
-	return SCM_UNSPECIFIED;
-    }
-    Tilesets[type].Name=gh_scm2newstr(name,NULL);
-    Tilesets[type].File=gh_scm2newstr(file,NULL);
-
-    // CONVERT TABLE!!
-    if( gh_vector_length(table)!=2528 ) {	// 0x9E0
-	fprintf(stderr,"Wrong conversion table length\n");
-	return SCM_UNSPECIFIED;
-    }
-
-    Tilesets[type].Table=wp=malloc(sizeof(*Tilesets[type].Table)*2528);
-    for( i=0; i<2528; ++i ) {
-	wp[i]=gh_scm2int(gh_vector_ref(table,gh_int2scm(i)));
-    }
-
-    return SCM_UNSPECIFIED;
-}
-
 /**
 **	Register CCL features for map.
 */
@@ -257,6 +221,8 @@ global void MapCclRegister(void)
 {
     gh_new_procedure0_0("reveal-map",CclRevealMap);
 
+    gh_new_procedure1_0("set-fog-of-war!",CclSetFogOfWar);
+
     gh_new_procedure0_0("fog-of-war",CclFogOfWar);
     gh_new_procedure0_0("no-fog-of-war",CclNoFogOfWar);
 
@@ -265,13 +231,12 @@ global void MapCclRegister(void)
 
     gh_new_procedure0_0("original-fog-of-war",CclOriginalFogOfWar);
     gh_new_procedure0_0("gray-fog-of-war",CclGrayFogOfWar);
+
     gh_new_procedure1_0("fog-of-war-contrast",CclFogOfWarContrast);
     gh_new_procedure1_0("fog-of-war-brightness",CclFogOfWarBrightness);
     gh_new_procedure1_0("fog-of-war-saturation",CclFogOfWarSaturation);
 
     gh_new_procedure1_0("forest-regeneration",CclForestRegeneration);
-
-    gh_new_procedure4_0("tileset",CclTileset);
 }
 
 #endif	// } defined(USE_CCL) || defined(USE_CCL2)
diff --git a/src/map/script_tileset.cpp b/src/map/script_tileset.cpp
new file mode 100644
index 000000000..aadf03b2e
--- /dev/null
+++ b/src/map/script_tileset.cpp
@@ -0,0 +1,138 @@
+//   ___________		     _________		      _____  __
+//   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
+//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+//    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
+//    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
+//	  \/		    \/	   \/	     \/		   \/
+//  ______________________                           ______________________
+//			  T H E   W A R   B E G I N S
+//	   FreeCraft - A free fantasy real time strategy game engine
+//
+/**@name ccl_tileset.c	-	The tileset ccl functions. */
+//
+//	(c) Copyright 2000 by Lutz Sammer
+//
+//	$Id$
+
+//@{
+
+/*----------------------------------------------------------------------------
+--	Includes
+----------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "freecraft.h"
+
+#if defined(USE_CCL) || defined(USE_CCL2)	// {
+
+#include "ccl.h"
+#include "tileset.h"
+
+/*----------------------------------------------------------------------------
+--	Functions
+----------------------------------------------------------------------------*/
+
+/**
+**	Parse tileset definition.
+**
+**	@param slot	Slot name
+**	@param name	Reference name
+**	@param file	Graphic file
+**	@param table	Conversion table
+*/
+local SCM CclTileset(SCM slot,SCM name,SCM file,SCM table)
+{
+    int type;
+    int i;
+    unsigned short* wp;
+
+    if( !gh_symbol_p(slot) ) {
+	fprintf(stderr,"Illegal tileset slot name\n");
+	return SCM_UNSPECIFIED;
+    }
+    if( slot==gh_symbol2scm("tileset-summer") ) {
+	type=TilesetSummer;
+    } else if( slot==gh_symbol2scm("tileset-winter") ) {
+	type=TilesetWinter;
+    } else if( slot==gh_symbol2scm("tileset-wasteland") ) {
+	type=TilesetWasteland;
+    } else if( slot==gh_symbol2scm("tileset-swamp") ) {
+	type=TilesetSwamp;
+    } else {
+	fprintf(stderr,"Wrong tileset slot name\n");
+	return SCM_UNSPECIFIED;
+    }
+    Tilesets[type].Name=gh_scm2newstr(name,NULL);
+    Tilesets[type].File=gh_scm2newstr(file,NULL);
+
+    // CONVERT TABLE!!
+    if( gh_vector_length(table)!=2528 ) {	// 0x9E0
+	fprintf(stderr,"Wrong conversion table length\n");
+	return SCM_UNSPECIFIED;
+    }
+
+    Tilesets[type].Table=wp=malloc(sizeof(*Tilesets[type].Table)*2528);
+    for( i=0; i<2528; ++i ) {
+	wp[i]=gh_scm2int(gh_vector_ref(table,gh_int2scm(i)));
+    }
+
+    return SCM_UNSPECIFIED;
+}
+
+/**
+**	Define tileset mapping from original number to internal symbol
+**
+*/
+local SCM CclDefineTilesetWcNames(SCM list)
+{
+    int i;
+    char** cp;
+
+    i=gh_length(list);
+    if( (cp=TilesetWcNames) ) {		// Free all old names
+	while( *cp ) {
+	    free(*cp++);
+	}
+	free(TilesetWcNames);
+    }
+
+    //
+    //	Get new table.
+    //
+    TilesetWcNames=cp=malloc((i+1)*sizeof(char*));
+    while( i-- ) {
+	*cp++=gh_scm2newstr(gh_car(list),NULL);
+	list=gh_cdr(list);
+    }
+    *cp=NULL;
+
+    return SCM_UNSPECIFIED;
+}
+
+/**
+**	Define tileset
+**
+*/
+local SCM CclDefineTileset(SCM list)
+{
+    // FIXME: write this
+    return list;
+}
+
+/**
+**	Register CCL features for tileset.
+*/
+global void TilesetCclRegister(void)
+{
+    // FIXME: will be removed
+    gh_new_procedure4_0("tileset",CclTileset);
+
+    gh_new_procedureN("define-tileset-wc-names",CclDefineTilesetWcNames);
+    gh_new_procedureN("define-tileset",CclDefineTileset);
+}
+
+#endif	// } defined(USE_CCL) || defined(USE_CCL2)
+
+//@}
diff --git a/src/map/tileset.cpp b/src/map/tileset.cpp
index 8eedc2194..65f89bc69 100644
--- a/src/map/tileset.cpp
+++ b/src/map/tileset.cpp
@@ -9,14 +9,17 @@
 //	   FreeCraft - A free fantasy real time strategy game engine
 //
 /**@name tileset.c	-	The tileset. */
-/*
-**	(c) Copyright 1998-2000 by Lutz Sammer
-**
-**	$Id$
-*/
+//
+//	(c) Copyright 1998-2000 by Lutz Sammer
+//
+//	$Id$
 
 //@{
 
+/*----------------------------------------------------------------------------
+--	Includes
+----------------------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -26,9 +29,21 @@
 #include "map.h"
 
 /*----------------------------------------------------------------------------
---	Tileset
+--	Variables
 ----------------------------------------------------------------------------*/
 
+extern int WoodTable[16];		/// Table for wood removable.
+extern int RockTable[20];		/// Table for rock removable.
+
+/**
+**	Mapping of wc numbers to our internal symbols.
+**	The numbers are used in puds.
+**	0=summer, 1=winter, 2=wasteland, 3=swamp.
+*/
+global char** TilesetWcNames;
+
+#if 1		//	FIXME: only support ccl version.
+
 /**
 **	Table to convert summer pud tile numbers to internal.
 */
@@ -1317,129 +1332,10 @@ local const unsigned short TileTableWasteland[0x9E0] = {
  0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
 };
 
-
-// FIXME: following tables are almost empty: only forest fields are correct
-// FIXME: JOHNS most things could be computed
-
 /**
-**	Table to get information about the summer tile features.
+**	Count of available Tilesets.
 */
-local unsigned char TileTypeTableSummer[TILE_COUNT] = {
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // FOW tiles
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // walls
-    7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8, // walls
-    8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7, // walls
-    7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8, // walls
-    8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, // walls
-    9,9,9,9,9,9,2,2,2,2,2,2,2,2,2,2, // wood
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2, // forest
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,5, // forest
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // rocks
-    5,5,5,5,5,5,4,5,5,5,5,5,5,5,5,5, // rocks
-    5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, // rocks
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-};
-
-/**
-**	Table to get information about the winter tile features.
-*/
-local unsigned char TileTypeTableWinter[TILE_COUNT] = {
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // FOW tiles
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // walls
-    7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8, // walls
-    8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7, // walls
-    7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8, // walls
-    8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, // walls
-    9,9,9,9,9,9,2,2,2,2,2,2,2,2,2,2, // wood
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2, // forest
-    2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5, // forest
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // rocks
-    5,4,5,5,5,5,5,5,5,5,5,5,5,5,5,0, // rocks
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-};
-
-/**
-**	Table to get information about the wasteland tile features.
-*/
-local unsigned char TileTypeTableWasteland[TILE_COUNT] = {
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // FOW tiles
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // walls
-    7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8, // walls
-    8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7, // walls
-    7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8, // walls
-    8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, // walls
-    9,9,9,9,9,9,2,2,2,2,2,2,2,2,2,2, // wood
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2, // forest
-    2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5, // forest
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // rocks
-    5,5,5,4,5,5,5,5,5,5,5,5,5,5,5,5, // rocks
-    5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-};
-
-/**
-**	Table to get information about the swamp tile features.
-*/
-local unsigned char TileTypeTableSwamp[TILE_COUNT] = {
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // FOW tiles
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // walls
-    7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8, // walls
-    8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7, // walls
-    7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8, // walls
-    8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, // walls
-    9,9,9,9,9,9,2,2,2,2,2,2,2,2,2,2, // wood
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2, // forest
-    2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5, // forest
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, // rocks
-    5,4,5,5,5,5,5,5,5,5,5,5,5,5,5,0, // rocks
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-};
+global int TilesetsCount=4;
 
 /**
 **	Tileset information.
@@ -1448,69 +1344,157 @@ local unsigned char TileTypeTableSwamp[TILE_COUNT] = {
 */
 global Tileset Tilesets[TilesetMax] = {
 {
-    "tileset-summer",
-    "summer",		"graphic/tileset/summer.png"
+    "tileset-summer"
+    ,"summer"
+#ifdef NEW_NAMES
+    ,"graphic/tilesets/summer/terrain/summer.png"
+#else
+    ,"graphic/tileset/summer.png"
+#endif
     ,TileTableSummer
-    ,TileTypeTableSummer
-    ,101, 126
-    ,142, 142+24
+    ,NULL
+    ,NULL
+#if 1
     ,16,52,88
     ,34,70,88
+#endif
+    ,{ 115, 116, 117, 118, 119, 120 }
+    ,121, 122, 123
+    ,126
+    ,{ -1 ,-1 }
+    ,{ 153, 154, 155, 156, 157, 158 }
+    ,161, 162, 163
+    ,166
 },
 {
     "tileset-winter",
     "winter",		"graphic/tileset/winter.png"
     ,TileTableWinter
-    ,TileTypeTableWinter
-    ,101, 126
-    ,137, 137+24
+    ,NULL
+    ,NULL
+#if 1
     ,16,52,88
     ,34,70,88
+#endif
+    ,{ 115, 116, 117, 118, 119, 120 }
+    ,121, 122, 123
+    ,126
+    ,{ -1 ,-1 }
+    ,{ 148, 149, 150, 151, 152, 153 }
+    ,156, 157, 158
+    ,161
 },
 {
     "tileset-wasteland",
     "wasteland",	"graphic/tileset/wasteland.png"
     ,TileTableWasteland
-    ,TileTypeTableWasteland
-    ,101, 126
-    ,139, 139+24
+    ,NULL
+    ,NULL
+#if 1
     ,16,52,88
     ,34,70,88
+#endif
+    ,{ 115, 116, 117, 118, 119, 120 }
+    ,121, 122, 123
+    ,126
+    ,{ -1 ,-1 }
+    ,{ 150, 151, 152, 153, 154, 155 }
+    ,158, 159, 160
+    ,163
 },
 {
     "tileset-swamp",
     "swamp",		"graphic/tileset/swamp.png"
     ,TileTableSwamp
-    ,TileTypeTableSwamp
-    ,101, 126
-    ,136, 136+24
+    ,NULL
+    ,NULL
+#if 1
     ,16,52,88
     ,34,70,88
+#endif
+    ,{ 115, 116, 117, 118, 119, 120 }
+    ,121, 122, 123
+    ,126
+    ,{ -1 ,-1 }
+    ,{ 147, 148, 149, 150, 151, 152 }
+    ,155, 156, 157
+    ,160
 },
 };
 
+#endif
+
+/*----------------------------------------------------------------------------
+--	Functions
+----------------------------------------------------------------------------*/
+
 /**
 **	Load tileset and setup TheMap for this tileset.
+**
+**	@see TheMap, @see Tilesets
 */
 global void LoadTileset(void)
 {
     int i;
     int n;
     int tile;
+    int gap;
+    int tiles_per_row;
     unsigned char* data;
+    const unsigned short* table;
 
-    TheMap.Tileset=&Tilesets[TheMap.Terrain];
+    //TheMap.Tileset=&Tilesets[TheMap.Terrain];
+    //
+    //	Find the tileset.
+    //
+    for( i=0; i<TilesetsCount; ++i ) {
+	if( !strcmp(TilesetWcNames[TheMap.Terrain],Tilesets[i].Ident) ) {
+	    break;
+	}
+    }
+    if( i==TilesetsCount ) {
+	fprintf(stderr,"Tileset `%s' not available\n"
+		,TilesetWcNames[TheMap.Terrain]);
+	exit(-1);
+    }
+    TheMap.Tileset=&Tilesets[i];
+
+    //
+    //	Load and prepare the tileset
+    //
 
     TheMap.TileData=LoadGraphic(TheMap.Tileset->File);
 
     //
     //	Calculate number of tiles in graphic tile
     //
-    TheMap.TileCount=n=(TheMap.TileData->Width*TheMap.TileData->Height)
-	    /(TileSizeX*TileSizeY);
+    if( TheMap.TileData->Width==626 ) {
+	// FIXME: allow 1 pixel gap between the tiles!!
+	gap=1;
+	tiles_per_row=(TheMap.TileData->Width+1)/(TileSizeX+1);
+	TheMap.TileCount=n=tiles_per_row*((TheMap.TileData->Height+1)
+		/(TileSizeY+1));
+    } else if( TheMap.TileData->Width==527 ) {
+	// FIXME: allow 1 pixel gap between the tiles!!
+	gap=1;
+	tiles_per_row=(TheMap.TileData->Width+1)/(TileSizeX+1);
+	TheMap.TileCount=n=tiles_per_row*((TheMap.TileData->Height+1)
+		/(TileSizeY+1));
+    } else {
+	gap=0;
+	tiles_per_row=TheMap.TileData->Width/TileSizeX;
+	TheMap.TileCount=n=tiles_per_row*(TheMap.TileData->Height
+		/TileSizeY);
+    }
+
+    DebugLevel2Fn(" %d Tiles in file %s, pro row %d\n"
+	    ,TheMap.TileCount,TheMap.Tileset->File,tiles_per_row);
+
+    if( n>MaxTilesInTileset ) {
+	fprintf(stderr,"Too many tiles in tileset. Increase MaxTilesInTileset and recompile.\n");
+	exit(-1);
+    }
 
-    DebugLevel3(__FUNCTION__": %d Tiles in file %s\n"
-	    ,TheMap.TileCount,TheMap.Tileset->File);
 
     //
     //	Precalculate the graphic starts of the tiles
@@ -1522,15 +1506,19 @@ global void LoadTileset(void)
     }
 
     //
-    // Convert the graphic data into faster format
+    //	Convert the graphic data into faster format
     //
     for( tile=0; tile<n; ++tile ) {
 	unsigned char* s;
 	unsigned char* d;
 
-	s=((char*)TheMap.TileData->Frames)+((tile%TILE_PER_ROW)*TileSizeX)
-		+((tile/TILE_PER_ROW)*TileSizeY)*TheMap.TileData->Width;
-	d=data+tile*TileSizeX*TileSizeY;
+	s=((char*)TheMap.TileData->Frames)
+		+((tile%tiles_per_row)*(TileSizeX+gap))
+		+((tile/tiles_per_row)*(TileSizeY+gap))*TheMap.TileData->Width;
+	d=TheMap.Tiles[tile];
+	if( d!=data+tile*TileSizeX*TileSizeY ) {
+	    abort();
+	}
 	for( i=0; i<TileSizeY; ++i ) {
 	    memcpy(d,s,TileSizeX*sizeof(unsigned char));
 	    d+=TileSizeX;
@@ -1540,36 +1528,345 @@ global void LoadTileset(void)
 
     free(TheMap.TileData->Frames);	// release old memory
     TheMap.TileData->Frames=data;
-
-    // FIXME:	the complete TileTypeTableXXX can be calculated.
+    TheMap.TileData->Width=TileSizeX;
+    TheMap.TileData->Height=TileSizeY*n;
 
     //
-    //	Mark water tiles, used for color cycling
+    //	Build the TileTypeTable
+    //
+    //	FIXME: types are currently hardcoded, use the supplied flags.
+    //
+
+    table=TheMap.Tileset->Table;
+    TheMap.Tileset->TileTypeTable
+	    =calloc(n,sizeof(*TheMap.Tileset->TileTypeTable));
+
+    //
+    //	Solid tiles
     //
     for( i=0; i<0x10; ++i ) {
-	tile=TheMap.Tileset->Table[0x010+i];	// solid light water
-	if( tile ) {
-	    TheMap.Tileset->TileTypeTable[tile]
-		    =TileTypeWater;
+	if( (tile=table[0x010+i]) ) {		// solid light water
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeWater;
 	}
-	tile=TheMap.Tileset->Table[0x020+i];	// solid dark water
-	if( tile ) {
-	    TheMap.Tileset->TileTypeTable[tile]
-		    =TileTypeWater;
+	if( (tile=table[0x020+i]) ) {		// solid dark water
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeWater;
+	}
+	if( (tile=table[0x030+i]) ) {		// solid light coast
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeCoast;
+	}
+	if( (tile=table[0x040+i]) ) {		// solid dark coast
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeCoast;
+	}
+	if( (tile=table[0x050+i]) ) {		// solid light ground
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeGrass;
+	}
+	if( (tile=table[0x060+i]) ) {		// solid dark ground
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeGrass;
+	}
+	if( (tile=table[0x070+i]) ) {		// solid forest
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeWood;
+	}
+	if( (tile=table[0x080+i]) ) {		// solid rocks
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeRock;
+	}
+
+	if( i<3 && (tile=table[0x090+i]) ) {	// solid human walls
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeHumanWall;
+	}
+	if( i<3 && (tile=table[0x0A0+i]) ) {	// solid orc walls
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeOrcWall;
+	}
+	if( i<3 && (tile=table[0x0B0+i]) ) {	// solid human walls
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeHumanWall;
+	}
+	if( i<3 && (tile=table[0x0C0+i]) ) {	// solid orc walls
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeOrcWall;
+	}
+
+	// 00,D0,E0,F0 Unused
+    }
+
+    //
+    //	Mixed tiles
+    //
+    for( i=0; i<0xE0; ++i ) {
+	if( (tile=table[0x100+i]) ) {		// mixed water
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeWater;
+	}
+	if( (tile=table[0x200+i]) ) {		// mixed water/coast
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeWater;
+	}
+	if( (tile=table[0x300+i]) ) {		// mixed coast
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeCoast;
+	}
+	if( (tile=table[0x400+i]) ) {		// mixed rocks/coast
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeRock;
+	}
+	if( (tile=table[0x500+i]) ) {		// mixed ground/coast
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeCoast;
+	}
+	if( (tile=table[0x600+i]) ) {		// mixed ground
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeGrass;
+	}
+	if( (tile=table[0x700+i]) ) {		// mixed forest/ground
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeWood;
+	}
+	if( (((i&0xF0)==0x40 || (i&0xF0)==0x90) && (i&0xF)<5)
+		|| (i&0xF)<3 ) { 
+	    if( (tile=table[0x800+i]) ) {	// mixed human wall
+		TheMap.Tileset->TileTypeTable[tile]=TileTypeHumanWall;
+	    }
+	    if( (tile=table[0x900+i]) ) {	// mixed orc wall
+		TheMap.Tileset->TileTypeTable[tile]=TileTypeOrcWall;
+	    }
 	}
     }
-    for( i=0; i<0x100; ++i ) {
-	tile=TheMap.Tileset->Table[0x100+i];	// mixed water
-	if( tile ) {
-	    TheMap.Tileset->TileTypeTable[tile]
-		    =TileTypeWater;
+
+    //
+    //	mark the special tiles
+    //
+    for( i=0; i<6; ++i ) {
+	if( (tile=TheMap.Tileset->ExtraTrees[i]) ) {
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeWood;
 	}
-	tile=TheMap.Tileset->Table[0x200+i];	// mixed water/coast
-	if( tile ) {
-	    TheMap.Tileset->TileTypeTable[tile]
-		    =TileTypeWater;
+	if( (tile=TheMap.Tileset->ExtraRocks[i]) ) {
+	    TheMap.Tileset->TileTypeTable[tile]=TileTypeRock;
 	}
     }
+    if( (tile=TheMap.Tileset->TopOneTree) ) {
+	TheMap.Tileset->TileTypeTable[tile]=TileTypeWood;
+    }
+    if( (tile=TheMap.Tileset->MidOneTree) ) {
+	TheMap.Tileset->TileTypeTable[tile]=TileTypeWood;
+    }
+    if( (tile=TheMap.Tileset->BotOneTree) ) {
+	TheMap.Tileset->TileTypeTable[tile]=TileTypeWood;
+    }
+    if( (tile=TheMap.Tileset->TopOneRock) ) {
+	TheMap.Tileset->TileTypeTable[tile]=TileTypeRock;
+    }
+    if( (tile=TheMap.Tileset->MidOneRock) ) {
+	TheMap.Tileset->TileTypeTable[tile]=TileTypeRock;
+    }
+    if( (tile=TheMap.Tileset->BotOneRock) ) {
+	TheMap.Tileset->TileTypeTable[tile]=TileTypeRock;
+    }
+
+#if 0
+    for( i=0; i<TheMap.TileCount; ++i ) {
+	printf("%d,",TheMap.Tileset->TileTypeTable[i]);
+	if( (i&0x0F)==0xF ) {
+	    printf("\n");
+	}
+    }
+#endif
+
+    //
+    //	Build wood removement table.
+    //
+    WoodTable[ 0]= -1;
+    WoodTable[ 1]= TheMap.Tileset->BotOneTree;
+    WoodTable[ 2]= -1;
+    WoodTable[ 3]= table[0x710];
+    WoodTable[ 4]= TheMap.Tileset->TopOneTree;
+    WoodTable[ 5]= TheMap.Tileset->MidOneTree;
+    WoodTable[ 6]= table[0x770];
+    WoodTable[ 7]= table[0x790];
+    WoodTable[ 8]= -1;
+    WoodTable[ 9]= table[0x700];
+    WoodTable[10]= -1;
+    WoodTable[11]= table[0x720];
+    WoodTable[12]= table[0x730];
+    WoodTable[13]= table[0x740];
+    WoodTable[14]= table[0x7B0];
+    WoodTable[15]= table[0x7D0];
+
+    //
+    //	Build rock removement table.
+    //
+    RockTable[ 0]= -1;
+    RockTable[ 1]= TheMap.Tileset->BotOneRock;
+    RockTable[ 2]= -1;
+    RockTable[ 3]= table[0x410];
+    RockTable[ 4]= TheMap.Tileset->TopOneRock;
+    RockTable[ 5]= TheMap.Tileset->MidOneRock;
+    RockTable[ 6]= table[0x470];
+    RockTable[ 7]= table[0x490];
+    RockTable[ 8]= -1;
+    RockTable[ 9]= table[0x400];
+    RockTable[10]= -1;
+    RockTable[11]= table[0x420];
+    RockTable[12]= table[0x430];
+    RockTable[13]= table[0x440];
+    RockTable[14]= table[0x4B0];
+    RockTable[15]= table[0x080];
+
+    RockTable[16]= table[0x4C0];
+    RockTable[17]= table[0x460];
+    RockTable[18]= table[0x4A0];
+    RockTable[19]= table[0x4D0];
+}
+
+/**
+**	Save solid part of tileset.
+*/
+local void SaveTilesetSolid(FILE* file,const unsigned short* table
+	,const char* name,const char* flag,int start)
+{
+    int i;
+    int j;
+    int n;
+
+    fprintf(file,"  ( 'solid \"%s\" %s\n    #(",name,flag);
+    for( n=15; n>=0 && !table[start+n] ; n-- ) {
+    }
+    i=6;
+    for( j=0; j<=n; ++j ) {
+	i+=fprintf(file," %3d",table[start+j]);
+    }
+    i+=fprintf(file,"))");
+
+    while( (i+=8)<80 ) {
+	fprintf(file,"\t");
+    }
+    fprintf(file,"; %03X\n",start);
+}
+
+/**
+**	Save mixed part of tileset.
+*/
+local void SaveTilesetMixed(FILE* file,const unsigned short* table
+	,const char* name1,const char* name2,const char* flag,int start)
+{
+    int x;
+    int i;
+    int j;
+    int n;
+
+    if( start>=0x9E0 ) {
+	return;
+    }
+    fprintf(file,"  ( 'mixed \"%s\" \"%s\" %s\n",name1,name2,flag);
+    for( x=0; x<0x100; x+=0x10 ) {
+	if( start+x>=0x9E0 ) {
+	    break;
+	}
+	fprintf(file,"    #(");
+	for( n=15; n>=0 && !table[start+x+n] ; n-- ) {
+	}
+	i=6;
+	for( j=0; j<=n; ++j ) {
+	    i+=fprintf(file," %3d",table[start+x+j]);
+	}
+	if( x==0xF0 || (start==0x900 && x==0xD0)) {
+	    i+=fprintf(file,"))");
+	} else {
+	    i+=fprintf(file,")");
+	}
+
+	while( (i+=8)<80 ) {
+	    fprintf(file,"\t");
+	}
+	fprintf(file,"; %03X\n",start+x);
+    }
+}
+
+/**
+**	Save the current tileset.
+**
+**	@param file	Output file.
+*/
+global void SaveTileset(FILE* file)
+{
+    const unsigned short* table;
+    const Tileset* tileset;
+    int i;
+
+    tileset=TheMap.Tileset;
+    fprintf(file,"\n;;; -----------------------------------------\n");
+    fprintf(file,";;; MODULE: tileset $Id$\n");
+
+    fprintf(file,"(define-tileset\n  '%s",tileset->Ident);
+    i=strlen(tileset->Ident);
+    if( i<5 ) {
+	fputc('\t',file);
+    }
+    if( i<13 ) {
+	fputc('\t',file);
+    }
+    fprintf(file,"\t\"%s\"",tileset->Name);
+    i=strlen(tileset->Name);
+    if( i<7 ) {
+	fputc('\t',file);
+    }
+    fprintf(file,"\t\"%s\"\n",tileset->File);
+    fprintf(file,"  ;; Slots\n  '(( 'special\t\t;; Can't be in pud\n");
+    fprintf(file,"    'extra-trees #( %d %d %d %d %d %d )\n"
+	,tileset->ExtraTrees[0] ,tileset->ExtraTrees[1]
+	,tileset->ExtraTrees[2] ,tileset->ExtraTrees[3]
+	,tileset->ExtraTrees[4] ,tileset->ExtraTrees[5]);
+    fprintf(file,"    'top-one-tree %d 'mid-one-tree %d 'bot-one-tree %d\n"
+	,tileset->TopOneTree ,tileset->MidOneTree ,tileset->BotOneTree);
+    fprintf(file,"    'removed-tree %d\n",tileset->RemovedTree);
+    fprintf(file,"    'growing-tree #( %d %d )\n"
+	,tileset->GrowingTree[0] ,tileset->GrowingTree[1]);
+    fprintf(file,"    'extra-rocks #( %d %d %d %d %d %d )\n"
+	,tileset->ExtraRocks[0] ,tileset->ExtraRocks[1]
+	,tileset->ExtraRocks[2] ,tileset->ExtraRocks[3]
+	,tileset->ExtraRocks[4] ,tileset->ExtraRocks[5]);
+    fprintf(file,"    'top-one-rock %d 'mid-one-rock %d 'bot-one-rock %d\n"
+	,tileset->TopOneRock ,tileset->MidOneRock ,tileset->BotOneRock);
+    fprintf(file,"    'removed-rock %d )\n",tileset->RemovedRock);
+
+    table=TheMap.Tileset->Table;
+    //
+    //	Solids
+    //
+    SaveTilesetSolid(file,table,"unused",		"",		0x00);
+    SaveTilesetSolid(file,table,"light-water",		"'water",	0x10);
+    SaveTilesetSolid(file,table,"dark-water",		"'water",	0x20);
+    SaveTilesetSolid(file,table,"light-coast",		"'no-building",	0x30);
+    SaveTilesetSolid(file,table,"dark-coast",		"'no-building",	0x40);
+    SaveTilesetSolid(file,table,"light-grass",		"",		0x50);
+    SaveTilesetSolid(file,table,"dark-grass",		"",		0x60);
+    SaveTilesetSolid(file,table,"forest",		"'forest",	0x70);
+    SaveTilesetSolid(file,table,"rocks",		"'rock",	0x80);
+    SaveTilesetSolid(file,table,"human-closed-wall",	"'wall",	0x90);
+    SaveTilesetSolid(file,table,"orc-closed-wall",	"'wall",	0xA0);
+    SaveTilesetSolid(file,table,"human-open-wall",	"'wall",	0xB0);
+    SaveTilesetSolid(file,table,"orc-open-wall",	"'wall",	0xC0);
+    SaveTilesetSolid(file,table,"unused",		"",		0xD0);
+    SaveTilesetSolid(file,table,"unused",		"",		0xE0);
+    SaveTilesetSolid(file,table,"unused",		"",		0xF0);
+
+    //
+    //	Mixeds
+    //
+    SaveTilesetMixed(file,table,"dark-water","light-water","'water",	0x100);
+    SaveTilesetMixed(file,table,"light-water","light-coast","'coast",	0x200);
+    SaveTilesetMixed(file,table,"dark-coast","light-coast","'no-building",0x300);
+    SaveTilesetMixed(file,table,"rocks","light-coast","'rock",		0x400);
+    SaveTilesetMixed(file,table,"light-coast","light-ground","'no-building",0x500);
+    SaveTilesetMixed(file,table,"dark-ground","light-ground","",	0x600);
+    SaveTilesetMixed(file,table,"forest","light-ground","'forest",	0x700);
+    SaveTilesetMixed(file,table,"human-wall","dark-ground","'wall",	0x800);
+    SaveTilesetMixed(file,table,"orc-wall","dark-ground","'wall",	0x900);
+    fprintf(file,"  )\n");
+    fprintf(file,"  ;; Animated tiles\n");
+    fprintf(file,"  '( #( ) ))\n");
+}
+
+/**
+**	Cleanup the tileset module.
+**
+**	NOTE: this didn't frees the configuration memory.
+*/
+global void CleanTileset(void)
+{
+    VideoFree(TheMap.TileData);
+    IfDebug( TheMap.TileData=NULL; );
+    free(TheMap.Tiles);
+    IfDebug( TheMap.Tiles=NULL; );
 }
 
 //@}
diff --git a/src/stratagus/script.cpp b/src/stratagus/script.cpp
index b8e8686a5..842cc7f65 100644
--- a/src/stratagus/script.cpp
+++ b/src/stratagus/script.cpp
@@ -734,7 +734,7 @@ local SCM CclFreeCraftMap(SCM list)
 		}
 		for( i=0; i<l; ++i ) {
 		    TheMap.Fields[i].Tile=
-			    Tilesets[TilesetSummer].Table[
+			    Tilesets[0].Table[
 				gh_scm2int(gh_vector_ref(value,gh_int2scm(i)))
 			    ];
 		}
@@ -859,6 +859,7 @@ local void gh_main_prog(int argc,char* argv[])
 
     gh_new_procedureN("missile-type",CclMissileType);
 
+    TilesetCclRegister();
     MapCclRegister();
     PathfinderCclRegister();
     UnitButtonCclRegister();
@@ -979,6 +980,7 @@ global void CclInit(void)
 
     init_lsubr("missile-type",CclMissileType);
 
+    TilesetCclRegister();
     MapCclRegister();
     PathfinderCclRegister();
     UnitButtonCclRegister();