void ForwardConv2DStateActionFeaturizer::featurize_unit()

in featurizers/forward_conv2d_state_action_featurizer.cpp [89:189]


void ForwardConv2DStateActionFeaturizer::featurize_unit(
        Vector<Feature> &feats,
        Unit &u,
        bool is_enemy,
        std::function<Unit*(int32_t)> get_unit_fn) {
    feats.emplace_back();
    auto feat = &feats.back();
    feat->feats.resize(feature_size);

    // Add unit features on tile of unit
    feat->x = u.x; feat->y = u.y;
    feat->our_type = u.type;
    feat->feats[IS_UNIT] = 1;
    feat->feats[IS_ENEMY] = is_enemy ? 1 : -1;
    feat->feats[CD] = u.groundCD / div_cd;
    feat->feats[MAXCD] = u.maxCD / div_cd;
    feat->feats[ARMOR] = u.armor;
    feat->feats[VELOCITY_X] = u.velocityX;
    feat->feats[VELOCITY_Y] = u.velocityY;
    if (is_enemy) feat->feats[ENEMY_HEALTH] = (u.health + u.shield) / div_hp;
    else feat->feats[ALLY_HEALTH] = (u.health + u.shield) / div_hp;
    feat->feats[IS_EVALUATING] = -1; // Never true for forward model

    auto first_frame = u.orders[0].first_frame;
    auto last_frame = first_frame + skip_frames - 1;
    if (!is_enemy) last_frame++;

    for (size_t i = 0; i < u.orders.size(); i++) {
        auto order = u.orders[i];
        // Skip duplicate orders
        if (i != 0 and order == u.orders[u.orders.size()-1]) continue;

        auto dX = order.targetX - u.x;
        auto dY = order.targetY - u.y;
        auto dist = sqrt(dX*dX + dY*dY);
        auto o_last_frame = (i == u.orders.size() - 1)
            ? last_frame
            : u.orders[i+1].first_frame - 1;
        auto typ = u.type + 1;
        auto otyp = order.type + 1;

        feats.emplace_back(); feat = &feats.back();
        feat->feats.resize(feature_size);
        feat->x = u.x; feat->y = u.y;
        feat->our_type = typ;
        feat->our_order = otyp;

        feat->feats[IS_ORDER]    = 1;
        feat->feats[IS_ENEMY]    = is_enemy ? 1 : -1;
        feat->feats[CD]          = u.groundCD / div_cd;
        feat->feats[VELOCITY_X]  = u.velocityX;
        feat->feats[VELOCITY_Y]  = u.velocityY;
        feat->feats[TARGET_X]    = (order.targetId != -1) ? dX / div_coord : 0;
        feat->feats[TARGET_Y]    = (order.targetId != -1) ? dY / div_coord : 0;
        feat->feats[GWATTACK]    = u.groundATK / div_dmg;
        feat->feats[GWDMGTYPE + u.groundDmgType] = 1;
        feat->feats[GWRANGE]     = u.groundRange / div_coord;
        feat->feats[AWATTACK]    = u.airATK / div_dmg;
        feat->feats[AWDMGTYPE + u.airDmgType] = 1;
        feat->feats[AWRANGE]     = u.airRange / div_coord;
        feat->feats[TARGET_DIST] = (order.targetId != -1) ? dist : 0;
        for (int k = order.first_frame - first_frame;
                k < o_last_frame - first_frame + 1;
                k++) feat->feats[ORDER_FRAMES + k] = 1;
        // Never true for forward models TODO Change for policy models
        feat->feats[IS_EVALUATING]     = -1;
        feat->feats[IS_EVALUATING_ORD] = -1;
        feat->feats[IS_EVALUATED_ORD]  = -1;

        if (order.targetId == -1) continue;
        // Only if we have a target

        feats.emplace_back(); feat = &feats.back();
        feat->feats.resize(feature_size);
        feat->x                        = order.targetX;
        feat->y                        = order.targetY;
        feat->their_type               = typ;
        feat->their_order              = otyp;
        feat->feats[IS_ORDER_TARGET]   = 1;
        feat->feats[IS_SOURCE_ENEMY]   = is_enemy ? 1 : -1;
        feat->feats[SOURCE_X]          = dX / div_coord;
        feat->feats[SOURCE_Y]          = dY / div_coord;
        feat->feats[SOURCE_DIST]       = dist;
        feat->feats[SOURCE_CD]         = u.groundCD / div_cd;
        feat->feats[SOURCE_GWATTACK]   = u.groundATK / div_dmg;
        feat->feats[SOURCE_GWDMGTYPE + u.groundDmgType] = 1;
        feat->feats[SOURCE_GWRANGE]    = u.groundRange / div_coord;
        feat->feats[SOURCE_AWATTACK]   = u.airATK / div_dmg;
        feat->feats[SOURCE_AWDMGTYPE + u.airDmgType] = 1;
        feat->feats[SOURCE_AWRANGE]    = u.airRange / div_coord;
        feat->feats[SOURCE_VELOCITY_X] = u.velocityX;
        feat->feats[SOURCE_VELOCITY_Y] = u.velocityY;
        for (int k = order.first_frame - first_frame;
                k < o_last_frame - first_frame + 1;
                k++) feat->feats[ORDER_FRAMES + k] = 1;
        // Never true for forward models TODO Change for policy models
        feat->feats[SOURCE_IS_EVALUATING]      = -1;
        feat->feats[SOURCE_IS_EVALUATING_ORD]  = -1;
        feat->feats[SOURCE_IS_EVALUATED_ORD]   = -1;
    }
}