SpacedOutChicken / DeCiv-Redux

Rebuild civilization after the end of the world. A mod for Unciv. Uses FantasyHex tiles and units.
96 stars 29 forks source link

Game crashes when Almaty attempts to gift a unit to the Patriots #48

Closed HaneulCheong closed 2 years ago

HaneulCheong commented 2 years ago

Platform Windows 64-bit

Version Base Game: 3.19.18 Mod: 6a66397f995536a30ebbe4b7d94eb0e268ec0c34

Describe the bug Game crashes when Almaty attempts to gift a unit to the Patriots under a certain unknown condition. Here's the stack trace:

Exception in thread "Thread-13" java.util.NoSuchElementException: Collection is empty.
        at kotlin.collections.CollectionsKt___CollectionsKt.random(_Collections.kt:558)
        at com.unciv.logic.civilization.CityStateFunctions.giveMilitaryUnitToPatron(CityStateFunctions.kt:98)
        at com.unciv.logic.civilization.diplomacy.DiplomacyManager.nextTurnFlags(DiplomacyManager.kt:530)
        at com.unciv.logic.civilization.diplomacy.DiplomacyManager.nextTurn(DiplomacyManager.kt:426)
        at com.unciv.logic.civilization.CivilizationInfo.endTurn(CivilizationInfo.kt:867)
        at com.unciv.logic.GameInfo.nextTurn$switchTurn(GameInfo.kt:204)
        at com.unciv.logic.GameInfo.nextTurn(GameInfo.kt:218)
        at com.unciv.ui.worldscreen.WorldScreen$nextTurn$1.invoke(WorldScreen.kt:645)
        at com.unciv.ui.worldscreen.WorldScreen$nextTurn$1.invoke(WorldScreen.kt:637)
        at com.unciv.ui.utils.ExtensionFunctionsKt$wrapCrashHandling$1.invoke(ExtensionFunctions.kt:329)
        at com.unciv.ui.utils.ExtensionFunctionsKt$wrapCrashHandlingUnit$1.invoke(ExtensionFunctions.kt:356)
        at com.unciv.ui.utils.ExtensionFunctionsKt$wrapCrashHandlingUnit$1.invoke(ExtensionFunctions.kt:356)
        at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

To Reproduce

  1. Download the save file below
  2. Run the game and load the save
  3. Push the Next Turn button

Expected behavior Almaty successfully gifts a unit to the Patriots.

Additional context

HaneulCheong commented 2 years ago

Here's the code around the line 98 of the source code's com.unciv.logic.civilization.CityStateFunctions.kt:

    fun giveMilitaryUnitToPatron(receivingCiv: CivilizationInfo) {
        val cities = NextTurnAutomation.getClosestCities(receivingCiv, civInfo)
        val city = cities.city1
        val uniqueUnit = civInfo.gameInfo.ruleSet.units[civInfo.cityStateUniqueUnit]
        // If the receiving civ has discovered the required tech and not the obsolete tech for our unique, always give them the unique
        val militaryUnit = if (uniqueUnit != null && receivingCiv.tech.isResearched(uniqueUnit.requiredTech!!)
            && (uniqueUnit.obsoleteTech == null || !receivingCiv.tech.isResearched(uniqueUnit.obsoleteTech!!))) uniqueUnit
            // Otherwise pick at random
            else city.cityConstructions.getConstructableUnits()
            .filter { !it.isCivilian() && it.isLandUnit() && it.uniqueTo==null }
            .toList().random() // <<<< Line 98!!
        // . . .
    }

The following units were on the construction list in Eagle Rock

HaneulCheong commented 2 years ago

According to the code:

  1. If the receiving civ has discovered the required tech and not the obsolete tech for our unique, always give them the unique
  2. Otherwise pick at random (under the following conditions) 2.1. Should be constructable 2.2. Is not a civilian 2.3. Is a land unit 2.4. Is not unique to any faction

Thus I suspect this is what happened internally:

HaneulCheong commented 2 years ago

It should also be noted that the game seems to accept only one city-state unique unit. This might also be part of the crash.

val uniqueUnit = civInfo.gameInfo.ruleSet.units[civInfo.cityStateUniqueUnit]
SpacedOutChicken commented 2 years ago

Have you posted this to the main Unciv bug report line? I think the other devs would like to see this.

SpacedOutChicken commented 2 years ago

As for the "one unique unit" thing you noticed, that might be referring to the unique unit that city-states can give as a gift. I'm hoping that they haven't lost the ability to have unique units of their own.

HaneulCheong commented 2 years ago

Just confirmed the game proceeding to next turn without an issue in 4.0.0. This issue seems solved with https://github.com/yairm210/Unciv/pull/6393.