X-Git-Url: https://git.ucc.asn.au/?p=progcomp2012.git;a=blobdiff_plain;f=agents%2Framen%2Fsrc%2Fdb.c;fp=agents%2Framen%2Fsrc%2Fdb.c;h=a62d44aae6e6510ac53346530e24886fbd434737;hp=0000000000000000000000000000000000000000;hb=52489d9b9b2d7633f9b7caaed0ed1ea40972032b;hpb=add28d0a7f265f5fcfdd67a4c1e590b19f76272e;ds=sidebyside diff --git a/agents/ramen/src/db.c b/agents/ramen/src/db.c new file mode 100644 index 0000000..a62d44a --- /dev/null +++ b/agents/ramen/src/db.c @@ -0,0 +1,258 @@ +/* + * UCC 2012 Programming Competition Entry + * - "Ramen" + * + * By John Hodge [TPG] + */ +#include +#include +#include "ai_common.h" +#include +#include + +#define TAG_BOARDSTATE 0x7342 + +typedef struct sTag +{ + uint16_t Tag; + uint16_t Length; +} tTag; + +typedef struct sSavedBoardState +{ + uint8_t W, H; + uint16_t Count; + char NormalisedBoard[]; +} tSavedBoardState; + +// === PROTOTYPES === +tSavedBoardState *DB_int_ReadState(FILE *fp, off_t *offset); +void DB_int_AppendTag(FILE *fp, uint16_t Tag, uint16_t Size, void *Data); + +// === CODE === +char *DB_GetOpponentFile(const char *Opponent) +{ + uint32_t checksum = 0; + + { + int ofs = 0; + const char *str = Opponent; + while( *str ) + { + checksum ^= *str << ofs; + str ++; + ofs += 5; + ofs %= 32 - 5; + } + } + + const char *filename = NULL; + int filenamelen = 0; + { + const char *last_slash = NULL; + const char *last_dot = NULL; + const char *str = Opponent; + while( *str ) + { + if(*str == '/') last_slash = str; + if(*str == '.') last_dot = str; + str ++; + } + filename = last_slash + 1; + if( last_slash > last_dot ) + filenamelen = str - filename; + else + filenamelen = last_dot - filename; + } + + int len = snprintf(NULL, 0, "%08x_%.*s.ramen", checksum, filenamelen, filename); + char *ret = malloc(len+1); + snprintf(ret, len+1, "%08x_%.*s.ramen", checksum, filenamelen, filename); +// fprintf(stderr, "DB File = '%s'\n", ret); + return ret; +} + +void DB_LoadGuesses(const char *DBFile, enum eColours Colour) +{ + FILE *fp; + off_t offset = 0; + tSavedBoardState *saved_board = NULL; + + fp = fopen(DBFile, "r+"); + if(!fp) return ; + + // Read board states, checking for a same state + while( (saved_board = DB_int_ReadState(fp, &offset)) ) + { + if( saved_board->W != giBoardWidth ) + continue ; + if( saved_board->H != giBoardHeight ) + continue ; + break; + } + + // TODO: Combine counts of how many times a state has been played + + if( saved_board ) + { + char bs[giBoardWidth*4]; + int ofs = 0; + + + if( Colour != COLOUR_RED ) + { + ofs = giBoardHeight-4; + char *bs2 = saved_board->NormalisedBoard; + memcpy(bs + giBoardWidth*0, bs2 + giBoardWidth*(4-1), giBoardWidth); + memcpy(bs + giBoardWidth*1, bs2 + giBoardWidth*(4-2), giBoardWidth); + memcpy(bs + giBoardWidth*2, bs2 + giBoardWidth*(4-3), giBoardWidth); + memcpy(bs + giBoardWidth*3, bs2 + giBoardWidth*(4-4), giBoardWidth); + } + else + { + memcpy(bs, saved_board->NormalisedBoard, giBoardWidth*4); + } +// for( int i = 0; i < 4; i ++ ) { +// fprintf(stderr, "%.*s\n", giBoardWidth, bs + giBoardWidth*i); +// } + + // Set guessed ranks + for( int i = 0; i < giBoardWidth*4; i ++ ) + { + tPiece *p = GetPieceByPos(i % giBoardWidth, i/giBoardWidth + ofs ); +// fprintf(stderr, "%c", bs[i]); +// if(i % giBoardWidth == giBoardWidth-1) +// fprintf(stderr, "\n"); + if( bs[i] == '\0' && p ) + break; + if( bs[i] != '\0' && !p ) + break; + if( p ) + p->GuessedRank = CharToRank(bs[i]); + } + } + + fclose(fp); +} + +void DB_WriteBackInitialState(const char *DBFile, enum eColours Colour, tPiece *Pieces) +{ + char bs[giBoardHeight*giBoardWidth]; + memset(bs, 0, sizeof(bs)); + + for( int i = 0; i < N_PIECES; i ++ ) + { + if( Pieces[i].StartY < 0 ) continue ; + char *bp = &bs[ Pieces[i].StartY*giBoardWidth + Pieces[i].StartX ]; + + if( *bp != '\0' ) + { + // Oops? + } + else + { + *bp = cRANK_CHARS[ Pieces[i].Rank ]; + } + } + + // Normalise board to RED + if( Colour != COLOUR_RED ) + { + memcpy(bs + giBoardWidth*0, bs + giBoardWidth*(giBoardHeight-1), giBoardWidth); + memcpy(bs + giBoardWidth*1, bs + giBoardWidth*(giBoardHeight-2), giBoardWidth); + memcpy(bs + giBoardWidth*2, bs + giBoardWidth*(giBoardHeight-3), giBoardWidth); + memcpy(bs + giBoardWidth*3, bs + giBoardWidth*(giBoardHeight-4), giBoardWidth); + } + + + off_t offset; + tSavedBoardState *saved_board; + FILE *fp = fopen(DBFile, "r+"); + if( !fp ) { + fp = fopen(DBFile, "w"); + } + + // Read board states, checking for a same state + while( (saved_board = DB_int_ReadState(fp, &offset)) ) + { +// fprintf(stderr, "DBG: %i == %i? and %i == %i\n", +// saved_board->W, giBoardWidth, saved_board->H, giBoardHeight +// ); + + if( saved_board->W != giBoardWidth ) + continue ; + if( saved_board->H != giBoardHeight ) + continue ; + + BOOL b_different = false; + + for( int i = 0; i < 4*giBoardWidth; i ++ ) + { + if( saved_board->NormalisedBoard[i] == '#' || bs[i] == '#' ) + continue ; + if( saved_board->NormalisedBoard[i] != bs[i] ) { + fprintf(stderr, "DBG: '%c' != '%c'\n", saved_board->NormalisedBoard[i], bs[i]); + b_different = true; + break; + } + } + + if( b_different ) continue ; + + break; + } + + if( saved_board ) + { + saved_board->Count ++; + fseek(fp, offset, SEEK_SET); + // Merge + for( int i = 0; i < 4*giBoardWidth; i ++ ) + { + if( saved_board->NormalisedBoard[i] == '#' ) + saved_board->NormalisedBoard[i] = bs[i]; + } + // Write back + fwrite(saved_board, sizeof(*saved_board) + giBoardWidth*4, 1, fp); + } + else + { + saved_board = malloc( sizeof(*saved_board) + giBoardWidth*4 ); + saved_board->W = giBoardWidth; + saved_board->H = giBoardHeight; + saved_board->Count = 1; + memcpy(saved_board->NormalisedBoard, bs, 4*giBoardWidth); + DB_int_AppendTag(fp, TAG_BOARDSTATE, sizeof(*saved_board) + giBoardWidth*4, saved_board); + } + free(saved_board); + + fclose(fp); +} + +tSavedBoardState *DB_int_ReadState(FILE *fp, off_t *offset) +{ + tTag tag; + tSavedBoardState *ret = NULL; + + do { + if( fread(&tag, sizeof(tag), 1, fp) != 1 ) + break ; + if( tag.Tag == TAG_BOARDSTATE ) + { + *offset = ftell(fp); + ret = malloc(tag.Length); + fread(ret, tag.Length, 1, fp); + } + fseek(fp, tag.Length, SEEK_CUR); + } while(!ret); + + return ret; +} + +void DB_int_AppendTag(FILE *fp, uint16_t Tag, uint16_t Size, void *Data) +{ + fseek(fp, 0, SEEK_END); + fwrite(&Tag, sizeof(uint16_t), 1, fp); + fwrite(&Size, sizeof(uint16_t), 1, fp); + fwrite(Data, Size, 1, fp); +}