public void ProcessMove(CardCall cc) { moveList.Add(cc); if (cc.Result == CallResult.Miss) { PlayerTurn = cc.TargetName; } }
public void ExportAFN(string gameName) { string fileString = ""; for (int i = 0; i < moveList.Count; i++) { string data = ""; if (moveList[i].GetType() == typeof(SuitCall)) { SuitCall c = (SuitCall)moveList[i]; data += c.SenderName + ";" + c.Team + ";" + c.HalfSuitName + ";"; if (c.Result == CallResult.Hit) { data += "hit"; } else if (c.Result == CallResult.Miss) { data += "miss"; } else { data += "unknown"; } fileString += data + Environment.NewLine; } else if (moveList[i].GetType() == typeof(CardCall)) { CardCall c = (CardCall)moveList[i]; data += c.SenderName + ";" + c.TargetName + ";" + c.CardRequested + ";"; if (c.Result == CallResult.Hit) { data += "hit"; } else if (c.Result == CallResult.Miss) { data += "miss"; } else { data += "unknown"; } fileString += data + Environment.NewLine; } } string path = gameName + ".afn"; if (!File.Exists(path)) { File.Create(path); } File.WriteAllText(path, fileString); }
/// <summary> /// Given the state of the game will return the move that Santiago will make /// </summary> /// <param name="gameState">An instance of Game that ends on Santiago's turn</param> /// <returns></returns> public CardCall MakeMove(Game gameState) { var bestCardCall = new CardCall { Result = CallResult.Unknown, SenderName = "santiago" }; var possibleCards = GetPossibleCards(); var bmProbability = GetProbabilityMove(possibleCards, out bool foundMove); if (foundMove) { bestCardCall.CardRequested = bmProbability.CardName; bestCardCall.TargetName = bmProbability.TargetName; return(bestCardCall); } Utility.Debug("No Probability Move found... Using MinSuit"); var bmHaveSuit = GetMinSuitMove(possibleCards, out foundMove); if (foundMove) { bestCardCall.CardRequested = bmHaveSuit.CardName; bestCardCall.TargetName = bmHaveSuit.TargetName; return(bestCardCall); } Utility.Debug("No MinSuit Move found... Using NumberHand"); var bmHandNumber = GetHandNumberMove(possibleCards, out foundMove); if (foundMove) { bestCardCall.CardRequested = bmHandNumber.CardName; bestCardCall.TargetName = bmHandNumber.TargetName; return(bestCardCall); } Utility.Error("No strategy procduced a valid move!!!!!"); return(null); // shouldn't happen if thresholds are low enough }
public static void PrintCardCall(CardCall cc) { var strResult = ""; if (cc.Result == CallResult.Unknown) { strResult = "Unknown..."; } else { strResult = cc.Result == CallResult.Hit ? "Hit!" : "Miss!"; } Console.ForegroundColor = ConsoleColor.DarkCyan; Console.WriteLine($"{cc.SenderName} called {cc.CardRequested} from {cc.TargetName} and it was a {strResult}"); Console.ForegroundColor = ConsoleColor.White; }
/// <summary> /// Processes each move in the game /// Changes probabilities etc... /// </summary> /// <param name="cc">The move that was made</param> public void ProcessMove(CardCall cc) { int halfSuitNumber; for (halfSuitNumber = 0; halfSuitNumber < HalfSuits.Count; halfSuitNumber++) { if (HalfSuits.Values.ToArray()[halfSuitNumber].Contains(cc.CardRequested)) { break; // get the halfsuit index that the called card was in } } if (cc.Result == CallResult.Hit) { handNumbers[Players.IndexOf(cc.SenderName)]++; handNumbers[Players.IndexOf(cc.TargetName)]--; if (cc.TargetName == "santiago") { hand.Remove(CardIndex[cc.CardRequested]); publicProbability[CardIndex[cc.CardRequested]] = 0; } if (cc.SenderName == "santiago") { hand.Add(CardIndex[cc.CardRequested]); publicProbability[CardIndex[cc.CardRequested]] = 1; } for (var i = 0; i < 6; i++) { if (i == Players.IndexOf(cc.SenderName)) { cardProbability[i][CardIndex[cc.CardRequested]] = 1.0; // He must also have another of the same suit if (haveHalfSuit[i][halfSuitNumber] >= 2) { haveHalfSuit[i][halfSuitNumber]++; // each card they call after that adds 1 } if (haveHalfSuit[i][halfSuitNumber] == -1) { haveHalfSuit[i][halfSuitNumber] = 2; // card they gained and at least one more } if (haveHalfSuit[Players.IndexOf(cc.TargetName)][halfSuitNumber] != -1) // { haveHalfSuit[Players.IndexOf(cc.TargetName)][halfSuitNumber]--; // target loses one of that halfsuit } } else { cardProbability[i][CardIndex[cc.CardRequested]] = 0.0; } } } else if (cc.Result == CallResult.Miss) { if (cc.SenderName == "santiago") { publicProbability[CardIndex[cc.CardRequested]] = 0; } for (var i = 0; i < 6; i++) { if (i == Players.IndexOf(cc.SenderName) || i == Players.IndexOf(cc.TargetName)) { double spreadProb = cardProbability[i][CardIndex[cc.CardRequested]] / 5.0; for (var j = 0; j < 6; j++) { if (j == i) { continue; } cardProbability[i][CardIndex[cc.CardRequested]] += spreadProb; } cardProbability[i][CardIndex[cc.CardRequested]] = 0.0; } } // which halfsuit is cardRequested in for (var i = 0; i < HalfSuits.Values.ToArray().Length; i++) { if (HalfSuits.Values.ToArray()[i].Contains(cc.CardRequested)) { haveHalfSuit[Players.IndexOf(cc.SenderName)][i] = Math.Max(haveHalfSuit[Players.IndexOf(cc.SenderName)][i], 1); } } } double knownCards = 0; for (int k = 0; k < 6; k++) { knownCards += Math.Max(0, haveHalfSuit[k][halfSuitNumber]); } for (int j = 0; j < HalfSuits[HalfSuits.Keys.ToArray()[halfSuitNumber]].Length; j++) { int cardID = CardIndex[HalfSuits[HalfSuits.Keys.ToArray()[halfSuitNumber]][j]]; if (Math.Abs(cardProbability[Players.IndexOf(cc.SenderName)][cardID]) < 0.01) // account for cards that you know they DON'T have { knownCards++; } } knownCards = Math.Min(knownCards, 6); for (int j = 0; j < HalfSuits[HalfSuits.Keys.ToArray()[halfSuitNumber]].Length; j++) { int cardID = CardIndex[HalfSuits[HalfSuits.Keys.ToArray()[halfSuitNumber]][j]]; bool changeCard = true; for (int k = 0; k < 6; k++) { if (Math.Abs(cardProbability[k][cardID] - 1) < 0.01) { changeCard = false; } } if (Math.Abs(cardProbability[Players.IndexOf(cc.SenderName)][cardID]) < 0.01) { changeCard = false; } if (changeCard) { cardProbability[Players.IndexOf(cc.SenderName)][cardID] = Math.Max(cardProbability[Players.IndexOf(cc.SenderName)][cardID], 1 / (7 - knownCards)); if (Math.Abs(1 / (7 - knownCards) - 1) < 0.01) { cardProbability[Players.IndexOf(cc.SenderName)][cardID] = 2; } } } var teamSuitCall = CheckTeammateSuitCalls(); // check if you can certainly (kind of) get a suit if (teamSuitCall != null) { Console.WriteLine($"Santiago has called the {teamSuitCall.HalfSuitName}"); ProcessMove(teamSuitCall); } }
// ReSharper disable once UnusedParameter.Local private static void Main(string[] args) { #region Initalize // Initalize CardIndex and NumberCard CardNames = File.ReadAllLines("CardAssignments.txt"); for (var i = 0; i < CardNames.Length; i++) { CardIndex.Add(CardNames[i], i); // CardIndex[cardName] = cardNumericalValue NumberCard.Add(i, CardNames[i]); } // Initalize Halfsuits var halfSuitNames = File.ReadAllLines("HalfSuitNames.txt"); var tempHalfSuits = File.ReadAllLines("HalfSuits.txt"); for (var i = 0; i < tempHalfSuits.Length; i++) { HalfSuits.Add(halfSuitNames[i], tempHalfSuits[i].Split(',')); } Console.ForegroundColor = ConsoleColor.White; var ai = new AI(); Players.Add("santiago"); PlayerTeams.Add("santiago", "Blue"); for (var i = 2; i <= 6; i++) { Console.WriteLine($"What is player {i}'s name?"); string nameInput = Console.ReadLine()?.ToLower(); while (Players.Contains(nameInput)) { Console.WriteLine("That name is already taken!"); nameInput = Console.ReadLine()?.ToLower(); } Players.Add(nameInput); if (Players.Count % 2 == 0) { PlayerTeams.Add(nameInput, "Red"); } else { PlayerTeams.Add(nameInput, "Blue"); } } // initalize the Player (names) list #endregion // Start game var game = new Game(); Console.WriteLine("Who's turn it is?"); string inpPlayerTurn = Console.ReadLine()?.ToLower(); while (!Players.Contains(inpPlayerTurn)) { Utility.Alert($"{inpPlayerTurn} is not a player! Please enter a valid player name."); inpPlayerTurn = Console.ReadLine(); } game.PlayerTurn = inpPlayerTurn; while (!game.GameOver) { if (game.PlayerTurn != "santiago") { // Take in move made Console.WriteLine($"{game.PlayerTurn}'s turn! What move did they make?"); var moveData = Console.ReadLine()?.Split(" "); if (moveData?[0] == "call") // ["call", HalfSuit, Result] { // Halfsuit Called if (!HalfSuits.ContainsKey(moveData?[1])) { Utility.Error("Halfsuit not recognized!"); continue; } if (moveData?[2] != "hit" && moveData?[2] != "miss") { Utility.Error("Result not recognized!"); continue; } var res = moveData[2] == "hit" ? CallResult.Hit : CallResult.Miss; var sc = new SuitCall(moveData[1].ToUpper(), PlayerTeams[game.PlayerTurn], game.PlayerTurn, res); game.ProcessMove(sc); ai.ProcessMove(sc); } else if (Players.Contains(moveData?[0])) // [TargetName, CardName, Result] { // Card Called if (!CardIndex.ContainsKey(moveData?[1])) { Utility.Error("Card not recognized!"); continue; } if (moveData?[2] != "hit" && moveData?[2] != "miss") { Utility.Error("Result not recognized!"); continue; } var res = moveData?[2] == "hit" ? CallResult.Hit : CallResult.Miss; var cc = new CardCall(moveData?[0].ToLower(), game.PlayerTurn, moveData?[1], res); game.ProcessMove(cc); ai.ProcessMove(cc); } else { Utility.Error("Invalid command! Calltype not recognized!"); game.ExportAFN("testGame"); } } else { // Make a move // ReSharper disable once InconsistentNaming var AIMove = ai.MakeMove(game); Utility.PrintCardCall(AIMove); Console.WriteLine("Result of Santiago's move? Hit/Miss"); string resString = Console.ReadLine()?.ToLower(); AIMove.Result = resString == "hit" ? CallResult.Hit : CallResult.Miss; ai.ProcessMove(AIMove); game.ProcessMove(AIMove); } } }