summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2016-06-03 14:02:45 +0200
committeremkael <emkael@tlen.pl>2016-06-03 14:02:45 +0200
commitdfe4c3b00198172c0f4bee6b26ce3962c69e4ccd (patch)
treee9fcc3567f12df3fbe970d0b601649788ab08418
parent734b29bb02802fd5a03359a1e77aff2c8f28fe9a (diff)
* lowest from equal contracts as par contract
-rw-r--r--doc/README.en.md4
-rw-r--r--doc/README.pl.md4
-rw-r--r--src/ParScore.cs47
3 files changed, 46 insertions, 9 deletions
diff --git a/doc/README.en.md b/doc/README.en.md
index bbf954a..2b5a381 100644
--- a/doc/README.en.md
+++ b/doc/README.en.md
@@ -51,8 +51,8 @@ There are some quirks to double dummy analysis results, which are purely convent
This includes:
* boards with the same par contract for both sides: par contract for the dealing side is assumed (contrary to [Richard Pavlicek's](http://www.rpbridge.net/7a23.htm) convention of assigning "Pass out" par contract in such cases)
- * from all equal par contracts (i.e. yielding the same score and not allowing a profitable sacrifice, or equally profitable sacrifices), the *highest* one is assigned as the par contract
- * when par contract is the same for both partners of a specific side, the declarer is unspecified (and may differ from BigDeal's)
+ * from all equal par contracts (i.e. yielding the same score), the *lowest* one is assumed the par contract
+ * when par contract is the same for both partners of a specific side, the declarer is unspecified (may, and usually will, differ from BigDeal's)
The priority of existing PBN tags treated as input sources for double dummy trick table and par contract/score is:
diff --git a/doc/README.pl.md b/doc/README.pl.md
index 8642d12..c2dd957 100644
--- a/doc/README.pl.md
+++ b/doc/README.pl.md
@@ -51,8 +51,8 @@ Rezultaty analizy "w widne" podlegają kilku umownym kwestiom. W przypadku jakic
Konwencje przyjęte w programie:
* w rozdaniach z tym samym optymalnym kontraktem dla obu stron jako minimaks przyjmuje się kontrakt dla strony rozdającej (w przeciwieństwie do koncepcji [Richarda Pavlicka](http://www.rpbridge.net/7a23.htm) przypisującej 4 pasy jako minimaks w tej sytuacji)
- * ze wszystkich równych kontraktów (tj. kontraktów wartych tyle samo i nieposiadających opłacalnej obrony, lub kontraktów będących równie opłacalnymi obronami), *najwyższy* z nich jest traktowany jako minimaks
- * w przypadku tego samego minimaksa z obu rąk tej samej strony, konkretny rozgrywający jest nieokreślony i wybrany dowolnie (i może różnić się od tego w wynikach BigDeal)
+ * ze wszystkich równych kontraktów (tj. kontraktów wartych tyle samo), *najniższy* z nich jest traktowany jako minimaks
+ * w przypadku tego samego minimaksa z obu rąk tej samej strony, konkretny rozgrywający jest nieokreślony i wybrany dowolnie (może, i zwykle będzie, różnić się od tego w wynikach BigDeal)
Istniejące w wejściowym pliku PBN tagi traktowano są jako źródło tabeli liczby lew oraz minimaksa teoretycznego w następującej kolejności:
diff --git a/src/ParScore.cs b/src/ParScore.cs
index 5032ea1..068be90 100644
--- a/src/ParScore.cs
+++ b/src/ParScore.cs
@@ -123,11 +123,13 @@ namespace BCDD
return nsPlaying ? nsHighest.Validate() : ewHighest.Validate();
}
ParContract highest = nsHighest.Higher(ewHighest) ? nsHighest : ewHighest;
+ ParContract otherSideHighest = nsHighest.Higher(ewHighest) ? ewHighest : nsHighest;
nsPlaying = ('N'.Equals(highest.Declarer) || 'S'.Equals(highest.Declarer));
bool defenseVulnerability = this.determineVulnerability(vulnerability, nsPlaying ? 'E' : 'N');
ParContract highestDefense = highest.GetDefense(ddTable, defenseVulnerability);
if (highestDefense != null)
{
+ // Highest contract has profitable defense
return highestDefense.Validate();
}
int denominationIndex = Array.IndexOf(BCalcWrapper.DENOMINATIONS, highest.Denomination);
@@ -151,13 +153,36 @@ namespace BCDD
{
ParContract contract = new ParContract(level, BCalcWrapper.DENOMINATIONS[i], BCalcWrapper.PLAYERS[player], false, 0);
contract.Score = contract.CalculateScore(ddTable[player, i], vulnerable);
- if (scoreSquared < contract.Score * highest.Score)
+ if (otherSideHighest.Higher(contract))
{
- possibleOptimums.Add(contract.GetDefense(ddTable, defenseVulnerability) ?? contract);
+ // Contract is lower than other side's contract
+ break;
}
- else
+ if (highest.Score * contract.Score > 0)
{
- break;
+ // Contract makes
+ if (Math.Abs(contract.Score) >= Math.Abs(highest.Score))
+ {
+ // Contract is profitable
+ ParContract defense = contract.GetDefense(ddTable, defenseVulnerability);
+ if (defense != null && (contract.Score * contract.Score > contract.Score * defense.Score))
+ {
+ // Contract has defense
+ possibleOptimums.Add(defense);
+ // So lower contracts will too.
+ break;
+ }
+ else
+ {
+ // Contract does not have defense
+ possibleOptimums.Add(contract);
+ }
+ }
+ else
+ {
+ // Contract is not profitable
+ break;
+ }
}
level--;
}
@@ -165,10 +190,22 @@ namespace BCDD
}
foreach (ParContract contract in possibleOptimums)
{
- if (Math.Abs(contract.Score) > Math.Abs(highest.Score) || (contract.Score == highest.Score && contract.Higher(highest)))
+ if ((Math.Abs(contract.Score) > Math.Abs(highest.Score)))
{
+ // Contract is more profitable
highest = contract;
}
+ else
+ {
+ if (contract.Score == highest.Score)
+ {
+ if (highest.Higher(contract))
+ {
+ // Equally profitable, but lower
+ highest = contract;
+ }
+ }
+ }
}
return highest.Validate();
}