I did not describe that anywhere yet. But it involves some randomization: it starts by generating some 10 random positions with a filling fraction of 25%, where the pieces of a given color are 3 times more likely to be at their own back rank than on the far rank. Then it counts the number of moves the piece under test would have on every empty square in these positions, distinguishing captures from non-captures. It translates that to the number of reachable and attacked squares on an empty board using the filling fraction. (E.g. if it would on average have 1.5 captures while the board is 12.5% populated with enemy pieces, it counts 1.5/0.125=12 attacked squares. If I would count attacked squares on an empty board directly, sliders would get too many moves, and hoppers would not have any.) It does not only calculate the average number of moves of the piece this way, but also the standard deviation, and adds the latter to the average. (This to compensate for the effect that during play you put pieces on squares where they are active, and avoid bad squares.) From the thus calculated mobilities N I derive a piece value with the formula (33+0.7*N)*N (centi-Pawn), which takes account of average cooperativity between moves, where captures are weighted as 1.33 move, and non-captures as 0.67. (And locust captures have some extra weight.)
It is still far from perfect, but good enough for the level at which the AI of the diagram is intended to play.
I did not describe that anywhere yet. But it involves some randomization: it starts by generating some 10 random positions with a filling fraction of 25%, where the pieces of a given color are 3 times more likely to be at their own back rank than on the far rank. Then it counts the number of moves the piece under test would have on every empty square in these positions, distinguishing captures from non-captures. It translates that to the number of reachable and attacked squares on an empty board using the filling fraction. (E.g. if it would on average have 1.5 captures while the board is 12.5% populated with enemy pieces, it counts 1.5/0.125=12 attacked squares. If I would count attacked squares on an empty board directly, sliders would get too many moves, and hoppers would not have any.) It does not only calculate the average number of moves of the piece this way, but also the standard deviation, and adds the latter to the average. (This to compensate for the effect that during play you put pieces on squares where they are active, and avoid bad squares.) From the thus calculated mobilities N I derive a piece value with the formula (33+0.7*N)*N (centi-Pawn), which takes account of average cooperativity between moves, where captures are weighted as 1.33 move, and non-captures as 0.67. (And locust captures have some extra weight.)
It is still far from perfect, but good enough for the level at which the AI of the diagram is intended to play.