Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I wrote some C code for working with some data for a game, I wanted to know what do you think and what could I do to improve it, what should I change, etc.

These are just some lines of the file, you can see the complete file at google code.

#ifndef _GAMEINT_H
#define _GAMEINT_H

#pragma pack( push, 1 )

typedef signed          __int8  int8_t;
typedef signed          __int16 int16_t;
typedef signed          __int32 int32_t;
typedef signed          __int64 int64_t;
typedef unsigned        __int8  uint8_t;
typedef unsigned        __int16 uint16_t;
typedef unsigned        __int32 uint32_t;
typedef unsigned        __int64 uint64_t;

//
// ------------------------- Character sex and sexual orientation (!!)-------------------------------------
typedef uint16_t CHARACTER_GENDER;      // 2 bits for gender and 2 bits for sexual orientation, everything else for padding
#define GENDER_MALE                     0x0001L
#define GENDER_FEMALE                   0x0002L
#define GENDER_ORIENTATION_MALE         0x0004L
#define GENDER_ORIENTATION_FEMALE       0x0008L
#define GENDER_RESERVED                 0xFFF0L

#define GENDER_ORIENTATION_BI           (GENDER_ORIENTATION_MALE | GENDER_ORIENTATION_FEMALE)
#define GENDER_HERMAPHRODITE            (GENDER_MALE | GENDER_FEMALE)

#define SET_GENDER( inout_GenderDescriptor, in_GenderToSet )    \
                ((CHARACTER_GENDER) ((inout_GenderDescriptor | in_GenderToSet) ? inout_GenderDescriptor : ( inout_GenderDescriptor |= in_GenderToSet ) ))
#define RESET_GENDER( inout_GenderDescriptor, in_GenderToReset )        \
                ((CHARACTER_GENDER) ((inout_GenderDescriptor | in_GenderToReset) ? ( inout_GenderDescriptor ^= in_GenderToReset ) : inout_GenderDescriptor ))
#define IS_GENDER( in_GenderDescriptor, in_Gender )             \
                ((bool)( in_GenderDescriptor | in_Gender ))

// ------------------------- Define bitfield values for races -------------------------------------
typedef uint16_t CHARACTER_RACE;        // 

#define RACE_HUMAN                      0x0001L 
#define RACE_DWARF                      0x0002L 
#define RACE_ELF                        0x0004L 
#define RACE_DRAGON                     0x0008L 

#define RACE_DEMON                      0x0010L 
#define RACE_GHOST                      0x0020L 
#define RACE_UNDEAD                     0x0040L 
#define RACE_ANGEL                      0x0080L 

#define RACE_PLANT                      0x0100L 
#define RACE_INSECT                     0x0200L 
#define RACE_FISH                       0x0400L 
#define RACE_REPTILE                    0x0800L 

#define RACE_BIRD                       0x1000L 
#define RACE_MAMMAL                     0x2000L 
#define RACE_ALIEN                      0x4000L 
#define RACE_ROBOT                      0x8000L 

#define RACE_IS_HUMAN( in_RaceDescriptor )      ((bool)( RACE_HUMAN     & in_RaceDescriptor ))
#define RACE_IS_DWARF( in_RaceDescriptor )      ((bool)( RACE_DWARF     & in_RaceDescriptor ))
#define RACE_IS_ELF( in_RaceDescriptor )        ((bool)( RACE_ELF       & in_RaceDescriptor ))
#define RACE_IS_DRAGON( in_RaceDescriptor )     ((bool)( RACE_DRAGON    & in_RaceDescriptor ))
#define RACE_IS_ANGEL( in_RaceDescriptor )      ((bool)( RACE_ANGEL     & in_RaceDescriptor ))  
#define RACE_IS_DEMON( in_RaceDescriptor )      ((bool)( RACE_DEMON     & in_RaceDescriptor ))
#define RACE_IS_GHOST( in_RaceDescriptor )      ((bool)( RACE_GHOST     & in_RaceDescriptor ))
#define RACE_IS_UNDEAD( in_RaceDescriptor )     ((bool)( RACE_UNDEAD    & in_RaceDescriptor ))

#define RACE_IS_PLANT( in_RaceDescriptor )      ((bool)( RACE_PLANT     & in_RaceDescriptor ))
#define RACE_IS_INSECT( in_RaceDescriptor )     ((bool)( RACE_INSECT    & in_RaceDescriptor ))
#define RACE_IS_FISH( in_RaceDescriptor )       ((bool)( RACE_FISH      & in_RaceDescriptor ))
#define RACE_IS_REPTILE( in_RaceDescriptor )    ((bool)( RACE_REPTILE   & in_RaceDescriptor ))
#define RACE_IS_BIRD( in_RaceDescriptor )       ((bool)( RACE_BIRD      & in_RaceDescriptor ))
#define RACE_IS_MAMMAL( in_RaceDescriptor )     ((bool)( RACE_MAMMAL    & in_RaceDescriptor ))
#define RACE_IS_ALIEN( in_RaceDescriptor )      ((bool)( RACE_ALIEN     & in_RaceDescriptor ))
#define RACE_IS_ROBOT( in_RaceDescriptor )      ((bool)( RACE_ROBOT     & in_RaceDescriptor ))

