Code
4047/// Move a single stack (civilian plus escort) to its destination4048void CvTacticalAI::PlotSingleHexOperationMoves(CvAIEscortedOperation* pOperation)4049{4050 int iUnitID;4051 UnitHandle pCivilian;4052 UnitHandle pEscort;4053 CvPlot* pCivilianMove;4054 CvPlot* pEscortMove;4055 bool bSaveMoves = false;40564057 // Simplification - assume only 1 army per operation now4058 if(pOperation->GetFirstArmyID() == -1)4059 {4060 return;4061 }4062 CvArmyAI* pThisArmy = m_pPlayer->getArmyAI(pOperation->GetFirstArmyID());4063 iUnitID = pThisArmy->GetFirstUnitID();4064 if(iUnitID != -1)4065 {4066 pCivilian = m_pPlayer->getUnit(iUnitID);4067 }40684069 if(!pCivilian)4070 {4071 return;4072 }40734074 // ESCORT AND CIVILIAN MEETING UP4075 if(pThisArmy->GetArmyAIState() == ARMYAISTATE_WAITING_FOR_UNITS_TO_REINFORCE ||4076 pThisArmy->GetArmyAIState() == ARMYAISTATE_WAITING_FOR_UNITS_TO_CATCH_UP)4077 {4078 pEscort = m_pPlayer->getUnit(pThisArmy->GetNextUnitID());4079 if(!pEscort || pEscort->TurnProcessed())4080 {4081 // Escort died or was poached for other tactical action, operation will clean itself up when call CheckOnTarget()4082 return;4083 }40844085 // Check to make sure escort can get to civilian4086 if(pEscort->GeneratePath(pCivilian->plot()))4087 {4088 // He can, so have civilian remain in place4089 ExecuteMoveToPlot(pCivilian, pCivilian->plot());40904091 if(pThisArmy->GetNumSlotsFilled() > 1)4092 {4093 if(pEscort)4094 {4095 // Move escort over4096 ExecuteMoveToPlot(pEscort, pCivilian->plot());4097 if(GC.getLogging() && GC.getAILogging())4098 {4099 CvString strTemp;4100 CvString strLogString;4101 strTemp = GC.getUnitInfo(pEscort->getUnitType())->GetDescription();4102 strLogString.Format("Moving escorting %s to civilian for operation, Civilian X: %d, Civilian Y: %d, X: %d, Y: %d", strTemp.GetCString(), pCivilian->plot()->getX(), pCivilian->plot()->getY(), pEscort->getX(), pEscort->getY());4103 LogTacticalMessage(strLogString);4104 }4105 }4106 }4107 }41084109 // Find a new place to meet up, look at all hexes adjacent to civilian4110 else4111 {4112 for(int iI = 0; iI < NUM_DIRECTION_TYPES; iI++)4113 {4114 CvPlot* pPlot = plotDirection(pCivilian->getX(), pCivilian->getY(), ((DirectionTypes)iI));4115 if(pPlot != NULL)4116 {4117 // Has to be somewhere we can move and be empty of other units4118 if(pEscort->canEnterTerrain(*pPlot) && pEscort->canEnterTerritory(pPlot->getTeam()))4119 {4120 if(pPlot->getNumUnits() == 0)4121 {4122 if(pEscort->GeneratePath(pPlot) && pCivilian->GeneratePath(pPlot))4123 {4124 ExecuteMoveToPlot(pEscort, pPlot);4125 ExecuteMoveToPlot(pCivilian, pPlot);4126 if(GC.getLogging() && GC.getAILogging())4127 {4128 CvString strTemp;4129 CvString strLogString;4130 strTemp = GC.getUnitInfo(pEscort->getUnitType())->GetDescription();4131 strLogString.Format("Moving escorting %s to open hex, Open hex X: %d, Open hex Y: %d, X: %d, Y: %d", strTemp.GetCString(), pPlot->getX(), pPlot->getY(), pEscort->getX(), pEscort->getY());4132 LogTacticalMessage(strLogString);4133 strTemp = GC.getUnitInfo(pCivilian->getUnitType())->GetDescription();4134 strLogString.Format("Moving %s to open hex, Open hex X: %d, Open hex Y: %d, X: %d, Y: %d", strTemp.GetCString(), pPlot->getX(), pPlot->getY(), pCivilian->getX(), pCivilian->getY());4135 LogTacticalMessage(strLogString);4136 }4137 return;4138 }4139 }4140 }4141 }4142 }41434144 // Didn't find an alternative, must abort operation4145 pOperation->RetargetCivilian(pCivilian.pointer(), pThisArmy);4146 pCivilian->finishMoves();4147 pEscort->finishMoves();4148 if(GC.getLogging() && GC.getAILogging())4149 {4150 CvString strTemp;4151 CvString strLogString;4152 strLogString.Format("Retargeting civilian escort operation. No empty tile adjacent to civilian to meet.");4153 LogTacticalMessage(strLogString);4154 }4155 }4156 }41574158 // MOVING TO TARGET4159 else4160 {4161 // If we're not there yet, we have work to do (otherwise CheckOnTarget() will finish operation for us)4162 if(pCivilian->plot() != pOperation->GetTargetPlot())4163 {4164 // Look at where we'd move this turn taking units into consideration4165 int iFlags = 0;4166 if(pThisArmy->GetNumSlotsFilled() > 1)4167 {4168 iFlags = MOVE_UNITS_IGNORE_DANGER;4169 }41704171 // Handle case of no path found at all for civilian4172 if(!pCivilian->GeneratePath(pOperation->GetTargetPlot(), iFlags, false /*bReuse*/))4173 {4174 pOperation->RetargetCivilian(pCivilian.pointer(), pThisArmy);4175 pCivilian->finishMoves();4176 pEscort = m_pPlayer->getUnit(pThisArmy->GetNextUnitID());4177 if(pEscort)4178 {4179 pEscort->finishMoves();4180 }4181 if(GC.getLogging() && GC.getAILogging())4182 {4183 CvString strLogString;4184 strLogString.Format("Retargeting civilian escort operation (path lost to target), X: %d, Y: %d", pOperation->GetTargetPlot()->getX(), pOperation->GetTargetPlot()->getY());4185 LogTacticalMessage(strLogString);4186 }4187 }41884189 else4190 {4191 pCivilianMove = pCivilian->GetPathEndTurnPlot();4192 bSaveMoves = (pCivilianMove == pOperation->GetTargetPlot());4193 if(pThisArmy->GetNumSlotsFilled() == 1)4194 {4195 ExecuteMoveToPlot(pCivilian, pCivilianMove, bSaveMoves);4196 if(GC.getLogging() && GC.getAILogging())4197 {4198 CvString strLogString;4199 CvString strTemp;4200 strTemp = pCivilian->getUnitInfo().GetDescription();4201 strLogString.Format("Moving %s without escort to target, X: %d, Y: %d", strTemp.GetCString(), pCivilian->plot()->getX(), pCivilian->plot()->getY());4202 LogTacticalMessage(strLogString);4203 }4204 }42054206 else4207 {4208 pEscort = m_pPlayer->getUnit(pThisArmy->GetNextUnitID());42094210 // See if escort can move to the same location in one turn4211 if(TurnsToReachTarget(pEscort, pCivilianMove) <= 1)4212 {4213 ExecuteMoveToPlot(pCivilian, pCivilianMove, bSaveMoves);4214 ExecuteMoveToPlot(pEscort, pCivilianMove);4215 if(GC.getLogging() && GC.getAILogging())4216 {4217 CvString strLogString;4218 CvString strTemp;4219 strTemp = pCivilian->getUnitInfo().GetDescription();4220 strLogString.Format("Moving %s to target, X: %d, Y: %d", strTemp.GetCString(), pCivilian->getX(), pCivilian->getY());4221 LogTacticalMessage(strLogString);4222 strTemp = pEscort->getUnitInfo().GetDescription();4223 strLogString.Format("Moving escorting %s to target, X: %d, Y: %d", strTemp.GetCString(), pEscort->getX(), pEscort->getY());4224 LogTacticalMessage(strLogString);4225 }4226 }42274228 else4229 {4230 CvTacticalAnalysisCell* pCell = GC.getGame().GetTacticalAnalysisMap()->GetCell(pCivilianMove->GetPlotIndex());4231 UnitHandle pBlockingUnit = pCivilianMove->getBestDefender(m_pPlayer->GetID());42324233 // See if friendly blocking unit is ending the turn there, or if no blocking unit (which indicates this is somewhere civilian4234 // can move that escort can't -- like minor civ territory), then find a new path based on moving the escort4235 if(pCell->IsFriendlyTurnEndTile() || !pBlockingUnit)4236 {4237 if(!pEscort->GeneratePath(pOperation->GetTargetPlot(), 0, false /*bReuse*/))4238 {4239 pOperation->RetargetCivilian(pCivilian.pointer(), pThisArmy);4240 pCivilian->finishMoves();4241 pEscort->finishMoves();4242 if(GC.getLogging() && GC.getAILogging())4243 {4244 CvString strLogString;4245 strLogString.Format("Retargeting civilian escort operation (path lost to target), X: %d, Y: %d", pOperation->GetTargetPlot()->getX(), pOperation->GetTargetPlot()->getY());4246 LogTacticalMessage(strLogString);4247 }4248 }4249 else4250 {4251 pEscortMove = pCivilian->GetPathEndTurnPlot();4252 bSaveMoves = (pEscortMove == pOperation->GetTargetPlot());42534254 // See if civilian can move to the same location in one turn4255 if(TurnsToReachTarget(pCivilian, pEscortMove) <= 1)4256 {4257 ExecuteMoveToPlot(pEscort, pEscortMove);4258 ExecuteMoveToPlot(pCivilian, pEscortMove, bSaveMoves);4259 if(GC.getLogging() && GC.getAILogging())4260 {4261 CvString strLogString;4262 CvString strTemp;4263 strTemp = pEscort->getUnitInfo().GetDescription();4264 strLogString.Format("Moving escorting %s to target, X: %d, Y: %d", strTemp.GetCString(), pEscort->getX(), pEscort->getY());4265 LogTacticalMessage(strLogString);4266 strTemp = pCivilian->getUnitInfo().GetDescription();4267 strLogString.Format("Moving %s to target, X: %d, Y: %d", strTemp.GetCString(), pCivilian->getX(), pCivilian->getY());4268 LogTacticalMessage(strLogString);4269 }4270 }4271 else4272 {4273 // Didn't find an alternative, retarget operation4274 pOperation->RetargetCivilian(pCivilian.pointer(), pThisArmy);4275 pCivilian->finishMoves();4276 pEscort->finishMoves();4277 if(GC.getLogging() && GC.getAILogging())4278 {4279 CvString strLogString;4280 strLogString.Format("Retargeting civilian escort operation. Too many blocking units.");4281 LogTacticalMessage(strLogString);4282 }4283 }4284 }4285 }42864287 // Looks like we should be able to move the blocking unit out of the way4288 else4289 {4290 if(ExecuteMoveOfBlockingUnit(pBlockingUnit))4291 {4292 ExecuteMoveToPlot(pEscort, pCivilianMove);4293 ExecuteMoveToPlot(pCivilian, pCivilianMove, bSaveMoves);4294 if(GC.getLogging() && GC.getAILogging())4295 {4296 CvString strLogString;4297 CvString strTemp;4298 strTemp = pEscort->getUnitInfo().GetDescription();4299 strLogString.Format("Moving escorting %s to target, X: %d, Y: %d", strTemp.GetCString(), pEscort->getX(), pEscort->getY());4300 LogTacticalMessage(strLogString);4301 strTemp = pCivilian->getUnitInfo().GetDescription();4302 strLogString.Format("Moving %s to target, X: %d, Y: %d", strTemp.GetCString(), pCivilian->getX(), pCivilian->getY());4303 LogTacticalMessage(strLogString);4304 }4305 }4306 else4307 {43084309 // Didn't find an alternative, try retargeting operation4310 pOperation->RetargetCivilian(pCivilian.pointer(), pThisArmy);4311 pCivilian->finishMoves();4312 pEscort->finishMoves();4313 if(GC.getLogging() && GC.getAILogging())4314 {4315 CvString strLogString;4316 strLogString.Format("Retargeting civilian escort operation. Could not move blocking unit.");4317 LogTacticalMessage(strLogString);4318 }4319 }4320 }4321 }4322 }4323 }4324 }4325 }4326}