bool CheckLineToPrint(SlotLine lineId, GenSymbolId symbolId, SymbolCombination symbolCombination, MatrixInWork matrix) { int maxMajorSymbols = symbolCombination.count; for (int i = 0; i < lineId.indexOnDrum.Length; i++) { int indexInDrum = lineId.indexOnDrum[i]; SymbolInWork matrixSymbol = matrix.symbols[i][indexInDrum]; if (i < maxMajorSymbols) { if ((matrixSymbol.symbolMask & symbolId.symbolId) == 0) { return(false); } } else { if ((matrixSymbol.symbolMask & symbolId.symbolId) != 0 && matrixSymbol.fixedSymbol) { return(false); } } } return(true); }
bool RemoveLine(SlotLine lineId, GenSymbolId symbolId, MatrixInWork matrix) { int maxMajorDrums = symbolId.symbolConfig.combinations[0].count; for (int i = 1; i < maxMajorDrums; i++) { SymbolInWork workSymbol = matrix.symbols[i][lineId.indexOnDrum[i]]; uint symbolMask = workSymbol.symbolMask; if ((symbolMask & symbolId.symbolId) == 0) { return(true); } else if (!workSymbol.fixedSymbol) { workSymbol.symbolMask = workSymbol.symbolMask - symbolId.symbolId; return(true); } } for (int i = maxMajorDrums; i < lineId.indexOnDrum.Length; i++) { SymbolInWork workSymbol = matrix.symbols[i][lineId.indexOnDrum[i]]; if (!workSymbol.fixedSymbol) { workSymbol.symbolMask = workSymbol.symbolMask - symbolId.symbolId; } } return(false); }
bool RemoveLinesForSymbol(int posOnFirstDrum, GenSymbolId symbolId, MatrixInWork startMatrix, List <string> usedLines, out List <SlotLine> linesNotRemoved) { List <GenLineId> linesForIndex = new List <GenLineId>(); foreach (var curLine in lineIdToGenLine.Values) { if (curLine.lineConfig.indexOnDrum[0] == posOnFirstDrum && !usedLines.Contains(curLine.lineConfig.tag) && CheckForAvaliableLine(symbolId, curLine, startMatrix)) { linesForIndex.Add(curLine); } } if (linesForIndex.Count == 0) { linesNotRemoved = null; return(true); } linesNotRemoved = new List <SlotLine>(); bool successRemoved = true; foreach (var curLine in linesForIndex) { if (!RemoveLine(curLine.lineConfig, symbolId, startMatrix)) { linesNotRemoved.Add(curLine.lineConfig); successRemoved = false; } } return(successRemoved); }
bool CheckSymbolByFirstUsed(int[] firstIndicies, MatrixInWork matrix, GenSymbolId symbolId) { for (int i = 0; i < firstIndicies.Length; i++) { if (matrix.symbols[0][firstIndicies[i]].symbolMask == symbolId.symbolId) { return(true); } } return(false); }
bool AddLineCombination(List <SlotLine> lineCombination, GenSymbolId symbolId, List <SymbolCombination> symbolCombinations, MatrixInWork matrix) { int combIndex = 0; foreach (var curLine in lineCombination) { if (!PrintSymbolLineToMatrix(curLine, symbolId, symbolCombinations[combIndex++], matrix)) { return(false); } } return(true); }
bool CheckForAvaliableLine(GenSymbolId symbolId, GenLineId lineId, MatrixInWork processMatrix) { int maxAgreeDrumIndex = symbolId.symbolConfig.combinations[0].count; for (int i = 0; i < maxAgreeDrumIndex; i++) { int indexOnDrum = lineId.lineConfig.indexOnDrum[i]; uint cellMask = processMatrix.symbols[i][indexOnDrum].symbolMask; if ((cellMask & symbolId.symbolId) == 0) { return(false); } } return(true); }
void CalculateRewardBySymbol(int index, GenSymbolId symbolId, FinalSpinReward inputReward) { /*List<GenLineId> linesForIndex = new List<GenLineId>(); * foreach (var curLine in lineIdToGenLine.Values) * { * if (curLine.lineConfig.indexOnDrum[0] == index) * linesForIndex.Add(curLine); * } * Shuffle(linesForIndex); * * List<uint> excludeLines = new List<uint>(); * * while (true) * { * uint linesCombination = 0b10101; // calculate by need reward and possible lines * CalculateRewardByLines(index, symbolId, linesCombination, linesForIndex); * } */ }
void AddPlayingLinesToSteps(GenSymbolId symbolId, MatrixInWork startMatrix, List <SlotLine> lines, List <MatrixStepBySymbol> linesToPlay, List <string> usedLines) { foreach (var curLine in lines) { foreach (var curCombination in symbolId.symbolConfig.combinations) { if (CheckLineToPrint(curLine, symbolId, curCombination, startMatrix)) { MatrixStepBySymbol newStep = new MatrixStepBySymbol(); newStep.symbolId = symbolId; newStep.matrix = startMatrix; newStep.combination = curCombination; newStep.currentReward = curCombination.reward; newStep.lineCombination = curLine; linesToPlay.Add(newStep); usedLines.Add(curLine.tag); } } } }
void CalculateRewardByLines(int index, GenSymbolId symbolId, uint linesCombination, List <GenLineId> linesForIndex) { int combinationCount = symbolId.symbolConfig.combinations.Length; int curCombinationIndex = 0; int[] currentCombinations = new int[combinationCount]; while (true) { int i = 0; foreach (var curLineId in linesForIndex) { if ((curLineId.lineId & linesCombination) != 0) { currentCombinations[i++] = curCombinationIndex; } } curCombinationIndex++; } //symbolId.symbolConfig.combinations[0]. }
SymbolStepResultType FindMatrixForSymbol(int posOnFirstDrum, GenSymbolId symbolId, MatrixInWork startMatrix, float maxEstimateReward, float chanceModificator, List <string> usedLines, out MatrixStepBySymbol result) { result = new MatrixStepBySymbol(); List <GenLineId> linesForIndex = new List <GenLineId>(); foreach (var curLine in lineIdToGenLine.Values) { if (curLine.lineConfig.indexOnDrum[0] == posOnFirstDrum && !usedLines.Contains(curLine.lineConfig.tag) && CheckForAvaliableLine(symbolId, curLine, startMatrix)) { linesForIndex.Add(curLine); } } if (linesForIndex.Count == 0) { return(SymbolStepResultType.NoAvaliableLines); } float maxThreshold = symbolId.symbolConfig.GetMinimumReward() / 2.0f; var chances = CalculateFactorChances(symbolId.symbolConfig.combinations, chanceModificator); SymbolCombination selectedCombination = null; if (symbolId.symbolConfig.combinations[0].reward > (maxEstimateReward + maxThreshold)) { return(SymbolStepResultType.EstimateRewardIsSmall); } else if (Mathf.Abs(symbolId.symbolConfig.combinations[0].reward - maxEstimateReward) < maxThreshold) { selectedCombination = symbolId.symbolConfig.combinations[0]; } while (selectedCombination == null) { SymbolCombination randomCombination = GetRandomCombination(chances); if (randomCombination.reward > (maxEstimateReward + maxThreshold) && chances[0].combination.reward < (maxEstimateReward + maxThreshold)) { continue; } selectedCombination = randomCombination; } Shuffle(linesForIndex); SlotLine resultLine = null; MatrixInWork newMatrix = startMatrix.Copy(); foreach (var curLine in linesForIndex) { if (CheckLineToPrint(curLine.lineConfig, symbolId, selectedCombination, newMatrix)) { PrintSymbolLineToMatrix(curLine.lineConfig, symbolId, selectedCombination, newMatrix); resultLine = curLine.lineConfig; break; } } if (resultLine == null) { return(SymbolStepResultType.LinesNotFound); } result.symbolId = symbolId; result.matrix = newMatrix; result.combination = selectedCombination; result.lineCombination = resultLine; result.currentReward = selectedCombination.reward; return(SymbolStepResultType.Success); }
void ProcessSymbols(int[] firstIndicies, MatrixInWork startMatrix) { List <MatrixStepBySymbol> steps = new List <MatrixStepBySymbol>(); int currentIndex = 0; float symbolRewardFactor = 1.0f; float curReward = 0.0f; float rewardChanceModifier = 1.0f; float maxRewardChanceValue = 16.0f; List <string> excludedLines = new List <string>(); int countClearStart = 0; int countIterations = 0; List <GenSymbolId> symbolsToGenerate = symbolIdToGenSymbol.Values.ToList(); while (true) { countIterations++; if (currentIndex >= firstIndicies.Length) { currentIndex = 0; } GenSymbolId currentSymbol = symbolsToGenerate[Random.Range(0, symbolsToGenerate.Count)]; MatrixInWork curMatrix; if (steps.Count == 0) { curMatrix = startMatrix; countClearStart++; } else { curMatrix = steps.Last().matrix; } float needAllReward = (currentSpinInfo.finalRewardPercent - curReward); MatrixStepBySymbol newStep; SymbolStepResultType result = FindMatrixForSymbol(firstIndicies[currentIndex], currentSymbol, curMatrix, needAllReward, rewardChanceModifier, excludedLines, out newStep); //если успешно добавили новую линию if (result == SymbolStepResultType.Success) { float newFinalReward = curReward + newStep.currentReward; //если достигли требуемой награды, прекращаем алгоритм if (Mathf.Abs(newFinalReward - currentSpinInfo.finalRewardPercent) < currentSymbol.symbolConfig.GetMinimumReward() * 0.5f) { Debug.LogError("Reward reached!"); curReward += newStep.currentReward; excludedLines.Add(newStep.lineCombination.tag); steps.Add(newStep); break; } else if (newFinalReward > (currentSpinInfo.finalRewardPercent + currentSymbol.symbolConfig.GetMinimumReward())) { //если не получилось за несколько раз, выдаем текущий результат (хоть он и не валидный) if (rewardChanceModifier < (-maxRewardChanceValue + 0.001f)) { Debug.LogError("Reward is very big! Finished"); curReward += newStep.currentReward; excludedLines.Add(newStep.lineCombination.tag); steps.Add(newStep); break; } else { //уменьшаем вероятность больших наград и начинаем сначала steps.Clear(); currentIndex = 0; curReward = 0.0f; excludedLines.Clear(); rewardChanceModifier = Mathf.Min(rewardChanceModifier, -1.0f); rewardChanceModifier = rewardChanceModifier * 2.0f; } continue; } curReward += newStep.currentReward; currentIndex++; steps.Add(newStep); excludedLines.Add(newStep.lineCombination.tag); } else if (result == SymbolStepResultType.EstimateRewardIsSmall) { //минимальная комбинация слишком большая для награды, которую осталось набрать, значит все ок, прерываем алгоритм. break; } else if (result == SymbolStepResultType.NoAvaliableLines || result == SymbolStepResultType.LinesNotFound) { //если не получилось за несколько раз, выдаем текущий результат (хоть он и не валидный) if (rewardChanceModifier > (maxRewardChanceValue - 0.0001f)) { Debug.LogError("Reward not reached, lines incorrect.."); break; } else { //уменьшаем вероятность больших наград и начинаем сначала steps.Clear(); currentIndex = 0; curReward = 0.0f; excludedLines.Clear(); rewardChanceModifier = Mathf.Max(rewardChanceModifier, 1.0f); rewardChanceModifier = rewardChanceModifier * 2.0f; } continue; } else { Debug.LogError("Something wrong! Unknown SymbolStepResultType"); steps.Clear(); excludedLines.Clear(); currentIndex = 0; curReward = 0.0f; rewardChanceModifier = 0.0f; } } Shuffle(symbolsToGenerate); //убираем линии которые еще могут сыграть, также генерим первые символы, если они еще не созданы, таким образом, что они не сыграют foreach (var curFirstindex in firstIndicies) { MatrixInWork lastMatrix = steps.Last().matrix; SymbolInWork matrixSymbol = lastMatrix.symbols[0][curFirstindex]; if (symbolIdToGenSymbol.ContainsKey(matrixSymbol.symbolMask)) { GenSymbolId foundSymbol; if (symbolIdToGenSymbol.TryGetValue(matrixSymbol.symbolMask, out foundSymbol)) { List <SlotLine> noRemoveLines; bool isRemoved = RemoveLinesForSymbol(curFirstindex, foundSymbol, lastMatrix, excludedLines, out noRemoveLines); if (!isRemoved && noRemoveLines != null) { AddPlayingLinesToSteps(foundSymbol, lastMatrix, noRemoveLines, steps, excludedLines); } } } else { GenSymbolId symbolFound = null; for (int j = 0; j < symbolsToGenerate.Count; j++) { GenSymbolId curSymbol = symbolsToGenerate[j]; if ((curSymbol.symbolId & matrixSymbol.symbolMask) != 0 && !CheckSymbolByFirstUsed(firstIndicies, lastMatrix, curSymbol)) { lastMatrix.symbols[0][curFirstindex].symbolMask = curSymbol.symbolId; symbolFound = curSymbol; break; } } if (symbolFound == null) { symbolFound = symbolsToGenerate[0]; } List <SlotLine> noRemoveLines; bool isRemoved = RemoveLinesForSymbol(curFirstindex, symbolFound, lastMatrix, excludedLines, out noRemoveLines); if (!isRemoved && noRemoveLines != null) { AddPlayingLinesToSteps(symbolFound, lastMatrix, noRemoveLines, steps, excludedLines); } } } //генерим оставшиеся символы, которые точно не сыграют MatrixInWork matrix = steps.Last().matrix; for (int i = 0; i < matrix.symbols.Length; i++) { for (int j = 0; j < matrix.symbols[i].Length; j++) { SymbolInWork symbol = matrix.symbols[i][j]; if (!symbol.fixedSymbol) { Shuffle(symbolsToGenerate); foreach (var curSymbolId in symbolsToGenerate) { if ((symbol.symbolMask & curSymbolId.symbolId) != 0) { symbol.symbolMask = curSymbolId.symbolId; symbol.fixedSymbol = true; } } } } } Debug.Log("Finish generate! Need reward=" + currentSpinInfo.finalRewardPercent + "; real reward=" + curReward + "; steps=" + steps.Count + "; clearStart=" + countClearStart + "; allIterations=" + countIterations); int k1 = 0; foreach (var curStep in steps) { Debug.Log("Step" + (k1++) + ": Symbol=" + curStep.symbolId.symbolConfig.tag + "; Line=" + curStep.lineCombination.ToString() + "; reward=" + curStep.combination.reward); } matrix = steps.Last().matrix; for (int i = 0; i < matrix.symbols.Length; i++) { string curLine = i + ": "; for (int j = 0; j < matrix.symbols[i].Length; j++) { string curSymbolStr = "["; foreach (var s in symbolsToGenerate) { if ((matrix.symbols[i][j].symbolMask & s.symbolId) == 0) { curSymbolStr += "<_" + s.symbolConfig.tag + "_>"; } else { curSymbolStr += "<" + s.symbolConfig.tag + ">"; } } curSymbolStr = curSymbolStr.Trim(new char[] { ',' }) + "]"; curLine += curSymbolStr + ","; } curLine = curLine.Trim(new char[] { ',' }) + "]"; Debug.Log("Matrix line " + curLine); } }