using System; using System.Runtime.InteropServices; using System.Text.RegularExpressions; namespace Analizator9000 { /// /// Structure holding single deal analysis result. /// public struct BCalcResult { /// /// Trump denomination (N/S/H/D/C). /// public char trumpSuit; /// /// Declaring player (N/E/S/W). /// public char declarer; /// /// Number of tricks taken by the declaring side. /// public int tricks; /// /// Deal number, parsed out from input string. /// public long dealNo; /// /// Constructor for result structure. /// /// Trump denomination (N/S/H/D/C). /// Declaring player (N/E/S/W). /// Number of tricks taken by the declaring side. /// Deal number, parsed out from input string. public BCalcResult(char a, char b, int c, long d) { trumpSuit = a; declarer = b; tricks = c; dealNo = d; } }; /// /// Wrapper class for libbcalcDDS.ddl. /// class BCalcWrapper { /// /// Allocates new instance of BCalc solver. /// /// Deal format string. See the original documentation for details. /// Card distribution. /// Trump denomination, in numeric format. See the original documentation for details. /// Player on lead, in numeric format. See the original documentation for details. /// Pointer to solver instance. /// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#ab636045f65412652246b769e8e95ed6f [DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr bcalcDDS_new(IntPtr format, IntPtr hands, Int32 trump, Int32 leader); /// /// Conducts DD analysis. /// /// Pointer to solver instance. /// Number of tricks to take by leading side. /// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a369ce661d027bef3f717967e42bf8b33 [DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)] private static extern Int32 bcalcDDS_getTricksToTake(IntPtr solver); /// /// Checks for solver errors. /// /// Pointer to solver instance. /// Error string or NULL if no error accured. /// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a89cdec200cde91331d40f0900dc0fb46 [DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr bcalcDDS_getLastError(IntPtr solver); /// /// Frees allocated solver instance and cleans up after it. /// /// Pointer to solver instance. /// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a4a68da83bc7da4663e2257429539912d [DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void bcalcDDS_delete(IntPtr solver); /// /// Sets trump denomination and resets the analysis. /// /// Pointer to solver instance. /// Trump denomination, in numeric format. See the original documentation for details. /// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a88fba3432e66efa5979bbc9e1f044164 [DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void bcalcDDS_setTrumpAndReset(IntPtr solver, Int32 trump); /// /// Sets leading player and resets the analysis. /// /// Pointer to solver instance. /// Player on lead, in numeric format. See the original documentation for details. /// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a616031c1e1d856c4aac14390693adb4c [DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void bcalcDDS_setPlayerOnLeadAndReset(IntPtr solver, Int32 player); /// /// Translation table between player characters and numeric values. /// public static String table = "NESW"; /// /// Translation table between denomination characters and numeric values. /// public static String denominations = "CDHSN"; /// /// Pointer to solver instance. /// private IntPtr solver; /// /// Deal distribution. /// private String deal; /// /// Internal number of deal being analyzed. /// private long dealNo; /// /// Trump suit, in numeric format. /// private int trumps; /// /// Constructor of class instance for single deal analysis. /// /// Deal distribution prefixed with deal number. public BCalcWrapper(String deal) { try { Match dealMatch = Regex.Match(deal, @"^(\d+): (.*)$"); if (!dealMatch.Success) { throw new Exception(); } this.deal = dealMatch.Groups[2].Value; this.dealNo = Convert.ToInt64(dealMatch.Groups[1].Value); } catch (Exception) { throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_dealLoadError", Form1.GetCulture()) + ": " + deal); } this.solver = BCalcWrapper.bcalcDDS_new(Marshal.StringToHGlobalAnsi(BCalcWrapper.table), Marshal.StringToHGlobalAnsi(this.deal), 0, 0); this.errorCheck(); } /// /// Sets the trump denomination. /// /// Trump denomination, in numeric format. public void setTrump(int trumpSuit) { if (trumpSuit < 0) { throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_trumpError", Form1.GetCulture()) + ": " + trumpSuit); } BCalcWrapper.bcalcDDS_setTrumpAndReset(solver, trumpSuit); this.errorCheck(); this.trumps = trumpSuit; } /// /// Runs the single contract analysis. /// /// Declaring player, in numeric format. /// Result structur for the contract. //TODO substitute from actual number of tricks to analyze, rather than 13, maybe. public BCalcResult run(int declarer) { if (declarer < 0) { throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_declarerError", Form1.GetCulture()) + ": " + declarer); } int l = (declarer + 1) % 4; BCalcWrapper.bcalcDDS_setPlayerOnLeadAndReset(solver, l); this.errorCheck(); int result = BCalcWrapper.bcalcDDS_getTricksToTake(this.solver); this.errorCheck(); return new BCalcResult(BCalcWrapper.denominations[this.trumps], BCalcWrapper.table[declarer], 13 - result, this.dealNo); } /// /// Releases the solver instaces. /// public void destroy() { BCalcWrapper.bcalcDDS_delete(this.solver); } /// /// Checks for errors, throws exception if any occured. /// private void errorCheck() { IntPtr error = BCalcWrapper.bcalcDDS_getLastError(this.solver); String eStr = Marshal.PtrToStringAnsi(error); if (eStr != null) { throw new Exception(eStr); } } } }