设为首页收藏本站

塞爱维(CIV)文明联盟

 找回密码
 注册
查看: 33104|回复: 20

[原创] 【攻略】关于战犯的判定

[复制链接]
发表于 2013-10-19 09:57:40 | 显示全部楼层 |阅读模式
很多人都不是很明白战犯的判定方法, 在这里做了一个汇总分析。
对代码不感兴趣,只看这一部分总结就可以了。

1、每个ai都单独计算和存储玩家的战犯点。
2、除了光复自己的城市,占领城市都有战犯点惩罚,占领小势力的城市(包括城邦)获得较多战犯点。占领城市战犯点算法参考2#楼引用的翻译。
但占领城市对未碰到的AI无影响(未碰面的ai不增加玩家战犯点),共同作战的AI增加的战犯点减半。
现在增加了占领城市战犯点增减的提示,处于宣战状态在城市等级条有提示,选择占领、解放或傀儡时也有提示。
3、宣战获得战犯点减半至250,主动宣战会增加所有AI战犯点的计算(不管遇到没遇到)。但是已经对该玩家宣战的AI不受影响。
4、征服城邦或ai获得战犯点(1000)已经取消,现在只计算占领城市的战犯点。
5、解放ai或城邦减少相应的战犯点,算法与占领城市获得战犯点相同。另外正常情况下,战犯点每回合消退5。
6、战犯四个等级的阈值分别是200、100、50、20(这是3.142补丁的数据,已经降低了后三个等级的门槛),这是根据战犯指数判断的。
战犯指数=战犯点*AI战犯厌恶度/100。
7、有AI或城邦被征服后,增加最高两个战犯等级的另一种判定,只有玩家征服了25%(判定为2级战犯),40%(判定为一级战犯)左右城邦和AI(按玩家数量计算),才可能生效。
这个设定是针对小地图的平衡。

[ 本帖最后由 everchu 于 2013-10-20 16:52 编辑 ]

评分

1

查看全部评分

 楼主| 发表于 2013-10-19 09:58:04 | 显示全部楼层
二楼详解:
占领城市获得战犯点的算法翻译自CFC论坛,时间有点远,翻了一下代码发现这个有点问题,但可以作为参考,计算出来的值要乘以100。
好战状态现在是根据每城计算的(宣战仍然有影响),征服文明对这个数值没有影响,不灭国的做法已经无法躲避惩罚。
对文明或城邦宣战的好战惩罚减半至2.5,征服惩罚取消。
如果夺回自己的城市,不会有好战惩罚。解放城市也能减少对所有文明的好战惩罚。
这是个很好的买卖!
每个城的好战惩罚计算:
不同地图下,城市数量分值= 13 (擂台), 26 (极小), 39 (小), 52 (标准), 80 (大), 132 (极大)
城市总数= max(当前游戏内总城市数量, 1)
原主人城市数量= max(原主人城市数量, 1)
好战分值改变量= (10 * 城市数量分值) / (城市总数*原主人城市数量)
因此,如果我打下了俄国一个城市,并且俄国拥有20个城市,标准地图, 那么我获得的好战惩罚= (10 × 52) / (48 × 20) = 0.54 。而原来宣战惩罚为+5(征服为+10)。
解放城市算法相同,相反地减少惩罚。
一些结论:
•        打下城市的好战惩罚,小文明比大文明多。
•        解放城市减少的惩罚,小文明比大文明多。
•        宣战惩罚较小。


以下代码来自:Sid Meier's Civilization V\Assets\DLC\Expansion2\Gameplay\XML\AI\GlobalDiplomacyAIDefines.xml
  1. <!--Warmonger Threat of a Player-->
  2. -<Row Name="WARMONGER_THREAT_CRITICAL_THRESHOLD"> <Value>200</Value> </Row>
  3. -<Row Name="WARMONGER_THREAT_SEVERE_THRESHOLD"> <Value>100</Value> </Row>
  4. -<Row Name="WARMONGER_THREAT_MAJOR_THRESHOLD"> <Value>50</Value> </Row>
  5. -<Row  Name="WARMONGER_THREAT_MINOR_THRESHOLD"> <Value>20</Value> </Row>
