|
楼主 |
发表于 2013-12-26 18:14:14
|
显示全部楼层
本帖最后由 ming_infinite 于 2016-9-28 14:17 编辑
3研究和溢出Research&Overflow
3.1回合研究doResearch
来看过回合研究科技的时候,具体发生了什么。
CvPlayer.cpp
Line:19531- // --------------------------------------------------------------------------------
- void CvPlayer::doResearch()
- {
- if(GC.getGame().isOption(GAMEOPTION_NO_SCIENCE))
- {
- return;
- }
- AI_PERF_FORMAT("AI-perf.csv", ("CvPlayer::doResearch, Turn %03d, %s", GC.getGame().getElapsedGameTurns(), getCivilizationShortDescription()) );
- bool bForceResearchChoice;
- int iOverflowResearch;
- if(GetPlayerTechs()->IsResearch())
- {
- bForceResearchChoice = false;
- // Force player to pick Research if he doesn't have anything assigned
- if(GetPlayerTechs()->GetCurrentResearch() == NO_TECH)
- {
- if(GetID() == GC.getGame().getActivePlayer() && GetScienceTimes100() > 0)
- {
- chooseTech();
- }
- if(GC.getGame().getElapsedGameTurns() > 4)
- {
- AI_chooseResearch();
- bForceResearchChoice = true;
- }
- }
- TechTypes eCurrentTech = GetPlayerTechs()->GetCurrentResearch();
- if(eCurrentTech == NO_TECH)
- {
- int iOverflow = (GetScienceTimes100()) / std::max(1, calculateResearchModifier(eCurrentTech));
- changeOverflowResearchTimes100(iOverflow);
- }
- else
- {
- iOverflowResearch = (getOverflowResearchTimes100() * calculateResearchModifier(eCurrentTech)) / 100;
- setOverflowResearch(0);
- if(GET_TEAM(getTeam()).GetTeamTechs())
- {
- int iBeakersTowardsTechTimes100 = GetScienceTimes100() + iOverflowResearch;
- GET_TEAM(getTeam()).GetTeamTechs()->ChangeResearchProgressTimes100(eCurrentTech, iBeakersTowardsTechTimes100, GetID());
- UpdateResearchAgreements(GetScienceTimes100() / 100);
- }
- }
- if(bForceResearchChoice)
- {
- clearResearchQueue();
- }
- }
- GetPlayerTechs()->CheckForTechAchievement();
- }
复制代码 首先,如果当前没有研究科技,会让选一个。该部分略。
如果当前玩家没有正在研究的科技(这是可能的),那么将当前回合瓶直接加到溢出当中
如果有科技正在研究,那么将溢出和回合瓶注入到该科技当中
研发进度增量=回合瓶+溢出*研发补正
溢出,一般是科技完成时产生的,不属于任何科技,处于溢出状态的瓶子。研发补正是当前所选择研究科技的研发补正。
也就是说,溢出的瓶子最终变成多少,是由下一个要研究的科技决定的。如果你将溢出的瓶子指向一个没有补正的科技,那么也就不会发生任何变化,1+1=2。如果你将溢出的瓶子指向一个贬值的科技,那么溢出的瓶子就乘以该科技的研发补正。
前面科技剩余回合数的计算,就考虑到了溢出流入科技时的补正,因而每个科技所显示的剩余回合数都是按其对应补正计算后的数值,是更为准确的数值。尽管这样的回合数可能看起来会有些奇怪。
瓶子流入科技,科技累计的瓶子最终超过了科技成本,即研发完成,那又发生了什么呢,看接下来的部分。
3.2研究进度的改变和研究完成
CvTechClasses.cpp
Line:1934- /// Accessor: set research done on one tech (in hundredths)
- void CvTeamTechs::SetResearchProgressTimes100(TechTypes eIndex, int iNewValue, PlayerTypes ePlayer)
- {
- CvAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
- CvAssertMsg(eIndex < GC.getNumTechInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
- CvAssertMsg(ePlayer >= 0, "eIndex is expected to be non-negative (invalid Index)");
- CvAssertMsg(ePlayer < MAX_PLAYERS, "ePlayer is expected to be within maximum bounds (invalid Index)");
- if(GetResearchProgressTimes100(eIndex) != iNewValue)
- {
- m_paiResearchProgress[eIndex] = iNewValue;
- CvAssert(GetResearchProgressTimes100(eIndex) >= 0);
- if(m_pTeam->GetID() == GC.getGame().getActiveTeam())
- {
- GC.GetEngineUserInterface()->setDirty(GameData_DIRTY_BIT, true);
- GC.GetEngineUserInterface()->setDirty(Score_DIRTY_BIT, true);
- }
- int iResearchProgress = GetResearchProgressTimes100(eIndex);
- int iResearchCost = GetResearchCost(eIndex) * 100;
- // Player modifiers to cost
- int iResearchMod = std::max(1, GET_PLAYER(ePlayer).calculateResearchModifier(eIndex));
- iResearchCost = (iResearchCost * 100) / iResearchMod;
- int iNumCitiesMod = GC.getMap().getWorldInfo().GetNumCitiesTechCostMod(); // Default is 40, gets smaller on larger maps
- iNumCitiesMod = iNumCitiesMod * GET_PLAYER(ePlayer).GetMaxEffectiveCities(/*bIncludePuppets*/ true);
- iResearchCost = iResearchCost * (100 + iNumCitiesMod) / 100;
-
- int iOverflow = iResearchProgress - iResearchCost;
- // April 2014 Balance Patch change - EFB
- // Don't allow the overflow to get out of hand
- int iMaxOverflow = GetMaxResearchOverflow(eIndex, ePlayer);
- if (iOverflow > iMaxOverflow)
- {
- iOverflow = iMaxOverflow;
- }
- if(iOverflow >= 0)
- {
- GET_PLAYER(ePlayer).changeOverflowResearchTimes100(iOverflow);
- m_pTeam->setHasTech(eIndex, true, ePlayer, true, true);
- SetNoTradeTech(eIndex, true);
- // Mark city specialization dirty
- GET_PLAYER(ePlayer).GetCitySpecializationAI()->SetSpecializationsDirty(SPECIALIZATION_UPDATE_RESEARCH_COMPLETE);
- // Culture bonus for Player researching a Tech
- PlayerTypes eLoopPlayer;
- int iCulture;
- TeamTypes eTeamID = m_pTeam->GetID();
- for(int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
- {
- eLoopPlayer = (PlayerTypes) iPlayerLoop;
- CvPlayerAI& kLoopPlayer = GET_PLAYER(eLoopPlayer);
- if(kLoopPlayer.getTeam() == eTeamID)
- {
- iCulture = kLoopPlayer.GetCulturePerTechResearched();
- if(iCulture != 0)
- {
- kLoopPlayer.changeJONSCulture(iCulture);
- }
- }
- }
- }
- }
- }
复制代码 溢出=研究进度-科技成本,超出的部分就是溢出了。
此时,如果溢出超限,则溢出=溢出上限。
溢出上限
Line:2114- int CvTeamTechs::GetMaxResearchOverflow(TechTypes eTech, PlayerTypes ePlayer) const
- {
- CvPlayer &kPlayer = GET_PLAYER(ePlayer);
- // 5 turns of science is a reasonable allowance of overflow (about equal to a standard research agreement award)
- int iReturnValue = kPlayer.GetScienceTimes100() * 5;
- // Alternatively let it be the raw cost of the tech (times 100)
- CvTechEntry* pkTechInfo = GC.getTechInfo(eTech);
- if(pkTechInfo == NULL)
- {
- return 0;
- }
- int iCost = pkTechInfo->GetResearchCost() * 100;
- iReturnValue = max(iCost, iReturnValue);
- return iReturnValue;
- }
复制代码 溢出是否超限的判定只发生在此刻也就是研究完成时。上限值为此时回合瓶*5与科技在xml中定义的原始成本两者中的较大值。
判断完溢出上限,将此时不超过该上限的瓶子累加进原有的溢出当中。
也就是说,你可以获得超过溢出上限的溢出,但不能通过仅一次完成科技获得。可以多次完成科技积累溢出,但如前所述,这一过程不能过回合。因为过回合时溢出会进入研究进度中。
在一个回合内完成多个科技可以累加溢出超过上限,但在接下来过回合时同样无法超出下一次的上限。 |
|