Jump to content

R&D AI Improvements


Amineri

Recommended Posts

  • Replies 144
  • Created
  • Last Reply

Top Posters In This Topic

Well, I looked up both, and I *think* they are fixed in EW.

 

The freeze was in XGAIAbilityDM.AI_GetScoreModifier ... there was a divide by zero error.

 

The lack of hunkering down was in XGAIAbilityDM.AI_DefenseScore ... I don't recall the error.

 

But in both cases, it looks like Amineri's fixes are in place.

 

I haven't observed the alien freeze, nor have I have observed the aliens hunkering down in EW.

Link to comment
Share on other sites

Yeah, I don't necessarily see anything with the hunker down rules themselves that would prevent it from ever being used (I've certainly seen it used before), but it is a fairly rare occurrence since it has two sets of requirements (the only ability to have any set in BuildConditions actually):

 

1. The alien is overwatched and not flanked

Or

2. The alien is alone and outnumbered

 

I think one of the things that was discussed before was that you could freeze an alien in place while you maneuvered right up to it to capture it, and I think the hunker down rules seem to support that. Adding an egress mechanism when alone and outnumbered seems like a good idea, no?

Link to comment
Share on other sites

I have observed aliens hunkering down, sometimes consistently when overwatched by 3-4 soldiers from hard cover. Once I saw Elite Muton using hunker down while he was supressed. But in most cases supressed aliens do nothing, not even overwatch.

 

On a side note: aliens seems to use grenades a LOT more that in the EU. For example, soldier with ghost armor will be grenaded immediately even when in no cover. Even by Elites who have decent aim, especially on Impossible. I consistently observed all the pack throwing their grenades on my heavy in EW, while in EU they were shooting after destroying cover with first grenade.

Link to comment
Share on other sites

monju125, yes, I confirm seeing hunker down in these conditions! But again, I'm seeing suppressed aliens skip turn consistently, it's not one time thing. But I use suppression a LOT: 2 heavies + support, sometimes I choose to supress all three aliens at once. :smile:
Link to comment
Share on other sites

 

 

I think one of the things that was discussed before was that you could freeze an alien in place while you maneuvered right up to it to capture it,

 

This was the EU freeze ... there may be another freeze due to suppression, which wghost has observed. In our experience, true freezes were a result of a code error, so perhaps there's one where the AI considers suppression or has a really low shot chance.

Link to comment
Share on other sites

The Suppression-related inaction in EU was unrelated to the divide-by-zero error (which indeed has been fixed in EW).

 

Basically Suppression has a hard-filter to prevent any form of movement action when suppressed. This is set in XGAIAbilityRules.BuildConditions with the line :

SetAbilityRestriction(1, 1);

