/* * DUMPMEM.C * * Copyright (C) 1990 by Aaron L. Brenner * * Purpose: * Produce a formatted dump of TICTAC.MEM. * * Revision history: * 1.00 06/17/90 ALB Created. */ #include #include #define mem_err(x) err_exit("memory allocation", x) #define eof_err(x) err_exit("unexpected EOF", x) char memory_name[] = "tictac.mem"; /* File name for "memory" */ /* * Define the structure of each recorded move */ typedef struct playlist { unsigned char pl_move; /* Move this corresponds to */ char pl_weight; /* "Weight" for this move */ struct playlist *pl_next; /* Next one in the list */ } PLAYLIST; /* * Define the structure of each "remembered" board */ typedef struct boardlist { unsigned int bl_board; /* Encoded board */ unsigned char bl_count; /* Count of play list elements */ PLAYLIST *bl_plays; /* List of plays made here */ struct boardlist *bl_next; /* Next board in the list */ } BOARDLIST; BOARDLIST *board_memory = NULL; /* Head of list of boards */ unsigned powers[9] = { 3, 9, 27, 81, 243, 729, 2187, 6561, 19683 }; int board_count; /* * Error exit routine */ void err_exit(char *msg, char *locus) { fputs("Fatal ", stderr); /* Tell them it's a fatal error */ fputs(msg, stderr); /* Spit out the message */ fputs(" error in/about ", stderr); /* Say about where it is */ fputs(locus, stderr); fputc('\n', stderr); /* New line */ exit(1); /* Get the hell out of Dodge */ } /* * Load the memory file * * The memory file is organized as follows: * word count of boards * * * The count of pairs for each board is stored with the board. */ void load_boards() { FILE *memfile; unsigned bcount, pcount, count2; BOARDLIST *tboards, /* Ptr for allocating */ *tbdtail; /* Keeps track of the end of */ /* the board list so we don't */ /* have to chain through the */ /* entire list each time */ PLAYLIST *tplays, /* Ptr for allocating */ *tplaystail; /* Same purpose as tbdtail, but */ /* for the move list */ /* * Try to open the memory file. If it fails, no big deal, just no memory */ if ((memfile = fopen(memory_name, "rb")) != NULL) { /* * Make the file buffer bigger than 1 sector so that the I/O goes * faster */ setvbuf(memfile, NULL, _IOFBF, 8192); /* * Read in the count of boards. If that fails, die. */ if ((board_count = (unsigned)getw(memfile)) == EOF) eof_err("load_boards[board count]"); tbdtail = NULL; /* Set up the tail ptr */ /* * Load in each board in the file */ for (count2 = 0; count2 < board_count; count2++) { /* * Allocate a structure for this board. If it fails, die. */ if ((tboards = malloc(sizeof(BOARDLIST))) == NULL) mem_err("load_boards[board list]"); if (tbdtail == NULL) /* If none yet, */ board_memory = tboards; /* Set the list head */ else /* But if we already have some, */ tbdtail->bl_next = tboards; /* set our tail ptr's ptr */ tbdtail = tboards; /* Point to the last one */ tboards->bl_plays = NULL; /* Set up ptr to play list */ tboards->bl_next = NULL; /* Keep list terminated */ /* * Read in the board itself. If it fails, die. */ if (fread(&(tboards->bl_board), 1, sizeof(tboards->bl_board) + sizeof(char), memfile) != (sizeof(tboards->bl_board) + sizeof(char))) eof_err("load_boards[board data]"); } /* * We've read in all the board configurations. Now, we have to go * through each board, reading in the plays for that board. */ for (tboards = board_memory; tboards != NULL; tboards = tboards->bl_next) { tplaystail = NULL; /* Set up list tail ptr */ pcount = tboards->bl_count; /* Get play list count */ for (count2 = 0; count2 < pcount; count2++) { if ((tplays = malloc(sizeof(PLAYLIST))) == NULL) mem_err("load_boards[play list]"); if (tplaystail == NULL) /* If none yet, */ tboards->bl_plays = tplays; /* Set ptr in board entry */ else /* Otherwise keep list right */ tplaystail->pl_next = tplays; tplaystail = tplays; tplays->pl_next = NULL; /* Keep list terminated */ /* * Read in a move/weight pair. If it fails, die. */ if (fread(&(tplays->pl_move), 1, sizeof(unsigned char) + sizeof(char), memfile) < (sizeof(unsigned char) + sizeof(char))) eof_err("load_boards[play list]"); } } fclose(memfile); /* Close it */ } } /* * Dump the memory file. */ void dump_memory() { FILE *mfile; BOARDLIST *tb; PLAYLIST *tp; int i, j; unsigned coded_board; char t2[9][6]; unsigned char dboard[9]; if ((mfile = fopen("tmdump.txt", "w")) == NULL) err_exit("file creation", "dump_memory[create dump file]"); setvbuf(mfile, NULL, _IOFBF, 8192); fputs("Dump of TICTAC.MEM\n==================\n\n", mfile); fprintf(mfile, "Contains %d boards\n\n", board_count); for (i = 1, tb = board_memory; tb != NULL; i++, tb = tb->bl_next) { coded_board = tb->bl_board; for (j = 8; j >= 0; j--) { dboard[j] = (coded_board / powers[j]); coded_board %= powers[j]; } for (j = 0; j < 9; j++) if (dboard[j] == 1) strcpy(t2[j], "**X**"); else if (dboard[j] == 2) strcpy(t2[j], "**O**"); else t2[j][0] = '\0'; for (tp = tb->bl_plays; tp != NULL; tp = tp->pl_next) sprintf(t2[tp->pl_move], "%5d", tp->pl_weight); fprintf(mfile, "Board %-8d%5s|%5s|%s\n%31s\n", i, t2[6], t2[7], t2[8], "-----+-----+-----"); fprintf(mfile, "%14s%5s|%5s|%s\n%31s\n", "", t2[3], t2[4], t2[5], "-----+-----+-----"); fprintf(mfile, "%14s%5s|%5s|%s\n\n", "", t2[0], t2[1], t2[2]); } fclose(mfile); } main() { load_boards(); /* Load in the memory file */ dump_memory(); /* Dump it */ }