复制代码
以上是战犯等级的临界值定义:小20,中50,严重100,极其严重200(秋季补丁之前分别是是50,100,150,200,现在降低了门槛),对应的判定值暂称之为战犯指数。
  1. -<Row Name="WARMONGER_THREAT_MINOR_ATTACKED_WEIGHT"> <Value>250</Value> </Row>
  2. -<Row Name="WARMONGER_THREAT_MINOR_CONQUERED_WEIGHT"> <Value>1000</Value> </Row>
  3. -<Row Name="WARMONGER_THREAT_MAJOR_ATTACKED_WEIGHT"><Value>250</Value> </Row>
  4. -<Row Name="WARMONGER_THREAT_MAJOR_CONQUERED_WEIGHT"> <Value>1000</Value> </Row>
复制代码
以上分别是宣战或征服城邦或ai的获得的战犯点,宣战250,征服1000,两者相同。从最新的dLL代码看,征服增加1000点的代码被备注掉了,就是征服只有占城的惩罚,没有额外1000点惩罚了。
占领城市获得的战犯点的计算方法参考前面的翻译。
战犯指数=战犯点*AI战犯厌恶度/100。
AI的性格参考S大的帖子 [完工][扒光AI的小内内][XML&DLL]BNW AI性格倾向全解析

以下是秋季补丁增加的信息提示,在战犯判定方面更体贴了。
Warmonger UI improvements:
Now there are 4 different levels of concern displayed by the AI about the player's warmongering.
战狂信息界面:AI对玩家的战狂态度将细分为4个等级(外交界面可以看到)
Added a tooltip to the city banner for each city owned by a civ you are at war with that shows the warmonger penalty and/or liberation bonus.
处于交战状态下的话,敌对文明的城市等级条处将显示占领/解放该城市带来多少战狂指数变化的提示
Added a tooltip for warmonger penalty and/or liberation bonus to the Annex/Liberate/Puppet popup.
选择吞并/解放/傀儡城市的界面将新增战狂指数变化的提示
  1. -<Row Name="WARMONGER_THREAT_PER_TURN_DECAY"> <Value>-5</Value> </Row>
复制代码
战犯点每回合消退5,宣战一次需要50回合消退时间。
  1. -<Row Name="WARMONGER_THREAT_PERSONALITY_MOD"> <Value>10</Value> </Row>
  2. -<Row Name="WARMONGER_THREAT_CRITICAL_PERCENT_THRESHOLD"> <Value>40</Value> </Row>
  3. -<Row Name="WARMONGER_THREAT_SEVERE_PERCENT_THRESHOLD"> <Value>25</Value> </Row>
复制代码
以上定义的值只有在有文明或城邦被征服后用到,见三楼代码的红色部分。
增加了严重和极其严重的战犯等级的另一种判定,在ai或城邦被征服较多的情况下,可能生效。

[ 本帖最后由 everchu 于 2013-10-19 14:38 编辑 ]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-19 09:58:40 | 显示全部楼层
代码楼,相关DLL代码分析。

