summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2014-12-22 17:12:06 +0000
committeremkael <emkael@tlen.pl>2014-12-22 17:12:06 +0000
commitc113941d5b292a9d65954b0e4b640ffd025d0631 (patch)
tree6dd86e7d29d980aee00aa1c03086e3a4c84bb102
parent9cd94c487bc8dbd7e5d2eed3c9efa461ef1dda51 (diff)
* moving constants around
* scoring single contract depending on the outcome git-svn-id: https://svn.emkael.info/an9k@37 05ec0d5d-773b-4d93-9e23-c81a7ac79feb
-rw-r--r--Analizator9000/Analizator9000/BCalcWrapper.cs38
-rw-r--r--Analizator9000/Analizator9000/Contract.cs219
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
/// <summary>
/// Structure holding single deal analysis result.
/// </summary>
- struct BCalcResult
+ public struct BCalcResult
{
/// <summary>
- /// Denomination: non-trumps
- /// </summary>
- public const int DENOMINATION_NONTRUMP = 0;
- /// <summary>
- /// Denomination: spades
- /// </summary>
- public const int DENOMINATION_SPADES = 1;
- /// <summary>
- /// Denomination: hearts
- /// </summary>
- public const int DENOMINATION_HEARTS = 2;
- /// <summary>
- /// Denomination: diamonds
- /// </summary>
- public const int DENOMINATION_DIAMONDS = 3;
- /// <summary>
- /// Denomination: clubs
- /// </summary>
- public const int DENOMINATION_CLUBS = 4;
- /// <summary>
/// Trump denomination (N/S/H/D/C).
/// </summary>
public char trumpSuit;
/// <summary>
- /// Declarer: North
- /// </summary>
- public const int DECLARER_NORTH = 0;
- /// <summary>
- /// Declarer: East
- /// </summary>
- public const int DECLARER_EAST = 1;
- /// <summary>
- /// Declarer: South
- /// </summary>
- public const int DECLARER_SOUTH = 2;
- /// <summary>
- /// Declarer: West
- /// </summary>
- public const int DECLARER_WEST = 3;
- /// <summary>
/// Declaring player (N/E/S/W).
/// </summary>
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,11 +6,63 @@ using System.Text;
namespace Analizator9000
{
/// <summary>
- /// Tuple describing contract parameters. Created only because .NET 3.5 doesn't have Tuple type yet.
+ /// Tuple describing contract parameters.
/// </summary>
- class Contract: IEquatable<Contract>
+ public class Contract: IEquatable<Contract>
{
/// <summary>
+ /// Denomination: non-trumps
+ /// </summary>
+ public const int DENOMINATION_NONTRUMP = 4;
+ /// <summary>
+ /// Denomination: spades
+ /// </summary>
+ public const int DENOMINATION_SPADES = 3;
+ /// <summary>
+ /// Denomination: hearts
+ /// </summary>
+ public const int DENOMINATION_HEARTS = 2;
+ /// <summary>
+ /// Denomination: diamonds
+ /// </summary>
+ public const int DENOMINATION_DIAMONDS = 1;
+ /// <summary>
+ /// Denomination: clubs
+ /// </summary>
+ public const int DENOMINATION_CLUBS = 0;
+ /// <summary>
+ /// Declarer: North
+ /// </summary>
+ public const int DECLARER_NORTH = 0;
+ /// <summary>
+ /// Declarer: East
+ /// </summary>
+ public const int DECLARER_EAST = 1;
+ /// <summary>
+ /// Declarer: South
+ /// </summary>
+ public const int DECLARER_SOUTH = 2;
+ /// <summary>
+ /// Declarer: West
+ /// </summary>
+ public const int DECLARER_WEST = 3;
+ /// <summary>
+ /// Vulnerability: none
+ /// </summary>
+ public const int VULNERABLE_NONE = 0;
+ /// <summary>
+ /// Vulnerability: all
+ /// </summary>
+ public const int VULNERABLE_BOTH = 1;
+ /// <summary>
+ /// Vulnerability: NS
+ /// </summary>
+ public const int VULNERABLE_NS = 2;
+ /// <summary>
+ /// Vulnerability: EW
+ /// </summary>
+ public const int VULNERABLE_EW = 3;
+ /// <summary>
/// Level of the contract.
/// </summary>
public int Level;
@@ -20,6 +72,18 @@ namespace Analizator9000
/// <see cref="BCalcWrapper"/>
public int Denomination;
/// <summary>
+ /// Contract without double
+ /// </summary>
+ public const int MODIFIERS_NONE = 0;
+ /// <summary>
+ /// Contract doubled
+ /// </summary>
+ public const int MODIFIERS_DOUBLE = 1;
+ /// <summary>
+ /// Contract redoubled
+ /// </summary>
+ public const int MODIFIERS_REDOUBLE = 2;
+ /// <summary>
/// Modifiers - double or redouble.
/// </summary>
public int Modifiers;
@@ -28,7 +92,15 @@ namespace Analizator9000
/// </summary>
/// <see cref="BCalcWrapper"/>
public int Declarer;
-
+ /// <summary>
+ /// Number of occurrences of the contract within board traveller.
+ /// </summary>
+ public int Frequency;
+ /// <summary>
+ /// Position of the contract in boards traveller table.
+ /// </summary>
+ public int TableRow;
+
/// <summary>
/// Constructor for contract without full information (just general trick-taking in a denomination).
/// </summary>
@@ -47,12 +119,16 @@ namespace Analizator9000
/// <param name="denom">Trump denomination.</param>
/// <param name="decl">Declaring player.</param>
/// <param name="modifiers">Modifiers: 1 = X, 2 = XX</param>
- public Contract(int level, int denom, int decl, int modifiers = 0)
+ /// <param name="frequency">Traveller frequency</param>
+ /// <param name="tableRow">Traveller row index</param>
+ 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;
}
/// <summary>
@@ -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;
+ }
+
+ /// <summary>
+ /// Method used in object comparisons, taking the Equals() method into account.
+ /// <see cref="Equals"/>
+ /// </summary>
+ /// <returns>Object hash</returns>
+ 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;
+ }
+
+ /// <summary>
+ /// Calculates score for contract result
+ /// </summary>
+ /// <param name="result">BCalc output result</param>
+ /// <param name="vulnerability">Vulnerability for the deal</param>
+ /// <returns>Score for NS pair</returns>
+ 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;
}
}
}