ObjectTransition RecallDatabase::computeObjectTransitionSingleton(const vector<Game::StateInst> &states, int baseFrameIndex, const string &objectName)
{
    const Game::StateInst &curState = states[baseFrameIndex];
    const Game::StateInst &nextState = states[baseFrameIndex + 1];

    const Game::ObjectInst *mostRecentInst = nullptr;
    for (int frame = baseFrameIndex; !mostRecentInst && frame >= 0; frame--)
    {
        const auto &instances = states[frame].objects.find(objectName)->second;
        if (instances.size() > 0)
            mostRecentInst = &instances[0];
    }

    const vector<Game::ObjectInst> &nextInstances = nextState.objects.find(objectName)->second;

    ObjectTransition result;

    result.nextReward = nextState.reward;
    if (nextInstances.size() == 0)
    {
        result.nextAnimation = mostRecentInst ? mostRecentInst->segmentHash : 0;
        result.nextAlive = 0;
        result.velocity = vec2s(0, 0);
    }
    else //if (nextInstances.size() >= 1)
    {
        result.nextAnimation = nextInstances[0].segmentHash;
        result.nextAlive = 1;
        if (mostRecentInst == nullptr)
            result.velocity = vec2s(0, 0);
        else
            result.velocity = nextInstances[0].origin - mostRecentInst->origin;
    }
    return result;
}
Example #2
0
	Counter(Scene2::Texture &tex, const vec2f &at, const f32 &scale, const u32 &val)
		: Tex({	Scene2::Texture( tex, rectf(0,164, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(Stride,164, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(Stride*2,164, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(Stride*3,164, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(Stride*4,164, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(0,0, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(Stride,0, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(Stride*2,0, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(Stride*3,0, Stride, 164), vec2s(496,329)  ), 
			Scene2::Texture( tex, rectf(Stride*4,0, Stride, 164), vec2s(496,329)  )
	}), Value(val)
	{
		for( int i = 3; i--; ) {
			Spr[i].Size = vec2f(99, 164)*scale;
			Spr[i].Pos = at + vec2f(Spr[i].Size.x,0)*(f32)i;
			Spr[i].Tex = &Tex[0];
			Spr[i].Rotation = 0;
		}
	}
ObjectTransition ObjectSampleDataset::predictTransitionSingleton(AppState &state, const ReplayDatabase &replays, int testReplayIndex, const vector<Game::StateInst> &states, int baseFrameIndex, int action, const HistoryMetricWeights &metric) const
{
    if (objectName == "unnamed")
        return ObjectTransition();

    HistorySlotInfo slotInfo;
    for (auto &it : state.model.stateSpec.objects)
        slotInfo.objectNames.push_back(it.name);
    slotInfo.lines = HistoryMetricWeights().lines;
    
    ObjectHistory history = RecallDatabase::computeObjectHistorySingleton(state, states, baseFrameIndex, objectName, slotInfo);
    vector<ObjectSample*> candidates = getTransitionCandidates(history);

    if (state.dumpAllTransitions)
    {
        candidates = allSamples;
    }

    //cout << objectName << " candidates: " << candidates.size() << endl;
    /*if (candidates.size() == 1)
    {
        cout << "Singular candidate -- get more training data" << endl;
        candidates = allSamples;
    }*/

    ObjectTransition blankTransition;
    blankTransition.nextAlive = true;
    blankTransition.nextAnimation = 0;
    blankTransition.nextReward = 0;
    blankTransition.velocity = vec2s(0, 0);

    if (candidates.size() == 0)
    {
        cout << "No candidates found for " << objectName << endl;
        return blankTransition;
    }

    vector<ObjectSample*> bestSamples;
    double bestSamplesDist = std::numeric_limits<double>::max();

    ofstream dumpFile;
    if (state.dumpAllTransitions)
    {
        dumpFile.open(learningParams().ROMDatasetDir + "dump" + objectName + ".csv", ios::out);
        dumpFile << "selected action: " << action << endl;
        for (int history = 0; history <= 10; history++)
            dumpFile << "action" << history << ": " << states[max(0, (int)states.size() - 1 - history)].action << endl;
        dumpFile << "frame,action,padBPos,ballPos,trans-vy,barrier,velDist,animDist,actionDist,positionDist,contactPadADist,offsetPadADist,contactPadBDist,offsetPadBDist,lineConstraints,dist" << endl;
    }

    for (ObjectSample *sample : candidates)
    {
        /*if (sample->frame.toString() == "r1-f185")
        {
            int a = 5;
        }*/

        const vector<Game::StateInst> &candidateStates = replays.replays[sample->frame.replayIndex]->states;

        const double animationDist = AtariUtil::compareAnimationDescriptorDistSingleton(states, baseFrameIndex, candidateStates, sample->frame.frameIndex, objectName, learningParams().historyFrames);
        
        double actionDist = AtariUtil::compareActionDescriptorDist(states, baseFrameIndex, candidateStates, sample->frame.frameIndex, learningParams().historyFrames);
        if (sample->nextAction != action)
            actionDist++;

        const double positionDist = AtariUtil::comparePositionDescriptorDistSingleton(states, baseFrameIndex, candidateStates, sample->frame.frameIndex, objectName, learningParams().historyFrames);

        const double velocityDist = AtariUtil::compareVelocityDescriptorDistSingleton(states, baseFrameIndex, candidateStates, sample->frame.frameIndex, objectName, learningParams().historyFrames);

        const double contactPadADist = AtariUtil::compareContactDescriptorDistSingleton(state.segmentDatabase, states, baseFrameIndex, candidateStates, sample->frame.frameIndex, objectName, "padA");
        const double offsetPadADist = AtariUtil::compareOffsetDescriptorDistSingleton(state.segmentDatabase, states, baseFrameIndex, candidateStates, sample->frame.frameIndex, objectName, "padA");

        const double contactPadBDist = AtariUtil::compareContactDescriptorDistSingleton(state.segmentDatabase, states, baseFrameIndex, candidateStates, sample->frame.frameIndex, objectName, "padB");
        const double offsetPadBDist = AtariUtil::compareOffsetDescriptorDistSingleton(state.segmentDatabase, states, baseFrameIndex, candidateStates, sample->frame.frameIndex, objectName, "padB");
        
        const double lineConstraints = AtariUtil::compareLineConstraintsSingleton(states, baseFrameIndex, candidateStates, sample->frame.frameIndex, objectName, metric.lines);

        const double dist = velocityDist * metric.velocity +
                           animationDist * metric.animation +
                           actionDist * metric.action +
                           positionDist * metric.position +
                           contactPadADist * 20 +
                           offsetPadADist +
                           contactPadBDist * 20 +
                           offsetPadBDist +
                           lineConstraints;

        if (state.dumpAllTransitions)
        {
            dumpFile << sample->frame.toString() << ",";

            const Game::StateInst &stateInst = candidateStates[sample->frame.frameIndex];

            dumpFile << stateInst.action << ",";

            if (stateInst.objects.find("padB")->second.size() == 0)
                dumpFile << "dead,";
            else
                dumpFile << stateInst.objects.find("padB")->second[0].origin.toString("x") << ",";

            if (stateInst.objects.find("ball")->second.size() == 0)
                dumpFile << "dead,";
            else
                dumpFile << stateInst.objects.find("ball")->second[0].origin.toString("x") << ",";

            dumpFile << sample->transition.velocity.y << ",x,";
            
            dumpFile << velocityDist << ",";
            dumpFile << animationDist << ",";
            dumpFile << actionDist << ",";
            dumpFile << positionDist << ",";
            dumpFile << contactPadADist << ",";
            dumpFile << offsetPadADist << ",";
            dumpFile << contactPadBDist << ",";
            dumpFile << offsetPadBDist << ",";
            dumpFile << lineConstraints << ",";
            dumpFile << dist << endl;
        }
        
        if (sample->frame.replayIndex == testReplayIndex)
            continue;

        if (dist < bestSamplesDist)
            bestSamples.clear();
        
        if (dist <= bestSamplesDist)
        {
            bestSamples.push_back(sample);
            bestSamplesDist = dist;
        }
    }

    if (bestSamples.size() == 0)
    {
        cout << "No non-training samples found for " << objectName << endl;
        return blankTransition;
    }

    if (state.dumpAllTransitions)
    {
        dumpFile << "Best samples:" << endl;
        for (int i = 0; i < bestSamples.size(); i++)
        {
            dumpFile << i << "," << bestSamples[i]->frame.toString() << "," << bestSamples[i]->toString() << endl;
        }
    }

    if (Constants::transitionDebugging)
    {
        cout << "Best samples: " << bestSamples.size() << endl;
        for (int sampleIndex = 0; sampleIndex < min(2, (int)bestSamples.size()); sampleIndex++)
            cout << bestSamples[sampleIndex]->toString() << endl;
    }

    return bestSamples[0]->transition;
}