C7-Game / Prototype

An early-stage, open-source 4X strategy game
https://c7-game.github.io/
MIT License
34 stars 9 forks source link

If only non-defending units are left defending a city after combat, it should be destroyed #395

Open QuintillusCFC opened 1 year ago

QuintillusCFC commented 1 year ago

This is a follow-up to #286

Currently, if a non-combat unit is the only defending unit when a rival unit attempts to move into the city, it is destroyed (eventually it will be captured).

However, if there is exactly one defending unit, and it is defeated, the city is not destroyed. A lone Catapult may prevent capture, for example.

This appears to be due to the interaction of these code blocks:

    // If the enemy was defeated, check if there is another enemy on the tile. If so we can't complete the move
    // but still pay one movement point for the combat.
    else if (combatResult == CombatResult.DefenderKilled || combatResult == CombatResult.DefenderRetreated) {
        if (!unit.CanEnterTile(newLoc, false)) {
            unit.movementPoints.onUnitMove(1);
            return true;
        }

And and CanEnterTile method in MapUnitExtensions (excerpt):

        // Check for units belonging to other civs
        foreach (MapUnit other in tile.unitsOnTile)
            if (other.owner != unit.owner) {
                if (!other.owner.IsAtPeaceWith(unit.owner))
                    return allowCombat;
                else
                    return false;
            }

It is returning false because allowCombat is false since combat already ended.

A better way of doing this might be to utilize TileExtension's FindTopDefender method (which uses MapUnitExtension's canDefendAgainst method, and if there are no defenders, the unit can move in.

But CanDefendAgainst will also need to be enhanced to account for non-defense-capable units.

Adding the refactor tag since there is some duplication of logic between methods, and the area can probably be simplified a bit.

QuintillusCFC commented 1 year ago

Random seed: 1893199352 Commit: 9b0998bbaf288c987df3c630bfaa22ce76196769 Turn: 56

A Veteran Barbarian Warrior will attack Babylon and win, with one hitpoint left. Right-click on Babylon and you can see in the console that only one Catapult remains.