Program: 55857
Project: 55857
Buggy source:
@Override protected void action(){
switch (state) {
case AGGRESSIVE:
    break;
case HITTING:
  if (!isEnemyAttackable(enemy,isInTower)) {
    changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
  }
 else {
    hitEnemy(enemy);
    if (state != ESoldierState.HITTING) {
      break;
    }
    if (enemy.getHealth() <= 0) {
      enemy=null;
      changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
      break;
    }
  }
changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
case SEARCH_FOR_ENEMIES:
final short minSearchDistance=getMinSearchDistance();
IAttackable oldEnemy=enemy;
enemy=super.getGrid().getEnemyInSearchArea(getAttackPosition(),movable,minSearchDistance,getMaxSearchDistance(isInTower),!defending);
if (oldEnemy != null && oldEnemy != enemy) {
inSaveGotoMode=false;
}
if (enemy == null) {
if (minSearchDistance > 0) {
IAttackable toCloseEnemy=super.getGrid().getEnemyInSearchArea(getAttackPosition(),movable,(short)0,minSearchDistance,!defending);
if (toCloseEnemy != null) {
if (!isInTower) {
EDirection escapeDirection=EDirection.getApproxDirection(toCloseEnemy.getPos(),movable.getPos());
super.goInDirection(escapeDirection,false);
movable.moveTo(null);
}
break;
}
}
if (defending) {
building.towerDefended(this);
defending=false;
}
changeStateTo(ESoldierState.AGGRESSIVE);
}
 else if (isEnemyAttackable(enemy,isInTower)) {
super.lookInDirection(EDirection.getApproxDirection(movable.getPos(),enemy.getPos()));
startAttackAnimation(enemy);
changeStateTo(ESoldierState.HITTING);
}
 else if (!isInTower) {
changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
goToEnemy(enemy);
}
 else {
changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
}
break;
case INIT_GOTO_TOWER:
changeStateTo(ESoldierState.GOING_TO_TOWER);
if (!movable.getPos().equals(building.getDoor()) && !super.goToPos(building.getDoor())) {
notifyTowerThatRequestFailed();
}
break;
case GOING_TO_TOWER:
if (building.isNotDestroyed() && building.getPlayer() == movable.getPlayer()) {
OccupyerPlace place=building.addSoldier(this);
super.setPosition(place.getPosition().calculatePoint(building.getDoor()));
super.enableNothingToDoAction(false);
super.setVisible(false);
if (isBowman()) {
this.inTowerAttackPosition=building.getTowerBowmanSearchPosition(place);
}
changeStateTo(ESoldierState.AGGRESSIVE);
isInTower=true;
}
 else {
changeStateTo(ESoldierState.AGGRESSIVE);
building=null;
}
break;
}
}

Fixed version (ground truth):
@Override protected void action(){
switch (state) {
case AGGRESSIVE:
    break;
case HITTING:
  if (!isEnemyAttackable(enemy,isInTower)) {
    changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
  }
 else {
    hitEnemy(enemy);
    if (state != ESoldierState.HITTING) {
      break;
    }
    if (enemy.getHealth() <= 0) {
      enemy=null;
      changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
      break;
    }
  }
changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
case SEARCH_FOR_ENEMIES:
final short minSearchDistance=getMinSearchDistance();
IAttackable oldEnemy=enemy;
enemy=super.getGrid().getEnemyInSearchArea(getAttackPosition(),movable,minSearchDistance,getMaxSearchDistance(isInTower),!defending);
if (oldEnemy != null && oldEnemy != enemy) {
inSaveGotoMode=false;
}
if (enemy == null) {
if (minSearchDistance > 0) {
IAttackable toCloseEnemy=super.getGrid().getEnemyInSearchArea(getAttackPosition(),movable,(short)0,minSearchDistance,!defending);
if (toCloseEnemy != null) {
if (!isInTower) {
EDirection escapeDirection=EDirection.getApproxDirection(toCloseEnemy.getPos(),movable.getPos());
super.goInDirection(escapeDirection,EGoInDirectionMode.GO_IF_ALLOWED_AND_FREE);
movable.moveTo(null);
}
break;
}
}
if (defending) {
building.towerDefended(this);
defending=false;
}
changeStateTo(ESoldierState.AGGRESSIVE);
}
 else if (isEnemyAttackable(enemy,isInTower)) {
super.lookInDirection(EDirection.getApproxDirection(movable.getPos(),enemy.getPos()));
startAttackAnimation(enemy);
changeStateTo(ESoldierState.HITTING);
}
 else if (!isInTower) {
changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
goToEnemy(enemy);
}
 else {
changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES);
}
break;
case INIT_GOTO_TOWER:
changeStateTo(ESoldierState.GOING_TO_TOWER);
if (!movable.getPos().equals(building.getDoor()) && !super.goToPos(building.getDoor())) {
notifyTowerThatRequestFailed();
}
break;
case GOING_TO_TOWER:
if (building.isNotDestroyed() && building.getPlayer() == movable.getPlayer()) {
OccupyerPlace place=building.addSoldier(this);
super.setPosition(place.getPosition().calculatePoint(building.getDoor()));
super.enableNothingToDoAction(false);
super.setVisible(false);
if (isBowman()) {
this.inTowerAttackPosition=building.getTowerBowmanSearchPosition(place);
}
changeStateTo(ESoldierState.AGGRESSIVE);
isInTower=true;
}
 else {
changeStateTo(ESoldierState.AGGRESSIVE);
building=null;
}
break;
}
}