The 1st 1 is eAbility_Move, the second 1 is a bit flag for the unit being Suppressed (the condition flags are set in XGAIAbilityRules.UpdateConditions. There is a test in XGAIAbilityDM.PassOrFilterAbility that calls XGAIAbilityRules.PassesRestrictions. If the unit is being suppressed then the move ability failes this Restrictions test is removed the the list of abilities that will be scored.

 

However, there is another set of tests that happen in XGAIBehavior.ShouldAvoidMovement to indicate whether the unit shouldn't move. These are things like (1) has a 70%+ shot, (2) Isn't melee (3) isn't facing too much overwatching ... but NOT whether the unit is being suppressed. This function is used in XGAIAbilityDM.Init to initialize a class variable :

m_bShouldAvoidMovement = m_kBehavior.ShouldAvoidMovement();

For this issue, the key place this class variable is used is in XGAIAbilityDM.PassesMovementFilter :

    if(((!m_bShouldAvoidMovement && m_kUnit.GetRemainingActions() > 1) && !m_kUnit.IsInCover() || m_kUnit.GetNumFlankers() > 0) && m_kUnit.CanUseCover())
    {
        if((kAbility.GetType() == 1) || kAbility.GetType() == 5)
        {
            return true;
        }
        else
        {
            strDebugFailure @= "failed PassesMovementFilter: Unit flanked or not in cover should move on first action.";
            return false;
        }
    }

This code filters any non-movement ability (excepting 1=eAbility_Move and 5=eAbility_Launch). You can see the reasoning in the strDebugFailure line ... the supposition is that a flanked or exposed unit (that can use cover) with any movement left MUST move to find cover, as long as the unit shouldn't be avoiding movement.

 

And this the combination of these two events is what leads to "suppression freezing". Suppression triggers a Requirement filter that filters out eAbility_Move, while being flanked or exposed results in filtering out any non-move abilities. This results in the filtering of all abilities, with the exception of Launch. You can see this happening in game .. if you Suppress an exposed/flanked Floater it will always use the Launch ability.

 

The fix for this (which isn't in Enemy Within) is to add the following condition to ShouldAvoidMovement:

if(m_kUnit.IsBeingSuppressed())
{
	return true;
}

This doesn't actually do any further restrictions on moving (those are already implemented via the PassesRestrictions test). It simply correctly updates the status of ShouldAvoidMovement (and hence m_bShouldAvoidMovement) to correctly recognize that the unit is being suppressed and so cannot move.

Link to comment
Share on other sites

Amineri -- I'll get this fix in Long War.

 

Here's the text for a upkmodder file with the fix:

 

 

 

MODFILEVERSION=4
UPKFILE=XComGame.upk
GUID=5B 06 B8 18 67 22 12 44 85 9B A8 5B 9D 57 1D 4B // EW Patch 1
FUNCTION=ShouldAvoidMovement@XGAIBehavior
KEYWORD=Fixes bug in which suppressed enemies would freeze and skip their turn
RESIZE=16

[BEFORE_HEX]
[HEADER]
87 01 00 00 1f 01 00 00
[/HEADER]
[CODE]
07 29 01 82 9A 36 19 01 8F 9A 00 00 09 00 8A 39 00 00 00 01 8A 39 00 00 25 16 18 0D 00 81 2D 01 A5 9A 00 00 16 16 
	//if((m_kUnit.m_arrFlankingUnits.Length == 0) && !m_bKeepHidden)

07 A0 00 2D 01 9C 9A 00 00 
	//if(m_bHasVulnerableTarget)

0F 00 E9 9E 00 00 1B D4 38 00 00 00 00 00 00 19 01 8F 9A 00 00 09 00 9E F8 FF FF 00 01 9E F8 FF FF 01 5B 9A 00 00 4A 16 
	//iCurrHitChance = GetHitChanceEstimateFrom(m_kUnit.Location, m_kVulnerableTarget)

07 9D 00 97 00 E9 9E 00 00 92 2C 46 1B EE 37 00 00 00 00 00 00 16 16 16 
	//if(iCurrHitChance > (70 + (GetCoverNoMoveMinHitChanceBump())))

04 27 
	//return true

06 29 01 
	//goto J0x129

58 19 01 8F 9A 00 00 73 00 95 39 00 00 00 01 95 39 00 00 00 E8 9E 00 00 00 4A 28 01 
	//foreach m_kUnit.m_arrVisibleEnemies(kUnit,)

0F 00 E9 9E 00 00 1B D4 38 00 00 00 00 00 00 19 01 8F 9A 00 00 09 00 9E F8 FF FF 00 01 9E F8 FF FF 00 E8 9E 00 00 28 16 
	//iCurrHitChance = GetHitChanceEstimateFrom(m_kUnit.Location, kUnit, false)

07 27 01 97 00 E9 9E 00 00 92 2C 46 1B EE 37 00 00 00 00 00 00 16 16 16 
	//if(iCurrHitChance > (70 + (GetCoverNoMoveMinHitChanceBump())))

30
	//IP(1/1)
	
04 27 
	//return true

31
	//IN(1/1)
	
30
	//IP(1/1)
	
07 7A 01 82 82 81 19 01 8F 9A 00 00 0A 00 83 3A 00 00 00 1B 18 45 00 00 00 00 00 00 16 16 18 0D 00 81 2D 01 A3 9A 00 00 16 16 18 16 00 97 01 5C 9A 00 00 1B 67 39 00 00 00 00 00 00 16 16 16 
	//if((!m_kUnit.IsMeleeOnly() && !m_bIsMindControlled) && m_iOverwatchDangerZone > (GetMaxDangerLevelForMovement()))

04 27 
	//return true

04 28 
	//return false

04 3A EA 9E 00 00 
	//return ReturnValue

53 
//	
[/CODE]
[/BEFORE_HEX]


[AFTER_HEX]
[HEADER]
a1 01 00 00 35 01 00 00
[/HEADER]
[CODE]
07 29 01 82 9A 36 19 01 8F 9A 00 00 09 00 8A 39 00 00 00 01 8A 39 00 00 25 16 18 0D 00 81 2D 01 A5 9A 00 00 16 16 
	//if((m_kUnit.m_arrFlankingUnits.Length == 0) && !m_bKeepHidden)

07 A0 00 2D 01 9C 9A 00 00 
	//if(m_bHasVulnerableTarget)

0F 00 E9 9E 00 00 1B D4 38 00 00 00 00 00 00 19 01 8F 9A 00 00 09 00 9E F8 FF FF 00 01 9E F8 FF FF 01 5B 9A 00 00 4A 16 
	//iCurrHitChance = GetHitChanceEstimateFrom(m_kUnit.Location, m_kVulnerableTarget)

07 9D 00 97 00 E9 9E 00 00 92 2C 46 1B EE 37 00 00 00 00 00 00 16 16 16 
	//if(iCurrHitChance > (70 + (GetCoverNoMoveMinHitChanceBump())))

04 27 
	//return true

06 29 01 
	//goto J0x129

58 19 01 8F 9A 00 00 73 00 95 39 00 00 00 01 95 39 00 00 00 E8 9E 00 00 00 4A 28 01 
	//foreach m_kUnit.m_arrVisibleEnemies(kUnit,)

0F 00 E9 9E 00 00 1B D4 38 00 00 00 00 00 00 19 01 8F 9A 00 00 09 00 9E F8 FF FF 00 01 9E F8 FF FF 00 E8 9E 00 00 28 16 
	//iCurrHitChance = GetHitChanceEstimateFrom(m_kUnit.Location, kUnit, false)

07 27 01 97 00 E9 9E 00 00 92 2C 46 1B EE 37 00 00 00 00 00 00 16 16 16 
	//if(iCurrHitChance > (70 + (GetCoverNoMoveMinHitChanceBump())))

30
	//IP(1/1)
	
04 27 
	//return true

31
	//IN(1/1)
	
30
	//IP(1/1)
	
07 7A 01 82 82 81 19 01 8F 9A 00 00 0A 00 83 3A 00 00 00 1B 18 45 00 00 00 00 00 00 16 16 18 0D 00 81 2D 01 A3 9A 00 00 16 16 18 16 00 97 01 5C 9A 00 00 1B 67 39 00 00 00 00 00 00 16 16 16 
	//if((!m_kUnit.IsMeleeOnly() && !m_bIsMindControlled) && m_iOverwatchDangerZone > (GetMaxDangerLevelForMovement()))

04 27 
	//return true

07 9e 01 19 01 8F 9A 00 00 0A 00 C0 35 00 00 00 1B 11 44 00 00 00 00 00 00 16
//if(m_kUnit.IsBeingSuppressed())

	04 27
	// return true

04 28 
	//return false

53 
[/CODE]
[/AFTER_HEX]

 

 

Edited by johnnylump
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...