public ParContract GetPBNParContract() { String contractField = this.board.GetOptimumResult(); if ("Pass".Equals(contractField)) { return(new ParContract()); } Match contractMatch = ParScore.pbnContractPattern.Match(contractField); if (!contractMatch.Success) { throw new ParScoreInvalidException("Invalid format for OptimumResult field: " + contractField); } String scoreField = this.board.GetOptimumScore(); Match scoreMatch = ParScore.pbnScorePattern.Match(scoreField); if (!scoreMatch.Success) { throw new ParScoreInvalidException("Invalid format for OptimumScore field: " + scoreField); } int score = Int16.Parse(scoreMatch.Groups[2].Value); if ("EW".Equals(scoreMatch.Groups[1].Value)) { score = -score; } ParContract contract = new ParContract(Int16.Parse(contractMatch.Groups[1].Value), contractMatch.Groups[2].Value[0], contractMatch.Groups[4].Value[0], "X".Equals(contractMatch.Groups[3].Value), score); return(contract.Validate()); }
private ParContract getHighestMakeableContract(int[,] ddTable, bool forNS = true, bool forEW = true) { ParContract contract = new ParContract(); int tricks = 0; for (int i = 3; i >= 0; i--) { if ((i % 2 == 0 && forNS) || (i % 2 == 1 && forEW)) { for (int j = 0; j < 5; j++) { int level = ddTable[i, j] - 6; if (level > contract.Level || (level == contract.Level && j > Array.IndexOf(BCalcWrapper.DENOMINATIONS, contract.Denomination))) { contract.Level = level; contract.Denomination = BCalcWrapper.DENOMINATIONS[j]; contract.Declarer = BCalcWrapper.PLAYERS[i]; tricks = ddTable[i, j]; } } } } String vulnerability = this.board.GetVulnerable().ToUpper(); bool vulnerable = this.determineVulnerability(vulnerability, contract.Declarer); contract.Score = contract.CalculateScore(tricks, vulnerable); return(contract); }
public void SaveParContract(ParContract contract) { this.DeleteOptimumScore(); this.WriteOptimumScore(contract); // we're not writing DDS custom fields, just parse them this.DeleteMinimax(); this.WriteMinimax(contract); }
public ParContract GetDefense(int[,] ddTable, bool vulnerable) { int declarerIndex = Array.IndexOf(BCalcWrapper.PLAYERS, this.Declarer); int denominationIndex = Array.IndexOf(BCalcWrapper.DENOMINATIONS, this.Denomination); if (this.Level != 0 && this.Level + 6 <= ddTable[declarerIndex, denominationIndex]) { List <int> defendersIndexes = new List <int>(); defendersIndexes.Add((declarerIndex + 1) & 3); defendersIndexes.Add((declarerIndex + 3) & 3); List <ParContract> possibleDefense = new List <ParContract>(); int scoreSquared = this.Score * this.Score; for (int i = 0; i < 5; i++) { int level = this.Level; if (i <= denominationIndex) { level++; } if (level <= 7) { foreach (int defender in defendersIndexes) { if (level + 6 > ddTable[defender, i]) { ParContract defense = new ParContract(level, BCalcWrapper.DENOMINATIONS[i], BCalcWrapper.PLAYERS[defender], true, 0); defense.Score = defense.CalculateScore(ddTable[defender, i], vulnerable); if (scoreSquared > this.Score * defense.Score) { possibleDefense.Add(defense); } } } } } if (possibleDefense.Count > 0) { possibleDefense.Sort((x, y) => Math.Abs(x.Score - this.Score).CompareTo(Math.Abs(y.Score - this.Score))); ParContract optimumDefense = possibleDefense.Last(); possibleDefense = possibleDefense.FindAll(x => x.Score == optimumDefense.Score); foreach (ParContract defense in possibleDefense) { // Lowest from the most profitable sacrifices if (optimumDefense.Higher(defense)) { optimumDefense = defense; } } return(optimumDefense); } } return(null); }
public void WriteMinimax(ParContract contract) { String minimax; if (contract.Score == 0) { minimax = "7NS0"; } else { minimax = String.Format("{0}{1}{2}{3}{4}", contract.Level, contract.Denomination, contract.Doubled ? "D" : "", contract.Declarer, contract.Score); } this.Fields.Add(new PBNField("Minimax", minimax)); }
public ParContract GetJFRParContract() { String parString = this.board.GetMinimax(); Match parMatch = ParScore.jfrContractPattern.Match(parString); if (!parMatch.Success) { throw new ParScoreInvalidException("Invalid format for Minimax field: " + parString); } if ("0".Equals(parMatch.Groups[4].Value)) { return(new ParContract()); // pass-out } ParContract contract = new ParContract(Int16.Parse(parMatch.Groups[1].Value), parMatch.Groups[2].Value[0], parMatch.Groups[4].Value[0], "D".Equals(parMatch.Groups[3].Value), Int16.Parse(parMatch.Groups[5].Value)); return(contract.Validate()); }
static void Main(string[] args) { List <String> files = Program.getFiles(args); List <String> errors = new List <String>(); if (files.Count > 0) { foreach (String filename in files) { try { Console.WriteLine("Analyzing " + filename); PBNFile file = new PBNFile(filename); foreach (PBNBoard board in file.Boards) { DDTable table = new DDTable(board); String boardNo; try { boardNo = board.GetNumber(); } catch (FieldNotFoundException) { boardNo = "?"; } try { int[,] ddTable = table.GetDDTable(); if (ddTable != null) { Console.WriteLine("Board " + boardNo); DDTable.PrintTable(ddTable); ParScore par = new ParScore(board); ParContract contract = par.GetParContract(ddTable); Console.WriteLine(contract); Console.WriteLine(); board.SaveDDTable(ddTable); board.SaveParContract(contract); } else { String error = "unable to determine DD table for board " + boardNo; errors.Add(String.Format("[{0}] {1}", filename, error)); Console.WriteLine("ERROR: " + error); } } catch (DllNotFoundException) { throw; } catch (Exception e) { errors.Add(String.Format("[{0}:{1}] {2}", filename, boardNo, e.Message)); Console.WriteLine("ERROR: " + e.Message); } file.WriteBoard(board); } file.Save(); } catch (DllNotFoundException e) { errors.Add("libbcalcdds.dll could not be loaded - make sure it's present in application directory!"); Console.WriteLine("ERROR: " + e.Message); break; } catch (Exception e) { errors.Add(e.Message); Console.WriteLine("ERROR: " + e.Message); } } if (errors.Count > 0) { Console.WriteLine("Following ERRORs occured:"); foreach (String error in errors) { Console.WriteLine(error); } Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } } }
public override bool Equals(object other) { ParContract obj = (ParContract)(other); return(this.Level == obj.Level && this.Denomination == obj.Denomination && this.Score == obj.Score); }
public bool Higher(ParContract obj) { return(this.Level > obj.Level || (this.Level == obj.Level && Array.IndexOf(BCalcWrapper.DENOMINATIONS, this.Denomination) > Array.IndexOf(BCalcWrapper.DENOMINATIONS, obj.Denomination))); }
public ParContract GetDDTableParContract(int[,] ddTable) { String dealer = this.board.GetDealer(); String vulnerability = this.board.GetVulnerable().ToUpper(); ParContract nsHighest = this.getHighestMakeableContract(ddTable, true, false); ParContract ewHighest = this.getHighestMakeableContract(ddTable, false, true); bool nsPlaying = ("N".Equals(dealer) || "S".Equals(dealer)); if (nsHighest == ewHighest) { 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); int declarerIndex = Array.IndexOf(BCalcWrapper.PLAYERS, highest.Declarer); List <int> playerIndexes = new List <int>(); playerIndexes.Add(declarerIndex); playerIndexes.Add((declarerIndex + 2) & 3); bool vulnerable = this.determineVulnerability(vulnerability, highest.Declarer); int scoreSquared = highest.Score * highest.Score; List <ParContract> possibleOptimums = new List <ParContract>(); for (int i = 0; i < 5; i++) { foreach (int player in playerIndexes) { int level = highest.Level; if (i > denominationIndex) { level--; } while (level > 0) { ParContract contract = new ParContract(level, BCalcWrapper.DENOMINATIONS[i], BCalcWrapper.PLAYERS[player], false, 0); contract.Score = contract.CalculateScore(ddTable[player, i], vulnerable); if (otherSideHighest.Higher(contract)) { // Contract is lower than other side's contract break; } if (highest.Score * contract.Score > 0) { // 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--; } } } foreach (ParContract contract in possibleOptimums) { 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()); }
public void WriteOptimumScore(ParContract contract) { this.Fields.Add(new PBNField("OptimumScore", String.Format("NS {0}", contract.Score))); }