[C3C] Hunting down the Barbarian NW/SE axis bug

BlueSox14

Chieftain
Joined
Nov 11, 2021
Messages
7
Inspired by the great work that Flintlock has done with his C3X patch, I became intrigued with just how he manages to do this. I'm also really irritated by the barbarian NW/SE axis bug.

I thought I might try to investigate this particular bug as a learning exercise. Whether or not I manage to identify the location of this bug remains to be seen, but as long as I learn something along the way it won't matter so much.

This thread is for anyone that wants to follow my progress, learn or even participate in identifying this bug.

I am by no means an authority on this bug, Civ3 or programming making me totally ill-equipped to investigate this! Corrections to any statements I make, or ideas I have are warmly received.


What is the barbarian NW/SE axis bug?


The intended behaviour for barbarians as shipped with vanilla Civ3 is to 'check' a number of surrounding squares. If it 'sees' a non-barbarian unit within this range, it will pursue them as a matter of priority. If it can't 'see' any units the barbarian unit will fortify (if NoAIPatrol=1) or patrol randomly (if NoAIPatrol=0).

Details are sketchy, but at some point with the PTW expansion, a bug was introduced where instead of 'checking' all the surrounding squares, the barbarian would only 'check' the squares on the NW/SE axis.

This bug was corrected with a later PTW expansion patch. However, the bug resurfaced again with Conquests.

If I haven't covered off on any significant aspects of the bug above then please let me know!

There are two excellent threads I've found on this bug below:
https://forums.civfanatics.com/threads/fix-for-the-barbarians-sort-of.100704/
https://forums.civfanatics.com/threads/submarine-bug-investigation.526635/

In the second link above, Antal proposes that the AI calculates a 'net' of positions which, based on what I know, seems relevant to the barbarian NW/SE axis bug.


Flintlock and the C3X patch


For anyone who hasn't been following, Flintlock is doing some really incredible things, fixing bugs that have been present for two decades, and introducing wonderful QOL improvements into Civ3 with his C3X patch.

Check it out here:
https://forums.civfanatics.com/threads/sub-bug-fix-and-other-adventures-in-exe-modding.666881/


Want to follow along?

Flintlock has made the reverse engineering work he is doing on the Civ3 executable available on GitHub. You can find the link on page 21 of the thread above.

My own experience includes a little bit of visual basic programming and absolutely zilch in assembly programming!

I have since learned that the reverse engineering work disassembles the executable into assembly language. So I've had to start by reading up on assembly language.


Resources

I've found the below resources on assembly programming useful.
https://www.cs.virginia.edu/~evans/cs216/guides/x86.html
https://www.tutorialspoint.com/assembly_programming/index.htm

If anyone has got other resources that will be helpful, please share!

If there are any assembly language guru's out there, I'd appreciate any pointers on what to cover in order for me to try to begin working through the assembly code in Ghidra.


Going forward

So that's pretty much where I'm at. Life gets busy and I can never quite give these things the sort of time I would like to. I want to get through a little more reading on assembly, mostly around memory, stacks and how information is stored and transferred.

After that I'll try to start taking a closer look at trying to identify the logical functions where this bug might reside. If anyone wants to make a start, a couple of functions that look promising are:
  • ai_move_barbarian
  • Trade_Net::get_movement_cost
  • Trade_Net::set_unit_path
 
I would prefer it to be user-configurable. It would make it possible to better tweak how aggressive and unpredictable barbarians behave. Also, a setting that decides wheather barbarians always targets "civilized units" nearby or just wander around randomly (disregarding other units and settlements/colonies) could be an improvement IMO. "Improvement" in the sense of letting us better adjust the impact/threat of roaming barbarians.
 
I've done a little testing around this bug to clarify some parameters which I hope will come in handy when taking a closer look at the assembly code. Below testing conducted in Conquests.

Below are my findings:

Where units have defence of at least 1 (ie. warriors), the barbarian ai will only appear to 'see' these units along the NW/SE axis up to 12 tiles away. The below roman warriors would all appear to be 'seen' by the barbarian ai. This behaviour and distance was the same between the sedentary and raging barbarian settings.