#define RACE_SET_HUMAN  ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_HUMAN     )
#define RACE_SET_DWARF  ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_DWARF     )
#define RACE_SET_ELF    ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_ELF       )
#define RACE_SET_DRAGON ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_DRAGON    )
#define RACE_SET_ANGEL  ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_ANGEL     )
#define RACE_SET_DEMON  ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_DEMON     )
#define RACE_SET_GHOST  ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_GHOST     )
#define RACE_SET_UNDEAD ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_UNDEAD    )

#define RACE_SET_PLANT  ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_PLANT     )
#define RACE_SET_INSECT ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_INSECT    )
#define RACE_SET_FISH   ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_FISH      )
#define RACE_SET_REPTILE( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_REPTILE   )
#define RACE_SET_BIRD   ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_BIRD      )
#define RACE_SET_MAMMAL ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_MAMMAL    )
#define RACE_SET_ALIEN  ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_ALIEN     )
#define RACE_SET_ROBOT  ( inout_RaceDescriptor )        (inout_RaceDescriptor |= RACE_ROBOT     )

#define SET_RACE( inout_RaceDescriptor, in_RaceToSet )  \
                ((CHARACTER_RACE) ((inout_RaceDescriptor | in_RaceToSet) ? inout_RaceDescriptor : ( inout_RaceDescriptor |= in_RaceToSet ) ))
#define RESET_RACE( inout_RaceDescriptor, in_RaceToReset )      \
                ((CHARACTER_RACE) ((inout_RaceDescriptor | in_RaceToReset) ? ( inout_RaceDescriptor ^= in_RaceToReset ) : inout_RaceDescriptor ))
#define IS_RACE( in_RaceDescriptor, in_Race )           \
                ((bool)( in_RaceDescriptor | in_Race ))



struct RaceInfo
{
   uint8_t IsHuman      :1;
   uint8_t IsDwarf      :1;
   uint8_t IsElf        :1;
   uint8_t IsDragon     :1;
   uint8_t IsAngel      :1;
   uint8_t IsDemon      :1;
   uint8_t IsGhost      :1;
   uint8_t IsUndead     :1;

   uint8_t IsPlant      :1;
   uint8_t IsInsect     :1;
   uint8_t IsFish       :1;
   uint8_t IsReptile    :1;
   uint8_t IsBird       :1;
   uint8_t IsMammal     :1;
   uint8_t IsAlien      :1;
   uint8_t IsRobot      :1;
};
// ------------------------- Character professions -------------------------------------
typedef uint16_t CHARACTER_PROFESSION;  

// This may look "farmiliar" (1005) to you
#define PROFESSION_NOVICE               0x0001L 
#define PROFESSION_SWORDMAN             0x0002L 
#define PROFESSION_ARCHER               0x0004L 
#define PROFESSION_MAGE                 0x0008L 
#define PROFESSION_THIEF                0x0010L 
#define PROFESSION_MERCHANT             0x0020L 
#define PROFESSION_ACOLYTE              0x0040L 
#define PROFESSION_EXTENDED             0x0080L

#define PROFESSION_MEDIC                0x0100L
#define PROFESSION_MECHANIC             0x0200L
#define PROFESSION_SNIPER               0x0400L
#define PROFESSION_DRIVER               0x0800L
#define PROFESSION_MARINE               0x1000L
#define PROFESSION_SPY                  0x2000L
#define PROFESSION_ELITE                0x4000L
#define PROFESSION_RESERVED             0x8000L


// define some sized counters 
typedef uint8_t         COUNTER_TYPE_8;
typedef uint16_t        COUNTER_TYPE_16;
typedef uint32_t        COUNTER_TYPE_32;
typedef uint64_t        COUNTER_TYPE_64;

#define COUNTER_TYPE_DEFAULT    COUNTER_TYPE_16

// define a size for tile indices
typedef uint16_t TILEINDEX_TYPE;

// define a restriction on tile count (WARNING! if you make a chunk size larger than 32x32x64 (64 Kibitiles), you will need an index size larger than 16 bit)
#define MAX_TILE_COUNT_X    32
#define MAX_TILE_COUNT_Y    64
#define MAX_TILE_COUNT_Z    32

// define some sized ID types
typedef int32_t DEFINITION_ID, 
                CHARACTER_ID,
                WEAPON_ID   ,
                ITEM_ID     ,
                RACE_ID     ,
                ARMOR_ID    ,
                TILE_ID     ,
                INVENTORY_ID,
                ELEMENTAL_ID,
                MAP_ID      ,
                QUEST_ID    ,
                SCRIPT_ID;


