/*
 *  slide.h
 *
 *  main header file for jimslide
 *  copyright Jim Leonard 1999
 */

#include "btree64k.h"

#define WORK_FILE_NAME "js_tmp%02d.tmp"
#define MAX_WORK_FILES 100

/*#define MAX_BLOCKS_PER_PIECE 24 */
#define MAX_PIECE 128

struct PieceDef_s {
   int pieceType;
   int startX;
   int startY;
   int moveX;
   int moveY;
   int curLoc;
   int numBloc;
   int *xbloc;
   int *ybloc;
   int *xyoffset;
   int moveBlock[4]; /* number of blocks that need moved to move the piece in a given direction */
   int *moveTo[4];  /* blocks that become 'pieceType' when piece moves a given direction */
   int *moveFrom[4]; /* blocks that become a space when piece moves a given direction */
   int xstep;    /* ie if set, board can't be stored unless the net x or y */
   int ystep;    /* movement is a multiple of xstep or ystep */
   char label;
   char pad1; /* pad to integer allignment incase the compiler doesn't do it for me */
   char pad2;
   char pad3;
   };
typedef struct PieceDef_s PieceDef;

struct PosListNode_s {
   struct PosListNode_s *next;
   SList *pList;  /* NULL if not in presently in memory */
   size_t pListSize;
   size_t uncompressedSize;
   FILE *file;    /* NULL if not in a file */
   long offset;
   };
typedef struct PosListNode_s PosListNode;


struct Generation_s {
   struct Generation_s *next;
   struct Generation_s *prev;
   unsigned int numBoards;
   PosListNode *pln0;
   PosListNode *lastPln;
   };
typedef struct Generation_s Generation;


struct PosFILE_s {
   int level;     /* merge level */
   int entry;     /* which entry (typically 0 or 1) */
   int seqNo;     /* which file in the set */
   FILE *curFile; /* file handle of the currently open file*/
   int write;     /* set if this set is being created */
   int remove;    /* set if this set is to be deleted once read */
   int bytesWritten; /* number of bytes written to one file */
   unsigned int totalEntriesWritten;
   unsigned char nextHeader[SIZE_SL_HEADER];
   };
typedef struct PosFILE_s PosFILE;


#define LARGEST_BOARD_SIZE 2048
#define WALL_CHAR 255
#define SPACE_CHAR 254

struct WallList_s {
   int numWall;
   int wallX[LARGEST_BOARD_SIZE];
   int wallY[LARGEST_BOARD_SIZE];
   };
typedef struct WallList_s WallList;
extern WallList wallList;

struct WinCond_s {
   int pieceType;
   int iPieceType;
   int posX;
   int posY;
   int posXY;
   };
typedef struct WinCond_s WinCond;

struct WinList_s {
   int numWinCond;
   WinCond winCond[MAX_PIECE];
   };
typedef struct WinList_s WinList;
extern WinList winList;


extern unsigned char baseBoard[LARGEST_BOARD_SIZE];
extern unsigned char workBoard[LARGEST_BOARD_SIZE];

void TryPiece();
void TryMove(int offset);
void TryPiece_1();
void TryMove_1(int offset);
void ProcessBoard();
void ShowWin();
int ProcessMoves();
int GetNextBoard(unsigned char *board);
int EnqueueBoard(unsigned char *board);
void DoInits(Generation *gen0, Generation *winGen, int move0, int winMove);
void InitBaseBoard();
void InitBoard(unsigned char *board);
void InitPieces();
void CompressBoard(unsigned char *compressed, unsigned char *board);
void UncompressBoard(unsigned char *compressed, unsigned char *board);
void PrintBoard(unsigned char *board);
char PieceNum2Char(int pn);
int ReadParms(int argc, char *argv[]);
int CheckIfWin(unsigned char *board);
void ReadyNextGen();
int ProcessGen();
void InitGen(Generation *prevGen);
void ProcessNewPosList();
void ConcurrentShowWin(unsigned char *cPtr);
void AddPln(Generation *gen, SList *list);
void StorePln(PosListNode *pln, int freeSlist);
void GetPln(PosListNode *pln, SList *slptr, int decompress);
void DropPln(PosListNode *pln, int freeSlist);
void ReorgGNBQueue();
int Distance();
int CDistance(unsigned char *compressed);
void RenumberPieces(char *board);

/*
 * stuff dealing with bigstorage
 */
void InitLevelList();
void GetNewFileName(int level, int fileNum, char *fileName);
void CreateTempFileName(int level, int entry, int fileNum, char *fileName);
void pf_open(PosFILE *pfile);
void pf_remove(PosFILE *pfile);
PosFILE * OpenPosFile(int level, int entry, int write, int remove);
int ReadPosFile(PosFILE *inPF, SList *inlist, int uncompress);
unsigned int WritePosFile(PosFILE *outPF, SList *outlist);
void ClosePosFile(PosFILE *pf);
void RenamePosFileSet(int oldLevel, int oldEntry, int newLevel, int newEntry);
void RemovePosFileSet(int level, int entry);
void RemoveGeneration(int gen);
unsigned int MergeTempFiles(int inLevel1, int inEntry1,
                    int inLevel2, int inEntry2,
                    int outLevel, int outEntry);
unsigned int DedupFile (int inLevel1, int inEntry1,
                int inLevel2, int inEntry2,
                int outLevel, int outEntry);
unsigned int MergeTempFileWithLinkedList(int inLevel1, int inEntry1,
                    BTree *inTree,
                    int outLevel, int outEntry);
void DoMerge(int startLevel);
void DoFinalMerge(int curGen, int prevGen, int prevPrevGen);
unsigned char * FindDuplicateInLinkedList(int inLevel1, int inEntry1,
                    BTree *inTree);
unsigned char * FindDuplicateEntryInFiles(int inLevel1, int inEntry1,
                    int inLevel2, int inEntry2);
