bool MCRuleActor::ActByState()

in rts/game_MC/mc_rule_actor.cc [27:166]


bool MCRuleActor::ActByState(const GameEnv &env, const vector<int>& state, string *state_string, AssignedCmds *assigned_cmds) {
    // Each unit can only have one command. So we have this map.
    // cout << "Enter ActByState" << endl << flush;
    assigned_cmds->clear();
    *state_string = "NOOP";

    // Build workers.
    if (state[STATE_BUILD_WORKER]) {
        *state_string = "Build worker..NOOP";
        const Unit *base = _preload.Base();
        if (IsIdle(*_receiver, *base)) {
            if (_preload.BuildIfAffordable(WORKER)) {
                *state_string = "Build worker..Success";
                store_cmd(base, _B(WORKER), assigned_cmds);
            }
        }
    }

    const auto& my_troops = _preload.MyTroops();

    // Ask workers to gather.
    for (const Unit *u : my_troops[WORKER]) {
        if (IsIdle(*_receiver, *u)) {
            // Gather!
            store_cmd(u, _preload.GetGatherCmd(), assigned_cmds);
        }
    }

    // If resource permit, build barracks.
    if (state[STATE_BUILD_BARRACK]) {
        *state_string = "Build barracks..NOOP";
        if (_preload.Affordable(BARRACKS)) {
            // cout << "Building barracks!" << endl;
            const Unit *u = GameEnv::PickFirst(my_troops[WORKER], *_receiver, GATHER);
            if (u != nullptr) {
                CmdBPtr cmd = _preload.GetBuildBarracksCmd(env);
                if (cmd != nullptr) {
                    *state_string = "Build barracks..Success";
                    store_cmd(u, std::move(cmd), assigned_cmds);
                    _preload.Build(BARRACKS);
                }
            }
        }
    }

    // If we have barracks with resource, build troops.
    if (state[STATE_BUILD_MELEE_TROOP]) {
        *state_string = "Build Melee Troop..NOOP";
        if (_preload.Affordable(MELEE_ATTACKER)) {
            const Unit *u = GameEnv::PickFirstIdle(my_troops[BARRACKS], *_receiver);
            if (u != nullptr) {
                *state_string = "Build Melee Troop..Success";
                store_cmd(u, _B(MELEE_ATTACKER), assigned_cmds);
                _preload.Build(MELEE_ATTACKER);
            }
        }
    }

    if (state[STATE_BUILD_RANGE_TROOP]) {
        *state_string = "Build Range Troop..NOOP";
        if (_preload.Affordable(RANGE_ATTACKER)) {
            const Unit *u = GameEnv::PickFirstIdle(my_troops[BARRACKS], *_receiver);
            if (u != nullptr) {
                *state_string = "Build Range Troop..Success";
                store_cmd(u, _B(RANGE_ATTACKER), assigned_cmds);
                _preload.Build(RANGE_ATTACKER);
            }
        }
    }

    if (state[STATE_ATTACK]) {
        *state_string = "Attack..Normal";
        // Then let's go and fight.
        auto cmd = _preload.GetAttackEnemyBaseCmd();
        batch_store_cmds(my_troops[MELEE_ATTACKER], cmd, false, assigned_cmds);
        batch_store_cmds(my_troops[RANGE_ATTACKER], cmd, false, assigned_cmds);
    }

    const auto& enemy_troops = _preload.EnemyTroops();
    const auto& enemy_troops_in_range = _preload.EnemyTroopsInRange();
    const auto& all_my_troops = _preload.AllMyTroops();
    const auto& enemy_attacking_economy = _preload.EnemyAttackingEconomy();

    if (state[STATE_HIT_AND_RUN]) {
        *state_string = "Hit and run";
        // cout << "Enter hit and run procedure" << endl << flush;
        if (enemy_troops[MELEE_ATTACKER].empty() && enemy_troops[RANGE_ATTACKER].empty() && ! enemy_troops[WORKER].empty()) {
            // cout << "Enemy only have worker" << endl << flush;
            for (const Unit *u : my_troops[RANGE_ATTACKER]) {
                hit_and_run(env, u, enemy_troops[WORKER], assigned_cmds);
            }
        }
        if (! enemy_troops[MELEE_ATTACKER].empty()) {
            // cout << "Enemy only have malee attacker" << endl << flush;
            for (const Unit *u : my_troops[RANGE_ATTACKER]) {
                hit_and_run(env, u, enemy_troops[MELEE_ATTACKER], assigned_cmds);
            }
        }
        if (! enemy_troops[RANGE_ATTACKER].empty()) {
            auto cmd = _A(enemy_troops[RANGE_ATTACKER][0]->GetId());
            batch_store_cmds(my_troops[MELEE_ATTACKER], cmd, false, assigned_cmds);
            batch_store_cmds(my_troops[RANGE_ATTACKER], cmd, false, assigned_cmds);
        }
    }

    if (state[STATE_ATTACK_IN_RANGE]) {
      *state_string = "Attack enemy in range..NOOP";
      if (! enemy_troops_in_range.empty()) {
        *state_string = "Attack enemy in range..Success";
        auto cmd = _A(enemy_troops_in_range[0]->GetId());
        batch_store_cmds(my_troops[MELEE_ATTACKER], cmd, false, assigned_cmds);
        batch_store_cmds(my_troops[RANGE_ATTACKER], cmd, false, assigned_cmds);
      }
    }

    if (state[STATE_DEFEND]) {
      // Group Retaliation. All troops attack.
      *state_string = "Defend enemy attack..NOOP";

      const Unit *enemy_at_resource = _preload.EnemyAtResource();
      if (enemy_at_resource != nullptr) {
          *state_string = "Defend enemy attack..Success";
          batch_store_cmds(all_my_troops, _A(enemy_at_resource->GetId()), true, assigned_cmds);
      }

      const Unit *enemy_at_base = _preload.EnemyAtBase();
      if (enemy_at_base != nullptr) {
          *state_string = "Defend enemy attack..Success";
          batch_store_cmds(all_my_troops, _A(enemy_at_base->GetId()), true, assigned_cmds);
      }

      if (! enemy_attacking_economy.empty()) {
        *state_string = "Defend enemy attack..Success";
        auto it = enemy_attacking_economy.begin();
        auto cmd = _A((*it)->GetId());
        batch_store_cmds(all_my_troops, cmd, true, assigned_cmds);
      }
    }
    return true;
}