/// <summary> /// Get the best moved based on who has the most cards /// </summary> /// <param name="possibleCards">A list of possible cards to call</param> /// <param name="foundMove">An out parameter depending on if a move was found</param> /// <returns>The best move based on probability</returns> private CandidateMove GetHandNumberMove(List <int> possibleCards, out bool foundMove) { var bmHandNumber = new CandidateMove(); foundMove = false; int minNum = -1, minIndex = -1; for (int i = 0; i < handNumbers.Length; i++) { if (handNumbers[i] > minIndex) { minNum = handNumbers[i]; minIndex = i; } } List <CandidateMove> possibleCandidates = new List <CandidateMove>(); for (int i = 0; i < possibleCards.Count; i++) { if (cardProbability[minIndex][possibleCards[i]] > 0) { foundMove = true; bmHandNumber.CardId = possibleCards[i]; bmHandNumber.CardName = NumberCard[possibleCards[i]]; bmHandNumber.HitProbability = cardProbability[minIndex][possibleCards[i]]; bmHandNumber.SenderId = 0; bmHandNumber.SenderName = "santiago"; bmHandNumber.TargetId = minIndex; bmHandNumber.TargetName = Players[minIndex]; possibleCandidates.Add(new CandidateMove() // can't add by reference { CardId = bmHandNumber.CardId, CardName = bmHandNumber.CardName, HitProbability = bmHandNumber.HitProbability, SenderId = bmHandNumber.SenderId, SenderName = bmHandNumber.SenderName, TargetId = bmHandNumber.TargetId, TargetName = bmHandNumber.TargetName }); } } return(possibleCandidates[new Random().Next(possibleCandidates.Count)]); }
/// <summary> /// Get the best move based on who has the card with highest probability /// </summary> /// <param name="possibleCards">A list of possible cards to call</param> /// <param name="foundMove">An out parameter depending on if a move was found</param> /// <returns>The best move based on probability</returns> private CandidateMove GetProbabilityMove(List <int> possibleCards, out bool foundMove) { // TODO: if there are several cards with equal probability randomize the card to choose var bmProbability = new CandidateMove(); foundMove = false; for (var i = 0; i < possibleCards.Count; i++) { for (var j = 1; j < cardProbability.Length; j++) { if (!(cardProbability[j][possibleCards[i]] > bmProbability.HitProbability)) { continue; } if (cardProbability[j][possibleCards[i]] < minProbabilityThreshold) { continue; } if (PlayerTeams[Players[j]] == PlayerTeams["santiago"]) { continue; } if (!MoveCostBenefit(new CandidateMove // make sure that the move meets cost-benefit { TargetName = Players[j], CardName = NumberCard[possibleCards[i]] })) { continue; } foundMove = true; bmProbability.TargetId = j; bmProbability.TargetName = Players[j]; bmProbability.SenderId = 0; bmProbability.SenderName = "santiago"; bmProbability.CardId = possibleCards[i]; bmProbability.CardName = NumberCard[possibleCards[i]]; bmProbability.HitProbability = cardProbability[j][possibleCards[i]]; } } // loop through all possible cards and find where the highest probability is return(bmProbability); }
/// <summary> /// Calculate the check if the given moves passes cost benefit analysis /// </summary> /// <param name="cc">CandidateMove to check</param> /// <returns>Returns whether or not the move passes cost benefit</returns> private bool MoveCostBenefit(CandidateMove cc) { return((1.0 - cardProbability[Players.IndexOf(cc.TargetName)][CardIndex[cc.CardName]]) * CountPossibleLoss(Players.IndexOf(cc.TargetName)) < cardProbability[Players.IndexOf(cc.TargetName)][CardIndex[cc.CardName]] * riskFactor); }
/// <summary> /// Get the best move based on who has a certain amount of a halfsuit /// </summary> /// <param name="possibleCards">A list of possible cards to call</param> /// <param name="foundMove">An out parameter depending on if a move was found</param> /// <returns>The best move based on the minimum number of cards in a suit</returns> private CandidateMove GetMinSuitMove(List <int> possibleCards, out bool foundMove) { var bmMinSuit = new CandidateMove(); foundMove = false; int bestPlayerID = 0, bestHalfSuitIndex = 0, minCardsFound = -1; for (var i = 1; i < haveHalfSuit.Length; i++) { // go through each player (except Santiago) for (var j = 0; j < haveHalfSuit[i].Length; j++) { // go through each halfsuit if (haveHalfSuit[i][j] > minCardsFound) { bestHalfSuitIndex = j; bestPlayerID = i; minCardsFound = haveHalfSuit[i][j]; } } } var possibleCardCalls = new List <CandidateMove>(); var bestCardProbability = 0.0; for (var j = 0; j < HalfSuits.Values.ToArray()[bestHalfSuitIndex].Length; j++) { int cardIdNum = CardIndex[HalfSuits.Values.ToArray()[bestHalfSuitIndex][j]]; if (!(cardProbability[bestPlayerID][cardIdNum] >= bestCardProbability)) { continue; } if (cardProbability[bestPlayerID][cardIdNum] < minHaveSuitThreshold) { continue; } if (!possibleCards.Contains(cardIdNum)) { continue; } if (PlayerTeams[Players[bestPlayerID]] == PlayerTeams["santiago"]) { continue; } if (!MoveCostBenefit(new CandidateMove // make sure that the move meets cost-benefit { TargetName = Players[bestPlayerID], CardName = NumberCard[cardIdNum] })) { continue; } foundMove = true; bestCardProbability = cardProbability[bestPlayerID][cardIdNum]; bmMinSuit.CardId = cardIdNum; bmMinSuit.CardName = NumberCard[cardIdNum]; bmMinSuit.HitProbability = bestCardProbability; bmMinSuit.SenderId = 0; bmMinSuit.SenderName = "santiago"; bmMinSuit.TargetId = bestPlayerID; bmMinSuit.TargetName = Players[bestPlayerID]; possibleCardCalls.Add(new CandidateMove() { CardId = bmMinSuit.CardId, CardName = bmMinSuit.CardName, HitProbability = bmMinSuit.HitProbability, SenderId = bmMinSuit.SenderId, SenderName = bmMinSuit.SenderName, TargetId = bmMinSuit.TargetId, TargetName = bmMinSuit.TargetName }); } return(foundMove ? possibleCardCalls[new Random().Next(possibleCardCalls.Count)] : null); }