From b488e3d7839f96e66e656dc4e57908dfad313dc4 Mon Sep 17 00:00:00 2001 From: ilteroi Date: Wed, 19 Jun 2024 21:39:22 +0200 Subject: [PATCH] fix citadel logic in tactsim fix city state resurrection logic --- CvGameCoreDLL_Expansion2/CvAStar.cpp | 6 ++-- CvGameCoreDLL_Expansion2/CvGame.cpp | 2 +- CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp | 9 ++++++ CvGameCoreDLL_Expansion2/CvPlayerAI.cpp | 6 ++-- CvGameCoreDLL_Expansion2/CvTacticalAI.cpp | 37 +++++++++++++++-------- 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/CvGameCoreDLL_Expansion2/CvAStar.cpp b/CvGameCoreDLL_Expansion2/CvAStar.cpp index a8ef617835..f85a4962a0 100644 --- a/CvGameCoreDLL_Expansion2/CvAStar.cpp +++ b/CvGameCoreDLL_Expansion2/CvAStar.cpp @@ -418,24 +418,23 @@ bool CvAStar::FindPathWithCurrentConfiguration(int iXstart, int iYstart, int iXd saiRuntimeHistogram[iBin]++; CvUnit* pUnit = m_sData.iUnitID > 0 ? GET_PLAYER(m_sData.ePlayer).getUnit(m_sData.iUnitID) : NULL; +#if defined(VPDEBUG) if ( timer.GetDeltaInSeconds()>0.2 && data.ePath==PT_UNIT_MOVEMENT ) { //debug hook int iStartIndex = GC.getMap().plotNum(m_iXstart, m_iYstart); -#if defined(VPDEBUG) if (iStartIndex==giLastStartIndex && iStartIndex>0) { OutputDebugString("Repeated pathfinding start\n"); gStackWalker.ShowCallstack(5); } -#endif giLastStartIndex = iStartIndex; int iNumPlots = GC.getMap().numPlots(); //in some cases we have no destination plot, so exhaustion is not always a "fail" CvString msg = CvString::format("Run %d: Path type %d %s (%s from %d,%d to %d,%d - flags %d), tested %d, processed %d nodes in %d rounds (%d%% of map) in %.2f ms\n", - m_iCurrentGenerationID, m_sData.ePath, bSuccess ? "found" : "not found", pUnit ? pUnit->getName().c_str() : "unknown", + m_iCurrentGenerationID, m_sData.ePath, bSuccess||!HasValidDestination() ? "found" : "not found", pUnit ? pUnit->getName().c_str() : "unknown", m_iXstart, m_iYstart, m_iXdest, m_iYdest, m_sData.iFlags, m_iTestedNodes, m_iProcessedNodes, m_iRounds, (100 * m_iProcessedNodes) / iNumPlots, timer.GetDeltaInSeconds() * 1000); OutputDebugString( msg.c_str() ); @@ -448,6 +447,7 @@ bool CvAStar::FindPathWithCurrentConfiguration(int iXstart, int iYstart, int iXd //gStackWalker.SetLog(NULL); #endif } +#endif if (g_bPathFinderLogging) { diff --git a/CvGameCoreDLL_Expansion2/CvGame.cpp b/CvGameCoreDLL_Expansion2/CvGame.cpp index f3f27e35bb..3a9c0cf347 100644 --- a/CvGameCoreDLL_Expansion2/CvGame.cpp +++ b/CvGameCoreDLL_Expansion2/CvGame.cpp @@ -1577,7 +1577,7 @@ void CvGame::update() doTurn(); } - if(!isPaused()) // Check for paused again, the doTurn call might have called something that paused the game and we don't want an update to sneak through + if(!isPaused() && !bExternalPause) // Check for paused again, the doTurn call might have called something that paused the game and we don't want an update to sneak through { updateScore(); diff --git a/CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp b/CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp index 57a08e4539..67c4bfe729 100644 --- a/CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp @@ -4877,11 +4877,19 @@ void CvMinorCivAI::DoChangeAliveStatus(bool bAlive) for(int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++) { PlayerTypes ePlayer = (PlayerTypes) iPlayerLoop; + if (!GET_PLAYER(ePlayer).isAlive()) + continue; bool bFriends = false; bool bAllies = false; if (IsFriendshipAboveFriendsThreshold(ePlayer, GetEffectiveFriendshipWithMajor(ePlayer))) { + //make sure we are consistent + if (bAlive && !IsFriends(ePlayer)) + { + CUSTOMLOG("inconsistent friendship state after resurrection!"); + SetFriends(ePlayer, true); + } bFriends = true; } if(GetAlly() == ePlayer) @@ -4891,6 +4899,7 @@ void CvMinorCivAI::DoChangeAliveStatus(bool bAlive) } if(bFriends || bAllies) { + GET_PLAYER(ePlayer).GetDiplomacyAI()->LogMinorStatusChange(m_pPlayer->GetID(), bAlive ? "restore bonus yields after resurrection" : "remove bonus yields after elimination"); DoSetBonus(ePlayer, bAlive, bFriends, bAllies); } } diff --git a/CvGameCoreDLL_Expansion2/CvPlayerAI.cpp b/CvGameCoreDLL_Expansion2/CvPlayerAI.cpp index 1670ae1e07..8bf57fd953 100644 --- a/CvGameCoreDLL_Expansion2/CvPlayerAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvPlayerAI.cpp @@ -3104,7 +3104,7 @@ std::priority_queue CvPlayerAI::GetBestCultureBombPlots(BuildTyp const vector& CvPlayerAI::GetTopCitadelPlotsCached() { - const int MAX_CANDIDATES = 13; + const int MAX_CANDIDATES = 5; if (m_iCurrentCitadelTargetsTurn == GC.getGame().getGameTurn()) return m_vCurrentCitadelTargets; @@ -3120,8 +3120,8 @@ const vector& CvPlayerAI::GetTopCitadelPlotsCached() m_vCurrentCitadelTargets.push_back(candidate.pPlot); goodPlots.pop(); - //give up if the rest is much worse than what we have - if (goodPlots.top().score < candidate.score / 2) + //give up if the rest is much worse than what we just had + if (goodPlots.top().score < candidate.score * 0.7f) break; } diff --git a/CvGameCoreDLL_Expansion2/CvTacticalAI.cpp b/CvGameCoreDLL_Expansion2/CvTacticalAI.cpp index 543040559f..6817ef8e5b 100644 --- a/CvGameCoreDLL_Expansion2/CvTacticalAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvTacticalAI.cpp @@ -8064,12 +8064,6 @@ STacticalAssignment ScorePlotForNonFightingUnitMove(const SUnitStats& unit, cons return result; } } - else if (testPlot.isNicePlotForCitadel() && pUnit->IsGreatGeneral() && movePlot.iMovesLeft > 0) - { - result.eAssignmentType = A_USE_POWER; - result.iRemainingMoves = 0; - iScore += 100; - } else if (!pTestPlot->isFriendlyCity(*pUnit)) //cities are considered safe return result; @@ -8086,6 +8080,10 @@ STacticalAssignment ScorePlotForNonFightingUnitMove(const SUnitStats& unit, cons iScore -= 3; } + //place to be! + if (testPlot.isNicePlotForCitadel() && pUnit->IsGreatGeneral()) + iScore += 23; + //points for supported units (count only the first ring for performance ...) int iFriends = testPlot.getNumAdjacentFriendlies(CvTacticalPlot::TD_BOTH, -1); if (testPlot.hasFriendlyCombatUnit()) @@ -8788,10 +8786,23 @@ void CvTacticalPosition::getPreferredAssignmentsForUnit(const SUnitStats& unit, } else if (unit.iPlotIndex == it->iPlotIndex) { - STacticalAssignment newAssignment = ScorePlotForPillageMove(unit, testPlot, *it, *this); - //pillaging must have a positive score - if (newAssignment.iScore > 0 && (newAssignment.iRemainingMoves>0 || couldEndTurnAfterThisAssignment(newAssignment))) + STacticalAssignment newAssignment(unit.iPlotIndex, unit.iPlotIndex, unit.iUnitID, it->iMovesLeft,unit.eMoveStrategy,0,A_BLOCKED); + + //maybe we can do something special here? + if (testPlot.isNicePlotForCitadel() && pUnit->IsGreatGeneral()) + { + newAssignment.eAssignmentType = A_USE_POWER; + newAssignment.iScore = 1000; + } + else + newAssignment = ScorePlotForPillageMove(unit, testPlot, *it, *this); + + //special action must have a positive score + if (newAssignment.iScore > 0 && (newAssignment.iRemainingMoves > 0 || couldEndTurnAfterThisAssignment(newAssignment))) + { gPossibleMoves.push_back(newAssignment); + } + //stay in plot but do nothing special else if (refAssignment.iScore > TACTICAL_COMBAT_IMPOSSIBLE_SCORE) { int iBonus = 0; @@ -10366,7 +10377,7 @@ bool CvTacticalPosition::addTacticalPlot(const CvPlot* pPlot, const vectorcanMove() || !pUnit->canEndTurnAtPlot(pUnit->plot())) + if (!pUnit || !pUnit->canMove()) return false; eUnitMovementStrategy eStrategy = MS_NONE; @@ -10780,6 +10791,8 @@ vector TacticalAIHelpers::FindBestUnitAssignments( for(vector::iterator it=ourUnits.begin(); it!=ourUnits.end(); ++it) { CvUnit* pUnit = *it; + //if the add fails we might have marked a tactical plot as available but now suddenly it's occupied by a non-sim unit + //but should not happen with the pre-checks above and it's not a big problem anyway if (initialPosition->addAvailableUnit(pUnit)) { //make sure we know the immediate surroundings of every unit @@ -10981,7 +10994,7 @@ bool TacticalAIHelpers::ExecuteUnitAssignments(PlayerTypes ePlayer, const std::v //see if we can indeed reach the target plot this turn ... pUnit->ClearPathCache(); if (!pUnit->GeneratePath(pToPlot, iMoveflags) || pUnit->GetPathEndFirstTurnPlot() != pToPlot) - OutputDebugString("ouch, pathfinding problem\n"); + CUSTOMLOG("ouch, pathfinding problem for u%d at (%d:%d)\n", pUnit->GetID(), pToPlot->getX(), pToPlot->getY()); } #endif if (bPrecondition) @@ -10991,7 +11004,7 @@ bool TacticalAIHelpers::ExecuteUnitAssignments(PlayerTypes ePlayer, const std::v #ifdef TACTDEBUG //check this only for moves, eg melee kills can fail this check because the pathfinder assumes attacks end the turn! if (vAssignments[i].iRemainingMoves != pUnit->getMoves() && bPostcondition) - OutputDebugString("ouch, inconsistent movement points\n"); + CUSTOMLOG("ouch, inconsistent movement points for u%d at (%d:%d)\n", pUnit->GetID(), pToPlot->getX(), pToPlot->getY()); #endif break; case A_MOVE_SWAP: