//removes workers from factories until they are the minimum number to finish the current project //in still the same number of turns (as at the start of the function) int DecrementDueToWastedIndustry(bool max_industry) { m_pSystem->CalculateVariables(); const CAssemblyList& assembly_list = *m_pSystem->GetAssemblyList(); int unset = 0; if(assembly_list.IsEmpty() || assembly_list.GetWasBuildingBought()) return unset; const int min_rounds = m_pSystem->NeededRoundsToBuild(0, true); AssertBotE(min_rounds >= 1); if(max_industry && min_rounds > 1 || m_pSystem->GetWorker(WORKER::INDUSTRY_WORKER) == 0) return unset; while(true) { SetWorker(WORKER::INDUSTRY_WORKER, CSystem::SET_WORKER_MODE_DECREMENT); ++unset; m_pSystem->CalculateVariables(); const int current_rounds = m_pSystem->NeededRoundsToBuild(0, true, false); if(m_pSystem->GetWorker(WORKER::INDUSTRY_WORKER) == 0) { if(min_rounds < current_rounds) OnBestIndustryWorkerCountFound(unset); return unset; } if(min_rounds < current_rounds) { OnBestIndustryWorkerCountFound(unset); return unset; } } }
/** Set value for a dynamic PCD entry. This routine find the local token number according to dynamic-ex PCD's token space guid and token number firstly, and invoke callback function if this PCD entry registered callback function. Finally, invoken general SetWorker to set PCD value. @param ExTokenNumber Dynamic-ex PCD token number. @param Guid Token space guid for dynamic-ex PCD. @param Data PCD value want to be set @param SetSize Size of value. @param PtrType If TRUE, this PCD entry is pointer type. If FALSE, this PCD entry is not pointer type. @return status of SetWorker(). **/ EFI_STATUS ExSetWorker ( IN UINTN ExTokenNumber, IN CONST EFI_GUID *Guid, IN VOID *Data, IN OUT UINTN *Size, IN BOOLEAN PtrType ) { UINTN TokenNumber; if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) { return EFI_UNSUPPORTED; } TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber); if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) { return EFI_NOT_FOUND; } InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size); return SetWorker (TokenNumber, Data, Size, PtrType); }
/** Wrapper function for setting non-pointer type value for a PCD entry. @param TokenNumber Pcd token number autogenerated by build tools. @param Data Value want to be set for PCD entry @param Size Size of value. @return status of SetWorker. **/ EFI_STATUS SetValueWorker ( IN UINTN TokenNumber, IN VOID *Data, IN UINTN Size ) { return SetWorker (TokenNumber, Data, &Size, FALSE); }
/** Sets a value of a specified size for a given PCD token. When the PCD service sets a value, it will check to ensure that the size of the value being set is compatible with the Token's existing definition. If it is not, an error will be returned. @param[in] TokenNumber The PCD token number. @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token. On input, if the SizeOfValue is greater than the maximum size supported for this TokenNumber then the output value of SizeOfValue will reflect the maximum size supported for this TokenNumber. @param[in] Buffer The buffer to set for the PCD token. @retval EFI_SUCCESS Procedure returned successfully. @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was incompatible with a call to this function. Use GetSize() to retrieve the size of the target data. @retval EFI_NOT_FOUND The PCD service could not find the requested token number. **/ EFI_STATUS EFIAPI DxePcdSetPtr ( IN UINTN TokenNumber, IN OUT UINTN *SizeOfBuffer, IN VOID *Buffer ) { return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE); }
//puts an additional worker into industry, to prevent not finishing the project because //industry prod decreased due to loss of moral void SafeMoral() { const CAssemblyList& assembly_list = *m_pSystem->GetAssemblyList(); AssertBotE(m_WorkersLeftToSet >= 0); if(assembly_list.IsEmpty() || m_WorkersLeftToSet == 0) return; const int max_buildings = m_pSystem->GetNumberOfWorkbuildings(WORKER::INDUSTRY_WORKER, 0); if(m_pSystem->GetWorker(WORKER::INDUSTRY_WORKER) < max_buildings) SetWorker(WORKER::INDUSTRY_WORKER, CSystem::SET_WORKER_MODE_INCREMENT); }
//fills all remaining empty buildings of the given cathegory, only considering available workers and buildings bool FillRemainingSlots(WORKER::Typ type) { AssertBotE(m_WorkersLeftToSet >= 0); if(m_WorkersLeftToSet == 0) return false; m_WorkersLeftToSet += m_pSystem->GetWorker(type); m_pSystem->SetWorker(type, CSystem::SET_WORKER_MODE_SET, 0); const int buildings = m_pSystem->GetNumberOfWorkbuildings(type, 0); const int to_set = min(buildings, m_WorkersLeftToSet); SetWorker(type, CSystem::SET_WORKER_MODE_SET,to_set); return true; }
//distributes workers onto priorities remaining after max priorities have been processed //workers that cannot be set because of number of buildings are tried to be set into //the cathegory with next less workers void DoPriorities(const std::map<WORKER::Typ, int>& priorities, bool max_industry, bool safe_moral) { SafeMoralWorkerReserve reserve(*this, safe_moral); std::map<WORKER::Typ, int> prios(priorities); DoMaxPriorities(prios, max_industry); DefaultDistributionCalculator decalc(m_WorkersLeftToSet, prios); const std::vector<DistributionElem>& result = decalc.Calc(); int failed_to_set = 0; for(std::vector<DistributionElem>::const_iterator it = result.begin(); it != result.end(); ++it) { const int buildings = m_pSystem->GetNumberOfWorkbuildings(it->m_Type, 0); if(buildings >= it->m_iCount) { int try_set = it->m_iCount; if(it->m_Type != WORKER::INDUSTRY_WORKER) try_set += failed_to_set; if(buildings >= try_set) { if(it->m_Type != WORKER::INDUSTRY_WORKER) failed_to_set = 0; SetWorker(it->m_Type, CSystem::SET_WORKER_MODE_SET, try_set); } else { if(it->m_Type != WORKER::INDUSTRY_WORKER) failed_to_set -= buildings -it->m_iCount; SetWorker(it->m_Type, CSystem::SET_WORKER_MODE_SET, buildings); } } else { failed_to_set += it->m_iCount - buildings; SetWorker(it->m_Type, CSystem::SET_WORKER_MODE_SET, buildings); } AssertBotE(m_WorkersLeftToSet >= 0 && failed_to_set >= 0); failed_to_set += DecrementDueToFullStore(it->m_Type); if(it->m_Type == WORKER::INDUSTRY_WORKER) { failed_to_set += DecrementDueToWastedIndustry(max_industry); } } }
//removes workers from a cathegory which has a store until production + store <= store, //so that nothing will be wasted on next turn change int DecrementDueToFullStore(WORKER::Typ type) { int unset = 0; if(!m_pSystem->HasStore(type)) return unset; const int store = m_pSystem->GetResourceStore(type); while(true) { const int workers = m_pSystem->GetWorker(type); if(workers == 0) break; m_pSystem->CalculateVariables(); const int prod = m_pSystem->GetProduction()->GetXProd(type); if(store + prod <= m_pSystem->GetXStoreMax(type)) break; SetWorker(type, CSystem::SET_WORKER_MODE_DECREMENT); ++unset; } return unset; }
//Indreases workers in cathegories energy and food until we produce enough to suffice for the consumption we have bool IncreaseWorkersUntilSufficient(WORKER::Typ type, bool allow_insufficient) { AssertBotE(type == WORKER::ENERGY_WORKER || type == WORKER::FOOD_WORKER); if(m_pSystem->GetDisabledProductions()[type]) return true; while(true) { const int value = (type == WORKER::ENERGY_WORKER) ? m_pProd->GetEnergyProd() : m_pProd->GetFoodProd(); if(value >= 0) return true; if(m_WorkersLeftToSet <= 0) return allow_insufficient; const int number_of_buildings = m_pSystem->GetNumberOfWorkbuildings(type, 0); const int workers_set = m_pSystem->GetWorker(type); AssertBotE(workers_set <= number_of_buildings); if(workers_set == number_of_buildings) return allow_insufficient; SetWorker(type, CSystem::SET_WORKER_MODE_INCREMENT); m_pSystem->CalculateVariables(); } }
void OnBestIndustryWorkerCountFound(int& unset) { SetWorker(WORKER::INDUSTRY_WORKER, CSystem::SET_WORKER_MODE_INCREMENT); --unset; AssertBotE(unset >= 0); }