diff --git a/simutrans/trunk/bauer/fabrikbauer.cc b/simutrans/trunk/bauer/fabrikbauer.cc index b17cf46..9011b6b 100644 --- a/simutrans/trunk/bauer/fabrikbauer.cc +++ b/simutrans/trunk/bauer/fabrikbauer.cc @@ -109,17 +109,30 @@ void factory_builder_t::new_world() * Searches for a suitable building site using suche_platz(). * The site is chosen so that there is a street next to the building site. */ -class factory_place_with_road_finder: public building_placefinder_t { +class factory_site_searcher_t: public building_placefinder_t { + factory_desc_t::site_t site; public: - factory_place_with_road_finder(karte_t* welt) : building_placefinder_t(welt) {} + factory_site_searcher_t(karte_t* welt, factory_desc_t::site_t site_) : building_placefinder_t(welt), site(site_) {} virtual bool is_area_ok(koord pos, sint16 w, sint16 h, climate_bits cl) const { if( !building_placefinder_t::is_area_ok(pos, w, h, cl) ) { return false; } - bool next_to_road = false; + uint16 mincond = 0; + uint16 condmet = 0; + switch(site) { + case factory_desc_t::forest: + mincond = w*h; // at least w*h trees + break; + + case factory_desc_t::shore: + case factory_desc_t::river: + case factory_desc_t::City: + default: + mincond = 1; + } for (sint16 y = -1; y < h; y++) { for (sint16 x = -1; x < w; x++) { @@ -134,12 +147,34 @@ public: // something on top (monorail or power lines) return false; } - + // check for trees + if (condmet < mincond && site==factory_desc_t::forest) { + for(uint8 i=0; i< gr->get_top(); i++) { + if (gr->obj_bei(i)->get_typ() == obj_t::baum) { + condmet++; + } + } + } } else { - // border but not corner: near a road if possible - if (!next_to_road && (0 <= x || x < w-1) && (0 <= y || y < h-1)) { - next_to_road = gr->hat_weg(road_wt); + // border but not corner: check for road, shore, river + if (condmet < mincond && (0 <= x || x < w-1) && (0 <= y || y < h-1)) { + switch (site) { + case factory_desc_t::City: + condmet += gr->hat_weg(road_wt); break; + case factory_desc_t::shore: + condmet += welt->get_climate(k)==water_climate; break; + case factory_desc_t::river: + { + weg_t* river = gr->get_weg(water_wt); + if (river && river->get_desc()->get_styp()==type_river) { + condmet++; + printf("Found river near %s\n", pos.get_str()); + } + break; + } + default: ; + } } // do not build on an existing factory if( is_factory_at(k.x, k.y) ) { @@ -148,7 +183,7 @@ public: } } } - return next_to_road; + return condmet >= mincond; } }; @@ -293,10 +328,10 @@ void factory_builder_t::find_producer(weighted_vector_tpllookup_kartenboden(pos+koord(x,y)); @@ -307,34 +342,32 @@ bool factory_builder_t::check_construction_site(koord pos, koord size, bool wate } } else { - // check on land - if (!welt->square_is_free(pos, size.x, size.y, NULL, cl)) { - return false; + if (is_factory && site!=factory_desc_t::Land) { + return factory_site_searcher_t(welt, site).is_area_ok(pos, size.x, size.y, cl); } - } - // check for existing factories - if (is_factory) { - for(int y=0;ysquare_is_free(pos, size.x, size.y, NULL, cl); } } return true; } -koord3d factory_builder_t::find_random_construction_site( koord pos, const int radius, koord size, bool wasser, const building_desc_t *desc, bool ignore_climates, uint32 max_iterations ) +koord3d factory_builder_t::find_random_construction_site(koord pos, int radius, koord size, factory_desc_t::site_t site, const building_desc_t *desc, bool ignore_climates, uint32 max_iterations) { bool is_factory = desc->get_type()==building_desc_t::factory; + bool wasser = site == factory_desc_t::Water; + if(wasser) { // to ensure at least 3x3 water around (maybe this should be the station catchment area+1?) size += koord(6,6); } climate_bits climates = !ignore_climates ? desc->get_allowed_climate_bits() : ALL_CLIMATES; + if (ignore_climates && site != factory_desc_t::Water) { + //site = factory_desc_t::Land; + } uint32 diam = 2*radius + 1; uint32 area = diam * diam; @@ -352,12 +385,19 @@ koord3d factory_builder_t::find_random_construction_site( koord pos, const int r k = koord( pos.x - radius + (index % diam), pos.y - radius + (index / diam) ); // check place (it will actually check an grosse.x/y size rectangle, so we can iterate over less tiles) - if( factory_builder_t::check_construction_site(k, size, wasser, is_factory, climates) ) { + if( factory_builder_t::check_construction_site(k, size, site, is_factory, climates) ) { // then accept first hit + if (site != factory_desc_t::Water && site != factory_desc_t::Land) { + printf("Found spot for %d at %s / %d\n", site, k.get_str(), max_iterations); + } + // we accept first hit goto finish; } } // nothing found + if (site != factory_desc_t::Water && site != factory_desc_t::Land) { + printf("No spot found for %d near %s / %d\n", site, pos.get_str(), max_iterations); + } return koord3d::invalid; finish: @@ -395,7 +435,7 @@ void factory_builder_t::distribute_attractions(int max_number) } int rotation=simrand(attraction->get_all_layouts()-1); - pos = find_random_construction_site(pos.get_2d(), 20, attraction->get_size(rotation),false,attraction,false,0x0FFFFFFF); // so far -> land only + pos = find_random_construction_site(pos.get_2d(), 20, attraction->get_size(rotation), factory_desc_t::Land, attraction, false, 0x0FFFFFFF); // so far -> land only if(welt->lookup(pos)) { // space found, build attraction hausbauer_t::build(welt->get_public_player(), pos, rotation, attraction); @@ -591,12 +631,12 @@ int factory_builder_t::build_link(koord3d* parent, const factory_desc_t* info, s */ bool is_rotate=info->get_building()->get_all_layouts()>1 && size.x!=size.y && info->get_building()->can_rotate(); // first try with standard orientation - koord k = factory_place_with_road_finder(welt).find_place(city->get_pos(), size.x, size.y, info->get_building()->get_allowed_climate_bits()); + koord k = factory_site_searcher_t(welt, factory_desc_t::City).find_place(city->get_pos(), size.x, size.y, info->get_building()->get_allowed_climate_bits()); // second try: rotated koord k1 = koord::invalid; if (is_rotate && (k == koord::invalid || simrand(256)<128)) { - k1 = factory_place_with_road_finder(welt).find_place(city->get_pos(), size.y, size.x, info->get_building()->get_allowed_climate_bits()); + k1 = factory_site_searcher_t(welt, factory_desc_t::City).find_place(city->get_pos(), size.y, size.x, info->get_building()->get_allowed_climate_bits()); } rotate = simrand( info->get_building()->get_all_layouts() ); @@ -800,7 +840,7 @@ DBG_MESSAGE("factory_builder_t::build_link","supplier_count %i, lcount %i (need INT_CHECK("fabrikbauer 697"); - koord3d k = find_random_construction_site( our_fab->get_pos().get_2d(), DISTANCE, producer_d->get_building()->get_size(rotate),producer_d->get_placement()==factory_desc_t::Water, producer_d->get_building(), ignore_climates, 20000 ); + koord3d k = find_random_construction_site( our_fab->get_pos().get_2d(), DISTANCE, producer_d->get_building()->get_size(rotate), producer_d->get_placement(), producer_d->get_building(), ignore_climates, 20000 ); if( k == koord3d::invalid ) { // this factory cannot buuild in the desired vincinity producer.remove( producer_d ); @@ -992,13 +1032,13 @@ next_ware_check: int rotation = simrand( fab->get_building()->get_all_layouts() ); if(!in_city) { // find somewhere on the map - pos = find_random_construction_site( koord(welt->get_size().x/2,welt->get_size().y/2), welt->get_size_max()/2, fab->get_building()->get_size(rotation),fab->get_placement()==factory_desc_t::Water,fab->get_building(),ignore_climates,10000); + pos = find_random_construction_site( koord(welt->get_size().x/2,welt->get_size().y/2), welt->get_size_max()/2, fab->get_building()->get_size(rotation),fab->get_placement(),fab->get_building(),ignore_climates,10000); } else { // or within the city limit const stadt_t *city = pick_any_weighted(welt->get_cities()); koord diff = city->get_rechtsunten()-city->get_linksoben(); - pos = find_random_construction_site( city->get_center(), max(diff.x,diff.y)/2, fab->get_building()->get_size(rotation),fab->get_placement()==factory_desc_t::Water,fab->get_building(),ignore_climates, 1000); + pos = find_random_construction_site( city->get_center(), max(diff.x,diff.y)/2, fab->get_building()->get_size(rotation),fab->get_placement(),fab->get_building(),ignore_climates, 1000); } if(welt->lookup(pos)) { // Space found... diff --git a/simutrans/trunk/bauer/fabrikbauer.h b/simutrans/trunk/bauer/fabrikbauer.h index a4d2db9..47ee928 100644 --- a/simutrans/trunk/bauer/fabrikbauer.h +++ b/simutrans/trunk/bauer/fabrikbauer.h @@ -11,10 +11,8 @@ #include "../tpl/stringhashtable_tpl.h" #include "../tpl/weighted_vector_tpl.h" #include "../dataobj/koord3d.h" +#include "../descriptor/factory_desc.h" -class building_desc_t; -class goods_desc_t; -class factory_desc_t; class stadt_t; class karte_ptr_t; class player_t; @@ -134,14 +132,14 @@ private: * @param water true to search on water * @param cl allowed climates */ - static bool check_construction_site(koord pos, koord size, bool water, bool is_factory, climate_bits cl); + static bool check_construction_site(koord pos, koord size, factory_desc_t::site_t site, bool is_factory, climate_bits cl); /** * Find a random site to place a factory. * @param radius Radius of the search circle around @p pos * @param size size of the building site */ - static koord3d find_random_construction_site(koord pos, int radius, koord size,bool on_water, const building_desc_t *desc, bool ignore_climates, uint32 max_iterations); + static koord3d find_random_construction_site(koord pos, int radius, koord size, factory_desc_t::site_t site, const building_desc_t *desc, bool ignore_climates, uint32 max_iterations); /** * Checks if all factories in this factory tree can be rotated. diff --git a/simutrans/trunk/descriptor/factory_desc.h b/simutrans/trunk/descriptor/factory_desc.h index 1ef9f7c..f1eb216 100644 --- a/simutrans/trunk/descriptor/factory_desc.h +++ b/simutrans/trunk/descriptor/factory_desc.h @@ -207,7 +207,7 @@ class factory_desc_t : public obj_desc_t { friend class factory_reader_t; public: - enum site_t { Land, Water, City }; + enum site_t { Land, Water, City, river, shore, forest }; private: site_t placement; diff --git a/simutrans/trunk/descriptor/writer/factory_writer.cc b/simutrans/trunk/descriptor/writer/factory_writer.cc index 4fd11f9..aa8d611 100644 --- a/simutrans/trunk/descriptor/writer/factory_writer.cc +++ b/simutrans/trunk/descriptor/writer/factory_writer.cc @@ -148,6 +148,9 @@ void factory_writer_t::write_obj(FILE* fp, obj_node_t& parent, tabfileobj_t& obj !STRICMP(placing, "land") ? factory_desc_t::Land : !STRICMP(placing, "water") ? factory_desc_t::Water : !STRICMP(placing, "city") ? factory_desc_t::City : + !STRICMP(placing, "river") ? factory_desc_t::river : + !STRICMP(placing, "shore") ? factory_desc_t::shore : + !STRICMP(placing, "forest")? factory_desc_t::forest : factory_desc_t::Land; uint16 const productivity = obj.get_int("productivity", 10); uint16 const range = obj.get_int("range", 10);