diff -u -r sim_original/besch/reader/way_reader.cc sim_changed/besch/reader/way_reader.cc --- sim_original/besch/reader/way_reader.cc 2014-05-31 12:00:48.000000000 +0900 +++ sim_changed/besch/reader/way_reader.cc 2017-02-07 21:56:28.000000000 +0900 @@ -55,6 +55,7 @@ besch->obsolete_date = DEFAULT_RETIRE_DATE*12; besch->wt = road_wt; besch->styp = 0; + besch->overtaking_info = 0; besch->draw_as_obj = false; besch->number_seasons = 0; } @@ -63,7 +64,22 @@ const uint16 v = decode_uint16(p); version = v & 0x7FFF; - if(version==6) { + if(version==7) { + //version 7, now with overtaking_info + besch->cost = decode_uint32(p); + besch->maintenance = decode_uint32(p); + besch->topspeed = decode_uint32(p); + besch->max_weight = decode_uint32(p); + besch->intro_date = decode_uint16(p); + besch->obsolete_date = decode_uint16(p); + besch->axle_load = decode_uint16(p); + besch->wt = decode_uint8(p); + besch->styp = decode_uint8(p); + besch->overtaking_info = decode_sint8(p); //new + besch->draw_as_obj = decode_uint8(p); + besch->number_seasons = decode_sint8(p); + } + else if(version==6) { // version 6, now with axle load besch->cost = decode_uint32(p); besch->maintenance = decode_uint32(p); @@ -157,6 +173,10 @@ besch->axle_load = 9999; } + if( version < 7 ) { + besch->overtaking_info = 0; + } + // front images from version 5 on besch->front_images = version > 4; diff -u -r sim_original/besch/weg_besch.h sim_changed/besch/weg_besch.h --- sim_original/besch/weg_besch.h 2016-01-09 22:36:24.000000000 +0900 +++ sim_changed/besch/weg_besch.h 2017-02-07 23:19:43.000000000 +0900 @@ -68,6 +68,12 @@ bool front_images; /** + * Overtaking info (0 = overtaking is allowed, 1 = overtaking a loading convoy only, 2 = overtaking is completely forbidden) + * @author teamhimeH + */ + sint8 overtaking_info; + + /** * calculates index of image list for flat ways * for winter and/or front images * add +1 and +2 to get slope and straight diagonal images, respectively @@ -215,6 +221,10 @@ } void calc_checksum(checksum_t *chk) const; + + sint8 get_overtaking_info() const { + return overtaking_info; + } }; #endif diff -u -r sim_original/besch/writer/way_writer.cc sim_changed/besch/writer/way_writer.cc --- sim_original/besch/writer/way_writer.cc 2014-04-21 12:28:56.000000000 +0900 +++ sim_changed/besch/writer/way_writer.cc 2017-02-07 23:26:06.000000000 +0900 @@ -25,17 +25,18 @@ }; int ribi, hang; - obj_node_t node(this, 28, &parent); + obj_node_t node(this, 29, &parent); // Hajo: Version needs high bit set as trigger -> this is required // as marker because formerly nodes were unversionend - uint16 version = 0x8006; + uint16 version = 0x8007; uint32 price = obj.get_int("cost", 100); uint32 maintenance = obj.get_int("maintenance", 100); sint32 topspeed = obj.get_int("topspeed", 999); uint32 max_weight = obj.get_int("max_weight", 999); uint16 axle_load = obj.get_int("axle_load", 9999); + sint8 overtaking_info = obj.get_int("overtaking_info", 9999); uint16 intro = obj.get_int("intro_year", DEFAULT_INTRO_DATE) * 12; intro += obj.get_int("intro_month", 1) - 1; @@ -67,7 +68,8 @@ node.write_uint16(outfp, axle_load, 22); node.write_uint8 (outfp, wtyp, 24); node.write_uint8 (outfp, styp, 25); - node.write_uint8 (outfp, draw_as_ding, 26); + node.write_sint8 (outfp, overtaking_info, 26); + node.write_uint8 (outfp, draw_as_ding, 27); static const char* const image_type[] = { "", "front" }; @@ -76,7 +78,7 @@ sprintf(buf, "image[%s][0]", ribi_codes[0]); string str = obj.get(buf); if (str.empty()) { - node.write_data_at(outfp, &number_seasons, 27, 1); + node.write_data_at(outfp, &number_seasons, 28, 1); write_head(outfp, node, obj); sprintf(buf, "image[%s]", ribi_codes[0]); @@ -145,7 +147,7 @@ number_seasons++; } - node.write_data_at(outfp, &number_seasons, 27, 1); + node.write_data_at(outfp, &number_seasons, 28, 1); write_head(outfp, node, obj); // has switch images for both directions? diff -u -r sim_original/boden/wege/weg.h sim_changed/boden/wege/weg.h --- sim_original/boden/wege/weg.h 2015-01-24 20:36:34.000000000 +0900 +++ sim_changed/boden/wege/weg.h 2017-02-07 16:29:16.000000000 +0900 @@ -221,6 +221,12 @@ const char *get_name() const { return besch->get_name(); } /** + * Overtaking info (0 = overtaking is allowed, 1 = overtaking a loading convoy only, 2 = overtaking is completely forbidden) + * @author teamhimeH + */ + sint8 get_overtaking_info() const { return besch->get_overtaking_info(); } + + /** * Setzt neue Richtungsbits für einen Weg. * * Nachdem die ribis geändert werden, ist das weg_bild des diff -u -r sim_original/simconvoi.cc sim_changed/simconvoi.cc --- sim_original/simconvoi.cc 2016-02-01 20:38:42.000000000 +0900 +++ sim_changed/simconvoi.cc 2017-02-12 11:43:17.000000000 +0900 @@ -1,9 +1,10 @@ /** * convoi_t Class for vehicle associations - * Hansjörg Malthaner + * Hansj�rg Malthaner */ #include +#include #include "simdebug.h" #include "simunits.h" @@ -31,6 +32,7 @@ #include "gui/convoi_detail_t.h" #include "boden/grund.h" #include "boden/wege/schiene.h" // for railblocks +#include "boden/wege/strasse.h" #include "besch/vehikel_besch.h" #include "besch/roadsign_besch.h" @@ -127,6 +129,8 @@ wait_lock = 0; arrived_time = 0; + requested_change_lane = false; + jahresgewinn = 0; total_distance_traveled = 0; @@ -160,6 +164,7 @@ line_update_pending = linehandle_t(); home_depot = koord3d::invalid; + yielding_quit_index = -1; recalc_data_front = true; recalc_data = true; @@ -728,6 +733,10 @@ sum_gesamtgewicht += total_vehicle_weight; } } + if( get_yielding_quit_index() != -1 && speed_limit > kmh_to_speed(15) ) { + //When yielding lane, speed_limit is 15 kmph lower. + speed_limit -= kmh_to_speed(15); + } recalc_data = recalc_speed_limit = false; akt_speed_soll = min( speed_limit, brake_speed_soll ); } @@ -992,7 +1001,7 @@ /** * Berechne route von Start- zu Zielkoordinate - * @author Hanjsörg Malthaner + * @author Hansjörg Malthaner */ bool convoi_t::drive_to() { @@ -1131,7 +1140,7 @@ /** * Ein Fahrzeug hat ein Problem erkannt und erzwingt die * Berechnung einer neuen Route - * @author Hanjsörg Malthaner + * @author Hanjs�rg Malthaner */ void convoi_t::suche_neue_route() { @@ -1160,6 +1169,8 @@ case LOADING: laden(); + //When loading, vehicle should be on passing lane. + set_tiles_overtaking(0); break; case DUMMY4: @@ -1293,9 +1304,11 @@ if(restart_speed>=0) { akt_speed = restart_speed; } + /* if(state!=DRIVING) { set_tiles_overtaking( 0 ); } + */ } break; @@ -3529,9 +3542,11 @@ return false; } +/* if (!other_overtaker->can_be_overtaken()) { return false; } + */ if( other_speed == 0 ) { /* overtaking a loading convoi @@ -3547,6 +3562,12 @@ // also this is not possible, since a car loads in front of is!?! return false; } + //Overtaking info (0 = overtaking is allowed, 1 = overtaking a loading convoy only, 2 = overtaking is completely forbidden) + sint8 overtaking_info = str->get_overtaking_info(); + if( overtaking_info == 2 ){ + // This road prohibits overtaking. + return false; + } uint16 idx = fahr[0]->get_route_index(); const sint32 tiles = (steps_other-1)/(CARUNITS_PER_TILE*VEHICLE_STEPS_PER_CARUNIT) + get_tile_length() + 1; @@ -3568,11 +3589,15 @@ if( str->is_crossing() ) { return false; } + /* if( ribi_t::is_threeway(str->get_ribi()) ) { return false; } + */ // Check for other vehicles on the next tile const uint8 top = gr->get_top(); + //These conditions is abandoned to overtake in traffic jam. + /* for( uint8 j=1; j(gr->obj_bei(j)) ) { // check for other traffic on the road @@ -3587,15 +3612,33 @@ } } } + */ } convoi_t *ocnv = dynamic_cast(other_overtaker); set_tiles_overtaking( 2 + ocnv->get_length()/CARUNITS_PER_TILE + get_length()/CARUNITS_PER_TILE ); return true; } + // Around the end of route, overtaking should not be allowed. + if( get_route()->get_count() - fahr[0]->get_route_index() < 5 ) { + return false; + } + + // The flag whether the convoi is in traffic jam. When this is true, we must calculate overtaking in a different way. + bool in_congestion = false; int diff_speed = akt_speed - other_speed; if( diff_speed < kmh_to_speed(5) ) { - return false; + grund_t *gr = welt->lookup(get_pos()); + strasse_t *str=(strasse_t *)gr->get_weg(road_wt); + if( str==NULL ) { + printf("street is NULL!\n"); + return false; + }else if( akt_speed < fmin(max_power_speed, str->get_max_speed())/2 && diff_speed >= kmh_to_speed(0) ){ + //Warning: diff_speed == 0 is acceptable. We must consider the case diff_speed == 0. + in_congestion = true; + }else{ + return false; + } } // Number of tiles overtaking will take @@ -3604,10 +3647,16 @@ // Distance it takes overtaking (unit: vehicle_steps) = my_speed * time_overtaking // time_overtaking = tiles_to_overtake/diff_speed // tiles_to_overtake = convoi_length + current pos within tile + (pos_other_convoi within tile + length of other convoi) - one tile - int distance = akt_speed*(fahr[0]->get_steps()+get_length_in_steps()+steps_other-VEHICLE_STEPS_PER_TILE)/diff_speed; + int distance = 1; + if( !in_congestion ){ + distance = akt_speed*(fahr[0]->get_steps()+get_length_in_steps()+steps_other-VEHICLE_STEPS_PER_TILE)/diff_speed; + }else{ + distance = max_power_speed*(fahr[0]->get_steps()+get_length_in_steps()+steps_other-VEHICLE_STEPS_PER_TILE)/(max_power_speed-other_speed); + } + int time_overtaking = 0; - // Conditions for overtaking: + // Conditions for overtaking (originally): // Flat tiles, with no stops, no crossings, no signs, no change of road speed limit // First phase: no traffic except me and my overtaken car in the dangerous zone unsigned int route_index = fahr[0]->get_route_index()+1; @@ -3624,7 +3673,7 @@ pos_next = route.position_bei(route_index++); grund_t *gr = welt->lookup(pos); // no ground, or slope => about - if( gr==NULL || gr->get_weg_hang()!=hang_t::flach ) { + if( gr==NULL ) { return false; } @@ -3632,21 +3681,30 @@ if( str==NULL ) { return false; } + //Overtaking info (0 = overtaking is allowed, 1 = overtaking a loading convoy only, 2 = overtaking is completely forbidden) + sint8 overtaking_info = str->get_overtaking_info(); + if( overtaking_info != 0 ){ + // Since the other vehicle is moving... + return false; + } // the only roadsign we must account for are choose points and traffic lights if( str->has_sign() ) { const roadsign_t *rs = gr->find(1); if(rs) { const roadsign_besch_t *rb = rs->get_besch(); - if(rb->is_choose_sign() || rb->is_traffic_light() ) { + //We do not consider traffic-lights. This causes a drawing crash when vehicle stopped during overtaking. + if( rb->is_choose_sign() ) { // because we need to stop here ... return false; } } } // not overtaking on railroad crossings or on normal crossings ... + /* if( str->is_crossing() || ribi_t::is_threeway(str->get_ribi()) ) { return false; } + */ // street gets too slow (TODO: should be able to be correctly accounted for) if( akt_speed > kmh_to_speed(str->get_max_speed()) ) { return false; @@ -3664,7 +3722,12 @@ const overtaker_t *ov = v->get_overtaker(); if(ov) { if(this!=ov && other_overtaker!=ov) { - return false; + //If ov goes same directory, should not return false + ribi_t::ribi their_direction = ribi_t::rueckwaerts( fahr[0]->calc_direction(pos_prev, pos_next) ); + vehicle_base_t* const v = obj_cast(gr->obj_bei(j)); + if (v && v->get_direction() == their_direction && v->get_overtaker()) { + return false; + } } } else if( v->get_waytype()==road_wt && v->get_typ()!=obj_t::pedestrian ) { @@ -3727,8 +3790,9 @@ pos = pos_next; } - set_tiles_overtaking( 1+n_tiles ); - other_overtaker->set_tiles_overtaking( -1-(n_tiles*(akt_speed-diff_speed))/akt_speed ); + set_tiles_overtaking( 3+n_tiles ); + //The parameter about being overtaken is no longer meaningful. + //other_overtaker->set_tiles_overtaking( -1-(n_tiles*(akt_speed-diff_speed))/akt_speed ); return true; } @@ -3801,3 +3865,20 @@ return txt; } + +/* + * Functions to yield lane space to vehicles on passing lane. + * More natural movement controll is desired! + * @author teamhimeH + */ +void convoi_t::yield_lane_space() +{ + if( speed_limit > kmh_to_speed(15) ) { + uint32 quit_index = fahr[0]->get_route_index() + 3u; + if( quit_index >= get_route()->get_count() ) { + quit_index = get_route()->get_count() - 1u; + } + yielding_quit_index = quit_index; + must_recalc_speed_limit(); + } +} diff -u -r sim_original/simconvoi.h sim_changed/simconvoi.h --- sim_original/simconvoi.h 2016-01-09 22:36:24.000000000 +0900 +++ sim_changed/simconvoi.h 2017-02-12 11:57:14.000000000 +0900 @@ -267,6 +267,12 @@ uint32 arrived_time; /** + *The flag whether this convoi is requested to change lane by the convoi behind this. + *@author teamhimeH + */ + bool requested_change_lane; + + /** * accumulated profit over a year * @author Hanjsörg Malthaner */ @@ -397,6 +403,13 @@ uint32 move_to(uint16 start_index); + /** + * the route index of the point to quit yielding lane + * == -1 means this convoi isn't yielding. + * @author teamhimeH + */ + sint32 yielding_quit_index; + public: /** * Convoi haelt an Haltestelle und setzt quote fuer Fracht @@ -884,6 +897,16 @@ // Overtaking for convois virtual bool can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other); + + /* + * Functions related to requested_change_lane + * @author teamhimeH + */ + bool is_requested_change_lane() const { return requested_change_lane; } + void set_requested_change_lane(bool x) { requested_change_lane = x; } + void yield_lane_space(); + sint32 get_yielding_quit_index() const { return yielding_quit_index; } + void quit_yielding_lane() { yielding_quit_index = -1; must_recalc_speed_limit(); } }; #endif diff -u -r sim_original/vehicle/overtaker.h sim_changed/vehicle/overtaker.h --- sim_original/vehicle/overtaker.h 2015-11-29 19:51:22.000000000 +0900 +++ sim_changed/vehicle/overtaker.h 2017-02-07 14:08:44.000000000 +0900 @@ -60,6 +60,8 @@ virtual bool can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other) = 0; sint32 get_max_power_speed() const { return max_power_speed; } + + sint8 get_tiles_overtaking() const { return tiles_overtaking; } }; #endif diff -u -r sim_original/vehicle/simvehicle.cc sim_changed/vehicle/simvehicle.cc --- sim_original/vehicle/simvehicle.cc 2016-01-25 20:42:10.000000000 +0900 +++ sim_changed/vehicle/simvehicle.cc 2017-02-12 11:56:04.000000000 +0900 @@ -519,6 +519,8 @@ */ vehicle_base_t *vehicle_base_t::no_cars_blocking( const grund_t *gr, const convoi_t *cnv, const uint8 current_direction, const uint8 next_direction, const uint8 next_90direction ) { + bool cnv_overtaking = false;//whether this convoi is on passing lane. + if( cnv ) cnv_overtaking = cnv -> is_overtaking(); // Search vehicle for( uint8 pos=1; pos<(volatile uint8)gr->get_top(); pos++ ) { if( vehicle_base_t* const v = obj_cast(gr->obj_bei(pos)) ) { @@ -529,6 +531,7 @@ // check for car uint8 other_direction=255; bool other_moving = false; + bool other_overtaking = false; if( road_vehicle_t const* const at = obj_cast(v) ) { // ignore ourself if( cnv == at->get_convoi() ) { @@ -536,24 +539,27 @@ } other_direction = at->get_direction(); other_moving = at->get_convoi()->get_akt_speed() > kmh_to_speed(1); + other_overtaking = at->get_convoi()->is_overtaking();//whether the other convoi is on passing lane. } // check for city car else if( v->get_waytype() == road_wt ) { other_direction = v->get_direction(); if( private_car_t const* const sa = obj_cast(v) ){ other_moving = sa->get_current_speed() > 1; + other_overtaking = sa->is_overtaking(); } } - // ok, there is another car ... if( other_direction != 255 ) { - if( next_direction == other_direction && !ribi_t::is_threeway(gr->get_weg_ribi(road_wt)) ) { + if( next_direction == other_direction && !ribi_t::is_threeway(gr->get_weg_ribi(road_wt)) && cnv_overtaking == other_overtaking ) { + // only consider cars on same lane. // cars going in the same direction and no crossing => that mean blocking ... return v; } const ribi_t::ribi other_90direction = (gr->get_pos().get_2d() == v->get_pos_next().get_2d()) ? other_direction : calc_direction(gr->get_pos(), v->get_pos_next()); - if( other_90direction == next_90direction ) { + if( other_90direction == next_90direction && cnv_overtaking == other_overtaking ) { + //Whether this code is safe is not clear!!(can ignore cars on the other lane?) // Want to exit in same as other ~50% of the time return v; } @@ -561,7 +567,8 @@ const bool drives_on_left = welt->get_settings().is_drive_left(); const bool across = next_direction == (drives_on_left ? ribi_t::rotate45l(next_90direction) : ribi_t::rotate45(next_90direction)); // turning across the opposite directions lane const bool other_across = other_direction == (drives_on_left ? ribi_t::rotate45l(other_90direction) : ribi_t::rotate45(other_90direction)); // other is turning across the opposite directions lane - if( other_direction == next_direction && !(other_across || across) ) { + if( other_direction == next_direction && !(other_across || across) && cnv_overtaking == other_overtaking) { + // only consider cars on same lane. // entering same straight waypoint as other ~18% return v; } @@ -583,6 +590,7 @@ return v; } else if( other_direction == current_direction && current_90direction == ribi_t::keine ) { + // !It is not clear whether we should consider opposite lane in this case! // entering same diagonal waypoint as other ~1% return v; } @@ -2107,7 +2115,8 @@ uint32 test_index = route_index + 1u; // way should be clear for overtaking: we checked previously - if( !cnv->is_overtaking() ) { + // Now we have to consider even if convoi is overtaking! + //if( !cnv->is_overtaking() ) { // calculate new direction route_t const& r = *cnv->get_route(); koord3d next = route_index < r.get_count() - 1u ? r.position_bei(route_index + 1u) : pos_next; @@ -2121,6 +2130,43 @@ const bool drives_on_left = welt->get_settings().is_drive_left(); bool int_block = ribi_t::is_threeway(str->get_ribi_unmasked()) && (((drives_on_left ? ribi_t::rotate90l(curr_90direction) : ribi_t::rotate90(curr_90direction)) & str->get_ribi_unmasked()) || curr_90direction != next_90direction || (rs && rs->get_besch()->is_traffic_light())); + //If this convoi is overtaking, the convoi must avoid a head-on crash. + if( cnv->is_overtaking() ){ + while( test_index < route_index + 4u && test_index < r.get_count() ){ + grund_t *grn = welt->lookup(r.position_bei(test_index)); + for( uint8 pos=1; pos<(volatile uint8)grn->get_top(); pos++ ){ + if( vehicle_base_t* const v = obj_cast(grn->obj_bei(pos)) ){ + if( v->get_typ()==obj_t::pedestrian ) { + continue; + } + ribi_t::ribi other_direction=255; + if( road_vehicle_t const* const at = obj_cast(v) ) { + //ignore ourself + if( cnv == at->get_convoi() ){ + continue; + } + other_direction = at->get_direction(); + } + //check for city car + else if( v->get_waytype() == road_wt ) { + other_direction = v->get_direction(); + } + if( other_direction != 255 ){ + //There is another car. We have to check if this convoi is facing or not. + //calc_direction(next,get_pos()):opposite direction of next_direction. + if( calc_direction(next,get_pos()) == other_direction ) { + //printf("crash avoid. (%d,%d)\n", get_pos().x, get_pos().y); + cnv->set_tiles_overtaking(0); + } + } + } + } + test_index++; + } + } + + test_index = route_index + 1u;//reset test_index + // check exit from crossings and intersections, allow to proceed after 4 consecutive while( !obj && (str->is_crossing() || int_block) && test_index < r.get_count() && test_index < route_index + 4u ) { if( str->is_crossing() ) { @@ -2216,10 +2262,11 @@ } } } - } + //} // stuck message ... if( obj && !second_check_count ) { + /* if( obj->is_stuck() ) { // end of traffic jam, but no stuck message, because previous vehicle is stuck too restart_speed = 0; @@ -2227,23 +2274,50 @@ cnv->reset_waiting(); } else { + */ if( test_index == route_index + 1u ) { // no intersections or crossings, we might be able to overtake this one ... - overtaker_t *over = obj->get_overtaker(); - if( over && !over->is_overtaken() ) { + convoi_t *over = obj->get_overtaker_cv(); + if( over ) { + /* if( over->is_overtaking() ) { // otherwise we would stop every time being overtaken return true; } + */ // not overtaking/being overtake: we need to make a more thought test! if( road_vehicle_t const* const car = obj_cast(obj) ) { convoi_t* const ocnv = car->get_convoi(); - if( cnv->can_overtake( ocnv, (ocnv->get_state()==convoi_t::LOADING ? 0 : over->get_max_power_speed()), ocnv->get_length_in_steps()+ocnv->get_vehikel(0)->get_steps()) ) { + // yielding vehicle should not be overtaken by the vehicle whose maximum speed is same. + bool yielding_factor = true; + if( ocnv->get_yielding_quit_index() != -1 && this->get_speed_limit() - ocnv->get_speed_limit() < kmh_to_speed(10) ) { + yielding_factor = false; + } + if( !cnv->is_overtaking() && !other_lane_blocked() && yielding_factor && cnv->can_overtake( ocnv, (ocnv->get_state()==convoi_t::LOADING ? 0 : over->get_akt_speed()), ocnv->get_length_in_steps()+ocnv->get_vehikel(0)->get_steps()) ) { return true; } + strasse_t *str=(strasse_t *)gr->get_weg(road_wt); + sint32 cnv_max_speed = (int)fmin(cnv->get_speed_limit(), str->get_max_speed()*kmh_to_speed(1)); + sint32 other_max_speed = (int)fmin(ocnv->get_speed_limit(), str->get_max_speed()*kmh_to_speed(1)); + //printf("cnv=%d, other=%d, str=%d (%d,%d)\n", cnv_max_speed/kmh_to_speed(1),other_max_speed/kmh_to_speed(1),str->get_max_speed(), get_pos().x, get_pos().y); + if( cnv->is_overtaking() && kmh_to_speed(10) < cnv_max_speed - other_max_speed ) { + //If the convoi is on passing lane and there is slower convoi in front of this, this convoi request the slower to go to traffic lane. + ocnv->set_requested_change_lane(true); + } + //For the case that the faster convoi is on traffic lane. + if( !cnv->is_overtaking() && kmh_to_speed(10) < cnv_max_speed - other_max_speed ) { + if( vehicle_base_t* const br = car->other_lane_blocked() ) { + if( road_vehicle_t const* const blk = obj_cast(br) ) { + if( car->get_direction() == blk->get_direction() && abs(car->get_convoi()->get_speed_limit() - blk->get_convoi()->get_speed_limit()) < kmh_to_speed(5) ){ + //same direction && (almost) same speed vehicle exists. + ocnv->yield_lane_space(); + } + } + } + } } else if( private_car_t* const caut = obj_cast(obj) ) { - if( cnv->can_overtake(caut, caut->get_besch()->get_geschw(), VEHICLE_STEPS_PER_TILE) ) { + if( !cnv->is_overtaking() && !other_lane_blocked() && cnv->can_overtake(caut, caut->get_besch()->get_geschw(), VEHICLE_STEPS_PER_TILE) ) { return true; } } @@ -2251,8 +2325,7 @@ } // we have to wait ... restart_speed = (cnv->get_akt_speed()*3)/4; - cnv->set_tiles_overtaking(0); - } + //} } return obj==NULL; @@ -2267,6 +2340,54 @@ return cnv; } +//return overtaker in "convoi_t" +convoi_t* road_vehicle_t::get_overtaker_cv() +{ + return cnv; +} + +vehicle_base_t* road_vehicle_t::other_lane_blocked() const{ + //This function calculate whether the convoi can change lane. + //TODO: This function haven't considered city car! + if( leading ){ + route_t const& r = *cnv->get_route(); + //check whether there's no car in -1 ~ +1 section. + for(uint32 test_index = route_index < r.get_count() - 1u ? route_index + 1u : r.get_count() - 1u; test_index >= route_index - 1u; test_index--){ + grund_t *gr = welt->lookup(r.position_bei(test_index)); + for( uint8 pos=1; pos<(volatile uint8)gr->get_top(); pos++ ) { + if( vehicle_base_t* const v = obj_cast(gr->obj_bei(pos)) ) { + if( v->get_typ()==obj_t::pedestrian ) { + continue; + } + if( road_vehicle_t const* const at = obj_cast(v) ) { + // ignore ourself + if( cnv == at->get_convoi() ) { + continue; + } + if( cnv->is_overtaking() && at->get_convoi()->is_overtaking() ){ + continue; + } + if( !cnv->is_overtaking() && !(at->get_convoi()->is_overtaking()) ){ + //Prohibit going on passing lane when facing traffic exists. + ribi_t::ribi other_direction = at->get_direction(); + route_t const& r = *cnv->get_route(); + koord3d next = route_index < r.get_count() - 1u ? r.position_bei(route_index + 1u) : pos_next; + if( calc_direction(next,get_pos()) == other_direction ) { + return v; + } + continue; + } + return v; + } + } + } + if( test_index == 0 ) { + break; + } + } + } + return NULL; +} void road_vehicle_t::enter_tile(grund_t* gr) { @@ -2275,9 +2396,29 @@ const int cargo = get_total_cargo(); weg_t *str = gr->get_weg(road_wt); str->book(cargo, WAY_STAT_GOODS); - if (leading) { + if ( leading ) { str->book(1, WAY_STAT_CONVOIS); cnv->update_tiles_overtaking(); + //decide if overtaking convoi should go back to the traffic lane. + if( cnv->get_tiles_overtaking() == 1 && str->get_overtaking_info() == 0 ){ + if( vehicle_base_t* v = other_lane_blocked() ){ + //lane change denied + cnv->set_tiles_overtaking(3); + if( cnv->is_requested_change_lane() ) { + //request the blocking convoi to reduce speed. + if( road_vehicle_t const* const car = obj_cast(v) ) { + car->get_convoi()->yield_lane_space(); + } + } + } + else { + //lane change accepted + cnv->set_requested_change_lane(false); + } + } + if( cnv->get_yielding_quit_index() == route_index ) { + cnv->quit_yielding_lane(); + } } } diff -u -r sim_original/vehicle/simvehicle.h sim_changed/vehicle/simvehicle.h --- sim_original/vehicle/simvehicle.h 2015-11-29 19:51:22.000000000 +0900 +++ sim_changed/vehicle/simvehicle.h 2017-02-12 11:00:18.000000000 +0900 @@ -164,6 +164,7 @@ virtual void leave_tile(); virtual overtaker_t *get_overtaker() { return NULL; } + virtual convoi_t* get_overtaker_cv() { return NULL; } vehicle_base_t(); @@ -511,6 +512,9 @@ schedule_t * generate_new_schedule() const; virtual overtaker_t* get_overtaker(); + virtual convoi_t* get_overtaker_cv(); + + virtual vehicle_base_t* other_lane_blocked() const; };