Apparent Intelligence


Begin groundwork for planning


  • Created Planner class and began moving relevant functionality that had been in visualisation classes over.
  • Created GetBestPlan method and implemented scoring functions for combined plan, FUP and SBF (Combined plan calls FUP and SBF scoring functions)
  • Experimented with different fitness functions (FUP, SBF and Combined)


Getting the candidate FUP and SBF locations to the planner was actually a bit more difficult than I anticipated. I have implemented it but it isnt in a clean way. I think it will need to be abstracted out further. Currently I have implemented it as a separate step inside the Planner class. This is clearly inefficient but preferable to an uglier implementation that tightly couples the Graph class or similar to the Planner class.

My plan for a cleaner implementation at this stage is to add in an event in the viewshed class which the Planner can tap into; something like OnViewshedValueAssigned(VectorInt2 coord) where the Planner class adds a callback where it will complete the current checks for candidate FUP/SBF eligibility.

The GetBestPlan method is currently a brute force method which checks every single FUP/SBF candidate combination and keeps track of the lowest score (currently the scoring is higher for poorer plans). This had some terrible results initially however with some massaging, some reasonable results are starting to appear. It is very clear that creating a highly robust fitness function is likely the most important element of this project. The intent will be to keep a small terrain and brute force plan until a reasonable fitness function is determined. Once that is established, it is reasonable to move onto the Evolutionary Algorithm element.

Code for the fitness function is as follows:

 public float ScorePlan(VectorInt2 fup, VectorInt2 sbf)
    float scoreFUP = ScoreFUP(fup);
    float scoreSBF = ScoreSBF(sbf);

    float comboScore;
    float fupAngle = MathHelper.AngleBetweenPoints(fup, PlanningParams.enemyCentralLocation, MathHelper.ANGLE_UNIT.DEGREES);
    float sbfAngle = MathHelper.AngleBetweenPoints(sbf, PlanningParams.enemyCentralLocation, MathHelper.ANGLE_UNIT.DEGREES);
    float angleBetween = MathHelper.AngleDifference(fupAngle, sbfAngle);
    float angleScore = (90 - angleBetween) * 0.1f;
    if (angleScore < 1) angleScore = 1; 
        comboScore = angleScore; 
    return (scoreFUP + scoreSBF) * comboScore;

public float ScoreFUP(VectorInt2 fup) 
    float score = PlanningParams.GetCostfield().CostAt(fup.X, fup.Y); 
    if (score > 200000)
        return float.MaxValue;

    score = MathHelper.SquareDist(fup, PlanningParams.enemyCentralLocation);
    return score;

 public float ScoreSBF(VectorInt2 sbf)
     float score = PlanningParams.GetCostfield().CostAt(sbf.X, sbf.Y);
     if (score > 2000000)
        return float.MaxValue;

     score = 25000 - MathHelper.SquareDist(sbf, PlanningParams.enemyCentralLocation);
     if (PlanningParams.terrainObj.HeightAt(sbf) > PlanningParams.terrainObj.HeightAt(PlanningParams.enemyCentralLocation))
        score *= 0.4f;

     return score;

A summary of the above:


  • If path cost greater than 200000 then return max value
    • This very loosly covers paths that go through line of sight. Currently a poor estimation and needs work, likely in the costfield class
  • Otherwise the cost is the distance between FUP and enemy location squared


  • As per FUP for costfield over 200000
  • Otherwise the score is the square distance subtracted from 25000
    • Very much a placeholder here
    • This gives an ideal distance (score of 0) of 500m
    • Should be absolute value otherwise greater distances will be negative score
  • If the height is greater than the enemy position, the score gets multiplied by 0.4
  • This means a smaller (better) score for positions higher than the enemy location


  • The angle is subtracted from 90 degrees (90 is ideal)
    • This is multiplied by 0.1 for weighting
    • Capped at 1 as a low value (The angle between function always returns positive value)
  • The combo score is the sum of the FUP and SBF score multiplied by the angle score
  • An angle closer to 90 degrees will be a smaller value multiplying the other values

This is all very ad hoc so far and more than a little bit of trial and error. It is slowly getting decent results though. It is approaching a point that the plan developed on the test terrain is somewhat tactically reasonable, as can be seen below.

3D isometric view of friendly and enemy position with route to SBF and FUP locations. Plan appears generally tactically sound.
The output of the Planner with the current fitness function. The position in the bottom right is the SBF and the position in the upper left is the FUP location

Much more work needs to be done though, with a range of different test maps.

As discussed above, things that will assist:

  • Incorporate event based node analysis for candidate locations (Optimisation)
  • Extend cost map to maintain a separate costing purely considering viewshed
  • Conditions for FUP/SBF to be accepted to be reviewed
  • More thorough mathematical analysis of fitness function.


3 hours (67 hours running total)


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s