* Collision test function. * @param v %Train vehicle to test collision with. * @param t %Train being examined. * @return Number of victims. */
| 3203 | * @return Number of victims. |
| 3204 | */ |
| 3205 | static uint CheckTrainCollision(Vehicle *v, Train *t) |
| 3206 | { |
| 3207 | /* not a train or in depot */ |
| 3208 | if (v->type != VEH_TRAIN || Train::From(v)->track == TRACK_BIT_DEPOT) return 0; |
| 3209 | |
| 3210 | /* do not crash into trains of another company. */ |
| 3211 | if (v->owner != t->owner) return 0; |
| 3212 | |
| 3213 | /* get first vehicle now to make most usual checks faster */ |
| 3214 | Train *coll = Train::From(v)->First(); |
| 3215 | |
| 3216 | /* can't collide with own wagons */ |
| 3217 | if (coll == t) return 0; |
| 3218 | |
| 3219 | int x_diff = v->x_pos - t->x_pos; |
| 3220 | int y_diff = v->y_pos - t->y_pos; |
| 3221 | |
| 3222 | /* Do fast calculation to check whether trains are not in close vicinity |
| 3223 | * and quickly reject trains distant enough for any collision. |
| 3224 | * Differences are shifted by 7, mapping range [-7 .. 8] into [0 .. 15] |
| 3225 | * Differences are then ORed and then we check for any higher bits */ |
| 3226 | uint hash = (y_diff + 7) | (x_diff + 7); |
| 3227 | if (hash & ~15) return 0; |
| 3228 | |
| 3229 | /* Slower check using multiplication */ |
| 3230 | int min_diff = (Train::From(v)->gcache.cached_veh_length + 1) / 2 + (t->gcache.cached_veh_length + 1) / 2 - 1; |
| 3231 | if (x_diff * x_diff + y_diff * y_diff > min_diff * min_diff) return 0; |
| 3232 | |
| 3233 | /* Happens when there is a train under bridge next to bridge head */ |
| 3234 | if (abs(v->z_pos - t->z_pos) > 5) return 0; |
| 3235 | |
| 3236 | /* Crash both trains. Two statements required to guarantee execution |
| 3237 | * order because RandomRange() is involved. */ |
| 3238 | uint num_victims = TrainCrashed(t); |
| 3239 | return num_victims + TrainCrashed(coll); |
| 3240 | } |
| 3241 | |
| 3242 | /** |
| 3243 | * Checks whether the specified train has a collision with another vehicle. If |
no test coverage detected