/// <summary> /// Returns all possible combinations of sets and runs which can be found in the given lists of sets and runs /// </summary> private static List <CardCombo> GetPossibleSetAndRunCombos(List <Set> sets, List <Run> runs, CardCombo currentCombo) { var possibleCombos = new List <CardCombo>(); for (int i = 0; i < sets.Count; i++) { var combo = new CardCombo(currentCombo); combo.AddSet(sets[i]); // This fixed set alone is also a possibility possibleCombos.Add(combo); // Get all runs which are possible with the current set List <Run> possibleRuns = runs.Where(run => !run.Intersects(sets[i])).ToList(); possibleCombos.AddRange(GetPossibleRunCombos(possibleRuns, combo)); // Only sets which don't intersect the current one are possible combinations List <Set> otherSets = sets.Skip(i + 1).Where(set => !set.Intersects(sets[i])).ToList(); if (otherSets.Count > 0) { possibleCombos.AddRange(GetPossibleSetAndRunCombos(otherSets, possibleRuns, combo)); } } return(possibleCombos); }
private void SetCardCombo(CardCombo cardCombo) { Clear(); Cur_CardCombo = cardCombo; foreach (int id in cardCombo.ComboCardIDList) { GeneralizeRow(id); } StartCoroutine(ClientUtils.UpdateLayout(UIManager.Instance.GetBaseUIForm <LevelEditorPanel>().RightPanel)); }
/// <summary> /// Returns all possible combinations of runs which can be found in the given list of runs /// </summary> private static List <CardCombo> GetPossibleRunCombos(List <Run> runs, CardCombo currentRunCombo) { var possibleRunCombos = new List <CardCombo>(); for (int i = 0; i < runs.Count; i++) { var currentCombo = new CardCombo(currentRunCombo); currentCombo.AddRun(runs[i]); // This fixed run alone is also a possibility possibleRunCombos.Add(currentCombo); List <Run> otherRuns = runs.Skip(i + 1).Where(run => !run.Intersects(runs[i])).ToList(); if (otherRuns.Count > 0) { possibleRunCombos.AddRange(GetPossibleRunCombos(otherRuns, currentCombo)); } } return(possibleRunCombos); }
private void ReturnJokerMoveFinished(Card joker) { returningJoker.MoveFinished.RemoveAllListeners(); isJokerBeingReturned = false; HandCardSpot.AddCard(joker); returningJoker = null; // All possible runs/sets/singles have to be calculated again with that newly returned joker laydownCards = GetBestCardCombo(HandCardSpot.Objects, true); singleLayDownCards = PlayerUtil.UpdateSingleLaydownCards(HandCardSpot.Objects, laydownCards); PossibleSinglesChanged.Invoke(singleLayDownCards); if (laydownCards.CardCount == HandCardCount) { KeepOneSingleCard(); } // Proceed with waiting State = PlayerState.WAITING; waitStartTime = Time.time; }
public void Initialize(CardCombo cardCombo, UnityAction <CardCombo> deleteAction, UnityAction <CardCombo> moveUpButton, UnityAction <CardCombo> moveDownButton) { Clear(); Cur_CardCombo = cardCombo; MoveUpButton.onClick.RemoveAllListeners(); MoveUpButton.onClick.AddListener(delegate { moveUpButton(Cur_CardCombo); }); MoveDownButton.onClick.RemoveAllListeners(); MoveDownButton.onClick.AddListener(delegate { moveDownButton(Cur_CardCombo); }); DeleteButton.onClick.RemoveAllListeners(); DeleteButton.onClick.AddListener(delegate { deleteAction(Cur_CardCombo); }); ClearButton.onClick.RemoveAllListeners(); ClearButton.onClick.AddListener(delegate { Clear(); Cur_CardCombo.Clear(); Initialize(Cur_CardCombo, deleteAction, moveUpButton, moveDownButton); UIManager.Instance.GetBaseUIForm <LevelEditorPanel>().StartCoroutine(ClientUtils.UpdateLayout(UIManager.Instance.GetBaseUIForm <LevelEditorPanel>().RightPanel)); }); SelectThisCardListButton.onClick.RemoveAllListeners(); SelectThisCardListButton.onClick.AddListener(delegate { IsSelected = true; }); SetCardCombo(cardCombo); }
public void Initialize(List <CardCombo> cardComboList, UnityAction initializeParentPanel) { Clear(); Cur_CardComboList = cardComboList; LanguageManager.Instance.RegisterTextKey(Label, "LevelEditorPanel_CardComboList"); AddCardComboButton.onClick.RemoveAllListeners(); AddCardComboButton.onClick.AddListener(delegate { CardCombo new_CardCombo = new CardCombo(new List <int>()); Cur_CardComboList.Add(new_CardCombo); LevelEditorPanel_CardCombo cc = GameObjectPoolManager.Instance.PoolDict[GameObjectPoolManager.PrefabNames.LevelEditorPanel_CardCombo].AllocateGameObject <LevelEditorPanel_CardCombo>(LevelEditorPanel_CardComboContainer); cc.Initialize(new_CardCombo, deleteAction : delegate(CardCombo _cc) { Cur_CardComboList.Remove(_cc); Initialize(Cur_CardComboList, initializeParentPanel); }, moveUpButton : delegate(CardCombo _cc) { int index = Cur_CardComboList.IndexOf(_cc); if (index > 0) { Cur_CardComboList.Remove(_cc); Cur_CardComboList.Insert(index - 1, _cc); Initialize(Cur_CardComboList, initializeParentPanel); } }, moveDownButton : delegate(CardCombo _cc) { int index = Cur_CardComboList.IndexOf(_cc); if (index >= 0 && index < Cur_CardComboList.Count - 1) { Cur_CardComboList.Remove(_cc); Cur_CardComboList.Insert(index + 1, _cc); Initialize(Cur_CardComboList, initializeParentPanel); } } ); LevelEditorPanel_CardCombos.Add(cc); initializeParentPanel(); StartCoroutine(ClientUtils.UpdateLayout(UIManager.Instance.GetBaseUIForm <LevelEditorPanel>().RightPanel)); }); ClearAllCardComboButton.onClick.RemoveAllListeners(); ClearAllCardComboButton.onClick.AddListener(delegate { Cur_CardComboList.Clear(); Clear(); }); RefreshButton.onClick.RemoveAllListeners(); RefreshButton.onClick.AddListener(delegate { StartCoroutine(ClientUtils.UpdateLayout(UIManager.Instance.GetBaseUIForm <LevelEditorPanel>().RightPanel)); }); foreach (CardCombo cardCombo in cardComboList) { LevelEditorPanel_CardCombo cc = GameObjectPoolManager.Instance.PoolDict[GameObjectPoolManager.PrefabNames.LevelEditorPanel_CardCombo].AllocateGameObject <LevelEditorPanel_CardCombo>(LevelEditorPanel_CardComboContainer); cc.Initialize(cardCombo, deleteAction : delegate(CardCombo _cc) { Cur_CardComboList.Remove(_cc); Initialize(Cur_CardComboList, initializeParentPanel); }, moveUpButton : delegate(CardCombo _cc) { int index = Cur_CardComboList.IndexOf(_cc); if (index > 0) { Cur_CardComboList.Remove(_cc); Cur_CardComboList.Insert(index - 1, _cc); Initialize(Cur_CardComboList, initializeParentPanel); } }, moveDownButton : delegate(CardCombo _cc) { int index = Cur_CardComboList.IndexOf(_cc); if (index >= 0 && index < Cur_CardComboList.Count - 1) { Cur_CardComboList.Remove(_cc); Cur_CardComboList.Insert(index + 1, _cc); Initialize(Cur_CardComboList, initializeParentPanel); } }); LevelEditorPanel_CardCombos.Add(cc); } initializeParentPanel(); StartCoroutine(ClientUtils.UpdateLayout(UIManager.Instance.GetBaseUIForm <LevelEditorPanel>().RightPanel)); }
public static Level GetLevelFromXML(XmlNode node_levelInfo, out bool needRefresh) { needRefresh = false; string Name_zh = node_levelInfo.Attributes["name_zh"].Value; string Name_en = node_levelInfo.Attributes["name_en"].Value; SortedDictionary <string, string> names = new SortedDictionary <string, string> { { "zh", Name_zh }, { "en", Name_en } }; int picID = int.Parse(node_levelInfo.Attributes["picID"].Value); LevelTypes levelType = (LevelTypes)Enum.Parse(typeof(LevelTypes), node_levelInfo.Attributes["levelType"].Value); int difficultyLevel = int.Parse(node_levelInfo.Attributes["difficultyLevel"].Value); switch (levelType) { case LevelTypes.Enemy: { XmlNode node_EnemyInfo = node_levelInfo.FirstChild; EnemyType enemyType = (EnemyType)Enum.Parse(typeof(EnemyType), node_EnemyInfo.Attributes["enemyType"].Value); BuildInfo bi = BuildInfo.GetBuildInfoFromXML(node_EnemyInfo.FirstChild, out bool _needRefresh_build, BuildCards.DefaultCardLimitNumTypes.BasedOnCardBaseInfoLimitNum); needRefresh |= _needRefresh_build; XmlNode node_BonusGroupInfos = node_EnemyInfo.ChildNodes.Item(1); List <BonusGroup> BonusGroups = new List <BonusGroup>(); for (int i = 0; i < node_BonusGroupInfos.ChildNodes.Count; i++) { XmlNode bonusGroupInfo = node_BonusGroupInfos.ChildNodes.Item(i); BonusGroup bg = BonusGroup.GenerateBonusGroupFromXML(bonusGroupInfo, out bool _needRefresh_bonus); needRefresh |= _needRefresh_bonus; BonusGroups.Add(bg); } XmlNode node_CardPriorityInfos = node_EnemyInfo.ChildNodes.Item(2); CardPriority CardPriority = CardPriority.GenerateCardPriorityFromXML(node_CardPriorityInfos, out bool _needRefresh_priority); XmlNode node_ComboListInfos = node_EnemyInfo.ChildNodes.Item(3); List <CardCombo> ComboList = new List <CardCombo>(); for (int i = 0; i < node_ComboListInfos.ChildNodes.Count; i++) { XmlNode comboInfo = node_ComboListInfos.ChildNodes.Item(i); CardCombo cc = CardCombo.GenerateCardComboFromXML(comboInfo, out bool _needRefresh_combo); needRefresh |= _needRefresh_combo; ComboList.Add(cc); } Enemy enemy = new Enemy(picID, names, difficultyLevel, bi, enemyType, BonusGroups, ComboList, CardPriority); return(enemy); } case LevelTypes.Shop: { XmlNode node_ShopInfo = node_levelInfo.FirstChild; List <ShopItem> shopItems = new List <ShopItem>(); for (int i = 0; i < node_ShopInfo.ChildNodes.Count; i++) { XmlNode node_ShopItem = node_ShopInfo.ChildNodes.Item(i); ShopItem si = ShopItem.GenerateShopItemFromXML(node_ShopItem, out bool _needRefresh_shop); needRefresh |= _needRefresh_shop; if (si != null) { shopItems.Add(si); } } int shopItemCardCount = int.Parse(node_ShopInfo.Attributes["shopItemCardCount"].Value); int shopItemOthersCount = int.Parse(node_ShopInfo.Attributes["shopItemOthersCount"].Value); Shop shop = new Shop(picID, names, difficultyLevel, shopItems, shopItemCardCount, shopItemOthersCount); return(shop); } } return(null); }
public static Level BaseDeserialize(DataStream reader) { LevelTypes levelType = (LevelTypes)reader.ReadSInt32(); int levelID = reader.ReadSInt32(); int levelPicID = reader.ReadSInt32(); int levelNameCount = reader.ReadSInt32(); SortedDictionary <string, string> LevelNames = new SortedDictionary <string, string>(); for (int i = 0; i < levelNameCount; i++) { string ls = reader.ReadString8(); string value = reader.ReadString8(); LevelNames[ls] = value; } int difficultyLevel = reader.ReadSInt32(); Level res = null; switch (levelType) { case LevelTypes.Enemy: { BuildInfo BuildInfo = BuildInfo.Deserialize(reader); EnemyType EnemyType = (EnemyType)(reader.ReadSInt32()); int bonusCount = reader.ReadSInt32(); List <BonusGroup> BonusGroups = new List <BonusGroup>(); for (int i = 0; i < bonusCount; i++) { BonusGroups.Add(BonusGroup.Deserialize(reader)); } CardPriority cp = CardPriority.Deserialize(reader); int cardComboCount = reader.ReadSInt32(); List <CardCombo> cardComboList = new List <CardCombo>(); for (int i = 0; i < cardComboCount; i++) { cardComboList.Add(CardCombo.Deserialize(reader)); } res = new Enemy(levelPicID, LevelNames, difficultyLevel, BuildInfo, EnemyType, BonusGroups, cardComboList, cp); break; } case LevelTypes.Shop: { int count = reader.ReadSInt32(); List <ShopItem> shopItems = new List <ShopItem>(); for (int i = 0; i < count; i++) { ShopItem si = ShopItem.Deserialize(reader); shopItems.Add(si); } int shopItemCardCount = reader.ReadSInt32(); int shopItemOthersCount = reader.ReadSInt32(); res = new Shop(levelPicID, LevelNames, difficultyLevel, shopItems, shopItemCardCount, shopItemOthersCount); break; } } res.LevelID = levelID; return(res); }
private void UpdateCombos(List <CardCombo> cardCombos) { if (!gameObject.activeInHierarchy) { return; } outputView.ClearMessages(); if (cardCombos.Count == 0) { return; } // Do not display duplicate possibilities List <CardCombo> uniqueCombos = new List <CardCombo>(); foreach (CardCombo combo in cardCombos) { if (uniqueCombos.All(c => !c.LooksEqual(combo))) { uniqueCombos.Add(combo); } } string poss = " possibilit" + (uniqueCombos.Count == 1 ? "y" : "ies"); string var = " variant" + (cardCombos.Count == 1 ? "" : "s"); string header = uniqueCombos.Count + poss + " [" + cardCombos.Count + var + "]:"; outputView.PrintMessage(new ScrollView.Message(header)); for (int i = 0; i < uniqueCombos.Count; i++) { CardCombo cardCombo = uniqueCombos[i]; if (cardCombo.PackCount == 0) { continue; } string msg = ""; if (cardCombo.Sets.Count > 0) { foreach (Set set in cardCombo.Sets) { msg += set + ", "; } } if (cardCombo.Runs.Count > 0) { foreach (Run run in cardCombo.Runs) { msg += run + ", "; } } msg = msg.TrimEnd().TrimEnd(',') + " (" + cardCombo.Value + ")"; Color msgColor = Color.black; if (!player.HasLaidDown) { msgColor = cardCombo.Value < Tb.I.GameMaster.MinimumLaySum ? notEnoughPointsColor : Color.black; } outputView.PrintMessage(new ScrollView.Message(msg, msgColor)); } }
public void AIOperation() { while (true) { bool lastOperation = false; bool failedAgain = false; while (true) { // Try preset combo first CardCombo cc = FindCardComboInHand(); if (cc != null) { foreach (int cardID in cc.ComboCardIDList) { CardBase cb = MyPlayer.HandManager.SelectHandCardByCardID(cardID); if (cb != null) { TryUseCard(cb); } } } // Try cards by card priority CardBase card = FindCardUsable(); ModuleMech mech = FindMechMovable(); if (card == null && mech == null) { if (!lastOperation) { failedAgain = true; //try twice and both failed, then stop } break; } else { if (card != null) { if (TryUseCard(card)) //succeed { lastOperation = true; } else { TriedCards.Add(card.M_CardInstanceId); //don't try the cards already tried } } if (mech != null) { if (TryAttack(mech)) //succeed { lastOperation = true; } else { TriedMechs.Add(mech.M_MechID); //don't try the mechs already tried } } } } TriedCards.Clear(); TriedMechs.Clear(); if (failedAgain) { break; } } BattleGameManager.OnEndRoundRequest(new EndRoundRequest(ClientID)); }
/// <summary> /// Updates the list of single cards which can be laid down, <see cref="singleLayDownCards"/>. /// </summary> /// <param name="turnEnded">Whether the update happens right after the player has discarded a card and therefore ended their turn</param> public static List <Single> UpdateSingleLaydownCards(List <Card> PlayerHandCards, CardCombo laydownCards, bool turnEnded = false) { var singleLayDownCards = new List <Single>(); var availableCards = new List <Card>(PlayerHandCards); // Exclude the cards which will be laid down anyway as sets/runs availableCards = availableCards.Except(laydownCards.GetCards()).ToList(); var jokerCards = availableCards.Where(c => c.IsJoker()); bool allowedJokers = false; // At first, do not allow jokers to be laid down as singles availableCards = availableCards.Where(c => !c.IsJoker()).ToList(); bool canFitCard = false; do { var cardSpots = Tb.I.GameMaster.GetAllCardSpots().Where(cs => !cs.IsFull(false)); canFitCard = false; for (int i = availableCards.Count - 1; i >= 0; i--) { var availableCard = availableCards[i]; CardSpot chosenSpot = null; Card joker = null; foreach (var cardSpot in cardSpots) { if (!cardSpot.CanFit(availableCard, out joker)) { continue; } // Find all single cards which are already gonna be added to the cardspot in question var plannedMoves = singleLayDownCards.Where(single => single.CardSpot == cardSpot); bool alreadyPlanned = false; foreach (var move in plannedMoves) { // Don't add the current card if another is already planned for that place if (((availableCard.IsJoker() || move.Card.IsJoker()) && move.Card.Color == availableCard.Color) || (move.Card.Suit == availableCard.Suit && move.Card.Rank == availableCard.Rank)) { alreadyPlanned = true; break; } } if (alreadyPlanned) { continue; } // Try to find a spot with a replacable joker. Single jokers just take the first found spot chosenSpot = cardSpot; if (joker != null || allowedJokers) { break; } } if (chosenSpot != null) { singleLayDownCards.Add(new Single(availableCard, chosenSpot, joker)); availableCards.RemoveAt(i); canFitCard = true; } } // Allow laying down single jokers if no other single card can be found // less than 3 normal cards remain and the turn has not yet ended if (!canFitCard && !allowedJokers && jokerCards.Count() > 0 && availableCards.Count < 3 && !turnEnded) { availableCards.AddRange(jokerCards); allowedJokers = true; canFitCard = true; } } while (canFitCard); return(singleLayDownCards); }
private void DrawCardFinished(Card card, bool isServingCard) { card.MoveFinished.RemoveAllListeners(); HandCardSpot.AddCard(card); card.SetTurned(false); if (isServingCard) { State = PlayerState.IDLE; return; } var combos = CardUtil.GetAllPossibleCombos(HandCardSpot.Objects, Tb.I.GameMaster.GetAllCardSpotCards(), false); PossibleCardCombosChanged.Invoke(combos); laydownCards = combos.Count > 0 ? combos[0] : new CardCombo(); singleLayDownCards = PlayerUtil.UpdateSingleLaydownCards(HandCardSpot.Objects, laydownCards); PossibleSinglesChanged.Invoke(singleLayDownCards); if (Tb.I.GameMaster.LayingAllowed()) { var usedJokers = false; // If the player has not laid down card packs yet, check if their sum would be enough to do so if (!HasLaidDown) { HasLaidDown = laydownCards.Value >= Tb.I.GameMaster.MinimumLaySum; /// Try to reach <see cref="GameMaster.MinimumLaySum"/> by appending jokers to any possible cardcombo var jokers = HandCardSpot.Objects.Where(c => c.IsJoker()).ToList(); if (!HasLaidDown && jokers.Count() > 0) { for (int i = 0; i < combos.Count; i++) { var combo = new CardCombo(combos[i]); var jokersInUse = combo.GetCards().Where(c => c.IsJoker()).ToList(); var remainingJokers = jokers.Except(jokersInUse).ToList(); if (remainingJokers.Count == 0) { continue; } var canLayCombo = combo.TryAddJoker(remainingJokers); if (canLayCombo && combo.CardCount < HandCardCount) { usedJokers = true; laydownCards = combo; combos.Insert(0, combo); PossibleCardCombosChanged.Invoke(combos); NewThought.Invoke("Use jokers to lay down"); HasLaidDown = true; break; } } if (!HasLaidDown) { NewThought.Invoke("Cannot reach " + Tb.I.GameMaster.MinimumLaySum + " using jokers"); } } } // At least one card must remain when laying down if (!usedJokers && HasLaidDown && laydownCards.CardCount == HandCardCount) { KeepOneSingleCard(); } } State = PlayerState.WAITING; waitStartTime = Time.time; }