ai/default/default.c
changeset 2544 50cb52cdeb73
parent 2529 97c0b71ee7dd
child 2551 436aaaa22ba5
equal deleted inserted replaced
2543:a6344040f735 2544:50cb52cdeb73
   120 
   120 
   121 	p->ai.state = AIS_WANT_NEW_ROUTE;
   121 	p->ai.state = AIS_WANT_NEW_ROUTE;
   122 	p->ai.state_counter = 0;
   122 	p->ai.state_counter = 0;
   123 }
   123 }
   124 
   124 
   125 static int AiChooseTrainToBuild(byte railtype, int32 money, byte flag, TileIndex tile)
   125 static EngineID AiChooseTrainToBuild(byte railtype, int32 money, byte flag, TileIndex tile)
   126 {
   126 {
   127 	int best_veh_index = -1;
   127 	EngineID best_veh_index = INVALID_ENGINE;
   128 	byte best_veh_score = 0;
   128 	byte best_veh_score = 0;
   129 	int32 ret;
   129 	int32 ret;
   130 	int i;
   130 	EngineID i;
   131 
   131 
   132 	for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
   132 	for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
   133 		const RailVehicleInfo *rvi = RailVehInfo(i);
   133 		const RailVehicleInfo *rvi = RailVehInfo(i);
   134 		const Engine* e = GetEngine(i);
   134 		const Engine* e = GetEngine(i);
   135 
   135 
   150 	}
   150 	}
   151 
   151 
   152 	return best_veh_index;
   152 	return best_veh_index;
   153 }
   153 }
   154 
   154 
   155 static int AiChooseRoadVehToBuild(byte cargo, int32 money, TileIndex tile)
   155 static EngineID AiChooseRoadVehToBuild(byte cargo, int32 money, TileIndex tile)
   156 {
   156 {
   157 	int best_veh_index = -1;
   157 	EngineID best_veh_index = INVALID_ENGINE;
   158 	int32 best_veh_cost = 0;
   158 	int32 best_veh_cost = 0;
   159 	int32 ret;
   159 	int32 ret;
   160 
   160 
   161 	int i = _cargoc.ai_roadveh_start[cargo];
   161 	EngineID i = _cargoc.ai_roadveh_start[cargo];
   162 	int end = i + _cargoc.ai_roadveh_count[cargo];
   162 	EngineID end = i + _cargoc.ai_roadveh_count[cargo];
   163 	const Engine* e = GetEngine(i);
   163 	const Engine* e = GetEngine(i);
   164 
   164 
   165 	do {
   165 	do {
   166 		if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D)
   166 		if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D)
   167 			continue;
   167 			continue;
   174 	} while (++e, ++i != end);
   174 	} while (++e, ++i != end);
   175 
   175 
   176 	return best_veh_index;
   176 	return best_veh_index;
   177 }
   177 }
   178 
   178 
   179 static int AiChooseAircraftToBuild(int32 money, byte flag)
   179 static EngineID AiChooseAircraftToBuild(int32 money, byte flag)
   180 {
   180 {
   181 	int best_veh_index = -1;
   181 	EngineID best_veh_index = INVALID_ENGINE;
   182 	int32 best_veh_cost = 0;
   182 	int32 best_veh_cost = 0;
   183 	int32 ret;
   183 	int32 ret;
   184 
   184 
   185 	int i = AIRCRAFT_ENGINES_INDEX;
   185 	EngineID i = AIRCRAFT_ENGINES_INDEX;
   186 	int end = i + NUM_AIRCRAFT_ENGINES;
   186 	EngineID end = i + NUM_AIRCRAFT_ENGINES;
   187 	const Engine* e = GetEngine(i);
   187 	const Engine* e = GetEngine(i);
   188 
   188 
   189 	do {
   189 	do {
   190 		if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D)
   190 		if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D)
   191 			continue;
   191 			continue;
   216 
   216 
   217 	return base;
   217 	return base;
   218 }
   218 }
   219 
   219 
   220 #if 0
   220 #if 0
   221 static int AiChooseShipToBuild(byte cargo, int32 money)
   221 static EngineID AiChooseShipToBuild(byte cargo, int32 money)
   222 {
   222 {
   223 	// XXX: not done
   223 	// XXX: not done
   224 	return 0;
   224 	return INVALID_ENGINE;
   225 }
   225 }
   226 #endif
   226 #endif
   227 
   227 
   228 static int AiChooseRoadVehToReplaceWith(Player *p, Vehicle *v)
   228 static EngineID AiChooseRoadVehToReplaceWith(Player* p, Vehicle* v)
   229 {
   229 {
   230 	int32 avail_money = p->player_money + v->value;
   230 	int32 avail_money = p->player_money + v->value;
   231 	return AiChooseRoadVehToBuild(v->cargo_type, avail_money, v->tile);
   231 	return AiChooseRoadVehToBuild(v->cargo_type, avail_money, v->tile);
   232 }
   232 }
   233 
   233 
   234 static int AiChooseAircraftToReplaceWith(Player *p, Vehicle *v)
   234 static EngineID AiChooseAircraftToReplaceWith(Player* p, Vehicle* v)
   235 {
   235 {
   236 	int32 avail_money = p->player_money + v->value;
   236 	int32 avail_money = p->player_money + v->value;
   237 	return AiChooseAircraftToBuild(avail_money, v->engine_type>=253?1:0);
   237 	return AiChooseAircraftToBuild(avail_money, v->engine_type>=253?1:0);
   238 }
   238 }
   239 
   239 
   240 static int AiChooseTrainToReplaceWith(Player *p, Vehicle *v)
   240 static EngineID AiChooseTrainToReplaceWith(Player* p, Vehicle* v)
   241 {
   241 {
   242 	int32 avail_money = p->player_money + v->value;
   242 	int32 avail_money = p->player_money + v->value;
   243 	int num=0;
   243 	int num=0;
   244 	Vehicle *u = v;
   244 	Vehicle *u = v;
   245 
   245 
   249 
   249 
   250 	// XXX: check if a wagon
   250 	// XXX: check if a wagon
   251 	return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0, v->tile);
   251 	return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0, v->tile);
   252 }
   252 }
   253 
   253 
   254 static int AiChooseShipToReplaceWith(Player *p, Vehicle *v)
   254 static EngineID AiChooseShipToReplaceWith(Player* p, Vehicle* v)
   255 {
   255 {
   256 	error("!AiChooseShipToReplaceWith");
   256 	error("!AiChooseShipToReplaceWith");
   257 
   257 
   258 	/* maybe useless, but avoids compiler warning this way */
   258 	/* maybe useless, but avoids compiler warning this way */
   259 	return 0;
   259 	return INVALID_ENGINE;
   260 }
   260 }
   261 
   261 
   262 static void AiHandleGotoDepot(Player *p, int cmd)
   262 static void AiHandleGotoDepot(Player *p, int cmd)
   263 {
   263 {
   264 	if (p->ai.cur_veh->current_order.type != OT_GOTO_DEPOT)
   264 	if (p->ai.cur_veh->current_order.type != OT_GOTO_DEPOT)
   287 
   287 
   288 static void AiHandleReplaceTrain(Player *p)
   288 static void AiHandleReplaceTrain(Player *p)
   289 {
   289 {
   290 	Vehicle *v = p->ai.cur_veh;
   290 	Vehicle *v = p->ai.cur_veh;
   291 	BackuppedOrders orderbak[1];
   291 	BackuppedOrders orderbak[1];
   292 	int veh;
   292 	EngineID veh;
   293 
   293 
   294 	// wait until the vehicle reaches the depot.
   294 	// wait until the vehicle reaches the depot.
   295 	if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
   295 	if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
   296 		AiHandleGotoDepot(p, CMD_TRAIN_GOTO_DEPOT);
   296 		AiHandleGotoDepot(p, CMD_TRAIN_GOTO_DEPOT);
   297 		return;
   297 		return;
   298 	}
   298 	}
   299 
   299 
   300 	veh = AiChooseTrainToReplaceWith(p, v);
   300 	veh = AiChooseTrainToReplaceWith(p, v);
   301 	if (veh != -1) {
   301 	if (veh != INVALID_ENGINE) {
   302 		TileIndex tile;
   302 		TileIndex tile;
   303 
   303 
   304 		BackupVehicleOrders(v, orderbak);
   304 		BackupVehicleOrders(v, orderbak);
   305 		tile = v->tile;
   305 		tile = v->tile;
   306 
   306 
   307 		if (!CmdFailed(DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON)) &&
   307 		if (!CmdFailed(DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON)) &&
   308 			  !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE)) ) {
   308 			  !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE)) ) {
   309 			veh = _new_train_id;
   309 			VehicleID veh = _new_train_id;
   310 			AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
   310 			AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
   311 			DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN);
   311 			DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN);
   312 
   312 
   313 			DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
   313 			DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
   314 		}
   314 		}
   317 
   317 
   318 static void AiHandleReplaceRoadVeh(Player *p)
   318 static void AiHandleReplaceRoadVeh(Player *p)
   319 {
   319 {
   320 	Vehicle *v = p->ai.cur_veh;
   320 	Vehicle *v = p->ai.cur_veh;
   321 	BackuppedOrders orderbak[1];
   321 	BackuppedOrders orderbak[1];
   322 	int veh;
   322 	EngineID veh;
   323 
   323 
   324 	if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
   324 	if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
   325 		AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT);
   325 		AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT);
   326 		return;
   326 		return;
   327 	}
   327 	}
   328 
   328 
   329 	veh = AiChooseRoadVehToReplaceWith(p, v);
   329 	veh = AiChooseRoadVehToReplaceWith(p, v);
   330 	if (veh != -1) {
   330 	if (veh != INVALID_ENGINE) {
   331 		TileIndex tile;
   331 		TileIndex tile;
   332 
   332 
   333 		BackupVehicleOrders(v, orderbak);
   333 		BackupVehicleOrders(v, orderbak);
   334 		tile = v->tile;
   334 		tile = v->tile;
   335 
   335 
   336 		if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH)) &&
   336 		if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH)) &&
   337 			  !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH)) ) {
   337 			  !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH)) ) {
   338 			veh = _new_roadveh_id;
   338 			VehicleID veh = _new_roadveh_id;
   339 			AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
   339 			AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
   340 			DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
   340 			DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
   341 
   341 
   342 			DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
   342 			DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
   343 		}
   343 		}
   345 }
   345 }
   346 
   346 
   347 static void AiHandleReplaceAircraft(Player *p)
   347 static void AiHandleReplaceAircraft(Player *p)
   348 {
   348 {
   349 	Vehicle *v = p->ai.cur_veh;
   349 	Vehicle *v = p->ai.cur_veh;
   350 	int veh;
       
   351 	BackuppedOrders orderbak[1];
   350 	BackuppedOrders orderbak[1];
       
   351 	EngineID veh;
   352 
   352 
   353 	if (!IsAircraftHangarTile(v->tile) && !(v->vehstatus&VS_STOPPED)) {
   353 	if (!IsAircraftHangarTile(v->tile) && !(v->vehstatus&VS_STOPPED)) {
   354 		AiHandleGotoDepot(p, CMD_SEND_AIRCRAFT_TO_HANGAR);
   354 		AiHandleGotoDepot(p, CMD_SEND_AIRCRAFT_TO_HANGAR);
   355 		return;
   355 		return;
   356 	}
   356 	}
   357 
   357 
   358 	veh = AiChooseAircraftToReplaceWith(p, v);
   358 	veh = AiChooseAircraftToReplaceWith(p, v);
   359 	if (veh != -1) {
   359 	if (veh != INVALID_ENGINE) {
   360 		TileIndex tile;
   360 		TileIndex tile;
   361 
   361 
   362 		BackupVehicleOrders(v, orderbak);
   362 		BackupVehicleOrders(v, orderbak);
   363 		tile = v->tile;
   363 		tile = v->tile;
   364 
   364 
   365 		if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT)) &&
   365 		if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT)) &&
   366 			  !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT)) ) {
   366 			  !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT)) ) {
   367 			veh = _new_aircraft_id;
   367 			VehicleID veh = _new_aircraft_id;
   368 			AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
   368 			AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
   369 			DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT);
   369 			DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT);
   370 
   370 
   371 			DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
   371 			DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
   372 		}
   372 		}
   376 static void AiHandleReplaceShip(Player *p)
   376 static void AiHandleReplaceShip(Player *p)
   377 {
   377 {
   378 	error("!AiHandleReplaceShip");
   378 	error("!AiHandleReplaceShip");
   379 }
   379 }
   380 
   380 
   381 typedef int CheckReplaceProc(Player *p, Vehicle *v);
   381 typedef EngineID CheckReplaceProc(Player* p, Vehicle* v);
   382 
   382 
   383 static CheckReplaceProc * const _veh_check_replace_proc[] = {
   383 static CheckReplaceProc * const _veh_check_replace_proc[] = {
   384 	AiChooseTrainToReplaceWith,
   384 	AiChooseTrainToReplaceWith,
   385 	AiChooseRoadVehToReplaceWith,
   385 	AiChooseRoadVehToReplaceWith,
   386 	AiChooseShipToReplaceWith,
   386 	AiChooseShipToReplaceWith,
   397 
   397 
   398 static void AiStateCheckReplaceVehicle(Player *p)
   398 static void AiStateCheckReplaceVehicle(Player *p)
   399 {
   399 {
   400 	Vehicle *v = p->ai.cur_veh;
   400 	Vehicle *v = p->ai.cur_veh;
   401 
   401 
   402 	if (v->type == 0 || v->owner != _current_player || v->type > VEH_Ship || _veh_check_replace_proc[v->type - VEH_Train](p, v) == -1) {
   402 	if (v->type == 0 ||
       
   403 			v->owner != _current_player ||
       
   404 			v->type > VEH_Ship ||
       
   405 			_veh_check_replace_proc[v->type - VEH_Train](p, v) == INVALID_ENGINE) {
   403 		p->ai.state = AIS_VEH_LOOP;
   406 		p->ai.state = AIS_VEH_LOOP;
   404 	} else {
   407 	} else {
   405 		p->ai.state_counter = 0;
   408 		p->ai.state_counter = 0;
   406 		p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE;
   409 		p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE;
   407 	}
   410 	}
  1714 	8, 4
  1717 	8, 4
  1715 };
  1718 };
  1716 
  1719 
  1717 static void AiDoTerraformLand(TileIndex tile, int dir, int unk, int mode)
  1720 static void AiDoTerraformLand(TileIndex tile, int dir, int unk, int mode)
  1718 {
  1721 {
  1719 	byte old_player;
  1722 	PlayerID old_player;
  1720 	uint32 r;
  1723 	uint32 r;
  1721 	uint slope;
  1724 	uint slope;
  1722 	uint h;
  1725 	uint h;
  1723 
  1726 
  1724 	old_player = _current_player;
  1727 	old_player = _current_player;
  2375 
  2378 
  2376 static void AiStateBuildRailVeh(Player *p)
  2379 static void AiStateBuildRailVeh(Player *p)
  2377 {
  2380 {
  2378 	const AiDefaultBlockData *ptr;
  2381 	const AiDefaultBlockData *ptr;
  2379 	TileIndex tile;
  2382 	TileIndex tile;
  2380 	int i, veh;
  2383 	EngineID veh;
       
  2384 	int i;
  2381 	int cargo;
  2385 	int cargo;
  2382 	int32 cost;
  2386 	int32 cost;
  2383 	Vehicle *v;
  2387 	Vehicle *v;
  2384 	uint loco_id;
  2388 	uint loco_id;
  2385 
  2389 
  2404 			break;
  2408 			break;
  2405 	}
  2409 	}
  2406 
  2410 
  2407 	// Which locomotive to build?
  2411 	// Which locomotive to build?
  2408 	veh = AiChooseTrainToBuild(p->ai.railtype_to_use, p->player_money, (cargo!=CT_PASSENGERS)?1:0, tile);
  2412 	veh = AiChooseTrainToBuild(p->ai.railtype_to_use, p->player_money, (cargo!=CT_PASSENGERS)?1:0, tile);
  2409 	if (veh == -1) {
  2413 	if (veh == INVALID_ENGINE) {
  2410 handle_nocash:
  2414 handle_nocash:
  2411 		// after a while, if AI still doesn't have cash, get out of this block by selling the wagons.
  2415 		// after a while, if AI still doesn't have cash, get out of this block by selling the wagons.
  2412 		if (++p->ai.state_counter == 1000) {
  2416 		if (++p->ai.state_counter == 1000) {
  2413 			for(i=0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) {
  2417 			for(i=0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) {
  2414 				cost = DoCommandByTile(tile, p->ai.wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON);
  2418 				cost = DoCommandByTile(tile, p->ai.wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON);
  3495 
  3499 
  3496 static void AiStateBuildAircraftVehicles(Player *p)
  3500 static void AiStateBuildAircraftVehicles(Player *p)
  3497 {
  3501 {
  3498 	const AiDefaultBlockData *ptr;
  3502 	const AiDefaultBlockData *ptr;
  3499 	TileIndex tile;
  3503 	TileIndex tile;
  3500 	int veh;
  3504 	EngineID veh;
  3501 	int i;
  3505 	int i;
  3502 	uint loco_id;
  3506 	uint loco_id;
  3503 
  3507 
  3504 	ptr = _airport_default_block_data[p->ai.src.cur_building_rule];
  3508 	ptr = _airport_default_block_data[p->ai.src.cur_building_rule];
  3505 	for(;ptr->mode!=0;ptr++) {}
  3509 	for(;ptr->mode!=0;ptr++) {}
  3506 
  3510 
  3507 	tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs));
  3511 	tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs));
  3508 
  3512 
  3509 	veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind!=0 ? 1 : 0);
  3513 	veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind!=0 ? 1 : 0);
  3510 	if (veh == -1) return;
  3514 	if (veh == INVALID_ENGINE) return;
  3511 
  3515 
  3512 	/* XXX - Have the AI pick the hangar terminal in an airport. Eg get airport-type
  3516 	/* XXX - Have the AI pick the hangar terminal in an airport. Eg get airport-type
  3513 	 * and offset to the FIRST depot because the AI picks the st->xy tile */
  3517 	 * and offset to the FIRST depot because the AI picks the st->xy tile */
  3514 	tile += ToTileIndexDiff(GetAirport(GetStation(_m[tile].m2)->airport_type)->airport_depots[0]);
  3518 	tile += ToTileIndexDiff(GetAirport(GetStation(_m[tile].m2)->airport_type)->airport_depots[0]);
  3515 	if (CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT))) return;
  3519 	if (CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT))) return;