I don't think we need a whole function `rules()`.  Consider a simple constant string we can print:
```
static auto const rules =
    "Rules:\n"
    "1. You are in a cave system (a dodecahedron) such that each cave connects to three other caves.\n"
    "2. Somewhere in the cave lives a dreadful monster - Wumpus.\n"
    "   He has sucker feet to cling to the walls of bottomless pits and is too heavy to be picked up by super-bats.\n"
    "   He also has has big teeth and will eat you if you are in the same room as him.\n"
    "3. In the cave system, two caves are bottomless pits. Step in cave with one = you are scattered into pieces (Game Over).\n"
    "4. Also, two caves contain super-bats, which will carry you off to a random cave.\n"
    "   Bats can carry you to any room, including Pit room and Wumpus room, which will result in death (Game Over).\n"
    "5. If the adjacent room to your position contains any of three events (Wumpus, bat, pit), you will be notified.\n"
    "6. Only one instance of event can spawn at a room, but Wumpus can move to both bat and pit rooms and remain there.\n"
    "7. You have 5 arrows.\n"
    "   When you think you know where the Wumpus is (or even if you don't) shoot an arrow into a room.\n"
    "   If you hit the Wumpus, he will die and you win the game (Game WON).\n"
    "8. If you miss, the Wumpus, who is also a very light sleeper:\n"
    "     1) Will wake up and move (75%) to one of his adjacent rooms, or\n"
    "     2) Will continue sleeping (25%).\n"
    "   Wumpus can move in your room, so you would become a delicious snack (Game Over).\n"
    "9. The arrows are magical, so you choose three destinations, knowing where they would fly.\n"
    "10. If all arrows are gone, you are defenceless and therefore die of panic (Game Over).\n"
    "\n"
    " Notes: \n"
    "1. If Wumpus moved to a bat room, then player also moved to this room (containing both bat and Wumpus already) -\n"
    "   bat logic activates, so you are saved...probably.\n"
    "GOOD LUCK, YUMMY HUMAN...\n"
    "\n";

int main()
{
    std::cout << rules;
```

(I also fixed the spelling and grammar there)

---
I don't see why we need to return `static_cast<int>(Heart::EXIT)` when the player doesn't want to play any more.  A simple `0`, or `EXIT_SUCCESS` from the standard library would be a better choice, since refusing to play shouldn't be an error condition.

---
I think that `labyrinth` should be a member of `Heart` rather than a global variable shared amongst all hearts.  We could initialise it directly, rather than needing `initializeRooms()`:
```
    vector<Room> labyrinth{{
            //Rooms 1 to 5
            Room{{2,5,8}}, Room{{1,3,10}}, Room{{2,4,12}}, Room{{3,5,14}}, Room{{1,4,6}},
            //Rooms 6 to 10
            Room{{5,7,15}}, Room{{6,8,17}}, Room{{1,7,9}}, Room{{8,10,18}}, Room{{2,9,11}},
            // Rooms 11 to 15
            Room{{10,12,19}}, Room{{3,11,13}}, Room{{12,14,20}}, Room{{4,13,15}}, Room{{6,14,16}},
            // Rooms 16 to 20
            Room{{15,17,20}}, Room{{7,16,18}}, Room{{9,17,19}}, Room{{11,18,20}}, Room{{13,16,19}},
        }};
```
There's an inconsistency in `Room`: we have `vector<int> adjRooms`, suggesting a room can be connected to any number of other rooms.  But everywhere else in the code assumes that `adjRooms.size()` is exactly 3.  Either we should have more general code, or we should replace the vector with an array of size 3.

That also makes the above initialiser simpler, because we could just provide 3 arguments to the `Room` constructor (e.g. `Room{2,5,8}`) instead of a vector instance.

----
(partial review - that's as far as I got when Real Life intervened).