Good OOP practices: Polymorphism and Encapsulation

Here is a simpler version, but not terribly OO:

#include <iostream>
#include <map>

struct Contender{
    enum class Thing {_, Rock, Scissors, Paper};
    using StatusMap = std::map<Thing,bool>;

    float _strength = 1.0;
    Thing _thing;
    StatusMap _map;

    Contender(Thing t, StatusMap map): _thing(t), _map(map){}

    void adjustStrength(bool won){
        _strength *= (won)? 2.0 : .5; 
    }

    void challenge(Contender& c) {
        if (_thing != c._thing){
            //Should be more defensive here.
            bool win = c._map[_thing];
            adjustStrength(win);
            c.adjustStrength(!win);
        }
    }

    virtual ~Contender(){}
};

struct Rock : Contender {
    Rock() : Contender(Thing::Rock, StatusMap{
        {Thing::Scissors, false},
        {Thing::Paper, true}
    }){}

    ~Rock() override {}
};

struct Scissors : Contender {
    Scissors() : Contender(Thing::Scissors, StatusMap{
        {Thing::Rock, true},
        {Thing::Paper, false}
    }){}

    ~Scissors() override {}
};

struct Paper : Contender {
    Paper() : Contender(Thing::Paper, StatusMap{
        {Thing::Rock, false},
        {Thing::Scissors, true},
    }){}

    ~Paper() override {}
};

int main(){
    Rock r;
    Scissors s;
    Paper p;
    r.challenge(s);
    std::cout << r._strength << ":" << s._strength << "\n";
}
/r/cpp_questions Thread Parent