CvDiplomacyAI.cpp
战犯等级的判定:
void CvDiplomacyAI::DoUpdateWarmongerThreats()
{
        ThreatTypes eThreatType;

        int iThreatValue;

        int iNumPlayersKilled;
        int iNumPlayersEver = GC.getGame().countCivPlayersEverAlive();
        int iPlayersKilledPercent;
        int iWarmongerMod;

        PlayerTypes eLoopPlayer;
        for(int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
        {
                eLoopPlayer = (PlayerTypes) iPlayerLoop;

                if(IsPlayerValid(eLoopPlayer))
                {
                        eThreatType = THREAT_NONE;
                        iThreatValue = GetOtherPlayerWarmongerScore(eLoopPlayer);

                        // Now do the final assessment
                        if(iThreatValue >= /*200*/ GC.getWARMONGER_THREAT_CRITICAL_THRESHOLD())
                                eThreatType = THREAT_CRITICAL;
                        else if(iThreatValue >= /*100*/ GC.getWARMONGER_THREAT_SEVERE_THRESHOLD())
                                eThreatType = THREAT_SEVERE;
                        else if(iThreatValue >= /*50*/ GC.getWARMONGER_THREAT_MAJOR_THRESHOLD())
                                eThreatType = THREAT_MAJOR;
                        else if(iThreatValue >= /*20*/ GC.getWARMONGER_THREAT_MINOR_THRESHOLD())
                                eThreatType = THREAT_MINOR;

                        // Also test % of players killed (in case we're on a map with very few players or something)
                        iNumPlayersKilled = GetOtherPlayerNumMinorsConquered(eLoopPlayer) + GetOtherPlayerNumMajorsConquered(eLoopPlayer);
                        if(iNumPlayersKilled > 0)
                        {
                                iPlayersKilledPercent = iNumPlayersKilled * 100 / iNumPlayersEver;

                                iWarmongerMod = GetWarmongerHate() - /*5*/ GC.getDEFAULT_FLAVOR_VALUE();        // Calculate difference from default
                                iWarmongerMod *= /*10*/ GC.getWARMONGER_THREAT_PERSONALITY_MOD();        // This will range from -50 to 50 (%)
                                iPlayersKilledPercent += (iPlayersKilledPercent * iWarmongerMod / 100);

                                if(iPlayersKilledPercent >= /*40*/ GC.getWARMONGER_THREAT_CRITICAL_PERCENT_THRESHOLD())
                                        eThreatType = THREAT_CRITICAL;
                                if(iPlayersKilledPercent >= /*25*/ GC.getWARMONGER_THREAT_SEVERE_PERCENT_THRESHOLD())
                                        eThreatType = THREAT_SEVERE;
                        }


                        // Set the Threat
                        SetWarmongerThreat(eLoopPlayer, eThreatType);

                        // decay score
                        ChangeOtherPlayerWarmongerAmount(eLoopPlayer, /*-5*/GC.getWARMONGER_THREAT_PER_TURN_DECAY());
                }
        }
}

战犯指数的计算
int CvDiplomacyAI::GetOtherPlayerWarmongerScore(PlayerTypes ePlayer)
{
        int iReturnValue = GetOtherPlayerWarmongerAmount(ePlayer);
        iReturnValue *= GetWarmongerHate();
        iReturnValue /= 100;
        return iReturnValue;
}

对城邦宣战直接增加250战犯点
/// Changes how many Minors have we seen this Player attack
void CvDiplomacyAI::ChangeOtherPlayerNumMinorsAttacked(PlayerTypes ePlayer, int iChange)
{
        SetOtherPlayerNumMinorsAttacked(ePlayer, GetOtherPlayerNumMinorsAttacked(ePlayer) + iChange);
        ChangeOtherPlayerWarmongerAmount(ePlayer, iChange * /*250 */ GC.getWARMONGER_THREAT_MINOR_ATTACKED_WEIGHT());
}

征服的1000点被备注掉了
/// Changes how many Minors have we seen this Player conquer
void CvDiplomacyAI::ChangeOtherPlayerNumMinorsConquered(PlayerTypes ePlayer, int iChange)
{
        SetOtherPlayerNumMinorsConquered(ePlayer, GetOtherPlayerNumMinorsConquered(ePlayer) + iChange);
        //ChangeOtherPlayerWarmongerAmount(ePlayer, iChange * /*1000*/ GC.getWARMONGER_THREAT_MINOR_CONQUERED_WEIGHT());
}

对AI宣战,如果其他AI也在对该AI作战,不会增加250战犯点
/// Changes how many Majors have we seen this Player attack
void CvDiplomacyAI::ChangeOtherPlayerNumMajorsAttacked(PlayerTypes ePlayer, int iChange, TeamTypes eAttackedTeam)
{
        if(iChange > 0)
        {
                PlayerTypes eAttackedPlayer;
                for(int iAttackedPlayerLoop = 0; iAttackedPlayerLoop < MAX_MAJOR_CIVS; iAttackedPlayerLoop++)
                {
                        eAttackedPlayer = (PlayerTypes) iAttackedPlayerLoop;

                        // Player must be on this team
                        if(GET_PLAYER(eAttackedPlayer).getTeam() != eAttackedTeam)
                                continue;

                        // Don't ACTUALLY count this if we're at war with the guy also
                        if(IsAtWar(eAttackedPlayer))
                                return;
                }
        }

        SetOtherPlayerNumMajorsAttacked(ePlayer, GetOtherPlayerNumMajorsAttacked(ePlayer) + iChange);
        ChangeOtherPlayerWarmongerAmount(ePlayer, iChange * /*250 */ GC.getWARMONGER_THREAT_MAJOR_ATTACKED_WEIGHT());
}


征服ai的1000点惩罚也备注掉了
/// Changes how many Majors have we seen this Player conquer
void CvDiplomacyAI::ChangeOtherPlayerNumMajorsConquered(PlayerTypes ePlayer, int iChange)
{
        SetOtherPlayerNumMajorsConquered(ePlayer, GetOtherPlayerNumMajorsConquered(ePlayer) + iChange);
        //ChangeOtherPlayerWarmongerAmount(ePlayer, iChange * /*1000 */ GC.getWARMONGER_THREAT_MAJOR_CONQUERED_WEIGHT());
}

占领城市只对遇到的AI有影响,对共同作战的AI减半
void CvDiplomacyAIHelpers::ApplyWarmongerPenalties(PlayerTypes eConqueror, PlayerTypes eConquered)
{
        CvPlayer &kConqueringPlayer = GET_PLAYER(eConqueror);

        for(int iMajorLoop = 0; iMajorLoop < MAX_MAJOR_CIVS; iMajorLoop++)
        {
                PlayerTypes eMajor = (PlayerTypes)iMajorLoop;
                if (eConqueror != eMajor && GET_PLAYER(eMajor).isAlive())
                {
                        // Have I met the player who conquered the city?
                        CvTeam &kAffectedTeam = GET_TEAM(GET_PLAYER(eMajor).getTeam());
                        if (kAffectedTeam.isHasMet(kConqueringPlayer.getTeam()))
                        {
                                int iNumCities = max(GET_PLAYER(eConquered).getNumCities(), 1);
                                int iWarmongerOffset = CvDiplomacyAIHelpers::GetWarmongerOffset(iNumCities);

                                // Half penalty if I'm also at war with conquered civ
                                if (kAffectedTeam.isAtWar(GET_PLAYER(eConquered).getTeam()))
                                {
                                        iWarmongerOffset /= 2;
                                }

                                GET_PLAYER(eMajor).GetDiplomacyAI()->ChangeOtherPlayerWarmongerAmount(eConqueror, iWarmongerOffset);
                        }
                }
        }
}

占领城市战犯点的算法:
(1000 * 城市数量分值) / (max(地图城市总数,1)*max(原主人剩余城市数量,1))
Cfc上给出的算法是正确的,只是要乘以100
int CvDiplomacyAIHelpers::GetWarmongerOffset(int iNumCitiesRemaining)
{
        int iEstimatedCitiesOnMap = GC.getMap().getWorldInfo().GetEstimatedNumCities();
        int iActualCitiesOnMap = GC.getGame().getNumCities();
        int iWarmongerOffset = (1000 * iEstimatedCitiesOnMap) / (max(iActualCitiesOnMap, 1) * iNumCitiesRemaining);

        return iWarmongerOffset;
}
转5#楼》》

[ 本帖最后由 everchu 于 2013-10-20 16:55 编辑 ]
回复 支持 反对

使用道具 举报

发表于 2013-10-19 10:15:11 | 显示全部楼层
谢谢了,对这个问题还是挺感兴趣的

5、有AI或城邦被征服后,增加最高两个战犯等级的另一种判定,在AI或城邦剩存较少时,外交可能就没法搞啦。

关于这点没有看懂,能详细解释一下么
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-19 10:24:02 | 显示全部楼层
主要的判定是这两句,中间计算太复杂,不用管。
if(iPlayersKilledPercent >= /*40*/ GC.getWARMONGER_THREAT_CRITICAL_PERCENT_THRESHOLD())
                                        eThreatType = THREAT_CRITICAL;
                                if(iPlayersKilledPercent >= /*25*/ GC.getWARMONGER_THREAT_SEVERE_PERCENT_THRESHOLD())
                                        eThreatType = THREAT_SEVERE;
大概的意思是说,如果玩家征服AI或城邦超过40%,战犯判定直接极其严重,超过25%,判定为严重。
这个百分数是经过一串计算的,不是直接值。
==================================分割线===============================================
上接3#楼,CvPlayer.cpp:
解放城市减少相应的战犯点,战犯点算法与占领城市相同,红字部分
/// This player liberates iOldCityID and gives it back to ePlayer
void CvPlayer::DoLiberatePlayer(PlayerTypes ePlayer, int iOldCityID)
{
        CvCity* pCity = getCity(iOldCityID);
        CvAssert(pCity);
        if (!pCity)
                return;

        PlayerTypes eOldOwner = pCity->getOwner();
        CvPlot* pPlot = pCity->plot();

        // Set that this team has been liberated
        TeamTypes eTeam = getTeam();
        TeamTypes eLiberatedTeam = GET_PLAYER(ePlayer).getTeam();

        // Who originally took out this team?
        TeamTypes eConquerorTeam = GET_TEAM(eLiberatedTeam).GetKilledByTeam();

        if (!GET_PLAYER(ePlayer).isAlive())
        {
                GET_PLAYER(ePlayer).setBeingResurrected(true);
                GET_TEAM(eLiberatedTeam).SetLiberatedByTeam(eTeam);

                // Put everyone at peace with this guy
                for(int iOtherTeamLoop = 0; iOtherTeamLoop < MAX_CIV_TEAMS; iOtherTeamLoop++)
                {
                        if(eLiberatedTeam != iOtherTeamLoop)
                        {
                                GET_TEAM(eLiberatedTeam).makePeace((TeamTypes) iOtherTeamLoop, /*bBumpUnits*/false, /*bSuppressNotification*/true);
                        }
                }
       
                if (!GET_PLAYER(ePlayer).isMinorCiv())
                {
                        // add notification
                        Localization::String strMessage = Localization::Lookup("TXT_KEY_NOTIFICATION_CIV_RESURRECTED");
                        strMessage << getCivilizationShortDescriptionKey(); // LIBERATING CIV NAME
                        strMessage << pCity->getNameKey(); // CITY NAME
                        strMessage << GET_PLAYER(ePlayer).getCivilizationAdjectiveKey(); // LIBERATED CIV NAME
                        strMessage << GET_PLAYER(ePlayer).getCivilizationDescriptionKey();// LIBERATED CIV NAME
                        Localization::String strSummary = Localization::Lookup("TXT_KEY_NOTIFICATION_CIV_RESURRECTED_SHORT");
                        if(GC.getGame().isGameMultiPlayer() && GET_PLAYER(ePlayer).isHuman())
                        {
                                strSummary << GET_PLAYER(ePlayer).getNickName();
                        }
                        else
                        {
                                strSummary << GET_PLAYER(ePlayer).getNameKey();
                        }
                        if(GC.getGame().isGameMultiPlayer() && GET_PLAYER(m_eID).isHuman())
                        {
                                strSummary << GET_PLAYER(m_eID).getNickName();
                        }
                        else
                        {
                                strSummary << GET_PLAYER(m_eID).getNameKey();
                        }                       

                        for(int iI = 0; iI < MAX_PLAYERS; iI++)
                        {
                                const PlayerTypes eOtherPlayer = static_cast<PlayerTypes>(iI);
                                CvPlayerAI& kOtherPlayer = GET_PLAYER(eOtherPlayer);
                                if(kOtherPlayer.isAlive() && kOtherPlayer.GetNotifications() && iI != m_eID)
                                {
                                        kOtherPlayer.GetNotifications()->Add(NOTIFICATION_RESURRECTED_MAJOR_CIV, strMessage.toUTF8(), strSummary.toUTF8(), pCity->getX(), pCity->getY(), -1);
                                }
                        }

                        CvString temp = strMessage.toUTF8();
                        GC.getGame().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, m_eID, temp);
                }
        }
        else
        {
                GET_PLAYER(ePlayer).GetDiplomacyAI()->ChangeNumCitiesLiberated(m_eID, 1);

                if (!GET_PLAYER(ePlayer).isMinorCiv())
                {
                        // add notification
                        Localization::String strMessage = Localization::Lookup("TXT_KEY_NOTIFICATION_CITY_LIBERATED");
                        if(GC.getGame().isGameMultiPlayer() && isHuman())
                        {
                                strMessage << getNickName();
                        }
                        else
                        {
                                strMessage << getNameKey();
                        }
                        strMessage << pCity->getNameKey(); // CITY NAME
                        strMessage << GET_PLAYER(ePlayer).getCivilizationShortDescriptionKey();// RESTORED CIV NAME
                        Localization::String strSummary = Localization::Lookup("TXT_KEY_NOTIFICATION_CIV_LIBERATED_SHORT");
                        strSummary << pCity->getNameKey();
                        if(GC.getGame().isGameMultiPlayer() && GET_PLAYER(ePlayer).isHuman())
                        {
                                strSummary << GET_PLAYER(ePlayer).getNickName();
                        }
                        else
                        {
                                strSummary << GET_PLAYER(ePlayer).getNameKey();
                        }

                        for(int iI = 0; iI < MAX_PLAYERS; iI++)
                        {
                                const PlayerTypes eOtherPlayer = static_cast<PlayerTypes>(iI);
                                CvPlayerAI& kOtherPlayer = GET_PLAYER(eOtherPlayer);
                                if(kOtherPlayer.isAlive() && kOtherPlayer.GetNotifications() && iI != m_eID)
                                {
                                        kOtherPlayer.GetNotifications()->Add(NOTIFICATION_LIBERATED_MAJOR_CITY, strMessage.toUTF8(), strSummary.toUTF8(), pCity->getX(), pCity->getY(), -1);
                                }
                        }
                }
        }

        // Give the city back to the liberated player
        GET_PLAYER(ePlayer).acquireCity(pCity, false, true);

        if (!GET_PLAYER(ePlayer).isMinorCiv())
        {
                // slewis - if the player we're liberating the city for is dead, give the liberating player a resurrection mark in the once-defeated player's book
                if (!GET_PLAYER(ePlayer).isAlive())
                {
                        CvDiplomacyAI* pDiploAI = GET_PLAYER(ePlayer).GetDiplomacyAI();
                        PlayerTypes eMePlayer = GetID();
                        pDiploAI->SetResurrectedBy(eMePlayer, true);
                        pDiploAI->SetLandDisputeLevel(eMePlayer, DISPUTE_LEVEL_NONE);
                        pDiploAI->SetWonderDisputeLevel(eMePlayer, DISPUTE_LEVEL_NONE);
                        pDiploAI->SetMinorCivDisputeLevel(eMePlayer, DISPUTE_LEVEL_NONE);
                        pDiploAI->SetWarmongerThreat(eMePlayer, THREAT_NONE);

                        pDiploAI->SetPlayerNoSettleRequestCounter(eMePlayer, -1);
                        pDiploAI->SetPlayerStopSpyingRequestCounter(eMePlayer, -1);
                        pDiploAI->SetDemandCounter(eMePlayer, -1);
                        pDiploAI->ChangeNumTimesCultureBombed(eMePlayer, -pDiploAI->GetNumTimesCultureBombed(eMePlayer));
                        pDiploAI->ChangeNegativeReligiousConversionPoints(eMePlayer, -pDiploAI->GetNegativeReligiousConversionPoints(eMePlayer));
                        pDiploAI->ChangeNegativeArchaeologyPoints(eMePlayer, -pDiploAI->GetNegativeArchaeologyPoints(eMePlayer));

                        pDiploAI->ChangeNumTimesRobbedBy(eMePlayer, -pDiploAI->GetNumTimesRobbedBy(eMePlayer));
                        pDiploAI->SetPlayerBrokenMilitaryPromise(eMePlayer, false);
                        pDiploAI->SetPlayerIgnoredMilitaryPromise(eMePlayer, false);
                        pDiploAI->SetBrokenBorderPromiseValue(eMePlayer, 0);
                        pDiploAI->SetIgnoredBorderPromiseValue(eMePlayer, 0);
                        pDiploAI->SetBrokenExpansionPromiseValue(eMePlayer, 0);
                        pDiploAI->SetIgnoredExpansionPromiseValue(eMePlayer, 0);

                        pDiploAI->SetPlayerBrokenAttackCityStatePromise(eMePlayer, false);
                        pDiploAI->SetPlayerIgnoredAttackCityStatePromise(eMePlayer, false);
                        pDiploAI->SetPlayerBrokenBullyCityStatePromise(eMePlayer, false);
                        pDiploAI->SetPlayerIgnoredBullyCityStatePromise(eMePlayer, false);

                        pDiploAI->SetPlayerBrokenNoConvertPromise(eMePlayer, false);
                        pDiploAI->SetPlayerIgnoredNoConvertPromise(eMePlayer, false);

                        pDiploAI->SetPlayerBrokenNoDiggingPromise(eMePlayer, false);
                        pDiploAI->SetPlayerIgnoredNoDiggingPromise(eMePlayer, false);

                        pDiploAI->SetPlayerBrokenSpyPromise(eMePlayer, false);
                        pDiploAI->SetPlayerIgnoredSpyPromise(eMePlayer, false);

                        pDiploAI->SetPlayerBrokenCoopWarPromise(eMePlayer, false);

                        pDiploAI->SetOtherPlayerNumProtectedMinorsKilled(eMePlayer, 0);
                        pDiploAI->SetOtherPlayerNumProtectedMinorsAttacked(eMePlayer, 0);
                        pDiploAI->SetOtherPlayerNumProtectedMinorsBullied(eMePlayer, 0);
                        pDiploAI->SetOtherPlayerTurnsSinceSidedWithProtectedMinor(eMePlayer, -1);

                        pDiploAI->SetFriendDenouncedUs(eMePlayer, false);
                        pDiploAI->SetDenouncedPlayer(eMePlayer, false); // forget any denouncing
                        GetDiplomacyAI()->SetDenouncedPlayer(ePlayer, false); // forget any denouncing
                        pDiploAI->SetFriendDeclaredWarOnUs(eMePlayer, false);

                        pDiploAI->ChangeNumTimesNuked(eMePlayer, -pDiploAI->GetNumTimesNuked(eMePlayer));
                }
        }

        // Now verify the player is alive
        GET_PLAYER(ePlayer).verifyAlive();
        GET_PLAYER(ePlayer).setBeingResurrected(false);

        // Is this a Minor we have liberated?
        if(GET_PLAYER(ePlayer).isMinorCiv())
        {
                GET_PLAYER(ePlayer).GetMinorCivAI()->DoLiberationByMajor(eOldOwner, eConquerorTeam);
        }

        // slewis
        // negate warmonger
        for(int iMajorLoop = 0; iMajorLoop < MAX_MAJOR_CIVS; iMajorLoop++)
        {
                PlayerTypes eMajor = (PlayerTypes)iMajorLoop;
                if(GetID() != eMajor && GET_PLAYER(eMajor).isAlive())
                {
                        // Have I met the player who conquered the city?
                        if(GET_TEAM(GET_PLAYER(eMajor).getTeam()).isHasMet(getTeam()))
                        {
                                int iNumCities = max(GET_PLAYER(ePlayer).getNumCities(), 1);
                                int iWarmongerOffset = CvDiplomacyAIHelpers::GetWarmongerOffset(iNumCities);
                                GET_PLAYER(eMajor).GetDiplomacyAI()->ChangeOtherPlayerWarmongerAmount(GetID(), -iWarmongerOffset);

                        }
                }
        }

        // Move Units from player that don't belong here
        if(pPlot->getNumUnits() > 0)
        {
                // Get the current list of units because we will possibly be moving them out of the plot's list
                IDInfoVector currentUnits;
                if (pPlot->getUnits(&currentUnits) > 0)
                {
                        for(IDInfoVector::const_iterator itr = currentUnits.begin(); itr != currentUnits.end(); ++itr)
                        {
                                CvUnit* pLoopUnit = (CvUnit*)GetPlayerUnit(*itr);

                                if(pLoopUnit && pLoopUnit->getOwner() == eOldOwner)
                                {
                                        pLoopUnit->finishMoves();
                                        if (!pLoopUnit->jumpToNearestValidPlot())
                                                pLoopUnit->kill(false);
                                }
                        }
                }
        }
}

[ 本帖最后由 everchu 于 2013-10-20 16:54 编辑 ]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-19 10:35:37 | 显示全部楼层

回复 5# 的帖子

有一种说法是在没有碰到ai前宣战,三楼代码可以看到。

[ 本帖最后由 everchu 于 2013-10-19 13:46 编辑 ]
回复 支持 反对

使用道具 举报

发表于 2013-10-19 10:36:57 | 显示全部楼层

回复 4# 的帖子

對於你的問題
數字上不太懂表達出來

但是"外交上沒方法搞" 這點上不太認同
我正在打的一局
早期(古典)我(5城狀態下)推了個城邦也不見外交崩盤
希望有數據達人可以解釋一下機製

經驗所得
1. 鄰居的AI 有高的討厭性 交易可能不全價
  遠點AI有負面影響(不宣友) 但交易還是全價
  已宣友AI 連紅字也沒有 還是全價
2. AI討厭戰犯沒錯 但是好像是討厭"最大的戰犯"
  即是戰犯點最高的那個 那你做了"小"戰犯的話 便請找人做個"大"戰犯
  只要不是大戰犯 沒人遣責 / 宣戰

另外 以上數據是以什麼速度來計算 (標準? 史詩? 馬拉松?)
還是跟速度沒關係?
回复 支持 反对

