For the tactical AI of our turn based strategy game we use an approach inspired by utility-based decision making. Here is a simplified explanation:
Each AI Action (i.e. Attack, Advance, Hide) has a list of Considerations and an Execute routine.
Each Consideration is a relatively simple function that takes some parameters (i.e. the tested position, the unit that is tested, etc.) and returns a normalized floating point score (from zero to one). Some example Considerations are ConsiderDamage, ConsiderAnyTargets, ConsiderAdvanceImprovement, ConsiderUnitsSpread, ConsiderSafePath, ConsiderSafeSpot etc.
The AI evaluates all possible Actions at all available positions (i.e. in movement range) by invoking all Considerations for each Action/Position pair, and combining Consideration results by multiplying them. This product is the score for the Action/Position pair.
A boost can be applied to pair scores by multiplication, so some actions are preferred to others. For example in our game the MoveThenAttack action has a boost value a few times higher than the Roam and Advance actions, so MoveThenAttack is almost always preferred by the AI if there is an opportunity for an actual attack at a given position.
Finally the AI picks the Action/Position with the highest score and invokes the Action's Execute routine at Position.
Here are some talks on utility-based game AI: