/* Concatenation of identifiers in the preprocessor */
#ifdef lint
#define SAME(x) x
#define CAT(x,y) SAME(x)y
#else
#define CAT(x,y) x/**/y
#endif

/* A trivial abstraction */
#define bool   int
#define FALSE  0
#define TRUE   1

/* Just for our convenience */
typedef unsigned char   u_char;
typedef unsigned long   u_long;


/******* Definition of and operations on the abstract type 'Square' *******/

typedef   int Square;		/* -1, 0..99 */

#define SQ(col, row)   ((row) * 10 + (col))
#define ROW(sq)        ((sq) / 10)
#define COL(sq)        ((sq) % 10)

/* A PASS is a move to nowhere. This is used when no move is allowed. */
/* UNDO can be returned from get_users_move(). This is a request from */
/* the user to undo his/her last move. */
#define PASS          -1
#define UNDO          -2
#define RESIGN        -3


/******* Definition of and operations on the abstract type 'Sqlist' *******/

typedef struct sqcell_t {
    Square           sq;
    struct sqcell_t   *next;
} Sqcell;



/*
 * This assumes longs are 32 bits!!!
 */

typedef union {
    u_char       bytes[8];
    struct {
	u_long   long1;
	u_long   long2;
    } longs;
} Sqlist;


extern u_long   pl_bits[];
extern Sqcell   *pl_lists[];


#define RESET_SQLIST(list) \
    ((list).longs.long1 = (list).longs.long2 = 0)

#define EMPTY_SQLIST(list) \
    ((list).longs.long1 == 0 && (list).longs.long2 == 0)


#define sl_traverse(var) \
    int  CAT(_1_,var); Sqcell *CAT(_2_,var)

#define for_all_in_sqlist(list,var,sq) \
    for (CAT(_1_,var) = 0; CAT(_1_,var) < 8; ++CAT(_1_,var)) \
        for (CAT(_2_,var) = pl_lists[(list).bytes[CAT(_1_,var)]]; \
	     CAT(_2_,var) != NULL \
	         && (sq = CAT(_2_,var)->sq + (CAT(_1_,var) + 1) * 10); \
	     CAT(_2_,var) = CAT(_2_,var)->next)

/*
 * #define for_all_in_sqlist(list, var, sq) \
 *     for (x1 = 0; x1 < 8; ++x1) \
 *         for (x2 = pl_lists[(list).bytes[x1]]; \
 * 	        x2 != NULL && (sq = x2->sq + (x1 + 1) * 10); \
 * 	        x2 = x2->next)
 */


#define add_element(list, sq) \
    if ((sq) < 50) \
        (list).longs.long1 |= pl_bits[sq]; \
    else \
        (list).longs.long2 |= pl_bits[sq]

#define delete_element(list, sq) \
    if ((sq) < 50) \
        (list).longs.long1 &= ~pl_bits[sq]; \
    else \
        (list).longs.long2 &= ~pl_bits[sq]



#define subtract_list(list1, list2) \
    ((list1).longs.long1 &= ~(list2).longs.long1, \
     (list1).longs.long2 &= ~(list2).longs.long2)

#define member(list, sq) \
    ((sq) < 50 ? (((list).longs.long1 & pl_bits[sq]) != 0) \
               : (((list).longs.long2 & pl_bits[sq]) != 0))

extern void printlist();
extern void init_sqlists();


/******* Definition of and operations on the abstract type 'Sqqueue' *******/


typedef struct {
    Sqcell   *first;
    Sqcell   *last;
} Sqqueue;

#define reset_queue(q) \
    ((q)->first = NULL, (q)->last = NULL)

#define emptyqueue(q) \
    ((q)->first == NULL)


extern void     queue();
extern Square dequeue_first();
