is it possible in C to combine lists of macros to generate an enum with every possible combination? Example:
#define REMAP_LIST R(FOE) R(ANY) R()
#define STATUS_LIST P(TRY) P() P(ABORT)
#define EVENT_LIST X(MOVE) X(HEAL)
Result:
enum e {
FOE_TRY_MOVE, FOE_TRY_HEAL, FOE_MOVE, FOE_HEAL, FOE_ABORT_MOVE, FOE_ABORT_HEAL,
ANY_TRY_MOVE, ANY_TRY_HEAL, ANY_MOVE, ANY_HEAL, ANY_ABORT_MOVE, ANY_ABORT_HEAL,
etc.
};
Defining everything manually would obviously be insane...
As @NateEldredge already mentioned, it would be best to use a bitfield.
For example:
struct bitfield {
unsigned int pov:2; //2 bits, 2^2 states -> 0: any, 1: foe, 2: me
unsigned int event:1; //1 bit, 2 states -> 0: move, 1: heal
unsigned int step:2; //2 bits, 2^2 states -> 0: none, 1: try, 2: hold, 3: exec
};
Then define some constants:
//character types
#define ANY 0
#define FOE 1
#define ME 2
//actions
#define MOVE 0
#define HEAL 1
//state
#define NONE 0
#define TRY 1
#define HOLD 2
#define EXECUTE 3
Usage:
//FOE_TRY_MOVE
struct bitfield b;
b.pov = FOE;
b.event = MOVE;
b.step = TRY;
In the comments below you mentioned string maps, here is an example to print a bitfield (similar steps if you want to create a string).
const char *pov_strings[] = {"ANY", "FOE", "ME"};
const char *event_strings[] = {"MOVE", "HEAL"};
const char *step_strings[] = {"NONE", "TRY", "HOLD", "EXECUTE"};
void print_bitfield(struct bitfield b)
{
printf("%s_%s", pov_strings[b.pov], event_strings[b.event]);
if (b.step) {
printf("_%s", step_strings[b.step]);
}
}
Of course to answer the question, here the macro version for generating the enumerator list.
The idea is, that each POV is combined with a set of Events and additional Steps. The assumption is, that each POV has the same Events and Steps.
//concatenate A and B
#define CAT_(A, B) A##B
#define CAT(A, B) CAT_(A, B)
//concat pov and evt with an underscore separator
//expands to: POV_EVT
#define POV_EVENT(POV, EVT) \
CAT(CAT(POV, _), EVT)
//concat pov, evt and step with an underscore separator
//expands to: POV_EVT_STEP
#define POV_EVENT_STEP(POV, EVT, STEP) \
CAT(CAT(POV_EVENT(POV, EVT), _), STEP)
//generates the steps of the combinations of POV_EVT
#define EVENT_LIST(POV, EVT) \
POV_EVENT(POV, EVT), \
POV_EVENT_STEP(POV, EVT, TRY), \
POV_EVENT_STEP(POV, EVT, HOLD), \
POV_EVENT_STEP(POV, EVT, EXECUTE)
//generates the events of POV
#define POV_LIST(POV) \
EVENT_LIST(POV, MOVE), \
EVENT_LIST(POV, HEAL)
//generate the enum
enum e {
POV_LIST(ANY),
POV_LIST(FOE),
POV_LIST(ME)
};
which expands to
enum e {
ANY_MOVE,
ANY_MOVE_TRY,
ANY_MOVE_HOLD,
ANY_MOVE_EXECUTE,
ANY_HEAL,
ANY_HEAL_TRY,
ANY_HEAL_HOLD,
ANY_HEAL_EXECUTE,
FOE_MOVE,
FOE_MOVE_TRY,
FOE_MOVE_HOLD,
FOE_MOVE_EXECUTE,
FOE_HEAL,
FOE_HEAL_TRY,
FOE_HEAL_HOLD,
FOE_HEAL_EXECUTE,
ME_MOVE,
ME_MOVE_TRY,
ME_MOVE_HOLD,
ME_MOVE_EXECUTE,
ME_HEAL,
ME_HEAL_TRY,
ME_HEAL_HOLD,
ME_HEAL_EXECUTE
};