#ifndef MOVE_H_INCLUDED
#define MOVE_H_INCLUDED

#include <stdint.h>
#include "quadboard.h"
#include "state.h"

// the move data type
typedef uint32_t MOVE;

// bit 0-5: to square
#define MV_GET_TO(mv) ((mv) & 0x3F)
#define MV_SET_TO(mv, sq) ((mv) | (sq))

// bit 6-11: from square
#define MV_GET_FROM(mv) (((mv) & 0xFC0) >> 6)
#define MV_SET_FROM(mv, sq) ((mv) | ((sq) << 6))

// bit 12-14: promotion type
#define MV_GET_PROMO(mv) (((mv) & 0x7000) >> 12)
#define MV_SET_PROMO(mv, pt) ((mv) | ((pt) << 12))
#define IS_MV_PROMO(mv) ((mv) & 0x7000)

// bit 15: enpassant or castle
#define MV_SET_SPECIAL(mv) ((mv) | 0x8000)
#define IS_MV_SPECIAL(mv) ((mv) & 0x8000)

// bit 16-31: additional info
#define MV_GET_SCORE(mv) ((mv) >> 16)
#define MV_ADD_SCORE(mv, val) ((mv) + ((val) << 16))

// other macros and constants
#define MV_NULL 0
#define MV_NEW(from, to) (MV_SET_TO(MV_SET_FROM(MV_NULL, from), to))
#define IS_MV_FRONT_2(mv, pl) ((((mv) & 0xE38) ^ (0xE38 & -(pl))) == 0xC20)

// input-output in UCI format
MOVE mv_scan_uci(const char* uci, const QUADBOARD* qb, STATE st, int c960);
void mv_print_uci(char* uci, const QUADBOARD* qb, STATE st, int c960, MOVE mv);

// serialise a map of target squares in a list of moves (single source)
int mv_unroll_bb_from(MOVE* mv, BITBOARD bb, int from);
int mv_unroll_bb_diff(MOVE* mv, BITBOARD bb, int diff);
int mv_unroll_bb_promo(MOVE* mv, BITBOARD bb, int diff);

// check the legality of the move
int is_mv_legal(const QUADBOARD* curr, const QUADBOARD* next, MOVE mv);

// sanity check on the move
int is_mv_bad(const QUADBOARD* qb, STATE st, MOVE mv);

// test the functions above
int mv_test();

#endif // MOVE_H_INCLUDED
