Index: trunk/bauer/hausbauer.cc =================================================================== --- trunk/bauer/hausbauer.cc (revision 8738) +++ trunk/bauer/hausbauer.cc (working copy) @@ -67,6 +67,9 @@ }; +sint16 hausbauer_t::largest_city_building_area = 1; + + /** * Compares house descriptors. * Order of comparison: @@ -141,12 +144,30 @@ // now insert the desc into the correct list. switch(desc->get_type()) { case building_desc_t::city_res: + if( desc->get_x()*desc->get_y() > 9 ) { + dbg->fatal( "hausbauer_t::successfully_loaded()", "maximum city building size (3x3) but %s is (%sx%i)", desc->get_name(), desc->get_x(), desc->get_y() ); + } + if( desc->get_x()*desc->get_y() > largest_city_building_area ) { + largest_city_building_area = desc->get_x()*desc->get_y(); + } city_residential.insert_ordered(desc,compare_building_desc); break; case building_desc_t::city_ind: + if( desc->get_x()*desc->get_y() > 9 ) { + dbg->fatal( "hausbauer_t::successfully_loaded()", "maximum city building size (3x3) but %s is (%sx%i)", desc->get_name(), desc->get_x(), desc->get_y() ); + } + if( desc->get_x()*desc->get_y() > largest_city_building_area ) { + largest_city_building_area = desc->get_x()*desc->get_y(); + } city_industry.insert_ordered(desc,compare_building_desc); break; case building_desc_t::city_com: + if( desc->get_x()*desc->get_y() > 9 ) { + dbg->fatal( "hausbauer_t::successfully_loaded()", "maximum city building size (3x3) but %s is (%sx%i)", desc->get_name(), desc->get_x(), desc->get_y() ); + } + if( desc->get_x()*desc->get_y() > largest_city_building_area ) { + largest_city_building_area = desc->get_x()*desc->get_y(); + } city_commercial.insert_ordered(desc,compare_building_desc); break; @@ -814,15 +835,20 @@ * @param level the minimum level of the house/station * @param cl allowed climates */ -static const building_desc_t* get_city_building_from_list(const vector_tpl& list, int level, uint16 time, climate cl, uint32 clusters ) +static const building_desc_t* get_city_building_from_list(const vector_tpl& list, int level, uint16 time, climate cl, uint32 clusters, koord minsize, koord maxsize ) { weighted_vector_tpl selections(16); + sint16 area = maxsize.x*maxsize.y; + sint16 minarea = minsize.x*minsize.y; // DBG_MESSAGE("hausbauer_t::get_aus_liste()","target level %i", level ); const building_desc_t *desc_at_least=NULL; FOR(vector_tpl, const desc, list) { - if( desc->is_allowed_climate(cl) && desc->get_distribution_weight()>0 && desc->is_available(time) ) { + if( desc->is_allowed_climate(cl) && desc->get_distribution_weight()>0 && desc->is_available(time) && desc->get_x()*desc->get_y()<=area && desc->get_x()*desc->get_y()>=minarea ) { + // size check + if( (desc->get_x() <= maxsize.x || desc->get_y() <= maxsize.x) && (desc->get_x() >= minsize.x || desc->get_y() >= minsize.x) ) { desc_at_least = desc; + } } const int thislevel = desc->get_level(); @@ -840,22 +866,28 @@ if( thislevel == level && desc->get_distribution_weight() > 0 ) { if( cl==MAX_CLIMATES || desc->is_allowed_climate(cl) ) { if( desc->is_available(time) ) { -// DBG_MESSAGE("hausbauer_t::get_city_building_from_list()","appended %s at %i", desc->get_name(), thislevel ); - /* Level, time period, and climate are all OK. - * Now modify the chance rating by a factor based on the clusters. - */ - // FIXME: the factor should be configurable by the pakset/ - int chance = desc->get_distribution_weight(); - if( clusters ) { - uint32 my_clusters = desc->get_clusters(); - if( my_clusters & clusters ) { - chance *= stadt_t::get_cluster_factor(); + // not too big? + if( desc->get_x()*desc->get_y()<=area && ( desc->get_x() <= maxsize.x || desc->get_y() <= maxsize.x ) ) { + // or too small + if( desc->get_x()*desc->get_y()>=area && ( desc->get_x() >= minsize.x || desc->get_y() >= minsize.x ) ) { + // DBG_MESSAGE("hausbauer_t::get_city_building_from_list()","appended %s at %i", desc->get_name(), thislevel ); + /* Level, time period, and climate are all OK. + * Now modify the chance rating by a factor based on the clusters. + */ + // FIXME: the factor should be configurable by the pakset/ + int chance = desc->get_distribution_weight(); + if( clusters ) { + uint32 my_clusters = desc->get_clusters(); + if( my_clusters & clusters ) { + chance *= stadt_t::get_cluster_factor(); + } + else { + chance /= stadt_t::get_cluster_factor(); + } + } + selections.append(desc, chance); } - else { - chance /= stadt_t::get_cluster_factor(); - } } - selections.append(desc, chance); } } } @@ -873,21 +905,21 @@ } -const building_desc_t* hausbauer_t::get_commercial(int level, uint16 time, climate cl, uint32 clusters) +const building_desc_t* hausbauer_t::get_commercial(int level, uint16 time, climate cl, uint32 clusters, koord minsize, koord maxsize ) { - return get_city_building_from_list(city_commercial, level, time, cl, clusters); + return get_city_building_from_list(city_commercial, level, time, cl, clusters, minsize, maxsize ); } -const building_desc_t* hausbauer_t::get_industrial(int level, uint16 time, climate cl, uint32 clusters) +const building_desc_t* hausbauer_t::get_industrial(int level, uint16 time, climate cl, uint32 clusters, koord minsize, koord maxsize ) { - return get_city_building_from_list(city_industry, level, time, cl, clusters); + return get_city_building_from_list(city_industry, level, time, cl, clusters, minsize, maxsize ); } -const building_desc_t* hausbauer_t::get_residential(int level, uint16 time, climate cl, uint32 clusters) +const building_desc_t* hausbauer_t::get_residential(int level, uint16 time, climate cl, uint32 clusters, koord minsize, koord maxsize ) { - return get_city_building_from_list(city_residential, level, time, cl, clusters); + return get_city_building_from_list(city_residential, level, time, cl, clusters, minsize, maxsize ); } Index: trunk/bauer/hausbauer.h =================================================================== --- trunk/bauer/hausbauer.h (revision 8738) +++ trunk/bauer/hausbauer.h (working copy) @@ -30,6 +30,8 @@ class hausbauer_t { private: + static sint16 largest_city_building_area; + static vector_tpl attractions_land; ///< Sights outside of cities static vector_tpl attractions_city; ///< Sights within cities static vector_tpl townhalls; ///< Town halls @@ -45,6 +47,8 @@ static karte_ptr_t welt; public: + static sint16 get_largest_city_building_area() { return largest_city_building_area; } + /// description for elevated monorail (mandatory description) static const building_desc_t* elevated_foundation_desc; @@ -78,13 +82,13 @@ static void fill_menu(tool_selector_t* tool_selector, building_desc_t::btype, waytype_t wt, sint16 sound_ok); /// @returns a random commercial building matching the requirements. - static const building_desc_t* get_commercial(int level, uint16 time, climate c, uint32 clusters = 0l); + static const building_desc_t* get_commercial(int level, uint16 time, climate c, uint32 clusters, koord minsize, koord maxsize ); /// @returns a random industrial building matching the requirements. - static const building_desc_t* get_industrial(int level, uint16 time, climate cl, uint32 clusters = 0); + static const building_desc_t* get_industrial(int level, uint16 time, climate cl, uint32 clusters, koord minsize, koord maxsize ); /// @returns a random residential building matching the requirements. - static const building_desc_t* get_residential(int level, uint16 time, climate cl, uint32 clusters = 0); + static const building_desc_t* get_residential(int level, uint16 time, climate cl, uint32 clusters, koord minsize, koord maxsize ); /// @returns headquarters with level @p level (takes the first matching one) static const building_desc_t* get_headquarters(int level, uint16 time); Index: trunk/obj/gebaeude.cc =================================================================== --- trunk/obj/gebaeude.cc (revision 8738) +++ trunk/obj/gebaeude.cc (working copy) @@ -778,9 +778,9 @@ switch(type) { case building_desc_t::city_res: { - const building_desc_t *bdsc = hausbauer_t::get_residential( level, welt->get_timeline_year_month(), welt->get_climate( get_pos().get_2d() ) ); + const building_desc_t *bdsc = hausbauer_t::get_residential( level, welt->get_timeline_year_month(), welt->get_climate( get_pos().get_2d() ), 0, koord(1,1), koord(1,1) ); if(bdsc==NULL) { - bdsc = hausbauer_t::get_residential(level,0, MAX_CLIMATES ); + bdsc = hausbauer_t::get_residential(level,0, MAX_CLIMATES, 0, koord(1,1), koord(1,1) ); } if( bdsc) { dbg->message("gebaeude_t::rwdr", "replace unknown building %s with residence level %i by %s",buf,level,bdsc->get_name()); @@ -791,9 +791,10 @@ case building_desc_t::city_com: { - const building_desc_t *bdsc = hausbauer_t::get_commercial( level, welt->get_timeline_year_month(), welt->get_climate( get_pos().get_2d() ) ); + // for replacement, ignore cluster and size + const building_desc_t *bdsc = hausbauer_t::get_commercial( level, welt->get_timeline_year_month(), welt->get_climate( get_pos().get_2d() ), 0, koord(1,1), koord(1,1) ); if(bdsc==NULL) { - bdsc = hausbauer_t::get_commercial(level,0, MAX_CLIMATES ); + bdsc = hausbauer_t::get_commercial(level, 0, MAX_CLIMATES, 0, koord(1,1), koord(1,1) ); } if(bdsc) { dbg->message("gebaeude_t::rwdr", "replace unknown building %s with commercial level %i by %s",buf,level,bdsc->get_name()); @@ -804,11 +805,11 @@ case building_desc_t::city_ind: { - const building_desc_t *bdsc = hausbauer_t::get_industrial( level, welt->get_timeline_year_month(), welt->get_climate( get_pos().get_2d() ) ); + const building_desc_t *bdsc = hausbauer_t::get_industrial( level, welt->get_timeline_year_month(), welt->get_climate( get_pos().get_2d() ), 0, koord(1,1), koord(1,1) ); if(bdsc==NULL) { - bdsc = hausbauer_t::get_industrial(level,0, MAX_CLIMATES ); + bdsc = hausbauer_t::get_industrial(level, 0, MAX_CLIMATES, 0, koord(1,1), koord(1,1) ); if(bdsc==NULL) { - bdsc = hausbauer_t::get_residential(level,0, MAX_CLIMATES ); + bdsc = hausbauer_t::get_residential(level, 0, MAX_CLIMATES, 0, koord(1,1), koord(1,1) ); } } if (bdsc) { Index: trunk/simcity.cc =================================================================== --- trunk/simcity.cc (revision 8738) +++ trunk/simcity.cc (working copy) @@ -2754,10 +2754,20 @@ koord(-1, -1) }; +static koord const area3x3[] = { + koord( 0, 1), // 1x2 + koord( 1, 0), // 2x1 + koord( 1, 1), // 2x2 + koord( 2, 0), // 3x1 + koord( 2, 1), // 3x2 + koord( 0, 2), // 1x3 + koord( 2, 2) // 3x3 +}; // updates one surrounding road with current city road bool update_city_street(koord pos) { +// !!! We should take the bulding size into consideration, missing!!! const way_desc_t* cr = world()->get_city_road(); for( int i=0; i<8; i++ ) { if( grund_t *gr = world()->lookup_kartenboden(pos+neighbors[i]) ) { @@ -2788,7 +2798,7 @@ // calculates the "best" oreintation of a citybuilding -int stadt_t::orient_city_building(const koord k, const building_desc_t *h ) +int stadt_t::orient_city_building(const koord k, const building_desc_t *h, koord maxsize ) { /******************************************************* * these are the layout possible for city buildings @@ -2823,6 +2833,13 @@ if( h == NULL ) { return -1; } + + // for large asszmetric building, we just allow one option depending of building size + if( h->get_x(0)!=h->get_y(0) ) { + return h->get_x(0) <= maxsize.x ? 0 : 1; + } + + // otherwise we can do a more sophisticated check if( grund_t *gr = welt->lookup_kartenboden(k) ) { int rotation = 0; int max_layout = h->get_all_layouts()-1; @@ -2877,7 +2894,6 @@ } - void stadt_t::build_city_building(const koord k) { grund_t* gr = welt->lookup_kartenboden(k); @@ -2915,41 +2931,91 @@ const uint16 current_month = welt->get_timeline_year_month(); const climate cl = welt->get_climate(k); + // Run through orthogonal neighbors (only) looking for which cluster to build // This is a bitmap -- up to 32 clustering types are allowed. uint32 neighbor_building_clusters = 0; + uint8 area_level=0; // used to calculate the maximum size + sint8 zpos = gr->get_pos().z + slope_t::max_diff(gr->get_grund_hang()); for( int i = 0; i < 4; i++ ) { grund_t* gr = welt->lookup_kartenboden(k + neighbors[i]); - if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) { + if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) { // We have a building as a neighbor... - gebaeude_t const* const gb = obj_cast(gr->first_obj()); - if( gb != NULL ) { + if( gebaeude_t const* const gb = obj_cast(gr->first_obj()) ) { // We really have a building as a neighbor... const building_desc_t* neighbor_building = gb->get_tile()->get_desc(); neighbor_building_clusters |= neighbor_building->get_clusters(); + if( gb->get_pos().z == zpos && neighbor_building->get_x()*neighbor_building->get_y()==1 ) { + // also in right height and citybuilding, and (1x1) (so we don not tear down existing larger building, even if we can do that) + area_level |= (neighbor_building->is_city_building() << i); + } } + else if( gr->ist_natur() && gr->get_pos().z+slope_t::max_diff(gr->get_grund_hang())==zpos ) { + // we can of course also build on nature + area_level |= (1 << i); + } } } + // since the above test is only enough for 2x1 and 1x2, we must test more tiles, if we want larger + koord maxsize=koord(1,1); + switch( area_level&3 ) { + case 3: + if( hausbauer_t::get_largest_city_building_area() > 2 ) { + // now test the remaining tiles for even laregr size + for( area_level=2; area_level < 8; area_level++ ) { + grund_t* gr = welt->lookup_kartenboden(k + area3x3[area_level]); + if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) { + // We have a building as a neighbor... + if( gebaeude_t const* const testgb = obj_cast(gr->first_obj()) ) { + // We really have a building as a neighbor... + const building_desc_t* neighbor_building = testgb->get_tile()->get_desc(); + if( testgb->get_pos().z == zpos && neighbor_building->is_city_building() && neighbor_building->get_x()*neighbor_building->get_y()==1 ) { + // also in right height and citybuilding + maxsize = area3x3[area_level]+koord(1,1); + continue; + } + } + else if( gr->ist_natur() && gr->get_pos().z+slope_t::max_diff(gr->get_grund_hang())==zpos ) { + // we can of course also build on nature + maxsize = area3x3[area_level]+koord(1,1); + continue; + } + } + // we only reach here upon unsuitable ground + break; + } + } + break; + case 2: + maxsize = area3x3[1]+koord(1,1); + break; + case 1: + maxsize = area3x3[0]+koord(1,1); + break; + default: + break; + } + // Find a house to build const building_desc_t* h = NULL; - if (sum_commercial > sum_industrial && sum_commercial > sum_residential) { - h = hausbauer_t::get_commercial(0, current_month, cl, neighbor_building_clusters); + if (sum_commercial > sum_industrial && sum_commercial >= sum_residential) { + h = hausbauer_t::get_commercial(0, current_month, cl, neighbor_building_clusters, koord(1,1), maxsize); if (h != NULL) { arb += (h->get_level()+1) * 20; } } - if (h == NULL && sum_industrial > sum_residential && sum_industrial > sum_commercial) { - h = hausbauer_t::get_industrial(0, current_month, cl, neighbor_building_clusters); + if (h == NULL && sum_industrial > sum_residential && sum_industrial >= sum_commercial) { + h = hausbauer_t::get_industrial(0, current_month, cl, neighbor_building_clusters, koord(1,1), maxsize); if (h != NULL) { arb += (h->get_level()+1) * 20; } } - if (h == NULL && sum_residential > sum_industrial && sum_residential > sum_commercial) { - h = hausbauer_t::get_residential(0, current_month, cl, neighbor_building_clusters); + if (h == NULL && sum_residential > sum_industrial && sum_residential >= sum_commercial) { + h = hausbauer_t::get_residential(0, current_month, cl, neighbor_building_clusters, koord(1,1), maxsize); if (h != NULL) { // will be aligned next to a street won += (h->get_level()+1) * 10; @@ -2956,15 +3022,18 @@ } } - int rotation = orient_city_building( k, h ); + // so we found at least one suitable building for this place + int rotation = orient_city_building( k, h, maxsize ); if( rotation >= 0 ) { - const gebaeude_t* gb = hausbauer_t::build(NULL, pos, rotation, h); + const gebaeude_t* gb = hausbauer_t::build(NULL, welt->lookup_kartenboden(k)->get_pos(), rotation, h); add_gebaeude_to_stadt(gb); } + // to be extended for larger building ... update_city_street(k); } + void stadt_t::renovate_city_building(gebaeude_t *gb) { const building_desc_t::btype alt_typ = gb->get_tile()->get_desc()->get_type(); @@ -2972,13 +3041,11 @@ return; // only renovate res, com, ind } - if( gb->get_tile()->get_desc()->get_x()*gb->get_tile()->get_desc()->get_y() != 1 ) { - return; // too big ... - } - // Now we are sure that this is a city building - const int level = gb->get_tile()->get_desc()->get_level(); - const koord k = gb->get_pos().get_2d(); + const building_desc_t *gb_desc = gb->get_tile()->get_desc(); + const int level = gb_desc->get_level(); + + koord k = gb->get_pos().get_2d() - gb->get_tile()->get_offset(); // Divide unemployed by 4, because it counts towards commercial and industrial, // and both of those count 'double' for population relative to residential. @@ -2999,19 +3066,56 @@ // Run through orthogonal neighbors (only) looking for which cluster to build // This is a bitmap -- up to 32 clustering types are allowed. uint32 neighbor_building_clusters = 0; - for (int i = 0; i < 4; i++) { - grund_t* gr = welt->lookup_kartenboden(k + neighbors[i]); - if (gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude) { + sint8 zpos = gb->get_pos().z; + koord minsize = gb->get_tile()->get_desc()->get_size(gb->get_tile()->get_layout()); + for( int i = 0; i < 4; i++ ) { + // since we handle buildings larger than (1x1) we add an offset + grund_t* gr = welt->lookup_kartenboden(k + neighbors[i]+minsize-koord(1,1)); + if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) { // We have a building as a neighbor... - gebaeude_t const* const gb = obj_cast(gr->first_obj()); - if (gb != NULL) { + if( gebaeude_t const* const testgb = obj_cast(gr->first_obj()) ) { // We really have a building as a neighbor... - const building_desc_t* neighbor_building = gb->get_tile()->get_desc(); + const building_desc_t* neighbor_building = testgb->get_tile()->get_desc(); neighbor_building_clusters |= neighbor_building->get_clusters(); } } } + // now test the surrounding tiles for larger size + koord maxsize=koord(1,1); + if( hausbauer_t::get_largest_city_building_area() > 1 ) { + for( int area_level=0; area_level < 8; area_level++ ) { + grund_t* gr = welt->lookup_kartenboden(k + area3x3[area_level]); + if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) { + // We have a building as a neighbor... + if( gebaeude_t const* const testgb = obj_cast(gr->first_obj()) ) { + // We really have a building as a neighbor... + const building_desc_t* neighbor_building = testgb->get_tile()->get_desc(); + if( gb->get_tile()->get_desc() == neighbor_building && testgb->get_tile()->get_offset() == area3x3[area_level] ) { + // part of same building + maxsize = area3x3[area_level]+koord(1,1); + continue; + } + if( testgb->get_pos().z == zpos && neighbor_building->is_city_building() && neighbor_building->get_x()*neighbor_building->get_y()==1 ) { + // also in right height and citybuilding + maxsize = area3x3[area_level]+koord(1,1); + continue; + } + } +#if 0 +/* since we only replace tiles, natur is not allowed for the moment, but could be easilz changed */ + else if( gr->ist_natur() && gr->get_pos().z+slope_t::max_diff(gr->get_grund_hang())==zpos ) { + // we can of course also build on nature + maxsize = area3x3[area_level]+koord(1,1); + continue; + } +#endif + } + // we only reach here upon unsuitable ground + break; + } + } + building_desc_t::btype want_to_have = building_desc_t::unknown; int sum = 0; @@ -3020,7 +3124,7 @@ if (sum_commercial > sum_industrial && sum_commercial > sum_residential) { // we must check, if we can really update to higher level ... const int try_level = (alt_typ == building_desc_t::city_com ? level + 1 : level); - h = hausbauer_t::get_commercial(try_level, current_month, cl, neighbor_building_clusters); + h = hausbauer_t::get_commercial(try_level, current_month, cl, neighbor_building_clusters, minsize, maxsize ); if( h != NULL && h->get_level() >= try_level ) { want_to_have = building_desc_t::city_com; sum = sum_commercial; @@ -3031,7 +3135,7 @@ || (sum_commercial > sum_residential && want_to_have == building_desc_t::unknown) ) { // we must check, if we can really update to higher level ... const int try_level = (alt_typ == building_desc_t::city_ind ? level + 1 : level); - h = hausbauer_t::get_industrial(try_level , current_month, cl, neighbor_building_clusters); + h = hausbauer_t::get_industrial(try_level , current_month, cl, neighbor_building_clusters, minsize, maxsize ); if( h != NULL && h->get_level() >= try_level ) { want_to_have = building_desc_t::city_ind; sum = sum_industrial; @@ -3042,7 +3146,7 @@ if( want_to_have == building_desc_t::unknown ) { // we must check, if we can really update to higher level ... const int try_level = (alt_typ == building_desc_t::city_res ? level + 1 : level); - h = hausbauer_t::get_residential(try_level, current_month, cl, neighbor_building_clusters); + h = hausbauer_t::get_residential(try_level, current_month, cl, neighbor_building_clusters, minsize, maxsize ); if( h != NULL && h->get_level() >= try_level ) { want_to_have = building_desc_t::city_res; sum = sum_residential; @@ -3060,70 +3164,87 @@ if( sum > 0 && h != NULL ) { // DBG_MESSAGE("stadt_t::renovate_city_building()", "renovation at %i,%i (%i level) of typ %i to typ %i with desire %i", k.x, k.y, alt_typ, want_to_have, sum); + // no renovation for now, if new is smaller + assert( gb_desc->get_x()*gb_desc->get_y() <= h->get_x()*h->get_y() ); + int rotation = 0; if( h->get_all_layouts()>1 ) { - // check for pavement - int streetdir = 0; - for( int i = 0; i < 4; i++ ) { - // Neighbors goes through these in 'preferred' order, orthogonal first - grund_t *gr = welt->lookup_kartenboden(k + neighbors[i]); - if( gr && gr->get_weg_hang() == gr->get_grund_hang() && gr->hat_weg(road_wt) ){ - streetdir += (1 << i); - } - } - // not completely unique layout, see if any of the neighbouring building gives a hint - rotation = building_layout[streetdir] & ~CHECK_NEIGHBOUR; - bool unique_orientation = !(building_layout[streetdir] & CHECK_NEIGHBOUR); - // only streets in diagonal corners => make a house there in L direction - if( !streetdir ) { - int count = 0; - for( int i = 4; i < 8; i++ ) { + + // only do this of symmetric of small enough building + if( h->get_x()==h->get_y() || (h->get_x()get_x()lookup_kartenboden(k + neighbors[i]); - if( gr && gr->get_weg_hang() == gr->get_grund_hang() && gr->hat_weg(road_wt) ) { - rotation = i; - count ++; + if( gr && gr->get_weg_hang() == gr->get_grund_hang() && gr->hat_weg(road_wt) ){ + streetdir += (1 << i); } } - unique_orientation = (count==1); - } - if( !unique_orientation ) { - int max_layout = h->get_all_layouts()-1; - for( int i = 0; i < 4; i++ ) { - // Neighbors goes through these in 'preferred' order, orthogonal first - grund_t *gr = welt->lookup_kartenboden(k + neighbors[i]); - if( gr && gr->get_typ()==grund_t::fundament ){ - if( gebaeude_t *gb = gr->find() ) { - if( gb->get_tile()->get_desc()->get_all_layouts() > max_layout ) { - // so take the roation of the next bilding with similar or more rotations - rotation = gb->get_tile()->get_layout(); - max_layout = gb->get_tile()->get_desc()->get_all_layouts(); + // not completely unique layout, see if any of the neighbouring building gives a hint + rotation = building_layout[streetdir] & ~CHECK_NEIGHBOUR; + bool unique_orientation = !(building_layout[streetdir] & CHECK_NEIGHBOUR); + // only streets in diagonal corners => make a house there in L direction + if( !streetdir ) { + int count = 0; + for( int i = 4; i < 8; i++ ) { + // Neighbors goes through these in 'preferred' order, orthogonal first + grund_t *gr = welt->lookup_kartenboden(k + neighbors[i]); + if( gr && gr->get_weg_hang() == gr->get_grund_hang() && gr->hat_weg(road_wt) ) { + rotation = i; + count ++; + } + } + unique_orientation = (count==1); + } + if( !unique_orientation ) { + int max_layout = h->get_all_layouts()-1; + for( int i = 0; i < 4; i++ ) { + // Neighbors goes through these in 'preferred' order, orthogonal first + grund_t *gr = welt->lookup_kartenboden(k + neighbors[i]); + if( gr && gr->get_typ()==grund_t::fundament ){ + if( gebaeude_t *gb = gr->find() ) { + if( gb->get_tile()->get_desc()->get_all_layouts() > max_layout ) { + // so take the roation of the next bilding with similar or more rotations + rotation = gb->get_tile()->get_layout(); + max_layout = gb->get_tile()->get_desc()->get_all_layouts(); + } } } } } } + else { + // asymmetric building + rotation = (h->get_x(0)<=maxsize.x && h->get_y(0)<=maxsize.y) ? 0 : 1; + } } - switch(alt_typ) { - case building_desc_t::city_res: won -= level * 10; break; - case building_desc_t::city_com: arb -= level * 20; break; - case building_desc_t::city_ind: arb -= level * 20; break; - default: break; + for( int x=0; xget_x(rotation); x++ ) { + for( int y=0; yget_y(rotation); y++ ) { + koord kpos = k+koord(x,y); + grund_t *gr = welt->lookup_kartenboden(kpos); + gebaeude_t *oldgb = gr->find(); + switch(oldgb->get_tile()->get_desc()->get_type()) { + case building_desc_t::city_res: won -= level * 10; break; + case building_desc_t::city_com: arb -= level * 20; break; + case building_desc_t::city_ind: arb -= level * 20; break; + default: break; + } + // exchange building; try to face it to street in front + oldgb->mark_images_dirty(); + oldgb->set_tile( h->get_tile(rotation, x, y), true ); + welt->lookup_kartenboden(kpos)->calc_image(); + update_gebaeude_from_stadt(oldgb); + update_city_street(kpos); + switch(h->get_type()) { + case building_desc_t::city_res: won += h->get_level() * 10; break; + case building_desc_t::city_com: arb += h->get_level() * 20; break; + case building_desc_t::city_ind: arb += h->get_level() * 20; break; + default: break; + } + } } - // exchange building; try to face it to street in front - gb->mark_images_dirty(); - gb->set_tile( h->get_tile(rotation, 0, 0), true ); - welt->lookup_kartenboden(k)->calc_image(); - update_gebaeude_from_stadt(gb); - update_city_street(k); - - switch(want_to_have) { - case building_desc_t::city_res: won += h->get_level() * 10; break; - case building_desc_t::city_com: arb += h->get_level() * 20; break; - case building_desc_t::city_ind: arb += h->get_level() * 20; break; - default: break; - } } } Index: trunk/simcity.h =================================================================== --- trunk/simcity.h (revision 8738) +++ trunk/simcity.h (working copy) @@ -439,7 +439,7 @@ factory_set_t& access_target_factories_for_mail() { return target_factories_mail; } // calculated the "best" orietation of city buildings, also used by editor, thus public - static int orient_city_building(const koord k, const building_desc_t *h ); + static int orient_city_building(const koord k, const building_desc_t *h, koord size ); // this function removes houses from the city house list // (called when removed by player, or by town) Index: trunk/simtool.cc =================================================================== --- trunk/simtool.cc (revision 8738) +++ trunk/simtool.cc (working copy) @@ -5352,7 +5352,7 @@ else if( default_param[1]=='A' ) { if( desc->get_type()!=building_desc_t::attraction_land && desc->get_type()!=building_desc_t::attraction_city ) { // auto rotation only valid for city buildings - rotation = stadt_t::orient_city_building( k, desc ); + rotation = stadt_t::orient_city_building( k, desc, desc->get_size() ); if( rotation < 0 ) { return NOTICE_UNSUITABLE_GROUND; }