private int alphabeta(Coordinate field, int boardvalue, int alpha, int beta, int depthbound, int depth #if PRETTY , string parent #endif ) { #if STATS ++nodesvisited; depthnodes[depth]++; if (depth > maxdepth) { maxdepth = depth; } #endif ++expirenodecnt; if (expirenodecnt >= 3000) { expirenodecnt = 0; //Console.WriteLine("Checking timeout: {0}", DateTime.Now); if (DateTime.Now > expiretime) { //Console.WriteLine("Timeout: {0}", DateTime.Now); throw new ABSearchTimeoutException(); } } int attacker = (depth % 2 == 0) ? 1 : -1; InterestingFieldAgent fieldagentbackup = (InterestingFieldAgent)fieldagent.Clone(); board[field.X, field.Y] = -1 * attacker; // remember: field comes still from the upper level. fieldagent.UpdateInterestingFieldArray(board, field); fieldagent.UpdateThreatLists(board, field, -1 * attacker); boardvalue += field.Val; #if PRETTY string thisnode = "" + nodesvisited; if (nodesvisited < 250) { string infostring = ""; infostring += "<table>"; infostring += "<tr><td>"; infostring += "node: " + thisnode + "-" + depthnodes[depth] + ", boardval: " + boardvalue + ", moveval: " + eval.statVal(board, field, -1 * attacker); infostring += "</td></tr>"; infostring += "<tr><td>compare val: " + field.Val + "</td></tr>"; infostring += "<tr><td>last move from: " + attacker * -1 + "</td></tr>"; infostring += "<tr><td>Own threats: " + fieldagent.ownthreatlist.Count + "</td></tr>"; foreach (Threat t in fieldagent.ownthreatlist) { infostring += "<tr><td>cat : " + t.category + "</td></tr>"; foreach (Coordinate c in t.fields) { infostring += "<tr><td>coord : " + c + "</td></tr>"; } } infostring += "<tr><td>Own threats added: " + fieldagent.ownaddedthreatlist.Count + "</td></tr>"; foreach (Threat t in fieldagent.ownaddedthreatlist) { infostring += "<tr><td>cat : " + t.category + "</td></tr>"; foreach (Coordinate c in t.fields) { infostring += "<tr><td>coord : " + c + "</td></tr>"; } } infostring += "<tr><td>Own threats removed: " + fieldagent.ownremovedthreatlist.Count + "</td></tr>"; foreach (Threat t in fieldagent.ownremovedthreatlist) { infostring += "<tr><td>cat : " + t.category + "</td></tr>"; foreach (Coordinate c in t.fields) { infostring += "<tr><td>coord : " + c + "</td></tr>"; } } infostring += "<tr><td>Opp threats: " + fieldagent.oppthreatlist.Count + "</td></tr>"; foreach (Threat t in fieldagent.oppthreatlist) { infostring += "<tr><td>cat : " + t.category + "</td></tr>"; foreach (Coordinate c in t.fields) { infostring += "<tr><td>coord : " + c + "</td></tr>"; } } infostring += "<tr><td>Opp threats added: " + fieldagent.oppaddedthreatlist.Count + "</td></tr>"; foreach (Threat t in fieldagent.oppaddedthreatlist) { infostring += "<tr><td>cat : " + t.category + "</td></tr>"; foreach (Coordinate c in t.fields) { infostring += "<tr><td>coord : " + c + "</td></tr>"; } } infostring += "<tr><td>Opp threats removed: " + fieldagent.oppremovedthreatlist.Count + "</td></tr>"; foreach (Threat t in fieldagent.oppremovedthreatlist) { infostring += "<tr><td>cat : " + t.category + "</td></tr>"; foreach (Coordinate c in t.fields) { infostring += "<tr><td>coord : " + c + "</td></tr>"; } } infostring += "</table>"; PrettyPrint.PrintBoard(wr, thisnode, board, infostring); wr.WriteLine("{0} -> {1};", parent, nodesvisited); } #endif if (boardvalue > StatValEvaluator.WINBORDER || boardvalue < -StatValEvaluator.WINBORDER) { board[field.X, field.Y] = 0; if (attacker == 1) { return(boardvalue - depth * 10000); } else { return(boardvalue + depth * 10000); } } if (depth == depthbound) { board[field.X, field.Y] = 0; return(boardvalue); } ArrayList fields = null; if (depth == 0) { fields = firstMoveFields; } else { fields = fieldagent.ReallyInterestingFields(board, attacker); } // Calculate the static value for all fields for (int i = 0; i < fields.Count; ++i) { Coordinate c = (Coordinate)fields[i]; board[c.X, c.Y] = attacker; InterestingFieldAgent valifabackup = (InterestingFieldAgent)fieldagent.Clone(); fieldagent.UpdateThreatLists(board, c, attacker); c.Val = eval.statVal(board, c, attacker); fieldagent = valifabackup; board[c.X, c.Y] = 0; fields[i] = c; } fields.Sort(); if (depth % 2 == 0) { //MAX node fields.Reverse(); foreach (Coordinate ifield in fields) { int max = alpha; if ((max = alphabeta(ifield, boardvalue, alpha, beta, depthbound, depth + 1 #if PRETTY , thisnode #endif )) > alpha) { alpha = max; if (depth == 0) { tmpbestfield = ifield; } } if (depth == 0) { Console.WriteLine("Got max from {0}: {1}", ifield, max); } if (alpha >= beta) { fieldagent = fieldagentbackup; if (depth == 0) { tmpbestfield = ifield; } board[field.X, field.Y] = 0; return(beta); } } fieldagent = fieldagentbackup; board[field.X, field.Y] = 0; return(alpha); } else { //MIN node foreach (Coordinate ifield in fields) { if (depth == 0) { tmpbestfield = ifield; } int min = beta; if ((min = alphabeta(ifield, boardvalue, alpha, beta, depthbound, depth + 1 #if PRETTY , thisnode #endif )) < beta) { beta = min; if (depth == 0) { tmpbestfield = ifield; } } if (alpha >= beta) { fieldagent = fieldagentbackup; if (depth == 0) { tmpbestfield = ifield; } board[field.X, field.Y] = 0; return(alpha); } } fieldagent = fieldagentbackup; board[field.X, field.Y] = 0; return(beta); } }