From dfe4c3b00198172c0f4bee6b26ce3962c69e4ccd Mon Sep 17 00:00:00 2001 From: emkael Date: Fri, 3 Jun 2016 14:02:45 +0200 Subject: * lowest from equal contracts as par contract --- doc/README.en.md | 4 ++-- doc/README.pl.md | 4 ++-- src/ParScore.cs | 47 ++++++++++++++++++++++++++++++++++++++++++----- 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(); } -- cgit v1.2.3