Path generation: To avoid clashes of creeps pathing through the same square, we can check if adjacent squares are already in a creep's planned path and weight them accordingly (+3 * plains) to see if it's cheaper to wait or go a different way.
Per-tick movement: We can perform moves one creep at a time, in priority order, canceling moves for lower-priority creeps that conflict with higher-priority moves
Path generation: To avoid clashes of creeps pathing through the same square, we can check if adjacent squares are already in a creep's planned path and weight them accordingly (+3 * plains) to see if it's cheaper to wait or go a different way.
Per-tick movement: We can perform moves one creep at a time, in priority order, canceling moves for lower-priority creeps that conflict with higher-priority moves