使用道具 举报

发表于 2013-10-19 10:43:02 | 显示全部楼层

回复 5# 的帖子

這個大概可以理解為

玩家/AI 已經接近觸發"征服勝利"的可能
戰犯指數 -> 高 -> 全世界敵視
然後 全世界因此可能結成"反XX盟約"
用以對抗 某世界公敵
以保持世界的平衡性 以防止過度簡單的逐一擊破吧
-> 要征服 便要跟世界為敵
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-19 10:56:57 | 显示全部楼层

回复 7# 的帖子

这些数据与游戏速度、难度和地图大小无关,难度有ai的态度修正。
这些定义可以在这里找到:
\Sid Meier's Civilization V\Assets\DLC\Expansion2\Gameplay\XML\GameInfo\CIV5GameSpeeds.xml
\Sid Meier's Civilization V\Assets\DLC\Expansion2\Gameplay\XML\GameInfo \CIV5HandicapInfos.xml
\Sid Meier's Civilization V\Assets\DLC\Expansion2\Gameplay\XML\GameInfo\ CIV5Worlds.xml

你不要混淆了ai的态度和战犯判定,ai还有虚伪等其他性格。
战犯判定不一定会在外交界面显示出来,而交易价格反映ai的态度(或亲密度)。
回复 支持 反对

