Index: src/ship_cmd.cpp =================================================================== --- src/ship_cmd.cpp (revision 15986) +++ src/ship_cmd.cpp (working copy) @@ -558,6 +558,37 @@ } }; +/** 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 :) + + 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 +691,38 @@ 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)) { + if (tracks == TRACK_BIT_3WAY_NE) { + if (track != TRACK_X) { + track = TRACK_X; + } else { + track = TRACK_RIGHT; + } + } else if (tracks == TRACK_BIT_3WAY_SE) { + if (track != TRACK_Y) { + track = TRACK_Y; + } else { + track = TRACK_LOWER; + } + } else if (tracks == TRACK_BIT_3WAY_SW) { + if (track != TRACK_X) { + track = TRACK_X; + } else { + track = TRACK_LEFT; + } + } else if (tracks == TRACK_BIT_3WAY_NW) { + if (track != TRACK_Y) { + track = TRACK_Y; + } else { + track = TRACK_UPPER; + } + } + } + b = _ship_subcoord[diagdir][track]; gp.x = (gp.x & ~0xF) | b[0];