Simulating City Morale

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Simulating City Morale

      This is the new thread I said I would create for discussing Predicting Morale

      My goal is being able to start with nothing more than the 70% City Morale that is the Day 1 default, then use a player-specified list of morale daily penalties and bonuses to come up daily morale predictions that closely track actual Morale values a City will have in a game.

      There are two things in the rest of this post.
      1) Actual Morale-Penalty and City-Morale values I recorded during a Pacific Theater game (for a city call Khovid).
      2) Data and a graph showing a software subroutine's Morale predictions.

      Those predictions come from a Java software method/subroutine that is pasted into my next post in this thread.

      The graph shows that the predictions are A) generally to optimistic (the predicted Morale is generally higher than the actual Morale), and B) Don't track the Morale changes well during the period when the Morale was close to the city's Adjusted-Target-Morale (the sum of the city's Target-Morale and the city's Penalties).

      I can toss in a "heuristic" guess or two to mimic rounding that might be occurring in the game software, and I can increase the Morale penalties to account for assumed rounding/truncation occurring in the game display code. If I do that those changes can create better agreement in the first half of the predictions, but they don't do much to improve how well the predictions track the last half of the actual Morale values.

      I welcome feedback from anyone able to review or execute the code. There might be a bug or two lurking in it.

      Source Code

      1. Day 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
      2. khovidArray = { 70.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 81.0, 79.0, 80.0, 81.0, 79.0, 80.0, 79.0, 76.0, Double.NaN, Double.NaN };
      3. civCasArray = { 0.0, 0.0, -1.0, -2.0, -3.0, -2.0, -4.0, -3.0, -2.0, -2.0, -1.0, -3.0, -2.0, -2.0, -2.0, -2.0, -3.0, -5.0, -5.0 , -5.0 };
      4. atWarArray = { 0.0, -6.0, -8.0, -6.0, -6.0, -2.0, -4.0, -2.0, -6.0, -4.0, -6.0, -6.0, -8.0, -8.0, -8.0, -6.0, -6.0, -10.0, -10.0, -10.0 };



      NewDayAtWarCivCasPenaltiesAdjTgtOldMoraleDiffSubtractPredictedPredictedNxtActualErrorError
      100090702016.773.373721.31
      2-60-68473.310.78.975.175732.12
      3-8-1-98175.15.94.976.176742.12
      4-6-2-88276.15.94.977.177752.12
      5-6-3-98177.13.93.377.778761.72
      6-2-2-48677.78.36.979.179772.12
      7-4-4-88279.12.92.479.680781.62
      8-2-3-58579.65.44.580.580791.51
      9-6-2-88280.51.51.380.781800.71
      10-4-2-68480.73.32.781.381810.30
      11-6-1-78381.31.71.481.682792.63
      12-6-3-98181.6-0.6-0.581.581801.51
      13-8-2-108081.5-1.5-1.281.281810.20
      14-8-2-108081.2-1.2-181817922
      15-8-2-108081-1-0.980.981800.91
      16-6-2-88280.91.1181817922
      17-6-3-981810081817655
      18-10-5-157581-6-58080NaNNaNNaN



      PacificMorale.JPG
    • Here is the subroutine (a Java method) that created the predictions my previous post (immediately above).

      Anyone who cares to run it can adjust the inputs, the algorithm, or both to experiment with the effects of rounding/truncating values when displaying or storing them.

      Source Code

      1. public void computeMoraleHistory( )
      2. {
      3. // Day 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
      4. Double[] khovidArray = { 70.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 81.0, 79.0, 80.0, 81.0, 79.0, 80.0, 79.0, 76.0, Double.NaN, Double.NaN };
      5. Double[] civCasArray = { 0.0, 0.0, -1.0, -2.0, -3.0, -2.0, -4.0, -3.0, -2.0, -2.0, -1.0, -3.0, -2.0, -2.0, -2.0, -2.0, -3.0, -5.0, -5.0 , -5.0 };
      6. Double[] atWarArray = { 0.0, -6.0, -8.0, -6.0, -6.0, -2.0, -4.0, -2.0, -6.0, -4.0, -6.0, -6.0, -8.0, -8.0, -8.0, -6.0, -6.0, -10.0, -10.0, -10.0 };
      7. ArrayList<Double> khovidDaily = new ArrayList<>( Arrays.asList( khovidArray ) );
      8. ArrayList<Double> atWarDaily = new ArrayList<>( Arrays.asList( atWarArray ) );
      9. ArrayList<Double> civCasDaily = new ArrayList<>( Arrays.asList( civCasArray ) );
      10. ArrayList<Double> moraleHistory = new ArrayList<>( );
      11. moraleHistory.add( 0.70 ); // Day 1 morale of all Cities
      12. double moralePropagationFactor = (1 - ( 1.0 / 6 ) );
      13. double moraleTarget = 0.90;
      14. double moraleBonus = 0.0;
      15. double distanceToCapitol = -0.0;
      16. System.out.printf( "Morale Tgt = %7.3f, Morale Bonus = %7.3f, Dist2Cap = %7.3f\n", moraleTarget, moraleBonus, distanceToCapitol );
      17. // 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
      18. System.out.printf( " NewDay AtWar CivCas Penalties AdjTgt OldMorale Diff Subtract Predicted Predicted NxtActual Error Error\n");
      19. for ( int day = 1; day <= 18; day++ )
      20. {
      21. double moralePenalty = distanceToCapitol + atWarDaily.get( day-1 ) + civCasDaily.get( day-1 );
      22. double adjustedTarget = moraleTarget + ( 0.01 * ( moralePenalty + moraleBonus ) );
      23. double oldMorale = moraleHistory.get( day - 1 );
      24. double difference = ( adjustedTarget - oldMorale );
      25. double subtraction = ( moralePropagationFactor * difference );
      26. double newMorale = adjustedTarget - subtraction;
      27. moraleHistory.add( newMorale );
      28. System.out.printf( "%10d%10.1f%10.1f%10.1f%10.1f%10.1f%10.1f%10.1f%10.1f%10.0f%10.0f%10.1f%10.0f\n",
      29. day, atWarDaily.get( day-1 ), civCasDaily.get( day-1 ),
      30. moralePenalty,100* adjustedTarget, 100*oldMorale,
      31. 100*difference, 100*subtraction,
      32. 100*newMorale, 100*newMorale,
      33. khovidDaily.get( day ),
      34. ( ( 100 * newMorale ) - khovidDaily.get( day ) ),
      35. ( ( 100 * newMorale ) - khovidDaily.get( day ) ) );
      36. }
      37. }
      Display All

      The post was edited 1 time, last by KFGauss ().