From 87612d3dc25746a208b9f7853f06836bd2fe43c0 Mon Sep 17 00:00:00 2001 From: thorvald Date: Tue, 4 Jun 2024 01:04:04 +0200 Subject: [PATCH] Implemented check final contract --- src/bots.py | 75 ++++++++++++++++++++++++++++++++----- src/config/default_api.conf | 4 +- src/frontend/api.html | 1 + src/sample.py | 11 +++++- 4 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/bots.py b/src/bots.py index e0367c55..934f6281 100644 --- a/src/bots.py +++ b/src/bots.py @@ -10,6 +10,7 @@ from objects import BidResp, CandidateBid, Card, CardResp, CandidateCard from bidding import bidding +from collections import defaultdict import carding from util import hand_to_str, expected_tricks_sd, p_defeat_contract, follow_suit, calculate_seed, get_play_status @@ -243,17 +244,71 @@ def bid(self, auction): #print("self.models.check_final_contract", self.models.check_final_contract) #print("candidates[0].bid", candidates[0].bid) - if self.models.check_final_contract: - if candidates[0].bid == "PASS" and len(samples) > 0: + if len(auction) > 4 and self.models.check_final_contract and (passout or auction[-2] != "PASS"): + # We will avoid rescuing if we have a score of 500 or more + if candidates[0].bid == "PASS" and len(samples) > 0 and candidates[0].expected_score < 500: # We need to find a sample or two from the bidding - print(samples[0].split(" ")[0]) - X = self.get_binary_contract(self.seat, self.vuln, self.hand_str, samples[0].split(" ")[0]) - contract_id, doubled, tricks = self.models.contract_model.model[0](X) - contract = bidding.ID2BID[contract_id] + ("X" if doubled else "") - result = {"contract": contract, - "tricks": tricks} - print(result) - + alternatives = {} + current_contract = bidding.get_contract(auction)[0:2] + if self.verbose: + print("current_contract", current_contract) + for i in range(len(samples)): + if self.verbose: + print(samples[i].split(" ")[(self.seat + 2) % 4]) + X = self.get_binary_contract(self.seat, self.vuln, self.hand_str, samples[i].split(" ")[(self.seat + 2) % 4]) + contract_id, doubled, tricks = self.models.contract_model.model[0](X) + contract = bidding.ID2BID[contract_id] + ("X" if doubled else "") + if current_contract == contract: + if self.verbose: + print("Contract bid, stopping rescue") + break + + # if the contract is in candidates we assume previous calculations are right and we stop + for c in candidates: + if c.bid == contract: + if self.verbose: + print("Contract found in candidates, stopping rescue") + break + # Skip invalid bids + if bidding.can_bid(contract, auction): + result = {"contract": contract, "tricks": tricks} + score = scoring.score(contract, self.vuln, tricks) + if self.verbose: + print(result, score) + if contract not in alternatives: + alternatives[contract] = [] + alternatives[contract].append({"score": score, "tricks": tricks}) + + if len(alternatives) > 0: + # Initialize dictionaries to store counts and total scores + contract_counts = defaultdict(int) + contract_total_scores = defaultdict(int) + + # Iterate through the alternatives dictionary to populate counts and total scores + for contract, entries in alternatives.items(): + for entry in entries: + score = entry["score"] + + contract_counts[contract] += 1 + contract_total_scores[contract] += score + + # Calculate the average scores + contract_average_scores = {contract: contract_total_scores[contract] / contract_counts[contract] + for contract in contract_counts} + + # Print the results + if self.verbose: + print("Contract Counts:", dict(contract_counts)) + print("Contract Average Scores:", contract_average_scores) + # Find the contract with the highest count + max_count_contract = max(contract_counts, key=contract_counts.get) + # Unless we gain 300 we will not override BEN + if contract_average_scores[max_count_contract] > candidates[0].expected_score + 250: + candidatebid = CandidateBid(bid=max_count_contract, insta_score=-1, + expected_score=contract_average_scores[max_count_contract], adjust=0) + candidates.insert(0, candidatebid) + who = "Rescue" + print(f"Rescuing {current_contract} {max_count_contract}") # We return the bid with the highest expected score or highest adjusted score return BidResp(bid=candidates[0].bid, candidates=candidates, samples=samples[:self.sample_hands_for_review], shape=p_shp, hcp=p_hcp, who=who, quality=good_quality) diff --git a/src/config/default_api.conf b/src/config/default_api.conf index 851d501d..ba331b01 100644 --- a/src/config/default_api.conf +++ b/src/config/default_api.conf @@ -34,7 +34,7 @@ use_biddingquality = True # Upvote the samples that matches the bidding best use_probability = False # Before the final pass validate the contract with a neural network -check_final_contract = False +check_final_contract = True [adjustments] # Are adjustments enabled @@ -172,4 +172,4 @@ sample_hands_opening_lead = 200 # Max number of samples to include when reviewing a board sample_hands_for_review = 20 # If probability for a bid is below this, then drop the sample -exclude_samples = 0.001 +exclude_samples = 0.07 diff --git a/src/frontend/api.html b/src/frontend/api.html index 3bd1d9fa..da657eda 100644 --- a/src/frontend/api.html +++ b/src/frontend/api.html @@ -472,6 +472,7 @@

Enter Board information

if (tokenKey && !tokens[0].startsWith("[")) { if (tokenKey === 'Auction') { line = line.replace(/Pass/g,"P").trim() + line = line.replace(/PASS/g,"P").trim() line = line.replace(/NT/g,"N") line = line.replace(/ =\d+=/, ''); line = line.replace(/\s/g,"-") diff --git a/src/sample.py b/src/sample.py index a4b56da6..4ec60f9c 100644 --- a/src/sample.py +++ b/src/sample.py @@ -276,7 +276,7 @@ def sample_cards_auction(self, auction, nesw_i, hand_str, vuln, n_samples, rng, n_samples = lho_pard_rho.shape[0] if self.verbose: - print(f"n_samples {n_samples} matching bidding info") + print(f"n_samples {n_samples} from bidding info") print("n_steps", n_steps) if (models.model_version == 0 or models.ns == -1): index = 0 @@ -321,11 +321,18 @@ def sample_cards_auction(self, auction, nesw_i, hand_str, vuln, n_samples, rng, for i in range(n_steps): if lho_actual_bids[i] not in (bidding.BID2ID['PAD_START'], bidding.BID2ID['PAD_END']): min_scores_lho = np.minimum(min_scores_lho, lho_sample_bids[:, i, lho_actual_bids[i]]) + #print(lho_actual_bids[i]) + if (lho_actual_bids[i] == 31): + for j in range(n_samples): + if (lho_sample_bids[j, i, lho_actual_bids[i]] >0.3): + print(hand_to_str(lho_pard_rho[j, 0:1, :])) + print(lho_sample_bids[j, i, lho_actual_bids[i]]) + if pard_actual_bids[i] not in (bidding.BID2ID['PAD_START'], bidding.BID2ID['PAD_END']): min_scores_partner = np.minimum(min_scores_partner, pard_sample_bids[:, i, pard_actual_bids[i]]) if rho_actual_bids[i] not in (bidding.BID2ID['PAD_START'], bidding.BID2ID['PAD_END']): min_scores_rho = np.minimum(min_scores_rho, rho_sample_bids[:, i, rho_actual_bids[i]]) - + if self.use_distance: # Initialize an array to store distances distances = np.zeros(n_samples)