1def opening(ai*) 2 if(turn = 1, [ 3 recruit('Skeleton Archer', loc(11,21)), 4 recruit('Dark Adept', loc(11,22)), 5 recruit('Dark Adept', loc(10,22)), 6 recruit('Skeleton Archer', loc(9,22)), 7 recruit('Ghost', loc(11,24)), 8 move(loc(11,23), loc(14,22)) ], 9 if(turn = 2, [ 10 move(loc(11,21),loc(13,17)), 11 if(unit_at(loc(11,22)).max_moves = 6, 12 move(loc(11,22),loc(13,18)), 13 move(loc(11,22),loc(15,19))), 14 move(loc(10,22),loc(7,19)), 15 move(loc(9,22),loc(4,22)), 16 move(loc(11,24),loc(18,24)), 17 move(loc(14,22),loc(11,23)), 18 recruit('Dark Adept', loc(11,21)), 19 recruit('Dark Adept', loc(11,22)) ], 20 if(turn = 3, [ 21 move(loc(18,24),loc(20,22)), 22 move(loc(15,19),loc(17,17)), 23 move(loc(4,22),loc(5,18)), 24 recruit('Skeleton Archer', loc(11,21)) ], 25 if(turn = 4, [ 26 recruit('Skeleton Archer', loc(11,21)) ], 27 [])))); 28 29def rate_position_defensiveness(ai*,src,dst) 30 units_can_reach(ai.my_moves, dst).size - units_can_reach(ai.enemy_moves, dst).size; 31 32def rate_position_danger(ai*,unit,dst) 33 (100*sum(map(units_can_reach(ai.enemy_moves, dst), 'enemy', max_possible_damage(enemy, unit)*defense_on(unit, dst)))) / unit.hitpoints; 34 35def build_attacks(attack_move) 36 if(attack_move, 37 map(attack_move.movements, attack(src, dst, attack_move.target)), 38 []); def targets(ai) 39 ai.enemy_and_unowned_villages; 40 41def distance_to_target(ai,dst) 42 min(map(targets(ai), distance_between(dst, self))); 43 44def move_to_targets(ai*) 45 find(moves, src != my_leader.loc and rate_position_defensiveness(ai, src, dst) > 0) 46 where moves = sort(my_moves.moves, distance_to_target(ai, a.dst) < distance_to_target(ai, b.dst)); 47 48def get_village_captures(ai) 49 sum(map(ai.enemy_and_unowned_villages, 'village', map(units_can_reach(ai.my_moves, village), move(loc, village))), []); 50 51def get_village_garrisons(ai*) 52 sum(map(my_villages, 'village', map(units_can_reach(ai.my_moves, village), move(loc, village))), []); 53 54def uncontended_captures(ai) 55 filter(get_village_captures(ai), (src != ai.my_leader.loc) and (units_can_reach(ai.enemy_moves, dst).empty)); 56 57def move_to_keep(ai*) 58 if(keep_in_range, 59 move(my_leader.loc, keep_in_range), 60 null()) 61 where keep_in_range = find(unit_moves(my_leader.loc), 'moveto', find(keeps, moveto = self)); 62 63def village_value(ai*) 400; 64 65def rate_healing(unit*) 66 value * ((min(max_hitpoints - hitpoints, 8)*100)/max_hitpoints); 67 68def rate_village_garrison(ai*, move_from, village) 69 if(find(enemy_moves, dst = village), 70 village_value(ai), 71 0); 72 73def rate_village_capture(ai*,src,dst) village_value(ai); 74 75def rate_village_proximity(ai*, unit, dst) 76 if(distance = 1, 77 0, 78 village_value(ai)/(distance/unit.max_moves + 1)) 79 where distance = distance_to_nearest_unowned_village(dst); 80 81def rate_move(ai*,src,dst) 82 if(is_village(map, dst), 83 rate_healing(u) + if(find(my_villages, self = dst), 84 rate_village_garrison(ai, src, dst), 85 rate_village_capture(ai, src, dst)), 86 rate_village_proximity(ai, u, dst)) - (danger*u.value)/2 87 where u = unit_at(src), danger = rate_position_danger(ai, unit_at(src), dst); 88 89def rate_attack(ai*,attack) 90 if(attack, 91 (attack.chance_to_kill*attack.target_value + (((attack.avg_damage_inflicted*100)/unit_at(attack.target).max_hitpoints)*attack.target_value) + sum(map(attack.movements, rate_move(ai, src, dst))))/attack.movements.size, 92 null()); 93 94def get_best_move(ai*, candidate_moves) 95 if(rate_attack(ai, best_attack) > 96 if(best_move, rate_move(ai, best_move.src, 97 best_move.dst), 98 0), 99 build_attacks(best_attack), 100 [best_move]) 101 where best_attack = choose(attacks, rate_attack(ai, self)), 102 best_move = choose(candidate_moves, rate_move(ai, src, dst)); 103 104def move_leader_to_keep(ai*) 105 if(dest, 106 [move(my_leader.loc, dest)], 107 []) 108 where dest = find(unit_moves(my_leader.loc), 'dst', find(keeps, 'keep', keep = dst)); 109 110if(vars.turn_opening != turn, 111 [set_var('turn_opening', turn)] + opening(self), 112if(my_leader.loc and find(keeps, self = my_leader.loc) = null(), 113 move_leader_to_keep(self), 114[]) + get_best_move(self, filter(my_moves.moves, src != my_leader.loc)) + [ recruit('Skeleton Archer', loc(11,21)), recruit('Dark Adept', loc(11,22)) ]) 115