/************************************************************************/
/* File Name: isomap.c */
/* Creator: ax.minaduki@gmail.com */
/* Create Time: April 11st, 2010 */
/* Module: Lawine library */
/* Descript: Isometric map API implementation */
/************************************************************************/
/************************************************************************/
/* File Name : isomap.h */
/* Creator : ax.minaduki@gmail.com */
/* Create Time : April 11st, 2010 */
/* Module : Lawine library */
/* Descript : Isometric map API definition */
/************************************************************************/
//////////////////////////////////////// START of #include "isomap.h" ////////////////////////////////////////
/************************************************************************/
#include <common.h>
//////////////////////////////////////// START of #include <lawinedef.h> ////////////////////////////////////////
#define L_ERA_ERROR -1
#define L_ERA_BADLANDS 0
#define L_ERA_PLATFORM 1
#define L_ERA_INSTALL 2
#define L_ERA_ASHWORLD 3
#define L_ERA_JUNGLE 4
#define L_ERA_DESERT 5
#define L_ERA_ICE 6
#define L_ERA_TWILIGHT 7
#define L_ERA_NUM 8
#define L_TILE_SIZE 32
#define L_SPK_WIDTH 640
#define L_SPK_HEIGHT 480
enum {
L_BRUSH_BADLANDS_DIRT,
L_BRUSH_BADLANDS_MUD,
L_BRUSH_BADLANDS_HIGH_DIRT,
L_BRUSH_BADLANDS_WATER,
L_BRUSH_BADLANDS_GRASS,
L_BRUSH_BADLANDS_HIGH_GRASS,
L_BRUSH_BADLANDS_STRUCTURE,
L_BRUSH_BADLANDS_ASPHALT,
L_BRUSH_BADLANDS_ROCKY_GROUND,
L_BRUSH_BADLANDS_NUM,
};
enum {
L_BRUSH_PLATFORM_SPACE,
L_BRUSH_PLATFORM_LOW_PLATFORM,
L_BRUSH_PLATFORM_RUSTY_PIT,
L_BRUSH_PLATFORM_PLATFORM,
L_BRUSH_PLATFORM_DARK_PLATFORM,
L_BRUSH_PLATFORM_PLATING,
L_BRUSH_PLATFORM_SOLAR_ARRAY,
L_BRUSH_PLATFORM_HIGH_PLATFORM,
L_BRUSH_PLATFORM_HIGH_PLATING,
L_BRUSH_PLATFORM_ELEVATED_CATWALK,
L_BRUSH_PLATFORM_NUM,
};
enum {
L_BRUSH_INSTALL_SUBSTRUCTURE,
L_BRUSH_INSTALL_FLOOR,
L_BRUSH_INSTALL_ROOF,
L_BRUSH_INSTALL_SUBSTRUCTURE_PLATING,
L_BRUSH_INSTALL_PLATING,
L_BRUSH_INSTALL_SUBSTRUCTURE_PANELS,
L_BRUSH_INSTALL_BOTTOMLESS_PIT,
L_BRUSH_INSTALL_NUM,
};
enum {
L_BRUSH_ASHWORLD_MAGMA,
L_BRUSH_ASHWORLD_DIRT,
L_BRUSH_ASHWORLD_LAVA,
L_BRUSH_ASHWORLD_SHALE,
L_BRUSH_ASHWORLD_BROKEN_ROCK,
L_BRUSH_ASHWORLD_HIGH_DIRT,
L_BRUSH_ASHWORLD_HIGH_LAVA,
L_BRUSH_ASHWORLD_HIGH_SHALE,
L_BRUSH_ASHWORLD_NUM,
};
enum {
L_BRUSH_JUNGLE_WATER,
L_BRUSH_JUNGLE_DIRT,
L_BRUSH_JUNGLE_MUD,
L_BRUSH_JUNGLE_JUNGLE,
L_BRUSH_JUNGLE_ROCKY_GROUND,
L_BRUSH_JUNGLE_RUINS,
L_BRUSH_JUNGLE_RAISED_JUNGLE,
L_BRUSH_JUNGLE_TEMPLE,
L_BRUSH_JUNGLE_HIGH_DIRT,
L_BRUSH_JUNGLE_HIGH_JUNGLE,
L_BRUSH_JUNGLE_HIGH_RUINS,
L_BRUSH_JUNGLE_HIGH_RAISED_JUNGLE,
L_BRUSH_JUNGLE_HIGH_TEMPLE,
L_BRUSH_JUNGLE_NUM,
};
enum {
L_BRUSH_DESERT_TAR,
L_BRUSH_DESERT_DIRT,
L_BRUSH_DESERT_DRIED_MUD,
L_BRUSH_DESERT_SAND_DUNES,
L_BRUSH_DESERT_ROCKY_GROUND,
L_BRUSH_DESERT_CRAGS,
L_BRUSH_DESERT_SANDY_SUNKEN_PIT,
L_BRUSH_DESERT_COMPOUND,
L_BRUSH_DESERT_HIGH_DIRT,
L_BRUSH_DESERT_HIGH_SAND_DUNES,
L_BRUSH_DESERT_HIGH_CRAGS,
L_BRUSH_DESERT_HIGH_SANDY_SUNKEN_PIT,
L_BRUSH_DESERT_HIGH_COMPOUND,
L_BRUSH_DESERT_NUM,
};
enum {
L_BRUSH_ICE_ICE,
L_BRUSH_ICE_SNOW,
L_BRUSH_ICE_MOGULS,
L_BRUSH_ICE_DIRT,
L_BRUSH_ICE_ROCKY_SNOW,
L_BRUSH_ICE_GRASS,
L_BRUSH_ICE_WATER,
L_BRUSH_ICE_OUTPOST,
L_BRUSH_ICE_HIGH_SNOW,
L_BRUSH_ICE_HIGH_DIRT,
L_BRUSH_ICE_HIGH_GRASS,
L_BRUSH_ICE_HIGH_WATER,
L_BRUSH_ICE_HIGH_OUTPOST,
L_BRUSH_ICE_NUM,
};
enum {
L_BRUSH_TWLIGHT_WATER,
L_BRUSH_TWLIGHT_DIRT,
L_BRUSH_TWLIGHT_MUD,
L_BRUSH_TWLIGHT_CRUSHED_ROCK,
L_BRUSH_TWLIGHT_CREVICES,
L_BRUSH_TWLIGHT_FLAGSTONES,
L_BRUSH_TWLIGHT_SUNKEN_GROUND,
L_BRUSH_TWLIGHT_BASILICA,
L_BRUSH_TWLIGHT_HIGH_DIRT,
L_BRUSH_TWLIGHT_HIGH_CRUSHED_ROCK,
L_BRUSH_TWLIGHT_HIGH_FLAGSTONES,
L_BRUSH_TWLIGHT_HIGH_SUNKEN_GROUND,
L_BRUSH_TWLIGHT_HIGH_BASILICA,
L_BRUSH_TWLIGHT_NUM,
};
typedef struct {
WORD mega_index:4;
WORD group_no:12;
} LTILEIDX;
typedef struct {
WORD pos:4;
WORD isom:8;
WORD unused:4;
} LISOMCOORD;
typedef struct {
LISOMCOORD left;
LISOMCOORD top;
LISOMCOORD right;
LISOMCOORD bottom;
} LISOMTILE;
typedef LTILEIDX *LTILEPTR;
typedef CONST LTILEIDX *LTILECPTR;
typedef LISOMTILE *LISOMPTR;
typedef CONST LISOMTILE *LISOMCPTR;
/************************************************************************/
//////////////////////////////////////// END of #include <lawinedef.h> ////////////////////////////////////////
/************************************************************************/
#define CALC_ISOM_LINE(y) ((y) + 1)
#define CALC_ISOM_ROW(x) ((x) / 2 + 1)
/************************************************************************/
typedef struct {
INT era; /* ERA */
INT def; /* 默认地形 */
SIZE size; /* 地图大小 */
LISOMPTR isom; /* ISOM数据 */
LTILEPTR tile; /* TILE数据 */
VPTR dirty; /* 脏标志位图 */
} ISOM_MAP;
typedef struct {
WORD type; /* TILE类型 */
WORD left_abut; /* TILE左侧邻接关系ID */
WORD top_abut; /* TILE上方邻接关系ID */
WORD right_abut; /* TILE右侧邻接关系ID */
WORD bottom_abut; /* TILE下方邻接关系ID */
WORD up_abut; /* TILE上层邻接关系ID */
WORD down_abut; /* TILE下层邻接关系ID */
} ISOM_TILE;
typedef struct {
WORD group_no; /* TILE编组序号 */
WORD mega_mask; /* MegaTile存在性掩码 */
ISOM_TILE tile; /* TILE索引 */
} ISOM_DICT;
/************************************************************************/
CAPI extern BOOL init_iso_map(VOID);
CAPI extern VOID exit_iso_map(VOID);
CAPI extern BOOL init_iso_era(INT era, CONST ISOM_DICT *tile_dict, UINT tile_num);
CAPI extern VOID exit_iso_era(INT era);
CAPI extern BOOL create_iso_map(ISOM_MAP *map, BOOL new_map);
CAPI extern VOID destroy_iso_map(ISOM_MAP *map);
CAPI extern BOOL brush_iso_map(ISOM_MAP *map, INT brush, CONST POINT *tile_pos);
CAPI extern BOOL update_iso_map(CONST ISOM_MAP *map);
/************************************************************************/
//////////////////////////////////////// END of #include "isomap.h" ////////////////////////////////////////
/************************************************************************/
/* Vertically adjacent ID constant */
#define V_ABUT_NONE 0 /* No */
#define V_ABUT_CENTER 1 /* Central */
#define V_ABUT_LEFT 2 /* Left margin */
#define V_ABUT_RIGHT 3 /* Right boundary */
#define SHAPE_NUM 14 /* The number of edge shape */
#define CLIFF_NUM 4 /* Each level of the adjacent cliff terrain corresponding ID number */
#define MAX_CENTER 13 /* Central terrain largest number of species (Jungle / Desert / Ice / Twilight) */
#define MAX_EDGE 12 /* The maximum number of terrain types (Jungle / Desert / Ice / Twilight) edge */
#define MAX_LINK 6 /* Maximum number of single-direction (Platform: Platform) connection */
#define MAX_SHAPE_ID 16 /* Edge shape index max + 1 */
#define MAX_CENTER_ISOM 0x0f /* The maximum value of the central ISOM terrain (Platform: Dark Platform) + 1 */
#define CENTER_FLAG 0x00 /* 0x0 # represents a direct use of low-level terrain TILE border ID */
#define DIFFUSE_FLAG 0x10 /* 0x1 # indicates if the diffusion terrain, using high-level terrain TILE boundary ID, otherwise use the appropriate value SIDE_MASK */
#define CLIFF_FLAG 0x20 /* 0x2 # indicates if the cliff terrain, cliff TILE using the corresponding boundary ID, otherwise the lower terrain TILE border ID */
#define SIDE_FLAG 0x30 /* 0x3 # represents a direct use of the constant (it actually represents the eight edge direction) */
#define MAP_FLAG_MASK 0xf0
/************************************************************************/
#define for_each_from(from) for ((from) = 0; (from) < FROM_NUM; (from)++)
#define REVERSE(order) (!(order))
#define OPPOSITE(from) (((from) + FROM_NUM / 2) % FROM_NUM)
#define SIDE_OF_FROM(from) ((((from) + 1) % FROM_NUM) / (FROM_NUM / 2))
#define DIR1_OF_FROM(from) (from)
#define DIR2_OF_FROM(from) (((from) + 1) % FROM_NUM)
#define X_DIR_OF_FROM(from) ((((from) + 1) % FROM_NUM) / (FROM_NUM / 2) * (FROM_NUM / 2))
#define Y_DIR_OF_FROM(from) ((from) / (FROM_NUM / 2) * (FROM_NUM / 2) + 1)
#define IS_FROM_DIR(from, dir) ((from) == (dir) || ((from) + 1) % FROM_NUM == (dir))
#define MAKE_SHAPE_ID(l, t, r, b) (((l) << LEFT) | ((t) << TOP) | ((r) << RIGHT) | ((b) << BOTTOM))
#define LOC_MAP_POS(data, pos, size) ((data) + (pos)->x + (pos)->y * CALC_ISOM_ROW((size)->cx))
#define CALC_DIRTY_SIZE(size) ((CALC_ISOM_ROW((size)->cx) * CALC_ISOM_LINE((size)->cy)) >> 3)
#define SET_DIRTY(dirty, pos, size) (*((BUFPTR)(dirty) + (((pos)->x + (pos)->y * CALC_ISOM_ROW((size)->cx)) >> 3)) |= (1 << ((pos)->x & 0x07)))
#define GET_DIRTY(dirty, pos, size) (*((BUFPTR)(dirty) + (((pos)->x + (pos)->y * CALC_ISOM_ROW((size)->cx)) >> 3)) & (1 << ((pos)->x & 0x07)))
// TODO:
#define M_CENTER CENTER_FLAG
#define M_DIFFUSE(n) (DIFFUSE_FLAG | (n))
#define M_CLIFF(n) (CLIFF_FLAG | (n))
#define M_SIDE(n) (SIDE_FLAG | (n))
/************************************************************************/
/* lL tL rH bH */
#define LLHH_PARAM { \
{ LOW, LOW, HIGH, HIGH }, /* order */ \
{ AS_LOW, AS_EDGE, AS_EDGE, AS_EDGE }, /* type */ \
{ M_CENTER, M_CENTER, M_SIDE(3), M_SIDE(3) }, /* x_abut */ \
{ M_CENTER, M_SIDE(3) }, /* y_abut */ \
}
/* lH tL rL bH */
#define HLLH_PARAM { \
{ HIGH, LOW, LOW, HIGH }, /* order */ \
{ AS_EDGE, AS_LOW, AS_EDGE, AS_EDGE }, /* type */ \
{ M_CENTER, M_CENTER, M_SIDE(1), M_SIDE(1) }, /* x_abut */ \
{ M_SIDE(1), M_CENTER }, /* y_abut */ \
}
/* lH tH rL bL */
#define HHLL_PARAM { \
{ HIGH, HIGH, LOW, LOW }, /* order */ \
{ AS_EDGE, AS_EDGE, M_CLIFF(AS_LOW), AS_EDGE }, /* type */ \
{ M_SIDE(4), M_SIDE(4), M_CLIFF(0), M_CLIFF(0) }, /* x_abut */ \
{ M_SIDE(4), M_CLIFF(0) }, /* y_abut */ \
}
/* lL tH rH bL */
#define LHHL_PARAM { \
{ LOW, HIGH, HIGH, LOW }, /* order */ \
{ AS_EDGE, AS_EDGE, AS_EDGE, M_CLIFF(AS_LOW) }, /* type */ \
{ M_SIDE(2), M_SIDE(2), M_CLIFF(1), M_CLIFF(1) }, /* x_abut */ \
{ M_CLIFF(1), M_SIDE(2) }, /* y_abut */ \
}
/* lL tL rL bH */
#define LLLH_PARAM { \
{ LOW, LOW, LOW, HIGH }, /* order */ \
{ AS_LOW, AS_LOW, AS_EDGE, AS_EDGE }, /* type */ \
{ M_CENTER, M_CENTER, M_SIDE(1), M_SIDE(3) }, /* x_abut */ \
{ M_CENTER, M_CENTER }, /* y_abut */ \
}
/* lH tL rL bL */
#define HLLL_PARAM { \
{ HIGH, LOW, LOW, LOW }, /* order */ \
{ AS_EDGE, AS_LOW, AS_LOW, AS_EDGE }, /* type */ \
{ M_CENTER, M_CENTER, M_CENTER, M_CLIFF(3) }, /* x_abut */ \
{ M_SIDE(6), M_CENTER }, /* y_abut */ \
}
/* lL tH rL bL */
#define LHLL_PARAM { \
{ LOW, HIGH, LOW, LOW }, /* order */ \
{ AS_EDGE, AS_EDGE, M_CLIFF(AS_LOW), M_CLIFF(AS_LOW) }, /* type */ \
{ M_SIDE(2), M_SIDE(4), M_CLIFF(0), M_CLIFF(1) }, /* x_abut */ \
{ M_CLIFF(1), M_CLIFF(0) }, /* y_abut */ \
}
/* lL tL rH bL */
#define LLHL_PARAM { \
{ LOW, LOW, HIGH, LOW }, /* order */ \
{ AS_LOW, AS_EDGE, AS_EDGE, AS_LOW }, /* type */ \
{ M_CENTER, M_CENTER, M_CLIFF(2), M_CENTER }, /* x_abut */ \
{ M_CENTER, M_SIDE(5) }, /* y_abut */ \
}
/* lL tH rH bH */
#define LHHH_PARAM { \
{ LOW, HIGH, HIGH, HIGH }, /* order */ \
{ AS_EDGE, M_DIFFUSE(AS_HIGH), M_DIFFUSE(AS_HIGH), AS_EDGE }, /* type */ \
{ M_SIDE(2), M_DIFFUSE(8), M_DIFFUSE(8), M_SIDE(3) }, /* x_abut */ \
{ M_CLIFF(1), M_DIFFUSE(8) }, /* y_abut */ \
}
/* lH tH rL bH */
#define HHLH_PARAM { \
{ HIGH, HIGH, LOW, HIGH }, /* order */ \
{ M_DIFFUSE(AS_HIGH), AS_EDGE, AS_EDGE, M_DIFFUSE(AS_HIGH) }, /* type */ \
{ M_DIFFUSE(7), M_SIDE(4), M_SIDE(1), M_DIFFUSE(7) }, /* x_abut */ \
{ M_DIFFUSE(7), M_CLIFF(0) }, /* y_abut */ \
}
/* lH tL rH bH */
#define HLHH_PARAM { \
{ HIGH, LOW, HIGH, HIGH }, /* order */ \
{ AS_EDGE, AS_EDGE, AS_EDGE, AS_EDGE }, /* type */ \
{ M_CENTER, M_CENTER, M_SIDE(3), M_SIDE(1) }, /* x_abut */ \
{ M_SIDE(1), M_SIDE(3) }, /* y_abut */ \
}
/* lH tH rH bL */
#define HHHL_PARAM { \
{ HIGH, HIGH, HIGH, LOW }, /* order */ \
{ AS_EDGE, AS_EDGE, AS_EDGE, AS_EDGE }, /* type */ \
{ M_SIDE(4), M_SIDE(2), M_CLIFF(1), M_CLIFF(0) }, /* x_abut */ \
{ M_SIDE(4), M_SIDE(2) }, /* y_abut */ \
}
/* lL tH rL bH */
#define LHLH_PARAM { \
{ LOW, HIGH, LOW, HIGH }, /* order */ \
{ AS_EDGE, AS_EDGE, AS_EDGE, AS_EDGE }, /* type */ \
{ M_SIDE(2), M_SIDE(4), M_SIDE(1), M_SIDE(3) }, /* x_abut */ \
{ M_CLIFF(1), M_CLIFF(0) }, /* y_abut */ \
}
/* lH tL rH bL */
#define HLHL_PARAM { \
{ HIGH, LOW, HIGH, LOW }, /* order */ \
{ AS_EDGE, AS_EDGE, AS_EDGE, AS_EDGE }, /* type */ \
{ M_CENTER, M_CENTER, M_CLIFF(2), M_CLIFF(3) }, /* x_abut */ \
{ M_SIDE(6), M_SIDE(5) }, /* y_abut */ \
}
/* L_ERA_BADLANDS */
#define BADLANDS_PARAM { \
0x0d, /* edge_start */ \
{ /* center */ \
{ 0x01, 0x02, 0x01, S_NONE }, /* 0: dirt L_BRUSH_BADLANDS_DIRT */ \
{ 0x09, 0x04, 0x0f, S_NONE }, /* 1: mud L_BRUSH_BADLANDS_MUD */ \
{ 0x02, 0x03, 0x04, S_NONE }, /* 2: high-dirt L_BRUSH_BADLANDS_HIGH_DIRT */ \
{ 0x03, 0x05, 0x05, S_NONE }, /* 3: water L_BRUSH_BADLANDS_WATER */ \
{ 0x04, 0x06, 0x02, S_NONE }, /* 4: grass L_BRUSH_BADLANDS_GRASS */ \
{ 0x07, 0x07, 0x03, S_NONE }, /* 5: high-grass L_BRUSH_BADLANDS_HIGH_GRASS */ \
{ 0x08, 0x12, 0x0e, S_MATTED }, /* 6: structure L_BRUSH_BADLANDS_STRUCTURE */ \
{ 0x05, 0x0e, 0x0a, S_TILE }, /* 7: asphalt L_BRUSH_BADLANDS_ASPHALT */ \
{ 0x06, 0x0f, 0x0b, S_DIFFUSE }, /* 8: rocky-ground L_BRUSH_BADLANDS_ROCKY_GROUND */ \
}, \
{ /* edge */ \
{ 0x01, 0x02, FALSE, 0x22, { 0x1e, 0x1f, 0x20, 0x21 } }, /* 0: 0D-1A dirt / high-dirt */ \
{ 0x03, 0x01, FALSE, 0x23, { 0x22, 0x23, 0x24, 0x25 } }, /* 1: 1B-28 water / dirt */ \
{ 0x01, 0x04, FALSE, 0x14, { 0x00, 0x00, 0x00, 0x00 } }, /* 2: 29-36 dirt / grass */ \
{ 0x01, 0x06, FALSE, 0x1c, { 0x00, 0x00, 0x00, 0x00 } }, /* 3: 37-44 dirt / rocky-ground */ \
{ 0x02, 0x07, FALSE, 0x15, { 0x00, 0x00, 0x00, 0x00 } }, /* 4: 45-52 high-dirt / high-grass */ \
{ 0x01, 0x05, FALSE, 0x1b, { 0x00, 0x00, 0x00, 0x00 } }, /* 5: 53-60 dirt / asphalt */ \
{ 0x05, 0x08, FALSE, 0x1f, { 0x1a, 0x1b, 0x1c, 0x1d } }, /* 6: 61-6E asphalt / structure */ \
{ 0x01, 0x09, FALSE, 0x16, { 0x00, 0x00, 0x00, 0x00 } }, /* 7: 6F-7C dirt / mud */ \
}, \
}
/* L_ERA_PLATFORM */
#define PLATFORM_PARAM { \
0x18, /* edge_start */ \
{ /* center */ \
{ 0x01, 0x02, 0x01, S_NONE }, /* 0: space L_BRUSH_PLATFORM_SPACE */ \
{ 0x09, 0x08, 0x0d, S_MATTED }, /* 1: low-platform L_BRUSH_PLATFORM_LOW_PLATFORM */ \
{ 0x0a, 0x09, 0x12, S_MATTED }, /* 2: rusty-pit L_BRUSH_PLATFORM_RUSTY_PIT */ \
{ 0x02, 0x03, 0x02, S_NONE }, /* 3: platform L_BRUSH_PLATFORM_PLATFORM */ \
{ 0x0e, 0x0b, 0x07, S_TILE }, /* 4: dark-platform L_BRUSH_PLATFORM_DARK_PLATFORM */ \
{ 0x0b, 0x04, 0x03, S_TILE }, /* 5: plating L_BRUSH_PLATFORM_PLATING */ \
{ 0x08, 0x07, 0x06, S_TILE }, /* 6: solar-array L_BRUSH_PLATFORM_SOLAR_ARRAY */ \
{ 0x04, 0x05, 0x04, S_NONE }, /* 7: high-platform L_BRUSH_PLATFORM_HIGH_PLATFORM */ \
{ 0x0c, 0x06, 0x05, S_TILE }, /* 8: high-plating L_BRUSH_PLATFORM_HIGH_PLATING */ \
{ 0x0d, 0x0a, 0x08, S_MATTED }, /* 9: elevated-catwalk L_BRUSH_PLATFORM_ELEVATED_CATWALK */ \
}, \
{ /* edge */ \
{ 0x01, 0x02, FALSE, 0x14, { 0x17, 0x18, 0x19, 0x1a } }, /* 0: 18-25 space / platform */ \
{ 0x02, 0x04, FALSE, 0x15, { 0x1b, 0x1c, 0x1d, 0x1e } }, /* 1: 26-33 platform / high-platform */ \
{ 0x02, 0x08, FALSE, 0x10, { 0x00, 0x00, 0x00, 0x00 } }, /* 2: 34-41 platform / solar-array */ \
{ 0x02, 0x09, TRUE, 0x11, { 0x0e, 0x0f, 0x10, 0x11 } }, /* 3: 42-4F low-platform / platform */ \
{ 0x02, 0x0a, TRUE, 0x12, { 0x13, 0x14, 0x15, 0x16 } }, /* 4: 50-5D rusty-pit / platform */ \
{ 0x02, 0x0b, FALSE, 0x0e, { 0x00, 0x00, 0x00, 0x00 } }, /* 5: 5E-6B platform / plating */ \
{ 0x04, 0x0c, FALSE, 0x0f, { 0x00, 0x00, 0x00, 0x00 } }, /* 6: 6C-79 high-platform / high-plating */ \
{ 0x02, 0x0d, FALSE, 0x13, { 0x09, 0x0a, 0x0b, 0x0c } }, /* 7: 7A-87 platform / elevated-catwalk */ \
{ 0x02, 0x0e, FALSE, 0x0d, { 0x00, 0x00, 0x00, 0x00 } }, /* 8: 88-95 platform / dark-platform */ \
}, \
}
/* L_ERA_INSTALL */
#define INSTALL_PARAM { \
0x16, /* edge_start */ \
{ /* center */ \
{ 0x01, 0x02, 0x01, S_STEP }, /* 0: substructure L_BRUSH_INSTALL_SUBSTRUCTURE */ \
{ 0x02, 0x03, 0x02, S_STEP }, /* 1: floor L_BRUSH_INSTALL_FLOOR */ \
{ 0x03, 0x06, 0x03, S_ROOF }, /* 2: roof L_BRUSH_INSTALL_ROOF */ \
{ 0x04, 0x04, 0x04, S_TILE }, /* 3: substructure-plating L_BRUSH_INSTALL_SUBSTRUCTURE_PLATING */ \
{ 0x05, 0x05, 0x05, S_TILE }, /* 4: plating L_BRUSH_INSTALL_PLATING */ \
{ 0x06, 0x08, 0x07, S_TILE }, /* 5: substructure-panels L_BRUSH_INSTALL_SUBSTRUCTURE_PANELS */ \
{ 0x07, 0x07, 0x06, S_NONE }, /* 6: bottomless-pit L_BRUSH_INSTALL_BOTTOMLESS_PIT */ \
}, \
{ /* edge */ \
{ 0x01, 0x02, FALSE, 0x0c, { 0x08, 0x09, 0x0a, 0x0b } }, /* 0: 16-23 substructure / floor */ \
{ 0x02, 0x03, FALSE, 0x0d, { 0x0c, 0x0d, 0x0e, 0x0f } }, /* 1: 24-31 floor / roof */ \
{ 0x01, 0x04, FALSE, 0x0a, { 0x00, 0x00, 0x00, 0x00 } }, /* 2: 32-3F substructure / substructure-plating */ \
{ 0x02, 0x05, FALSE, 0x0b, { 0x00, 0x00, 0x00, 0x00 } }, /* 3: 40-4D floor / plating */ \
{ 0x01, 0x06, FALSE, 0x0e, { 0x00, 0x00, 0x00, 0x00 } }, /* 4: 4E-5B substructure / substructure-panels */ \
{ 0x07, 0x01, FALSE, 0x0f, { 0x10, 0x11, 0x12, 0x13 } }, /* 5: 5C-69 bottomless-pit / substructure */ \
}, \
}
/* L_ERA_ASHWORLD */
#define ASHWORLD_PARAM { \
0x1b, /* edge_start */ \
{ /* center */ \
{ 0x01, 0x08, 0x07, S_NONE }, /* 0: magma L_BRUSH_ASHWORLD_MAGMA */ \
{ 0x02, 0x02, 0x01, S_NONE }, /* 1: dirt L_BRUSH_ASHWORLD_DIRT */ \
{ 0x03, 0x03, 0x02, S_TILE }, /* 2: lava L_BRUSH_ASHWORLD_LAVA */ \
{ 0x04, 0x06, 0x05, S_DIFFUSE }, /* 3: shale L_BRUSH_ASHWORLD_SHALE */ \
{ 0x08, 0x09, 0x08, S_TILE }, /* 4: broken-rock L_BRUSH_ASHWORLD_BROKEN_ROCK */ \
{ 0x05, 0x04, 0x03, S_NONE }, /* 5: high-dirt L_BRUSH_ASHWORLD_HIGH_DIRT */ \
{ 0x06, 0x05, 0x04, S_TILE }, /* 6: high-lava L_BRUSH_ASHWORLD_HIGH_LAVA */ \
{ 0x07, 0x07, 0x06, S_DIFFUSE }, /* 7: high-shale L_BRUSH_ASHWORLD_HIGH_SHALE */ \
}, \
{ /* edge */ \
{ 0x01, 0x02, FALSE, 0x11, { 0x09, 0x0a, 0x0b, 0x0c } }, /* 0: 1B-28 magma / dirt */ \
{ 0x02, 0x05, FALSE, 0x10, { 0x0d, 0x0e, 0x0f, 0x10 } }, /* 1: 29-36 dirt / high-dirt */ \
{ 0x02, 0x03, FALSE, 0x0b, { 0x00, 0x00, 0x00, 0x00 } }, /* 2: 37-44 dirt / lava */ \
{ 0x05, 0x06, FALSE, 0x0c, { 0x00, 0x00, 0x00, 0x00 } }, /* 3: 45-52 high-dirt / high-lava */ \
{ 0x02, 0x04, FALSE, 0x0d, { 0x00, 0x00, 0x00, 0x00 } }, /* 4: 53-60 dirt / shale */ \
{ 0x05, 0x07, FALSE, 0x0e, { 0x00, 0x00, 0x00, 0x00 } }, /* 5: 61-6E high-dirt / high-shale */ \
{ 0x02, 0x08, FALSE, 0x0f, { 0x00, 0x00, 0x00, 0x00 } }, /* 6: 6F-7C dirt / broken-rock */ \
}, \
}
/* L_ERA_JUNGLE */
#define JUNGLE_PARAM { \
0x11, /* edge_start */ \
{ /* center */ \
{ 0x03, 0x05, 0x05, S_NONE }, /* 0: water L_BRUSH_JUNGLE_WATER */ \
{ 0x01, 0x02, 0x01, S_NONE }, /* 1: dirt L_BRUSH_JUNGLE_DIRT */ \
{ 0x0d, 0x04, 0x0f, S_NONE }, /* 2: mud L_BRUSH_JUNGLE_MUD */ \
{ 0x04, 0x08, 0x08, S_NONE }, /* 3: jungle L_BRUSH_JUNGLE_JUNGLE */ \
{ 0x06, 0x0f, 0x0b, S_DIFFUSE }, /* 4: rocky-ground L_BRUSH_JUNGLE_ROCKY_GROUND */ \
{ 0x07, 0x0b, 0x06, S_DIFFUSE }, /* 5: ruins L_BRUSH_JUNGLE_RUINS */ \
{ 0x05, 0x09, 0x0c, S_DIFFUSE }, /* 6: raised-jungle L_BRUSH_JUNGLE_RAISED_JUNGLE */ \
{ 0x08, 0x10, 0x10, S_MATTED }, /* 7: temple L_BRUSH_JUNGLE_TEMPLE */ \
{ 0x02, 0x03, 0x04, S_NONE }, /* 8: high-dirt L_BRUSH_JUNGLE_HIGH_DIRT */ \
{ 0x09, 0x0a, 0x09, S_NONE }, /* 9: high-jungle L_BRUSH_JUNGLE_HIGH_JUNGLE */ \
{ 0x0a, 0x0c, 0x07, S_DIFFUSE }, /* a: high-ruins L_BRUSH_JUNGLE_HIGH_RUINS */ \
{ 0x0b, 0x0d, 0x0d, S_DIFFUSE }, /* b: high-raised-jungle L_BRUSH_JUNGLE_HIGH_RAISED_JUNGLE */ \
{ 0x0c, 0x11, 0x11, S_MATTED }, /* c: high-temple L_BRUSH_JUNGLE_HIGH_TEMPLE */ \
}, \
{ /* edge */ \
{ 0x01, 0x02, FALSE, 0x22, { 0x1e, 0x1f, 0x20, 0x21 } }, /* 0: 11-1E dirt / high-dirt */ \
{ 0x03, 0x01, FALSE, 0x23, { 0x22, 0x23, 0x24, 0x25 } }, /* 1: 1F-2C water / dirt */ \
{ 0x01, 0x04, FALSE, 0x17, { 0x00, 0x00, 0x00, 0x00 } }, /* 2: 2D-3A dirt / jungle */ \
{ 0x01, 0x06, FALSE, 0x1c, { 0x00, 0x00, 0x00, 0x00 } }, /* 3: 3B-48 dirt / rocky-ground */ \
{ 0x04, 0x05, FALSE, 0x1d, { 0x00, 0x00, 0x00, 0x00 } }, /* 4: 49-56 jungle / raised jungle */ \
{ 0x04, 0x07, FALSE, 0x19, { 0x00, 0x00, 0x00, 0x00 } }, /* 5: 57-64 jungle / ruins */ \
{ 0x04, 0x08, FALSE, 0x20, { 0x12, 0x13, 0x14, 0x15 } }, /* 6: 65-72 jungle / temple */ \
{ 0x02, 0x09, FALSE, 0x18, { 0x00, 0x00, 0x00, 0x00 } }, /* 7: 73-80 high-dirt / high-jungle */ \
{ 0x09, 0x0a, FALSE, 0x1a, { 0x00, 0x00, 0x00, 0x00 } }, /* 8: 81-8E high-jungle / high-ruins */ \
{ 0x09, 0x0b, FALSE, 0x1e, { 0x00, 0x00, 0x00, 0x00 } }, /* 9: 8F-9C high-jungle / high-raised-jungle */ \
{ 0x09, 0x0c, FALSE, 0x21, { 0x16, 0x17, 0x18, 0x19 } }, /* a: 9D-AA high-jungle / high-temple */ \
{ 0x01, 0x0d, FALSE, 0x16, { 0x00, 0x00, 0x00, 0x00 } }, /* b: AB-B8 dirt / mud */ \
}, \
}
/* L_ERA_DESERT */
#define DESERT_PARAM { \
0x11, /* edge_start */ \
{ /* center */ \
{ 0x03, 0x05, 0x05, S_NONE }, /* 0: tar L_BRUSH_DESERT_TAR */ \
{ 0x01, 0x02, 0x01, S_NONE }, /* 1: dirt L_BRUSH_DESERT_DIRT */ \
{ 0x0d, 0x04, 0x0f, S_NONE }, /* 2: dried-mud L_BRUSH_DESERT_DRIED_MUD */ \
{ 0x04, 0x08, 0x08, S_NONE }, /* 3: sand-dunes L_BRUSH_DESERT_SAND_DUNES */ \
{ 0x06, 0x0f, 0x0b, S_DIFFUSE }, /* 4: rocky-ground L_BRUSH_DESERT_ROCKY_GROUND */ \
{ 0x07, 0x0b, 0x06, S_DIFFUSE }, /* 5: crags L_BRUSH_DESERT_CRAGS */ \
{ 0x05, 0x09, 0x0c, S_DIFFUSE }, /* 6: sandy-sunken-pit L_BRUSH_DESERT_SANDY_SUNKEN_PIT */ \
{ 0x08, 0x10, 0x10, S_MATTED }, /* 7: compound L_BRUSH_DESERT_COMPOUND */ \
{ 0x02, 0x03, 0x04, S_NONE }, /* 8: high-dirt L_BRUSH_DESERT_HIGH_DIRT */ \
{ 0x09, 0x0a, 0x09, S_NONE }, /* 9: high-sand-dunes L_BRUSH_DESERT_HIGH_SAND_DUNES */ \
{ 0x0a, 0x0c, 0x07, S_DIFFUSE }, /* a: high-crags L_BRUSH_DESERT_HIGH_CRAGS */ \
{ 0x0b, 0x0d, 0x0d, S_DIFFUSE }, /* b: high-sandy-sunken-pit L_BRUSH_DESERT_HIGH_SANDY_SUNKEN_PIT */ \
{ 0x0c, 0x11, 0x11, S_MATTED }, /* c: high-compound L_BRUSH_DESERT_HIGH_COMPOUND */ \
}, \
{ /* edge */ \
{ 0x01, 0x02, FALSE, 0x22, { 0x1e, 0x1f, 0x20, 0x21 } }, /* 0: 11-1E dirt / high-dirt */ \
{ 0x03, 0x01, FALSE, 0x23, { 0x22, 0x23, 0x24, 0x25 } }, /* 1: 1F-2C tar / dirt */ \
{ 0x01, 0x04, FALSE, 0x17, { 0x00, 0x00, 0x00, 0x00 } }, /* 2: 2D-3A dirt / sand-dunes */ \
{ 0x01, 0x06, FALSE, 0x1c, { 0x00, 0x00, 0x00, 0x00 } }, /* 3: 3B-48 dirt / rocky-ground */ \
{ 0x04, 0x05, FALSE, 0x1d, { 0x00, 0x00, 0x00, 0x00 } }, /* 4: 49-56 sand-dunes / sandy-sunken-pit */ \
{ 0x04, 0x07, FALSE, 0x19, { 0x00, 0x00, 0x00, 0x00 } }, /* 5: 57-64 sand-dunes / crags */ \
{ 0x04, 0x08, FALSE, 0x20, { 0x12, 0x13, 0x14, 0x15 } }, /* 6: 65-72 sand-dunes / compound */ \
{ 0x02, 0x09, FALSE, 0x18, { 0x00, 0x00, 0x00, 0x00 } }, /* 7: 73-80 high-dirt / high-sand-dunes */ \
{ 0x09, 0x0a, FALSE, 0x1a, { 0x00, 0x00, 0x00, 0x00 } }, /* 8: 81-8E high-sand-dunes / high-crags */ \
{ 0x09, 0x0b, FALSE, 0x1e, { 0x00, 0x00, 0x00, 0x00 } }, /* 9: 8F-9C high-sand-dunes / high-sandy-sunken-pit */ \
{ 0x09, 0x0c, FALSE, 0x21, { 0x16, 0x17, 0x18, 0x19 } }, /* a: 9D-AA high-sand-dunes / high-compound */ \
{ 0x01, 0x0d, FALSE, 0x16, { 0x00, 0x00, 0x00, 0x00 } }, /* b: AB-B8 dirt / dried-mud */ \
}, \
}
/* L_ERA_ICE */
#define ICE_PARAM { \
0x11, /* edge_start */ \
{ /* center */ \
{ 0x03, 0x05, 0x05, S_NONE }, /* 0: ice L_BRUSH_ICE_ICE */ \
{ 0x01, 0x02, 0x01, S_NONE }, /* 1: snow L_BRUSH_ICE_SNOW */ \
{ 0x0d, 0x04, 0x0f, S_NONE }, /* 2: moguls L_BRUSH_ICE_MOGULS */ \
{ 0x04, 0x08, 0x08, S_NONE }, /* 3: dirt L_BRUSH_ICE_DIRT */ \
{ 0x06, 0x0f, 0x0b, S_DIFFUSE }, /* 4: rocky-snow L_BRUSH_ICE_ROCKY_SNOW */ \
{ 0x07, 0x0b, 0x06, S_DIFFUSE }, /* 5: grass L_BRUSH_ICE_GRASS */ \
{ 0x05, 0x09, 0x0c, S_DIFFUSE }, /* 6: water L_BRUSH_ICE_WATER */ \
{ 0x08, 0x10, 0x10, S_MATTED }, /* 7: outpost L_BRUSH_ICE_OUTPOST */ \
{ 0x02, 0x03, 0x04, S_NONE }, /* 8: high-snow L_BRUSH_ICE_HIGH_SNOW */ \
{ 0x09, 0x0a, 0x09, S_NONE }, /* 9: high-dirt L_BRUSH_ICE_HIGH_DIRT */ \
{ 0x0a, 0x0c, 0x07, S_DIFFUSE }, /* a: high-grass L_BRUSH_ICE_HIGH_GRASS */ \
{ 0x0b, 0x0d, 0x0d, S_DIFFUSE }, /* b: high-water L_BRUSH_ICE_HIGH_WATER */ \
{ 0x0c, 0x11, 0x11, S_MATTED }, /* c: high-outpost L_BRUSH_ICE_HIGH_OUTPOST */ \
}, \
{ /* edge */ \
{ 0x01, 0x02, FALSE, 0x22, { 0x1e, 0x1f, 0x20, 0x21 } }, /* 0: 11-1E snow / high-snow */ \
{ 0x03, 0x01, FALSE, 0x23, { 0x22, 0x23, 0x24, 0x25 } }, /* 1: 1F-2C ice / snow */ \
{ 0x01, 0x04, FALSE, 0x17, { 0x00, 0x00, 0x00, 0x00 } }, /* 2: 2D-3A snow / dirt */ \
{ 0x01, 0x06, FALSE, 0x1c, { 0x00, 0x00, 0x00, 0x00 } }, /* 3: 3B-48 snow / rocky-snow */ \
{ 0x04, 0x05, FALSE, 0x1d, { 0x00, 0x00, 0x00, 0x00 } }, /* 4: 49-56 dirt / water */ \
{ 0x04, 0x07, FALSE, 0x19, { 0x00, 0x00, 0x00, 0x00 } }, /* 5: 57-64 dirt / grass */ \
{ 0x04, 0x08, FALSE, 0x20, { 0x12, 0x13, 0x14, 0x15 } }, /* 6: 65-72 dirt / outpost */ \
{ 0x02, 0x09, FALSE, 0x18, { 0x00, 0x00, 0x00, 0x00 } }, /* 7: 73-80 high-snow / high-dirt */ \
{ 0x09, 0x0a, FALSE, 0x1a, { 0x00, 0x00, 0x00, 0x00 } }, /* 8: 81-8E high-dirt / high-grass */ \
{ 0x09, 0x0b, FALSE, 0x1e, { 0x00, 0x00, 0x00, 0x00 } }, /* 9: 8F-9C high-dirt / high-water */ \
{ 0x09, 0x0c, FALSE, 0x21, { 0x16, 0x17, 0x18, 0x19 } }, /* a: 9D-AA high-dirt / high-outpost */ \
{ 0x01, 0x0d, FALSE, 0x16, { 0x00, 0x00, 0x00, 0x00 } }, /* b: AB-B8 snow / moguls */ \
}, \
}
/* L_ERA_TWILIGHT */
#define TWILIGHT_PARAM { \
0x11, /* edge_start */ \
{ /* center */ \
{ 0x03, 0x05, 0x05, S_NONE }, /* 0: water L_BRUSH_TWLIGHT_WATER */ \
{ 0x01, 0x02, 0x01, S_NONE }, /* 1: dirt L_BRUSH_TWLIGHT_DIRT */ \
{ 0x0d, 0x04, 0x0f, S_NONE }, /* 2: mud L_BRUSH_TWLIGHT_MUD */ \
{ 0x04, 0x08, 0x08, S_NONE }, /* 3: crushed-rock L_BRUSH_TWLIGHT_CRUSHED_ROCK */ \
{ 0x06, 0x0f, 0x0b, S_DIFFUSE }, /* 4: crevices L_BRUSH_TWLIGHT_CREVICES */ \
{ 0x07, 0x0b, 0x06, S_DIFFUSE }, /* 5: flagstones L_BRUSH_TWLIGHT_FLAGSTONES */ \
{ 0x05, 0x09, 0x0c, S_DIFFUSE }, /* 6: sunken-ground L_BRUSH_TWLIGHT_SUNKEN_GROUND */ \
{ 0x08, 0x10, 0x10, S_MATTED }, /* 7: basilica L_BRUSH_TWLIGHT_BASILICA */ \
{ 0x02, 0x03, 0x04, S_NONE }, /* 8: high-dirt L_BRUSH_TWLIGHT_HIGH_DIRT */ \
{ 0x09, 0x0a, 0x09, S_NONE }, /* 9: high-crushed-rock L_BRUSH_TWLIGHT_HIGH_CRUSHED_ROCK */ \
{ 0x0a, 0x0c, 0x07, S_DIFFUSE }, /* a: high-flagstones L_BRUSH_TWLIGHT_HIGH_FLAGSTONES */ \
{ 0x0b, 0x0d, 0x0d, S_DIFFUSE }, /* b: high-sunken-ground L_BRUSH_TWLIGHT_HIGH_SUNKEN_GROUND */ \
{ 0x0c, 0x11, 0x11, S_MATTED }, /* c: high-basilica L_BRUSH_TWLIGHT_HIGH_BASILICA */ \
}, \
{ /* edge */ \
{ 0x01, 0x02, FALSE, 0x22, { 0x1e, 0x1f, 0x20, 0x21 } }, /* 0: 11-1E dirt / high-dirt */ \
{ 0x03, 0x01, FALSE, 0x23, { 0x22, 0x23, 0x24, 0x25 } }, /* 1: 1F-2C water / dirt */ \
{ 0x01, 0x04, FALSE, 0x17, { 0x00, 0x00, 0x00, 0x00 } }, /* 2: 2D-3A dirt / crushed-rock */ \
{ 0x01, 0x06, FALSE, 0x1c, { 0x00, 0x00, 0x00, 0x00 } }, /* 3: 3B-48 dirt / crevices */ \
{ 0x04, 0x05, FALSE, 0x1d, { 0x00, 0x00, 0x00, 0x00 } }, /* 4: 49-56 crushed-rock / raised crushed-rock */ \
{ 0x04, 0x07, FALSE, 0x19, { 0x00, 0x00, 0x00, 0x00 } }, /* 5: 57-64 crushed-rock / flagstones */ \
{ 0x04, 0x08, FALSE, 0x20, { 0x12, 0x13, 0x14, 0x15 } }, /* 6: 65-72 crushed-rock / basilica */ \
{ 0x02, 0x09, FALSE, 0x18, { 0x00, 0x00, 0x00, 0x00 } }, /* 7: 73-80 high-dirt / high-crushed-rock */ \
{ 0x09, 0x0a, FALSE, 0x1a, { 0x00, 0x00, 0x00, 0x00 } }, /* 8: 81-8E high-crushed-rock / high-flagstones */ \
{ 0x09, 0x0b, FALSE, 0x1e, { 0x00, 0x00, 0x00, 0x00 } }, /* 9: 8F-9C high-crushed-rock / high-sunken-ground */ \
{ 0x09, 0x0c, FALSE, 0x21, { 0x16, 0x17, 0x18, 0x19 } }, /* a: 9D-AA high-crushed-rock / high-basilica */ \
{ 0x01, 0x0d, FALSE, 0x16, { 0x00, 0x00, 0x00, 0x00 } }, /* b: AB-B8 dirt / mud */ \
}, \
}
/************************************************************************/
enum ORDER { LOW, HIGH };
enum SIDE { LEFT_SIDE, RIGHT_SIDE, SIDE_NUM };
enum DIR { LEFT, TOP, RIGHT, BOTTOM, DIR_NUM };
enum FROM { LEFT_TOP, TOP_RIGHT, RIGHT_BOTTOM, BOTTOM_LEFT, FROM_NUM };
/* Central terrain type enumeration */
enum CENTER_STYLE {
S_NONE, /* Non-specific terrain */
S_MATTED, /* With bedding terrain */
S_DIFFUSE, /* Diffusion terrain */
S_TILE, /* Fangzhuan type terrain */
S_STEP, /* Stepped terrain */
S_ROOF, /* Roof type terrain */
};
/* TILE type mapping enumerate */
enum TYPE_MAP {
AS_EDGE, /* The edge of the same type itself TILE */
AS_LOW, /* With the same type of low-level terrain TILE */
AS_HIGH, /* With the same type of high-level terrain TILE */
};
/************************************************************************/
/* Edge shape parameters structure */
struct SHAPE_PARAM {
INT order[DIR_NUM]; /* Four corners of the diamond each level terrain */
INT type[FROM_NUM]; /* Four corners of the diamond type information corresponding to each TILE */
INT x_abut[FROM_NUM]; /* Horizontal X axis adjacency information */
/* Its index corresponding relationship is: */
/* LEFT_TOP upper left diamond RIGHT */
/* TOP_RIGHT upper right diamond LEFT */
/* RIGHT_BOTTOM right diamond LEFT */
/* BOTTOM_LEFT left diamond RIGHT */
INT y_abut[SIDE_NUM]; /* Y axis horizontal adjacency information */
/* Its index corresponding relationship is: */
/* LEFT_SIDE upper left and lower left diamond diamond TOP BOTTOM */
/* RIGHT_SIDE upper right and lower right diamond diamond TOP BOTTOM */
};
/* ERA-related parameter structure */
struct ERA_PARAM {
WORD edge_start; /* The initial value of the edge of the ISOM */
/* From the beginning of each successive SHAPE_NUM as a group, corresponding to an edge array member */
struct {
WORD isom; /* ISOM corresponding value */
WORD type; /* TILE corresponding type */
WORD abut; /* Horizontal adjacency ID */
WORD style; /* Central terrain type */
} center[MAX_CENTER]; /* Central terrain parameters */
struct {
WORD low; /* ISOM value lower terrain */
WORD high; /* ISOM value level terrain */
BOOL upend; /* When the value is inverted to generate the vertical relationship ISOM */
/* Only Platform in Low Platform and Rusty Pit have this feature */
WORD type; /* Edge transition TILE type */
WORD cliff[CLIFF_NUM]; /* Cliff horizontal adjacency ID (cliff edge only valid) */
} edge[MAX_EDGE]; /* Edge of the terrain parameters */
};
/* ERA-related information, initialization generated by ERA_PARAM */
struct ERA_INFO {
BOOL init_flag; /* Initialization flag */
INT center_num; /* Central terrain number (center array of effective number of members) */
INT edge_num; /* Edge terrain number (edge array effectively Members) */
INT max_center_type; /* Maximum central terrain types */
struct {
INT below; /* Before being connected under the terrain index */
INT below_edge; /* The index formed by joining the lower edge */
INT above_num; /* Terrain number (above, above_edge effective number of members) connected on order */
INT above[MAX_LINK]; /* Before being connected to an array of terrain on the index */
INT above_edge[MAX_LINK]; /* Array index above the connecting edges formed by the */
} center[MAX_CENTER]; /* Central terrain information */
struct {
INT low; /* Terrain Terrain index lower */
INT high; /* Terrain index level terrain */
BOOL cliff; /* Whether the brink */
INT shape[SHAPE_NUM][DIR_NUM]; /* The corners of the rhombic shape of the edge of the terrain index */
} edge[MAX_EDGE]; /* Edge terrain information */
};
/* ISOM diamond structure information of the mapping TILE */
struct TILE_MAP {
WORD type[FROM_NUM]; /* Four corners of the ISOM diamond diamond TILE type */
WORD x_abut[FROM_NUM]; /* Four corners of the diamond-shaped rhombic ISOM X-axis (horizontal) adjacent ID */
WORD y_abut[FROM_NUM]; /* Four corners of the diamond-shaped rhombic ISOM Y-axis (horizontal) adjacent ID */
WORD z_abut[FROM_NUM]; /* Four corners of the diamond-shaped rhombic ISOM Z-axis (vertical) adjacent ID */
WORD proj[SIDE_NUM]; /* Projected onto a vertical cliff terrain adjacent ID TILE diamond on the bottom */
};
/* Coordinate information queue node structure */
struct POS_QUENE {
POINT pos; /* Coordinate information */
struct POS_QUENE *next; /* The next node in the queue */
};
/************************************************************************/
/* Position value even diamond (left, top, right, bottom sequence) */
static CONST WORD TILE_POS_EVEN[DIR_NUM] = { 0x8, 0xa, 0x0, 0x2 };
/* Odd position value diamond (left, top, right, bottom sequence) */
static CONST WORD TILE_POS_ODD[DIR_NUM] = { 0x4, 0xc, 0xe, 0x6 };
/* 14 kinds of combinations of shapes edge */
static CONST struct SHAPE_PARAM SHAPE_TABLE[SHAPE_NUM] = {
LLHH_PARAM, HLLH_PARAM, HHLL_PARAM, LHHL_PARAM,
LLLH_PARAM, HLLL_PARAM, LHLL_PARAM, LLHL_PARAM,
LHHH_PARAM, HHLH_PARAM, HLHH_PARAM, HHHL_PARAM,
LHLH_PARAM, HLHL_PARAM,
};
/* Each ERA of ISOM parameter table */
static CONST struct ERA_PARAM PARAM_TABLE[L_ERA_NUM] = {
BADLANDS_PARAM, PLATFORM_PARAM, INSTALL_PARAM, ASHWORLD_PARAM,
JUNGLE_PARAM, DESERT_PARAM, ICE_PARAM, TWILIGHT_PARAM,
};
/* Global Variables */
static BOOL g_InitFlag;
static UINT g_TileDictNum[L_ERA_NUM];
static ISOM_DICT *g_TileDict[L_ERA_NUM];
static struct ERA_INFO g_EraInfo[L_ERA_NUM];
static INT g_Isom2Center[L_ERA_NUM][MAX_CENTER_ISOM];
static INT g_Shape2Index[MAX_SHAPE_ID];
static struct POS_QUENE g_PosQueneHead;
static struct POS_QUENE *g_PosQueneTail;
/************************************************************************/
/* Public function */
static BOOL validate_iso_map(CONST ISOM_MAP *map, BOOL create);
static BOOL check_pos(CONST ISOM_MAP *map, CONST POINT *pos);
static VOID calc_corner_pos(INT from, CONST POINT *base, POINT *corner);
static VOID calc_link_pos(INT from, CONST POINT *base, POINT *link);
static WORD get_center_isom(INT era, INT center);
static WORD get_edge_isom(INT era, INT edge, INT shape);
static INT isom_to_center(INT era, WORD isom);
static BOOL isom_to_edge_shape(INT era, WORD isom, INT *edge, INT *shape);
static INT shape_to_index(INT left, INT top, INT right, INT bottom);
/* ISOM value generation correlation function */
static BOOL isometric_brush(ISOM_MAP *map, INT brush, CONST POINT *pos);
static WORD isometric_link(ISOM_MAP *map, WORD isom, INT from, CONST POINT *pos);
static BOOL update_isom(ISOM_MAP *map, WORD isom, INT from, CONST POINT *pos);
static BOOL set_tile_pos(ISOM_MAP *map, CONST POINT *pos);
static BOOL get_isom_shape(INT era, WORD isom, INT *low, INT *high, INT *shape_info);
static WORD match_shape(INT era, CONST INT *shape_info);
static INT search_brush_link(INT era, INT brush_from, INT brush_to);
/* TILE mapping correlation function */
static BOOL make_tile_map(CONST ISOM_MAP *map, CONST POINT *pos, ISOM_TILE *tile);
static VOID adjust_dirty_map(CONST ISOM_MAP *map, CONST POINT *pos, CONST ISOM_TILE *isom);
static VOID update_tile(CONST ISOM_MAP *map, CONST POINT *pos, CONST ISOM_TILE *isom);
static VOID map_isom_tile(CONST ISOM_MAP *map, CONST struct TILE_MAP *tile_map, CONST POINT *pos, ISOM_TILE *tile);
static CONST ISOM_DICT *lookup_tile(INT era, CONST ISOM_TILE *tile);
static INT gen_mega_tile_index(INT era, INT map_cx, INT y, CONST ISOM_DICT *dict, CONST ISOM_TILE *isom, LTILECPTR tile);
static WORD map_edge_tile_type(INT era, INT low, INT high, INT edge, INT temp);
static WORD map_edge_hor_abuttal(INT era, INT low, INT high, INT edge, INT temp, WORD *proj);
static WORD map_edge_ver_abuttal(INT era, INT low, INT high, INT edge, INT temp);
static VOID project_abuttal(CONST ISOM_MAP *map, ISOM_TILE *tile, INT from, WORD proj, CONST POINT *pos);
/* Coordinate information related to the operation queue function */
static BOOL init_pos_quene(CONST POINT *pos);
static VOID exit_pos_quene(VOID);
static BOOL push_pos_quene(CONST POINT *pos);
static BOOL pop_pos_quene(VOID);
static CONST POINT *peek_pos_quene(VOID);
static BOOL is_pos_quene_empty(VOID);
/************************************************************************/
BOOL init_iso_map(VOID)
{
INT i, shape;
CONST INT *order;
/* As already initialized, doing nothing */
if (g_InitFlag)
return TRUE;
/* First of all fill the shape index mapping table to an invalid value */
DMemSet(g_Shape2Index, -1, sizeof(g_Shape2Index));
/* Initialization shape index mapping table in order to find the corresponding index from the specific shape of the edge shape */
for (i = 0; i < SHAPE_NUM; i++) {
order = SHAPE_TABLE[i].order;
shape = MAKE_SHAPE_ID(order[LEFT], order[TOP], order[RIGHT], order[BOTTOM]);
DAssert(DBetween(shape, 0, MAX_SHAPE_ID));
g_Shape2Index[shape] = i;
}
/* Set initialization flag */
g_InitFlag = TRUE;
return TRUE;
}
VOID exit_iso_map(VOID)
{
/* If you do not do anything yet initialized */
if (!g_InitFlag)
return;
/* Clear initialization flag */
g_InitFlag = FALSE;
/* Clear global variables */
DVarClr(g_TileDictNum);
DVarClr(g_TileDict);
DVarClr(g_EraInfo);
DVarClr(g_Isom2Center);
DVarClr(g_Shape2Index);
}
BOOL init_iso_era(INT era, CONST ISOM_DICT *tile_dict, UINT tile_num)
{
INT center, edge, shape, low, high;
UINT size;
WORD isom;
ISOM_DICT *dict;
struct ERA_INFO *info;
CONST struct ERA_PARAM *param;
/* Such as global yet failed to initialize the */
if (!g_InitFlag)
return FALSE;
/* Parameters validity check */
if (!DBetween(era, 0, L_ERA_NUM) || !tile_dict || !tile_num)
return FALSE;
/* If you specify the ERA has been initialized, then do nothing */
if (g_EraInfo[era].init_flag)
return TRUE;
DAssert(!g_TileDictNum[era] && !g_TileDict[era]);
/* Creating TILE dictionary */
/* Memory Allocation */
size = tile_num * sizeof(ISOM_DICT);
dict = DAlloc(size);
if (!dict)
return FALSE;
/* Dictionary content setting */
DMemCpy(dict, tile_dict, size);
g_TileDict[era] = dict;
g_TileDictNum[era] = tile_num;
/* ERA initialization parameter information with ERA */
param = &PARAM_TABLE[era];
info = &g_EraInfo[era];
/* Counter is cleared */
info->center_num = 0;
info->edge_num = 0;
/* The central value of terrain types ISOM lookup table of contents initialized to an invalid value */
DMemSet(&g_Isom2Center[era], -1, sizeof(g_Isom2Center[era]));
/* Initialization central terrain information */
for (center = 0; center < MAX_CENTER; center++) {
info->center[center].above_num = 0;
info->center[center].below = -1;
info->center[center].below_edge = -1;
DMemSet(info->center[center].above, -1, sizeof(info->center[center].above));
DMemSet(info->center[center].above_edge, -1, sizeof(info->center[center].above_edge));
}
/* Circulation to the central terrain establishment of various lookup tables, while the number of central statistical terrain types */
for (center = 0; center < MAX_CENTER; center++) {
/* In case of 0 indicates the end */
isom = param->center[center].isom;
if (!isom)
break;
/* Central Statistical maximum terrain type */
if (param->center[center].type > info->max_center_type)
info->max_center_type = param->center[center].type;
DAssert(isom < MAX_CENTER_ISOM);
/* Filling ISOM value to the central terrain type lookup table */
g_Isom2Center[era][isom] = center;
/* Central terrain types cumulative count */
info->center_num++;
}
/* Cycle to generate an edge shape information, and access to the number of edges */
for (edge = 0; edge < MAX_EDGE; edge++) {
/* In case of 0 indicates the end */
if (!param->edge[edge].low || !param->edge[edge].high)
break;
DAssert(param->edge[edge].low < MAX_CENTER_ISOM);
DAssert(param->edge[edge].high < MAX_CENTER_ISOM);
/* Determine the topography and terrain index lower level terrain */
low = g_Isom2Center[era][param->edge[edge].low];
high = g_Isom2Center[era][param->edge[edge].high];
DAssert(low >= 0 && high >= 0);
/* If you need to reverse the up and down relationship, in this reversal */
if (param->edge[edge].upend)
DSwap(low, high);
/* Filled with high and low terrain index values */
info->edge[edge].low = low;
info->edge[edge].high = high;
/* Determine whether the cliff edge */
info->edge[edge].cliff = param->edge[edge].cliff[0] ? TRUE : FALSE;
/* Each corner of the look-up table to generate an edge shaped diamond terrain index information */
for (shape = 0; shape < SHAPE_NUM; shape++) {
info->edge[edge].shape[shape][LEFT] = SHAPE_TABLE[shape].order[LEFT] ? high : low;
info->edge[edge].shape[shape][TOP] = SHAPE_TABLE[shape].order[TOP] ? high : low;
info->edge[edge].shape[shape][RIGHT] = SHAPE_TABLE[shape].order[RIGHT] ? high : low;
info->edge[edge].shape[shape][BOTTOM] = SHAPE_TABLE[shape].order[BOTTOM] ? high : low;
}
/* Cumulative count edge terrain type */
info->edge_num++;
}
DAssert(info->center_num > 0 && info->edge_num > 0);
/* Circulation of information throughout the terrain brush */
for (center = 0; center < info->center_num; center++) {
/* In case of 0 indicates the end */
isom = param->center[center].isom;
if (!isom)
break;
/* Check each set of edge combination itemized */
for (edge = 0; edge < info->edge_num; edge++) {
/* If the connection at the top of */
if (param->edge[edge].low == isom) {
DAssert(info->center[center].above_num <= MAX_LINK);
DAssert(param->edge[edge].high < MAX_CENTER_ISOM);
high = g_Isom2Center[era][param->edge[edge].high];
DAssert(high >= 0);
info->center[center].above[info->center[center].above_num] = high;
info->center[center].above_edge[info->center[center].above_num] = edge;
info->center[center].above_num++;
continue;
}
/* If it is connected to the bottom (at most one) */
if (param->edge[edge].high == isom) {
DAssert(param->edge[edge].low < MAX_CENTER_ISOM);
low = g_Isom2Center[era][param->edge[edge].low];
DAssert(low >= 0);
info->center[center].below = low;
info->center[center].below_edge = edge;
continue;
}
}
}
/* Set initialization flag */
info->init_flag = TRUE;
return TRUE;
}
VOID exit_iso_era(INT era)
{
/* Parameters validity check */
if (!DBetween(era, 0, L_ERA_NUM))
return;
/* If you do not do anything yet initialized */
if (!g_EraInfo[era].init_flag)
return;
/* Clear the corresponding dictionary information */
g_TileDictNum[era] = 0;
DFree(g_TileDict[era]);
g_TileDict[era] = NULL;
/* Clear ERA-related information */
DVarClr(g_EraInfo[era]);
DVarClr(g_Isom2Center[era]);
}
BOOL create_iso_map(ISOM_MAP *map, BOOL new_map)
{
INT i, j, row, line, center;
UINT size;
WORD group, mega;
VPTR dirty;
LISOMPTR data;
LTILEPTR tile;
LISOMCOORD isom;
ISOM_TILE index;
CONST ISOM_DICT *dict;
CONST struct ERA_PARAM *param;
/* If not then fail to initialize */
if (!g_InitFlag)
return FALSE;
/* Parameters validity check */
if (!validate_iso_map(map, TRUE))
return FALSE;
row = CALC_ISOM_ROW(map->size.cx);
line = CALC_ISOM_LINE(map->size.cy);
size = row * line * sizeof(LISOMTILE);
data = DAlloc(size);
if (!data)
return FALSE;
/* ISOM initialization */
DMemClr(data, size);
size = map->size.cx * map->size.cy * sizeof(LTILEIDX);
tile = DAlloc(size);
if (!tile) {
DFree(data);
return FALSE;
}
/* TILE initialization */
DMemClr(tile, size);
size = CALC_DIRTY_SIZE(&map->size);
dirty = DAlloc(size);
if (!dirty) {
DFree(data);
DFree(tile);
return FALSE;
}
/* Dirty flag map initialization */
DMemClr(dirty, size);
map->isom = data;
map->tile = tile;
map->dirty = dirty;
/* Just initialize the structure rather than the new map, then stop here */
if (!new_map)
return TRUE;
param = &PARAM_TABLE[map->era];
/* Filling structure set */
isom.pos = 0;
isom.isom = get_center_isom(map->era, map->def);
isom.unused = 0;
/* Filled with an initial value of each diamond ISOM */
for (i = 0; i < line; i++) {
for (j = 0; j < row; j++, data++) {
data->left = isom;
data->top = isom;
data->right = isom;
data->bottom = isom;
}
}
center = isom_to_center(map->era, isom.isom);
index.type = param->center[center].type;
index.left_abut = param->center[center].abut;
index.top_abut = param->center[center].abut;
index.right_abut = param->center[center].abut;
index.bottom_abut = param->center[center].abut;
index.up_abut = V_ABUT_NONE;
index.down_abut = V_ABUT_NONE;
dict = lookup_tile(map->era, &index);
DAssert(dict && dict->group_no);
/* The initial value of the filling in each TILE */
for (i = 0; i < map->size.cy; i++) {
for (j = 0; j < map->size.cx; j += 2) {
group = dict->group_no;
mega = gen_mega_tile_index(map->era, map->size.cx, i, dict, &index, tile);
tile->mega_index = mega;
tile->group_no = group++;
tile++;
tile->mega_index = mega;
tile->group_no = group;
tile++;
}
}
/* Successful return */
return TRUE;
}
VOID destroy_iso_map(ISOM_MAP *map)
{
if (!map)
return;
DFree(map->isom);
map->isom = NULL;
DFree(map->tile);
map->tile = NULL;
DFree(map->dirty);
map->dirty = NULL;
}
BOOL brush_iso_map(ISOM_MAP *map, INT brush, CONST POINT *tile_pos)
{
POINT pos;
/* If not then fail to initialize */
if (!g_InitFlag)
return FALSE;
/* ISOM map parameter validity check */
if (!validate_iso_map(map, FALSE))
return FALSE;
/* Brush terrain index value that is central to be within the allowable range of values */
if (!DBetween(brush, 0, g_EraInfo[map->era].center_num))
return FALSE;
/* TILE coordinates validity check */
if (!tile_pos || tile_pos->x < 0 || tile_pos->y < 0)
return FALSE;
/*
TILE coordinate system to adjust the coordinate system ISOM diamond.
It should be noted for a brush, brush it coordinates coordinate position
ISOM diamond diamond center is located. Is surrounded by four diamond
ISOM involved in the brush, that the coordinates of the lower right side
of the diamond.
*/
pos.x = tile_pos->x / 2;
pos.y = tile_pos->y;
/* Whether out of bounds */
if (pos.x >= CALC_ISOM_ROW(map->size.cx) || pos.y >= CALC_ISOM_LINE(map->size.cy))
return FALSE;
/* Brush center where the diamond must be even diamond */
if (pos.x % 2 ^ pos.y % 2)
return FALSE;
/* Isometric brush handle */
return isometric_brush(map, brush, &pos);
}
BOOL update_iso_map(CONST ISOM_MAP *map)
{
#ifndef NDEBUG
FILE *fp;
LTILEPTR tile;
#endif
INT row, line, size;
POINT pos;
ISOM_TILE *isom;
/* If not then fail to initialize */
if (!g_InitFlag)
return FALSE;
/* Parameters validity check */
if (!validate_iso_map(map, FALSE))
return FALSE;
/* ISOM ranks calculation */
row = CALC_ISOM_ROW(map->size.cx);
line = CALC_ISOM_LINE(map->size.cy);
/* TILE mapping table memory allocation */
size = line * row * sizeof(ISOM_TILE);
isom = DAlloc(size);
DMemClr(isom, size);
/* TILE first generate a rough map */
for (pos.y = 0; pos.y < line; pos.y++) {
for (pos.x = 0; pos.x < row; pos.x++)
make_tile_map(map, &pos, isom);
}
/* Re-adjust the dirty flag map based on the mapping table TILE */
for (pos.y = 0; pos.y < line; pos.y++) {
for (pos.x = 0; pos.x < row; pos.x++)
adjust_dirty_map(map, &pos, isom);
}
/* Due to the random number used below, so in this initialization */
DInitRand();
/* TILE type generated correction mapping table above, and then find the actual look-up table corresponding TILE */
for (pos.y = 0; pos.y < line; pos.y++) {
for (pos.x = 0; pos.x < row; pos.x++)
update_tile(map, &pos, isom);
}
#ifndef NDEBUG
tile = map->tile;
fp = fopen("isom\\temp.cv5.txt", "w");
if (fp) {
for (pos.y = 0; pos.y < line; pos.y++) {
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t%02X\t\t", LOC_MAP_POS(isom, &pos, &map->size)->top_abut);
fputc('\n', fp);
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "%02X\t%02X\t%02X\t",
LOC_MAP_POS(isom, &pos, &map->size)->left_abut,
LOC_MAP_POS(isom, &pos, &map->size)->type,
LOC_MAP_POS(isom, &pos, &map->size)->right_abut
);
fputc('\n', fp);
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t%02X\t\t", LOC_MAP_POS(isom, &pos, &map->size)->bottom_abut);
fputc('\n', fp);
}
fclose(fp);
}
fp = fopen("isom\\temp.isom.txt", "w");
if (fp) {
for (pos.y = 0; pos.y < line; pos.y++) {
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t%02X\t\t", LOC_MAP_POS(map->isom, &pos, &map->size)->top.isom);
fputc('\n', fp);
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "%02X\t\t%02X\t",
LOC_MAP_POS(map->isom, &pos, &map->size)->left.isom,
LOC_MAP_POS(map->isom, &pos, &map->size)->right.isom
);
fputc('\n', fp);
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t%02X\t\t", LOC_MAP_POS(map->isom, &pos, &map->size)->bottom.isom);
fputc('\n', fp);
}
fclose(fp);
}
fp = fopen("isom\\temp.tile.txt", "w");
if (fp) {
for (pos.y = 0; pos.y < line; pos.y++) {
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t\t\t");
fputc('\n', fp);
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t%04X\t\t", tile[pos.y*map->size.cx+pos.x*2].group_no);
fputc('\n', fp);
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t\t\t");
fputc('\n', fp);
}
fclose(fp);
}
fp = fopen("isom\\temp.cliff.txt", "w");
if (fp) {
for (pos.y = 0; pos.y < line; pos.y++) {
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t%d\t\t", LOC_MAP_POS(isom, &pos, &map->size)->up_abut);
fputc('\n', fp);
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t\t\t");
fputc('\n', fp);
for (pos.x = 0; pos.x < row; pos.x++)
fprintf(fp, "\t%d\t\t", LOC_MAP_POS(isom, &pos, &map->size)->down_abut);
fputc('\n', fp);
}
fclose(fp);
}
#endif
DFree(isom);
size = CALC_DIRTY_SIZE(&map->size);
DMemClr(map->dirty, size);
return TRUE;
}
/************************************************************************/
static BOOL validate_iso_map(CONST ISOM_MAP *map, BOOL create)
{
INT row, line;
if (!map || !DBetween(map->era, 0, L_ERA_NUM))
return FALSE;
if (map->size.cx < 0)
return FALSE;
if (map->size.cy < 0)
return FALSE;
row = CALC_ISOM_ROW(map->size.cx);
line = CALC_ISOM_LINE(map->size.cy);
if (create)
return TRUE;
if (!map->isom || !map->tile || !g_EraInfo[map->era].init_flag)
return FALSE;
if (!DBetween(map->def, 0, g_EraInfo[map->era].center_num))
return FALSE;
return TRUE;
}
static BOOL check_pos(CONST ISOM_MAP *map, CONST POINT *pos)
{
DAssert(map && pos);
if (!DBetween(pos->x, 0, CALC_ISOM_ROW(map->size.cx)))
return FALSE;
if (!DBetween(pos->y, 0, CALC_ISOM_LINE(map->size.cy)))
return FALSE;
return TRUE;
}
static VOID calc_corner_pos(INT from, CONST POINT *base, POINT *corner)
{
DAssert(DBetween(from, 0, FROM_NUM) && base && corner);
/*
Brush the parties calculate the coordinates of diamond bits, complete the following map:
from corner.x corner.y
LEFT_TOP base.x - 1 base.y - 1
TOP_RIGHT base.x base.y - 1
RIGHT_BOTTOM base.x base.y
BOTTOM_LEFT base.x - 1 base.y
*/
corner->x = IS_FROM_DIR(from, LEFT) ? base->x - 1 : base->x;
corner->y = IS_FROM_DIR(from, TOP) ? base->y - 1 : base->y;
}
static VOID calc_link_pos(INT from, CONST POINT *base, POINT *link)
{
DAssert(DBetween(from, 0, FROM_NUM) && base && link);
/*
Computing center coordinates brush connection, complete the following map:
from link.x link.y
LEFT_TOP base.x - 1 base.y - 1
TOP_RIGHT base.x + 1 base.y - 1
RIGHT_BOTTOM base.x + 1 base.y + 1
BOTTOM_LEFT base.x - 1 base.y + 1
*/
link->x = IS_FROM_DIR(from, LEFT) ? base->x - 1 : base->x + 1;
link->y = IS_FROM_DIR(from, TOP) ? base->y - 1 : base->y + 1;
}
static WORD get_center_isom(INT era, INT center)
{
DAssert(DBetween(era, 0, L_ERA_NUM) && g_EraInfo[era].init_flag);
DAssert(DBetween(center, 0, g_EraInfo[era].center_num));
return PARAM_TABLE[era].center[center].isom;
}
static WORD get_edge_isom(INT era, INT edge, INT shape)
{
DAssert(DBetween(era, 0, L_ERA_NUM) && g_EraInfo[era].init_flag);
DAssert(DBetween(edge, 0, g_EraInfo[era].edge_num));
DAssert(DBetween(shape, 0, SHAPE_NUM));
return PARAM_TABLE[era].edge_start + edge * SHAPE_NUM + shape;
}
static INT isom_to_center(INT era, WORD isom)
{
INT center;
DAssert(DBetween(era, 0, L_ERA_NUM) && g_InitFlag);
DAssert(g_EraInfo[era].init_flag);
if (isom >= PARAM_TABLE[era].edge_start)
return -1;
if (isom >= MAX_CENTER_ISOM)
return -1;
center = g_Isom2Center[era][isom];
if (center < 0)
return -1;
return center;
}
static BOOL isom_to_edge_shape(INT era, WORD isom, INT *edge, INT *shape)
{
DAssert(edge && shape);
DAssert(DBetween(era, 0, L_ERA_NUM) && g_InitFlag);
DAssert(g_EraInfo[era].init_flag);
*edge = -1;
*shape = -1;
if (isom < PARAM_TABLE[era].edge_start)
return FALSE;
*edge = (isom - PARAM_TABLE[era].edge_start) / SHAPE_NUM;
if (*edge >= g_EraInfo[era].edge_num) {
*edge = -1;
return FALSE;
}
*shape = (isom - PARAM_TABLE[era].edge_start) % SHAPE_NUM;
return TRUE;
}
static INT shape_to_index(INT left, INT top, INT right, INT bottom)
{
INT shape;
DAssert(g_InitFlag);
shape = MAKE_SHAPE_ID(left, top, right, bottom);
if (!DBetween(shape, 0, MAX_SHAPE_ID))
return -1;
return g_Shape2Index[shape];
}
static BOOL isometric_brush(ISOM_MAP *map, INT brush, CONST POINT *pos)
{
INT from;
WORD isom;
POINT link_pos;
WORD update;
DAssert(map && pos);
/* Location queue initialization */
if (!init_pos_quene(pos))
return FALSE;
/* First obtain the corresponding central terrain brush ISOM value */
isom = get_center_isom(map->era, brush);
/* Update brush down position at the ISOM value */
for_each_from (from)
update_isom(map, isom, from, pos);
/* You must use a breadth-first */
while (!is_pos_quene_empty()) {
/* Get the coordinates of the current first team */
pos = peek_pos_quene();
DAssert(pos);
/* Get the current value ISOM */
isom = LOC_MAP_POS(map->isom, pos, &map->size)->left.isom;
DAssert(isom == LOC_MAP_POS(map->isom, pos, &map->size)->top.isom);
// TODO:
if (!isom)
continue;
/* The direction of the mating connector are on the periphery of four terrain */
for_each_from (from) {
/* Connecting terrain contour matching */
update = isometric_link(map, isom, from, pos);
if (!update)
continue;
/* Calculate the coordinates changed ISOM diamond, into a queue to be processed */
calc_link_pos(from, pos, &link_pos);
if (!push_pos_quene(&link_pos)) {
exit_pos_quene();
return FALSE;
}
}
/* After processing the current first team coordinates, the team */
DVerify(pop_pos_quene());
}
return TRUE;
}
static WORD isometric_link(ISOM_MAP *map, WORD isom, INT from, CONST POINT *pos)
{
INT opp, low, high, link_low, link_high, brush1, brush2, brush3, brush4;
WORD link, new_link;
POINT corner, link_pos;
LISOMPTR data;
INT shape[DIR_NUM], link_shape[DIR_NUM];
LISOMCOORD *tile;
CONST struct ERA_PARAM *param;
DAssert(map && pos && DBetween(from, 0, FROM_NUM));
/* Map out of bounds checking */
if (!check_pos(map, pos))
return 0;
calc_corner_pos(from, pos, &corner);
/* Map out of bounds checking */
if (!check_pos(map, &corner))
return 0;
data = LOC_MAP_POS(map->isom, &corner, &map->size);
tile = (LISOMCOORD *)&data->left;
/*
Get connection object ISOM value, the corresponding relationship is as follows:
from dir1 dir2
LEFT_TOP LEFT TOP
TOP_RIGHT TOP RIGHT
RIGHT_BOTTOM RIGHT BOTTOM
BOTTOM_LEFT BOTTOM LEFT
*/
link = tile[DIR1_OF_FROM(from)].isom;
DAssert(tile[DIR2_OF_FROM(from)].isom);
calc_link_pos(from, pos, &link_pos);
/* Map out of bounds checking */
if (!check_pos(map, &link_pos))
return 0;
if (!get_isom_shape(map->era, isom, &low, &high, shape))
return 0;
// TODO: ISOM connection target value may be 0, need to deal with!!
if (!get_isom_shape(map->era, link, &link_low, &link_high, link_shape)) {
DAssert(FALSE);
return 0;
}
param = &PARAM_TABLE[map->era];
opp = OPPOSITE(from);
/*
Here, as the correspondence between:
from brush1 brush2 link_brush1 link_brush2 link_brush3 link_brush4
LEFT_TOP LEFT TOP BOTTOM RIGHT LEFT TOP
TOP_RIGHT TOP RIGHT LEFT BOTTOM TOP RIGHT
RIGHT_BOTTOM RIGHT BOTTOM TOP LEFT RIGHT BOTTOM
BOTTOM_LEFT BOTTOM LEFT RIGHT TOP BOTTOM LEFT
*/
brush1 = shape[DIR1_OF_FROM(from)];
brush2 = shape[DIR2_OF_FROM(from)];
/*
For non-Matted terrain, terrain topography and connections if the
current boundaries of the target boundary agreement, then that can be
connected, you can not do any conversion termination; But for Matted
terrain, the terrain on the border if there is lower, then the
connection inside of the target terrain must also be consistent with
the job.
*/
/* First, to force the border can match */
link_shape[DIR2_OF_FROM(opp)] = brush1;
link_shape[DIR1_OF_FROM(opp)] = brush2;
/* If you connect the shape of the amended illegal, the core idea is based on the existing shape information, find two brush terrain can be connected with two brush to fill those incompatible diamond. */
/* Note that the brush1-4, which are arranged in counterclockwise order, so the mapping between 1-4,2-3. */
brush3 = link_shape[DIR2_OF_FROM(from)];
brush4 = link_shape[DIR1_OF_FROM(from)];
/*
If the boundary between two identical terrain, then brush1 (brush2) is
first selected. Because brush3 and brush4 must be connected to any of
them so long to establish a connection relationship from brush1, Select
from brush1 recent topographical terrain as another candidate to fill
the existing brush3 and brush4 on its connection to the chain.
*/
brush4 = search_brush_link(map->era, brush1, brush4);
brush3 = search_brush_link(map->era, brush2, brush3);
/* TODO: comment */
if (brush1 != brush2) {
if (brush4 != brush2)
brush4 = brush1;
if (brush3 != brush1)
brush3 = brush2;
}
link_shape[DIR2_OF_FROM(from)] = brush3;
link_shape[DIR1_OF_FROM(from)] = brush4;
/*
Matted terrain handling.
First, the current brush diamond lower and upper edges of the terrain
is not the same means, they will not need to do Matted terrain handling.
If the current brush is Matted senior diamond terrain, while the
direction of the current brush close connection to the lower side of
the terrain topography, It must be handled as follows
*/
if (low != high) {
if (param->center[high].style == S_MATTED) {
if (brush1 == low && link_shape[DIR1_OF_FROM(from)] != high)
link_shape[DIR1_OF_FROM(from)] = low;
if (brush2 == low && link_shape[DIR2_OF_FROM(from)] != high)
link_shape[DIR2_OF_FROM(from)] = low;
} else {
brush4 = link_shape[DIR1_OF_FROM(from)];
brush3 = link_shape[DIR2_OF_FROM(from)];
if (param->center[brush1].style != S_MATTED && param->center[brush4].style == S_MATTED && shape[DIR2_OF_FROM(opp)] != brush4)
link_shape[DIR1_OF_FROM(from)] = brush1;
if (param->center[brush2].style != S_MATTED && param->center[brush3].style == S_MATTED && shape[DIR1_OF_FROM(opp)] != brush3)
link_shape[DIR2_OF_FROM(from)] = brush2;
}
}
/*
Boundary special treatment. Beyond the borders of the diamond shape with
its mandatory that same diamond shape recently the expansion direction.
from x x-equ y y-equ
LEFT_TOP LEFT BOTTOM TOP RIGHT
TOP_RIGHT RIGHT BOTTOM TOP LEFT
RIGHT_BOTTOM RIGHT TOP BOTTOM LEFT
BOTTOM_LEFT LEFT TOP BOTTOM RIGHT
*/
if (link_shape[DIR1_OF_FROM(opp)] != link_shape[DIR2_OF_FROM(opp)]) {
calc_corner_pos(from, &link_pos, &corner);
if (!DBetween(corner.x, 0, CALC_ISOM_ROW(map->size.cx)))
link_shape[X_DIR_OF_FROM(from)] = link_shape[Y_DIR_OF_FROM(opp)];
if (!DBetween(corner.y, 0, CALC_ISOM_LINE(map->size.cy)))
link_shape[Y_DIR_OF_FROM(from)] = link_shape[X_DIR_OF_FROM(opp)];
}
/* If the change did not occur before the connection ISOM value corresponding to the shape corrected, do nothing */
new_link = match_shape(map->era, link_shape);
if (new_link == link)
return 0;
DAssert(new_link);
/* ISOM produce a new value is updated by its brush diamond */
for_each_from (from)
update_isom(map, new_link, from, &link_pos);
return new_link;
}
static BOOL update_isom(ISOM_MAP *map, WORD isom, INT from, CONST POINT *pos)
{
INT opp;
POINT corner;
LISOMPTR data;
LISOMCOORD *coord[DIR_NUM];
DAssert(map && pos && DBetween(from, 0, FROM_NUM));
/* Calculating the coordinates of the corner of the diamond on the specified direction */
calc_corner_pos(from, pos, &corner);
/* Set TILE diamond position */
if (!set_tile_pos(map, &corner))
return FALSE;
data = LOC_MAP_POS(map->isom, &corner, &map->size);
coord[LEFT] = &data->left;
coord[TOP] = &data->top;
coord[RIGHT] = &data->right;
coord[BOTTOM] = &data->bottom;
/* TILE diamond mark as dirty */
SET_DIRTY(map->dirty, &corner, &map->size);
/* To brush it might be the upper left corner, but the ISOM diamond is really a diamond in the lower right corner of the upper left corner, so in this first obtained from the opposite direction */
opp = OPPOSITE(from);
/*
ISOM filling corresponding value, the corresponding relationship is as follows:
from opp dir1 dir2
LEFT_TOP RIGHT_BOTTOM RIGHT BOTTOM
TOP_RIGHT BOTTOM_LEFT BOTTOM LEFT
RIGHT_BOTTOM LEFT_TOP LEFT TOP
BOTTOM_LEFT TOP_RIGHT TOP RIGHT
*/
coord[DIR1_OF_FROM(opp)]->isom = isom;
coord[DIR2_OF_FROM(opp)]->isom = isom;
return TRUE;
}
static BOOL set_tile_pos(ISOM_MAP *map, CONST POINT *pos)
{
LISOMPTR data;
CONST WORD *tile_pos;
DAssert(map && pos);
/* Out of Bounds checking */
if (!check_pos(map, pos))
return FALSE;
/* According to the parity of the set position value */
tile_pos = ((pos->x + pos->y) & 0x01) ? TILE_POS_EVEN : TILE_POS_ODD;