Cancel an attack
In this guide, we will learn how to cancel one of our ongoing attacks, equivalent to clicking the red cross next to an attack in the game chat. We will use the Controller.cancel_attack method.
The cancel_attack method takes an AttackID. You can get this ID from one of your own ongoing attacks in state.me.ongoingAttacks (see SimplifiedAttack).
In the example below, if we are under pressure (incoming attacks) and we have very few idle troops left, we cancel our largest ongoing attack to free troops faster.
python
# If we are being attacked and running low on idle troops, retreat one attack.
if len(state.me.incomingAttacks) > 0 and state.me.idleTroops < state.me.maxTroops * 0.15:
if len(state.me.ongoingAttacks) > 0:
attack_to_cancel = max(state.me.ongoingAttacks, key=lambda atk: atk.troops)
await controller.cancel_attack(attack_to_cancel.attackID)java
// If we are being attacked and running low on idle troops, retreat one attack.
if (!state.me.incomingAttacks.isEmpty() && state.me.idleTroops < state.me.maxTroops * 0.15) {
if (!state.me.ongoingAttacks.isEmpty()) {
SimplifiedAttack attackToCancel = null;
double mostTroops = -1;
for (SimplifiedAttack attack : state.me.ongoingAttacks) {
if (attack.troops > mostTroops) {
mostTroops = attack.troops;
attackToCancel = attack;
}
}
if (attackToCancel != null) {
controller.cancelAttack(attackToCancel.attackID);
}
}
}Note that cancelling an attack is not free: part of the troops will be lost during retreat, and the rest will return to your idle troops.
Possible improvements:
- Cancel attacks targeting strong players first, and keep attacks targeting
None/nullto continue free expansion. - Cancel attacks with the largest
borderSizefirst if you want to reduce overextension. - Combine this with your alliance and quick chat logic to ask for help before retreating.
