public bool PlaceCard(TriadGameData gameData, TriadCard card, ETriadCardOwner owner, int boardPos) { TriadDeckInstance useDeck = (owner == ETriadCardOwner.Blue) ? gameData.deckBlue : gameData.deckRed; int cardIdx = useDeck.GetCardIndex(card); return(PlaceCard(gameData, cardIdx, useDeck, owner, boardPos)); }
public DeckCtrl() { drawMode = ECardDrawMode.Detailed; allowRearrange = true; enableHitTest = true; enableLocking = false; ignoreDragOnContextClose = false; clickAction = EDeckCtrlAction.Pick; deckOwner = ETriadCardOwner.Blue; cardTileSize = 50; cardTileSpacing = 6; InitializeComponent(); toolStripMenuOnlyOwned.Checked = true; }
public void Load(JsonParser.ObjectValue configOb) { string ownerStr = configOb["player"] as JsonParser.StringValue; owner = (ownerStr == "blue") ? ETriadCardOwner.Blue : (ownerStr == "red") ? ETriadCardOwner.Red : ETriadCardOwner.Unknown; boardPos = configOb["pos"] as JsonParser.IntValue; if (configOb.entries.ContainsKey("board")) { string boardCode = configOb["board"] as JsonParser.StringValue; boardCode = boardCode.Replace(" ", ""); expectedState = new ETriadCardOwner[9]; for (int idx = 0; idx < expectedState.Length; idx++) { expectedState[idx] = (boardCode[idx] == 'R') ? ETriadCardOwner.Red : (boardCode[idx] == 'B') ? ETriadCardOwner.Blue : ETriadCardOwner.Unknown; } } var cardName = configOb["card"] as JsonParser.StringValue; if (cardName != null) { card = TriadCardDB.Get().Find(cardName); } else { var cardSides = configOb["card"] as JsonParser.ArrayValue; int numU = cardSides[0] as JsonParser.IntValue; int numL = cardSides[1] as JsonParser.IntValue; int numD = cardSides[2] as JsonParser.IntValue; int numR = cardSides[3] as JsonParser.IntValue; card = TriadCardDB.Get().Find(numU, numL, numD, numR); } }
public bool SolverFindBestMove(TriadGameData gameData, out int boardPos, out TriadCard card, out TriadGameResultChance probabilities) { bool bResult = false; card = null; boardPos = -1; currentProgress = 0; string namePrefix = string.IsNullOrEmpty(solverName) ? "" : ("[" + solverName + "] "); // prepare available board data int availBoardMask = 0; int numAvailBoard = 0; for (int Idx = 0; Idx < gameData.board.Length; Idx++) { if (gameData.board[Idx] == null) { availBoardMask |= (1 << Idx); numAvailBoard++; } } // prepare available cards data TriadDeckInstance useDeck = (gameData.state == ETriadGameState.InProgressBlue) ? gameData.deckBlue : gameData.deckRed; ETriadCardOwner turnOwner = (gameData.state == ETriadGameState.InProgressBlue) ? ETriadCardOwner.Blue : ETriadCardOwner.Red; int availCardsMask = 0; if (gameData.state == ETriadGameState.InProgressBlue && gameData.forcedCardIdx >= 0) { availCardsMask = 1 << gameData.forcedCardIdx; } else { availCardsMask = useDeck.availableCardMask; } if ((modFeatures & TriadGameModifier.EFeature.FilterNext) != 0) { foreach (TriadGameModifier mod in modifiers) { mod.OnFilterNextCards(gameData, ref availCardsMask); } } int numAvailCards = 0; for (int Idx = 0; Idx < TriadDeckInstance.maxAvailableCards; Idx++) { numAvailCards += ((availCardsMask & (1 << Idx)) != 0) ? 1 : 0; } // check all combinations if ((numAvailCards > 0) && (numAvailBoard > 0)) { int numCombinations = numAvailCards * numAvailBoard; TriadGameResultChance bestProb = new TriadGameResultChance(-1.0f, 0); int cardProgressCounter = 0; for (int cardIdx = 0; cardIdx < TriadDeckInstance.maxAvailableCards; cardIdx++) { bool bCardNotAvailable = (availCardsMask & (1 << cardIdx)) == 0; if (bCardNotAvailable) { continue; } currentProgress = 100 * cardProgressCounter / numAvailCards; cardProgressCounter++; for (int boardIdx = 0; boardIdx < gameData.board.Length; boardIdx++) { bool bBoardNotAvailable = (availBoardMask & (1 << boardIdx)) == 0; if (bBoardNotAvailable) { continue; } TriadGameData gameDataCopy = new TriadGameData(gameData); bool bPlaced = PlaceCard(gameDataCopy, cardIdx, useDeck, turnOwner, boardIdx); if (bPlaced) { TriadGameResultChance gameProb = SolverFindWinningProbability(gameDataCopy); if (gameProb.IsBetterThan(bestProb)) { bestProb = gameProb; card = useDeck.GetCard(cardIdx); boardPos = boardIdx; bResult = true; } } } } probabilities = bestProb; Logger.WriteLine(namePrefix + "Solver win:" + bestProb.winChance.ToString("P2") + " (draw:" + bestProb.drawChance.ToString("P2") + "), blue[" + gameData.deckBlue + "], red[" + gameData.deckRed + "], turn:" + turnOwner + ", availBoard:" + numAvailBoard + " (" + availBoardMask.ToString("x") + ") availCards:" + numAvailCards + " (" + (useDeck == gameData.deckBlue ? "B" : "R") + ":" + availCardsMask.ToString("x") + ")"); } else { probabilities = new TriadGameResultChance(0, 0); Logger.WriteLine(namePrefix + "Can't find move! availSpots:" + numAvailBoard + " (" + availBoardMask.ToString("x") + ") availCards:" + numAvailCards + " (" + (useDeck == gameData.deckBlue ? "B" : "R") + ":" + availCardsMask.ToString("x") + ")"); } return(bResult); }
public bool PlaceCard(TriadGameData gameData, int cardIdx, TriadDeckInstance cardDeck, ETriadCardOwner owner, int boardPos) { bool bResult = false; bool bIsAllowedOwner = ((owner == ETriadCardOwner.Blue) && (gameData.state == ETriadGameState.InProgressBlue)) || ((owner == ETriadCardOwner.Red) && (gameData.state == ETriadGameState.InProgressRed)); TriadCard card = cardDeck.GetCard(cardIdx); if (bIsAllowedOwner && (boardPos >= 0) && (gameData.board[boardPos] == null) && (card != null)) { gameData.board[boardPos] = new TriadCardInstance(card, owner); gameData.numCardsPlaced++; if (owner == ETriadCardOwner.Blue) { gameData.deckBlue.OnCardPlacedFast(cardIdx); gameData.state = ETriadGameState.InProgressRed; } else { gameData.deckRed.OnCardPlacedFast(cardIdx); gameData.state = ETriadGameState.InProgressBlue; } bResult = true; bool bAllowCombo = false; if ((modFeatures & TriadGameModifier.EFeature.CardPlaced) != 0) { foreach (TriadGameModifier mod in modifiers) { mod.OnCardPlaced(gameData, boardPos); bAllowCombo = bAllowCombo || mod.AllowsCombo(); } } List <int> comboList = new List <int>(); int comboCounter = 0; CheckCaptures(gameData, boardPos, comboList, comboCounter); while (bAllowCombo && comboList.Count > 0) { if (gameData.bDebugRules) { Logger.WriteLine(">> combo step: {0}", string.Join(",", comboList)); } List <int> nextCombo = new List <int>(); comboCounter++; foreach (int pos in comboList) { CheckCaptures(gameData, pos, nextCombo, comboCounter); } comboList = nextCombo; } if ((modFeatures & TriadGameModifier.EFeature.PostCapture) != 0) { foreach (TriadGameModifier mod in modifiers) { mod.OnPostCaptures(gameData, boardPos); } } if (gameData.numCardsPlaced == gameData.board.Length) { OnAllCardsPlaced(gameData); } } return(bResult); }
public bool PlaceCard(TriadGameData gameData, int cardIdx, TriadDeckInstance cardDeck, ETriadCardOwner owner, int boardPos) { bool bResult = false; bool bIsAllowedOwner = ((owner == ETriadCardOwner.Blue) && (gameData.state == ETriadGameState.InProgressBlue)) || ((owner == ETriadCardOwner.Red) && (gameData.state == ETriadGameState.InProgressRed)); TriadCard card = cardDeck.GetCard(cardIdx); if (bIsAllowedOwner && (boardPos >= 0) && (gameData.board[boardPos] == null) && (card != null)) { #if DEBUG Stopwatch timer = new Stopwatch(); timer.Start(); #endif // DEBUG gameData.board[boardPos] = new TriadCardInstance(card, owner); gameData.numCardsPlaced++; if (owner == ETriadCardOwner.Blue) { gameData.deckBlue.OnCardPlacedFast(cardIdx); gameData.state = ETriadGameState.InProgressRed; } else { gameData.deckRed.OnCardPlacedFast(cardIdx); gameData.state = ETriadGameState.InProgressBlue; } #if DEBUG perfStats.PlaceCardOnPlaced += timer.ElapsedTicks; timer.Restart(); #endif // DEBUG bResult = true; bool bAllowCombo = false; if ((modFeatures & TriadGameModifier.EFeature.CardPlaced) != 0) { foreach (TriadGameModifier mod in modifiers) { mod.OnCardPlaced(gameData, boardPos); bAllowCombo = bAllowCombo || mod.AllowsCombo(); } } #if DEBUG perfStats.PlaceCardOnPlacedMods += timer.ElapsedTicks; timer.Restart(); #endif // DEBUG List <int> comboList = new List <int>(); int comboCounter = 0; CheckCaptures(gameData, boardPos, comboList, comboCounter); #if DEBUG perfStats.PlaceCardCaptures += timer.ElapsedTicks; timer.Restart(); #endif // DEBUG while (bAllowCombo && comboList.Count > 0) { List <int> nextCombo = new List <int>(); comboCounter++; foreach (int pos in comboList) { CheckCaptures(gameData, pos, nextCombo, comboCounter); } comboList = nextCombo; } #if DEBUG perfStats.PlaceCardCapturesCombo += timer.ElapsedTicks; timer.Restart(); #endif // DEBUG if ((modFeatures & TriadGameModifier.EFeature.PostCapture) != 0) { foreach (TriadGameModifier mod in modifiers) { mod.OnPostCaptures(gameData, boardPos); } } #if DEBUG perfStats.PlaceCardPostCaptures += timer.ElapsedTicks; timer.Restart(); #endif // DEBUG if (gameData.numCardsPlaced == gameData.board.Length) { OnAllCardsPlaced(gameData); } #if DEBUG timer.Stop(); perfStats.PlaceCardAllPlaced += timer.ElapsedTicks; #endif // DEBUG } return(bResult); }
public TriadCardInstance(TriadCardInstance copyFrom) { card = copyFrom.card; owner = copyFrom.owner; scoreModifier = copyFrom.scoreModifier; }
public TriadCardInstance(TriadCard card, ETriadCardOwner owner) { this.card = card; this.owner = owner; scoreModifier = 0; }
public override void OnAllCardsPlaced(TriadGameData gameData) { if (gameData.state == ETriadGameState.BlueDraw && gameData.numRestarts < 3) { // implement this rule only for manual mode, screen captures get everything automatically TriadDeckInstanceManual deckBlueEx = gameData.deckBlue as TriadDeckInstanceManual; TriadDeckInstanceManual deckRedEx = gameData.deckRed as TriadDeckInstanceManual; if (deckBlueEx != null && deckRedEx != null) { List <TriadCard> blueCards = new List <TriadCard>(); List <TriadCard> redCards = new List <TriadCard>(); List <TriadCard> redUnknownCards = new List <TriadCard>(); string redCardsDebug = ""; for (int Idx = 0; Idx < gameData.board.Length; Idx++) { if (gameData.board[Idx].owner == ETriadCardOwner.Blue) { blueCards.Add(gameData.board[Idx].card); } else { redCards.Add(gameData.board[Idx].card); } gameData.board[Idx] = null; } if (deckBlueEx.numPlaced < deckRedEx.numPlaced) { // blue has cards on hand, all known for (int Idx = 0; Idx < deckBlueEx.deck.knownCards.Count; Idx++) { bool bIsAvailable = !deckBlueEx.IsPlaced(Idx); if (bIsAvailable) { blueCards.Add(deckBlueEx.deck.knownCards[Idx]); break; } } gameData.state = ETriadGameState.InProgressBlue; } else { // red has cards on hand, check known vs unknown for (int Idx = 0; Idx < deckRedEx.deck.knownCards.Count; Idx++) { bool bIsAvailable = !deckRedEx.IsPlaced(Idx); if (bIsAvailable) { redCards.Add(deckRedEx.deck.knownCards[Idx]); redCardsDebug += deckRedEx.deck.knownCards[Idx].Name + ":K, "; break; } } if (redCards.Count < blueCards.Count) { for (int Idx = 0; Idx < deckRedEx.deck.unknownCardPool.Count; Idx++) { int cardIdx = Idx + deckRedEx.deck.knownCards.Count; bool bIsAvailable = !deckRedEx.IsPlaced(cardIdx); if (bIsAvailable) { redUnknownCards.Add(deckRedEx.deck.unknownCardPool[Idx]); redCardsDebug += deckRedEx.deck.unknownCardPool[Idx].Name + ":U, "; } } } gameData.state = ETriadGameState.InProgressRed; } gameData.deckBlue = new TriadDeckInstanceManual(new TriadDeck(blueCards)); gameData.deckRed = new TriadDeckInstanceManual(new TriadDeck(redCards, redUnknownCards)); gameData.numCardsPlaced = 0; gameData.numRestarts++; for (int Idx = 0; Idx < gameData.typeMods.Length; Idx++) { gameData.typeMods[Idx] = 0; } if (gameData.bDebugRules) { redCardsDebug = (redCardsDebug.Length > 0) ? redCardsDebug.Remove(redCardsDebug.Length - 2, 2) : "(board only)"; ETriadCardOwner nextTurnOwner = (gameData.state == ETriadGameState.InProgressBlue) ? ETriadCardOwner.Blue : ETriadCardOwner.Red; Logger.WriteLine(">> " + RuleName + "! next turn:" + nextTurnOwner + ", red:" + redCardsDebug); } } } }