upload_2021-12-7_22-44-28.jpeg


Where units have a defence of zero (ie. settlers), the ai barbarians will appear to 'see' all units one tile away and consequently attack. Barbarians will not appear to 'see' settlers two squares away.

upload_2021-12-7_22-46-1.jpeg


This in and of itself also seems bugged. Surely barbarians should 'see' more than one tile away?

I note that the number of squares that the barbarian appears to 'see' is 24 (refer top picture). This is the same number of squares in the net below:

upload_2021-12-7_22-48-12.jpeg


This is complete speculation on my behalf at the moment, but I just wonder if the number of squares that appear to be 'seen' at the moment is correct, but something is wrong with the math/logic in the coding and it's spreading those 24 squares along that axis. Contributing to this is the coordinate system below where the x & y values along that axis increment/decrement relative to the barbarian tile by one. I feel like there might be some clues in the root cause of the bug there.

upload_2021-12-7_22-52-41.jpeg


I've been mulling over how such logic would be coded. The below activities seem logical (but speculation at this point):

1) Cast a search net for certain targets (whether units with no defence, or units with defence greater than zero). This might be implemented with multiple casting/searches and the bug might only occur in the search for one of those unit types only.
2) Once the search net is cast, decide how to proceed - proceed towards target, run away, fortify as examples of responses.
3) Once action to be taken is decided, what is the movement required? Perhaps the pathing logic is bugged.

Testing above suggests that the bug lies in how the search net is cast...on the basis that barbarians being able to see 12 tiles away seems awfully far.

I tried to test this with PTW, but unfortunately with my CD copy of conquests, it automatically patches PTW to the latest version...the version that includes the bug. I'll run some testing in vanilla Civ 3 to get a better idea of barbarian ai behaviour pre-bug...but the vanilla Civ 3 editor doesn't include a debug mode...which makes testing a little bit more fiddly. On top of that, AI patrolling is enabled by default in vanilla so it's always a bit hard to know what is driving barbarian movement.

If anyone has access to Civ 3 PTW on CD, and wouldn't mind running some tests on a version prior to the final patch, then let me know. That would help a lot.
 
Where units have a defence of zero (ie. settlers), the ai barbarians will appear to 'see' all units one tile away and consequently attack. Barbarians will not appear to 'see' settlers two squares away.

This in and of itself also seems bugged. Surely barbarians should 'see' more than one tile away?

Good work and observations, BlueSox14. Regarding units with zero defence: The advanced barbarians has two movement points, and they will ambush any defenseless unit within attacking range (ie. two tiles).

I've always thougth that any unguarded defenseless unit (outside the NW/SE axis) would be targeted from far away as well, but your tests shows that only units within attacking range are.
 
Very minor update today. Testing on the final vanilla version (1.29f) indicates that barbarian ai would appear to 'see' units up to and including six tiles away. Anything inside the boundary below:

upload_2021-12-9_21-36-40.png


That sort of blows my earlier speculation out of the water where I wondered if the search net was intended to compromise 24 squares. It comprises 168 squares above!

Anyhow, I think it was useful to clarify these parameters before trying to return to the assembly code and figure out what is occurring there.

I'm going to assume that the intended search net is therefore up to and including six tiles away. If anyone has reason to challenge this, then I'd love to hear your thoughts.

Back to digesting assembly tutorials for a time to see if I can figure out what I'm looking at in Ghidra!
 
Hi all,

After commencing some study into this bug, life, as it does, got in the way.

However, I'm delighted to share that Flintlock has identified the source of this bug! If you aren't following Flintlocks work in the C3X: EXE Mod including Bug Fixes, Stack Bombard, and Much More thread and would like to know a little more about this, then please check out his write up here:

https://forums.civfanatics.com/thre...ck-bombard-and-much-more.666881/post-16434678

Stay civilized everyone!
 
Top Bottom