From c113941d5b292a9d65954b0e4b640ffd025d0631 Mon Sep 17 00:00:00 2001 From: emkael Date: Mon, 22 Dec 2014 17:12:06 +0000 Subject: * moving constants around * scoring single contract depending on the outcome git-svn-id: https://svn.emkael.info/an9k@37 05ec0d5d-773b-4d93-9e23-c81a7ac79feb --- Analizator9000/Analizator9000/BCalcWrapper.cs | 38 +---- Analizator9000/Analizator9000/Contract.cs | 219 +++++++++++++++++++++++++- 2 files changed, 215 insertions(+), 42 deletions(-) diff --git a/Analizator9000/Analizator9000/BCalcWrapper.cs b/Analizator9000/Analizator9000/BCalcWrapper.cs index 7614e1c..fb8a87f 100644 --- a/Analizator9000/Analizator9000/BCalcWrapper.cs +++ b/Analizator9000/Analizator9000/BCalcWrapper.cs @@ -10,49 +10,13 @@ namespace Analizator9000 /// /// Structure holding single deal analysis result. /// - struct BCalcResult + public struct BCalcResult { - /// - /// Denomination: non-trumps - /// - public const int DENOMINATION_NONTRUMP = 0; - /// - /// Denomination: spades - /// - public const int DENOMINATION_SPADES = 1; - /// - /// Denomination: hearts - /// - public const int DENOMINATION_HEARTS = 2; - /// - /// Denomination: diamonds - /// - public const int DENOMINATION_DIAMONDS = 3; - /// - /// Denomination: clubs - /// - public const int DENOMINATION_CLUBS = 4; /// /// Trump denomination (N/S/H/D/C). /// public char trumpSuit; /// - /// Declarer: North - /// - public const int DECLARER_NORTH = 0; - /// - /// Declarer: East - /// - public const int DECLARER_EAST = 1; - /// - /// Declarer: South - /// - public const int DECLARER_SOUTH = 2; - /// - /// Declarer: West - /// - public const int DECLARER_WEST = 3; - /// /// Declaring player (N/E/S/W). /// public char declarer; diff --git a/Analizator9000/Analizator9000/Contract.cs b/Analizator9000/Analizator9000/Contract.cs index e6c4978..26e1d07 100644 --- a/Analizator9000/Analizator9000/Contract.cs +++ b/Analizator9000/Analizator9000/Contract.cs @@ -6,10 +6,62 @@ using System.Text; namespace Analizator9000 { /// - /// Tuple describing contract parameters. Created only because .NET 3.5 doesn't have Tuple type yet. + /// Tuple describing contract parameters. /// - class Contract: IEquatable + public class Contract: IEquatable { + /// + /// Denomination: non-trumps + /// + public const int DENOMINATION_NONTRUMP = 4; + /// + /// Denomination: spades + /// + public const int DENOMINATION_SPADES = 3; + /// + /// Denomination: hearts + /// + public const int DENOMINATION_HEARTS = 2; + /// + /// Denomination: diamonds + /// + public const int DENOMINATION_DIAMONDS = 1; + /// + /// Denomination: clubs + /// + public const int DENOMINATION_CLUBS = 0; + /// + /// Declarer: North + /// + public const int DECLARER_NORTH = 0; + /// + /// Declarer: East + /// + public const int DECLARER_EAST = 1; + /// + /// Declarer: South + /// + public const int DECLARER_SOUTH = 2; + /// + /// Declarer: West + /// + public const int DECLARER_WEST = 3; + /// + /// Vulnerability: none + /// + public const int VULNERABLE_NONE = 0; + /// + /// Vulnerability: all + /// + public const int VULNERABLE_BOTH = 1; + /// + /// Vulnerability: NS + /// + public const int VULNERABLE_NS = 2; + /// + /// Vulnerability: EW + /// + public const int VULNERABLE_EW = 3; /// /// Level of the contract. /// @@ -20,6 +72,18 @@ namespace Analizator9000 /// public int Denomination; /// + /// Contract without double + /// + public const int MODIFIERS_NONE = 0; + /// + /// Contract doubled + /// + public const int MODIFIERS_DOUBLE = 1; + /// + /// Contract redoubled + /// + public const int MODIFIERS_REDOUBLE = 2; + /// /// Modifiers - double or redouble. /// public int Modifiers; @@ -28,7 +92,15 @@ namespace Analizator9000 /// /// public int Declarer; - + /// + /// Number of occurrences of the contract within board traveller. + /// + public int Frequency; + /// + /// Position of the contract in boards traveller table. + /// + public int TableRow; + /// /// Constructor for contract without full information (just general trick-taking in a denomination). /// @@ -47,12 +119,16 @@ namespace Analizator9000 /// Trump denomination. /// Declaring player. /// Modifiers: 1 = X, 2 = XX - public Contract(int level, int denom, int decl, int modifiers = 0) + /// Traveller frequency + /// Traveller row index + public Contract(int level, int denom, int decl, int modifiers = 0, int frequency = 0, int tableRow = 0) { + this.Frequency = frequency; this.Level = level; this.Denomination = denom; this.Declarer = decl; this.Modifiers = modifiers; + this.TableRow = tableRow; } /// @@ -63,7 +139,140 @@ namespace Analizator9000 public bool Equals(Contract other) { return this.Denomination == other.Denomination && this.Declarer == other.Declarer && - this.Level == other.Level && this.Modifiers == other.Modifiers; + this.Level == other.Level && this.Modifiers == other.Modifiers && this.Frequency == other.Frequency && this.TableRow == other.TableRow; + } + + /// + /// Method used in object comparisons, taking the Equals() method into account. + /// + /// + /// Object hash + public override int GetHashCode() + { + int hash = this.Denomination; + hash *= 10; + hash += this.Declarer; + hash *= 10; + hash += this.Level; + hash *= 10; + hash += this.Modifiers; + hash *= 10; + hash += this.Frequency; + hash *= 10; + hash += this.TableRow; + return hash; + } + + /// + /// Calculates score for contract result + /// + /// BCalc output result + /// Vulnerability for the deal + /// Score for NS pair + public int getScore(BCalcResult result, int vulnerability) + { + // All PASS. + if (this.Level == 0) + { + return 0; + } + if (BCalcWrapper.table[this.Declarer] != result.declarer) + { + throw new Exception("Declarer mismatch!"); + } + // Determining vulnerability of the contract + bool vulnerable = (vulnerability == Contract.VULNERABLE_BOTH) + || (vulnerability == Contract.VULNERABLE_EW && this.Declarer == Contract.DECLARER_EAST) + || (vulnerability == Contract.VULNERABLE_EW && this.Declarer == Contract.DECLARER_WEST) + || (vulnerability == Contract.VULNERABLE_NS && this.Declarer == Contract.DECLARER_NORTH) + || (vulnerability == Contract.VULNERABLE_NS && this.Declarer == Contract.DECLARER_SOUTH); + int score = 0; + // Contract not made + if (this.Level + 6 > result.tricks) + { + int undertricks = this.Level + 6 - result.tricks; + if (this.Modifiers < 1) // undoubled undertricks + { + score = vulnerable ? -100 : -50; + score *= undertricks; + } + else // (re-)doubled undertricks + { + do + { + if (undertricks == 1) // first undertrick: 100 non-vul, 200 vul + { + score -= vulnerable ? 200 : 100; + } + else + { + if (undertricks == 2 && !vulnerable) // second non-vul undertrick: 200 + { + score -= 200; + } + else // further undertricks: 300 + { + score -= 300; + } + } + undertricks--; + } + while (undertricks > 0); + score *= this.Modifiers; // redouble doubles the score + } + } + else // Contract made, yay! + { + int parTricks = this.Level; + do + { + if (this.Denomination == Contract.DENOMINATION_NONTRUMP && parTricks == 1) // first non-trump trick: 40 + { + score += 40; + } + else // other tricks + { + switch (this.Denomination) + { + case Contract.DENOMINATION_NONTRUMP: + case Contract.DENOMINATION_SPADES: + case Contract.DENOMINATION_HEARTS: + score += 30; + break; + case Contract.DENOMINATION_DIAMONDS: + case Contract.DENOMINATION_CLUBS: + score += 20; + break; + } + } + parTricks--; + } + while (parTricks > 0); + if (this.Modifiers > 0) // (re-)doubled tricks + { + score *= this.Modifiers * 2; + } + score += (score >= 100) ? (vulnerable ? 500 : 300) : 50; // game premium + if (this.Level == 7) // grand slam premium + { + score += vulnerable ? 1500 : 1000; + } + else if (this.Level == 6) // small slam premium + { + score += vulnerable ? 750 : 500; + } + score += this.Modifiers * 50; // failed (re-)double premium + int overtricks = result.tricks - this.Level - 6; + score += this.Modifiers > 0 + ? (vulnerable ? 200 : 100) * this.Modifiers * overtricks // (re-)double overtricks: 100/200/200/400 + : overtricks * ((this.Denomination == Contract.DENOMINATION_CLUBS || this.Denomination == Contract.DENOMINATION_DIAMONDS) ? 20 : 30); // undoubled overtricks + } + // If EW played the board, the score is shifted to the other side + if (this.Declarer == Contract.DECLARER_WEST || this.Declarer == Contract.DECLARER_EAST) + { + score = -score; + } + return score; } } } -- cgit v1.2.3