Hex Conquer (Borders Only)

Perhaps I misinterpreted this... I was under the impression Brazil AND another were razing... If it's just the other than it doesn't make sense that it was Brazil, and maybe the events that Brazil was doing are unrelated.

There's something confusing about your scenario in that crash occurs between Inuit and Brazil turn as per your description, but the city involved belongs to neither. iirc my razing check should only apply to a player on their own turn, and to that player's owned cities... And yet it seems to clearly be crashing during a raze check. It might be as simple as applying an additional conditional in the Lua to double check that whatever city is being processed by the raze function actually belongs to the relevant player... It's unclear how the raze check would even find a non-player city to begin with, it literally just loops all the current player's cities to check for razing status and pop=1

In any case there's some rare scenario during tile reassignment that CTD's the game, maybe @dailyminerals can shed some light on what was happening in there game when it occurred
I wanted to test it again, but it appears I saved the mod list on my Google Drive and had to delete it later, so I would have to download all of them with the correct versions and I just really don't want to do that right now. Hopefully the issue comes up in my current game too, but if not, I'll probably do this in the summer when I have more time.
 
Yeah I didn't test for same reason... But I did take a brief cruise through the logs... It's strange that the crash occurs when it does ie between Brazil/Inuit turn, despite an Assyrian city being razed.

This suggests that some part of the game engine is still considering the razing city as belonging to one of the other two civs nearby, even though that's clearly not the case in the screenshot.

Speculatively, it might be fixable if we added an additional conditional to ensure that the city being assessed actually belongs to the player the city loop function it returns from, but this shouldn't be necessary.

Too weird, need more info to narrow in on what is occurring

edit:

@Captain Carrot do you remember if there were any players that had been elminated? perhaps whose turn fell between brazil and inuit?
 
Last edited:
the speculative fix I have in mind is not too difficult to code -- I'm not sure if it fixes what's going wrong here, but nonetheless, I have pasted it here. Do the following:
  1. open main.lua in text editor (highly recommend anyone attempting this use notepad++ rather than just notepad)
  2. navigate to line 264, find the HexCREndTurn function
  3. replace the entire function (delete, then copy/paste from below) -- make sure just the function and not the hook below it
  4. save file, launch civ, load game, try to progress through CTD turn
  5. report back here with results
Spoiler :

