patterncppMinor
Design of class Location in a World in a universe
Viewed 0 times
designuniverseworldclasslocation
Problem
A
Here are some instances of
This is the design I've come up with to set all this up. Note that class
Originally, I only had
```
#include
#include
#include
enum PlaneEnum {MATERIAL_PLANE, SHADOW_PLANE, ABYSS, ARCADIA, NUM_PLANES};
enum RealmEnum {FORGOTTEN_REALMS, FAERUN, WATERDEEP, PAZUNIA, DRILLERS_HIVES,
FORGOTTEN_LAND, GRAND_ABYSS, NUM_REALMS};
class Plane {} MaterialPlane = new Plane, ShadowPlane = new Plane;
class OuterPlane : public Plane {} Abyss = new OuterPlane, Arcadia = new OuterPlane;
const std::array planes = {MaterialPlane, ShadowPlane, Abyss, Arcadia};
class Realm {
private:
const PlaneEnum planeEnum;
protected:
Realm (PlaneEnum p) : planeEnum(p) {}
public:
Plane* getPlane() const {return planes[planeEnum];}
};
class World : public Realm {
public:
World (PlaneEnum p) : Realm(
Plane of existence is like a universe in the multiverse. At first, I thought that a Plane will consist of many Worlds, and each World consists of many Locations. But it is not so simple.Here are some instances of
Planes:MaterialPlane: It has differentWorlds, as I originally understoodPlanesto be.
Arcadia: AnOuterPlane(derived fromPlane) that has 2Layers, which I suppose can be interpreted as Worlds, but has properties not found in Worlds.
Abyss: Similar to Arcadia, but has an infinite number of Layers.
TemporalPlane: It hasTemporalWorlds, where time has changed, but the physical location has not. Not a very clear description, but that's what I found.
ShadowPlane: No worlds, no layers, no subplanes, but has regions that continually flow onto other planes. Not a very clear description, but that's what I found.
Neth: A plane that has no substructure, and is a plane that is actually living.
This is the design I've come up with to set all this up. Note that class
Location has already been defined and used extensively in my program, as does the class World.Originally, I only had
Location that was attached to a World. This is what I'm planning to expand this to.```
#include
#include
#include
enum PlaneEnum {MATERIAL_PLANE, SHADOW_PLANE, ABYSS, ARCADIA, NUM_PLANES};
enum RealmEnum {FORGOTTEN_REALMS, FAERUN, WATERDEEP, PAZUNIA, DRILLERS_HIVES,
FORGOTTEN_LAND, GRAND_ABYSS, NUM_REALMS};
class Plane {} MaterialPlane = new Plane, ShadowPlane = new Plane;
class OuterPlane : public Plane {} Abyss = new OuterPlane, Arcadia = new OuterPlane;
const std::array planes = {MaterialPlane, ShadowPlane, Abyss, Arcadia};
class Realm {
private:
const PlaneEnum planeEnum;
protected:
Realm (PlaneEnum p) : planeEnum(p) {}
public:
Plane* getPlane() const {return planes[planeEnum];}
};
class World : public Realm {
public:
World (PlaneEnum p) : Realm(
Solution
You're suffering from an excess of mimesis here. You've done an impressive job of translating your fantasy setting from English prose into a C++ object model... but sadly that's not worth anything, because the computer will never appreciate it, and the player will never see it.
Let's start over, as if we were designing an adventure game program, instead of transcribing a worldbuilding session. We probably have a player (just one player, so we can just use a singleton named
Okay, so now we have all the mechanics that we need in order to put the player in a location and to move the player from one location to another.
But what about planes? How will we represent that certain locations belong to a given plane? Ah, well, that sounds like a table lookup.
Now we can express things such as
and even
None of this stuff requires a complicated object model; we're not trying to mirror a whole fantasy world in our adventure game program. Instead, we're trying to mirror just enough of it to manage the player's experience of being in that world. Any concept that doesn't directly affect the player's experience can be tossed out of the program.
And in case you're wondering,
Don't overcomplicate things. :)
Let's start over, as if we were designing an adventure game program, instead of transcribing a worldbuilding session. We probably have a player (just one player, so we can just use a singleton named
player to hold his data), and the player has a current location, right?enum Location : int {
FORGOTTEN_REALMS, FAERUN, WATERDEEP, PAZUNIA, DRILLERS_HIVES,
FORGOTTEN_LAND, GRAND_ABYSS, // ...
};
struct Player {
Location location;
// ...other stuff, like inventory and so on...
} player;
void newGame() {
player.location = GRAND_ABYSS;
}
void travel(Location newloc) {
player.location = newloc;
describe_surroundings();
}Okay, so now we have all the mechanics that we need in order to put the player in a location and to move the player from one location to another.
But what about planes? How will we represent that certain locations belong to a given plane? Ah, well, that sounds like a table lookup.
enum Plane : int {
MATERIAL_PLANE, SHADOW_PLANE, ABYSS, ARCADIA, // ...
};
struct LocationData {
Plane plane;
std::string description;
// ...
};
std::map locData = {
{ FORGOTTEN_REALMS, { MATERIAL_PLANE, "You wander in the Forgotten Realms." } },
{ FAERUN, { MATERIAL_PLANE, "You are welcomed in Faerun." } },
{ WATERDEEP, { MATERIAL_PLANE, "You explore Waterdeep." } },
{ PAZUNIA, { ABYSS, "You climb among the crags of Pazunia." } },
{ DRILLERS_HIVES, { ABYSS, "You skulk among the Drillers' Hives." } },
{ FORGOTTEN_LAND, { ABYSS, "You search the Forgotten Land." } },
{ GRAND_ABYSS, { ABYSS, "You fall swiftly through the Grand Abyss." } },
};Now we can express things such as
newGame();
assert(player.location == GRAND_ABYSS);
assert(locData[player.location].plane == ABYSS);
player.location = FAERUN; // travel to a new location
assert(locData[player.location].plane == MATERIAL_PLANE);and even
void travel(Location newloc) {
if (locData[player.location].plane != locData[newloc].plane) {
puts("You have no means of travel between the planes.");
} else {
player.location = newloc;
describe_surroundings();
}
}None of this stuff requires a complicated object model; we're not trying to mirror a whole fantasy world in our adventure game program. Instead, we're trying to mirror just enough of it to manage the player's experience of being in that world. Any concept that doesn't directly affect the player's experience can be tossed out of the program.
And in case you're wondering,
describe_surroundings() would be implemented something likevoid describe_surroundings() {
puts(locData[player.location].description);
}Don't overcomplicate things. :)
Code Snippets
enum Location : int {
FORGOTTEN_REALMS, FAERUN, WATERDEEP, PAZUNIA, DRILLERS_HIVES,
FORGOTTEN_LAND, GRAND_ABYSS, // ...
};
struct Player {
Location location;
// ...other stuff, like inventory and so on...
} player;
void newGame() {
player.location = GRAND_ABYSS;
}
void travel(Location newloc) {
player.location = newloc;
describe_surroundings();
}enum Plane : int {
MATERIAL_PLANE, SHADOW_PLANE, ABYSS, ARCADIA, // ...
};
struct LocationData {
Plane plane;
std::string description;
// ...
};
std::map<Location, LocationData> locData = {
{ FORGOTTEN_REALMS, { MATERIAL_PLANE, "You wander in the Forgotten Realms." } },
{ FAERUN, { MATERIAL_PLANE, "You are welcomed in Faerun." } },
{ WATERDEEP, { MATERIAL_PLANE, "You explore Waterdeep." } },
{ PAZUNIA, { ABYSS, "You climb among the crags of Pazunia." } },
{ DRILLERS_HIVES, { ABYSS, "You skulk among the Drillers' Hives." } },
{ FORGOTTEN_LAND, { ABYSS, "You search the Forgotten Land." } },
{ GRAND_ABYSS, { ABYSS, "You fall swiftly through the Grand Abyss." } },
};newGame();
assert(player.location == GRAND_ABYSS);
assert(locData[player.location].plane == ABYSS);
player.location = FAERUN; // travel to a new location
assert(locData[player.location].plane == MATERIAL_PLANE);void travel(Location newloc) {
if (locData[player.location].plane != locData[newloc].plane) {
puts("You have no means of travel between the planes.");
} else {
player.location = newloc;
describe_surroundings();
}
}void describe_surroundings() {
puts(locData[player.location].description);
}Context
StackExchange Code Review Q#98265, answer score: 4
Revisions (0)
No revisions yet.