// define numerical values for referencing the point structures
typedef uint16_t CHARACTER_POINT_TYPE;

#define POINTTYPE_COMMON    0x1L
#define POINTTYPE_TBS       0x2L
#define POINTTYPE_RPG       0x4L
#define POINTTYPE_FULL      (POINTTYPE_COMMON|POINTTYPE_TBS|POINTTYPE_RPG)
#define POINTTYPE_NONE      0L

// define some common groups of variables of character data
//
struct CHARACTER_RESTRICT_DATA
{
    CHARACTER_RACE          Race;
    CHARACTER_GENDER        Gender;
    CHARACTER_PROFESSION    Profession;
    CHARACTER_EFFECT        Effect;
    ELEMENTAL_TYPE          ElementalType;
};

// Defines a structure with common names for points in a game
struct CHARACTER_POINT_DATA_COMMON              
{   // This is a small structure compared to other onesa
    uint32_t    CharacterHealth;
    uint32_t    CharacterMana;  // it could be anything else, i just called it mana because it was easier
    uint32_t    CharacterSpeed; //
    uint64_t    CharacterScore; // it could be anything else, I just called it score beacuse it was shorter than "experience" for example
};
#endif // _GAMEINT_H        
share|improve this question
3  
Look at stackoverflow.com/a/1674459/387981 – Matteo Aug 20 '12 at 5:26
1  
Constant variables are lvalues. The compiler may or may not give the variable a memory location. Macro constants are substituted with the text they are assigned. Therefore if you define them using literals, they will be literals when the preprocessor does its magic (making them rvalues). These properties may matter depending on what you're doing. – Jeff Mercado Aug 20 '12 at 5:56
4  
Best to use SO for questions about advice and which is best technique. SO also has a lot more users so you are likely to get more answers. – Loki Astari Aug 20 '12 at 6:34

2 Answers

At runtime the const has the possibility of being pulled out of memory (not optimized). A macro (#define) just replaces the text with a value--so it's like a constant value.

I really don't think there's any noticeable difference in performance in the two. From a usability standpoint, consts are type-safe so they are generally a better choice in general.

But, if it matters, test and verify. If one violates specific performance requirements, pick the one that doesn't. If you don't have criteria to choose, it probably doesn't matter.

share|improve this answer

This is just from a quick reading.

#pragma pack( push, 1 )

This is not portable. Microsoft and GNU compilers will do the right thing with it. But generally I would suggest just letting the compiler specify an alignment.

typedef signed          __int8  int8_t;
typedef signed          __int16 int16_t;

This stuff is weird. Just use <stdint.h>.

 #define RACE_HUMAN                      0x0001L 
 #define RACE_DWARF                      0x0002L 
 #define RACE_ELF                        0x0004L 
 #define RACE_DRAGON                     0x0008L 

I suggest maybe using an enum. That way the types and their possible values tend to be self-documenting.

If you want bitfields I don't suggest counting off as 1, 2,, 4, 8, but rather (1<<0), (1<<1), (1<<2), (1<<3), your intention will be clearer and it'll be harder to screw up.

#define RACE_IS_HUMAN( in_RaceDescriptor )      ((bool)( RACE_HUMAN     & in_RaceDescriptor ))
#define RACE_IS_DWARF( in_RaceDescriptor )      ((bool)( RACE_DWARF     & in_RaceDescriptor ))
#define RACE_IS_ELF( in_RaceDescriptor )        ((bool)( RACE_ELF       & in_RaceDescriptor ))

The verbosity here is crazy. Assuming you do want macros to be the way to go, why not just make one and have a possible value be a 2nd macro parameter? For example:

#define IS_RACE(descriptor, race) ((descriptor) & (race))

Actually this leads me to your use of bool in the macros. True you can use 0x100 for example as a boolean expression (where nonzero is true), however you can't portably cast 0x100 as a bool. The proper way to do this would be ((x & y) ? true : false). You may find your way fails to work when you switch to an environment where bool is a different size.

Also, can a player be multiple races? If not, why is it a bit-field?

share|improve this answer
Thanks! I didn't know about pack not working. I thought about using the bitshift method to enumerate but then I was wondering if the result is processed by the compiler or if the bitshift operation is performed every time during runtime. I didn't notice I was still using a simple cast instead of the inline conditional, thanks for making me notice, i'm gonna fix them ASAP. About the races in bitfields... it's because I can make masks with that, for example "this weapon can be wear by A, B and C races", that's why there's the structure called "character_restrict". – Pablo Ariel Oct 21 '12 at 16:16
Actually it's not that I want macros to be the way to go, this code is just the first layer, then I'm building another layer with lists structures that take these values and macros and build proper behavior definitions with them and some functions to save and load data from file/mem, and then another layer with C++ classes that reference these description structures. Then the classes could be instanced and point to the weapon/character/race description tables and provide a higher level functionality, while the lower level layers would manipulate the data itself. – Pablo Ariel Oct 21 '12 at 16:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.