diff --git a/simutrans/trunk/boden/grund.cc b/simutrans/trunk/boden/grund.cc index 77ff320..19552ce 100644 --- a/simutrans/trunk/boden/grund.cc +++ b/simutrans/trunk/boden/grund.cc @@ -635,6 +635,9 @@ void grund_t::info(cbuffer_t& buf) const if(get_weg_ribi_unmasked(water_wt)) { buf.printf("\nwater ribi: %i",get_weg_ribi_unmasked(water_wt)); } + if(is_water()) { + buf.printf("\ncanal ribi: %i", ((const wasser_t*)this)->get_canal_ribi()); + } buf.printf("\ndraw_as_obj= %i",(flags&draw_as_obj)!=0); buf.append("\nclimates= "); diff --git a/simutrans/trunk/boden/wasser.cc b/simutrans/trunk/boden/wasser.cc index caf9c5f..4b29d18 100644 --- a/simutrans/trunk/boden/wasser.cc +++ b/simutrans/trunk/boden/wasser.cc @@ -33,6 +33,16 @@ void wasser_t::prepare_for_refresh() } +/** + * helper function: return maximal possible ribis, does not + * take water ribi of sea tiles into account. + */ +ribi_t::ribi get_base_water_ribi(grund_t *gr) +{ + return gr->is_water() ? (ribi_t::ribi)ribi_t::all : gr->grund_t::get_weg_ribi(water_wt); +} + + void wasser_t::calc_image_internal(const bool calc_only_snowline_change) { if( !calc_only_snowline_change ) { @@ -52,11 +62,31 @@ void wasser_t::calc_image_internal(const bool calc_only_snowline_change) // test tiles to north, south, east and west and add to ribi if water ribi = ribi_t::none; + canal_ribi = ribi_t::none; + ribi_t::ribi base_ribi = get_base_water_ribi(this); + for( uint8 i = 0; i < 4; i++ ) { grund_t *gr_neighbour = NULL; - if( get_neighbour( gr_neighbour, invalid_wt, ribi_t::nsew[i] ) ) { - if (gr_neighbour->is_water() || (gr_neighbour->get_weg_ribi(water_wt) & ribi_t::reverse_single(ribi_t::nsew[i]))!=0 ) { - ribi |= ribi_t::nsew[i]; + ribi_t::ribi test = ribi_t::nsew[i]; + + if( (test&base_ribi) && get_neighbour(gr_neighbour, invalid_wt, test) ) { + // neighbour tile has water ways + ribi_t::ribi ribi_neigh_base = get_base_water_ribi(gr_neighbour); + if ((ribi_neigh_base & ribi_t::reverse_single(test))==0) { + // we cannot go back to our tile + continue; + } + + // set water ribi bit + ribi |= test; + + // test whether we can turn on neighbour canal tile + if (!gr_neighbour->is_water()) { + ribi_t::ribi ribi_orth = ribi_t::doubles( ribi_t::rotate90( test )); + if ((ribi_neigh_base & ribi_orth) != ribi_orth) { + // turning not possible, mark it as canal ribi + canal_ribi |= test; + } } } } @@ -71,4 +101,5 @@ void wasser_t::rotate90() { grund_t::rotate90(); ribi = ribi_t::rotate90(ribi); + canal_ribi = ribi_t::rotate90(canal_ribi); } diff --git a/simutrans/trunk/boden/wasser.h b/simutrans/trunk/boden/wasser.h index 689554c..0617c74 100644 --- a/simutrans/trunk/boden/wasser.h +++ b/simutrans/trunk/boden/wasser.h @@ -12,11 +12,18 @@ class wasser_t : public grund_t { protected: + /// cache ribis to tiles connected by water ribi_t::ribi ribi; + /// helper variable, ribis to canal tiles, where ships cannot turn left or right + ribi_t::ribi canal_ribi; + /** + * This method also recalculates ribi and cache_ribi! + */ void calc_image_internal(const bool calc_only_snowline_change); public: + wasser_t(loadsave_t *file, koord pos ) : grund_t(koord3d(pos,0) ), ribi(ribi_t::none) { rdwr(file); } wasser_t(koord3d pos) : grund_t(pos), ribi(ribi_t::none) {} @@ -32,6 +39,8 @@ public: // map rotation void rotate90(); + ribi_t::ribi get_canal_ribi() const { return canal_ribi; } + // static stuff from here on for water animation static int stage; static bool change_stage; diff --git a/simutrans/trunk/dataobj/route.cc b/simutrans/trunk/dataobj/route.cc index e92e0e0..6f84e2d 100644 --- a/simutrans/trunk/dataobj/route.cc +++ b/simutrans/trunk/dataobj/route.cc @@ -13,6 +13,7 @@ #include "../simhalt.h" #include "../boden/wege/weg.h" #include "../boden/grund.h" +#include "../boden/wasser.h" #include "../dataobj/marker.h" #include "../ifc/simtestdriver.h" #include "loadsave.h" @@ -492,8 +493,14 @@ bool route_t::intern_calc_route(karte_t *welt, const koord3d ziel, const koord3d // only check previous direction plus directions not available on this tile // if going straight only check straight direction // if going diagonally check both directions that generate this diagonal + // also enter all available canals and turn to get around canals if (tmp->parent!=NULL) { - k->jps_ribi = ~way_ribi | current_dir; + k->jps_ribi = ~way_ribi | current_dir | ((wasser_t*)to)->get_canal_ribi(); + + if (gr->is_water()) { + // turn on next tile to enter possible neighbours of canal tiles + k->jps_ribi |= ((const wasser_t*)gr)->get_canal_ribi(); + } } }