/* Ensure that map heights of adjacent fields are not too far apart. */ static void clamp_map_heights() { map_tile_t *tiles = game.map.tiles; int changed = 1; while (changed) { changed = 0; for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { map_pos_t pos = MAP_POS(x, y); int h = tiles[pos].height; map_pos_t pos_d = MAP_MOVE_DOWN(pos); int h_d = tiles[pos_d].height; changed |= adjust_map_height(h, h_d, &tiles[pos_d]); map_pos_t pos_dr = MAP_MOVE_DOWN_RIGHT(pos); int h_dr = tiles[pos_dr].height; changed |= adjust_map_height(h, h_dr, &tiles[pos_dr]); map_pos_t pos_r = MAP_MOVE_RIGHT(pos); int h_r = tiles[pos_r].height; changed |= adjust_map_height(h, h_r, &tiles[pos_r]); } } } }
static void draw_minimap_buildings(minimap_t *minimap, frame_t *frame) { const int building_remap[] = { BUILDING_CASTLE, BUILDING_STOCK, BUILDING_TOWER, BUILDING_HUT, BUILDING_FORTRESS, BUILDING_TOOLMAKER, BUILDING_SAWMILL, BUILDING_WEAPONSMITH, BUILDING_STONECUTTER, BUILDING_BOATBUILDER, BUILDING_FORESTER, BUILDING_LUMBERJACK, BUILDING_PIGFARM, BUILDING_FARM, BUILDING_FISHER, BUILDING_MILL, BUILDING_BUTCHER, BUILDING_BAKER, BUILDING_STONEMINE, BUILDING_COALMINE, BUILDING_IRONMINE, BUILDING_GOLDMINE, BUILDING_STEELSMELTER, BUILDING_GOLDSMELTER }; for (int row = 0; row < game.map.rows; row++) { for (int col = 0; col < game.map.cols; col++) { int pos = MAP_POS(col, row); int obj = MAP_OBJ(pos); if (obj > MAP_OBJ_FLAG && obj <= MAP_OBJ_CASTLE) { int color = game.player[MAP_OWNER(pos)]->color; if (minimap->advanced > 0) { building_t *bld = game_get_building(MAP_OBJ_INDEX(pos)); if (BUILDING_TYPE(bld) == building_remap[minimap->advanced]) { draw_minimap_point(minimap, col, row, color, minimap->scale, frame); } } else { draw_minimap_point(minimap, col, row, color, minimap->scale, frame); } } } } }
int gui_take(t_server *server, t_client *graphic, t_client *client, t_gui_arg *arg) { int i; t_string **map; t_player *pl; map = server->world.map; pl = client->player; i = MAP_POS(pl->x, pl->y, server->world.width); queue_push_message(&graphic->queue, "pgt %d %d\n", pl->id, arg->id); queue_push_message(&graphic->queue, "pin %d %d %d %d %d %d %d %d %d %d\n", pl->id, pl->x, pl->y, pl->inventory[0], pl->inventory[1], pl->inventory[2], pl->inventory[3], pl->inventory[4], pl->inventory[5], pl->inventory[6]); queue_push_message(&graphic->queue, "bct %d %d %d %d %d %d %d %d %d\n", pl->x, pl->y, count_resource(map[i], FOOD), count_resource(map[i], LINEMATE), count_resource(map[i], DERAUMERE), count_resource(map[i], SIBUR), count_resource(map[i], MENDIANE), count_resource(map[i], PHIRAS), count_resource(map[i], THYSTAME)); return (0); }
/* Calculate height values of the subdivisions in the midpoint displacement algorithm. */ static void init_map_heights_midpoints() { map_tile_t *tiles = game.map.tiles; /* This is the central part of the midpoint displacement algorithm. The initial 16x16 squares are subdivided into 8x8 then 4x4 and so on, until all positions in the map have a height value. The random offset applied to the midpoints is based on r1 and r2. The offset is a random value in [-r2; r1-r2). r1 controls the roughness of the terrain; a larger value of r1 will result in rough terrain while a smaller value will generate smoother terrain. A high spikyness will result in sharp mountains and smooth valleys. A low spikyness will result in smooth mountains and sharp valleys. */ int rnd = game_random_int(); int r1 = 0x80 + (rnd & 0x7f); int r2 = (r1 * TERRAIN_SPIKYNESS) >> 16; for (int i = 8; i > 0; i >>= 1) { for (int y = 0; y < game.map.rows; y += 2*i) { for (int x = 0; x < game.map.cols; x += 2*i) { map_pos_t pos = MAP_POS(x, y); int h = tiles[pos].height; map_pos_t pos_r = MAP_MOVE_RIGHT_N(pos, 2*i); map_pos_t pos_mid_r = MAP_MOVE_RIGHT_N(pos, i); int h_r = tiles[pos_r].height; if (game.map_preserve_bugs) { /* The intention was probably just to set h_r to the map height value, but the upper bits of rnd must be preserved in h_r in the first iteration to generate the same maps as the original game. */ if (x == 0 && y == 0 && i == 8) h_r |= rnd & 0xff00; } tiles[pos_mid_r].height = calc_height_displacement((h + h_r)/2, r1, r2); map_pos_t pos_d = MAP_MOVE_DOWN_N(pos, 2*i); map_pos_t pos_mid_d = MAP_MOVE_DOWN_N(pos, i); int h_d = tiles[pos_d].height; tiles[pos_mid_d].height = calc_height_displacement((h+h_d)/2, r1, r2); map_pos_t pos_dr = MAP_MOVE_RIGHT_N(MAP_MOVE_DOWN_N(pos, 2*i), 2*i); map_pos_t pos_mid_dr = MAP_MOVE_RIGHT_N(MAP_MOVE_DOWN_N(pos, i), i); int h_dr = tiles[pos_dr].height; tiles[pos_mid_dr].height = calc_height_displacement((h+h_dr)/2, r1, r2); } } r1 >>= 1; r2 >>= 1; } }
/* Return a random map position. Returned as map_pos_t and also as col and row if not NULL. */ static map_pos_t get_rnd_map_coord(int *col, int *row) { int c = game_random_int() & game.map.col_mask; int r = game_random_int() & game.map.row_mask; if (col != NULL) *col = c; if (row != NULL) *row = r; return MAP_POS(c, r); }
/* Create level land that will later be filled with water. It is created in areas that are below a certain threshold. The areas are also limited in size. */ static void map_init_sea_level() { map_tile_t *tiles = game.map.tiles; if (game.map_water_level < 0) return; for (int h = 0; h <= game.map_water_level; h++) { for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { map_pos_t pos = MAP_POS(x, y); if (tiles[pos].height == h) { map_init_level_area(tiles, pos); } } } } /* Map positions are marked in the previous loop. 0: Above water level. 252: Land at water level. 253: Water. */ for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { map_pos_t pos = MAP_POS(x, y); int h = tiles[pos].height; switch (h) { case 0: tiles[pos].height = game.map_water_level + 1; break; case 252: tiles[pos].height = game.map_water_level; break; case 253: tiles[pos].height = game.map_water_level - 1; tiles[pos].u.resource = game_random_int() & 7; /* Fish */ break; } } } }
map_pos_t minimap_map_pos_from_screen_pix(minimap_t *minimap, int x, int y) { int mx = x + minimap->offset_x; int my = y + minimap->offset_y; int col = ((my/2 + mx)/minimap->scale) & game.map.col_mask; int row = (my/minimap->scale) & game.map.row_mask; return MAP_POS(col, row); }
static void init_map_types_2_sub() { map_tile_t *tiles = game.map.tiles; for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { tiles[MAP_POS(x, y)].obj = 0; } } }
/* Midpoint displacement map generator. This function initialises the height values in the corners of 16x16 squares. */ static void init_map_heights_squares() { map_tile_t *tiles = game.map.tiles; for (int y = 0; y < game.map.rows; y += 16) { for (int x = 0; x < game.map.cols; x += 16) { int rnd = game_random_int() & 0xff; tiles[MAP_POS(x,y)].height = min(rnd, 250); } } }
/* Rescale height values to be in [0;31]. */ static void map_heights_rescale() { map_tile_t *tiles = game.map.tiles; for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { map_pos_t pos = MAP_POS(x, y); tiles[pos].height = (tiles[pos].height + 6) >> 3; } } }
/* Adjust heights so zero height is sea level. */ static void map_heights_rebase() { map_tile_t *tiles = game.map.tiles; int h = game.map_water_level - 1; for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { tiles[MAP_POS(x, y)].height -= h; } } }
static void draw_minimap_roads(minimap_t *minimap, frame_t *frame) { for (int row = 0; row < game.map.rows; row++) { for (int col = 0; col < game.map.cols; col++) { int pos = MAP_POS(col, row); if (MAP_PATHS(pos)) { draw_minimap_point(minimap, col, row, 1, minimap->scale, frame); } } } }
static void draw_minimap_traffic(minimap_t *minimap, frame_t *frame) { for (int row = 0; row < game.map.rows; row++) { for (int col = 0; col < game.map.cols; col++) { int pos = MAP_POS(col, row); if (MAP_IDLE_SERF(pos)) { int color = game.player[MAP_OWNER(pos)]->color; draw_minimap_point(minimap, col, row, color, minimap->scale, frame); } } } }
static void draw_minimap_ownership(minimap_t *minimap, int density, frame_t *frame) { for (int row = 0; row < game.map.rows; row++) { for (int col = 0; col < game.map.cols; col++) { map_pos_t pos = MAP_POS(col, row); if (MAP_HAS_OWNER(pos)) { int color = game.player[MAP_OWNER(pos)]->color; draw_minimap_point(minimap, col, row, color, density, frame); } } } }
void MapManager::initMaps() { XMLFile doc("data/config/maps.xml"); XMLElement *areasElement = doc.FirstChildElement("maps").ToElement(); XMLElement *areaElement = areasElement->FirstChildElement("area"); u16 areaID = 0; while(areaElement) { XMLElement *mapElement = areaElement->FirstChildElement("map"); std::vector<Map*> currentArea; while(mapElement) { std::stringstream mapFilename; u8 layers; u16 x, y, tilesetID; layers = mapElement->IntAttribute("layers"); x = mapElement->IntAttribute("x"); y = mapElement->IntAttribute("y"); tilesetID = mapElement->IntAttribute("tilesetID"); mapFilename << "data/maps/map" << areaID << "-" << x << "-" << y << ".tmx"; currentArea.push_back(new Map(mapFilename.str().c_str(), x, y, areaID, layers, tilesetID)); currentArea.back()->setBattleback(new Image(std::string(std::string("graphics/battlebacks/") + mapElement->Attribute("battleback") + ".jpg").c_str())); XMLElement *eventElement = mapElement->FirstChildElement("event"); while(eventElement) { currentArea.back()->addEvent(EventManager::getEventByName(eventElement->Attribute("name"))); eventElement = eventElement->NextSiblingElement("event"); } mapElement = mapElement->NextSiblingElement("map"); } maps.push_back(currentArea); areaID++; areaElement = areaElement->NextSiblingElement("area"); } u16 startarea = areasElement->IntAttribute("startarea"); u16 startx = areasElement->IntAttribute("startx"); u16 starty = areasElement->IntAttribute("starty"); currentMap = maps[startarea][MAP_POS(startarea, startx, starty)]; }
/* Set type of map fields based on the height value. */ static void init_map_types() { map_tile_t *tiles = game.map.tiles; for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { map_pos_t pos = MAP_POS(x, y); int h1 = tiles[pos].height; int h2 = tiles[MAP_MOVE_RIGHT(pos)].height; int h3 = tiles[MAP_MOVE_DOWN_RIGHT(pos)].height; int h4 = tiles[MAP_MOVE_DOWN(pos)].height; tiles[pos].type = (calc_map_type(h1 + h3 + h4) << 4) | calc_map_type(h1 + h2 + h3); } } }
static void draw_minimap_traffic(minimap_t *minimap, frame_t *frame) { const int player_colors[] = { 64, 72, 68, 76 }; for (int row = 0; row < game.map.rows; row++) { for (int col = 0; col < game.map.cols; col++) { int pos = MAP_POS(col, row); if (MAP_IDLE_SERF(pos)) { int color = player_colors[MAP_OWNER(pos)]; draw_minimap_point(minimap, col, row, color, minimap->scale, frame); } } } }
static void draw_minimap_ownership(minimap_t *minimap, int density, frame_t *frame) { const int player_colors[] = { 64, 72, 68, 76 }; for (int row = 0; row < game.map.rows; row++) { for (int col = 0; col < game.map.cols; col++) { map_pos_t pos = MAP_POS(col, row); if (MAP_HAS_OWNER(pos)) { int color = player_colors[MAP_OWNER(pos)]; draw_minimap_point(minimap, col, row, color, density, frame); } } } }
static void init_map_types_2() { init_map_types_2_sub(); map_tile_t *tiles = game.map.tiles; for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { map_pos_t pos = MAP_POS(x, y); if (tiles[pos].height > 0) { tiles[pos].obj = 1; int num = 0; int changed = 1; while (changed) { changed = 0; for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { map_pos_t pos = MAP_POS(x, y); if (tiles[pos].obj == 1) { num += 1; tiles[pos].obj = 2; int flags = 0; if (tiles[pos].type & 0xc) flags |= 3; if (tiles[pos].type & 0xc0) flags |= 6; if (tiles[MAP_MOVE_LEFT(pos)].type & 0xc) flags |= 0xc; if (tiles[MAP_MOVE_UP_LEFT(pos)].type & 0xc0) flags |= 0x18; if (tiles[MAP_MOVE_UP_LEFT(pos)].type & 0xc) flags |= 0x30; if (tiles[MAP_MOVE_UP(pos)].type & 0xc0) flags |= 0x21; for (dir_t d = DIR_RIGHT; d <= DIR_UP; d++) { if (BIT_TEST(flags, d)) { if (tiles[MAP_MOVE(pos, d)].obj == 0) { tiles[MAP_MOVE(pos, d)].obj = 1; changed = 1; } } } } } } } if (4*num >= game.map.tile_count) goto break_loop; } } } break_loop: for (int y = 0; y < game.map.rows; y++) { for (int x = 0; x < game.map.cols; x++) { map_pos_t pos = MAP_POS(x, y); if (tiles[pos].height > 0 && tiles[pos].obj == 0) { tiles[pos].height = 0; tiles[pos].type = 0; tiles[MAP_MOVE_LEFT(pos)].type &= 0xf0; tiles[MAP_MOVE_UP_LEFT(pos)].type = 0; tiles[MAP_MOVE_UP(pos)].type &= 0xf; } } } init_map_types_2_sub(); }
static void init_map_heights_diamond_square() { map_tile_t *tiles = game.map.tiles; /* This is the central part of the diamond-square algorithm. The squares are first subdivided into four new squares and the height of the midpoint is calculated by averaging the corners and adding a random offset. Each "diamond" that appears is then processed in the same way. The random offset applied to the midpoints is based on r1 and r2. The offset is a random value in [-r2; r1-r2). r1 controls the roughness of the terrain; a larger value of r1 will result in rough terrain while a smaller value will generate smoother terrain. A high spikyness will result in sharp mountains and smooth valleys. A low spikyness will result in smooth mountains and sharp valleys. */ int rnd = game_random_int(); int r1 = 0x80 + (rnd & 0x7f); int r2 = (r1 * TERRAIN_SPIKYNESS) >> 16; for (int i = 8; i > 0; i >>= 1) { /* Diamond step */ for (int y = 0; y < game.map.rows; y += 2*i) { for (int x = 0; x < game.map.cols; x += 2*i) { map_pos_t pos = MAP_POS(x, y); int h = tiles[pos].height; map_pos_t pos_r = MAP_MOVE_RIGHT_N(pos, 2*i); int h_r = tiles[pos_r].height; map_pos_t pos_d = MAP_MOVE_DOWN_N(pos, 2*i); int h_d = tiles[pos_d].height; map_pos_t pos_dr = MAP_MOVE_RIGHT_N(MAP_MOVE_DOWN_N(pos, 2*i), 2*i); int h_dr = tiles[pos_dr].height; map_pos_t pos_mid_dr = MAP_MOVE_RIGHT_N(MAP_MOVE_DOWN_N(pos, i), i); int avg = (h + h_r + h_d + h_dr) / 4; tiles[pos_mid_dr].height = calc_height_displacement(avg, r1, r2); } } /* Square step */ for (int y = 0; y < game.map.rows; y += 2*i) { for (int x = 0; x < game.map.cols; x += 2*i) { map_pos_t pos = MAP_POS(x, y); int h = tiles[pos].height; map_pos_t pos_r = MAP_MOVE_RIGHT_N(pos, 2*i); int h_r = tiles[pos_r].height; map_pos_t pos_d = MAP_MOVE_DOWN_N(pos, 2*i); int h_d = tiles[pos_d].height; map_pos_t pos_ur = MAP_MOVE_RIGHT_N(MAP_MOVE_DOWN_N(pos, -i), i); int h_ur = tiles[pos_ur].height; map_pos_t pos_dr = MAP_MOVE_RIGHT_N(MAP_MOVE_DOWN_N(pos, i), i); int h_dr = tiles[pos_dr].height; map_pos_t pos_dl = MAP_MOVE_RIGHT_N(MAP_MOVE_DOWN_N(pos, i), -i); int h_dl = tiles[pos_dl].height; map_pos_t pos_mid_r = MAP_MOVE_RIGHT_N(pos, i); int avg_r = (h + h_r + h_ur + h_dr) / 4; tiles[pos_mid_r].height = calc_height_displacement(avg_r, r1, r2); map_pos_t pos_mid_d = MAP_MOVE_DOWN_N(pos, i); int avg_d = (h + h_d + h_dl + h_dr) / 4; tiles[pos_mid_d].height = calc_height_displacement(avg_d, r1, r2); } } r1 >>= 1; r2 >>= 1; } }