Index: bauer/wegbauer.cc =================================================================== --- bauer/wegbauer.cc (リビジョン 8188) +++ bauer/wegbauer.cc (作業コピー) @@ -866,7 +866,224 @@ return ok; } +/* This is the core routine for the elevated way search + * it will check + * A) allowed step + * B) if allowed, calculate the cost for the step from from to to + * @author prissi(Ichou modified) + */ +/* It should not be river/airport/tunnel/bridge/terraformable + */ +bool way_builder_t::is_allowed_step_elevated(const grund_t *from, const grund_t *to, sint32 *costs) +{ + const koord from_pos=from->get_pos().get_2d(); + const koord to_pos=to->get_pos().get_2d(); + const koord zv=to_pos-from_pos; + // fake empty elevated tiles + static monorailboden_t to_dummy(koord3d::invalid, slope_t::flat); + static monorailboden_t from_dummy(koord3d::invalid, slope_t::flat); + bool to_flat = false; // to tile will be flattened + if(from!=to) { + // check slopes + bool ok_slope = from->get_weg_hang() == slope_t::flat || ribi_t::doubles(ribi_type(from->get_weg_hang()))==ribi_t::doubles(ribi_type(zv)); + ok_slope &= to->get_weg_hang() == slope_t::flat || ribi_t::doubles(ribi_type(to->get_weg_hang()))==ribi_t::doubles(ribi_type(zv)); + + if (!ok_slope) { + // slopes not ok and no terraforming possible + return false; + } + } + + // ok, slopes are ok + bool ok = true; + + // check scenario conditions + if (welt->get_scenario()->is_work_allowed_here(player_builder, (bautyp&tunnel_flag ? TOOL_BUILD_TUNNEL : TOOL_BUILD_WAY)|GENERAL_TOOL, bautyp&bautyp_mask, to->get_pos()) != NULL) { + return false; + } + + // check if there is already suitable elevated way + if( (to->get_typ() != grund_t::monorailboden || to->get_weg_nr(0)->get_desc()->get_wtyp()!=desc->get_wtyp() || !check_owner(to->obj_bei(0)->get_owner(),player_builder) ) || (from->get_typ() != grund_t::monorailboden || from->get_weg_nr(0)->get_desc()->get_wtyp()!=desc->get_wtyp() || !check_owner(from->obj_bei(0)->get_owner(),player_builder) ) ) { + return false; + } + // other terrain checks should not be needed because there is already a way + + + // universal check for depots/stops/... + if( !check_building( from, zv ) || !check_building( to, -zv ) ) { + return false; + } + + // universal check for crossings + if (to!=from && (bautyp&bautyp_mask)!=leitung) { + waytype_t const wtyp = (bautyp == river) ? water_wt : (waytype_t)(bautyp & bautyp_mask); + if(!check_crossing(zv,to,wtyp,player_builder) || !check_crossing(-zv,from,wtyp,player_builder)) { + return false; + } + } + + // universal check for building under powerlines + if ((bautyp&bautyp_mask)!=leitung) { + if (!check_powerline(zv,to) || !check_powerline(-zv,from)) { + return false; + } + } + + bool fundament = to->get_typ()==grund_t::fundament; + + // now check way specific stuff + settings_t const& s = welt->get_settings(); + switch(bautyp&bautyp_mask) { + + case strasse: + { + const weg_t *str=to->get_weg(road_wt); + + // we allow connection to any road + ok = (str || !fundament) && !to->is_water(); + if(!ok) { + return false; + } + // check for end/start of bridge or tunnel + // fail if no proper way exists, or the way's ribi are not 0 and are not matching the slope type + ribi_t::ribi test_ribi = (str ? str->get_ribi_unmasked() : 0) | ribi_type(zv); + if(to->get_weg_hang()!=to->get_grund_hang() && (str==NULL || !(ribi_t::is_straight(test_ribi) || test_ribi==0 ))) { + return false; + } + // calculate costs + *costs = str ? 0 : s.way_count_straight; + if((str==NULL && to->hat_wege()) || (str && to->has_two_ways())) { + *costs += 4; // avoid crossings + } + if(to->get_weg_hang()!=0 && !to_flat) { + *costs += s.way_count_slope; + } + } + break; + + case schiene: + default: + { + const weg_t *sch=to->get_weg(desc->get_wtyp()); + // extra check for AI construction (not adding to existing tracks!) + if((bautyp&bot_flag)!=0 && (sch || to->get_halt().is_bound())) { + return false; + } + // ok, regular construction here + // if no way there: check for right ground type, otherwise check owner + ok = sch==NULL ? (!fundament && !to->is_water()) : check_owner(sch->get_owner(),player_builder); + if(!ok) { + return false; + } + // check for end/start of bridge or tunnel + // fail if no proper way exists, or the way's ribi are not 0 and are not matching the slope type + ribi_t::ribi test_ribi = (sch ? sch->get_ribi_unmasked() : 0) | ribi_type(zv); + if(to->get_weg_hang()!=to->get_grund_hang() && (sch==NULL || !(ribi_t::is_straight(test_ribi) || test_ribi==0 ))) { + return false; + } + // calculate costs + *costs = s.way_count_straight; + if (!sch) *costs += 1; // only prefer existing rails a little + if((sch && to->has_two_ways()) || (sch==NULL && to->hat_wege())) { + *costs += 4; // avoid crossings + } + if(to->get_weg_hang()!=0 && !to_flat) { + *costs += s.way_count_slope; + } + } + break; + + case schiene_tram: // Dario: Tramway + { + const weg_t *sch=to->get_weg(track_wt); + // roads are checked in check_crossing + // if no way there: check for right ground type, otherwise check owner + ok = sch==NULL ? (!fundament && !to->is_water()) : check_owner(sch->get_owner(),player_builder); + // tram track allowed in road tunnels, but only along existing roads / tracks + if(from!=to) { + if(from->ist_tunnel()) { + const ribi_t::ribi ribi = from->get_weg_ribi_unmasked(road_wt) | from->get_weg_ribi_unmasked(track_wt) | ribi_t::doubles(ribi_type(from->get_grund_hang())); + ok = ok && ((ribi & ribi_type(zv))==ribi_type(zv)); + } + if(to->ist_tunnel()) { + const ribi_t::ribi ribi = to->get_weg_ribi_unmasked(road_wt) | to->get_weg_ribi_unmasked(track_wt) | ribi_t::doubles(ribi_type(to->get_grund_hang())); + ok = ok && ((ribi & ribi_type(-zv))==ribi_type(-zv)); + } + } + if(ok) { + // calculate costs + *costs = s.way_count_straight; + if (!to->hat_weg(track_wt)) *costs += 1; // only prefer existing rails a little + // prefer own track + if(to->hat_weg(road_wt)) { + *costs += s.way_count_straight; + } + if(to->get_weg_hang()!=0 && !to_flat) { + *costs += s.way_count_slope; + } + } + } + break; + + case leitung: + ok = !to->is_water() && (to->get_weg(air_wt)==NULL); + ok &= !(to->ist_tunnel() && to->hat_wege()); + if(to->get_weg_nr(0)!=NULL) { + // only 90 deg crossings, only a single way + ribi_t::ribi w_ribi= to->get_weg_nr(0)->get_ribi_unmasked(); + ok &= ribi_t::is_straight(w_ribi) && !ribi_t::is_single(w_ribi) && ribi_t::is_straight(ribi_type(zv)) && (w_ribi&ribi_type(zv))==0; + } + if(to->has_two_ways()) { + // only 90 deg crossings, only for trams ... + ribi_t::ribi w_ribi= to->get_weg_nr(1)->get_ribi_unmasked(); + ok &= ribi_t::is_straight(w_ribi) && !ribi_t::is_single(w_ribi) && ribi_t::is_straight(ribi_type(zv)) && (w_ribi&ribi_type(zv))==0; + } + // do not connect to other powerlines + { + leitung_t *lt = to->get_leitung(); + ok &= (lt==NULL) || check_owner(player_builder, lt->get_owner()); + } + + if(to->get_typ()!=grund_t::tunnelboden) { + // only fields are allowed + if(to->get_typ()!=grund_t::boden) { + ok &= to->get_typ() == grund_t::fundament && to->find(); + } + // no bridges and monorails here in the air + ok &= (welt->access(to_pos)->get_boden_in_hoehe(to->get_pos().z+1)==NULL); + } + + // calculate costs + if(ok) { + *costs = s.way_count_straight; + if( !to->get_leitung() ) { + // extra malus for not following an existing line or going on ways + *costs += s.way_count_double_curve + (to->hat_wege() ? 8 : 0); // prefer existing powerlines + } + } + break; + + case wasser: + { + const weg_t *canal = to->get_weg(water_wt); + // if no way there: check for right ground type, otherwise check owner + ok = canal || !fundament; + // calculate costs + if(ok) { + *costs = to->is_water() || canal ? s.way_count_straight : s.way_count_leaving_road; // prefer water very much + if(to->get_weg_hang()!=0 && !to_flat) { + *costs += s.way_count_slope * 2; + } + } + break; + } + + } + return ok; +} + + bool way_builder_t::check_terraforming( const grund_t *from, const grund_t *to, uint8* new_from_slope, uint8* new_to_slope) { // only for normal green tiles @@ -1691,7 +1908,418 @@ } } +/* this routine uses A* to calculate the best route + * beware: change the cost and you will mess up the system! + * (but you can try, look at simuconf.tab) + */ +/* It should not be river/airport/tunnel/bridge/terraformable + */ +sint32 way_builder_t::intern_calc_route_elevated(const koord3d start, const koord3d ziel) +{ + // we clear it here probably twice: does not hurt ... + route.clear(); + terraform_index.clear(); + const koord3d koordup(0, 0, welt->get_settings().get_way_height_clearance()); + + // check for existing koordinates + bool has_target_ground = welt->lookup(ziel) || welt->lookup(ziel + koordup); + if( !has_target_ground ) { + return -1; + } + + + // memory in static list ... + if(route_t::nodes==NULL) { + route_t::MAX_STEP = welt->get_settings().get_max_route_steps(); // may need very much memory => configurable + route_t::nodes = new route_t::ANode[route_t::MAX_STEP+4+1]; + } + + static binary_heap_tpl queue; + + // initialize marker field + marker_t& markerbelow = marker_t::instance(welt->get_size().x, welt->get_size().y); + marker_t& markerabove = marker_t::instance_second(welt->get_size().x, welt->get_size().y); + + // clear the queue (should be empty anyhow) + queue.clear(); + + // some thing for the search + grund_t *to; + koord3d gr_pos; // just the last valid pos ... + route_t::ANode *tmp=NULL; + uint32 step = 0; + const grund_t *gr=NULL, *gu = NULL; + + gr = welt->lookup(start); + // is valid ground? + sint32 dummy; + if( gr && is_allowed_step(gr,gr,&dummy) ) { + // DBG_MESSAGE("way_builder_t::intern_calc_route()","cannot start on (%i,%i,%i)",start.x,start.y,start.z); + tmp = &(route_t::nodes[step]); + step ++; + tmp->parent = NULL; + tmp->gr = gr; + tmp->f = calc_distance(start, ziel, ziel); + tmp->g = 0; + tmp->dir = 0; + + tmp->count = 0; + + queue.insert(tmp); + } + + gu = welt->lookup(start + koordup); + if( gu && is_allowed_step_elevated(gu,gu,&dummy) ) { + // DBG_MESSAGE("way_builder_t::intern_calc_route()","cannot start on (%i,%i,%i)",start.x,start.y,start.z); + tmp = &(route_t::nodes[step]); + step ++; + tmp->parent = NULL; + tmp->gr = gu; + tmp->f = calc_distance(start, ziel, ziel); + tmp->g = 0; + tmp->dir = 0; + + tmp->count = is_upperlayer; + + queue.insert(tmp); + } + + + if( queue.empty() ) { + // no valid ground to start. + return -1; + } + + INT_CHECK("wegbauer 347"); + + // get exclusively the tile list + route_t::GET_NODE(); + + // to speed up search, but may not find all shortest ways + uint32 min_dist = 99999999; + +//DBG_MESSAGE("route_t::itern_calc_route()","calc route from %d,%d,%d to %d,%d,%d",ziel.x, ziel.y, ziel.z, start.x, start.y, start.z); + do { + route_t::ANode *test_tmp = queue.pop(); + + if( (test_tmp->count&is_upperlayer?markerabove:markerbelow).test_and_mark(test_tmp->gr) ) { + // we were already here on a faster route, thus ignore this branch + // (trading speed against memory consumption) + continue; + } + + tmp = test_tmp; + if(test_tmp->count & is_upperlayer) { + gu = tmp->gr; + gr_pos = gu->get_pos() - koordup; + gr = welt->lookup(gr_pos); + } + else { + gr = tmp->gr; + gr_pos = gr->get_pos(); + gu = welt->lookup(gr_pos + koordup); + } + +#ifdef DEBUG_ROUTES +DBG_DEBUG("insert to close","(%i,%i,%i) f=%i",gr->get_pos().x,gr->get_pos().y,gr->get_pos().z,tmp->f); +#endif + + // already there + if( ziel == gr_pos || tmp->g>maximum) { + // we added a target to the closed list: we are finished + break; + } + + // the four possible directions plus any additional stuff due to already existing brides plus new ones ... + next_gr.clear(); + + //search following the lower layer + if(gr) { + + // only one direction allowed ... + const ribi_t::ribi straight_dir = tmp->parent!=NULL ? ribi_type(gr->get_pos() - tmp->parent->gr->get_pos()) : (ribi_t::ribi)ribi_t::all; + + // test directions + // .. use only those that are allowed by current slope + // .. do not go backward + const ribi_t::ribi slope_dir = (slope_t::is_way_ns(gr->get_weg_hang()) ? ribi_t::northsouth : ribi_t::none) | (slope_t::is_way_ew(gr->get_weg_hang()) ? ribi_t::eastwest : ribi_t::none); + const ribi_t::ribi test_dir = (tmp->count & build_straight)==0 ? slope_dir & ~ribi_t::backward(straight_dir) + : straight_dir; + + // testing all four possible directions + for(ribi_t::ribi r=1; (r&16)==0; r<<=1) { + if((r & test_dir)==0) { + // not allowed to go this direction + continue; + } + + const koord zv(r); + if(!gr->get_neighbour(to,invalid_wt,r) || !check_slope(gr, to)) { + // slopes do not match + continue; + } + + // something valid? + if(markerbelow.is_marked(to)) { + continue; + } + + sint32 new_cost = 0; + bool is_ok = is_allowed_step(gr,to,&new_cost); + + if(is_ok) { + // now add it to the array ... + next_gr.append(next_gr_t(to, new_cost, 0)); + } + } + } + + //search following the upper layer + if(gu) { + + // only one direction allowed ... + const ribi_t::ribi straight_dir = tmp->parent!=NULL ? ribi_type(gu->get_pos() - tmp->parent->gr->get_pos()) : (ribi_t::ribi)ribi_t::all; + + // test directions + // .. use only those that are allowed by current slope + // .. do not go backward + const ribi_t::ribi slope_dir = (slope_t::is_way_ns(gu->get_weg_hang()) ? ribi_t::northsouth : ribi_t::none) | (slope_t::is_way_ew(gu->get_weg_hang()) ? ribi_t::eastwest : ribi_t::none); + const ribi_t::ribi test_dir = (tmp->count & build_straight)==0 ? slope_dir & ~ribi_t::backward(straight_dir) + : straight_dir; + + // testing all four possible directions + for(ribi_t::ribi r=1; (r&16)==0; r<<=1) { + if((r & test_dir)==0) { + // not allowed to go this direction + continue; + } + + const koord zv(r); + if(!gu->get_neighbour(to,invalid_wt,r) || !check_slope(gu, to)) { + // slopes do not match + continue; + } + + // something valid? + if(markerabove.is_marked(to)) { + continue; + } + + sint32 new_cost = 0; + bool is_ok = is_allowed_step_elevated(gu,to,&new_cost); + + if(is_ok) { + // now add it to the array ... + next_gr.append(next_gr_t(to, new_cost, is_upperlayer)); + } + } + } + + // now check all valid ones ... + FOR(vector_tpl, const& r, next_gr) { + to = r.gr; + + if( to==NULL) { + continue; + } + + // new values for cost g + uint32 new_g = tmp->g + r.cost; + + settings_t const& s = welt->get_settings(); + // check for curves (usually, one would need the lastlast and the last; + // if not there, then we could just take the last + uint8 current_dir; + if(tmp->parent!=NULL) { + current_dir = ribi_type( tmp->parent->gr->get_pos(), to->get_pos() ); + if(tmp->dir!=current_dir) { + new_g += s.way_count_curve; + if(tmp->parent->dir!=tmp->dir) { + // discourage double turns + new_g += s.way_count_double_curve; + } + else if(ribi_t::is_perpendicular(tmp->dir,current_dir)) { + // discourage v turns heavily + new_g += s.way_count_90_curve; + } + } + else if(bautyp==leitung && ribi_t::is_bend(current_dir)) { + new_g += s.way_count_double_curve; + } + // extra malus leave an existing road after only one tile + waytype_t const wt = desc->get_wtyp(); + if (tmp->parent->gr->hat_weg(wt) && !(gr? gr: gu)->hat_weg(wt) && to->hat_weg(wt)) { + // but only if not straight track + if(!ribi_t::is_straight(tmp->dir)) { + new_g += s.way_count_leaving_road; + } + } + } + else { + current_dir = ribi_type( gr_pos, to->get_pos() ); + } + + const uint32 new_dist = calc_distance( to->get_pos(), ziel, ziel ); + + // special check for kinks at the end + if(new_dist==0 && current_dir!=tmp->dir) { + // discourage turn on last tile + new_g += s.way_count_double_curve; + } + + if(new_distmin_dist+50) { + // skip, if too far from current minimum tile + // will not find some ways, but will be much faster ... + // also it will avoid too big detours, which is probably also not the way, the builder intended + continue; + } + + + const uint32 new_f = new_g+new_dist; + + if((step&0x03)==0) { + INT_CHECK( "wegbauer 1347" ); +#ifdef DEBUG_ROUTES + if((step&1023)==0) {reliefkarte_t::get_karte()->calc_map();} +#endif + } + + // not in there or taken out => add new + route_t::ANode *k=&(route_t::nodes[step]); + step++; + + k->parent = tmp; + k->gr = to; + k->g = new_g; + k->f = new_f; + k->dir = current_dir; + // count is unused here, use it as flag-variable instead + k->count = r.flag; + + queue.insert( k ); + +#ifdef DEBUG_ROUTES +DBG_DEBUG("insert to open","(%i,%i,%i) f=%i",to->get_pos().x,to->get_pos().y,to->get_pos().z,k->f); +#endif + } + + } while (!queue.empty() && step < route_t::MAX_STEP); + +#ifdef DEBUG_ROUTES +DBG_DEBUG("way_builder_t::intern_calc_route()","steps=%i (max %i) in route, open %i, cost %u",step,route_t::MAX_STEP,queue.get_count(),tmp->g); +#endif + INT_CHECK("wegbauer 194"); + + route_t::RELEASE_NODE(); + + // target reached? + if( !(ziel == gr_pos) || step>=route_t::MAX_STEP || tmp->parent==NULL || tmp->g > maximum ) { + if (step>=route_t::MAX_STEP) { + dbg->warning("way_builder_t::intern_calc_route()","Too many steps (%i>=max %i) in route (too long/complex)",step,route_t::MAX_STEP); + } + return -1; + } + else { + const sint32 cost = tmp->g; + // reached => construct route + while(tmp != NULL) { + if(tmp->count & is_upperlayer) { + route.append(tmp->gr->get_pos() - koordup); + } else { + route.append(tmp->gr->get_pos() ); + } + tmp = tmp->parent; + } + return cost; + } + + return -1; +} + +/* It's for elevated + * so should not be river/airport/tunnel/bridge/terraformable + */ +void way_builder_t::intern_calc_straight_route_elevated(const koord3d start, const koord3d ziel) +{ + bool ok=true; + + koord3d koordup(0, 0, welt->get_settings().get_way_height_clearance()); + const grund_t *test_bd = welt->lookup(start), *test_bu = welt->lookup(start + koordup); + if (test_bd == NULL && test_bu == NULL) { + // not buildable + return; + } + sint32 dummy_cost; + if((!test_bd || !is_allowed_step(test_bd, test_bd, &dummy_cost)) && (!test_bu || !is_allowed_step_elevated(test_bu, test_bu, &dummy_cost)) ) { + // no legal ground to start ... + return; + } + + // we have to reach target height if no tunnel building or (target ground does not exists or is underground). + // in full underground mode if there is no tunnel under cursor, kartenboden gets selected + + koord3d pos=start; + + route.clear(); + route.append(start); + terraform_index.clear(); + + while(pos.get_2d()!=ziel.get_2d() && ok) { + + // shortest way + ribi_t::ribi diff; + if(abs(pos.x-ziel.x)>=abs(pos.y-ziel.y)) { + diff = (pos.x>ziel.x) ? ribi_t::west : ribi_t::east; + } + else { + diff = (pos.y>ziel.y) ? ribi_t::north : ribi_t::south; + } + grund_t *bd_von = welt->lookup(pos), *bu_von = welt->lookup(pos + koordup); + + if (bd_von==NULL && bu_von==NULL) { + ok = false; + } + else + { + grund_t *bd_nach = NULL; + //search following the lower layer + if (bd_von && bd_von->get_neighbour(bd_nach, invalid_wt, diff) && check_slope(bd_von, bd_nach) && is_allowed_step(bd_von, bd_nach, &dummy_cost) ) { + if(ok) { + pos = bd_nach->get_pos(); + } + } + //search following the upper layer + else if(bu_von && bu_von->get_neighbour(bd_nach, invalid_wt, diff) && check_slope(bu_von, bd_nach) && is_allowed_step_elevated(bu_von, bd_nach, &dummy_cost) ) { + if(ok) { + pos = bd_nach->get_pos() - koordup; + } + } + else { + //no shortest route + ok = false; + } + } + + route.append(pos); + DBG_MESSAGE("way_builder_t::calc_straight_route()","step %s = %i",koord(diff).get_str(),ok); + } + ok = pos==ziel; + + // we can built a straight route? + if(ok) { +DBG_MESSAGE("way_builder_t::intern_calc_straight_route()","found straight route max_n=%i",get_count()-1); + } + else { + route.clear(); + terraform_index.clear(); + } +} + + // special for starting/landing runways bool way_builder_t::intern_calc_route_runways(koord3d start3d, const koord3d ziel3d) { @@ -1778,6 +2406,12 @@ // these are straight anyway ... intern_calc_route_runways(start, ziel); } + else if(desc->get_styp() == type_elevated) { + intern_calc_straight_route_elevated(start,ziel); + if (route.empty()) { + intern_calc_straight_route_elevated(ziel,start); + } + } else { intern_calc_straight_route(start,ziel); if (route.empty()) { @@ -1825,14 +2459,23 @@ } else { keep_existing_city_roads |= (bautyp&bot_flag)!=0; - sint32 cost2 = intern_calc_route( start, ziel ); - INT_CHECK("wegbauer 1165"); - - if(cost2<0) { - // not successful: try backwards - intern_calc_route(ziel,start); - return; + sint32 cost2; + if(desc->get_styp() == type_elevated) { + cost2 = intern_calc_route_elevated(start[0], ziel[0]); + INT_CHECK("wegbauer 1165"); + if(cost2 < 0) { + intern_calc_route_elevated(ziel[0], start[0]); + return; + } } + else { + cost2 = intern_calc_route( start, ziel ); + INT_CHECK("wegbauer 1165"); + if(cost2 < 0) { + intern_calc_route( ziel, start ); + return; + } + } #ifdef REVERSE_CALC_ROUTE_TOO vector_tpl route2(0); @@ -1839,7 +2482,13 @@ vector_tpl terraform_index2(0); swap(route, route2); swap(terraform_index, terraform_index2); - sint32 cost = intern_calc_route( ziel, start ); + sint32 cost; + if(desc->get_styp() == type_elevated) { + cost = intern_calc_route_elevated(start[0], ziel[0]); + } + else { + cost = intern_calc_route( start, ziel ); + } INT_CHECK("wegbauer 1165"); // the cheaper will survive ... Index: bauer/wegbauer.h =================================================================== --- bauer/wegbauer.h (リビジョン 8188) +++ bauer/wegbauer.h (作業コピー) @@ -85,6 +85,7 @@ build_straight = 1, ///< next step has to be straight terraform = 2, ///< terraform this tile build_tunnel_bridge = 4, ///< bridge/tunnel ends here + is_upperlayer = 8, ///only used when elevated true:upperlayer }; struct next_gr_t @@ -119,7 +120,7 @@ const bridge_desc_t * bridge_desc; /** - * Type of bridges to build (zero=>no bridges) + * Type of tunnels to build (zero=>no bridges) * @author Hj. Malthaner */ const tunnel_desc_t * tunnel_desc; @@ -149,6 +150,7 @@ * @author prissi */ bool is_allowed_step(const grund_t *from, const grund_t *to, sint32 *costs); + bool is_allowed_step_elevated(const grund_t *from, const grund_t *to, sint32 *costs); private: // checks, if we can built a bridge here ... @@ -158,6 +160,9 @@ sint32 intern_calc_route(const vector_tpl &start, const vector_tpl &ziel); void intern_calc_straight_route(const koord3d start, const koord3d ziel); + sint32 intern_calc_route_elevated(const koord3d start, const koord3d ziel); + void intern_calc_straight_route_elevated(const koord3d start, const koord3d ziel); + // runways need to meet some special conditions enforced here bool intern_calc_route_runways(koord3d start, const koord3d ziel); Index: dataobj/marker.cc =================================================================== --- dataobj/marker.cc (リビジョン 8188) +++ dataobj/marker.cc (作業コピー) @@ -10,6 +10,7 @@ #include "marker.h" marker_t marker_t::the_instance; +marker_t marker_t::second_instance; void marker_t::init(int world_size_x, int world_size_y) @@ -37,6 +38,12 @@ return the_instance; } +marker_t& marker_t::instance_second(int world_size_x, int world_size_y) +{ + second_instance.init(world_size_x, world_size_y); + return second_instance; +} + marker_t::~marker_t() { delete [] bits; Index: dataobj/marker.h =================================================================== --- dataobj/marker.h (リビジョン 8188) +++ dataobj/marker.h (作業コピー) @@ -43,6 +43,7 @@ /// the instance static marker_t the_instance; + static marker_t second_instance; public: /** * Return handle to marker instance. @@ -53,6 +54,14 @@ static marker_t& instance(int world_size_x, int world_size_y); /** + * Return handle to marker instance. + * @param world_size_x x-size of map + * @param world_size_y y-size of map + * @returns handle to the singleton instance + */ + static marker_t& instance_second(int world_size_x, int world_size_y); + + /** * Marks tile as visited. */ void mark(const grund_t *gr); Index: simtool.cc =================================================================== --- simtool.cc (リビジョン 8188) +++ simtool.cc (作業コピー) @@ -2307,10 +2307,8 @@ { if( is_shift_pressed() && (desc->get_styp() == type_elevated && desc->get_wtyp() != air_wt) ) { grund_t *gr=welt->lookup(new_start); - if( weg_t *way = gr->get_weg( desc->get_waytype() ) ) { - if( way->get_desc()->get_styp() == type_elevated && welt->lookup(new_start-koord3d(0,0,welt->get_settings().get_way_height_clearance())) ) { - new_start.z -= welt->get_settings().get_way_height_clearance(); - } + if( gr->get_weg( desc->get_waytype() ) ) { + new_start.z -= welt->get_settings().get_way_height_clearance(); } } // elevated ways with SHIFT will selected the current layer, when already on an elevated way @@ -2390,23 +2388,22 @@ else { bauigel.set_keep_existing_faster_ways( true ); } - koord3d my_start = start; - // special check to replace elevated ways + + koord3d my_end = end; + // ending point is applied that elevated ways with SHIFT selects the current layer, when already on an elevated way if( is_shift_pressed() && (desc->get_styp() == type_elevated && desc->get_wtyp() != air_wt) ) { - grund_t *gr=welt->lookup(my_start); - if( weg_t *way = gr->get_weg( desc->get_waytype() ) ) { - if( way->get_desc()->get_styp() == type_elevated && welt->lookup( my_start + koord3d(0,0,welt->get_settings().get_way_height_clearance()) ) ) { - my_start.z += welt->get_settings().get_way_height_clearance(); - } + grund_t *gr=welt->lookup(my_end); + if( gr->get_weg( desc->get_waytype() ) ) { + my_end.z -= welt->get_settings().get_way_height_clearance(); } } // and continue as normal ... if( is_ctrl_pressed() || (env_t::straight_way_without_control && !env_t::networkmode && !is_scripted()) ) { DBG_MESSAGE("tool_build_way_t()", "try straight route"); - bauigel.calc_straight_route(my_start,end); + bauigel.calc_straight_route(start,my_end); } else { - bauigel.calc_route(my_start,end); + bauigel.calc_route(start,my_end); } DBG_MESSAGE("tool_build_way_t()", "builder found route with %d squares length.", bauigel.get_count()); }