From 63e97754fbf907cfefd277087bfbac5e0d4434e8 Mon Sep 17 00:00:00 2001 From: truelight Date: Thu, 6 Jan 2005 22:31:58 +0000 Subject: [PATCH] (svn r1407) -Codechange: changed a lot around _stations, _vehicles, _towns and _industries (in prepare of dynamic arrays): - DEREF_XXX is changed into GetXXX - All direct call are directed via GetXXX - struct Industry has now an index-field - ENUM'd some stuff - Replaced home built loops with FOR_ALL_XXX - Added _stations_size, _vehicles_size, ... which gives the length of the array (which will be dynamic in the near future) - Changed lengtof(XXX) to _XXX_size (e.g. _stations_size) - Removed all endof(XXX) (because mostly it was part of a FOR_ALL_XXX) - Made the sort-functions of all 4 dynamic - Made all 4 Initialize functions more of the same - Some minor tab-fixing and stuff (tnx to Tron for proof-reading my 100kb patch ;)) Note for all: please do NOT directly call _stations, _vehicles, _towns and _industries, but use the right wrapper to access them. Thank you. Ps: please also do not use 'v++', where v is of type Vehicle *. --- ai.c | 29 +++++++++++---------- ai_new.c | 60 +++++++++++++++++++++---------------------- aircraft_cmd.c | 44 ++++++++++++++++---------------- aircraft_gui.c | 20 +++++++-------- disaster_cmd.c | 36 +++++++++++++------------- economy.c | 46 ++++++++++++++++----------------- engine.c | 17 ++++++++----- industry.h | 17 +++++++++++-- industry_cmd.c | 56 ++++++++++++++++++++++------------------ industry_gui.c | 28 ++++++++++---------- misc.c | 12 +++++---- news_gui.c | 2 +- oldloader.c | 48 +++++++++++++++++++++++++---------- order_cmd.c | 24 +++++++++--------- order_gui.c | 16 ++++++------ rail_cmd.c | 2 +- roadveh_cmd.c | 24 +++++++++--------- roadveh_gui.c | 16 ++++++------ ship_cmd.c | 14 +++++----- ship_gui.c | 22 ++++++++-------- station.h | 16 +++++++++--- station_cmd.c | 60 +++++++++++++++++++++++++------------------ station_gui.c | 37 +++++++++++++++------------ strings.c | 4 +-- subsidy_gui.c | 14 +++++----- town.h | 15 ++++++++--- town_cmd.c | 28 ++++++++++++-------- town_gui.c | 25 ++++++++++-------- train_cmd.c | 42 ++++++++++++++---------------- train_gui.c | 28 ++++++++++---------- ttd.c | 35 +++++++++++++++++++++++++ vehicle.c | 69 ++++++++++++++++++++++++++++++-------------------- vehicle.h | 15 ++++++++--- vehicle_gui.c | 54 +++++++++++++++++++++------------------ viewport.c | 4 +-- 35 files changed, 567 insertions(+), 412 deletions(-) diff --git a/ai.c b/ai.c index 0c647cf37c..9ca11cc70a 100644 --- a/ai.c +++ b/ai.c @@ -69,10 +69,11 @@ static void AiCase1(Player *p) static void AiStateVehLoop(Player *p) { Vehicle *v; + uint index; - v = p->ai.cur_veh == NULL ? _vehicles : p->ai.cur_veh+1; + index = (p->ai.cur_veh == NULL) ? 0 : p->ai.cur_veh->index + 1; - for (;v != endof(_vehicles); v++) { + FOR_ALL_VEHICLES_FROM(v, index) { if (v->type == 0 || v->owner != _current_player) continue; @@ -297,7 +298,7 @@ static void AiHandleReplaceTrain(Player *p) if (DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON) != CMD_ERROR && DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE) != CMD_ERROR) { veh = _new_train_id; - AiRestoreVehicleOrders(&_vehicles[veh], orderbak); + AiRestoreVehicleOrders(GetVehicle(veh), orderbak); DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN); DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); @@ -325,7 +326,7 @@ static void AiHandleReplaceRoadVeh(Player *p) if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH) != CMD_ERROR && DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH) != CMD_ERROR) { veh = _new_roadveh_id; - AiRestoreVehicleOrders(&_vehicles[veh], orderbak); + AiRestoreVehicleOrders(GetVehicle(veh), orderbak); DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH); DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); @@ -353,7 +354,7 @@ static void AiHandleReplaceAircraft(Player *p) if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT) != CMD_ERROR && DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT) != CMD_ERROR) { veh = _new_aircraft_id; - AiRestoreVehicleOrders(&_vehicles[veh], orderbak); + AiRestoreVehicleOrders(GetVehicle(veh), orderbak); DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT); DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); @@ -413,12 +414,12 @@ typedef struct FoundRoute { } FoundRoute; static Town *AiFindRandomTown() { - Town *t = DEREF_TOWN(RandomRange(_total_towns)); + Town *t = GetTown(RandomRange(_total_towns)); return (t->xy != 0) ? t : NULL; } static Industry *AiFindRandomIndustry() { - Industry *i = DEREF_INDUSTRY(RandomRange(_total_industries)); + Industry *i = GetIndustry(RandomRange(_total_industries)); return (i->xy != 0) ? i : NULL; } @@ -447,16 +448,16 @@ static void AiFindSubsidyIndustryRoute(FoundRoute *fr) return; fr->cargo = cargo; - fr->from = from = DEREF_INDUSTRY(s->from); + fr->from = from = GetIndustry(s->from); if (cargo == CT_GOODS || cargo == CT_FOOD) { - to_tow = DEREF_TOWN(s->to); + to_tow = GetTown(s->to); if (to_tow->population < (uint32)(cargo == CT_FOOD ? 200 : 900)) return; // error fr->to = to_tow; to_xy = to_tow->xy; } else { - to_ind = DEREF_INDUSTRY(s->to); + to_ind = GetIndustry(s->to); fr->to = to_ind; to_xy = to_ind->xy; } @@ -485,8 +486,8 @@ static void AiFindSubsidyPassengerRoute(FoundRoute *fr) return; fr->cargo = s->cargo_type; - fr->from = from = DEREF_TOWN(s->from); - fr->to = to = DEREF_TOWN(s->to); + fr->from = from = GetTown(s->from); + fr->to = to = GetTown(s->to); // They must be big enough if (from->population < 400 || to->population < 400) @@ -1416,7 +1417,7 @@ static void AiWantOilRigAircraftRoute(Player *p) t = AiFindRandomTown(); if (t != NULL) { // Find a random oil rig industry - in = DEREF_INDUSTRY(RandomRange(_total_industries)); + in = GetIndustry(RandomRange(_total_industries)); if (in != NULL && in->type == IT_OIL_RIG) { if (GetTileDist(t->xy, in->xy) < 60) break; @@ -2412,7 +2413,7 @@ handle_nocash: loco_id = _new_train_id; // Sell a vehicle if the train is double headed. - v = &_vehicles[loco_id]; + v = GetVehicle(loco_id); if (v->next != NULL) { i = p->ai.wagon_list[p->ai.num_wagons*2-2]; p->ai.wagon_list[p->ai.num_wagons*2-2] = INVALID_VEHICLE; diff --git a/ai_new.c b/ai_new.c index 66b28c4545..8a6dc0dd18 100644 --- a/ai_new.c +++ b/ai_new.c @@ -185,7 +185,7 @@ static void AiNew_State_ActionDone(Player *p) { // Check if a city or industry is good enough to start a route there static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) { if (type == AI_CITY) { - Town *t = DEREF_TOWN(ic); + Town *t = GetTown(ic); Station *st; int count = 0; int j = 0; @@ -247,7 +247,7 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) { return true; } if (type == AI_INDUSTRY) { - Industry *i = DEREF_INDUSTRY(ic); + Industry *i = GetIndustry(ic); Station *st; int count = 0; int j = 0; @@ -405,16 +405,16 @@ static void AiNew_State_LocateRoute(Player *p) { // is. if (p->ainew.from_type == AI_CITY && p->ainew.tbt == AI_BUS) { - int max_cargo = DEREF_TOWN(p->ainew.from_ic)->max_pass + DEREF_TOWN(p->ainew.temp)->max_pass; - max_cargo -= DEREF_TOWN(p->ainew.from_ic)->act_pass + DEREF_TOWN(p->ainew.temp)->act_pass; + int max_cargo = GetTown(p->ainew.from_ic)->max_pass + GetTown(p->ainew.temp)->max_pass; + max_cargo -= GetTown(p->ainew.from_ic)->act_pass + GetTown(p->ainew.temp)->act_pass; // max_cargo is now the amount of cargo we can move between the two cities // If it is more than the distance, we allow it - if (GetTileDist(DEREF_TOWN(p->ainew.from_ic)->xy, DEREF_TOWN(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) { + if (GetTileDist(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) { // We found a good city/industry, save the data of it p->ainew.to_ic = p->ainew.temp; p->ainew.state = AI_STATE_FIND_STATION; - DEBUG(ai,1)("[AiNew - LocateRoute] Found bus-route of %d tiles long (from %d to %d)",GetTileDist(DEREF_TOWN(p->ainew.from_ic)->xy, DEREF_TOWN(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp); + DEBUG(ai,1)("[AiNew - LocateRoute] Found bus-route of %d tiles long (from %d to %d)",GetTileDist(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp); p->ainew.from_tile = 0; p->ainew.to_tile = 0; @@ -427,12 +427,12 @@ static void AiNew_State_LocateRoute(Player *p) { int i; // TODO: in max_cargo, also check other cargo (beside [0]) // First we check if the from_ic produces cargo that this ic accepts - if (DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0] != 0xFF && DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0] != 0) { + if (GetIndustry(p->ainew.from_ic)->produced_cargo[0] != 0xFF && GetIndustry(p->ainew.from_ic)->total_production[0] != 0) { for (i=0;i<3;i++) { - if (DEREF_INDUSTRY(p->ainew.temp)->accepts_cargo[i] == 0xFF) break; - if (DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0] == DEREF_INDUSTRY(p->ainew.temp)->accepts_cargo[i]) { + if (GetIndustry(p->ainew.temp)->accepts_cargo[i] == 0xFF) break; + if (GetIndustry(p->ainew.from_ic)->produced_cargo[0] == GetIndustry(p->ainew.temp)->accepts_cargo[i]) { // Found a compatbiel industry - max_cargo = DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0] - DEREF_INDUSTRY(p->ainew.from_ic)->total_transported[0]; + max_cargo = GetIndustry(p->ainew.from_ic)->total_production[0] - GetIndustry(p->ainew.from_ic)->total_transported[0]; found = true; p->ainew.from_deliver = true; p->ainew.to_deliver = false; @@ -440,14 +440,14 @@ static void AiNew_State_LocateRoute(Player *p) { } } } - if (!found && DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0] != 0xFF && DEREF_INDUSTRY(p->ainew.temp)->total_production[0] != 0) { + if (!found && GetIndustry(p->ainew.temp)->produced_cargo[0] != 0xFF && GetIndustry(p->ainew.temp)->total_production[0] != 0) { // If not check if the current ic produces cargo that the from_ic accepts for (i=0;i<3;i++) { - if (DEREF_INDUSTRY(p->ainew.from_ic)->accepts_cargo[i] == 0xFF) break; - if (DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0] == DEREF_INDUSTRY(p->ainew.from_ic)->accepts_cargo[i]) { + if (GetIndustry(p->ainew.from_ic)->accepts_cargo[i] == 0xFF) break; + if (GetIndustry(p->ainew.temp)->produced_cargo[0] == GetIndustry(p->ainew.from_ic)->accepts_cargo[i]) { // Found a compatbiel industry found = true; - max_cargo = DEREF_INDUSTRY(p->ainew.temp)->total_production[0] - DEREF_INDUSTRY(p->ainew.from_ic)->total_transported[0]; + max_cargo = GetIndustry(p->ainew.temp)->total_production[0] - GetIndustry(p->ainew.from_ic)->total_transported[0]; p->ainew.from_deliver = false; p->ainew.to_deliver = true; break; @@ -457,17 +457,17 @@ static void AiNew_State_LocateRoute(Player *p) { if (found) { // Yeah, they are compatible!!! // Check the length against the amount of goods - if (GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy) > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE && - GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) { + if (GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE && + GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) { p->ainew.to_ic = p->ainew.temp; if (p->ainew.from_deliver) { - p->ainew.cargo = DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0]; + p->ainew.cargo = GetIndustry(p->ainew.from_ic)->produced_cargo[0]; } else { - p->ainew.cargo = DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0]; + p->ainew.cargo = GetIndustry(p->ainew.temp)->produced_cargo[0]; } p->ainew.state = AI_STATE_FIND_STATION; - DEBUG(ai,1)("[AiNew - LocateRoute] Found truck-route of %d tiles long (from %d to %d)",GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp); + DEBUG(ai,1)("[AiNew - LocateRoute] Found truck-route of %d tiles long (from %d to %d)",GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp); p->ainew.from_tile = 0; p->ainew.to_tile = 0; @@ -506,7 +506,7 @@ static bool AiNew_CheckVehicleStation(Player *p, Station *st) { if (sched != NULL) { for (; sched->type != OT_NOTHING; ++sched) { if (sched->type == OT_GOTO_STATION && - DEREF_STATION(sched->station) == st) { + GetStation(sched->station) == st) { // This vehicle has this city in his list count++; } @@ -533,19 +533,19 @@ static void AiNew_State_FindStation(Player *p) { if (p->ainew.from_tile == 0) { // First we scan for a station in the from-city if (p->ainew.from_type == AI_CITY) { - town = DEREF_TOWN(p->ainew.from_ic); + town = GetTown(p->ainew.from_ic); tile = town->xy; } else { - industry = DEREF_INDUSTRY(p->ainew.from_ic); + industry = GetIndustry(p->ainew.from_ic); tile = industry->xy; } } else if (p->ainew.to_tile == 0) { // Second we scan for a station in the to-city if (p->ainew.to_type == AI_CITY) { - town = DEREF_TOWN(p->ainew.to_ic); + town = GetTown(p->ainew.to_ic); tile = town->xy; } else { - industry = DEREF_INDUSTRY(p->ainew.to_ic); + industry = GetIndustry(p->ainew.to_ic); tile = industry->xy; } } else { @@ -682,8 +682,8 @@ static void AiNew_State_FindPath(Player *p) { // Init path_info if (p->ainew.from_tile == AI_STATION_RANGE) { // For truck routes we take a range around the industry - p->ainew.path_info.start_tile_tl = DEREF_INDUSTRY(p->ainew.from_ic)->xy - TILE_XY(1,1); - p->ainew.path_info.start_tile_br = DEREF_INDUSTRY(p->ainew.from_ic)->xy + TILE_XY(DEREF_INDUSTRY(p->ainew.from_ic)->width, DEREF_INDUSTRY(p->ainew.from_ic)->height) + TILE_XY(1,1); + p->ainew.path_info.start_tile_tl = GetIndustry(p->ainew.from_ic)->xy - TILE_XY(1,1); + p->ainew.path_info.start_tile_br = GetIndustry(p->ainew.from_ic)->xy + TILE_XY(GetIndustry(p->ainew.from_ic)->width, GetIndustry(p->ainew.from_ic)->height) + TILE_XY(1,1); p->ainew.path_info.start_direction = p->ainew.from_direction; } else { p->ainew.path_info.start_tile_tl = p->ainew.from_tile; @@ -692,8 +692,8 @@ static void AiNew_State_FindPath(Player *p) { } if (p->ainew.to_tile == AI_STATION_RANGE) { - p->ainew.path_info.end_tile_tl = DEREF_INDUSTRY(p->ainew.to_ic)->xy - TILE_XY(1,1); - p->ainew.path_info.end_tile_br = DEREF_INDUSTRY(p->ainew.to_ic)->xy + TILE_XY(DEREF_INDUSTRY(p->ainew.to_ic)->width, DEREF_INDUSTRY(p->ainew.to_ic)->height) + TILE_XY(1,1); + p->ainew.path_info.end_tile_tl = GetIndustry(p->ainew.to_ic)->xy - TILE_XY(1,1); + p->ainew.path_info.end_tile_br = GetIndustry(p->ainew.to_ic)->xy + TILE_XY(GetIndustry(p->ainew.to_ic)->width, GetIndustry(p->ainew.to_ic)->height) + TILE_XY(1,1); p->ainew.path_info.end_direction = p->ainew.to_direction; } else { p->ainew.path_info.end_tile_tl = p->ainew.to_tile; @@ -847,9 +847,9 @@ static int AiNew_HowManyVehicles(Player *p) { // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done! tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16; if (p->ainew.from_deliver) - max_cargo = DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0]; + max_cargo = GetIndustry(p->ainew.from_ic)->total_production[0]; else - max_cargo = DEREF_INDUSTRY(p->ainew.to_ic)->total_production[0]; + max_cargo = GetIndustry(p->ainew.to_ic)->total_production[0]; // This is because moving 60% is more than we can dream of! max_cargo *= 0.6; diff --git a/aircraft_cmd.c b/aircraft_cmd.c index 082759ab5b..d351eb6477 100644 --- a/aircraft_cmd.c +++ b/aircraft_cmd.c @@ -217,7 +217,7 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) const AirportFTAClass *Airport; const TileIndexDiffC *cur_depot; byte i = 0; - st = DEREF_STATION(_map2[tile]); + st = GetStation(_map2[tile]); Airport = GetAirport(st->airport_type); for (cur_depot = Airport->airport_depots; i != Airport->nof_depots; cur_depot++) { if ((uint)(st->airport_tile + ToTileIndexDiff(*cur_depot)) == tile) { @@ -311,7 +311,7 @@ int32 CmdSellAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner) || !CheckStoppedInHangar(v)) return CMD_ERROR; @@ -332,7 +332,7 @@ int32 CmdStartStopAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -357,7 +357,7 @@ int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2) Vehicle *v; Station *st; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -370,7 +370,7 @@ int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2) InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); } } else { - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); // If an airport doesn't have terminals (so no landing space for airports), // it surely doesn't have any hangars if (st->xy == 0 || st->airport_tile == 0 || GetAirport(st->airport_type)->nofterminals == 0) @@ -393,7 +393,7 @@ int32 CmdChangeAircraftServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -419,7 +419,7 @@ int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN); - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner) || (!CheckStoppedInHangar(v) && !(SkipStoppedInHangerCheck))) return CMD_ERROR; @@ -481,7 +481,7 @@ static void CheckIfAircraftNeedsService(Vehicle *v) if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr)) return; - st = DEREF_STATION(v->current_order.station); + st = GetStation(v->current_order.station); // only goto depot if the target airport has terminals (eg. it is airport) if (st->xy != 0 && st->airport_tile != 0 && GetAirport(st->airport_type)->nofterminals != 0) { // printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); @@ -720,7 +720,7 @@ static bool Aircraft_5(Vehicle *v) uint dist; int x,y; - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); // prevent going to 0,0 if airport is deleted. { @@ -925,7 +925,7 @@ static void HandleCrashedAircraft(Vehicle *v) v->u.air.crashed_counter++; - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); // make aircraft crash down to the ground if ( st->airport_tile==0 && ((v->u.air.crashed_counter % 3) == 0) ) { @@ -1112,7 +1112,7 @@ static void CrashAirplane(Vehicle *v) v->cargo_count = 0; v->next->cargo_count = 0, - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); if(st->airport_tile==0) { newsitem = STR_PLANE_CRASH_OUT_OF_FUEL; } else { @@ -1135,7 +1135,7 @@ static void MaybeCrashAirplane(Vehicle *v) uint16 prob; int i; - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); //FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports prob = 0x10000 / 1500; @@ -1164,7 +1164,7 @@ static void AircraftEntersTerminal(Vehicle *v) if (v->current_order.type == OT_GOTO_DEPOT) return; - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); v->last_station_visited = v->u.air.targetairport; /* Check if station was ever visited before */ @@ -1253,7 +1253,7 @@ static void AircraftNextAirportPos_and_Order(Vehicle *v) v->current_order.type == OT_GOTO_DEPOT) v->u.air.targetairport = v->current_order.station; - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); Airport = GetAirport(st->airport_type); v->u.air.pos = v->u.air.previous_pos = Airport->entry_point; } @@ -1423,7 +1423,7 @@ static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *Airpo AirportFTA *current; uint16 tcur_speed, tsubspeed; - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); // flying device is accepted at this station // small airport --> no helicopters (AIRCRAFT_ONLY) // all other airports --> all types of flying devices (ALL) @@ -1537,7 +1537,7 @@ static void AirportClearBlock(Vehicle *v, const AirportFTAClass *Airport) Station *st; // we have left the previous block, and entered the new one. Free the previous block if (Airport->layout[v->u.air.previous_pos].block != Airport->layout[v->u.air.pos].block) { - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); CLRBITS(st->airport_flags, Airport->layout[v->u.air.previous_pos].block); } } @@ -1613,7 +1613,7 @@ static bool AirportHasBlock(Vehicle *v, AirportFTA *current_pos, const AirportFT // same block, then of course we can move if (Airport->layout[current_pos->position].block != next->block) { airport_flags = next->block; - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); // check additional possible extra blocks if (current_pos != reference && current_pos->block != NOTHING_block) { airport_flags |= current_pos->block; @@ -1640,7 +1640,7 @@ static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportF // if the next position is in another block, check it and wait until it is free if (Airport->layout[current_pos->position].block != next->block) { airport_flags = next->block; - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); //search for all all elements in the list with the same state, and blocks != N // this means more blocks should be checked/set current = current_pos; @@ -1672,7 +1672,7 @@ static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportF static bool FreeTerminal(Vehicle *v, byte i, byte last_terminal) { - Station *st = DEREF_STATION(v->u.air.targetairport); + Station *st = GetStation(v->u.air.targetairport); for (; i < last_terminal; i++) { if (!HASBIT(st->airport_flags, i)) { // TERMINAL# HELIPAD# @@ -1701,7 +1701,7 @@ static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *Airport) fails, then attempt fails and plane waits */ if (Airport->nofterminalgroups > 1) { - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); nofterminalspergroup = Airport->nofterminals / Airport->nofterminalgroups; temp = Airport->layout[v->u.air.pos].next_in_chain; while (temp != NULL) { @@ -1734,7 +1734,7 @@ static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *Airport) // if there are more helicoptergroups, pick one, just as in AirportFindFreeTerminal() if (Airport->nofhelipadgroups > 1) { - st = DEREF_STATION(v->u.air.targetairport); + st = GetStation(v->u.air.targetairport); nofhelipadspergroup = Airport->nofhelipads / Airport->nofhelipadgroups; temp = Airport->layout[v->u.air.pos].next_in_chain; while (temp != NULL) { @@ -1787,7 +1787,7 @@ static void AircraftEventHandler(Vehicle *v, int loop) // pass the right airport structure to the functions // DEREF_STATION gets target airport (Station *st), its type is passed to GetAirport // that returns the correct layout depending on type - AirportGoToNextPosition(v, GetAirport(DEREF_STATION(v->u.air.targetairport)->airport_type)); + AirportGoToNextPosition(v, GetAirport(GetStation(v->u.air.targetairport)->airport_type)); } void Aircraft_Tick(Vehicle *v) diff --git a/aircraft_gui.c b/aircraft_gui.c index 5bf84875c2..0228e36919 100644 --- a/aircraft_gui.c +++ b/aircraft_gui.c @@ -51,7 +51,7 @@ void CcBuildAircraft(bool success, uint tile, uint32 p1, uint32 p2) Vehicle *v; if (success) { - v = &_vehicles[_new_aircraft_id]; + v = GetVehicle(_new_aircraft_id); if (v->tile == _backup_orders_tile) { _backup_orders_tile = 0; RestoreVehicleOrders(v, _backup_orders_data); @@ -217,7 +217,7 @@ static void AircraftRefitWndProc(Window *w, WindowEvent *e) { switch(e->event) { case WE_PAINT: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); const byte *b; int sel; int x,y; @@ -296,7 +296,7 @@ static void AircraftRefitWndProc(Window *w, WindowEvent *e) } break; case 4: /* refit button */ if (WP(w,refit_d).cargo != 0xFF) { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT))) DeleteWindow(w); } @@ -339,7 +339,7 @@ static void ShowAircraftRefitWindow(Vehicle *v) static void AircraftDetailsWndProc(Window *w, WindowEvent *e) { int mod; - Vehicle *v = &_vehicles[w->window_number], *u; + Vehicle *v = GetVehicle(w->window_number), *u; switch(e->event) { case WE_PAINT: @@ -534,7 +534,7 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e) { switch(e->event) { case WE_PAINT: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); uint32 disabled = 1<<8; StringID str; @@ -595,7 +595,7 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e) } break; case WE_CLICK: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); switch(e->click.widget) { case 5: /* start stop */ @@ -832,7 +832,7 @@ static void AircraftDepotWndProc(Window *w, WindowEvent *e) HandleButtonClick(w, 5); - v = &_vehicles[WP(w,traindepot_d).sel]; + v = GetVehicle(WP(w,traindepot_d).sel); WP(w,traindepot_d).sel = INVALID_VEHICLE; _backup_orders_tile = v->tile; @@ -979,7 +979,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e) w->widget[1].unkA = STR_A009_AIRCRAFT; } else { /* Station Name -- (###) Aircraft */ - SetDParam(0, DEREF_STATION(station)->index); + SetDParam(0, GetStation(station)->index); SetDParam(1, w->vscroll.count); w->widget[1].unkA = STR_SCHEDULED_AIRCRAFT; } @@ -993,7 +993,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e) max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); for (i = w->vscroll.pos; i < max; ++i) { - Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); + Vehicle *v = GetVehicle(vl->sort_list[i].index); StringID str; assert(v->type == VEH_Aircraft && v->subtype <= 2); @@ -1047,7 +1047,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e) if (id_v >= vl->list_length) return; // click out of list bound - v = DEREF_VEHICLE(vl->sort_list[id_v].index); + v = GetVehicle(vl->sort_list[id_v].index); assert(v->type == VEH_Aircraft && v->subtype <= 2); diff --git a/disaster_cmd.c b/disaster_cmd.c index 88da6afab6..a00bedcf11 100644 --- a/disaster_cmd.c +++ b/disaster_cmd.c @@ -193,7 +193,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v) IS_BYTE_INSIDE(_map5[tile], 8, 0x43) && IS_HUMAN_PLAYER(_map_owner[tile])) { - st = DEREF_STATION(_map2[tile]); + st = GetStation(_map2[tile]); CLRBITS(st->airport_flags, RUNWAY_IN_block); } @@ -235,7 +235,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v) IS_BYTE_INSIDE(_map5[tile], 8, 0x43) && IS_HUMAN_PLAYER(_map_owner[tile])) { - st = DEREF_STATION(_map2[tile]); + st = GetStation(_map2[tile]); SETBITS(st->airport_flags, RUNWAY_IN_block); } } @@ -278,7 +278,7 @@ static void DisasterTick_UFO(Vehicle *v) DeleteDisasterVeh(v); } else { // target a vehicle - u = &_vehicles[v->dest_tile]; + u = GetVehicle(v->dest_tile); if (u->type != VEH_Road) { DeleteDisasterVeh(v); return; @@ -323,10 +323,9 @@ static void DisasterTick_UFO(Vehicle *v) static void DestructIndustry(Industry *i) { uint tile; - byte index = i - _industries; for(tile=0; tile != MapSize(); tile++) { - if (IS_TILETYPE(tile, MP_INDUSTRY) && _map2[tile] == index) { + if (IS_TILETYPE(tile, MP_INDUSTRY) && _map2[tile] == i->index) { _map_owner[tile] = 0; MarkTileDirtyByTile(tile); } @@ -352,7 +351,7 @@ static void DisasterTick_2(Vehicle *v) if (v->current_order.station == 2) { if (!(v->tick_counter&3)) { - Industry *i = DEREF_INDUSTRY(v->dest_tile); + Industry *i = GetIndustry(v->dest_tile); int x = GET_TILE_X(i->xy)*16; int y = GET_TILE_Y(i->xy)*16; uint32 r = Random(); @@ -373,7 +372,7 @@ static void DisasterTick_2(Vehicle *v) v->current_order.station = 2; v->age = 0; - i = DEREF_INDUSTRY(v->dest_tile); + i = GetIndustry(v->dest_tile); DestructIndustry(i); SetDParam(0, i->town->index); @@ -397,7 +396,7 @@ static void DisasterTick_2(Vehicle *v) v->dest_tile = ind = _map2[tile]; - if (DEREF_INDUSTRY(ind)->type == IT_OIL_REFINERY) { + if (GetIndustry(ind)->type == IT_OIL_REFINERY) { v->current_order.station = 1; v->age = 0; } @@ -423,7 +422,7 @@ static void DisasterTick_3(Vehicle *v) if (v->current_order.station == 2) { if (!(v->tick_counter&3)) { - Industry *i = DEREF_INDUSTRY(v->dest_tile); + Industry *i = GetIndustry(v->dest_tile); int x = GET_TILE_X(i->xy)*16; int y = GET_TILE_Y(i->xy)*16; uint32 r = Random(); @@ -444,7 +443,7 @@ static void DisasterTick_3(Vehicle *v) v->current_order.station = 2; v->age = 0; - i = DEREF_INDUSTRY(v->dest_tile); + i = GetIndustry(v->dest_tile); DestructIndustry(i); SetDParam(0, i->town->index); @@ -468,7 +467,7 @@ static void DisasterTick_3(Vehicle *v) v->dest_tile = ind = _map2[tile]; - if (DEREF_INDUSTRY(ind)->type == IT_FACTORY) { + if (GetIndustry(ind)->type == IT_FACTORY) { v->current_order.station = 1; v->age = 0; } @@ -600,7 +599,7 @@ static void DisasterTick_4b(Vehicle *v) } if (v->current_order.station == 0) { - u = &_vehicles[v->u.disaster.unk2]; + u = GetVehicle(v->u.disaster.unk2); if (abs(v->x_pos - u->x_pos) > 16) return; v->current_order.station = 1; @@ -701,18 +700,17 @@ static void Disaster0_Init() if (v == NULL) return; - for(st=_stations;;) { + /* Pick a random place, unless we find + a small airport */ + x = (GET_TILE_X(Random())) * 16 + 8; + + FOR_ALL_STATIONS(st) { if (st->xy && st->airport_tile != 0 && st->airport_type <= 1 && IS_HUMAN_PLAYER(st->owner)) { x = (GET_TILE_X(st->xy) + 2) * 16; break; } - - if (++st == endof(_stations)) { - x = (GET_TILE_X(Random())) * 16 + 8; - break; - } } InitializeDisasterVehicle(v, x, 0, 135, 3, 0); @@ -721,7 +719,7 @@ static void Disaster0_Init() u = ForceAllocateSpecialVehicle(); if (u != NULL) { v->next = u; - InitializeDisasterVehicle(u,x,0,0,3,1); + InitializeDisasterVehicle(u, x, 0, 0, 3, 1); u->vehstatus |= VS_DISASTER; } } diff --git a/economy.c b/economy.c index a8925f87fa..e15b3bc67a 100644 --- a/economy.c +++ b/economy.c @@ -270,7 +270,7 @@ void ChangeOwnershipOfPlayerItems(byte old_player, byte new_player) for(s=_subsidies; s != endof(_subsidies); s++) { if (s->cargo_type != 0xff && s->age >= 12) { - Station *st = DEREF_STATION(s->to); + Station *st = GetStation(s->to); if (st->owner == old_player) s->cargo_type = 0xff; } @@ -798,7 +798,7 @@ Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode) if (s->age < 12) { if (!(s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL)) { SetDParam(1, STR_2029); - i = DEREF_INDUSTRY(s->from); + i = GetIndustry(s->from); tile = i->xy; SetDParam(2, i->town->townnametype); SetDParam(3, i->town->townnameparts); @@ -807,34 +807,34 @@ Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode) if (s->cargo_type != CT_GOODS && s->cargo_type != CT_FOOD) { SetDParam(5, STR_2029); - i = DEREF_INDUSTRY(s->to); + i = GetIndustry(s->to); tile2 = i->xy; SetDParam(8, i->type + STR_4802_COAL_MINE); SetDParam(6, i->town->townnametype); SetDParam(7, i->town->townnameparts); } else { - t = DEREF_TOWN(s->to); + t = GetTown(s->to); tile2 = t->xy; SetDParam(5, t->townnametype); SetDParam(6, t->townnameparts); } } else { - t = DEREF_TOWN(s->from); + t = GetTown(s->from); tile = t->xy; SetDParam(1, t->townnametype); SetDParam(2, t->townnameparts); - t = DEREF_TOWN(s->to); + t = GetTown(s->to); tile2 = t->xy; SetDParam(3, t->townnametype); SetDParam(4, t->townnameparts); } } else { - st = DEREF_STATION(s->from); + st = GetStation(s->from); tile = st->xy; SetDParam(1, st->index); - st = DEREF_STATION(s->to); + st = GetStation(s->to); tile2 = st->xy; SetDParam(2, st->index); } @@ -888,11 +888,11 @@ static void FindSubsidyPassengerRoute(FoundRoute *fr) fr->distance = (uint)-1; - fr->from = from = DEREF_TOWN(RandomRange(_total_towns)); + fr->from = from = GetTown(RandomRange(_total_towns)); if (from->xy == 0 || from->population < 400) return; - fr->to = to = DEREF_TOWN(RandomRange(_total_towns)); + fr->to = to = GetTown(RandomRange(_total_towns)); if (from==to || to->xy == 0 || to->population < 400 || to->pct_pass_transported > 42) return; @@ -907,7 +907,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr) fr->distance = (uint)-1; - fr->from = i = DEREF_INDUSTRY(RandomRange(_total_industries)); + fr->from = i = GetIndustry(RandomRange(_total_industries)); if (i->xy == 0) return; @@ -932,7 +932,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr) if (cargo == CT_GOODS || cargo == CT_FOOD) { // The destination is a town - Town *t = DEREF_TOWN(RandomRange(_total_towns)); + Town *t = GetTown(RandomRange(_total_towns)); // Only want big towns if (t->xy == 0 || t->population < 900) @@ -941,7 +941,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr) fr->to = t; } else { // The destination is an industry - Industry *i2 = DEREF_INDUSTRY(RandomRange(_total_industries)); + Industry *i2 = GetIndustry(RandomRange(_total_industries)); // The industry must accept the cargo if (i == i2 || i2->xy == 0 || @@ -1008,7 +1008,7 @@ static void SubsidyMonthlyHandler() s->cargo_type = 0xFF; modified = true; } else if (s->age == 2*12-1) { - st = DEREF_STATION(s->to); + st = GetStation(s->to); if (st->owner == _local_player) { pair = SetupSubsidyDecodeParam(s, 1); AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b); @@ -1041,8 +1041,8 @@ static void SubsidyMonthlyHandler() FindSubsidyCargoRoute(&fr); if (fr.distance <= 70) { s->cargo_type = fr.cargo; - s->from = (Industry*)fr.from - _industries; - s->to = (fr.cargo == CT_GOODS || fr.cargo == CT_FOOD) ? ((Town*)fr.to)->index : (Industry*)fr.to - _industries; + s->from = ((Industry*)fr.from)->index; + s->to = (fr.cargo == CT_GOODS || fr.cargo == CT_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index; add_subsidy: if (!CheckSubsidyDuplicate(s)) { s->age = 0; @@ -1167,18 +1167,18 @@ static bool CheckSubsidised(Station *from, Station *to, byte cargo_type) /* Check distance from source */ if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL) { - xy = DEREF_TOWN(s->from)->xy; + xy = GetTown(s->from)->xy; } else { - xy = (DEREF_INDUSTRY(s->from))->xy; + xy = (GetIndustry(s->from))->xy; } if (GetTileDist1D(xy, from->xy) > 9) continue; /* Check distance from dest */ if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL || cargo_type == CT_GOODS || cargo_type == CT_FOOD) { - xy = DEREF_TOWN(s->to)->xy; + xy = GetTown(s->to)->xy; } else { - xy = (DEREF_INDUSTRY(s->to))->xy; + xy = (GetIndustry(s->to))->xy; } if (GetTileDist1D(xy, to->xy) > 9) @@ -1224,8 +1224,8 @@ static int32 DeliverGoods(int num_pieces, byte cargo_type, byte source, byte des } // Get station pointers. - s_from = DEREF_STATION(source); - s_to = DEREF_STATION(dest); + s_from = GetStation(source); + s_to = GetStation(dest); // Check if a subsidy applies. subsidised = CheckSubsidised(s_from, s_to, cargo_type); @@ -1349,7 +1349,7 @@ int LoadUnloadVehicle(Vehicle *v) old_player = _current_player; _current_player = v->owner; - st = DEREF_STATION(last_visited = v->last_station_visited); + st = GetStation(last_visited = v->last_station_visited); for (; v != NULL; v = v->next) { if (v->cargo_cap == 0) continue; diff --git a/engine.c b/engine.c index 734f507dcd..12d1c7d803 100644 --- a/engine.c +++ b/engine.c @@ -737,17 +737,22 @@ static void NewVehicleAvailable(Engine *e) // prevent that player from getting future intro periods for a while. if (e->flags&ENGINE_INTRODUCING) { FOR_ALL_PLAYERS(p) { + uint block_preview = p->block_preview; + if (!HASBIT(e->player_avail,p->index)) continue; - for(v=_vehicles;;) { + /* We assume the user did NOT build it.. prove me wrong ;) */ + p->block_preview = 20; + + FOR_ALL_VEHICLES(v) { if (v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship || (v->type == VEH_Aircraft && v->subtype <= 2)) { - if (v->owner == p->index && v->engine_type == index) break; - } - if (++v == endof(_vehicles)) { - p->block_preview = 20; - break; + if (v->owner == p->index && v->engine_type == index) { + /* The user did prove me wrong, so restore old value */ + p->block_preview = block_preview; + break; + } } } } diff --git a/industry.h b/industry.h index 852f23bbdb..81e030ed11 100644 --- a/industry.h +++ b/industry.h @@ -23,12 +23,25 @@ struct Industry { byte color_map; byte last_prod_year; byte was_cargo_delivered; + + uint16 index; }; VARDEF int _total_industries; // For the AI: the amount of industries active + VARDEF Industry _industries[90]; -#define DEREF_INDUSTRY(i) (&_industries[i]) -#define FOR_ALL_INDUSTRIES(i) for(i = _industries; i != endof(_industries); i++) +VARDEF uint _industries_size; + +VARDEF uint16 *_industry_sort; + +static inline Industry *GetIndustry(uint index) +{ + assert(index < _industries_size); + return &_industries[index]; +} + +#define FOR_ALL_INDUSTRIES(i) for(i = _industries; i != &_industries[_industries_size]; i++) + VARDEF bool _industry_sort_dirty; void DeleteIndustry(Industry *is); diff --git a/industry_cmd.c b/industry_cmd.c index 3b4aceb38f..5014daae55 100644 --- a/industry_cmd.c +++ b/industry_cmd.c @@ -282,7 +282,7 @@ static void DrawTile_Industry(TileInfo *ti) uint32 image, ormod; /* Pointer to industry */ - ind = DEREF_INDUSTRY(_map2[ti->tile]); + ind = GetIndustry(_map2[ti->tile]); ormod = (ind->color_map+0x307)<<16; /* Retrieve pointer to the draw industry tile struct */ @@ -358,7 +358,7 @@ static void GetAcceptedCargo_Industry(uint tile, AcceptedCargo ac) static void GetTileDesc_Industry(uint tile, TileDesc *td) { - Industry *i = DEREF_INDUSTRY(_map2[tile]); + Industry *i = GetIndustry(_map2[tile]); td->owner = i->owner; td->str = STR_4802_COAL_MINE + i->type; @@ -370,7 +370,7 @@ static void GetTileDesc_Industry(uint tile, TileDesc *td) static int32 ClearTile_Industry(uint tile, byte flags) { - Industry *i = DEREF_INDUSTRY(_map2[tile]); + Industry *i = GetIndustry(_map2[tile]); /* * water can destroy industries * in editor you can bulldoze industries @@ -395,7 +395,7 @@ static int32 ClearTile_Industry(uint tile, byte flags) int32 CmdDestroyIndustry(int x, int y, uint32 flags, uint32 p1, uint32 p2) { uint tile = TILE_FROM_XY(x,y); - Industry *i = DEREF_INDUSTRY((uint16)p1); + Industry *i = GetIndustry((uint16)p1); Town *t = ClosestTownFromTile(tile, (uint)-1); // find closest town to penaltize (ALWAYS penaltize) SET_EXPENSES_TYPE(EXPENSES_OTHER); @@ -430,7 +430,7 @@ static void TransportIndustryGoods(uint tile) uint cw, am; byte m5; - i = DEREF_INDUSTRY(_map2[tile]); + i = GetIndustry(_map2[tile]); type = i->type; cw = min(i->cargo_waiting[0], 255); @@ -784,7 +784,7 @@ static void TileLoop_Industry(uint tile) case 143: { - Industry *i = DEREF_INDUSTRY(_map2[tile]); + Industry *i = GetIndustry(_map2[tile]); if (i->was_cargo_delivered) { i->was_cargo_delivered = false; if ((_map3_hi[tile]|_map3_lo[tile]) != 0) @@ -823,7 +823,7 @@ static uint32 GetTileTrackStatus_Industry(uint tile, TransportType mode) static void GetProducedCargo_Industry(uint tile, byte *b) { - Industry *i = DEREF_INDUSTRY(_map2[tile]); + Industry *i = GetIndustry(_map2[tile]); b[0] = i->produced_cargo[0]; b[1] = i->produced_cargo[1]; } @@ -835,22 +835,20 @@ static void ChangeTileOwner_Industry(uint tile, byte old_player, byte new_player void DeleteIndustry(Industry *i) { - int index = i - _industries; - - BEGIN_TILE_LOOP(tile_cur, i->width, i->height, i->xy); + BEGIN_TILE_LOOP(tile_cur, i->width, i->height, i->xy); if (IS_TILETYPE(tile_cur, MP_INDUSTRY)) { - if (_map2[tile_cur] == (uint16)index) { + if (_map2[tile_cur] == i->index) { DoClearSquare(tile_cur); } } else if (IS_TILETYPE(tile_cur, MP_STATION) && _map5[tile_cur] == 0x4B) { DeleteOilRig(tile_cur); } - END_TILE_LOOP(tile_cur, i->width, i->height, i->xy); + END_TILE_LOOP(tile_cur, i->width, i->height, i->xy); i->xy = 0; _industry_sort_dirty = true; - DeleteSubsidyWithIndustry(index); - DeleteWindowById(WC_INDUSTRY_VIEW, index); + DeleteSubsidyWithIndustry(i->index); + DeleteWindowById(WC_INDUSTRY_VIEW, i->index); InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); } @@ -1400,8 +1398,9 @@ static Industry *AllocateIndustry() FOR_ALL_INDUSTRIES(i) { if (i->xy == 0) { - int index = i - _industries; - if (index > _total_industries) _total_industries = index; + if (i->index > _total_industries) + _total_industries = i->index; + return i; } } @@ -1475,7 +1474,7 @@ static void DoCreateNewIndustry(Industry *i, uint tile, int type, const Industry _map_type_and_height[cur_tile] = (_map_type_and_height[cur_tile]&~0xF0) | (MP_INDUSTRY<<4); _map5[cur_tile] = it->map5; - _map2[cur_tile] = i - _industries; + _map2[cur_tile] = i->index; _map_owner[cur_tile] = _generating_world ? 0x1E : 0; /* maturity */ } } while ((++it)->ti.x != -0x80); @@ -1711,7 +1710,7 @@ static void UpdateIndustryStatistics(Industry *i) if ( i->produced_cargo[0] != 0xFF || i->produced_cargo[1] != 0xFF ) - InvalidateWindow(WC_INDUSTRY_VIEW, i - _industries); + InvalidateWindow(WC_INDUSTRY_VIEW, i->index); if (i->prod_level == 0) DeleteIndustry(i); @@ -1819,7 +1818,7 @@ void IndustryMonthlyLoop() UpdateIndustryStatistics(i); } - i = DEREF_INDUSTRY(RandomRange(lengthof(_industries))); + i = GetIndustry(RandomRange(_industries_size)); if (i->xy == 0) { uint32 r; @@ -1839,7 +1838,15 @@ void IndustryMonthlyLoop() void InitializeIndustries() { - memset(_industries, 0, sizeof(_industries)); + Industry *i; + int j; + + memset(_industries, 0, sizeof(_industries[0]) * _industries_size); + + j = 0; + FOR_ALL_INDUSTRIES(i) + i->index = j++; + _total_industries = 0; _industry_sort_dirty = true; } @@ -1894,14 +1901,13 @@ static const byte _industry_desc[] = { static void Save_INDY() { Industry *ind; - int i = 0; + // Write the vehicles FOR_ALL_INDUSTRIES(ind) { if (ind->xy != 0) { - SlSetArrayIndex(i); + SlSetArrayIndex(ind->index); SlObject(ind, _industry_desc); } - i++; } } @@ -1910,7 +1916,9 @@ static void Load_INDY() int index; _total_industries = 0; while ((index = SlIterateArray()) != -1) { - SlObject(DEREF_INDUSTRY(index), _industry_desc); + Industry *i = GetIndustry(index); + + SlObject(i, _industry_desc); if (index > _total_industries) _total_industries = index; } } diff --git a/industry_gui.c b/industry_gui.c index 81643f4ce0..accf17b47e 100644 --- a/industry_gui.c +++ b/industry_gui.c @@ -275,7 +275,7 @@ static void IndustryViewWndProc(Window *w, WindowEvent *e) // in editor, use bulldoze to destroy industry // Destroy Industry button costing money removed per request of dominik //w->disabled_state = (_patches.extra_dynamite && !_networking && _game_mode != GM_EDITOR) ? 0 : (1 << 6); - i = DEREF_INDUSTRY(w->window_number); + i = GetIndustry(w->window_number); SetDParam(0, i->town->index); SetDParam(1, i->type + STR_4802_COAL_MINE); DrawWindowWidgets(w); @@ -316,12 +316,12 @@ static void IndustryViewWndProc(Window *w, WindowEvent *e) case WE_CLICK: switch(e->click.widget) { case 6: - i = DEREF_INDUSTRY(w->window_number); + i = GetIndustry(w->window_number); ScrollMainWindowToTile(i->xy + TILE_XY(1,1)); break; case 7: // Destroy Industry button costing money removed per request of dominik - //i = DEREF_INDUSTRY(w->window_number); + //i = GetIndustry(w->window_number); /* passing only i->xy is not safe if industry has a weird shape like: _ X X X X X @@ -365,7 +365,7 @@ void ShowIndustryViewWindow(int industry) w = AllocateWindowDescFront(&_industry_view_desc, industry); if (w) { w->flags4 |= WF_DISABLE_VP_SCROLL; - i = DEREF_INDUSTRY(w->window_number); + i = GetIndustry(w->window_number); AssignWindowViewport(w, 3, 17, 0xFE, 0x56, i->xy + TILE_XY(1,1), 1); } } @@ -385,7 +385,6 @@ static const Widget _industry_directory_widgets[] = { { WIDGETS_END}, }; -static uint16 _industry_sort[lengthof(_industries)]; static uint _num_industry_sort; static char _bufcache[96]; @@ -397,8 +396,8 @@ static int CDECL GeneralIndustrySorter(const void *a, const void *b) { char buf1[96]; byte val; - Industry *i = DEREF_INDUSTRY(*(const uint16*)a); - Industry *j = DEREF_INDUSTRY(*(const uint16*)b); + Industry *i = GetIndustry(*(const uint16*)a); + Industry *j = GetIndustry(*(const uint16*)b); int r = 0; switch (_industry_sort_order >> 1) { @@ -457,13 +456,16 @@ static int CDECL GeneralIndustrySorter(const void *a, const void *b) static void MakeSortedIndustryList() { Industry *i; - int n = 0, index = 0; + int n = 0; + + /* Create array for sorting */ + _industry_sort = realloc(_industry_sort, _industries_size * sizeof(_industry_sort[0])); + if (_industry_sort == NULL) + error("Could not allocate memory for the industry-sorting-list"); FOR_ALL_INDUSTRIES(i) { if(i->xy) - _industry_sort[n++] = index; - - index++; + _industry_sort[n++] = i->index; } _num_industry_sort = n; _last_industry_idx = 0xFFFF; // used for "cache" @@ -497,7 +499,7 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e) n = 0; while (p < _num_industry_sort) { - i = DEREF_INDUSTRY(_industry_sort[p]); + i = GetIndustry(_industry_sort[p]); SetDParam(0, i->town->index); SetDParam(1, i->type + STR_4802_COAL_MINE); if (i->produced_cargo[0] != 0xFF) { @@ -558,7 +560,7 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e) return; p = y + w->vscroll.pos; if (p < _num_industry_sort) { - c = DEREF_INDUSTRY(_industry_sort[p]); + c = GetIndustry(_industry_sort[p]); ScrollMainWindowToTile(c->xy); } } break; diff --git a/misc.c b/misc.c index b0b9d0eb6d..00f8e57397 100644 --- a/misc.c +++ b/misc.c @@ -607,6 +607,7 @@ static const uint16 _autosave_months[] = { void IncreaseDate() { + const int vehicles_per_day = (1 << (sizeof(_date_fract) * 8)) / 885; int i,ctr,t; YearMonthDay ymd; @@ -621,15 +622,15 @@ void IncreaseDate() 65536 / 885 = 74; 74x12 = 888. So max 888. Any vehicles above that were not _on_new_vehicle_day_proc'd eg. aged. So new code updates it for max vehicles. - (NUM_VEHICLES / maximum number of times ctr is incremented before reset ) + 1 (to get last vehicles too) + (_vehicles_size / maximum number of times ctr is incremented before reset ) + 1 (to get last vehicles too) max size of _date_fract / 885 (added each tick) is number of times before ctr is reset. Calculation might look complicated, but compiler just replaces it with 35, so that's ok */ ctr = _vehicle_id_ctr_day; - for(i=0; i!=(NUM_VEHICLES / ((1<type) != 0) + for (i = 0; i != (_vehicles_size / vehicles_per_day) + 1 && ctr != _vehicles_size; i++) { + Vehicle *v = GetVehicle(ctr++); + if ((t = v->type) != 0) _on_new_vehicle_day_proc[t - 0x10](v); } _vehicle_id_ctr_day = ctr; @@ -637,7 +638,8 @@ void IncreaseDate() /* increase day, and check if a new day is there? */ _tick_counter++; - if ( (_date_fract += 885) >= 885) + _date_fract += 885; + if (_date_fract >= 885) return; /* yeah, increse day counter and call various daily loops */ diff --git a/news_gui.c b/news_gui.c index 5359d8bad2..a09c59e343 100644 --- a/news_gui.c +++ b/news_gui.c @@ -165,7 +165,7 @@ static void NewsWindowProc(Window *w, WindowEvent *e) case 0: { NewsItem *ni = WP(w, news_d).ni; if (ni->flags & NF_VEHICLE) { - Vehicle *v = &_vehicles[ni->data_a]; + Vehicle *v = GetVehicle(ni->data_a); ScrollMainWindowTo(v->x_pos, v->y_pos); } else if (ni->flags & NF_TILE) { if (!ScrollMainWindowToTile(ni->data_a) && ni->data_b != 0) diff --git a/oldloader.c b/oldloader.c index 08d2cb4e81..d84ce5e9a7 100644 --- a/oldloader.c +++ b/oldloader.c @@ -504,7 +504,7 @@ assert_compile(sizeof(OldMain) == 487801 + 256*256*2); #endif #define REMAP_TOWN_IDX(x) (x - (0x0459154 - 0x0458EF0)) / sizeof(OldTown) -#define REMAP_TOWN_PTR(x) DEREF_TOWN( REMAP_TOWN_IDX(x) ) +#define REMAP_TOWN_PTR(x) GetTown( REMAP_TOWN_IDX(x) ) #define REMAP_ORDER_IDX(x) (x - (0x045AB08 - 0x0458EF0)) / sizeof(uint16) @@ -584,9 +584,14 @@ static void LoadSavegameBytes(void *p, size_t count) extern uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type); -static void FixTown(Town *t, OldTown *o, int num, byte town_name_type) +static void FixTown(OldTown *o, int num, byte town_name_type) { + Town *t; + uint i; + do { + t = GetTown(i); + t->xy = o->xy; t->population = o->population; t->townnametype = o->townnametype; @@ -622,12 +627,17 @@ static void FixTown(Town *t, OldTown *o, int num, byte town_name_type) t->act_water = o->act_water; t->road_build_months = o->road_build_months; t->fund_buildings_months = o->fund_buildings_months; - } while (t++,o++,--num); + } while (i++,o++,--num); } -static void FixIndustry(Industry *i, OldIndustry *o, int num) +static void FixIndustry(OldIndustry *o, int num) { + Industry *i; + uint j = 0; + do { + i = GetIndustry(j); + i->xy = o->xy; i->town = REMAP_TOWN_PTR(o->town); i->width = o->width; @@ -664,7 +674,7 @@ static void FixIndustry(Industry *i, OldIndustry *o, int num) i->last_prod_year = o->last_prod_year; i->counter = o->counter; i->was_cargo_delivered = o->was_cargo_delivered; - } while (i++,o++,--num); + } while (j++,o++,--num); } static void FixGoodsEntry(GoodsEntry *g, OldGoodsEntry *o, int num) @@ -680,9 +690,14 @@ static void FixGoodsEntry(GoodsEntry *g, OldGoodsEntry *o, int num) } while (g++,o++,--num); } -static void FixStation(Station *s, OldStation *o, int num) +static void FixStation(OldStation *o, int num) { + Station *s; + uint i = 0; + do { + s = GetStation(i); + s->xy = o->xy; s->town = REMAP_TOWN_PTR(o->town); s->bus_tile = o->bus_tile; @@ -713,7 +728,7 @@ static void FixStation(Station *s, OldStation *o, int num) s->blocked_months_obsolete = o->blocked_months_obsolete; s->airport_flags = o->airport_flags; s->last_vehicle = o->last_vehicle; - } while (s++,o++,--num); + } while (i++,o++,--num); } static void FixDepot(Depot *n, OldDepot *o, int num) @@ -724,9 +739,14 @@ static void FixDepot(Depot *n, OldDepot *o, int num) } while (n++,o++,--num); } -static void FixVehicle(Vehicle *n, OldVehicle *o, int num) +static void FixVehicle(OldVehicle *o, int num) { + Vehicle *n; + uint i = 0; + do { + n = GetVehicle(i); + n->type = o->type; n->subtype = o->subtype; @@ -793,7 +813,7 @@ static void FixVehicle(Vehicle *n, OldVehicle *o, int num) n->reliability_spd_dec = o->reliability_spd_dec; n->profit_this_year = o->profit_this_year; n->profit_last_year = o->profit_last_year; - n->next = o->next_in_chain == 0xffff ? NULL : &_vehicles[o->next_in_chain]; + n->next = (o->next_in_chain == 0xFFFF) ? NULL : GetVehicle(o->next_in_chain); n->value = o->value; n->string_id = RemapOldStringID(o->string_id); @@ -833,7 +853,7 @@ static void FixVehicle(Vehicle *n, OldVehicle *o, int num) n->u.disaster.unk2 = o->u.disaster.unk2; break; } - } while (n++,o++,--num); + } while (i++,o++,--num); } static void FixSubsidy(Subsidy *n, OldSubsidy *o, int num) @@ -1407,12 +1427,12 @@ bool LoadOldSaveGame(const char *file) _order_array[i] = UnpackOldOrder(m->order_list[i]); _ptr_to_next_order = _order_array + REMAP_ORDER_IDX(m->ptr_to_next_order); - FixTown(_towns, m->town_list, lengthof(m->town_list), m->town_name_type); - FixIndustry(_industries, m->industries, lengthof(m->industries)); - FixStation(_stations, m->stations, lengthof(m->stations)); + FixTown(m->town_list, lengthof(m->town_list), m->town_name_type); + FixIndustry(m->industries, lengthof(m->industries)); + FixStation(m->stations, lengthof(m->stations)); FixDepot(_depots, m->depots, lengthof(m->depots)); - FixVehicle(_vehicles, m->vehicles, lengthof(m->vehicles)); + FixVehicle(m->vehicles, lengthof(m->vehicles)); FixSubsidy(_subsidies, m->subsidies, lengthof(m->subsidies)); FixPlayer(_players, m->players, lengthof(m->players), m->town_name_type); diff --git a/order_cmd.c b/order_cmd.c index f3f1e7b4e6..d7a7abb3c1 100644 --- a/order_cmd.c +++ b/order_cmd.c @@ -13,7 +13,7 @@ */ int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - Vehicle *v = &_vehicles[p1 & 0xFFFF]; + Vehicle *v = GetVehicle(p1 & 0xFFFF); int sel = p1 >> 16; Order new_order = UnpackOrder(p2); @@ -26,8 +26,8 @@ int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) sel != 0 && v->schedule_ptr[sel - 1].type == OT_GOTO_STATION) { int dist = GetTileDist( - DEREF_STATION(v->schedule_ptr[sel - 1].station)->xy, - DEREF_STATION(new_order.station)->xy + GetStation(v->schedule_ptr[sel - 1].station)->xy, + GetStation(new_order.station)->xy ); if (dist >= 130) return_cmd_error(STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO); @@ -94,7 +94,7 @@ static int32 DecloneOrder(Vehicle *dst, uint32 flags) */ int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - Vehicle *v = &_vehicles[p1], *u; + Vehicle *v = GetVehicle(p1), *u; uint sel = (uint)p2; _error_message = STR_EMPTY; @@ -141,7 +141,7 @@ int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) { if (flags & DC_EXEC) { - Vehicle *v = &_vehicles[p1]; + Vehicle *v = GetVehicle(p1); { byte b = v->cur_order_index + 1; @@ -168,7 +168,7 @@ int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) */ int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - Vehicle *v = &_vehicles[p1]; + Vehicle *v = GetVehicle(p1); byte sel = (byte)p2; Order *sched; @@ -219,7 +219,7 @@ int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - Vehicle *dst = &_vehicles[p1 & 0xFFFF]; + Vehicle *dst = GetVehicle(p1 & 0xFFFF); if (!(dst->type && dst->owner == _current_player)) return CMD_ERROR; @@ -228,7 +228,7 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) // share vehicle orders? case 0: { - Vehicle *src = &_vehicles[p1 >> 16]; + Vehicle *src = GetVehicle(p1 >> 16); // sanity checks if (!(src->owner == _current_player && dst->type == src->type && dst != src)) @@ -255,7 +255,7 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) // copy vehicle orders? case 1: { - Vehicle *src = &_vehicles[p1 >> 16]; + Vehicle *src = GetVehicle(p1 >> 16); int delta; // sanity checks @@ -269,7 +269,7 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) for (i = src->schedule_ptr; i->type != OT_NOTHING; ++i) { if (i->type == OT_GOTO_STATION) { - const Station *st = DEREF_STATION(i->station); + const Station *st = GetStation(i->station); required_dst = (dst->cargo_type == CT_PASSENGERS) ? st->bus_tile : st->lorry_tile; if ( !required_dst ) return CMD_ERROR; @@ -366,7 +366,7 @@ int32 CmdRestoreOrderIndex(int x, int y, uint32 flags, uint32 p1, uint32 p2) { // nonsense to update the windows, since, train rebought will have its window deleted if (flags & DC_EXEC) { - Vehicle *v = &_vehicles[p1]; + Vehicle *v = GetVehicle(p1); v->service_interval = (uint16)(p2>>16); v->cur_order_index = (byte)(p2&0xFFFF); } @@ -415,7 +415,7 @@ int CheckOrders(Vehicle *v) //I uncommented this in order not to get two error messages //when two identical entries are in the list n_st++; - st = DEREF_STATION(order.station); + st = GetStation(order.station); required_tile = GetStationTileForVehicle(v,st); if (!required_tile) problem_type = 3; } diff --git a/order_gui.c b/order_gui.c index 6f3dd3962a..ac97db1752 100644 --- a/order_gui.c +++ b/order_gui.c @@ -13,7 +13,7 @@ static int OrderGetSel(Window *w) { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); const Order *sched = v->schedule_ptr; int num = WP(w,order_d).sel; int count = 0; @@ -41,7 +41,7 @@ static void DrawOrdersWindow(Window *w) StringID str; bool shared_schedule; - v = &_vehicles[w->window_number]; + v = GetVehicle(w->window_number); w->disabled_state = (v->owner == _local_player) ? 0 : 0x3F0; @@ -237,7 +237,7 @@ static Order GetOrderCmdFromTile(Vehicle *v, uint tile) } if (IS_TILETYPE(tile, MP_STATION)) { - st = DEREF_STATION(st_index = _map2[tile]); + st = GetStation(st_index = _map2[tile]); if (st->owner == _current_player || st->owner == OWNER_NONE) { byte facil; @@ -314,7 +314,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e) break; case WE_CLICK: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); int mode; switch(e->click.widget) { case 2: {/* orders list */ @@ -331,7 +331,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e) int xy = 0; switch (ord.type) { case OT_GOTO_STATION: /* station order */ - xy = _stations[ord.station].xy ; + xy = GetStation(ord.station)->xy ; break; case OT_GOTO_DEPOT: /* goto depot order */ xy = _depots[ord.station].xy; @@ -389,7 +389,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e) case WE_RCLICK: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); if (e->click.widget != 8) break; if (v->schedule_ptr[OrderGetSel(w)].type == OT_GOTO_DEPOT) GuiShowTooltips(STR_SERVICE_HINT); @@ -403,7 +403,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e) } break; case WE_PLACE_OBJ: { - OrdersPlaceObj(&_vehicles[w->window_number], e->place.tile, w); + OrdersPlaceObj(GetVehicle(w->window_number), e->place.tile, w); } break; case WE_ABORT_PLACE_OBJ: { @@ -424,7 +424,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e) */ if (v && HASBIT(w->click_state, 7)) { _place_clicked_vehicle = NULL; - HandleOrderVehClick(&_vehicles[w->window_number], v, w); + HandleOrderVehClick(GetVehicle(w->window_number), v, w); } } break; diff --git a/rail_cmd.c b/rail_cmd.c index bc71e40c4e..763dd09652 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -1453,7 +1453,7 @@ static Station *ComposeWaypointStation(uint tile) stat.train_tile = stat.xy = waypt->xy; /* FIXME - We should always keep town. */ - stat.town = waypt->town_or_string & 0xC000 ? &_towns[waypt->town_or_string & 0xFF] : NULL; + stat.town = waypt->town_or_string & 0xC000 ? GetTown(waypt->town_or_string & 0xFF) : NULL; stat.string_id = waypt->town_or_string & 0xC000 ? /* FIXME? */ 0 : waypt->town_or_string; stat.build_date = waypt->build_date; stat.class_id = 6; stat.stat_id = waypt->stat_id; diff --git a/roadveh_cmd.c b/roadveh_cmd.c index 3a44d4f74f..e7b42e5748 100644 --- a/roadveh_cmd.c +++ b/roadveh_cmd.c @@ -199,7 +199,7 @@ int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR; @@ -213,7 +213,7 @@ int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) return 0; } -// p1 = vehicle index in &_vehicles[] +// p1 = vehicle index in GetVehicle() // p2 not used int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) { @@ -221,7 +221,7 @@ int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - v = &_vehicles[p1]; + v = GetVehicle(p1); if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR; @@ -291,7 +291,7 @@ static int FindClosestRoadDepot(Vehicle *v) int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - Vehicle *v = &_vehicles[p1]; + Vehicle *v = GetVehicle(p1); int depot; if (v->type != VEH_Road || !CheckOwnership(v->owner)) @@ -327,7 +327,7 @@ int32 CmdTurnRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR; @@ -352,7 +352,7 @@ int32 CmdChangeRoadVehServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR; @@ -396,7 +396,7 @@ static void UpdateRoadVehDeltaXY(Vehicle *v) static void ClearCrashedStation(Vehicle *v) { uint tile = v->tile; - Station *st = DEREF_STATION(_map2[tile]); + Station *st = GetStation(_map2[tile]); byte *b, bb; b = (_map5[tile] >= 0x47) ? &st->bus_stop_status : &st->truck_stop_status; @@ -594,7 +594,7 @@ static void ProcessRoadVehOrder(Vehicle *v) if (order.type == OT_GOTO_STATION) { if (order.station == v->last_station_visited) v->last_station_visited = 0xFFFF; - st = DEREF_STATION(order.station); + st = GetStation(order.station); v->dest_tile = v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile; } else if (order.type == OT_GOTO_DEPOT) { v->dest_tile = _depots[order.station].xy; @@ -951,7 +951,7 @@ static int RoadFindPathToDest(Vehicle *v, uint tile, int direction) } else if (IS_TILETYPE(tile, MP_STATION)) { if (_map_owner[tile] == OWNER_NONE || _map_owner[tile] == v->owner) { /* Our station */ - Station *st = DEREF_STATION(_map2[tile]); + Station *st = GetStation(_map2[tile]); byte val = _map5[tile]; if (v->cargo_type != CT_PASSENGERS) { if (IS_BYTE_INSIDE(val, 0x43, 0x47) && (_patches.roadveh_queue || st->truck_stop_status&3)) @@ -1211,7 +1211,7 @@ again: if (IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && IS_TILETYPE(v->tile, MP_STATION)) { if ((tmp&7) >= 6) { v->cur_speed = 0; return; } if (IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x4B)) { - Station *st = DEREF_STATION(_map2[v->tile]); + Station *st = GetStation(_map2[v->tile]); byte *b; if (_map5[v->tile] >= 0x47) { @@ -1307,7 +1307,7 @@ again: _road_veh_data_1[v->u.road.state - 0x20 + (_opt.road_side<<4)] == v->u.road.frame) { byte *b; - st = DEREF_STATION(_map2[v->tile]); + st = GetStation(_map2[v->tile]); b = IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x47) ? &st->truck_stop_status : &st->bus_stop_status; if (v->current_order.type != OT_LEAVESTATION && @@ -1487,7 +1487,7 @@ void OnNewDay_RoadVeh(Vehicle *v) /* update destination */ if (v->current_order.type == OT_GOTO_STATION) { - st = DEREF_STATION(v->current_order.station); + st = GetStation(v->current_order.station); if ((tile=(v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile)) != 0) v->dest_tile = tile; } diff --git a/roadveh_gui.c b/roadveh_gui.c index 58c6abe86c..f55e1fef55 100644 --- a/roadveh_gui.c +++ b/roadveh_gui.c @@ -45,7 +45,7 @@ static void DrawRoadVehImage(Vehicle *v, int x, int y, VehicleID selection) static void RoadVehDetailsWndProc(Window *w, WindowEvent *e) { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); StringID str; int mod; @@ -204,7 +204,7 @@ static void RoadVehViewWndProc(Window *w, WindowEvent *e) { switch(e->event) { case WE_PAINT: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); StringID str; w->disabled_state = (v->owner != _local_player) ? (1<<8 | 1<<7) : 0; @@ -258,7 +258,7 @@ static void RoadVehViewWndProc(Window *w, WindowEvent *e) } break; case WE_CLICK: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); switch(e->click.widget) { case 5: /* start stop */ @@ -380,7 +380,7 @@ void CcBuildRoadVeh(bool success, uint tile, uint32 p1, uint32 p2) if (!success) return; - v = &_vehicles[_new_roadveh_id]; + v = GetVehicle(_new_roadveh_id); if (v->tile == _backup_orders_tile) { _backup_orders_tile = 0; RestoreVehicleOrders(v, _backup_orders_data); @@ -665,7 +665,7 @@ static void RoadDepotWndProc(Window *w, WindowEvent *e) HandleButtonClick(w, 5); - v = &_vehicles[WP(w,traindepot_d).sel]; + v = GetVehicle(WP(w,traindepot_d).sel); WP(w,traindepot_d).sel = INVALID_VEHICLE; _backup_orders_tile = v->tile; @@ -800,7 +800,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) w->widget[1].unkA = STR_9001_ROAD_VEHICLES; } else { /* Station Name -- (###) Road vehicles */ - SetDParam(0, DEREF_STATION(station)->index); + SetDParam(0, GetStation(station)->index); SetDParam(1, w->vscroll.count); w->widget[1].unkA = STR_SCHEDULED_ROAD_VEHICLES; } @@ -814,7 +814,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); for (i = w->vscroll.pos; i < max; ++i) { - Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); + Vehicle *v = GetVehicle(vl->sort_list[i].index); StringID str; assert(v->type == VEH_Road && v->owner == owner); @@ -865,7 +865,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) if (id_v >= vl->list_length) return; // click out of list bound - v = DEREF_VEHICLE(vl->sort_list[id_v].index); + v = GetVehicle(vl->sort_list[id_v].index); assert(v->type == VEH_Road && v->owner == owner); diff --git a/ship_cmd.c b/ship_cmd.c index d336031bb1..7b22502fad 100644 --- a/ship_cmd.c +++ b/ship_cmd.c @@ -243,7 +243,7 @@ static void ProcessShipOrder(Vehicle *v) if (order.station == v->last_station_visited) v->last_station_visited = 0xFFFF; - st = DEREF_STATION(order.station); + st = GetStation(order.station); if (st->dock_tile != 0) { v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(_dock_offs[_map5[st->dock_tile]-0x4B])); } @@ -679,7 +679,7 @@ static void ShipController(Vehicle *v) v->last_station_visited = v->current_order.station; /* Process station in the schedule. Don't do that for buoys (HVOT_BUOY) */ - st = DEREF_STATION(v->current_order.station); + st = GetStation(v->current_order.station); if (!(st->had_vehicle_of_type & HVOT_BUOY) && (st->facilities & FACIL_DOCK)) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */ v->current_order.type = OT_LOADING; @@ -884,7 +884,7 @@ int32 CmdSellShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -908,7 +908,7 @@ int32 CmdStartStopShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -927,7 +927,7 @@ int32 CmdSendShipToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) Vehicle *v; int depot; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -960,7 +960,7 @@ int32 CmdChangeShipServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -986,7 +986,7 @@ int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) p2 = p2 & 0xFF; SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN); - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; diff --git a/ship_gui.c b/ship_gui.c index d69e9a4f24..f08b3e0d9b 100644 --- a/ship_gui.c +++ b/ship_gui.c @@ -46,7 +46,7 @@ static void ShipRefitWndProc(Window *w, WindowEvent *e) { switch(e->event) { case WE_PAINT: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); const byte *b; int sel; int x,y; @@ -123,7 +123,7 @@ static void ShipRefitWndProc(Window *w, WindowEvent *e) } break; case 4: /* refit button */ if (WP(w,refit_d).cargo != 0xFF) { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP))) DeleteWindow(w); } @@ -166,7 +166,7 @@ static void ShowShipRefitWindow(Vehicle *v) static void ShipDetailsWndProc(Window *w, WindowEvent *e) { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); StringID str; int mod; @@ -326,7 +326,7 @@ void CcBuildShip(bool success, uint tile, uint32 p1, uint32 p2) Vehicle *v; if (!success) return; - v = &_vehicles[_new_ship_id]; + v = GetVehicle(_new_ship_id); if (v->tile == _backup_orders_tile) { _backup_orders_tile = 0; RestoreVehicleOrders(v, _backup_orders_data); @@ -484,7 +484,7 @@ static void ShowBuildShipWindow(TileIndex tile) static void ShipViewWndProc(Window *w, WindowEvent *e) { switch(e->event) { case WE_PAINT: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); uint32 disabled = 1<<8; StringID str; @@ -546,7 +546,7 @@ static void ShipViewWndProc(Window *w, WindowEvent *e) { } break; case WE_CLICK: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); switch(e->click.widget) { case 5: /* start stop */ @@ -799,7 +799,7 @@ static void ShipDepotWndProc(Window *w, WindowEvent *e) { HandleButtonClick(w, 5); - v = &_vehicles[WP(w,traindepot_d).sel]; + v = GetVehicle(WP(w,traindepot_d).sel); WP(w,traindepot_d).sel = INVALID_VEHICLE; _backup_orders_tile = v->tile; @@ -882,7 +882,7 @@ static void DrawSmallShipSchedule(Vehicle *v, int x, int y) { sel--; if (sched->type == OT_GOTO_STATION) { - st = DEREF_STATION(sched->station); + st = GetStation(sched->station); if (!(st->had_vehicle_of_type & HVOT_BUOY)) { SetDParam(0, sched->station); @@ -962,7 +962,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) w->widget[1].unkA = STR_9805_SHIPS; } else { /* Station Name -- (###) Trains */ - SetDParam(0, DEREF_STATION(station)->index); + SetDParam(0, GetStation(station)->index); SetDParam(1, w->vscroll.count); w->widget[1].unkA = STR_SCHEDULED_SHIPS; } @@ -976,7 +976,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); for (i = w->vscroll.pos; i < max; ++i) { - Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); + Vehicle *v = GetVehicle(vl->sort_list[i].index); StringID str; assert(v->type == VEH_Ship); @@ -1028,7 +1028,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) if (id_v >= vl->list_length) return; // click out of list bound - v = DEREF_VEHICLE(vl->sort_list[id_v].index); + v = GetVehicle(vl->sort_list[id_v].index); assert(v->type == VEH_Ship); diff --git a/station.h b/station.h index c6a9179e57..17a0bb4da1 100644 --- a/station.h +++ b/station.h @@ -94,13 +94,21 @@ void ShowStationViewWindow(int station); void UpdateAllStationVirtCoord(); VARDEF Station _stations[250]; +VARDEF uint _stations_size; + +VARDEF SortStruct *_station_sort; + +static inline Station *GetStation(uint index) +{ + assert(index < _stations_size); + return &_stations[index]; +} + +#define FOR_ALL_STATIONS(st) for(st = _stations; st != &_stations[_stations_size]; st++) + VARDEF bool _station_sort_dirty[MAX_PLAYERS]; VARDEF bool _global_station_sort_dirty; -#define DEREF_STATION(i) (&_stations[i]) -#define FOR_ALL_STATIONS(st) for(st=_stations; st != endof(_stations); st++) - - void GetProductionAroundTiles(uint *produced, uint tile, int w, int h, int rad); void GetAcceptanceAroundTiles(uint *accepts, uint tile, int w, int h, int rad); uint GetStationPlatforms(Station *st, uint tile); diff --git a/station_cmd.c b/station_cmd.c index 77c92b43d5..6f3940f4fc 100644 --- a/station_cmd.c +++ b/station_cmd.c @@ -25,6 +25,10 @@ const byte _airport_size_y[5] = {3, 6, 1, 6, 7 }; void ShowAircraftDepotWindow(uint tile); extern void UpdateAirplanesOnNewStation(Station *st); +enum { + STATIONS_MIN_FREE_FOR_AI = 30 +}; + static void MarkStationDirty(Station *st) { if (st->sign.width_1 != 0) { @@ -73,7 +77,7 @@ static Station *GetStationAround(uint tile, int w, int h, int closest_station) int t; t = _map2[tile_cur]; { - Station *st = DEREF_STATION(t); + Station *st = GetStation(t); // you cannot take control of an oilrig!! if (st->airport_type == AT_OILRIG && st->facilities == (FACIL_AIRPORT|FACIL_DOCK)) continue; @@ -87,7 +91,7 @@ static Station *GetStationAround(uint tile, int w, int h, int closest_station) } } END_TILE_LOOP(tile_cur, w + 2, h + 2, tile - TILE_XY(1,1)) - return (closest_station == -1) ? NULL : DEREF_STATION(closest_station); + return (closest_station == -1) ? NULL : GetStation(closest_station); } TileIndex GetStationTileForVehicle(Vehicle *v, Station *st) @@ -136,20 +140,19 @@ static bool CheckStationSpreadOut(Station *st, uint tile, int w, int h) static Station *AllocateStation() { Station *st, *a_free = NULL; - int count; int num_free = 0; int i; - for(st = _stations, count = lengthof(_stations); count != 0; count--, st++) { + FOR_ALL_STATIONS(st) { if (st->xy == 0) { num_free++; - if (a_free==NULL) + if (a_free == NULL) a_free = st; } } if (a_free == NULL || - (num_free < 30 && IS_HUMAN_PLAYER(_current_player))) { + (num_free < STATIONS_MIN_FREE_FOR_AI && IS_HUMAN_PLAYER(_current_player))) { _error_message = STR_3008_TOO_MANY_STATIONS_LOADING; return NULL; } @@ -961,7 +964,7 @@ int32 CmdRemoveFromRailroadStation(int x, int y, uint32 flags, uint32 p1, uint32 // make sure the specified tile belongs to the current player, and that it is a railroad station. if (!IS_TILETYPE(tile, MP_STATION) || _map5[tile] >= 8 || !_patches.nonuniform_stations) return CMD_ERROR; - st = DEREF_STATION(_map2[tile]); + st = GetStation(_map2[tile]); if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile))) return CMD_ERROR; // if we reached here, it means we can actually delete it. do that. @@ -1225,7 +1228,7 @@ int32 DoConvertStationRail(uint tile, uint totype, bool exec) { Station *st; - st = DEREF_STATION(_map2[tile]); + st = GetStation(_map2[tile]); if (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile)) return CMD_ERROR; // tile is not a railroad station? @@ -1967,7 +1970,7 @@ static void DrawTile_Station(TileInfo *ti) //debug("Cust-o-mized %p", statspec); if (statspec != NULL) { - Station *st = DEREF_STATION(_map2[ti->tile]); + Station *st = GetStation(_map2[ti->tile]); relocation = GetCustomStationRelocation(statspec, st, 0); //debug("Relocation %d", relocation); @@ -2052,7 +2055,7 @@ static void GetTileDesc_Station(uint tile, TileDesc *td) StringID str; td->owner = _map_owner[tile]; - td->build_date = DEREF_STATION(_map2[tile])->build_date; + td->build_date = GetStation(_map2[tile])->build_date; m5 = _map5[tile]; (str=STR_305E_RAILROAD_STATION, m5 < 8) || @@ -2207,7 +2210,7 @@ static uint32 VehicleEnter_Station(Vehicle *v, uint tile, int x, int y) } } else if (v->type == VEH_Road) { if (v->u.road.state < 16 && (v->u.road.state&4)==0 && v->u.road.frame==0) { - Station *st = DEREF_STATION(_map2[tile]); + Station *st = GetStation(_map2[tile]); byte m5 = _map5[tile]; byte *b, bb,state; @@ -2327,7 +2330,7 @@ static void UpdateStationRating(Station *st) { byte days = ge->days_since_pickup; if (st->last_vehicle != INVALID_VEHICLE && - (&_vehicles[st->last_vehicle])->type == VEH_Ship) + GetVehicle(st->last_vehicle)->type == VEH_Ship) days >>= 2; (days > 21) || (rating += 25, days > 12) || @@ -2408,10 +2411,10 @@ void OnTick_Station() return; i = _station_tick_ctr; - if (++_station_tick_ctr == lengthof(_stations)) + if (++_station_tick_ctr == _stations_size) _station_tick_ctr = 0; - st = DEREF_STATION(i); + st = GetStation(i); if (st->xy != 0) StationHandleBigTick(st); @@ -2466,7 +2469,7 @@ int32 CmdRenameStation(int x, int y, uint32 flags, uint32 p1, uint32 p2) return CMD_ERROR; if (flags & DC_EXEC) { - st = DEREF_STATION(p1); + st = GetStation(p1); old_str = st->string_id; st->string_id = str; UpdateStationVirtCoord(st); @@ -2520,7 +2523,7 @@ uint MoveGoodsToStation(uint tile, int w, int h, int type, uint amount) st_index = _map2[cur_tile]; for(i=0; i!=8; i++) { if (around[i] == 0xFF) { - st = DEREF_STATION(st_index); + st = GetStation(st_index); if ((st->had_vehicle_of_type & HVOT_BUOY) == 0 && ( !st->town->exclusive_counter || (st->town->exclusivity == st->owner) ) && // check exclusive transport rights st->goods[type].rating != 0 && @@ -2673,7 +2676,7 @@ void BuildOilRig(uint tile) void DeleteOilRig(uint tile) { - Station *st = DEREF_STATION(_map2[tile]); + Station *st = GetStation(_map2[tile]); DoClearSquare(tile); @@ -2691,7 +2694,7 @@ static void ChangeTileOwner_Station(uint tile, byte old_player, byte new_player) return; if (new_player != 255) { - Station *st = DEREF_STATION(_map2[tile]); + Station *st = GetStation(_map2[tile]); _map_owner[tile] = new_player; st->owner = new_player; _global_station_sort_dirty = true; // transfer ownership of station to another player @@ -2716,7 +2719,7 @@ static int32 ClearTile_Station(uint tile, byte flags) { return_cmd_error(STR_4800_IN_THE_WAY); } - st = DEREF_STATION(_map2[tile]); + st = GetStation(_map2[tile]); if (m5 < 8) return RemoveRailroadStation(st, tile, flags); @@ -2744,10 +2747,13 @@ static int32 ClearTile_Station(uint tile, byte flags) { void InitializeStations() { int i; + Station *s; - memset(_stations, 0, sizeof(_stations)); - for(i = 0; i != lengthof(_stations); i++) - _stations[i].index=i; + memset(_stations, 0, sizeof(_stations[0]) * _stations_size); + + i = 0; + FOR_ALL_STATIONS(s) + s->index = i++; _station_tick_ctr = 0; @@ -2843,7 +2849,7 @@ static void SaveLoad_STNS(Station *st) static void Save_STNS() { Station *st; - // Write the vehicles + // Write the stations FOR_ALL_STATIONS(st) { if (st->xy != 0) { SlSetArrayIndex(st->index); @@ -2856,7 +2862,8 @@ static void Load_STNS() { int index; while ((index = SlIterateArray()) != -1) { - Station *st = &_stations[index]; + Station *st = GetStation(index); + SaveLoad_STNS(st); // this means it's an oldstyle savegame without support for nonuniform stations @@ -2868,6 +2875,11 @@ static void Load_STNS() st->trainst_h = h; } } + + /* This is to ensure all pointers are within the limits of + _stations_size */ + if (_station_tick_ctr > _stations_size) + _station_tick_ctr = 0; } const ChunkHandler _station_chunk_handlers[] = { diff --git a/station_gui.c b/station_gui.c index c28bd32e1e..6a3a74a54e 100644 --- a/station_gui.c +++ b/station_gui.c @@ -45,7 +45,6 @@ static void StationsWndShowStationRating(int x, int y, int type, uint acceptance } } -static SortStruct _station_sort[lengthof(_stations)]; static uint16 _num_station_sort[MAX_PLAYERS]; static char _bufcache[64]; @@ -58,14 +57,14 @@ static int CDECL StationNameSorter(const void *a, const void *b) const SortStruct *cmp1 = (const SortStruct*)a; const SortStruct *cmp2 = (const SortStruct*)b; - st = DEREF_STATION(cmp1->index); + st = GetStation(cmp1->index); SetDParam(0, st->town->townnametype); SetDParam(1, st->town->townnameparts); GetString(buf1, st->string_id); if ( cmp2->index != _last_station_idx) { _last_station_idx = cmp2->index; - st = DEREF_STATION(cmp2->index); + st = GetStation(cmp2->index); SetDParam(0, st->town->townnametype); SetDParam(1, st->town->townnameparts); GetString(_bufcache, st->string_id); @@ -81,7 +80,13 @@ static void GlobalSortStationList() uint16 *i; // reset #-of stations to 0 because ++ is used for value-assignment - for (i = _num_station_sort; i != endof(_num_station_sort); i++) {*i = 0;} + for (i = _num_station_sort; i != endof(_num_station_sort); i++) + *i = 0; + + /* Create array for sorting */ + _station_sort = realloc(_station_sort, _stations_size * sizeof(_station_sort[0])); + if (_station_sort == NULL) + error("Could not allocate memory for the station-sorting-list"); FOR_ALL_STATIONS(st) { if(st->xy && st->owner != OWNER_NONE) { @@ -171,7 +176,7 @@ static void PlayerStationsWndProc(Window *w, WindowEvent *e) assert(i < _num_station_sort[window_number]); // at least one station must exist while (i < _num_station_sort[window_number]) { // do until max number of stations of owner - st = DEREF_STATION(_station_sort[i].index); + st = GetStation(_station_sort[i].index); assert(st->xy && st->owner == window_number); @@ -209,7 +214,7 @@ static void PlayerStationsWndProc(Window *w, WindowEvent *e) if (id_v >= _num_station_sort[owner]) { return;} // click out of station bound - st = DEREF_STATION(_station_sort[id_v].index); + st = GetStation(_station_sort[id_v].index); assert(st->xy && st->owner == owner); @@ -315,7 +320,7 @@ static void DrawStationViewWindow(Window *w) station_id = (byte)w->window_number; - st = DEREF_STATION(w->window_number); + st = GetStation(w->window_number); num = 1; for(i=0; i!=NUM_CARGO; i++) { @@ -449,7 +454,7 @@ static void StationViewWndProc(Window *w, WindowEvent *e) case WE_CLICK: switch(e->click.widget) { case 7: - ScrollMainWindowToTile(DEREF_STATION(w->window_number)->xy); + ScrollMainWindowToTile(GetStation(w->window_number)->xy); break; case 8: @@ -468,32 +473,32 @@ static void StationViewWndProc(Window *w, WindowEvent *e) break; case 9: { - Station *st = DEREF_STATION(w->window_number); + Station *st = GetStation(w->window_number); SetDParam(0, st->town->townnametype); SetDParam(1, st->town->townnameparts); ShowQueryString(st->string_id, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number); } break; case 10: { - const Station *st = DEREF_STATION(w->window_number); + const Station *st = GetStation(w->window_number); ShowPlayerTrains(st->owner, w->window_number); break; } case 11: { - const Station *st = DEREF_STATION(w->window_number); + const Station *st = GetStation(w->window_number); ShowPlayerRoadVehicles(st->owner, w->window_number); break; } case 12: { - const Station *st = DEREF_STATION(w->window_number); + const Station *st = GetStation(w->window_number); ShowPlayerAircraft(st->owner, w->window_number); break; } case 13: { - const Station *st = DEREF_STATION(w->window_number); + const Station *st = GetStation(w->window_number); ShowPlayerShips(st->owner, w->window_number); break; } @@ -507,13 +512,13 @@ static void StationViewWndProc(Window *w, WindowEvent *e) return; memcpy(_decode_parameters, b, 32); - st = DEREF_STATION(w->window_number); + st = GetStation(w->window_number); DoCommandP(st->xy, w->window_number, 0, NULL, CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION)); } break; case WE_DESTROY: { WindowNumber wno = - (w->window_number << 16) | DEREF_STATION(w->window_number)->owner; + (w->window_number << 16) | GetStation(w->window_number)->owner; DeleteWindowById(WC_TRAINS_LIST, wno); DeleteWindowById(WC_ROADVEH_LIST, wno); @@ -540,7 +545,7 @@ void ShowStationViewWindow(int station) w = AllocateWindowDescFront(&_station_view_desc, station); if (w) { - color = DEREF_STATION(w->window_number)->owner; + color = GetStation(w->window_number)->owner; if (color != 0x10) w->caption_color = color; w->vscroll.cap = 5; diff --git a/strings.c b/strings.c index ec3a8ea982..ea2c8b3456 100644 --- a/strings.c +++ b/strings.c @@ -432,7 +432,7 @@ static byte *DecodeString(byte *buff, const byte *str) case 0x9A: { // {STATION} Station *st; InjectDparam(1); - st = DEREF_STATION(GetDParam(1)); + st = GetStation(GetDParam(1)); if (!st->xy) { // station doesn't exist anymore buff = GetString(buff, STR_UNKNOWN_DESTINATION); break; @@ -444,7 +444,7 @@ static byte *DecodeString(byte *buff, const byte *str) } case 0x9B: { // {TOWN} Town *t; - t = DEREF_TOWN(GetDParam(0)); + t = GetTown(GetDParam(0)); assert(t->xy); SetDParam(0, t->townnameparts); buff = GetString(buff, t->townnametype); diff --git a/subsidy_gui.c b/subsidy_gui.c index 2a8bbf080d..e2b822eb2a 100644 --- a/subsidy_gui.c +++ b/subsidy_gui.c @@ -49,22 +49,22 @@ handle_click: /* determine from coordinate for subsidy and try to scroll to it */ offs = s->from; if (s->age >= 12) { - xy = DEREF_STATION(offs)->xy; + xy = GetStation(offs)->xy; } else if (s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL) { - xy = DEREF_TOWN(offs)->xy; + xy = GetTown(offs)->xy; } else { - xy = _industries[offs].xy; + xy = GetIndustry(offs)->xy; } if (!ScrollMainWindowToTile(xy)) { /* otherwise determine to coordinate for subsidy and scroll to it */ offs = s->to; if (s->age >= 12) { - xy = DEREF_STATION(offs)->xy; + xy = GetStation(offs)->xy; } else if (s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL || s->cargo_type == CT_GOODS || s->cargo_type == CT_FOOD) { - xy = DEREF_TOWN(offs)->xy; + xy = GetTown(offs)->xy; } else { - xy = _industries[offs].xy; + xy = GetIndustry(offs)->xy; } ScrollMainWindowToTile(xy); } @@ -112,7 +112,7 @@ static void DrawSubsidiesWindow(Window *w) if (s->cargo_type != 0xFF && s->age >= 12) { SetupSubsidyDecodeParam(s, 1); - p = DEREF_PLAYER(DEREF_STATION(s->to)->owner); + p = DEREF_PLAYER(GetStation(s->to)->owner); SetDParam(3, p->name_1); SetDParam(4, p->name_2); diff --git a/town.h b/town.h index 06845fffab..a80f3e11d4 100644 --- a/town.h +++ b/town.h @@ -91,10 +91,19 @@ enum { bool CheckforTownRating(uint tile, uint32 flags, Town *t, byte type); -#define DEREF_TOWN(i) (&_towns[i]) -#define FOR_ALL_TOWNS(c) for(c=_towns; c != endof(_towns); c++) - VARDEF Town _towns[70]; +VARDEF uint _towns_size; + +VARDEF uint16 *_town_sort; + +static inline Town *GetTown(uint index) +{ + assert(index < _towns_size); + return &_towns[index]; +} + +#define FOR_ALL_TOWNS(t) for(t = _towns; t != &_towns[_towns_size]; t++) + VARDEF int _total_towns; // For the AI: the amount of towns active VARDEF bool _town_sort_dirty; diff --git a/town_cmd.c b/town_cmd.c index 116b9d1f5b..b7a142ad0b 100644 --- a/town_cmd.c +++ b/town_cmd.c @@ -401,8 +401,8 @@ void OnTick_Town() return; i = _cur_town_ctr; - t = DEREF_TOWN(i); - if (++i == lengthof(_towns)) i = 0; + t = GetTown(i); + if (++i == _towns_size) i = 0; _cur_town_ctr = i; if (t->xy != 0) @@ -1354,7 +1354,7 @@ static void ClearTownHouse(Town *t, uint tile) { int32 CmdRenameTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) { StringID str; - Town *t = DEREF_TOWN(p1); + Town *t = GetTown(p1); str = AllocateNameUnique((byte*)_decode_parameters, 4); if (str == 0) @@ -1602,7 +1602,7 @@ int32 CmdDoTownAction(int x, int y, uint32 flags, uint32 p1, uint32 p2) cost = (_price.build_industry >> 8) * _town_action_costs[p2]; if (flags & DC_EXEC) { - _town_action_proc[p2](DEREF_TOWN(p1), p2); + _town_action_proc[p2](GetTown(p1), p2); InvalidateWindow(WC_TOWN_AUTHORITY, p1); } @@ -1817,11 +1817,14 @@ void TownsMonthlyLoop() void InitializeTowns() { Subsidy *s; + Town *t; int i; - memset(_towns, 0, sizeof(_towns)); - for(i=0; i!=lengthof(_towns); i++) - _towns[i].index = i; + memset(_towns, 0, sizeof(_towns[0]) * _towns_size); + + i = 0; + FOR_ALL_TOWNS(t) + t->index = i++; memset(_subsidies, 0, sizeof(_subsidies)); for (s=_subsidies; s != endof(_subsidies); s++) @@ -1908,9 +1911,11 @@ static void Save_TOWN() { Town *t; - FOR_ALL_TOWNS(t) if (t->xy != 0) { - SlSetArrayIndex(t->index); - SlObject(t, _town_desc); + FOR_ALL_TOWNS(t) { + if (t->xy != 0) { + SlSetArrayIndex(t->index); + SlObject(t, _town_desc); + } } } @@ -1918,7 +1923,8 @@ static void Load_TOWN() { int index; while ((index = SlIterateArray()) != -1) { - Town *t = DEREF_TOWN(index); + Town *t = GetTown(index); + SlObject(t, _town_desc); if (index > _total_towns) _total_towns = index; } diff --git a/town_gui.c b/town_gui.c index a263c20871..171294732d 100644 --- a/town_gui.c +++ b/town_gui.c @@ -85,7 +85,7 @@ static void TownAuthorityWndProc(Window *w, WindowEvent *e) { uint buttons; int numact; - Town *t = DEREF_TOWN(w->window_number); + Town *t = GetTown(w->window_number); switch(e->event) { case WE_PAINT: @@ -224,7 +224,7 @@ static void ShowTownAuthorityWindow(uint town) static void TownViewWndProc(Window *w, WindowEvent *e) { - Town *t = DEREF_TOWN(w->window_number); + Town *t = GetTown(w->window_number); switch(e->event) { case WE_PAINT: @@ -338,7 +338,7 @@ void ShowTownViewWindow(uint town) if (w) { w->flags4 |= WF_DISABLE_VP_SCROLL; - t = DEREF_TOWN(w->window_number); + t = GetTown(w->window_number); AssignWindowViewport(w, 3, 17, 0xFE, 0x56, t->xy, 1); } } @@ -357,7 +357,6 @@ static const Widget _town_directory_widgets[] = { // used to get a sorted list of the towns -static uint16 _town_sort[lengthof(_towns)]; static uint _num_town_sort; static char _bufcache[64]; @@ -370,13 +369,13 @@ static int CDECL TownNameSorter(const void *a, const void *b) byte val; int r; - t = DEREF_TOWN(*(const uint16*)a); + t = GetTown(*(const uint16*)a); SetDParam(0, t->townnameparts); GetString(buf1, t->townnametype); if ( (val=*(const uint16*)b) != _last_town_idx) { _last_town_idx = val; - t = DEREF_TOWN(val); + t = GetTown(val); SetDParam(0, t->townnameparts); GetString(_bufcache, t->townnametype); } @@ -388,8 +387,8 @@ static int CDECL TownNameSorter(const void *a, const void *b) static int CDECL TownPopSorter(const void *a, const void *b) { - const Town *ta = DEREF_TOWN(*(const uint16*)a); - const Town *tb = DEREF_TOWN(*(const uint16*)b); + const Town *ta = GetTown(*(const uint16*)a); + const Town *tb = GetTown(*(const uint16*)b); int r = ta->population - tb->population; if (_town_sort_order & 1) r = -r; return r; @@ -399,6 +398,12 @@ static void MakeSortedTownList() { Town *t; int n = 0; + + /* Create array for sorting */ + _town_sort = realloc(_town_sort, _towns_size * sizeof(_town_sort[0])); + if (_town_sort == NULL) + error("Could not allocate memory for the town-sorting-list"); + FOR_ALL_TOWNS(t) if(t->xy) _town_sort[n++] = t->index; @@ -434,7 +439,7 @@ static void TownDirectoryWndProc(Window *w, WindowEvent *e) int y = 28; while (i < _num_town_sort) { - t = DEREF_TOWN(_town_sort[i]); + t = GetTown(_town_sort[i]); assert(t->xy); @@ -473,7 +478,7 @@ static void TownDirectoryWndProc(Window *w, WindowEvent *e) if (id_v >= _num_town_sort) { return;} // click out of town bounds { - Town *t = DEREF_TOWN(_town_sort[id_v]); + Town *t = GetTown(_town_sort[id_v]); assert(t->xy); ScrollMainWindowToTile(t->xy); diff --git a/train_cmd.c b/train_cmd.c index 686ce0bbf5..44813fdef9 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -245,20 +245,16 @@ static int32 CmdBuildRailWagon(uint engine, uint tile, uint32 flags) if (flags & DC_EXEC) { byte img = rvi->image_index; - Vehicle *u; + Vehicle *u, *w; v->spritenum = img; - u = _vehicles; - for(;;) { - if (u->type == VEH_Train && u->tile == (TileIndex)tile && - u->subtype == 4 && u->engine_type == engine) { - u = GetLastVehicleInChain(u); - break; - } + u = NULL; - if (++u == endof(_vehicles)) { - u = NULL; + FOR_ALL_VEHICLES(w) { + if (w->type == VEH_Train && w->tile == (TileIndex)tile && + w->subtype == 4 && w->engine_type == engine) { + u = GetLastVehicleInChain(w); break; } } @@ -598,7 +594,7 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) Vehicle *src, *dst, *src_head, *dst_head; bool is_loco; - src = &_vehicles[p1 & 0xffff]; + src = GetVehicle(p1 & 0xFFFF); if (src->type != VEH_Train) return CMD_ERROR; is_loco = !(RailVehInfo(src->engine_type)->flags & RVI_WAGON) @@ -609,7 +605,7 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) dst = NULL; if (!is_loco) dst = FindGoodVehiclePos(src); } else { - dst = &_vehicles[((int32)p1 >> 16)]; + dst = GetVehicle(((int32)p1 >> 16)); } // don't move the same vehicle.. @@ -746,7 +742,7 @@ int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -772,7 +768,7 @@ int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -1018,7 +1014,7 @@ int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -1047,7 +1043,7 @@ int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -1073,7 +1069,7 @@ int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN); - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner) || ((CheckStoppedInDepot(v) < 0) && !(SkipStoppedInDepotCheck))) return CMD_ERROR; @@ -1182,7 +1178,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v) int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - Vehicle *v = &_vehicles[p1]; + Vehicle *v = GetVehicle(p1); TrainFindDepotData tfdd; if (v->current_order.type == OT_GOTO_DEPOT) { @@ -1219,7 +1215,7 @@ int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) */ int32 CmdChangeTrainServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - Vehicle *v = &_vehicles[p1]; + Vehicle *v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -1677,7 +1673,7 @@ static bool ProcessTrainOrder(Vehicle *v) if (order.type == OT_GOTO_STATION) { if (order.station == v->last_station_visited) v->last_station_visited = 0xFFFF; - v->dest_tile = DEREF_STATION(order.station)->xy; + v->dest_tile = GetStation(order.station)->xy; result = CheckReverseTrain(v); } else if (order.type == OT_GOTO_DEPOT) { v->dest_tile = _depots[order.station].xy; @@ -1783,7 +1779,7 @@ static void TrainEnterStation(Vehicle *v, int station) v->last_station_visited = station; /* check if a train ever visited this station before */ - st = DEREF_STATION(station); + st = GetStation(station); if (!(st->had_vehicle_of_type & HVOT_TRAIN)) { st->had_vehicle_of_type |= HVOT_TRAIN; SetDParam(0, st->index); @@ -2608,7 +2604,7 @@ static const byte _depot_track_ind[4] = {0,1,0,1}; // Validation for the news item "Train is waiting in depot" bool ValidateTrainInDepot( uint data_a, uint data_b ) { - Vehicle *v = &_vehicles[data_a]; + Vehicle *v = GetVehicle(data_a); if (v->u.rail.track == 0x80 && (v->vehstatus | VS_STOPPED)) return true; else @@ -2752,7 +2748,7 @@ void OnNewDay_Train(Vehicle *v) /* update destination */ if (v->current_order.type == OT_GOTO_STATION && - (tile = DEREF_STATION(v->current_order.station)->train_tile) != 0) + (tile = GetStation(v->current_order.station)->train_tile) != 0) v->dest_tile = tile; if ((v->vehstatus & VS_STOPPED) == 0) { diff --git a/train_gui.c b/train_gui.c index 90d69da588..9333ecf1f3 100644 --- a/train_gui.c +++ b/train_gui.c @@ -90,7 +90,7 @@ void CcBuildLoco(bool success, uint tile, uint32 p1, uint32 p2) if (!success) return; - v = &_vehicles[_new_train_id]; + v = GetVehicle(_new_train_id); if (tile == _backup_orders_tile) { _backup_orders_tile = 0; RestoreVehicleOrders(v, _backup_orders_data); @@ -458,7 +458,7 @@ static void TrainDepotMoveVehicle(Vehicle *wagon, int sel, Vehicle *head) { Vehicle *v; - v = &_vehicles[sel]; + v = GetVehicle(sel); if (/*v->subtype == 0 ||*/ v == wagon) return; @@ -553,7 +553,7 @@ static void TrainDepotWndProc(Window *w, WindowEvent *e) if (WP(w,traindepot_d).sel == INVALID_VEHICLE) return; - v = &_vehicles[WP(w,traindepot_d).sel]; + v = GetVehicle(WP(w,traindepot_d).sel); WP(w,traindepot_d).sel = INVALID_VEHICLE; SetWindowDirty(w); @@ -658,7 +658,7 @@ static void RailVehicleRefitWndProc(Window *w, WindowEvent *e) { switch(e->event) { case WE_PAINT: { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); const byte *b; int sel; int x,y; @@ -734,7 +734,7 @@ static void RailVehicleRefitWndProc(Window *w, WindowEvent *e) } break; case 4: /* refit button */ if (WP(w,refit_d).cargo != 0xFF) { - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE))) DeleteWindow(w); } @@ -797,7 +797,7 @@ static void TrainViewWndProc(Window *w, WindowEvent *e) Vehicle *v; StringID str; - v = &_vehicles[w->window_number]; + v = GetVehicle(w->window_number); w->disabled_state = (v->owner == _local_player) ? 0 : 0x380; @@ -864,7 +864,7 @@ static void TrainViewWndProc(Window *w, WindowEvent *e) case WE_CLICK: { int wid = e->click.widget; - Vehicle *v = &_vehicles[w->window_number]; + Vehicle *v = GetVehicle(w->window_number); switch(wid) { case 5: /* start/stop train */ @@ -905,7 +905,7 @@ static void TrainViewWndProc(Window *w, WindowEvent *e) Vehicle *v; uint32 h; - v = &_vehicles[w->window_number]; + v = GetVehicle(w->window_number); assert(v->type == VEH_Train); h = CheckStoppedInDepot(v) >= 0 ? (1 << 9) : (1 << 12); if (h != w->hidden_state) { @@ -1003,7 +1003,7 @@ static void DrawTrainDetailsWindow(Window *w) if (det_tab == 3) // reset tot_cargo array to 0 values memset(tot_cargo, 0, sizeof(tot_cargo)); - u = v = &_vehicles[w->window_number]; + u = v = GetVehicle(w->window_number); do { if (det_tab != 3) num++; @@ -1114,7 +1114,7 @@ static void TrainDetailsWndProc(Window *w, WindowEvent *e) Vehicle *v; switch(e->click.widget) { case 2: /* name train */ - v = &_vehicles[w->window_number]; + v = GetVehicle(w->window_number); SetDParam(0, v->unitnumber); ShowQueryString(v->string_id, STR_8865_NAME_TRAIN, 31, 150, w->window_class, w->window_number); break; @@ -1125,7 +1125,7 @@ static void TrainDetailsWndProc(Window *w, WindowEvent *e) case 7: /* dec serv interval */ mod = _ctrl_pressed? -5 : -10; do_change_service_int: - v = &_vehicles[w->window_number]; + v = GetVehicle(w->window_number); mod += v->service_interval; /* %-based service interval max 5%-90% @@ -1276,7 +1276,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) w->widget[1].unkA = STR_881B_TRAINS; } else { /* Station Name -- (###) Trains */ - SetDParam(0, DEREF_STATION(station)->index); + SetDParam(0, GetStation(station)->index); SetDParam(1, w->vscroll.count); w->widget[1].unkA = STR_SCHEDULED_TRAINS; } @@ -1290,7 +1290,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); for (i = w->vscroll.pos; i < max; ++i) { - Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); + Vehicle *v = GetVehicle(vl->sort_list[i].index); StringID str; assert(v->type == VEH_Train && v->owner == owner); @@ -1344,7 +1344,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) if (id_v >= vl->list_length) return; // click out of list bound - v = DEREF_VEHICLE(vl->sort_list[id_v].index); + v = GetVehicle(vl->sort_list[id_v].index); assert(v->type == VEH_Train && v->subtype == 0 && v->owner == owner); diff --git a/ttd.c b/ttd.c index 8d3955a90a..61680c1121 100644 --- a/ttd.c +++ b/ttd.c @@ -482,6 +482,35 @@ void ParseResolution(int res[2], char *s) res[1] = strtoul(t + 1, NULL, 0); } +static void InitializeDynamicVariables(void) +{ + /* Dynamic stuff needs to be initialized somewhere... */ + _stations_size = lengthof(_stations); + _station_sort = NULL; + + _vehicles_size = lengthof(_vehicles); + _vehicle_sort = NULL; + + _towns_size = lengthof(_towns); + _town_sort = NULL; + + _industries_size = lengthof(_industries); + _industry_sort = NULL; +} + +static void UnInitializeDynamicVariables(void) +{ + /* Dynamic stuff needs to be free'd somewhere... */ + free(_station_sort); + + free(_vehicle_sort); + + free(_town_sort); + + free(_industry_sort); +} + + void LoadIntroGame() { char filename[256]; @@ -640,6 +669,9 @@ int ttd_main(int argc, char* argv[]) // initialize airport state machines InitializeAirports(); + /* initialize all variables that are allocated dynamically */ + InitializeDynamicVariables(); + // Sample catalogue DEBUG(misc, 1) ("Loading sound effects..."); _os_version = GetOSVersion(); @@ -721,6 +753,9 @@ int ttd_main(int argc, char* argv[]) // uninitialize airport state machines UnInitializeAirports(); + /* uninitialize variables that are allocated dynamic */ + UnInitializeDynamicVariables(); + return 0; } diff --git a/vehicle.c b/vehicle.c index 2535047419..1d009221c3 100644 --- a/vehicle.c +++ b/vehicle.c @@ -15,6 +15,10 @@ #define INVALID_COORD (-0x8000) #define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0))) +enum { + VEHICLES_MIN_FREE_FOR_AI = 90 +}; + void VehicleServiceInDepot(Vehicle *v) { v->date_of_last_service = _date; @@ -106,14 +110,13 @@ Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z) int x2 = GET_TILE_X(to); int y2 = GET_TILE_Y(to); Vehicle *veh; - uint count; /* Make sure x1 < x2 or y1 < y2 */ if (x1 > x2 || y1 > y2) { intswap(x1,x2); intswap(y1,y2); } - for(veh = _vehicles, count=lengthof(_vehicles); count != 0; count--, veh++) { + FOR_ALL_VEHICLES(veh) { if ((veh->type == VEH_Train || veh->type == VEH_Road) && (z==0xFF || veh->z_pos == z)) { if ((veh->x_pos>>4) >= x1 && (veh->x_pos>>4) <= x2 && (veh->y_pos>>4) >= y1 && (veh->y_pos>>4) <= y2) { @@ -212,8 +215,7 @@ static Vehicle *InitializeVehicle(Vehicle *v) Vehicle *ForceAllocateSpecialVehicle() { Vehicle *v; - for(v=_vehicles + NUM_NORMAL_VEHICLES; - v!=&_vehicles[NUM_NORMAL_VEHICLES+NUM_SPECIAL_VEHICLES]; v++) { + FOR_ALL_VEHICLES_FROM(v, NUM_NORMAL_VEHICLES) { if (v->type == 0) return InitializeVehicle(v); } @@ -224,7 +226,10 @@ Vehicle *ForceAllocateSpecialVehicle() Vehicle *ForceAllocateVehicle() { Vehicle *v; - for(v=_vehicles; v!=&_vehicles[NUM_NORMAL_VEHICLES]; v++) { + FOR_ALL_VEHICLES(v) { + if (v->index >= NUM_NORMAL_VEHICLES) + return NULL; + if (v->type == 0) return InitializeVehicle(v); } @@ -239,12 +244,15 @@ Vehicle *AllocateVehicle() if (IS_HUMAN_PLAYER(_current_player)) { num = 0; - for(v=_vehicles; v!=&_vehicles[NUM_NORMAL_VEHICLES]; v++) { + FOR_ALL_VEHICLES(v) { + if (v->index >= NUM_NORMAL_VEHICLES) + break; + if (v->type == 0) num++; } - if (num <= 90) + if (num <= VEHICLES_MIN_FREE_FOR_AI) return NULL; } @@ -268,7 +276,7 @@ void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc) for(;;) { veh = _vehicle_position_hash[ (x+y)&0xFFFF ]; while (veh != INVALID_VEHICLE) { - Vehicle *v = &_vehicles[veh]; + Vehicle *v = GetVehicle(veh); void *a; if ((a = proc(v, data)) != NULL) @@ -310,7 +318,7 @@ void UpdateVehiclePosHash(Vehicle *v, int x, int y) if (old_hash != NULL) { Vehicle *last = NULL; int idx = *old_hash; - while((u = &_vehicles[idx]) != v) { + while ((u = GetVehicle(idx)) != v) { idx = u->next_hash; assert(idx != INVALID_VEHICLE); last = u; @@ -335,7 +343,7 @@ void InitializeVehicles() int i; // clear it... - memset(&_vehicles, 0, sizeof(_vehicles)); + memset(&_vehicles, 0, sizeof(_vehicles[0]) * _vehicles_size); memset(&_waypoints, 0, sizeof(_waypoints)); memset(&_depots, 0, sizeof(_depots)); @@ -359,24 +367,25 @@ Vehicle *GetPrevVehicleInChain(Vehicle *v) { Vehicle *org = v; - v = _vehicles; - while (v->type != VEH_Train || org != v->next) { - if (++v == endof(_vehicles)) - return NULL; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && org == v->next) + return v; } - return v; + return NULL; } Vehicle *GetFirstVehicleInChain(Vehicle *v) { - for(;;) { - Vehicle *u = v; - v = _vehicles; - while (v->type != VEH_Train || u != v->next) { - if (++v == endof(_vehicles)) - return u; - } + Vehicle *u; + + while (true) { + u = v; + v = GetPrevVehicleInChain(v); + /* If there is no such vehicle, + 'v' == NULL and so 'u' is the first vehicle in chain */ + if (v == NULL) + return u; } } @@ -658,7 +667,7 @@ void ViewportAddVehicles(DrawPixelInfo *dpi) for(;;) { veh = _vehicle_position_hash[ (x+y)&0xFFFF ]; while (veh != INVALID_VEHICLE) { - v = &_vehicles[veh]; + v = GetVehicle(veh); if (!(v->vehstatus & VS_HIDDEN) && dpi->left <= v->right_coord && @@ -1410,7 +1419,7 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */ uint16 new_engine_type = (uint16)(p2 & 0xFFFF); uint32 autorefit_money = (p2 >> 16) * 100000; - Vehicle *v = DEREF_VEHICLE(p1); + Vehicle *v = GetVehicle(p1); int cost, build_cost; SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); @@ -1628,7 +1637,7 @@ int32 CmdNameVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) Vehicle *v; StringID str; - v = &_vehicles[p1]; + v = GetVehicle(p1); if (!CheckOwnership(v->owner)) return CMD_ERROR; @@ -2013,10 +2022,11 @@ static void Load_VEHS() Vehicle *v; while ((index = SlIterateArray()) != -1) { - Vehicle *v = &_vehicles[index]; + Vehicle *v = GetVehicle(index); + v->next_in_chain_old = INVALID_VEHICLE; SlObject(v, _veh_descs[SlReadByte()]); - v->next = v->next_in_chain_old == INVALID_VEHICLE ? NULL : &_vehicles[v->next_in_chain_old]; + v->next = (v->next_in_chain_old == INVALID_VEHICLE) ? NULL : GetVehicle(v->next_in_chain_old); if (v->type == VEH_Train) v->u.rail.first_engine = 0xffff; @@ -2035,6 +2045,11 @@ static void Load_VEHS() for (w = v->next; w; w = w->next) w->u.rail.first_engine = v->engine_type; } + + /* This is to ensure all pointers are within the limits of + _vehicles_size */ + if (_vehicle_id_ctr_day >= _vehicles_size) + _vehicle_id_ctr_day = 0; } static const byte _depot_desc[] = { diff --git a/vehicle.h b/vehicle.h index 59dbaf62ef..29bf42362a 100644 --- a/vehicle.h +++ b/vehicle.h @@ -408,9 +408,6 @@ byte GetDirectionTowards(Vehicle *v, int x, int y); #define BEGIN_ENUM_WAGONS(v) do { #define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL); -#define DEREF_VEHICLE(i) (&_vehicles[i]) -#define FOR_ALL_VEHICLES(v) for(v=_vehicles; v != endof(_vehicles); v++) - /* vehicle.c */ enum { NUM_NORMAL_VEHICLES = 2048, @@ -419,6 +416,18 @@ enum { }; VARDEF Vehicle _vehicles[NUM_VEHICLES]; +VARDEF uint _vehicles_size; + +VARDEF SortStruct *_vehicle_sort; + +static inline Vehicle *GetVehicle(uint index) +{ + assert(index < _vehicles_size); + return &_vehicles[index]; +} + +#define FOR_ALL_VEHICLES(v) for(v = _vehicles; v != &_vehicles[_vehicles_size]; v++) +#define FOR_ALL_VEHICLES_FROM(v, from) for(v = GetVehicle(from); v != &_vehicles[_vehicles_size]; v++) VARDEF Order _order_array[5000]; VARDEF Order *_ptr_to_next_order; diff --git a/vehicle_gui.c b/vehicle_gui.c index 0f64ed7cbc..5c8cd07592 100644 --- a/vehicle_gui.c +++ b/vehicle_gui.c @@ -80,13 +80,17 @@ void ResortVehicleLists(void) void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station) { - SortStruct sort_list[NUM_NORMAL_VEHICLES]; int subtype = (type != VEH_Aircraft) ? 0 : 2; int n = 0; int i; if (!(vl->flags & VL_REBUILD)) return; + /* Create array for sorting */ + _vehicle_sort = realloc(_vehicle_sort, _vehicles_size * sizeof(_vehicle_sort[0])); + if (_vehicle_sort == NULL) + error("Could not allocate memory for the vehicle-sorting-list"); + DEBUG(misc, 1) ("Building vehicle list for player %d station %d...", owner, station); @@ -97,8 +101,8 @@ void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station) const Order *ord; for (ord = v->schedule_ptr; ord->type != OT_NOTHING; ++ord) if (ord->type == OT_GOTO_STATION && ord->station == station) { - sort_list[n].index = v - _vehicles; - sort_list[n].owner = v->owner; + _vehicle_sort[n].index = v->index; + _vehicle_sort[n].owner = v->owner; ++n; break; } @@ -108,18 +112,20 @@ void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station) const Vehicle *v; FOR_ALL_VEHICLES(v) { if (v->type == type && v->subtype <= subtype && v->owner == owner) { - sort_list[n].index = v - _vehicles; - sort_list[n].owner = v->owner; + _vehicle_sort[n].index = v->index; + _vehicle_sort[n].owner = v->owner; ++n; } } } - vl->sort_list = realloc(vl->sort_list, n * sizeof(vl->sort_list[0])); /* XXX unchecked malloc */ + vl->sort_list = realloc(vl->sort_list, n * sizeof(vl->sort_list[0])); + if (vl->sort_list == NULL) + error("Could not allocate memory for the vehicle-sorting-list"); vl->list_length = n; for (i = 0; i < n; ++i) - vl->sort_list[i] = sort_list[i]; + vl->sort_list[i] = _vehicle_sort[i]; vl->flags &= ~VL_REBUILD; vl->flags |= VL_RESORT; @@ -176,7 +182,7 @@ int CDECL GeneralOwnerSorter(const void *a, const void *b) */ int CDECL VehicleUnsortedSorter(const void *a, const void *b) { - return DEREF_VEHICLE((*(const SortStruct*)a).index)->index - DEREF_VEHICLE((*(const SortStruct*)b).index)->index; + return GetVehicle((*(const SortStruct*)a).index)->index - GetVehicle((*(const SortStruct*)b).index)->index; } // if the sorting criteria had the same value, sort vehicle by unitnumber @@ -184,8 +190,8 @@ int CDECL VehicleUnsortedSorter(const void *a, const void *b) int CDECL VehicleNumberSorter(const void *a, const void *b) { - const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); - const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); + const Vehicle *va = GetVehicle((*(const SortStruct*)a).index); + const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index); int r = va->unitnumber - vb->unitnumber; return (_internal_sort_order & 1) ? -r : r; @@ -196,8 +202,8 @@ int CDECL VehicleNameSorter(const void *a, const void *b) { const SortStruct *cmp1 = (const SortStruct*)a; const SortStruct *cmp2 = (const SortStruct*)b; - const Vehicle *va = DEREF_VEHICLE(cmp1->index); - const Vehicle *vb = DEREF_VEHICLE(cmp2->index); + const Vehicle *va = GetVehicle(cmp1->index); + const Vehicle *vb = GetVehicle(cmp2->index); char buf1[64] = "\0"; int r; @@ -224,8 +230,8 @@ int CDECL VehicleNameSorter(const void *a, const void *b) int CDECL VehicleAgeSorter(const void *a, const void *b) { - const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); - const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); + const Vehicle *va = GetVehicle((*(const SortStruct*)a).index); + const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index); int r = va->age - vb->age; VEHICLEUNITNUMBERSORTER(r, va, vb); @@ -235,8 +241,8 @@ int CDECL VehicleAgeSorter(const void *a, const void *b) int CDECL VehicleProfitThisYearSorter(const void *a, const void *b) { - const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); - const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); + const Vehicle *va = GetVehicle((*(const SortStruct*)a).index); + const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index); int r = va->profit_this_year - vb->profit_this_year; VEHICLEUNITNUMBERSORTER(r, va, vb); @@ -246,8 +252,8 @@ int CDECL VehicleProfitThisYearSorter(const void *a, const void *b) int CDECL VehicleProfitLastYearSorter(const void *a, const void *b) { - const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); - const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); + const Vehicle *va = GetVehicle((*(const SortStruct*)a).index); + const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index); int r = va->profit_last_year - vb->profit_last_year; VEHICLEUNITNUMBERSORTER(r, va, vb); @@ -257,8 +263,8 @@ int CDECL VehicleProfitLastYearSorter(const void *a, const void *b) int CDECL VehicleCargoSorter(const void *a, const void *b) { - const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); - const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); + const Vehicle *va = GetVehicle((*(const SortStruct*)a).index); + const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index); const Vehicle *v; int r = 0; int i; @@ -286,8 +292,8 @@ int CDECL VehicleCargoSorter(const void *a, const void *b) int CDECL VehicleReliabilitySorter(const void *a, const void *b) { - const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); - const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); + const Vehicle *va = GetVehicle((*(const SortStruct*)a).index); + const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index); int r = va->reliability - vb->reliability; VEHICLEUNITNUMBERSORTER(r, va, vb); @@ -297,8 +303,8 @@ int CDECL VehicleReliabilitySorter(const void *a, const void *b) int CDECL VehicleMaxSpeedSorter(const void *a, const void *b) { - const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); - const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); + const Vehicle *va = GetVehicle((*(const SortStruct*)a).index); + const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index); int r = va->max_speed - vb->max_speed; VEHICLEUNITNUMBERSORTER(r, va, vb); diff --git a/viewport.c b/viewport.c index f28465230e..3e86cf8d7e 100644 --- a/viewport.c +++ b/viewport.c @@ -116,7 +116,7 @@ void AssignWindowViewport(Window *w, int x, int y, if (follow_flags & 0x80000000) { Vehicle *veh; WP(w,vp_d).follow_vehicle = (VehicleID)(follow_flags & 0xFFFF); - veh = &_vehicles[WP(w,vp_d).follow_vehicle]; + veh = GetVehicle(WP(w,vp_d).follow_vehicle); pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos); } else { int x = GET_TILE_X(follow_flags) * 16; @@ -1271,7 +1271,7 @@ void UpdateViewportPosition(Window *w) Vehicle *veh; Point pt; - veh = &_vehicles[WP(w,vp_d).follow_vehicle]; + veh = GetVehicle(WP(w,vp_d).follow_vehicle); pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos); SetViewportPosition(w, pt.x, pt.y); } else {