3 Copyright (c) Scott Gasch
11 Support routines for dumping a search tree into an XML file for
12 offline analysis by typhoonui.exe.
25 #define NHUMAN_READABLE
27 #define SPACES_TO_INDENT_PER_PLY (2)
29 #define SPACES_TO_INDENT_PER_PLY (0)
31 #define DISK_SECTOR_SIZE_BYTES (512)
32 #define NUM_SECTORS_TO_BUFFER (2)
34 FILE *pfTreeDump = NULL;
35 ULONG g_uBufferSize = 0;
36 ULONG g_uBufferUsed = 0;
37 CHAR *g_Buffer = NULL;
39 volatile static ULONG g_uBufferLock = 0;
40 #define BUF_IS_LOCKED (g_uBufferLock != 0)
42 AcquireSpinLock(&g_uBufferLock); \
43 ASSERT(BUF_IS_LOCKED);
45 ASSERT(BUF_IS_LOCKED); \
46 ReleaseSpinLock(&g_uBufferLock);
54 InitializeTreeDump(void)
59 Initialize tree dumping system.
72 // Allocate an internal buffer so that our writes to disk
73 // approximate a sector size.
75 g_uBufferSize = DISK_SECTOR_SIZE_BYTES * NUM_SECTORS_TO_BUFFER;
76 g_Buffer = SystemAllocateMemory(g_uBufferSize);
79 // Here's the file we'll want to write to...
81 pfTreeDump = fopen("typhoon.xml", "wb+");
82 if (NULL == pfTreeDump)
84 UtilPanic(FATAL_ACCESS_DENIED,
85 NULL, "typhoon.xml", "write", "NULL", __FILE__, __LINE__);
87 fprintf(pfTreeDump, "<?xml version=\"1.0\" encoding=\"utf-8\""
88 " standalone=\"no\"?>\n");
92 void _FlushTheBuffer(void)
97 Flush the buffer to the disk file.
109 fprintf(pfTreeDump, g_Buffer);
116 _AppendToBuffer(CHAR *buf)
121 Append a string to the buffer; possibly flush the buffer to disk
122 first to make enough room for the new string.
126 CHAR *buf : the string to append
135 ASSERT(BUF_IS_LOCKED);
138 // How much space do we need?
140 uSpaceNeeded = strlen(buf);
141 ASSERT(uSpaceNeeded < MEDIUM_STRING_LEN_CHAR);
142 ASSERT(uSpaceNeeded < g_uBufferSize);
145 // See if we need to flush the real buffer to the disk before we can
146 // append this new message.
149 if (g_uBufferUsed + uSpaceNeeded >= g_uBufferSize)
152 ASSERT(g_uBufferUsed + uSpaceNeeded < g_uBufferSize);
156 // Append the new data to the big buffer
158 strcat(g_Buffer, buf);
159 g_uBufferUsed += uSpaceNeeded;
160 ASSERT(g_uBufferUsed < g_uBufferSize);
165 static void _IndentTreeDumpMessage(ULONG uPly)
170 Append a number of spaces to the buffer to indent the next output
171 appropriately based upon the current search ply.
175 ULONG uPly : the current search ply
183 ULONG uSpaces = uPly * SPACES_TO_INDENT_PER_PLY;
184 ASSERT(uSpaces < g_uBufferSizeBytes);
185 ASSERT(HUMAN_READABLE);
188 _AppendToBuffer(" ");
195 DTTrace(ULONG uPly, CHAR *szMessage, ...)
200 A printf-like routine for adding a message to the buffer / dumpfile.
201 Note: messages that exceed MEDIUM_STRING_LEN_CHAR are truncated.
205 ULONG uPly : the current search ply
206 CHAR *szMessage : the message format string
207 ... : variable number of interpolated arguments
216 CHAR buf[MEDIUM_STRING_LEN_CHAR];
220 // Populate the local buffer
222 va_start(ap, szMessage);
223 COMPILER_VSNPRINTF(buf, MEDIUM_STRING_LEN_CHAR - 2, szMessage, ap);
225 #ifdef HUMAN_READABLE
227 _IndentTreeDumpMessage(uPly);
229 _AppendToBuffer(buf);
234 CleanupTreeDump(void)
239 Tear down the tree dumping system
252 // Cleanup file and buffer
254 if (NULL != pfTreeDump)
261 if (NULL != g_Buffer)
263 SystemFreeMemory(g_Buffer);
271 DTEnterNode(SEARCHER_THREAD_CONTEXT *ctx,
280 Called by search or qsearch upon entering a new node.
284 SEARCHER_THREAD_CONTEXT *ctx : searcher context
286 FLAG fIsQNode : is it a q node?
287 SCORE iAlpha : current alpha
288 SCORE iBeta : current beta
296 ULONG uPly = ctx->uPly;
297 UINT64 u64NodeNum = ctx->sCounters.tree.u64TotalNodeCount;
300 if (FALSE == fIsQNode)
302 DTTrace(uPly, "<n n=\"%"
303 COMPILER_LONGLONG_UNSIGNED_FORMAT
308 DTTrace(uPly, "<qn n=\"%"
309 COMPILER_LONGLONG_UNSIGNED_FORMAT
311 p = PositionToFen(&ctx->sPosition);
313 DTTrace(uPly + 1, "<fen p=\"%s\"/>", p);
315 DTTrace(uPly + 1, "<i ab=\"%d, %d\" ply=\"%u\" depth=\"%u\"/>",
316 iAlpha, iBeta, uPly, uDepth);
322 DTLeaveNode(SEARCHER_THREAD_CONTEXT *ctx,
330 Called by the search upon leaving a normal (non q) node.
334 SEARCHER_THREAD_CONTEXT *ctx : searcher context
335 SCORE iBestScore : best score found
336 MOVE mvBestMove : best move found
344 ULONG uPly = ctx->uPly;
346 DTTrace(uPly + 1, "<d score=\"%d\" mv=\"%s\"/>",
347 iBestScore, MoveToSan(mvBestMove, &ctx->sPosition));
350 DTTrace(uPly, "</n>");
354 DTTrace(uPly, "</qn>");