public ClientBot(int Place, Table Table) { this.ActivePlace = Place; this.ActiveTable = Table; usedCards = new BaseCardList(); dontUsedCards = new CardList(); }
public ClientBot(int Place, Table Table, CardList cards) : this(Place, Table) { #if DEBUG Debug.WriteLine("Создание бота. Карты: {0}, Место: {1}, Стол: {2}", cards.ToString(), Place, Table.ID); #endif botCards = cards; RenewDontUsedCards(); }
// Создание списка бонусов из списка карт public BonusList(CardList cards) : base(cards) { list = new List<Bonus>(); SeniorBonus = null; // Если это не полная раздача карт на одного игрока - то что-то не так, отсюда нельзя создать список бонусов if (cards.Count != 8) return; // Выборка всех бонусов типа "последовательность" int streak = 1; for (var i = 1; i < cards.Count; i++) { // Проверяем, что две следующие друг за другом карты последовательны и одной масти if ((Math.Abs(((int)cards[i].Type) - ((int)cards[i - 1].Type)) == 1) && (cards[i].Suit == cards[i - 1].Suit)) { // Увеличиваем значение последовательности streak++; } else { // Если удалось собрать последовательность из 3 и более карт одной масти, то мы имеем бонус if (streak >= 3) { // Добавляем полученный бонус в список бонусов AddStreakBonus(cards, i, streak); } streak = 1; } } // После прохода по всем картам, может остаться неучтенной последняя имеющаяся последовательность if (streak >= 3) { AddStreakBonus(cards, 8, streak); } // Выборка всех бонусов типа 4Х for (var i = 0; i < 5; i++) { int c = 1; for (var j = i + 1; j < 8; j++) { if (cards[j].Type == cards[i].Type) c++; } if (c == 4) { // Добавляем бонус. В качестве козыря берем игру с козырем или без (для расчета стоимость 4XA if ((cards[i].Type != CardType.C_7) && (cards[i].Type != CardType.C_8)) AddBonusToList(new Bonus(BonusType.BONUS_4X, cards[i].Type, cards[i].IsGameWithTrump)); } } }
public Distribution() { Player1Cards = new CardList(); Player2Cards = new CardList(); Player3Cards = new CardList(); Player4Cards = new CardList(); Orders = new OrdersList(); bribes = new List<Bribe>(); ScoresTeam1 = 0; ScoresTeam2 = 0; IsCapotEnded = false; BonusesWinner = BeloteTeam.TEAM_NONE; Status = DistributionStatus.D_BAZAR; }
// Создание раздачи на четверых игроков /*public void Distribution(CardList p1, CardList p2, CardList p3, CardList p4) { // Если какой то из списков не предоставлен, то и колоду раздать не получится if ((p1 == null) || (p2 == null) || (p3 == null) || (p4 == null)) { return; } // Раздаем по 8 карт каждому игроку for (var i = 0; i < 8; i++) { p1.Add(GetRandomCard()); p2.Add(GetRandomCard()); p3.Add(GetRandomCard()); p4.Add(GetRandomCard()); } // Сортируем карты для всех игроков p1.Sort(); p2.Sort(); p3.Sort(); p4.Sort(); }*/ // Создание тестовой раздачи на четверых игроков public void Distribution(CardList p1, CardList p2, CardList p3, CardList p4) { // Если какой то из списков не предоставлен, то и колоду раздать не получится if ((p1 == null) || (p2 == null) || (p3 == null) || (p4 == null)) { return; } p1.Add(new Card(CardType.C_K, CardSuit.C_SPADES)); p1.Add(new Card(CardType.C_Q, CardSuit.C_SPADES)); p1.Add(new Card(CardType.C_J, CardSuit.C_SPADES)); p1.Add(new Card(CardType.C_J, CardSuit.C_HEARTS)); p1.Add(new Card(CardType.C_10, CardSuit.C_HEARTS)); p1.Add(new Card(CardType.C_9, CardSuit.C_HEARTS)); p1.Add(new Card(CardType.C_8, CardSuit.C_HEARTS)); p1.Add(new Card(CardType.C_7, CardSuit.C_HEARTS)); p2.Add(new Card(CardType.C_K, CardSuit.C_CLUBS)); p2.Add(new Card(CardType.C_Q, CardSuit.C_CLUBS)); p2.Add(new Card(CardType.C_J, CardSuit.C_CLUBS)); p2.Add(new Card(CardType.C_10, CardSuit.C_CLUBS)); p3.Add(new Card(CardType.C_9, CardSuit.C_CLUBS)); p3.Add(new Card(CardType.C_8, CardSuit.C_CLUBS)); p2.Add(new Card(CardType.C_7, CardSuit.C_CLUBS)); p2.Add(new Card(CardType.C_8, CardSuit.С_DIAMONDS)); p3.Add(new Card(CardType.C_10, CardSuit.C_SPADES)); p3.Add(new Card(CardType.C_9, CardSuit.C_SPADES)); p3.Add(new Card(CardType.C_8, CardSuit.C_SPADES)); p2.Add(new Card(CardType.C_7, CardSuit.C_SPADES)); p3.Add(new Card(CardType.C_10, CardSuit.С_DIAMONDS)); p2.Add(new Card(CardType.C_9, CardSuit.С_DIAMONDS)); p3.Add(new Card(CardType.C_J, CardSuit.С_DIAMONDS)); p3.Add(new Card(CardType.C_7, CardSuit.С_DIAMONDS)); p4.Add(new Card(CardType.C_A, CardSuit.C_CLUBS)); p4.Add(new Card(CardType.C_A, CardSuit.C_SPADES)); p4.Add(new Card(CardType.C_A, CardSuit.C_HEARTS)); p4.Add(new Card(CardType.C_A, CardSuit.С_DIAMONDS)); p4.Add(new Card(CardType.C_K, CardSuit.C_HEARTS)); p4.Add(new Card(CardType.C_Q, CardSuit.C_HEARTS)); p4.Add(new Card(CardType.C_K, CardSuit.С_DIAMONDS)); p4.Add(new Card(CardType.C_Q, CardSuit.С_DIAMONDS)); // Сортируем карты для всех игроков p1.Sort(); p2.Sort(); p3.Sort(); p4.Sort(); }
// Создание колоды для игры в блот public CardsDeck() { list = new CardList(); random = new Random(); // Добавляем в список все возможные карты в колоде foreach (CardSuit s in Enum.GetValues(typeof(CardSuit))) { if (s == CardSuit.C_NONE) continue; foreach (CardType t in Enum.GetValues(typeof(CardType))) { if (t == CardType.C_UNDEFINED) continue; list.Add(new Card(t, s)); } } }
public BaseBonusList(CardList cards) { #if DEBUG Debug.WriteLine("{0} Создание списка бонусов из списка карт: {1}", DateTime.Now, cards.ToString()); #endif }
// Обработка сообщений private void ProcessMessage(string command, string message) { Dictionary<string, string> bParams = Helpers.SplitCommandString(message); switch (command) { // Обработка раздачи карт case Messages.MESSAGE_GAME_DISTRIBUTIONCARDS: { botCards = new CardList(bParams["Cards"]); IsMakingOrder = false; usedCards.Clear(); RenewDontUsedCards(); //int totalScore1 = Int32.Parse(bParams["Scores1"]); //int totalScore2 = Int32.Parse(bParams["Scores2"]); break; } // Обработка перехода хода к данному боту case Messages.MESSAGE_GAME_BAZAR_NEXTBETPLAYER: { BetType bType = (BetType)Int32.Parse(bParams["Type"]); int minSize = Int32.Parse(bParams["MinSize"]); // Расчет и совершение заказа Thread.Sleep(500); Order order; if (!IsMakingOrder) { order = GetMaxPossibleOrder(); if (order.Size < minSize) order = new Order(OrderType.ORDER_PASS, 0, CardSuit.C_NONE); IsMakingOrder = true; } else order = new Order(OrderType.ORDER_PASS, 0, CardSuit.C_NONE); MakeOrder(order); break; } // Название ставки другого игрока case Messages.MESSAGE_GAME_BAZAR_SAYBET: { // НЕ НУЖНО break; } // Завершение процесса торговли case Messages.MESSAGE_GAME_BAZAR_END: { // НЕ НУЖНО break; } // Завершение процесса торговли без выбора козыря case Messages.MESSAGE_GAME_BAZAR_PASS: { // НЕ НУЖНО break; } // Переход хода к боту case Messages.MESSAGE_GAME_GAMING_NEXTPLAYER: { CardList PossibleCards = new CardList(bParams["Cards"]); // Расчет и показ бонусов Thread.Sleep(500); if (botBonuses != null) { if (botBonuses.Count > 0) { for (var i = botBonuses.Count - 1; i >= 0; i--) { if (botBonuses[i] != botBonuses.SeniorBonus) botBonuses.Delete(botBonuses[i]); } } AnnounceBonuses(botBonuses); } Thread.Sleep(500); // Расчет и совершение хода MakeMove(GetMovingCard(PossibleCards)); break; } // Извещение о ходе картой другим игроком case Messages.MESSAGE_GAME_GAMING_REMINDCARD: { int cardPlace = Int32.Parse(bParams["Place"]); Card newCard = new Card(bParams["Card"]); // Запоминание похоженной карты usedCards.Add(newCard); dontUsedCards.Remove(dontUsedCards[newCard.Type, newCard.Suit]); // int LocalScore1 = Int32.Parse(bParams["Scores1"]); // int LocalScore2 = Int32.Parse(bParams["Scores2"]); // int beloteRemind = Int32.Parse(bParams["Belote"]); break; } // Получение списка возможных бонусов case Messages.MESSAGE_GAME_BONUSES_ALL: { botBonuses = new BonusList(message); break; } // Оглашение типов бонусов другими игроками case Messages.MESSAGE_GAME_BONUSES_TYPES: { // НЕ НУЖНО break; } // Оглашение победителя бонусов case Messages.MESSAGE_GAME_BONUSES_WINNER: { // НЕ НУЖНО break; } default: { break; } } }
// Получение максимального возможного заказа для одной масти private Order GetOrderForSuit(CardSuit Suit) { Order result; try { int KCount = 0; int Aces = 0; int AceAnd10 = 0; int Ace10K = 0; int Ace10KQ = 0; CardList tempCardList = new CardList(botCards.ToString()); tempCardList.SetTrump(Suit); // Подсчет количества козырных карт, некозырных тузов и пар некозырных туз-10, туз-10-к, туз-10-к-д for (var i = 0; i < tempCardList.Count; i++) { if (tempCardList[i].IsTrump) { KCount++; } else { if (tempCardList[i].Type == CardType.C_A) { Aces++; if (tempCardList.Exists(new Card(CardType.C_10, tempCardList[i].Suit))) { AceAnd10++; if (tempCardList.Exists(new Card(CardType.C_K, tempCardList[i].Suit))) { Ace10K++; if (tempCardList.Exists(new Card(CardType.C_Q, tempCardList[i].Suit))) { Ace10KQ++; } } } } } } int orderSize = 0; // Выбираем размер ставки при игре с козырем if (Suit != CardSuit.C_NONE) { bool JackK = tempCardList.Exists(new Card(CardType.C_J, Suit)); bool NineK = tempCardList.Exists(new Card(CardType.C_9, Suit)); if ((JackK) && (NineK) && ((KCount + Aces) >= 4)) orderSize = 80; if ((JackK) && (NineK) && ((KCount + Aces) >= 5)) orderSize = 90; if ((JackK) && (NineK) && ((KCount + Aces) >= 5) && (AceAnd10 > 0)) orderSize = 100; if ((JackK) && (NineK) && (KCount >= 4) && (Aces >= 2)) orderSize = 110; if ((JackK) && (NineK) && (KCount >= 5) && (Aces >= 1)) orderSize = 120; if ((JackK) && (NineK) && (KCount >= 5) && (Aces >= 2)) orderSize = 130; if ((JackK) && (NineK) && (KCount >= 5) && (Aces >= 2) && (AceAnd10 > 0)) orderSize = 140; if ((JackK) && (KCount >= 6) && (Aces >= 1)) orderSize = 150; if ((JackK) && (KCount >= 7)) orderSize = 160; if (KCount == 8) orderSize = 250; if ((tempCardList.IsBelote) && (orderSize != 0)) orderSize += 20; } // Выбираем размер ставки при игре без козыря else { if (Aces >= 3) orderSize = 80; if ((Aces >= 3) && (AceAnd10 >= 1)) orderSize = 90; if ((Aces >= 3) && (AceAnd10 >= 2)) orderSize = 100; if ((Aces >= 3) && (AceAnd10 >= 3)) orderSize = 110; if ((Aces >= 3) && (AceAnd10 >= 2) && (Ace10K > 0)) orderSize = 120; if ((Aces >= 3) && (AceAnd10 >= 2) && (Ace10KQ > 0)) orderSize = 130; if ((Aces >= 4) && (AceAnd10 >= 1)) orderSize = 140; if ((Aces >= 4) && (AceAnd10 >= 2)) orderSize = 150; if ((Aces >= 4) && (AceAnd10 >= 3)) orderSize = 160; if ((Aces >= 4) && (AceAnd10 >= 4)) orderSize = 250; } if (orderSize == 0) { result = new Order(OrderType.ORDER_PASS, orderSize, CardSuit.C_NONE); } else { if (orderSize >= 250) { result = new Order(OrderType.ORDER_CAPOT, orderSize, Suit); } else { result = new Order(OrderType.ORDER_BET, orderSize, Suit); } } return result; } catch { return new Order(OrderType.ORDER_PASS, 0, CardSuit.C_NONE); } }
// Выбор карты для хода private Card GetMovingCard(CardList PossibleCards) { try { int movePlace = (usedCards.Count % 4) + 1; // Если игрок ходит первым if (movePlace == 1) { // Если игра с козырем if (botCards.CardListTrump != CardSuit.C_NONE) { Card higherTrump = PossibleCards.GetHigherCard(botCards.CardListTrump); // Если какой-то козырь найден... if (higherTrump != null) { Card higherTrumpInDeck = dontUsedCards.GetHigherCard(botCards.CardListTrump); // Если в колоде есть еще козыри... if (higherTrumpInDeck != null) { // Если у бота имеется самый старший из оставшихся козырей, то ходим им if ((higherTrump.Cost >= higherTrumpInDeck.Cost) && (higherTrump.Type != CardType.C_7)) { return higherTrump; } } // Иначе это самый старший, ходим им else { return higherTrump; } } } // Если козырем пойти не удалось, то пытаемся найти такую карту, чтобы она была старше всех карт оставшихся в колоде данной масти foreach (CardSuit s in Enum.GetValues(typeof(CardSuit))) { if ((s == CardSuit.C_NONE) || (s == botCards.CardListTrump)) continue; Card possibleCard = PossibleCards.GetHigherCard(s); Card higherCardInDeck = dontUsedCards.GetHigherCard(s); if ((higherCardInDeck != null) && (possibleCard != null)) { if (possibleCard.ThisIsBiggerThen(higherCardInDeck)) return possibleCard; } } List<Card> lowCards = new List<Card>(); // Если не удалось найти старшую карту, то пытаемся найти самую младшую из некозырных foreach (CardSuit s in Enum.GetValues(typeof(CardSuit))) { if ((s == CardSuit.C_NONE) || (s == botCards.CardListTrump)) continue; Card lowCard = PossibleCards.GetLowerCard(s); if (lowCard != null) lowCards.Add(lowCard); } if (lowCards.Count > 0) { if (lowCards.Count == 1) return lowCards[0]; Card tempCard = lowCards[0]; for (var i = 1; i < lowCards.Count - 1; i++) { if (tempCard.ThisIsBiggerThen(lowCards[i])) tempCard = lowCards[i]; } return tempCard; } // Если неудалось пойти ни одной картой, значит ходим минимальной козырной Card lowTrump = PossibleCards.GetLowerCard(botCards.CardListTrump); if (lowTrump != null) return lowTrump; else return PossibleCards[0]; } else { // Если ходит бот не первым, то сначала пытается скинуть самую младшую карту из некозырных, потом самую младшую из козырных /*List<Card> lowCards = new List<Card>(); foreach (CardSuit s in Enum.GetValues(typeof(CardSuit))) { if ((s == CardSuit.C_NONE) || (s == botCards.CardListTrump)) continue; Card lowCard = PossibleCards.GetLowerCard(s); if (lowCard != null) lowCards.Add(lowCard); } if (lowCards.Count > 0) { if (lowCards.Count == 1) return lowCards[0]; Card tempCard = lowCards[0]; for (var i = 1; i < lowCards.Count - 1; i++) { if (tempCard.ThisIsBiggerThen(lowCards[i])) tempCard = lowCards[i]; } return tempCard; } // Если неудалось пойти ни одной картой, значит ходим минимальной козырной Card lowTrump = PossibleCards.GetLowerCard(botCards.CardListTrump); if (lowTrump != null) return lowTrump; else return PossibleCards[0];*/ PossibleCards.Sort(); return PossibleCards[PossibleCards.Count - 1]; } } catch { return PossibleCards[0]; } }
// Функция возвращает список возможных к ходу карт, полученный из текущего списка карт, по взятке и месту хода public CardList PossibleCardsToMove(Bribe bribe, int Place) { #if DEBUG Debug.WriteLine("{0} Поиск повзможных карт для хода по текущей взятке ({1}) и номеру игрока - {2}", DateTime.Now, bribe, Place); #endif // В случае если взятка завершена, то игрок будет делать ход на следующей - соответственно он может использовать любую карту if ((bribe.IsEnded) || (bribe.IsEmpty)) return this; CardList possibleCards = new CardList(); // Если первый игрок пошел не с козырной масти... Случаи 1, 2, 3, 6 if (!bribe.IsTrumpBribe) { // В случае если на взятке с запрашиваемой некозырной мастью не было сделано хода с козырной мастью... Случаи 1, 2, 3 if (!bribe.BribeTrumped) { // Если у игрока есть карты этой масти, то можно пойти ими... Случай 1 if (SuitExists(bribe.BribeSuit)) { foreach (Card c in list) { if (c.Suit == bribe.BribeSuit) { possibleCards.Add(c); } } } else // Если у игрока нет карт запрашиваемой масти, но есть козыри, то нужно пойти одним из них... Случай 2 if (TrumpExists()) { // Если у игрока нет запрашиваемой масти, но в то же время первая карта старше if (bribe.FulledCount == 2) { // Если второй игрок пошел некозырной картой другой масти, то можно ходить любой картой if (bribe[0].Suit != bribe[1].Suit) return this; else { // Если первая карта больше второй, то можно пойти любой картой if (bribe[0].ThisIsBiggerThen(bribe[1])) return this; } } // Если у игрока нет запрашиваемой масти, но в то же время вторая карта старше if (bribe.FulledCount == 3) { // Если второй игрок пошел некозырной картой той же масти что и первый - проверяем дальше if (bribe[0].Suit == bribe[1].Suit) { // Если и третий игрок пошел той же мастью if (bribe[2].Suit == bribe[0].Suit) { // Если карта второго игрока больше чем карта первого и третьего - то можно пойти любой картой if ((bribe[1].ThisIsBiggerThen(bribe[0])) && (bribe[1].ThisIsBiggerThen(bribe[2]))) return this; } else { // Если первый игрок пошел картой младше - то можно ходить любой if (bribe[1].ThisIsBiggerThen(bribe[0])) return this; } } } foreach (Card c in list) { if (c.IsTrump) { possibleCards.Add(c); } } } // Если у игрока нет ни карт запрашиваемой масти, ни козырей, то он может пойти любой картой... Случай 3 else { return this; } } // Если на вязтке с запрашиваемой некозырной мастью был совершен ход козырной мастью... Случай 6 else { // Если имеются карты запрашиваемой масти, то надо ходить ими if (SuitExists(bribe.BribeSuit)) { foreach (Card c in list) { if (c.Suit == bribe.BribeSuit) { possibleCards.Add(c); } } } else { // Если ходит 4 игрок, то он не обязан перебивать карту своего сокомандника (игрока №2), если она козырная, иначе необходимо перебить, если возможно if (bribe.FulledCount == 3) { if (bribe[1].IsTrump) { // Если же и третий игрок пошел козырем, то нужно проверить, больше ли он чем козырь второго игрока if ((bribe[2].IsTrump) && (bribe[2].Cost >= bribe[1].Cost) && (bribe[2].Type != CardType.C_7)) { // Необходимо попробовать перебить Card card1 = list.Find(c => (c.IsTrump) && (c.Cost >= bribe.SeniorTrump.Cost) && (c.Type != CardType.C_7)); // В случае, если у игрока имеются козыри, старше чем использовались на раздаче, нужно использовать их if (card1 != null) { foreach (Card c in list) { if ((c.IsTrump) && (c.Cost > bribe.SeniorTrump.Cost)) possibleCards.Add(c); } return possibleCards; } // Если и таких карт нет, то можно использовать любую карту из имеющихся else { return this; } } else { return this; } } } Card card = list.Find(c => (c.IsTrump) && (c.Cost >= bribe.SeniorTrump.Cost) && (c.Type != CardType.C_7)); // В случае, если у игрока имеются козыри, старше чем использовались на раздаче, нужно использовать их if (card != null) { foreach (Card c in list) { if ((c.IsTrump) && (c.Cost >= bribe.SeniorTrump.Cost)) possibleCards.Add(c); } } // Если и таких карт нет, то можно использовать любую карту из имеющихся else { return this; } } } } // В случае если заказанная масть на взятке - козырная... Случаи 4, 5 else { // Если у ходящего игрока имеются козыри... Случай 4 if (TrumpExists()) { Card card = list.Find(c => (c.IsTrump) && (c.Cost >= bribe.SeniorTrump.Cost) && (c.Type != CardType.C_7)); // Если найдены козыри старше, чем использованы на взятке, то необходимо использовать их if (card != null) { foreach (Card c in list) { if ((c.IsTrump) && (c.Cost >= bribe.SeniorTrump.Cost)) possibleCards.Add(c); } } // Если козырей старше нет, то можно использовать любой else { foreach (Card c in list) { if (c.IsTrump) possibleCards.Add(c); } } } // Если козырей нет, то он может пойти любой картой... Случай 5 else { return this; } } return possibleCards; }
// Добавление бонуса типа "Последовательность" в список бонусов private void AddStreakBonus(CardList cards, int Position, int Streak) { BonusType bonusType; if (Streak == 3) bonusType = BonusType.BONUS_TERZ; else if (Streak == 4) bonusType = BonusType.BONUS_50; else { bonusType = BonusType.BONUS_100; } Bonus bonus = new Bonus(bonusType, cards[Position - Streak].Type, cards[Position - Streak].IsTrump, cards[Position - Streak].Suit); // Заполнение списка карт бонуса for (var i = Position - Streak; i < Position; i++) bonus.Cards.Add(cards[i]); AddBonusToList(bonus); }