1. We have added the ability to collapse/expand forum categories and widgets on forum home.
    Dismiss Notice
  2. Photobucket has changed its policy concerning hotlinking images and now requires an account with a $399.00 annual fee to allow hotlink. More information is available at: this link.
    Dismiss Notice
  3. All Civ avatars are brought back and available for selection in the Avatar Gallery! There are 945 avatars total.
    Dismiss Notice
  4. To make the site more secure, we have installed SSL certificates and enabled HTTPS for both the main site and forums.
    Dismiss Notice
  5. Civ6 is released! Order now! (Amazon US | Amazon UK | Amazon CA | Amazon DE | Amazon FR)
    Dismiss Notice
  6. Dismiss Notice
  7. Forum account upgrades are available for ad-free browsing.
    Dismiss Notice

Infinite Loop BTS 1.01

Discussion in 'Civ4 - Better AI' started by rramstad, Oct 9, 2010.

  1. Fuyu

    Fuyu Chieftain

    Joined:
    Nov 5, 2009
    Messages:
    1,220
    Location:
    Austria
    Code:
    bool CyPlayer::isTurnActive()
    {
    	return m_pPlayer ? m_pPlayer->isTurnActive() : false;
    }
    Code:
                [COLOR="Green"]### ### ### civjo: finish "Infinite Loop" - begin ### ### ###[/COLOR]
    
                [COLOR="Green"]### Shift + 0: force all units of all players to end turn[/COLOR]
                if( theKey==int(InputTypes.KB_0) and self.customEM.bShift ):
                    for iPlayer in range(0, game.countCivPlayersEverAlive()):
                        pPlayer = gc.getPlayer(iPlayer)
                        if not pPlayer.isNone() [B]and pPlayer.isTurnActive()[/B]:
                            iNumUnits = pPlayer.getNumUnits()
                            print(   "[COLOR="Gray"]~~~~~~~~~~~~~~~ %s (Player %s) %s units[/COLOR]" %
                                     ( gc.getCivilizationInfo(pPlayer.getCivilizationType()).getDescription(), iPlayer, iNumUnits )   )
    
                            iUnit = 0
                            iCountUnit = 0
                            while iCountUnit < iNumUnits:
                                pUnit = pPlayer.getUnit(iUnit)
                                if not pUnit.isNone():
                                    pUnit.finishMoves()
                                    print(   "[COLOR="Gray"]%s~ [%s,%s] %s %s-%s: finishMoves()[/COLOR]" %
                                             ( iCountUnit, pUnit.getX(), pUnit.getY(), pUnit.getName(), pUnit.getGroupID(), pUnit.getID() )   )
                                    iCountUnit += 1
                                iUnit += 1
                            [B]break[/B]
    
                [COLOR="Green"]### ### ### civjo: finish "Infinite Loop" - end ### ### ###[/COLOR]
    This should actually work.
     
  2. rramstad

    rramstad Chieftain

    Joined:
    Oct 9, 2010
    Messages:
    13
    Fuyu, could this code be merged into Tester.py and a new version uploaded to this thread? I'd be happy to try it out.

    (If not, I'll play around with the original.)

    Thanks everyone, I'm looking forward to reinstalling Civ IV on this system and trying to play through this!
     
  3. Fuyu

    Fuyu Chieftain

    Joined:
    Nov 5, 2009
    Messages:
    1,220
    Location:
    Austria
    You don't need to really merge anything, it's just the bolded parts that need to be added/replaced.
     
  4. Carboniferous

    Carboniferous Chieftain

    Joined:
    Feb 9, 2008
    Messages:
    107
    @Afforess - I have seen something similar with the version of this hack which exists in the original function: CvSelectionGroupAI::AI_update(). This hack checks the function readyToMove() up to 100 times for the group, and if the unit still says it can move, calls finishMoves(). In that case it was triggered by trying to get workers to perform impossible actions - e.g. building improvements they couldn't on their current plot. So, even the original developers didn't come up with a more elegant workaround!

    I agree about the selection group and mission code being a convoluted mess. In the mod I am writing, I discovered that workers and the like wake up each turn and instantly delete their mission and ask for a new one, even they have a bunch of missions queued and there is no immediate threat. (The reason I think is so settlers check for a new mission each turn in case their destination needs to change). It took several hours of debugging to figure that one out.
     
  5. civjo

    civjo Chieftain

    Joined:
    Oct 3, 2010
    Messages:
    67
    @Fuyu
    I changed my mind about C++/Python and agree now with you, this also makes the solution not only compatible with pure BBAI, but also more easily compatible with MODs using BBAI sources ... (therefore I chose Tester.py and not CvEventManager.py too)

    Thank you for providing the function name, isTurnActive. It saved me some time.

    Here the new Tester version (complete documentation ;)):

    ### Alt + [0-5]: force all (remaining) units of Domain # of the currently active player to end turn. # is € of {0...5}

    ### Alt + 8: show all units of the currently active player in PythonDbg.log
    ### Alt + 9: force all (remaining) units of the currently active player to end turn

    ### Shift + [0-2]: force current unit to end turn & increment iUnitIndex to next unit of domain type # (0 naval, 1 air, 2 land)

    ### Shift + 4: decrement iUnitIndex--
    ### Shift + 5: reset iUnitIndex
    ### Shift + 6: increment iUnitIndex++
    ### Shift + 7: increment iUnitIndex by 10

    ### Shift + 8: show current unit
    ### Shift + 9: force current unit to end turn

    BTW, bob2.sav can be reanimated by finishing ANY _ONE_ of the following units:
    Spoiler :
    38~ [40,30] Grenadier (True)24297619-2891814: 0 ----
    76~ [40,30] Grenadier (False)18317536-3358796: 0 g ----
    86~ [40,30] Knight (False)18317536-1843286: 0 g ----
    111~ [40,30] Cannon (False)18317536-4817007: 0 g ----
    179~ [40,30] Musketman (False)18317536-4120755: 0 g ----
    181~ [40,30] Cannon (True)18317536-4784309: 0 G ----
     

    Attached Files:

  6. Afforess

    Afforess The White Wizard

    Joined:
    Jul 31, 2007
    Messages:
    12,239
    Location:
    Austin, Texas
    I spent 8 straight hours of one fine saturday figuring out my solution. ;)
     
  7. Tholal

    Tholal Chieftain

    Joined:
    May 19, 2009
    Messages:
    1,663
    I had added Afforess' code to my mod, but it was never being hit, so I removed it. I did hit the other loop code mentioned by Carboniferous fairly regularly, but at this point, I seem to have the infinite loop issues handled.

    Aside from the grouping and ungrouping cause I mentioned earlier in this thread, another thing that can result in infinite loops is not pushing a MISSION_SKIP mission when you have a unit that isn't doing anything. Making sure that every unit that isn't already in the middle of a mission has some sort of mission every turn (even if it's just a SKIP) will go a long way towards eliminating the infinite loop issue.
     
  8. civjo

    civjo Chieftain

    Joined:
    Oct 3, 2010
    Messages:
    67
    How do units in the state you describe react to a given finishMoves() command? Does it result in a (temporary) 'skip mission', so that this case is already handled? Or is additional action needed?

    is this the status jdog5000 called in his original tester.py "stranded units"?
     
  9. Tholal

    Tholal Chieftain

    Joined:
    May 19, 2009
    Messages:
    1,663
    No idea.

    No. Stranded is a flag used for units that are either on another landmass or otherwise blocked so that they can't reach any of the player's cities. This is tied in with naval movement so that transport ships will try and pick up units flagged as Stranded.

    What I mean by a unit that isn't doing anything, is that sometimes a unit will pass through it's movement function and not meet any of the criteria for finding something useful to do, so they'll just stay where they are doing nothing (city defense units are one common example).

    From what I can tell, every unit needs a mission every turn. Even if that mission is 'do nothing'. Otherwise you'll end up with the infinite loops.
     
  10. civjo

    civjo Chieftain

    Joined:
    Oct 3, 2010
    Messages:
    67
    Do you have a save file with such an unit causing (soon) an infinite loop??
    If it is with your MOD, it can be easily tested for my question with the old tester.py: (shift 0) ... and it still loops further (or not!!) ...
    If it is plain BBAI, I would be more than happy, if you could post it here.

    ---> If anybody has a save file with infinite features:D ... I am interested!

    [edit: post#33 old tester.py: shift0, post#45 new tester.py: alt9]
     
  11. Llewen

    Llewen Chieftain

    Joined:
    Jun 5, 2004
    Messages:
    216
    I've just run into this problem. I'm wondering exactly what I need to do with the "fix". Do I replaced the code in the function with the fix code? Or do I place it before or after the code in the function?

    I've found the cpp file with this function. Do I need to use that to recompile a dll? In which case, which dll do I recompile, and how do I do it? I'm not a complete coding noob, so you can point me in the right direction and I will probably be able to figure it out.
     
  12. _j_

    _j_ Chieftain

    Joined:
    Feb 2, 2012
    Messages:
    9
    @Llewen
    I can't promise you a 100% solution but you'd definitely increase the chances of getting this fixed if you upload your savegame (preferably short before the infinite loop event).
     
  13. Llewen

    Llewen Chieftain

    Joined:
    Jun 5, 2004
    Messages:
    216
    Well the mod I was playing, Fall Further isn't being developed anymore. I've since switched to RiFE which is a mod mod of Fall Further and Fall from Heaven II. As for that specific game, I just went into the world builder mode and deleted groups of countries, then countries, then groups of units, then units, until I found the problem unit. I ended up having to do a similar thing twice more before I got through the game. But even though it took an hour or two each time, it was still better than losing the dozens of hours I had already spent on that particular game entirely. And once I knew what I was looking for, it was a bit easier (in this case it was leaders that were the problem).
     
  14. _j_

    _j_ Chieftain

    Joined:
    Feb 2, 2012
    Messages:
    9
    I suppose, you don't have this savegame anymore ... if you have it still laying around you could go a more convenient way:

    1. Download tester.py from post#45
    2. Look for the Tester.py file in your Better BTS AI Installation, default would be:
    C:\Program Files\Firaxis Games\Sid Meier's Civilization 4\Beyond the Sword\Mods\Better BTS AI\Assets\Python\Development
    3. Make a save copy and then overwrite it with the new downloaded Tester.py version.
    4. Alt + [0-2] gives you the Domain (0 naval, 1 air, 2 land) of the conflicting unit(s) of the country in question, reload savegame
    5. repeatedly Shift + [0-2] gives you a usable unit (look in PythonDbg.log), reload savegame
    6. Shift + 4,5,6,7,9 can be used to just finish _ONE_ single unit

    You'll need to reload the savegame 2 times and about 5 minutes (step 4-6).
     
  15. Llewen

    Llewen Chieftain

    Joined:
    Jun 5, 2004
    Messages:
    216
    Thanks, I'll try to remember that for next time if it happens again. :)
     
  16. _j_

    _j_ Chieftain

    Joined:
    Feb 2, 2012
    Messages:
    9
    "next time if it happens again"
    This is another part of the problem! :D 'It' really happens way too seldom!! ;)

    To be clear: "just finish _ONE_ single unit" means not delete unit, but 'Force _ONE_ single unit to End Turn' btw.
    (in the one 'infinite savegame' I have, ALL usable units have only 0 moving points left anyway :eek:)

    PS
    Even MODs which aren't based on BBAI, ie. don't have the Tester.py file, can solve this kind of 'hanging games' by porting the relevant code fragment eg. into the CvEventManager.
     
  17. IronCrown

    IronCrown Black Foe of the World

    Joined:
    Jun 21, 2007
    Messages:
    668
    I'd just say to random folks looking in here: Don't let yourself be discouraged from installing this mod (as I almost was) out of fear that your games may become broken. I have finished a lot of games already and did not yet run into this problem. Even if it should happen eventually, the vastly improved AI is still worth it.
     
  18. _j_

    _j_ Chieftain

    Joined:
    Feb 2, 2012
    Messages:
    9
    True, BBAI is a tremendous improvement, and I never met the beast myself, too. (Thank you, rramstad for your savegame)

    Just in case the rare event should happen, it is enough to read posts #45 and #54 ...
    Less than a quarter hour later you are surely playing again.
     
  19. isenchine

    isenchine Empress

    Joined:
    Oct 18, 2010
    Messages:
    1,774
    Location:
    Brussels, Belgium
    I've been playing with this today - thanks a lot to civjo for providing this Python tool :goodjob:

    However, it took me awhile to figure out that the key numbers to use should not be the ones from the numeric keypad but those from the main keyboard. Which is a problem when, like me, you're using a French keyboard with all numbers accessible only with the Shift key. In other words, I could not get 'Shift + Shift number' to work etc.

    The workaround is to use Ctrl instead of Shift, but still the combination of Ctrl+Shift+number is a bit difficult, so I changed all numbers to F1, F2, etc.

    Since civjo is using a formula like iDomain = theKey - 2 (to arrive to Domain = 0 = Sea), I had to change it to iDomain = theKey - 59 (Key F1 is 59, F2 is 60, etc).

    Hope this helps somebody someday... :)
     

Share This Page