Code:
function HexCREndTurn(iPlayer)
    print ("Hex CR razing check started")
    local pPlayer = Players[iPlayer]
    if pPlayer ~= nil and pPlayer:IsAlive() then
        for city in pPlayer:Cities() do
            local pCity = city
            if pCity ~= nil and (pCity:IsRazing()) and (pCity:GetPopulation() == 1) and (pCity:GetOwner() == iPlayer) then
                print ("Hex CR: city being razed has reached one pop")
                local pPlot = pCity:Plot()
                local pCityOwner = Players[pCity:GetOwner()]
                local pOwnerTeam = Teams[pCityOwner:GetTeam()]
                local iCityOriginalOwner = pCity:GetOriginalOwner()
                for i = 0, pCity:GetNumCityPlots()-1, 1 do
                    local lPlot = pCity:GetCityIndexPlot(i)
                    local ourCityAvailable = false
                    local teamAvailable = false
                    local allyAvailable = false
                    local friendAvailable = false
                    local noWarAvailable = false
                    local dPactAvailable = false
                    if (lPlot ~= nil) and ( (lPlot:GetOwner()) == (pCity:GetOwner()) ) then
                        local CityCandidates = {}
                        for pID = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
                            local nearCity, dist = getNearestCityWithException( pID, lPlot, pCity)
                            if (nearCity ~= nil) and (dist < 4) then
                                local us = (Players[pID] == pCityOwner)
                                local sameteam = (not us) and (Teams[Players[pID]:GetTeam()] == pOwnerTeam)
                                local friends = (not us) and (pCityOwner:IsDoF(pID))
                                local allies = (not us) and (pCityOwner:IsAllies(pID))
                                local war = (not us) and (pOwnerTeam:IsAtWar(Players[pID]:GetTeam()))
                                local dpact = (not us) and (pOwnerTeam:IsDefensivePact(Players[pID]:GetTeam()))
                      
                                if us then
                                    ourCityAvailable = true
                                end
                                if sameteam then
                                    teamAvailable = true
                                end
                                if friends then
                                    friendAvailable = true
                                end
                                if allies then
                                    allyAvailable = true
                                end
                                if not war then
                                    noWarAvailable = true
                                end
                                if dpact then
                                    dPactAvailable = true
                                end
                                table.insert(CityCandidates, {iPlayer = pID, bUs = us, bTeam = sameteam, bFriends = friends, bAllies = allies, bWar = war, bDpact = dpact, cNearCity = nearCity})
                          
                            end
                        end
                        if #CityCandidates > 0 then
                            if ourCityAvailable then
                                for i = 1, #CityCandidates, 1 do
                                    if CityCandidates[i] ~= nil then
                                        local lUs = CityCandidates[i].bUs
                                        if not lUs then
                                            table.remove(CityCandidates, i)
                                            i = i - 1
                                        end
                                    end
                                end
                            elseif teamAvailable then
                                for i = 1, #CityCandidates, 1 do
                                    if CityCandidates[i] ~= nil then
                                        local lTeam = CityCandidates[i].bTeam
                                        if not lTeam then
                                            table.remove(CityCandidates, i)
                                            i = i - 1
                                        end
                                    end
                                end
                            elseif dPactAvailable then
                                for i = 1, #CityCandidates, 1 do
                                    if CityCandidates[i] ~= nil then
                                        local lDpact = CityCandidates[i].bDpact
                                        if not lDpact then
                                            table.remove(CityCandidates, i)
                                            i = i - 1
                                        end
                                    end
                                end
                            elseif allyAvailable then
                                for i = 1, #CityCandidates, 1 do
                                    if CityCandidates[i] ~= nil then
                                        local lAlly = CityCandidates[i].bAllies
                                        if not lAlly then
                                            table.remove(CityCandidates, i)
                                            i = i - 1
                                        end
                                    end
                                end
                            elseif friendAvailable then
                                for i = 1, #CityCandidates, 1 do
                                    if CityCandidates[i] ~= nil then
                                        local lFriend = CityCandidates[i].bFriends
                                        if not lFriend then
                                            table.remove(CityCandidates, i)
                                            i = i - 1
                                        end
                                    end
                                end
                            elseif noWarAvailable then
                                for i = 1, #CityCandidates, 1 do
                                    if CityCandidates[i] ~= nil then
                                        local lNoWar = not CityCandidates[i].bWar
                                        if not lNoWar then
                                            table.remove(CityCandidates, i)
                                            i = i - 1
                                        end
                                    end
                                end
                            end
                            local randPlayer = math.random(#CityCandidates)
                            local iAssignPlayer = CityCandidates[randPlayer].iPlayer
                            local AssignCity = CityCandidates[randPlayer].cNearCity
                            if AssignCity == nil then return end -- city not found?
                            if Map.PlotDistance( AssignCity:GetX(), AssignCity:GetY(), lPlot:GetX(), lPlot:GetY() ) < 4 then
                                print("reassigning plot belonging to nearly razed city")
                                if ourCityAvailable then
                                    lPlot:SetOwner(-1, -1, false, false)
                                end
                                lPlot:SetOwner( iAssignPlayer, AssignCity, true, true )
                            end
                        end
                    end
                end
            end
        end
    end
end


@dailyminerals , if you still have your save, can you try this and let us know?
 
Last edited:
@Captain Carrot do you remember if there were any players that had been elminated? perhaps whose turn fell between brazil and inuit?
No, there was only one successful warmonger and they just made a vassal.

Speculatively, it might be fixable if we added an additional conditional to ensure that the city being assessed actually belongs to the player the city loop function it returns from, but this shouldn't be necessary.
If I had a dollar for every seemingly unnecessary check that ended up fixing everything...
 
If I had a dollar for every seemingly unnecessary check that ended up fixing everything...
Yeah on reviewing I realized I never put anything in to catch player=nil. Don't know how things like players exist in the game database while defined as nil, but apparently this is somewhat regular occurrence. That said it usually throws Lua exception rather than CTD when these checks are forgotten. Anyway my code above has this and a few others added in. Whoever next encounters razing crash needs to test
 
I checked-in with Gaia, the dev working on sapiens mod -- we're both under the impression that her version *should* work with VP. She has been developing one of the versions I worked on, and by now has done a lot of additional bugfixing and rebalancing. Specifically, I believe her version has addressed the puppet tile claiming issue. The razing issue may or may not persist there, she hasn't heard of it -- but its possible her edits to this mod got out in front of it anyway.

If it's not to everyone's liking, I'll look at making an proper update at some point specifically for VP, but I'd rather focus my limited time on other projects.

I suggest we all move on to Gaia's version for now, and reconvene here for any specific VP-related concerns -- alternatively, report any issues in the discussion on steam workshop, Gaia is pretty good at fixing things quickly. I'm tagged there too and will at least keep any reported issues in-mind if I do end up revisiting this. usadefcon's version is also a possible option

 
Last edited:
Does someone have a copy of Gaia's Tile Conquest mod (linked in the previous post)? For some reason, it has been removed from the Steam Workshop. If no-one has a copy, then I suppose the next-best thing is applying Tekamthi's suggested fix in the earlier post and hoping for the best. Of course, I'm rooting for Tekamthi to update this wonderful mod eventually.
 
I haven't been in touch with anyone in Gaia's community lately, but i take it that they are going a different route, integrating this stuff into other components.

The only thought I've had re: fixing the occasional crash, besides hoping the main branch dll sorts things out, is to change when the razing check happens. iirc it currently checks at the end of each player turn, for that same player... it looks for any cities that are in razing status with only 1 population remaining. This allows it to release nearby tiles shortly before the city disappears at that player's next turn start, however there is a gap between when the tile release occurs and when the razing actually completes (ie every other player gets to play 1 turn between these moments). As far as i'm aware a city will never raze from 2 or greater pop. to zero; if i'm wrong here we'll have to approach this a different way entirely, but thats how it works so far anyway.

What we could do, is instead have it check the next player at each player's turn end. This will bring the tile release much closer to the moment the city disappears from the map, and hopefully avoid whatever interim circumstance led to crash. ie there will be no players that have turns between the release and the completed raze. This solution is just a guess however. I don't have time to do this currently, but will eventually post an update with it... unless someone else has time first; it should be relatively trivial code adjustment; pls share if so
 
I've got a v6 ready to go... Just haven't had a chance to test enough to say I haven't broken anything important... Will try to run through a game with it over the next few days.

The goal here is to get us all using one version, rather than the disparate mix we've seen in this thread so far (I have 2 alternative versions so far, usadefcon has at least one as well...). This new version should enable all the desired functionality discussed so far, as well as some bug fixes (maybe). It does not include any of the work Gaia et al. may have done to improve this mod -- it might still be nice to mine their version for further improvements if we can find a copy.

I've attempted a speculative fix for the crashes people reported (two speculative fixes, really -- though I'm feeling 50/50 that the crash might originate in dll), as well as some general balance limitations on the mod's capture mechanism, using some suggestions from above re: distances etc. MR's original code had these functions already built-in, so it's not like I had to add any new cpu-intensive features; we'll see how it goes with these being called more often.

edit: pls see version 7 in post below
 
Last edited:
I've got a v6 ready to go... Just haven't had a chance to test enough to say I haven't broken anything important... Will try to run through a game with it over the next few days.

The goal here is to get us all using one version, rather than the disparate mix we've seen in this thread so far (I have 2 alternative versions so far, usadefcon has at least one as well...). This new version should enable all the desired functionality discussed so far, as well as some bug fixes (maybe). It does not include any of the work Gaia et al. may have done to improve this mod -- it might still be nice to mine their version for further improvements if we can find a copy.

I've attempted a speculative fix for the crashes people reported (two speculative fixes, really -- though I'm feeling 50/50 that the crash might originate in dll), as well as some general balance limitations on the mod's capture mechanism, using some suggestions from above re: distances etc. MR's original code had these functions already built-in, so it's not like I had to add any new cpu-intensive features; we'll see how it goes with these being called more often.

There are now some userOptions, with defaults set as follows:


NOTHING HERE IS TESTED CURRENTLY -- YOU ARE THE TESTER IF YOU DOWNLOAD.

I will attempt to hotfix any feedback received, but the results here may be a little wonky until we get more eyes on this version, and some reports back into this thread. That said the code changes are fairly slight, we're unlikely to see anything game-breaking, and any hotfixes should be compatible with save-games (this is pretty much a lua-only mod)
Thick you so much, I love this mod
 
I've got a v6 ready to go... Just haven't had a chance to test enough to say I haven't broken anything important... Will try to run through a game with it over the next few days.

The goal here is to get us all using one version, rather than the disparate mix we've seen in this thread so far (I have 2 alternative versions so far, usadefcon has at least one as well...). This new version should enable all the desired functionality discussed so far, as well as some bug fixes (maybe). It does not include any of the work Gaia et al. may have done to improve this mod -- it might still be nice to mine their version for further improvements if we can find a copy.

I've attempted a speculative fix for the crashes people reported (two speculative fixes, really -- though I'm feeling 50/50 that the crash might originate in dll), as well as some general balance limitations on the mod's capture mechanism, using some suggestions from above re: distances etc. MR's original code had these functions already built-in, so it's not like I had to add any new cpu-intensive features; we'll see how it goes with these being called more often.

There are now some userOptions, with defaults set as follows:


NOTHING HERE IS TESTED CURRENTLY -- YOU ARE THE TESTER IF YOU DOWNLOAD.

I will attempt to hotfix any feedback received, but the results here may be a little wonky until we get more eyes on this version, and some reports back into this thread. That said the code changes are fairly slight, we're unlikely to see anything game-breaking, and any hotfixes should be compatible with save-games (this is pretty much a lua-only mod)
I would recommend a numerical option for the size of the uncapturable zone around a city. I'm currently playing with a 2 tile uncapaureable radius.
 
I would recommend a numerical option for the size of the uncapturable zone around a city. I'm currently playing with a 2 tile uncapaureable radius.
are you using MR's functions to do this? i assume you're doing this in the PlotIsConquerable function? if its just 1 line of code, pls paste it in this thread, i'll figure out how to hide it behind a user option.

Edit: nvm was easy to implement

This mod takes some effort for me to just get all it's workings sorted out in my thoughts, enough that I can make meaningful updates to it... The original MR code is nicely written, I'm not knocking it, but it's complex. For this reason it's not easy to make updates on the fly, many weeks or months from now, after it's all been cleared from my short term memory.

So if anyone tuned in here has been sitting on some ideas for killer features, balance or otherwise, now is the time to suggest/remind me of them. I'm not gonna write any big new parts to this mod but if we can find clever ways to mitigate exploits or increase gameplay depth further in AI accessible ways, I'll consider...

For example, on a very simple level, citadel will always pillage on capture now (capturing intact citadel was pretty much a human-only play in my experience).

On that note, @usadefcon do you play with citadels as individual plot captures? My v6 still does adjacent captures but we could look at another boolean switch if you're not into this. Iirc the version of yours that I had tried a long time ago handled citadels differently than the original mod...
 
Last edited:
are you using MR's functions to do this? i assume you're doing this in the PlotIsConquerable function? if its just 1 line of code, pls paste it in this thread, i'll figure out how to hide it behind a user option.

Edit: nvm was easy to implement

This mod takes some effort for me to just get all it's workings sorted out in my thoughts, enough that I can make meaningful updates to it... The original MR code is nicely written, I'm not knocking it, but it's complex. For this reason it's not easy to make updates on the fly, many weeks or months from now, after it's all been cleared from my short term memory.

So if anyone tuned in here has been sitting on some ideas for killer features, balance or otherwise, now is the time to suggest/remind me of them. I'm not gonna write any big new parts to this mod but if we can find clever ways to mitigate exploits or increase gameplay depth further in AI accessible ways, I'll consider...

For example, on a very simple level, citadel will always pillage on capture now (capturing intact citadel was pretty much a human-only play in my experience).

On that note, @usadefcon do you play with citadels as individual plot captures? My v6 still does adjacent captures but we could look at another boolean switch if you're not into this. Iirc the version of yours that I had tried a long time ago handled citadels differently than the original mod...
I've been playing that citadels are just another tile and not treated differently, but I do like the idea of it pillaging on capture.
 
NOTHING HERE IS TESTED CURRENTLY -- YOU ARE THE TESTER IF YOU DOWNLOAD.

I will attempt to hotfix any feedback received, but the results here may be a little wonky until we get more eyes on this version, and some reports back into this thread. That said the code changes are fairly slight, we're unlikely to see anything game-breaking, and any hotfixes should be compatible with save-games (this is pretty much a lua-only mod)
mid-battle tile capture doesn't seem to work at all.
I march my armies across enemy lands uncontested yet they still don't flip.
I get an enemy tile if it's within 3 tiles of my city AND more than 3 tiles away from theirs, but sometimes the enemy still keeps some.
If I capture isolated cities, I get the tiles around it and some more.

Peace treaty tile flips seem to work fine, except I can only get the tiles far from his cities since I can't flip any.
Razed a couple cities and none of them broke the game.
 
mid-battle tile capture doesn't seem to work at all.
looking into it, ty for report -- assuming you left the 'useroptions' unchanged?

i have developed this a little further since v6, just getting to the point in my game where tile flip is possible, will try to iron out this mechanism if its failing and repost new version shortly

Edit: I was unaware of some of the peculiarities of civ 5 Lua environment; to make v6 work properly you can copy paste the user option variables to the top of conquer.lua. or just wait til my next upload in a day or two
 
Last edited:
i've taken a stab at rebalancing this mod a little in this latest version, however you can tune as desired using the options at top of conquer.lua (and one at top of main.lua). This latest version should have all the customizability options anyone could ask for; I have set the default values per my own take on best compromise for AI accessibility, gameplay balance, and system resource use, but its a bit of a theorycraft.

There's no point in messing with v6, v7 should do everything it attempted to do and more; deleting from post above. This remains in-need of testing, but I have at least confirmed the main functions hold up in general play this time around. As before, will attempt to hotfix any issues reported in this thread.

The important "balance" changes in this version (using default values) are as follows:
  • any improved plot (including road) must be pillaged before it can be captured
  • unit with red hp bar cannot capture
  • A puppet will try to reclaim ownership of nearby friendly plots after each building it completes
You can change most of these new effects as desired at top of conquer.lua; i've tried to include any other balance criteria discussed in this thread (and then some), ie a true community version. Other options available are as follows:
Spoiler :

conquer.lua
------------------
---User Options---
------------------
--unit rules
local bUnembarkedLandUnitsCaptureLandPlots = true;
local bUnembarkedLandUnitsCaptureAdjacentLandPlots = true;
local bUnembarkedLandUnitsCaptureAdjacentWaterPlots = true;
local bEmbarkedUnitsCaptureWaterPlots = true;
local bEmbarkedUnitsCaptureAdjacentWaterPlots = true;
local bEmbarkedUnitsCaptureAdjacentLandPlots = false;
local bWaterUnitsCaptureWaterPlots = true;
local bWaterUnitsCaptureAdjacentWaterPlots = true;
local bWaterUnitsCaptureAdjacentLandPlots = false;
--red hp bar = 33% and under, yellow = 34% to 66%, green 67% and up; nil to disable hp check
local iUnitMinimumHPpercentToCapture = 34;

--ownership rules
--see top of main.lua for minor civ capture ability
local bMinorCivPlotsCanBeCaptured = true;
--improvement handling rules
local bCitadelControlsAdjacentCaptures = true;
local bUnpillagedCitadelBlocksUnitCapture = true;
local bUnpillagedImprovementBlocksUnitCapture = true;
local bUnpillagedRouteBlocksUnitCapture = true;
--autopillage improvements on capture? improvement-blocks immediately above must be set to false for this to have observable effect
local bCitadelAutoPillageOnCapture = false
local bImprovementAutoPillageOnCapture = false;
local bRouteAutoPillageOnCapture = false;

local bUnpillagedFortBlocksUnitAdjacentCapture = true;
local bUnpillagedFortBlocksUnitPlotCapture = true;

--adjacency rules
local bLandMustBeAdjacentToFriendlyPlot = true;
local bWaterMustBeAdjacentToFriendlyPlot = true;

--distance rules
local bPlotMustBeAsCloseOrCloserToFriendlyCity = false;
-- eg. suggested value: GameDefines.MAXIMUM_ACQUIRE_PLOT_DISTANCE; or any other integer. nil to disable.
local iCaptureDistanceLimitFromFriendlyCity = nil;
-- eg. suggested value: math.ceil(GameDefines.MAXIMUM_WORK_PLOT_DISTANCE/2); or any other integer. nil to disable.
local iCaptureImmunityCityRadius = nil;
-- eg. suggested value: GameDefines.MAXIMUM_WORK_PLOT_DISTANCE; or any other integer. nil to disable.
local iCaptureImmunityCapitalRadius = nil;
------------------

main.lua
------------------
---User Options---
------------------
local bMinorCivCanCapture = true;
------------------
 

Attachments

Last edited:
Thank you again for maintaining this. I am pretty sure it helps the AI operationalize aggressive wars, which is a huge W.

I am just starting a game with the Gaia version, I am curious to play with their citadel anchoring land mechanic.

I like where this mod is going with pillage to capture. I think the Gaia mod with the citadel feature expanded to forts as well would be cool.
 
I think the Gaia mod with the citadel feature expanded to forts as well would be cool.
I think the various booleans i added last time could be tweaked to make it work same if desired -- BUT if you like the featureset in Gaia's version it might just be worth using hers, as she's done some major reworks for efficiency etc. Gaia has eliminated some of the complexities in the code, at a trade-off of a few features we still have available here, perhaps. Intends to continue updating as well i believe.

my v7 above is intended to be somewhat of a "final" version of this old MR code, at least to the extent i want to develop it. It still works well from my point of view; i may revisit if any major bugs are identified or if some vp update breaks it, if i'm still around, but otherwise i'm hoping v7 just works forever for those who want it.
 
Last edited:
I've played most of a game with Gaia's

Overall, I prefer this version. I've never had any crashes with it, and I like the raze to capture feature as it allows me to handicap myself by not abusing this but the AI pillages a lot so it works for them.

The citadel anchor mechanic didn't add much tactical depth and forts were kind of buggy about flipping.
 
Back
Top Bottom