使用道具 举报

发表于 2013-10-19 11:12:17 | 显示全部楼层

回复 5# 的帖子

灭城邦是不是相当于灭1个只有1个城市的文明,另外那个百分比大体来说与土地面积,还是城市数目,哪个方面影响会更大?
回复 支持 反对

使用道具 举报

发表于 2013-10-19 11:14:50 | 显示全部楼层

回复 7# 的帖子

鄰居的AI 有高的討厭性 交易可能不全價
  遠點AI有負面影響(不宣友) 但交易還是全價
  已宣友AI 連紅字也沒有 還是全價

这点我觉得很好理解,远点ai没有边界冲突本身就是一条绿字,而宣友的ai,只不过好感度比较高对方暂时还不愿意和你反脸
回复 支持 反对

使用道具 举报

发表于 2013-10-19 11:24:06 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2013-10-19 11:25:24 | 显示全部楼层
这些判定对世界公敌也同样吗?比如全世界都向某一AI宣战,这种情况应该有修正吧.
回复 支持 反对

使用道具 举报

发表于 2013-10-19 12:52:28 | 显示全部楼层

回复 6# 的帖子

这个应该是存在的,我玩分大陆图多,干过在碰到对手前直接把邻居灭国的事情,所以确实没有战犯惩罚
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-19 13:45:08 | 显示全部楼层
感谢各位的意见
早上偷懒了,没有查战犯点如何增加的代码,补到三楼了,等一会儿改下结论
回复 支持 反对

使用道具 举报

发表于 2013-10-19 13:58:57 | 显示全部楼层
似乎新版本这块有改了已经
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-19 14:30:20 | 显示全部楼层

回复 16# 的帖子

是改了,这是新版本的数据
已经做了编辑,有错误或不明白的再讨论吧
回复 支持 反对

使用道具 举报

发表于 2013-10-19 15:24:55 | 显示全部楼层

回复 17# 的帖子

是不是可以理解为只要没碰到就能随便下城,而宣战想避免的话还是需要先买宣
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-19 15:44:58 | 显示全部楼层

回复 18# 的帖子

从代码看是这样
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-20 16:49:13 | 显示全部楼层
感谢孟大加精,有些地方有点偷懒了。
现在加上了占领城市战犯点算法的代码,还有解放城市的代码,应该很完善了吧
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|塞爱维(CIV)文明联盟    

GMT+8, 2024-3-19 12:43

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表