Files
Coleman-Code/COM380/Project5/GambleKit/Engine/Game/GkGameWinningsAnalyzer.cpp
T
Amrit Panesar 39ee821f54 start 380 project5
changes to 380 project 4
changes to 350 project 2

Signed-off-by: Amrit Panesar <apanesar@4195tech.com>
2015-05-06 10:18:39 -07:00

487 lines
15 KiB
C++

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// GambleKit Copyright (C) 2014 Ivan Donev
//
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// contact: gamblekit@gmail.com
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "GkGameWinningsAnalyzer.h"
#include "..\Utils\GkMaths.h"
#include "..\OSSpecific\GkOSUtils.h"
#include <stdarg.h>
// Camparison of reel combinations - combinations may have
// A. Exactly the same symbol wins as the compared - equal
// B. The same symbol wins from the compared plus more - greater
// C. Symbol wins from the compared, but not all or with less symbols - lesser
// D. Not all the symbol wins from the compared plus more - different
//
// Rule set
//
// Definition: A symbol win is considered a winning of EXACTLY the same symbol and either on EXACTLY the same line OR BEING A SCATTER
//
// Signs of comparison:
// 1.1 Contains all the symbol wins as the compared one
// 1.2 Contains symbol wins, that are not present in the compared one
//
// In addition to that, there might be symbol win(s) with
// 2.1 The same number of winning items
// 2.2 Greater number of winning items
// 2.3 Lesser number of winning items
//
// Result
// Equal - 1.1 and not 1.2 and not 2.2. and not 2.3
// Greater - 1.1. and (1.2 or 2.2) and not 2.3
// Lesser - (not 1.1 or 2.3) and not 1.2 and not 2.2
// Different - otherwise
GkGameWinningsAnalyzer::GkGameWinningsAnalyzer(GkGameWinningsModel *model)
: GkBaseReelMap(model->numReels, model->numReelItems)
{
this->model = model;
this->comparisonMode = GameWinningAnalyzerComparisonMode_FullComparison;
this->InitWinningData(&this->winnings);
}
GkGameWinningsAnalyzer::~GkGameWinningsAnalyzer(void)
{
this->DisposeWinningData(&this->winnings);
}
GameWinning GkGameWinningsAnalyzer::GetSymbolWinning(int symbolIndex, int lineIndex)
{
GameWinning reelItem;
reelItem.symbolIndex = symbolIndex;
reelItem.lineIndex = lineIndex;
reelItem.numItems = 0;
reelItem.itemsStart = 0;
GameWinning result = reelItem;
GameWinningSymbolModel *symbolModel = this->model->GetSymbolModel(symbolIndex);
bool sequenceValid = false;
for (int reelIndex = 0; reelIndex < this->numReels; reelIndex++)
{
int reelSymbolIndex = this->GetLineSymbol(reelIndex, lineIndex);
GameWinningSymbolModel *reelSymbolModel = this->model->GetSymbolModel(reelSymbolIndex);
if (this->SymbolsMatch(symbolIndex, reelSymbolIndex))
{
if (symbolIndex == reelSymbolIndex)
sequenceValid = true;
if (reelItem.numItems == 0)
{
reelItem.itemsStart = reelIndex;
reelItem.symbolsFlags = GkGameWinningsModel::SymbolFlag_None;
}
reelItem.numItems++;
reelItem.symbolsFlags |= reelSymbolModel->flags;
if (sequenceValid && (reelItem.numItems > result.numItems))
{
result = reelItem;
}
}
else
{
if ((symbolModel->flags & GkGameWinningsModel::SymbolFlag_AnyPlace) == 0)
break;
sequenceValid = false;
reelItem.numItems = 0;
}
}
result.itemsEnd = result.itemsStart + result.numItems - 1;
result.winningCoefficient = this->model->GetSymbolCoefficient(result.symbolIndex, result.numItems);
return result;
}
bool GkGameWinningsAnalyzer::SymbolsMatch(int symbolIndex, int testSymbolIndex)
{
GameWinningSymbolModel *symbolModel = this->model->GetSymbolModel(symbolIndex),
*testSymbolModel = this->model->GetSymbolModel(testSymbolIndex);
return ((testSymbolIndex == symbolIndex) || ((testSymbolModel->flags & GkGameWinningsModel::SymbolFlag_Wild) != 0)) &&
((testSymbolModel->flags & symbolModel->exclusionFlags) == 0);
}
GameWinning GkGameWinningsAnalyzer::GetScatterWinning(int symbolIndex)
{
int scatterNumber = 0;
for (int symbolsIndex = 0; symbolsIndex < symbolsIndex; symbolsIndex++)
if (this->model->GetSymbolModel(symbolsIndex)->flags & GkGameWinningsModel::SymbolFlag_Scatter)
scatterNumber++;
GameWinning result;
result.symbolIndex = symbolIndex;
result.numItems = 0;
result.lineIndex = this->model->numLines + scatterNumber;
if (scatterNumber >= this->model->numScatters)
{
result.symbolsFlags = GkGameWinningsModel::SymbolFlag_None;
result.winningCoefficient = 0;
return result;
}
GameWinningSymbolModel *symbolModel = this->model->GetSymbolModel(symbolIndex);
for (int reelIndex = 0; reelIndex < this->numReels; reelIndex++)
{
this->model->lines[result.lineIndex].coordinates[reelIndex] = this->FindFirstSymbol(reelIndex, symbolIndex);
if (this->model->lines[result.lineIndex].coordinates[reelIndex] != -1)
{
if (result.numItems == 0)
result.itemsStart = reelIndex;
result.numItems++;
result.itemsEnd = reelIndex;
}
}
result.symbolsFlags = symbolModel->flags;
result.winningCoefficient = this->model->GetSymbolCoefficient(result.symbolIndex, result.numItems);
return result;
}
void GkGameWinningsAnalyzer::AnalyzeWinnings(GkBaseReelMap *reelMap)
{
if (reelMap != 0)
this->SetItems(reelMap);
this->winnings.count = 0;
// Analyze line winnings
for (int lineIndex = 0; lineIndex < this->model->numLines; lineIndex++)
{
if (this->model->lines[lineIndex].active)
{
GameWinning maxLineWin;
maxLineWin.winningCoefficient = 0;
for (int symbolIndex = 0; symbolIndex < this->model->numSymbols; symbolIndex++)
{
if ((this->model->GetSymbolModel(symbolIndex)->flags & GkGameWinningsModel::SymbolFlag_Scatter) == 0)
{
GameWinning symbolWin = this->GetSymbolWinning(symbolIndex, lineIndex);
if (symbolWin.winningCoefficient != 0)
{
if ((maxLineWin.winningCoefficient == 0) ||
(this->model->CompareSymbolWinnning(symbolWin.symbolIndex, symbolWin.numItems, maxLineWin.symbolIndex, maxLineWin.numItems) > 0))
{
maxLineWin = symbolWin;
}
}
}
}
if (maxLineWin.winningCoefficient != 0)
{
this->winnings.win[this->winnings.count++] = maxLineWin;
}
}
}
// Analyze scatters
for (int symbolIndex = 0; symbolIndex < this->model->numSymbols; symbolIndex++)
{
if ((this->model->GetSymbolModel(symbolIndex)->flags & GkGameWinningsModel::SymbolFlag_Scatter) != 0)
{
GameWinning symbolWin = this->GetScatterWinning(symbolIndex);
if (symbolWin.winningCoefficient != 0)
{
this->winnings.win[this->winnings.count++] = symbolWin;
}
}
}
// Calculate total winnigs, total flags and manage items with SymbolFlag_IgnoreWinning
this->totalWinning = 0;
this->totalFlags = GkGameWinningsModel::SymbolFlag_None;
for (int i = 0; i < this->winnings.count; i++)
{
if (this->winnings.win[i].symbolsFlags & GkGameWinningsModel::SymbolFlag_IgnoreWinning)
this->winnings.win[i].winningCoefficient = 0;
this->totalWinning += this->winnings.win[i].winningCoefficient;
this->totalFlags |= this->winnings.win[i].symbolsFlags;
}
this->SortWinnings();
}
int GkGameWinningsAnalyzer::WinningOrder(int winningIndex1, int winningIndex2)
{
bool win1End = (this->model->GetSymbolModel(this->winnings.win[winningIndex1].symbolIndex)->flags & GkGameWinningsModel::SymbolFlag_AtEnd) != 0;
bool win2End = (this->model->GetSymbolModel(this->winnings.win[winningIndex2].symbolIndex)->flags & GkGameWinningsModel::SymbolFlag_AtEnd) != 0;
if (win1End && !win2End)
return 1;
if (win2End && !win1End)
return -1;
return GkMaths::Sign(this->winnings.win[winningIndex1].lineIndex - this->winnings.win[winningIndex2].lineIndex);
}
int GkGameWinningsAnalyzer::CompareWinning(int winningIndex1, int winningIndex2)
{
return GkMaths::Sign(this->winnings.win[winningIndex1].winningCoefficient - this->winnings.win[winningIndex2].winningCoefficient);
}
void GkGameWinningsAnalyzer::SortWinnings()
{
for (int i = 0; i < this->winnings.count; i++)
{
int leadingWin = i;
for (int j = i + 1; j < this->winnings.count; j++)
{
if (this->WinningOrder(leadingWin, j) > 0)
leadingWin = j;
}
if (leadingWin != i)
{
GameWinning t = this->winnings.win[i];
this->winnings.win[i] = this->winnings.win[leadingWin];
this->winnings.win[leadingWin] = t;
}
}
}
void GkGameWinningsAnalyzer::MultiplyWinnings(int factor)
{
for (int i = 0; i < this->winnings.count; i++)
this->winnings.win[i].winningCoefficient *= factor;
this->totalWinning *= factor;
}
int GkGameWinningsAnalyzer::GetLineSymbol(int reelIndex, int lineIndex)
{
return this->GetSymbol(reelIndex, model->GetLineSymbolCoordinate(reelIndex, lineIndex));
}
int GkGameWinningsAnalyzer::FindWinning(int symbolIndex, int minSymbols)
{
for (int i = 0; i < this->winnings.count; i++)
if ((this->winnings.win[i].symbolIndex == symbolIndex) && (this->winnings.win[i].numItems >= minSymbols))
return i;
return -1;
}
bool GkGameWinningsAnalyzer::ReelBelongsToWinning(int reelIndex, int winningIndex)
{
if ((winningIndex < 0) || (winningIndex >= this->winnings.count))
return false;
if (this->winnings.win[winningIndex].symbolsFlags & GkGameWinningsModel::SymbolFlag_Scatter)
{
if (this->model->lines[this->winnings.win[winningIndex].lineIndex].coordinates[reelIndex] == -1)
return false;
}
else
{
if ((reelIndex < this->winnings.win[winningIndex].itemsStart) || (reelIndex > this->winnings.win[winningIndex].itemsStart + this->winnings.win[winningIndex].numItems - 1))
return false;
}
return true;
}
bool GkGameWinningsAnalyzer::ReelBelongsToAnyWinning(int reelIndex)
{
for (int winningIndex = 0; winningIndex < this->winnings.count; winningIndex++)
if (this->ReelBelongsToWinning(reelIndex, winningIndex))
return true;
return false;
}
bool GkGameWinningsAnalyzer::ReelItemBelongsToWinning(int reelIndex, int itemIndex, int winningIndex)
{
if (!this->ReelBelongsToWinning(reelIndex, winningIndex))
return false;
return this->model->lines[this->winnings.win[winningIndex].lineIndex].coordinates[reelIndex] == itemIndex;
}
bool GkGameWinningsAnalyzer::ReelItemBelongsToAnyWinning(int reelIndex, int itemIndex)
{
for (int winningIndex = 0; winningIndex < this->winnings.count; winningIndex++)
if (this->ReelItemBelongsToWinning(reelIndex, itemIndex, winningIndex))
return true;
return false;
}
void GkGameWinningsAnalyzer::InitWinningData(GameWinnings *data)
{
data->win = new GameWinning[this->model->numLines + this->model->numScatters];
data->count = 0;
}
void GkGameWinningsAnalyzer::DisposeWinningData(GameWinnings *data)
{
delete[] data->win;
data->count = 0;
}
void GkGameWinningsAnalyzer::SaveWinningData(GameWinnings *destination)
{
destination->count = this->winnings.count;
GkOSUtils::CopyMem(destination->win, this->winnings.win, sizeof(GameWinning) * this->winnings.count);
}
WinningDataComparisonResult GkGameWinningsAnalyzer::FindWinning(GameWinning *gameWinning)
{
for (int i = 0; i < this->winnings.count; i++)
{
GameWinning *testedWinning = &this->winnings.win[i];
if ((testedWinning->symbolIndex == gameWinning->symbolIndex) &&
((testedWinning->lineIndex == gameWinning->lineIndex) ||
((testedWinning->symbolsFlags & GkGameWinningsModel::SymbolFlag_Scatter) != 0) ||
(this->comparisonMode == GameWinningAnalyzerComparisonMode_IgnoreLineMatching)))
{
if (testedWinning->numItems == gameWinning->numItems)
return WinningDataComparisonResult_Equivalent;
if (testedWinning->numItems < gameWinning->numItems)
return WinningDataComparisonResult_Lesser;
if (testedWinning->numItems > gameWinning->numItems)
return WinningDataComparisonResult_Greater;
}
}
return WinningDataComparisonResult_Different;
}
WinningDataComparisonResult GkGameWinningsAnalyzer::CompareWith(GameWinnings *data)
{
bool containsLesserWin = false,
containsGreaterWin = false;
int numMatchingWins = 0;
for (int winIndex = 0; winIndex < data->count; winIndex++)
{
GameWinning *winning = &data->win[winIndex];
WinningDataComparisonResult camparedToData = this->FindWinning(winning);
if (camparedToData == WinningDataComparisonResult_Lesser)
containsLesserWin = true;
if (camparedToData == WinningDataComparisonResult_Greater)
containsGreaterWin = true;
if (camparedToData != WinningDataComparisonResult_Different)
numMatchingWins++;
}
bool containsAllDataWins = numMatchingWins == data->count,
containsOtherWins = numMatchingWins < this->winnings.count;
if (containsAllDataWins && !containsOtherWins && !containsLesserWin && !containsGreaterWin)
return WinningDataComparisonResult_Equivalent;
if (containsAllDataWins && (containsOtherWins || containsGreaterWin) && !containsLesserWin)
return WinningDataComparisonResult_Greater;
if ((!containsAllDataWins || containsLesserWin) && !containsOtherWins && !containsGreaterWin)
return WinningDataComparisonResult_Lesser;
return WinningDataComparisonResult_Different;
}
int GkGameWinningsAnalyzer::GetWinningReelsCount()
{
int result = 0;
for (int reelIndex = 0; reelIndex < this->model->numReels; reelIndex++)
if (this->ReelBelongsToAnyWinning(reelIndex))
result++;
return result;
}
int GkGameWinningsAnalyzer::GetWinningReelsCount(int winningIndex, int startReel, int numReels)
{
int result = 0;
if (numReels == -1)
numReels = this->model->numReels;
for (int reelIndex = startReel; reelIndex < startReel + numReels; reelIndex++)
if (this->ReelBelongsToWinning(reelIndex, winningIndex))
result++;
return result;
}
int GkGameWinningsAnalyzer::GetWinningItemReelIndex(int winningItemIndex)
{
for (int reelIndex = 0; reelIndex < this->model->numReels; reelIndex++)
{
if (this->ReelBelongsToAnyWinning(reelIndex))
{
if (winningItemIndex == 0)
return reelIndex;
winningItemIndex--;
}
}
return -1;
}
int GkGameWinningsAnalyzer::GetWinningItemReelIndex(int winningItemIndex, int winningIndex)
{
for (int reelIndex = 0; reelIndex < this->model->numReels; reelIndex++)
{
if (this->ReelBelongsToWinning(reelIndex, winningIndex))
{
if (winningItemIndex == 0)
return reelIndex;
winningItemIndex--;
}
}
return -1;
}
int GkGameWinningsAnalyzer::GetHighestWinning()
{
if (this->winnings.count == 0)
return -1;
int result = 0;
for (int winIndex = 1; winIndex < this->winnings.count; winIndex++)
if (this->CompareWinning(winIndex, result) > 0)
result = winIndex;
return result;
}