cbitmapbit-manipulationchess

Bitshift in a bitmap calculation doesn't seem to work


I have a CLI chess program that takes in input from user(eg: 'e2e4') and converts it into two bitmaps i.e., s_map and e_map.

The bitmaps are represented like 0x0000000000000000ULL;
where the rightmost bit represents h8, leftmost bit represent a1.

The algorithm I used


#ifdef _WIN32
#define CLR "cls"
#else
#define CLR "clear"
#endif
#define SQS 64
#define ROW 8

typedef struct {
    uint64_t wp;
    uint64_t wr;
    uint64_t wn;
    uint64_t wb;
    uint64_t wq;
    uint64_t wk;
    uint64_t bp;
    uint64_t br;
    uint64_t bn;
    uint64_t bb;
    uint64_t bq;
    uint64_t bk;
} PieceBitmaps;
typedef struct {
    uint64_t s_map, e_map;
} Move;
typedef struct {
    uint64_t s_map, e_map;
} Move;

int main(int argc, char * argv[]) {
    char turn = 'W';
    char winner = ' ';
    PieceBitmaps pieces = init_bitmap();
    Move input;
    while (winner == ' ') {
        system(CLR);
        print_stuff(turn, &pieces);
        do {
            input = get_input();
            printf("Hex: S-map: %x E-map: %x\n", input.s_map, input.e_map);
        } while (1); // TODO: Validity functions go here.
        turn = (turn == 'W') ? 'B' : 'W'; 
    }
}

Move input_to_bitmap(char* input) {
    Move mv;
    mv.s_map = 0x8000000000000000ULL >> (((input[1] - '1') * ROW) + (tolower(input[0]) - 'a'));
    mv.e_map = 0x8000000000000000ULL >> (((input[3] - '1') * ROW) + (tolower(input[2]) - 'a'));
    return mv;
}

Move get_input() {
    char input[5];
    printf("Enter the move eg='e2e4' : ");
    fgets(input, sizeof(input), stdin);
    printf("%s\n", input);
    if(strlen(input) == 4) while (getchar() != '\n'); // We clear the input buffer of garbage val to insure integrity for next iteration.
    if (check_valid_input(input)) return (Move){0X0ULL, 0x0ULL};
    return input_to_bitmap(input);
}

int check_valid_input(char* input) {
    if (input[0] > 'h' || input[0] < 'a' || input[2] > 'h' || input[2] < 'a' ||
    input[1] < '1' || input[1] > '8' || input[3] < '1' || input[3] > '8' || strlen(input) != 4) {
        puts("Enter the move in a valid format.");
        return 1;
    }
    return 0;
}

The >> index is correctly calculated but, the bit doesn't seem to shift for some particular squares like squares in rank1, rank2 and just show 0 for all of them, but are correctly shifted for other squares like h8, h7 etc.

The output looks like:

Enter the move eg='e2e4' : e2e4
e2e4
Hex: S-map: 0 E-map: 0
Enter the move eg='e2e4' : h8h7
h8h7
Hex: S-map: 1 E-map: 100
Enter the move eg='e2e4' : a1a4
a1a4
Hex: S-map: 0 E-map: 0
Enter the move eg='e2e4' : b1b4
b1b4
Hex: S-map: 0 E-map: 0
Enter the move eg='e2e4' : a2b4
a2b4
Hex: S-map: 0 E-map: 0
Enter the move eg='e2e4' : 

Any feedback will be appreciated.


Solution

  • The problem isn't in the conversion, but in the output.

    In the main function, you use the following to print the converted values:

    printf("Hex: S-map: %x E-map: %x\n", input.s_map, input.e_map);
    

    The %x format specifier expects an unsigned int as its argument, but you are passing in a uint64_t which is of a different size. Using the wrong format specifier invokes undefined behavior in your code.

    You need to instead use the PRIx64 macro which generates the proper format specifier to print a uint64_t in hex:

    printf("Hex: S-map: %" PRIx64 " E-map: %" PRIx64 "\n", input.s_map, input.e_map);