Index: src/ship_cmd.cpp =================================================================== --- src/ship_cmd.cpp (revision 16021) +++ src/ship_cmd.cpp (working copy) @@ -558,6 +558,26 @@ } }; +/** Find ship in front and keep distance of 2 tiles between ships */ +static Vehicle *PutSpaceBetweenShipsEnum(Vehicle *v, void *data) +{ + const Vehicle *u = (Vehicle*)data; + if (v->type != VEH_SHIP || v->vehstatus & VS_STOPPED ) return NULL; + if (v->direction == ReverseDir(u->direction)) PlayShipSound(v); // imminent frontal collision + if (v->cur_speed <= u->cur_speed) v->cur_speed >>= 1; // go half speed to let other ship pass + + return v; +} + +static const DiagDirection _next_tile_direction[6][4] = { + { DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_NW }, + { DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_NW }, + { DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_NW, DIAGDIR_SW }, + { DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_NE, DIAGDIR_SW }, + { DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_SE, DIAGDIR_NE }, + { DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_SE, DIAGDIR_NE } +}; + static void ShipController(Vehicle *v) { uint32 r; @@ -660,6 +680,51 @@ track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks); if (track == INVALID_TRACK) goto reverse_direction; + assert(track != TRACK_END); + /*try to avoid collision and keep distance between each other*/ + TileIndex next_tile = TileAddByDiagDir(gp.new_tile, _next_tile_direction[track][diagdir]); + + if (HasVehicleOnPos(gp.new_tile, v, &PutSpaceBetweenShipsEnum) || HasVehicleOnPos(next_tile, v, &PutSpaceBetweenShipsEnum)) { + + switch (tracks) { + + case TRACK_BIT_NONE: break; + + case TRACK_BIT_3WAY_NE: + if (track != TRACK_X) { + track = TRACK_X; + } else { + track = TRACK_RIGHT; + } + break; + + case TRACK_BIT_3WAY_SE: + if (track != TRACK_Y) { + track = TRACK_Y; + } else { + track = TRACK_LOWER; + } + break; + + case TRACK_BIT_3WAY_SW: + if (track != TRACK_X) { + track = TRACK_X; + } else { + track = TRACK_LEFT; + } + break; + + case TRACK_BIT_3WAY_NW: + if (track != TRACK_Y) { + track = TRACK_Y; + } else { + track = TRACK_UPPER; + } + + default: break; + } + } + b = _ship_subcoord[diagdir][track]; gp.x = (gp.x & ~0xF) | b[0];