Script to playback and save videos of games
[progcomp2012.git] / agents / ramen / db.c
1 /*
2  * UCC 2012 Programming Competition Entry
3  * - "Ramen"
4  *
5  * By John Hodge [TPG]
6  */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "ai_common.h"
10 #include <stdint.h>
11 #include <string.h>
12
13 #define TAG_BOARDSTATE  0x7342
14
15 typedef struct sTag
16 {
17         uint16_t        Tag;
18         uint16_t        Length;
19 } tTag;
20
21 typedef struct sSavedBoardState
22 {
23         uint8_t         W, H;
24         uint16_t        Count;
25         char    NormalisedBoard[];
26 } tSavedBoardState;
27
28 // === PROTOTYPES ===
29 tSavedBoardState        *DB_int_ReadState(FILE *fp, off_t *offset);
30 void    DB_int_AppendTag(FILE *fp, uint16_t Tag, uint16_t Size, void *Data);
31
32 // === CODE ===
33 char *DB_GetOpponentFile(const char *Opponent)
34 {
35         uint32_t        checksum = 0;
36
37         {
38                  int    ofs = 0;
39                 const char *str = Opponent;
40                 while( *str )
41                 {
42                         checksum ^= *str << ofs;
43                         str ++;
44                         ofs += 5;
45                         ofs %= 32 - 5;
46                 }
47         }
48         
49         const char      *filename = NULL;
50          int    filenamelen = 0;
51         {
52                 const char *last_slash = NULL;
53                 const char *last_dot = NULL;
54                 const char *str = Opponent;
55                 while( *str )
56                 {
57                         if(*str == '/') last_slash = str;
58                         if(*str == '.') last_dot = str;
59                         str ++;
60                 }
61                 filename = last_slash + 1;
62                 if( last_slash > last_dot )
63                         filenamelen = str - filename;
64                 else
65                         filenamelen = last_dot - filename;
66         }
67
68         int len = snprintf(NULL, 0, "%08x_%.*s.ramen", checksum, filenamelen, filename);
69         char *ret = malloc(len+1);
70         snprintf(ret, len+1, "%08x_%.*s.ramen", checksum, filenamelen, filename);
71 //      fprintf(stderr, "DB File = '%s'\n", ret);
72         return ret;
73 }
74
75 void DB_LoadGuesses(const char *DBFile, enum eColours Colour)
76 {
77         FILE    *fp;
78         off_t   offset = 0;
79         tSavedBoardState        *saved_board = NULL;
80
81         fp = fopen(DBFile, "r+");
82         if(!fp) return ;
83
84         // Read board states, checking for a same state
85         while( (saved_board = DB_int_ReadState(fp, &offset)) )
86         {
87                 if( saved_board->W != giBoardWidth )
88                         continue ;
89                 if( saved_board->H != giBoardHeight )
90                         continue ;
91                 break;
92         }
93
94         // TODO: Combine counts of how many times a state has been played
95
96         if( saved_board )
97         {
98                 char    bs[giBoardWidth*4];
99                  int    ofs = 0;
100
101
102                 if( Colour != COLOUR_RED )
103                 {
104                         ofs = giBoardHeight-4;
105                         char    *bs2 = saved_board->NormalisedBoard;
106                         memcpy(bs + giBoardWidth*0, bs2 + giBoardWidth*(4-1), giBoardWidth);
107                         memcpy(bs + giBoardWidth*1, bs2 + giBoardWidth*(4-2), giBoardWidth);
108                         memcpy(bs + giBoardWidth*2, bs2 + giBoardWidth*(4-3), giBoardWidth);
109                         memcpy(bs + giBoardWidth*3, bs2 + giBoardWidth*(4-4), giBoardWidth);
110                 }
111                 else
112                 {
113                         memcpy(bs, saved_board->NormalisedBoard, giBoardWidth*4);
114                 }
115 //              for( int i = 0; i < 4; i ++ ) {
116 //                      fprintf(stderr, "%.*s\n", giBoardWidth, bs + giBoardWidth*i);
117 //              }
118
119                 // Set guessed ranks
120                 for( int i = 0; i < giBoardWidth*4; i ++ )
121                 {
122                         tPiece  *p = GetPieceByPos(i % giBoardWidth, i/giBoardWidth + ofs );
123 //                      fprintf(stderr, "%c", bs[i]);
124 //                      if(i % giBoardWidth == giBoardWidth-1)
125 //                              fprintf(stderr, "\n");
126                         if( bs[i] == '\0' && p )
127                                 break;
128                         if( bs[i] != '\0' && !p )
129                                 break;
130                         if( p )
131                                 p->GuessedRank = CharToRank(bs[i]);
132                 }
133         }
134
135         fclose(fp);
136 }
137
138 void DB_WriteBackInitialState(const char *DBFile, enum eColours Colour, tPiece *Pieces)
139 {
140         char    bs[giBoardHeight*giBoardWidth];
141         memset(bs, 0, sizeof(bs));
142
143         for( int i = 0; i < N_PIECES; i ++ )
144         {
145                 if( Pieces[i].StartY < 0 )      continue ;
146                 char    *bp = &bs[ Pieces[i].StartY*giBoardWidth + Pieces[i].StartX ];
147
148                 if( *bp != '\0' )
149                 {
150                         // Oops?
151                 }
152                 else
153                 {
154                         *bp = cRANK_CHARS[ Pieces[i].Rank ];
155                 }
156         }
157
158         // Normalise board to RED
159         if( Colour != COLOUR_RED )
160         {
161                 memcpy(bs + giBoardWidth*0, bs + giBoardWidth*(giBoardHeight-1), giBoardWidth);
162                 memcpy(bs + giBoardWidth*1, bs + giBoardWidth*(giBoardHeight-2), giBoardWidth);
163                 memcpy(bs + giBoardWidth*2, bs + giBoardWidth*(giBoardHeight-3), giBoardWidth);
164                 memcpy(bs + giBoardWidth*3, bs + giBoardWidth*(giBoardHeight-4), giBoardWidth);
165         }
166
167
168         off_t   offset;
169         tSavedBoardState        *saved_board;
170         FILE *fp = fopen(DBFile, "r+");
171         if( !fp ) {
172                 fp = fopen(DBFile, "w");
173         }
174
175         // Read board states, checking for a same state
176         while( (saved_board = DB_int_ReadState(fp, &offset)) )
177         {
178 //              fprintf(stderr, "DBG: %i == %i? and %i == %i\n",
179 //                      saved_board->W, giBoardWidth, saved_board->H, giBoardHeight
180 //                      );
181
182                 if( saved_board->W != giBoardWidth )
183                         continue ;
184                 if( saved_board->H != giBoardHeight )
185                         continue ;
186
187                 BOOL    b_different = false;
188
189                 for( int i = 0; i < 4*giBoardWidth; i ++ )
190                 {
191                         if( saved_board->NormalisedBoard[i] == '#' || bs[i] == '#' )
192                                 continue ;
193                         if( saved_board->NormalisedBoard[i] != bs[i] ) {
194                                 fprintf(stderr, "DBG: '%c' != '%c'\n", saved_board->NormalisedBoard[i], bs[i]);
195                                 b_different = true;
196                                 break;
197                         }
198                 }
199
200                 if( b_different )       continue ;
201
202                 break;
203         }
204
205         if( saved_board )
206         {
207                 saved_board->Count ++;
208                 fseek(fp, offset, SEEK_SET);
209                 // Merge
210                 for( int i = 0; i < 4*giBoardWidth; i ++ )
211                 {
212                         if( saved_board->NormalisedBoard[i] == '#' )
213                                 saved_board->NormalisedBoard[i] = bs[i];
214                 }
215                 // Write back
216                 fwrite(saved_board, sizeof(*saved_board) + giBoardWidth*4, 1, fp);
217         }
218         else
219         {
220                 saved_board = malloc( sizeof(*saved_board) + giBoardWidth*4 );
221                 saved_board->W = giBoardWidth;
222                 saved_board->H = giBoardHeight;
223                 saved_board->Count = 1;
224                 memcpy(saved_board->NormalisedBoard, bs, 4*giBoardWidth);
225                 DB_int_AppendTag(fp, TAG_BOARDSTATE, sizeof(*saved_board) + giBoardWidth*4, saved_board);
226         }
227         free(saved_board);
228
229         fclose(fp);
230 }
231
232 tSavedBoardState *DB_int_ReadState(FILE *fp, off_t *offset)
233 {
234         tTag    tag;
235         tSavedBoardState        *ret = NULL;
236
237         do {
238                 if( fread(&tag, sizeof(tag), 1, fp) != 1 )
239                         break ;
240                 if( tag.Tag == TAG_BOARDSTATE )
241                 {
242                         *offset = ftell(fp);
243                         ret = malloc(tag.Length);
244                         fread(ret, tag.Length, 1, fp);
245                 }
246                 fseek(fp, tag.Length, SEEK_CUR);
247         } while(!ret);
248
249         return ret;
250 }
251
252 void DB_int_AppendTag(FILE *fp, uint16_t Tag, uint16_t Size, void *Data)
253 {
254         fseek(fp, 0, SEEK_END);
255         fwrite(&Tag, sizeof(uint16_t), 1, fp);
256         fwrite(&Size, sizeof(uint16_t), 1, fp);
257         fwrite(Data, Size, 1, fp);
258 }

UCC git Repository :: git.ucc.asn.au