- Added new code for serialization/deserializaiton of full games including initial game and all the player actions.
- Added an undo menu using this code (beware, it's still very very alpha). - Removed various warning - Cleaned up avatar loading - Added full random lists load/save including the deck shuffling (not sure if I could not replace that with seed load/save) - Moved momir and Co rules configuration out of GameStateDuel - Create a GameType type to avoid mixing int everywhere
This commit is contained in:
@@ -38,22 +38,6 @@ enum
|
|||||||
#endif //NETWORK_SUPPORT
|
#endif //NETWORK_SUPPORT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
GAME_TYPE_CLASSIC,
|
|
||||||
GAME_TYPE_MOMIR,
|
|
||||||
GAME_TYPE_RANDOM1,
|
|
||||||
GAME_TYPE_RANDOM2,
|
|
||||||
GAME_TYPE_STORY,
|
|
||||||
GAME_TYPE_DEMO,
|
|
||||||
GAME_TYPE_STONEHEWER,
|
|
||||||
GAME_TYPE_HERMIT,
|
|
||||||
|
|
||||||
#ifdef NETWORK_SUPPORT
|
|
||||||
GAME_TYPE_SLAVE,
|
|
||||||
#endif //NETWORK_SUPPORT
|
|
||||||
};
|
|
||||||
|
|
||||||
class MTGAllCards;
|
class MTGAllCards;
|
||||||
class TransitionBase;
|
class TransitionBase;
|
||||||
|
|
||||||
@@ -73,7 +57,7 @@ private:
|
|||||||
GameState* mGameStates[GAME_STATE_MAX];
|
GameState* mGameStates[GAME_STATE_MAX];
|
||||||
public:
|
public:
|
||||||
|
|
||||||
int gameType;
|
GameType gameType;
|
||||||
Rules * rules;
|
Rules * rules;
|
||||||
CardEffect *effect;
|
CardEffect *effect;
|
||||||
#ifdef NETWORK_SUPPORT
|
#ifdef NETWORK_SUPPORT
|
||||||
|
|||||||
@@ -26,10 +26,21 @@ class GameObserver{
|
|||||||
protected:
|
protected:
|
||||||
MTGCardInstance * cardWaitingForTargets;
|
MTGCardInstance * cardWaitingForTargets;
|
||||||
queue<WEvent *> eventsQueue;
|
queue<WEvent *> eventsQueue;
|
||||||
|
list<string> actionsList;
|
||||||
|
|
||||||
int untap(MTGCardInstance * card);
|
int untap(MTGCardInstance * card);
|
||||||
bool WaitForExtraPayment(MTGCardInstance* card);
|
bool WaitForExtraPayment(MTGCardInstance* card);
|
||||||
void initialize();
|
void initialize();
|
||||||
|
void cleanup();
|
||||||
|
string startupGameSerialized;
|
||||||
|
bool parseLine(const string& s);
|
||||||
|
void logAction(const string& s) {
|
||||||
|
actionsList.push_back(s);
|
||||||
|
};
|
||||||
|
bool processActions(bool undo);
|
||||||
|
friend ostream& operator<<(ostream&, GameObserver&);
|
||||||
|
bool load(const string& s, bool undo);
|
||||||
|
bool mLoading;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int currentPlayerId;
|
int currentPlayerId;
|
||||||
@@ -49,6 +60,7 @@ class GameObserver{
|
|||||||
vector<Player *> players; //created outside
|
vector<Player *> players; //created outside
|
||||||
time_t startedAt;
|
time_t startedAt;
|
||||||
Rules * mRules;
|
Rules * mRules;
|
||||||
|
GameType mGameType;
|
||||||
|
|
||||||
TargetChooser * getCurrentTargetChooser();
|
TargetChooser * getCurrentTargetChooser();
|
||||||
void stackObjectClicked(Interruptible * action);
|
void stackObjectClicked(Interruptible * action);
|
||||||
@@ -74,10 +86,9 @@ class GameObserver{
|
|||||||
void gameStateBasedEffects();
|
void gameStateBasedEffects();
|
||||||
void enchantmentStatus();
|
void enchantmentStatus();
|
||||||
void Affinity();
|
void Affinity();
|
||||||
void eventOccured();
|
|
||||||
void addObserver(MTGAbility * observer);
|
void addObserver(MTGAbility * observer);
|
||||||
bool removeObserver(ActionElement * observer);
|
bool removeObserver(ActionElement * observer);
|
||||||
void startGame(Rules * rules);
|
void startGame(GameType, Rules * rules);
|
||||||
void untapPhase();
|
void untapPhase();
|
||||||
MTGCardInstance * isCardWaiting(){ return cardWaitingForTargets; }
|
MTGCardInstance * isCardWaiting(){ return cardWaitingForTargets; }
|
||||||
int isInPlay(MTGCardInstance * card);
|
int isInPlay(MTGCardInstance * card);
|
||||||
@@ -90,6 +101,14 @@ class GameObserver{
|
|||||||
|
|
||||||
int receiveEvent(WEvent * event);
|
int receiveEvent(WEvent * event);
|
||||||
bool connectRule;
|
bool connectRule;
|
||||||
|
|
||||||
|
void logAction(Player* player, const string& s="");
|
||||||
|
void logAction(int playerId, const string& s="") {
|
||||||
|
logAction(players[playerId], s);
|
||||||
|
};
|
||||||
|
void logAction(MTGCardInstance* card, MTGGameZone* zone = NULL);
|
||||||
|
bool undo();
|
||||||
|
bool isLoading(){ return mLoading; };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -78,9 +78,10 @@ public:
|
|||||||
MENUITEM_MAIN_MENU = -13,
|
MENUITEM_MAIN_MENU = -13,
|
||||||
MENUITEM_EVIL_TWIN = kEvilTwinMenuID,
|
MENUITEM_EVIL_TWIN = kEvilTwinMenuID,
|
||||||
MENUITEM_MULLIGAN = -15,
|
MENUITEM_MULLIGAN = -15,
|
||||||
|
MENUITEM_UNDO = -16,
|
||||||
#ifdef NETWORK_SUPPORT
|
#ifdef NETWORK_SUPPORT
|
||||||
MENUITEM_REMOTE_CLIENT = -16,
|
MENUITEM_REMOTE_CLIENT = -17,
|
||||||
MENUITEM_REMOTE_SERVER = -17,
|
MENUITEM_REMOTE_SERVER = -18,
|
||||||
#endif
|
#endif
|
||||||
MENUITEM_MORE_INFO = kInfoMenuID
|
MENUITEM_MORE_INFO = kInfoMenuID
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -210,9 +210,8 @@ public:
|
|||||||
|
|
||||||
static MTGCardInstance ExtraRules[2];
|
static MTGCardInstance ExtraRules[2];
|
||||||
|
|
||||||
|
bool parseLine(const string& ss);
|
||||||
};
|
};
|
||||||
|
|
||||||
ostream& operator<<(ostream&, const MTGCardInstance&);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,6 +7,23 @@ const float DEFAULT_TEXT_FONT_SCALE = 1.0f;
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GAME_TYPE_CLASSIC,
|
||||||
|
GAME_TYPE_MOMIR,
|
||||||
|
GAME_TYPE_RANDOM1,
|
||||||
|
GAME_TYPE_RANDOM2,
|
||||||
|
GAME_TYPE_STORY,
|
||||||
|
GAME_TYPE_DEMO,
|
||||||
|
GAME_TYPE_STONEHEWER,
|
||||||
|
GAME_TYPE_HERMIT,
|
||||||
|
|
||||||
|
#ifdef NETWORK_SUPPORT
|
||||||
|
GAME_TYPE_SLAVE,
|
||||||
|
#endif //NETWORK_SUPPORT
|
||||||
|
} GameType;
|
||||||
|
|
||||||
class Constants
|
class Constants
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ class MTGGameZone {
|
|||||||
void debugPrint();
|
void debugPrint();
|
||||||
MTGCardInstance * removeCard(MTGCardInstance * card, int createCopy = 1);
|
MTGCardInstance * removeCard(MTGCardInstance * card, int createCopy = 1);
|
||||||
MTGCardInstance * hasCard(MTGCardInstance * card);
|
MTGCardInstance * hasCard(MTGCardInstance * card);
|
||||||
|
size_t getIndex(MTGCardInstance * card);
|
||||||
void cleanupPhase();
|
void cleanupPhase();
|
||||||
void beforeBeginPhase();
|
void beforeBeginPhase();
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ class Player: public Damageable
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
ManaPool * manaPool;
|
ManaPool * manaPool;
|
||||||
|
JTexture * mAvatarTex;
|
||||||
|
JQuadPtr mAvatar;
|
||||||
|
bool loadAvatar(string file, string resName = "playerAvatar");
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum ENUM_PLAY_MODE
|
enum ENUM_PLAY_MODE
|
||||||
@@ -25,8 +29,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
string mAvatarName;
|
string mAvatarName;
|
||||||
JTexture * mAvatarTex;
|
|
||||||
JQuadPtr mAvatar;
|
|
||||||
int playMode;
|
int playMode;
|
||||||
bool nomaxhandsize;
|
bool nomaxhandsize;
|
||||||
MTGPlayerCards * game;
|
MTGPlayerCards * game;
|
||||||
@@ -35,7 +37,7 @@ public:
|
|||||||
string deckFileSmall;
|
string deckFileSmall;
|
||||||
string deckName;
|
string deckName;
|
||||||
string phaseRing;
|
string phaseRing;
|
||||||
int offerInterruptOnPhase;
|
int offerInterruptOnPhase;
|
||||||
Player(GameObserver *observer, string deckFile, string deckFileSmall, MTGDeck * deck = NULL);
|
Player(GameObserver *observer, string deckFile, string deckFileSmall, MTGDeck * deck = NULL);
|
||||||
virtual ~Player();
|
virtual ~Player();
|
||||||
virtual void setObserver(GameObserver*g);
|
virtual void setObserver(GameObserver*g);
|
||||||
@@ -89,22 +91,18 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadAvatar(string file);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Returns the path to the stats file of currently selected deck.
|
** Returns the path to the stats file of currently selected deck.
|
||||||
*/
|
*/
|
||||||
std::string GetCurrentDeckStatsFile();
|
std::string GetCurrentDeckStatsFile();
|
||||||
bool parseLine(const string& s);
|
bool parseLine(const string& s);
|
||||||
|
friend ostream& operator<<(ostream&, const Player&);
|
||||||
};
|
};
|
||||||
|
|
||||||
class HumanPlayer: public Player
|
class HumanPlayer: public Player
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HumanPlayer(GameObserver *observer, string deckFile, string deckFileSmall = "", MTGDeck * deck = NULL);
|
HumanPlayer(GameObserver *observer, string deckFile, string deckFileSmall, MTGDeck * deck = NULL);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ostream& operator<<(ostream&, const Player&);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ protected:
|
|||||||
Player * loadPlayerRandom(GameObserver* observer, int isAI, int mode);
|
Player * loadPlayerRandom(GameObserver* observer, int isAI, int mode);
|
||||||
Player * initPlayer(GameObserver *observer, int playerId);
|
Player * initPlayer(GameObserver *observer, int playerId);
|
||||||
MTGDeck * buildDeck(int playerId);
|
MTGDeck * buildDeck(int playerId);
|
||||||
int strToGameMode(string s);
|
GameType strToGameMode(string s);
|
||||||
bool postUpdateInitDone;
|
bool postUpdateInitDone;
|
||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
@@ -57,7 +57,7 @@ public:
|
|||||||
|
|
||||||
string bg;
|
string bg;
|
||||||
string filename;
|
string filename;
|
||||||
int gamemode;
|
GameType gamemode;
|
||||||
bool hidden;
|
bool hidden;
|
||||||
string displayName;
|
string displayName;
|
||||||
int unlockOption;
|
int unlockOption;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
int startTime, endTime;
|
int startTime, endTime;
|
||||||
int gameType;
|
GameType gameType;
|
||||||
unsigned int seed;
|
unsigned int seed;
|
||||||
int nbFailed, nbTests, nbAIFailed, nbAITests;
|
int nbFailed, nbTests, nbAIFailed, nbAITests;
|
||||||
TestSuite(const char * filename);
|
TestSuite(const char * filename);
|
||||||
|
|||||||
@@ -63,9 +63,11 @@ std::string wordWrap(const std::string& s, float width, int fontId);
|
|||||||
//basic hash function
|
//basic hash function
|
||||||
unsigned long hash_djb2(const char *str);
|
unsigned long hash_djb2(const char *str);
|
||||||
|
|
||||||
int loadRandValues(string s);
|
void loadRandValues(string s);
|
||||||
|
ostream& saveRandValues(ostream& out);
|
||||||
int filesize(const char * filename);
|
int filesize(const char * filename);
|
||||||
int WRand();
|
int WRand();
|
||||||
|
ptrdiff_t MRand (ptrdiff_t i);
|
||||||
|
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
void dumpStack();
|
void dumpStack();
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ int AIAction::clickMultiAct(vector<Targetable*>& actionTargets)
|
|||||||
actionTargets.erase(actionTargets.begin() + f);
|
actionTargets.erase(actionTargets.begin() + f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::random_shuffle(actionTargets.begin(), actionTargets.end());
|
std::random_shuffle(actionTargets.begin(), actionTargets.end(), MRand);
|
||||||
//shuffle to make it less predictable, otherwise ai will always seem to target from right to left. making it very obvious.
|
//shuffle to make it less predictable, otherwise ai will always seem to target from right to left. making it very obvious.
|
||||||
for(int k = 0;k < int(actionTargets.size());k++)
|
for(int k = 0;k < int(actionTargets.size());k++)
|
||||||
{
|
{
|
||||||
@@ -172,7 +172,7 @@ int AIPlayer::clickMultiTarget(TargetChooser * tc, vector<Targetable*>& potentia
|
|||||||
potentialTargets.erase(potentialTargets.begin() + f);
|
potentialTargets.erase(potentialTargets.begin() + f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::random_shuffle(potentialTargets.begin(), potentialTargets.end());
|
std::random_shuffle(potentialTargets.begin(), potentialTargets.end(), MRand);
|
||||||
if(potentialTargets.size())
|
if(potentialTargets.size())
|
||||||
clickstream.push(NEW AIAction(this, NULL,tc->source,potentialTargets));
|
clickstream.push(NEW AIAction(this, NULL,tc->source,potentialTargets));
|
||||||
while(clickstream.size())
|
while(clickstream.size())
|
||||||
@@ -257,7 +257,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(GameObserver *observer, MTGAllCards *
|
|||||||
{
|
{
|
||||||
bool isOpponentAI = opponent->isAI() == 1;
|
bool isOpponentAI = opponent->isAI() == 1;
|
||||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI);
|
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI);
|
||||||
if ( meta->getVictoryPercentage() >= 65)
|
if ( meta && meta->getVictoryPercentage() >= 65)
|
||||||
deckSetting = HARD;
|
deckSetting = HARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1410,7 +1410,7 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
|
|||||||
if(tc->belongsToAbility.size())
|
if(tc->belongsToAbility.size())
|
||||||
{
|
{
|
||||||
AbilityFactory af(observer);
|
AbilityFactory af(observer);
|
||||||
MTGAbility * withoutGuessing = af.parseMagicLine(tc->belongsToAbility,NULL,NULL,tc->source);
|
MTGAbility * withoutGuessing = af.parseMagicLine(tc->belongsToAbility,0,NULL,tc->source);
|
||||||
cardEffect = af.abilityEfficiency(withoutGuessing,this,MODE_TARGET,tc,NULL);
|
cardEffect = af.abilityEfficiency(withoutGuessing,this,MODE_TARGET,tc,NULL);
|
||||||
delete withoutGuessing;
|
delete withoutGuessing;
|
||||||
}
|
}
|
||||||
@@ -1458,7 +1458,7 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
|
|||||||
if(tc->maxtargets != 1 && tc->belongsToAbility.size())
|
if(tc->maxtargets != 1 && tc->belongsToAbility.size())
|
||||||
{
|
{
|
||||||
AbilityFactory af(observer);
|
AbilityFactory af(observer);
|
||||||
MTGAbility * withoutGuessing = af.parseMagicLine(tc->belongsToAbility,NULL,NULL,tc->source);
|
MTGAbility * withoutGuessing = af.parseMagicLine(tc->belongsToAbility,0,NULL,tc->source);
|
||||||
OrderedAIAction * effCheck = NEW OrderedAIAction(this, withoutGuessing,(MTGCardInstance*)tc->source,card);
|
OrderedAIAction * effCheck = NEW OrderedAIAction(this, withoutGuessing,(MTGCardInstance*)tc->source,card);
|
||||||
if(effCheck->getEfficiency())
|
if(effCheck->getEfficiency())
|
||||||
{
|
{
|
||||||
@@ -2200,17 +2200,16 @@ AIPlayerBaka::AIPlayerBaka(GameObserver *observer, string file, string fileSmall
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mAvatarTex = WResourceManager::Instance()->RetrieveTexture(avatarFile, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR);
|
if(avatarFile != "")
|
||||||
if (!mAvatarTex)
|
|
||||||
{
|
{
|
||||||
avatarFile = "baka.jpg";
|
if(!loadAvatar(avatarFile, "bakaAvatar"))
|
||||||
mAvatarTex = WResourceManager::Instance()->RetrieveTexture(avatarFile, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR);
|
{
|
||||||
|
avatarFile = "baka.jpg";
|
||||||
|
loadAvatar(avatarFile, "bakaAvatar");
|
||||||
|
}
|
||||||
|
mAvatarName = avatarFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAvatarTex)
|
|
||||||
mAvatar = WResourceManager::Instance()->RetrieveQuad(avatarFile, 0, 0, 35, 50, "bakaAvatar", RETRIEVE_NORMAL,
|
|
||||||
TEXTURE_SUB_AVATAR);
|
|
||||||
|
|
||||||
if (fileSmall == "ai_baka_eviltwin")
|
if (fileSmall == "ai_baka_eviltwin")
|
||||||
mAvatar->SetHFlip(true);
|
mAvatar->SetHFlip(true);
|
||||||
|
|
||||||
|
|||||||
@@ -589,6 +589,7 @@ int ActionStack::setIsInterrupting(Player * player)
|
|||||||
int playerId = (player == observer->players[1]) ? 1 : 0;
|
int playerId = (player == observer->players[1]) ? 1 : 0;
|
||||||
interruptDecision[playerId] = -1;
|
interruptDecision[playerId] = -1;
|
||||||
observer->isInterrupting = player;
|
observer->isInterrupting = player;
|
||||||
|
observer->logAction(player, "yes");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,6 +961,7 @@ void ActionStack::cancelInterruptOffer(int cancelMode)
|
|||||||
askIfWishesToInterrupt = NULL;
|
askIfWishesToInterrupt = NULL;
|
||||||
observer->isInterrupting = NULL;
|
observer->isInterrupting = NULL;
|
||||||
timer = -1;
|
timer = -1;
|
||||||
|
observer->logAction(playerId, "no");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionStack::endOfInterruption()
|
void ActionStack::endOfInterruption()
|
||||||
@@ -967,6 +969,7 @@ void ActionStack::endOfInterruption()
|
|||||||
int playerId = (observer->isInterrupting == observer->players[1]) ? 1 : 0;
|
int playerId = (observer->isInterrupting == observer->players[1]) ? 1 : 0;
|
||||||
interruptDecision[playerId] = 0;
|
interruptDecision[playerId] = 0;
|
||||||
observer->isInterrupting = NULL;
|
observer->isInterrupting = NULL;
|
||||||
|
observer->logAction(playerId, "endinterruption");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ActionStack::CheckUserInput(JButton key)
|
bool ActionStack::CheckUserInput(JButton key)
|
||||||
|
|||||||
@@ -2360,6 +2360,7 @@ int MenuAbility::reactToChoiceClick(Targetable * object,int choice,int control)
|
|||||||
game->mLayers->stackLayer()->cancelInterruptOffer();
|
game->mLayers->stackLayer()->cancelInterruptOffer();
|
||||||
this->forceDestroy = 1;
|
this->forceDestroy = 1;
|
||||||
removeMenu = true;
|
removeMenu = true;
|
||||||
|
game->logAction(source->controller(), "choice " + choice);
|
||||||
return reactToTargetClick(object);
|
return reactToTargetClick(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -661,7 +661,6 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
|
|||||||
formattedfield = FormattedData(formattedfield, "expansion", setlist[card->setId].c_str());
|
formattedfield = FormattedData(formattedfield, "expansion", setlist[card->setId].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
float w = font->GetStringWidth(formattedfield.c_str()) * kWidthScaleFactor;
|
|
||||||
font->DrawString(formattedfield.c_str(), x + (Carditem->mPosX - BigWidth / 2) * pos.actZ, pos.actY + (Carditem->mPosY) * pos.actZ);
|
font->DrawString(formattedfield.c_str(), x + (Carditem->mPosX - BigWidth / 2) * pos.actZ, pos.actY + (Carditem->mPosY) * pos.actZ);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -994,7 +993,6 @@ void CardGui::TinyCropRender(MTGCard * card, const Pos& pos, JQuad * quad)
|
|||||||
formattedfield = FormattedData(formattedfield, "expansion", setlist[card->setId].c_str());
|
formattedfield = FormattedData(formattedfield, "expansion", setlist[card->setId].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
float w = font->GetStringWidth(formattedfield.c_str()) * kWidthScaleFactor;
|
|
||||||
font->DrawString(formattedfield.c_str(), x + (Carditem->mPosX - BigWidth / 2) * pos.actZ, pos.actY + (Carditem->mPosY) * pos.actZ);
|
font->DrawString(formattedfield.c_str(), x + (Carditem->mPosX - BigWidth / 2) * pos.actZ, pos.actY + (Carditem->mPosY) * pos.actZ);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -305,6 +305,10 @@ ostream& DamageStack::toString(ostream& out) const
|
|||||||
|
|
||||||
ostream& operator<<(ostream& out, const Damageable& p)
|
ostream& operator<<(ostream& out, const Damageable& p)
|
||||||
{
|
{
|
||||||
|
out << "life=" << p.life << endl;
|
||||||
|
out << "poisoncount=" << p.poisonCount << endl;
|
||||||
|
out << "damagecount=" << p.damageCount << endl;
|
||||||
|
out << "preventable=" << p.preventable << endl;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,8 +182,13 @@ DeckManager* DeckManager::GetInstance()
|
|||||||
// p2 is the opponent
|
// p2 is the opponent
|
||||||
int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player)
|
int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player)
|
||||||
{
|
{
|
||||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename(player->deckFile, (player->isAI() == 1) );
|
if(player->deckFile != "")
|
||||||
return meta->getDifficulty();
|
{
|
||||||
|
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename(player->deckFile, (player->isAI() == 1) );
|
||||||
|
return meta->getDifficulty();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return EASY;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeckManager::~DeckManager()
|
DeckManager::~DeckManager()
|
||||||
|
|||||||
@@ -79,8 +79,9 @@ void DuelLayers::Update(float dt, Player * currentPlayer)
|
|||||||
for (int i = 0; i < nbitems; ++i)
|
for (int i = 0; i < nbitems; ++i)
|
||||||
objects[i]->Update(dt);
|
objects[i]->Update(dt);
|
||||||
int isAI = currentPlayer->isAI();
|
int isAI = currentPlayer->isAI();
|
||||||
if (isAI)
|
if (isAI && !currentPlayer->getObserver()->isLoading())
|
||||||
currentPlayer->Act(dt);
|
currentPlayer->Act(dt);
|
||||||
|
|
||||||
CheckUserInput(isAI);
|
CheckUserInput(isAI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,12 @@
|
|||||||
#include <JRenderer.h>
|
#include <JRenderer.h>
|
||||||
#include "MTGGamePhase.h"
|
#include "MTGGamePhase.h"
|
||||||
#include "GuiPhaseBar.h"
|
#include "GuiPhaseBar.h"
|
||||||
|
#include "AIPlayerBaka.h"
|
||||||
GameObserver::GameObserver()
|
#include "MTGRules.h"
|
||||||
{
|
|
||||||
initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameObserver::initialize()
|
void GameObserver::initialize()
|
||||||
{
|
{
|
||||||
|
mGameType = GAME_TYPE_CLASSIC;
|
||||||
currentPlayer = NULL;
|
currentPlayer = NULL;
|
||||||
currentActionPlayer = NULL;
|
currentActionPlayer = NULL;
|
||||||
isInterrupting = NULL;
|
isInterrupting = NULL;
|
||||||
@@ -32,6 +30,61 @@ void GameObserver::initialize()
|
|||||||
combatStep = BLOCKERS;
|
combatStep = BLOCKERS;
|
||||||
mRules = NULL;
|
mRules = NULL;
|
||||||
connectRule = false;
|
connectRule = false;
|
||||||
|
mLoading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObserver::cleanup()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(targetChooser);
|
||||||
|
SAFE_DELETE(mLayers);
|
||||||
|
SAFE_DELETE(phaseRing);
|
||||||
|
SAFE_DELETE(replacementEffects);
|
||||||
|
for (size_t i = 0; i < players.size(); ++i)
|
||||||
|
{
|
||||||
|
SAFE_DELETE(players[i]);
|
||||||
|
}
|
||||||
|
players.clear();
|
||||||
|
|
||||||
|
currentPlayer = NULL;
|
||||||
|
currentActionPlayer = NULL;
|
||||||
|
isInterrupting = NULL;
|
||||||
|
currentPlayerId = 0;
|
||||||
|
currentGamePhase = -1;
|
||||||
|
targetChooser = NULL;
|
||||||
|
cardWaitingForTargets = NULL;
|
||||||
|
mExtraPayment = NULL;
|
||||||
|
gameOver = NULL;
|
||||||
|
phaseRing = NULL;
|
||||||
|
replacementEffects = NEW ReplacementEffects();
|
||||||
|
combatStep = BLOCKERS;
|
||||||
|
connectRule = false;
|
||||||
|
actionsList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObserver::~GameObserver()
|
||||||
|
{
|
||||||
|
LOG("==Destroying GameObserver==");
|
||||||
|
SAFE_DELETE(targetChooser);
|
||||||
|
SAFE_DELETE(mLayers);
|
||||||
|
SAFE_DELETE(phaseRing);
|
||||||
|
SAFE_DELETE(replacementEffects);
|
||||||
|
for (size_t i = 0; i < players.size(); ++i)
|
||||||
|
{
|
||||||
|
SAFE_DELETE(players[i]);
|
||||||
|
}
|
||||||
|
players.clear();
|
||||||
|
LOG("==GameObserver Destroyed==");
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObserver::GameObserver()
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObserver::GameObserver(vector<Player *> _players)
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
setPlayers(_players);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObserver::setPlayers(vector<Player *> _players)
|
void GameObserver::setPlayers(vector<Player *> _players)
|
||||||
@@ -43,12 +96,6 @@ void GameObserver::setPlayers(vector<Player *> _players)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObserver::GameObserver(vector<Player *> _players)
|
|
||||||
{
|
|
||||||
initialize();
|
|
||||||
setPlayers(_players);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GameObserver::getCurrentGamePhase()
|
int GameObserver::getCurrentGamePhase()
|
||||||
{
|
{
|
||||||
return currentGamePhase;
|
return currentGamePhase;
|
||||||
@@ -231,7 +278,7 @@ void GameObserver::userRequestNextGamePhase()
|
|||||||
{
|
{
|
||||||
nextGamePhase();
|
nextGamePhase();
|
||||||
}
|
}
|
||||||
|
logAction(currentPlayer, "next");
|
||||||
}
|
}
|
||||||
|
|
||||||
int GameObserver::forceShuffleLibraries()
|
int GameObserver::forceShuffleLibraries()
|
||||||
@@ -250,8 +297,9 @@ int GameObserver::forceShuffleLibraries()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObserver::startGame(Rules * rules)
|
void GameObserver::startGame(GameType gtype, Rules * rules)
|
||||||
{
|
{
|
||||||
|
mGameType = gtype;
|
||||||
turn = 0;
|
turn = 0;
|
||||||
mRules = rules;
|
mRules = rules;
|
||||||
if (rules)
|
if (rules)
|
||||||
@@ -266,6 +314,11 @@ void GameObserver::startGame(Rules * rules)
|
|||||||
currentPlayer = players[0];
|
currentPlayer = players[0];
|
||||||
currentActionPlayer = currentPlayer;
|
currentActionPlayer = currentPlayer;
|
||||||
phaseRing = NEW PhaseRing(this);
|
phaseRing = NEW PhaseRing(this);
|
||||||
|
|
||||||
|
stringstream stream;
|
||||||
|
stream << *this;
|
||||||
|
startupGameSerialized = stream.str();
|
||||||
|
|
||||||
if (rules)
|
if (rules)
|
||||||
rules->initGame(this);
|
rules->initGame(this);
|
||||||
|
|
||||||
@@ -311,6 +364,26 @@ void GameObserver::startGame(Rules * rules)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(gtype) {
|
||||||
|
case GAME_TYPE_MOMIR:
|
||||||
|
{
|
||||||
|
addObserver(NEW MTGMomirRule(this, -1, MTGCollection()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GAME_TYPE_STONEHEWER:
|
||||||
|
{
|
||||||
|
addObserver(NEW MTGStoneHewerRule(this, -1,MTGCollection()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GAME_TYPE_HERMIT:
|
||||||
|
{
|
||||||
|
addObserver(NEW MTGHermitRule(this, -1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObserver::addObserver(MTGAbility * observer)
|
void GameObserver::addObserver(MTGAbility * observer)
|
||||||
@@ -328,21 +401,6 @@ bool GameObserver::removeObserver(ActionElement * observer)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObserver::~GameObserver()
|
|
||||||
{
|
|
||||||
LOG("==Destroying GameObserver==");
|
|
||||||
SAFE_DELETE(targetChooser);
|
|
||||||
SAFE_DELETE(mLayers);
|
|
||||||
SAFE_DELETE(phaseRing);
|
|
||||||
SAFE_DELETE(replacementEffects);
|
|
||||||
for (size_t i = 0; i < players.size(); ++i)
|
|
||||||
{
|
|
||||||
SAFE_DELETE(players[i]);
|
|
||||||
}
|
|
||||||
players.clear();
|
|
||||||
LOG("==GameObserver Destroyed==");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameObserver::Update(float dt)
|
void GameObserver::Update(float dt)
|
||||||
{
|
{
|
||||||
Player * player = currentPlayer;
|
Player * player = currentPlayer;
|
||||||
@@ -890,8 +948,12 @@ bool GameObserver::WaitForExtraPayment(MTGCardInstance * card)
|
|||||||
int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
||||||
{
|
{
|
||||||
Player * clickedPlayer = NULL;
|
Player * clickedPlayer = NULL;
|
||||||
if (!card)
|
if (!card) {
|
||||||
clickedPlayer = ((Player *) object);
|
clickedPlayer = ((Player *) object);
|
||||||
|
logAction(clickedPlayer);
|
||||||
|
} else {
|
||||||
|
logAction(card);
|
||||||
|
}
|
||||||
if (targetChooser)
|
if (targetChooser)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@@ -928,8 +990,8 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WaitForExtraPayment(card))
|
if (WaitForExtraPayment(card))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
int reaction = 0;
|
int reaction = 0;
|
||||||
|
|
||||||
@@ -959,18 +1021,18 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reaction = mLayers->actionLayer()->isReactingToClick(card);
|
reaction = mLayers->actionLayer()->isReactingToClick(card);
|
||||||
if (reaction == -1)
|
if (reaction == -1)
|
||||||
return mLayers->actionLayer()->reactToClick(card);
|
return mLayers->actionLayer()->reactToClick(card);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{//this handles abilities on a menu...not just when card is being played
|
{//this handles abilities on a menu...not just when card is being played
|
||||||
reaction = mLayers->actionLayer()->isReactingToTargetClick(object);
|
reaction = mLayers->actionLayer()->isReactingToTargetClick(object);
|
||||||
if (reaction == -1)
|
if (reaction == -1)
|
||||||
return mLayers->actionLayer()->reactToTargetClick(object);
|
return mLayers->actionLayer()->reactToTargetClick(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!card)
|
if (!card)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
//Current player's hand
|
//Current player's hand
|
||||||
if (currentPlayer->game->hand->hasCard(card) && currentGamePhase == Constants::MTG_PHASE_CLEANUP
|
if (currentPlayer->game->hand->hasCard(card) && currentGamePhase == Constants::MTG_PHASE_CLEANUP
|
||||||
@@ -998,7 +1060,6 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GameObserver::untap(MTGCardInstance * card)
|
int GameObserver::untap(MTGCardInstance * card)
|
||||||
@@ -1118,3 +1179,247 @@ int GameObserver::targetListIsSet(MTGCardInstance * card)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ostream& operator<<(ostream& out, GameObserver& g)
|
||||||
|
{
|
||||||
|
if(g.startupGameSerialized == "")
|
||||||
|
{
|
||||||
|
out << "[init]" << endl;
|
||||||
|
out << "player=" << g.currentPlayerId + 1 << endl;
|
||||||
|
if(g.currentGamePhase != -1)
|
||||||
|
out << "phase=" << g.phaseRing->phaseName(g.currentGamePhase) << endl;
|
||||||
|
out << "[player1]" << endl;
|
||||||
|
out << *(g.players[0]) << endl;
|
||||||
|
out << "[player2]" << endl;
|
||||||
|
out << *(g.players[1]) << endl;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << "rvalues:";
|
||||||
|
out << saveRandValues(out);
|
||||||
|
out << endl;
|
||||||
|
out << g.startupGameSerialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "[do]" << endl;
|
||||||
|
list<string>::iterator it;
|
||||||
|
|
||||||
|
for(it = (g.actionsList.begin()); it != (g.actionsList.end()); it++)
|
||||||
|
{
|
||||||
|
out << (*it) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "[end]" << endl;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObserver::parseLine(const string& s)
|
||||||
|
{
|
||||||
|
size_t limiter = s.find("=");
|
||||||
|
if (limiter == string::npos) limiter = s.find(":");
|
||||||
|
string areaS;
|
||||||
|
if (limiter != string::npos)
|
||||||
|
{
|
||||||
|
areaS = s.substr(0, limiter);
|
||||||
|
if (areaS.compare("player") == 0)
|
||||||
|
{
|
||||||
|
currentPlayerId = atoi(s.substr(limiter + 1).c_str()) - 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (areaS.compare("phase") == 0)
|
||||||
|
{
|
||||||
|
currentGamePhase = PhaseRing::phaseStrToInt(s.substr(limiter + 1).c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObserver::load(const string& ss, bool undo)
|
||||||
|
{
|
||||||
|
int state = -1;
|
||||||
|
string s;
|
||||||
|
stringstream stream(ss);
|
||||||
|
string deckFile = players[0]->deckFile;
|
||||||
|
string deckFileSmall = players[0]->deckFileSmall;
|
||||||
|
|
||||||
|
DebugTrace("Loading " + ss);
|
||||||
|
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
while (std::getline(stream, s))
|
||||||
|
{
|
||||||
|
if (!s.size()) continue;
|
||||||
|
if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files
|
||||||
|
if (!s.size()) continue;
|
||||||
|
if (s[0] == '#') continue;
|
||||||
|
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||||
|
if (s.find("seed ") == 0)
|
||||||
|
{
|
||||||
|
// seed = atoi(s.substr(5).c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (s.find("rvalues:") == 0)
|
||||||
|
{
|
||||||
|
loadRandValues(s.substr(8).c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
if (s.compare("[init]") == 0)
|
||||||
|
state++;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
if (s.compare("[player1]") == 0)
|
||||||
|
{
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parseLine(s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (s.compare("[player2]") == 0)
|
||||||
|
{
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!players[0])
|
||||||
|
players.push_back(new HumanPlayer(this, deckFile, deckFileSmall));
|
||||||
|
players[0]->parseLine(s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (s.compare("[do]") == 0)
|
||||||
|
{
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!players[1]) {
|
||||||
|
AIPlayerFactory playerCreator;
|
||||||
|
players.push_back(playerCreator.createAIPlayer(this, MTGCollection(), players[0]));
|
||||||
|
}
|
||||||
|
players[1]->parseLine(s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (s.compare("[end]") == 0)
|
||||||
|
{
|
||||||
|
turn = 0;
|
||||||
|
mLayers = NEW DuelLayers();
|
||||||
|
mLayers->init(this);
|
||||||
|
currentPlayer = players[currentPlayerId];
|
||||||
|
phaseRing = NEW PhaseRing(this);
|
||||||
|
startedAt = time(0);
|
||||||
|
|
||||||
|
mRules->initGame(this);
|
||||||
|
phaseRing->goToPhase(0, currentPlayer, false);
|
||||||
|
phaseRing->goToPhase(currentGamePhase, currentPlayer);
|
||||||
|
processActions(undo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logAction(s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObserver::processActions(bool undo)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
list<string> copyList = actionsList;
|
||||||
|
actionsList.clear();
|
||||||
|
|
||||||
|
mLoading = true;
|
||||||
|
list<string>::iterator ite;
|
||||||
|
float counter = 0.0f;
|
||||||
|
|
||||||
|
// To handle undo, we'll remove the last P1 action and all P2 actions after.
|
||||||
|
if(undo) {
|
||||||
|
while(copyList.back().find("p2") != string::npos)
|
||||||
|
copyList.pop_back();
|
||||||
|
copyList.pop_back();
|
||||||
|
}
|
||||||
|
for(ite = copyList.begin(); ite != copyList.end(); ite++)
|
||||||
|
{
|
||||||
|
string s = *ite;
|
||||||
|
Player* p = players[1];
|
||||||
|
if (s.find("p1") != string::npos)
|
||||||
|
p = players[0];
|
||||||
|
|
||||||
|
MTGGameZone* zone = NULL;
|
||||||
|
if(s.find(p->game->hand->getName()) != string::npos)
|
||||||
|
zone = p->game->hand;
|
||||||
|
else if(s.find(p->game->battlefield->getName()) != string::npos)
|
||||||
|
zone = p->game->battlefield;
|
||||||
|
else if(s.find(p->game->graveyard->getName()) != string::npos)
|
||||||
|
zone = p->game->graveyard;
|
||||||
|
else if(s.find(p->game->library->getName()) != string::npos)
|
||||||
|
zone = p->game->library;
|
||||||
|
|
||||||
|
if(zone) {
|
||||||
|
size_t begin = s.find("[")+1;
|
||||||
|
size_t size = s.find("]")-begin;
|
||||||
|
int index = atoi(s.substr(begin, size).c_str());
|
||||||
|
cardClick(zone->cards[index], zone->cards[index]);
|
||||||
|
} else if (s.find("yes") != string::npos) {
|
||||||
|
mLayers->stackLayer()->setIsInterrupting(p);
|
||||||
|
} else if (s.find("no") != string::npos) {
|
||||||
|
mLayers->stackLayer()->cancelInterruptOffer();
|
||||||
|
} else if (s.find("endinterruption") != string::npos) {
|
||||||
|
mLayers->stackLayer()->endOfInterruption();
|
||||||
|
} else if (s.find("next") != string::npos) {
|
||||||
|
userRequestNextGamePhase();
|
||||||
|
} else if (s.find("choice") != string::npos) {
|
||||||
|
int choice = atoi(s.substr(s.find("choice ") + 7).c_str());
|
||||||
|
mLayers->actionLayer()->doReactTo(choice);
|
||||||
|
} else if (s == "p1" || s == "p2") {
|
||||||
|
cardClick(NULL, p);
|
||||||
|
} else {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let's fake an update
|
||||||
|
Update(counter);
|
||||||
|
counter += 1.000f;
|
||||||
|
// or two
|
||||||
|
Update(counter);
|
||||||
|
counter += 1.000f;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLoading = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObserver::logAction(Player* player, const string& s) {
|
||||||
|
if(player == players[0])
|
||||||
|
logAction("p1." + s);
|
||||||
|
else
|
||||||
|
logAction("p2." + s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObserver::logAction(MTGCardInstance* card, MTGGameZone* zone) {
|
||||||
|
stringstream stream;
|
||||||
|
if(zone == NULL) zone = card->currentZone;
|
||||||
|
stream << "p" << ((card->controller()==players[0])?"1.":"2.")
|
||||||
|
<< zone->getName()<< "[" << zone->getIndex(card) << "]";
|
||||||
|
logAction(stream.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObserver::undo()
|
||||||
|
{
|
||||||
|
stringstream stream;
|
||||||
|
stream << *this;
|
||||||
|
DebugTrace(stream.str());
|
||||||
|
return load(stream.str(), true);
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include "DeckManager.h"
|
#include "DeckManager.h"
|
||||||
|
|
||||||
#include "DeckMetaData.h"
|
#include "DeckMetaData.h"
|
||||||
#include "MTGRules.h"
|
|
||||||
#include "Credits.h"
|
#include "Credits.h"
|
||||||
#include "Translate.h"
|
#include "Translate.h"
|
||||||
#include "Rules.h"
|
#include "Rules.h"
|
||||||
@@ -267,11 +266,7 @@ void GameStateDuel::loadTestSuitePlayers()
|
|||||||
game->setPlayers(mPlayers);
|
game->setPlayers(mPlayers);
|
||||||
mParent->gameType = testSuite->gameType;
|
mParent->gameType = testSuite->gameType;
|
||||||
|
|
||||||
game->startGame(mParent->rules);
|
game->startGame(mParent->gameType, mParent->rules);
|
||||||
if (mParent->gameType == GAME_TYPE_MOMIR)
|
|
||||||
{
|
|
||||||
game->addObserver(NEW MTGMomirRule(game, -1, MTGCollection()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -447,19 +442,7 @@ void GameStateDuel::Update(float dt)
|
|||||||
if (!game)
|
if (!game)
|
||||||
{
|
{
|
||||||
game = new GameObserver(mPlayers);
|
game = new GameObserver(mPlayers);
|
||||||
game->startGame(mParent->rules);
|
game->startGame(mParent->gameType, mParent->rules);
|
||||||
if (mParent->gameType == GAME_TYPE_MOMIR)
|
|
||||||
{
|
|
||||||
game->addObserver(NEW MTGMomirRule(game, -1, MTGCollection()));
|
|
||||||
}
|
|
||||||
if (mParent->gameType == GAME_TYPE_STONEHEWER)
|
|
||||||
{
|
|
||||||
game->addObserver(NEW MTGStoneHewerRule(game, -1,MTGCollection()));
|
|
||||||
}
|
|
||||||
if (mParent->gameType == GAME_TYPE_HERMIT)
|
|
||||||
{
|
|
||||||
game->addObserver(NEW MTGHermitRule(game, -1));
|
|
||||||
}
|
|
||||||
|
|
||||||
//start of in game music code
|
//start of in game music code
|
||||||
musictrack = "";
|
musictrack = "";
|
||||||
@@ -539,6 +522,7 @@ void GameStateDuel::Update(float dt)
|
|||||||
}
|
}
|
||||||
//END almosthumane - mulligan
|
//END almosthumane - mulligan
|
||||||
menu->Add(MENUITEM_MAIN_MENU, "Back to main menu");
|
menu->Add(MENUITEM_MAIN_MENU, "Back to main menu");
|
||||||
|
menu->Add(MENUITEM_UNDO, "Undo");
|
||||||
menu->Add(MENUITEM_CANCEL, "Cancel");
|
menu->Add(MENUITEM_CANCEL, "Cancel");
|
||||||
}
|
}
|
||||||
setGamePhase(DUEL_STATE_MENU);
|
setGamePhase(DUEL_STATE_MENU);
|
||||||
@@ -922,10 +906,14 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
|
|||||||
menu->Close();
|
menu->Close();
|
||||||
setGamePhase(DUEL_STATE_CANCEL);
|
setGamePhase(DUEL_STATE_CANCEL);
|
||||||
break;
|
break;
|
||||||
|
case MENUITEM_UNDO:
|
||||||
//END almosthumane - mulligan
|
{
|
||||||
|
game->undo();
|
||||||
|
menu->Close();
|
||||||
|
setGamePhase(DUEL_STATE_CANCEL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -389,8 +389,8 @@ void GuiCombat::Render()
|
|||||||
damage = 0;
|
damage = 0;
|
||||||
if (activeAtk->card->has(Constants::TRAMPLE))
|
if (activeAtk->card->has(Constants::TRAMPLE))
|
||||||
{
|
{
|
||||||
observer->opponent()->mAvatar->SetHotSpot(18, 25);
|
observer->opponent()->getIcon()->SetHotSpot(18, 25);
|
||||||
enemy_avatar.Render(observer->opponent()->mAvatar.get());
|
enemy_avatar.Render(observer->opponent()->getIcon().get());
|
||||||
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
||||||
mFont->SetColor(ARGB(255, 255, 64, 0));
|
mFont->SetColor(ARGB(255, 255, 64, 0));
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,6 +64,12 @@ bool GuiHand::isInHand(CardView* card)
|
|||||||
GuiHandOpponent::GuiHandOpponent(GameObserver* observer, MTGHand* hand) :
|
GuiHandOpponent::GuiHandOpponent(GameObserver* observer, MTGHand* hand) :
|
||||||
GuiHand(observer, hand)
|
GuiHand(observer, hand)
|
||||||
{
|
{
|
||||||
|
vector<MTGCardInstance *>::iterator ite;
|
||||||
|
for(ite = hand->cards.begin(); ite != hand->cards.end(); ite++)
|
||||||
|
{
|
||||||
|
WEventZoneChange event(*ite, NULL, hand);
|
||||||
|
receiveEventPlus(&event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiHandOpponent::Render()
|
void GuiHandOpponent::Render()
|
||||||
@@ -92,6 +98,13 @@ GuiHandSelf::GuiHandSelf(GameObserver* observer, MTGHand* hand) :
|
|||||||
backpos.x = SCREEN_WIDTH - 30 * 7 - 14;
|
backpos.x = SCREEN_WIDTH - 30 * 7 - 14;
|
||||||
backpos.UpdateNow();
|
backpos.UpdateNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<MTGCardInstance *>::iterator ite;
|
||||||
|
for(ite = hand->cards.begin(); ite != hand->cards.end(); ite++)
|
||||||
|
{
|
||||||
|
WEventZoneChange event(*ite, NULL, hand);
|
||||||
|
receiveEventPlus(&event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiHandSelf::~GuiHandSelf()
|
GuiHandSelf::~GuiHandSelf()
|
||||||
|
|||||||
@@ -56,27 +56,27 @@ void GuiAvatar::Render()
|
|||||||
float x0 = actX;
|
float x0 = actX;
|
||||||
float y0 = actY;
|
float y0 = actY;
|
||||||
|
|
||||||
if (player->mAvatar.get())
|
if (player->getIcon().get())
|
||||||
{
|
{
|
||||||
if (corner == BOTTOM_RIGHT)
|
if (corner == BOTTOM_RIGHT)
|
||||||
{
|
{
|
||||||
x0 -= player->mAvatar->mWidth * actZ;
|
x0 -= player->getIcon()->mWidth * actZ;
|
||||||
y0 -= player->mAvatar->mHeight * actZ;
|
y0 -= player->getIcon()->mHeight * actZ;
|
||||||
}
|
}
|
||||||
switch (corner)
|
switch (corner)
|
||||||
{
|
{
|
||||||
case TOP_LEFT:
|
case TOP_LEFT:
|
||||||
player->mAvatar->SetHotSpot(0, 0);
|
player->getIcon()->SetHotSpot(0, 0);
|
||||||
break;
|
break;
|
||||||
case BOTTOM_RIGHT:
|
case BOTTOM_RIGHT:
|
||||||
player->mAvatar->SetHotSpot(35, 50);
|
player->getIcon()->SetHotSpot(35, 50);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
player->mAvatar->SetColor(ARGB((int)actA, 255, avatarRed, avatarRed));
|
player->getIcon()->SetColor(ARGB((int)actA, 255, avatarRed, avatarRed));
|
||||||
r->RenderQuad(player->mAvatar.get(), actX, actY, actT, actZ, actZ);
|
r->RenderQuad(player->getIcon().get(), actX, actY, actT, actZ, actZ);
|
||||||
if (mHasFocus)
|
if (mHasFocus)
|
||||||
{
|
{
|
||||||
r->FillRect(x0, x0, player->mAvatar->mWidth * actZ, player->mAvatar->mHeight * actZ, ARGB(abs(128 - wave),255,255,255));
|
r->FillRect(x0, x0, player->getIcon()->mWidth * actZ, player->getIcon()->mHeight * actZ, ARGB(abs(128 - wave),255,255,255));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -498,6 +498,18 @@ MTGCardInstance * MTGGameZone::hasCard(MTGCardInstance * card)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t MTGGameZone::getIndex(MTGCardInstance * card)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < cards.size(); i++)
|
||||||
|
{
|
||||||
|
if(cards[i] == card)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int MTGGameZone::countByType(const char * value)
|
unsigned int MTGGameZone::countByType(const char * value)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@@ -669,7 +681,7 @@ void MTGGameZone::cleanupPhase()
|
|||||||
|
|
||||||
void MTGGameZone::shuffle()
|
void MTGGameZone::shuffle()
|
||||||
{
|
{
|
||||||
std::random_shuffle(cards.begin(), cards.end());
|
std::random_shuffle(cards.begin(), cards.end(), MRand );
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTGGameZone::addCard(MTGCardInstance * card)
|
void MTGGameZone::addCard(MTGCardInstance * card)
|
||||||
@@ -999,16 +1011,15 @@ ostream& MTGInPlay::toString(ostream& out) const
|
|||||||
}
|
}
|
||||||
ostream& operator<<(ostream& out, const MTGGameZone& z)
|
ostream& operator<<(ostream& out, const MTGGameZone& z)
|
||||||
{
|
{
|
||||||
return z.toString(out);
|
for (int i = 0; i < z.nb_cards; i++)
|
||||||
}
|
{
|
||||||
|
out << z.cards[i]->getMTGId();
|
||||||
ostream& operator<<(ostream& out, const MTGPlayerCards& z)
|
if(i < z.nb_cards - 1)
|
||||||
{
|
out << ",";
|
||||||
out << z.library->nb_cards << " ";
|
}
|
||||||
for (int i = 0; i < z.library->nb_cards; i++)
|
|
||||||
out << z.library->cards[i]->getMTGId() << " ";
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
|
// return z.toString(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MTGGameZone::parseLine(const string& ss)
|
bool MTGGameZone::parseLine(const string& ss)
|
||||||
@@ -1022,6 +1033,7 @@ bool MTGGameZone::parseLine(const string& ss)
|
|||||||
}
|
}
|
||||||
cards.clear();
|
cards.clear();
|
||||||
cardsMap.clear();
|
cardsMap.clear();
|
||||||
|
nb_cards = 0;
|
||||||
|
|
||||||
while(s.size())
|
while(s.size())
|
||||||
{
|
{
|
||||||
@@ -1072,6 +1084,28 @@ bool MTGGameZone::parseLine(const string& ss)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ostream& operator<<(ostream& out, const MTGPlayerCards& z)
|
||||||
|
{
|
||||||
|
if(z.library->cards.size()) {
|
||||||
|
out << "library=";
|
||||||
|
out << *(z.library) << endl;
|
||||||
|
}
|
||||||
|
if(z.battlefield->cards.size()) {
|
||||||
|
out << "inplay=";
|
||||||
|
out << *(z.battlefield) << endl;
|
||||||
|
}
|
||||||
|
if(z.graveyard->cards.size()) {
|
||||||
|
out << "graveyard=";
|
||||||
|
out << *(z.graveyard) << endl;
|
||||||
|
}
|
||||||
|
if(z.hand->cards.size()) {
|
||||||
|
out << "hand=";
|
||||||
|
out << *(z.hand) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
bool MTGPlayerCards::parseLine(const string& s)
|
bool MTGPlayerCards::parseLine(const string& s)
|
||||||
{
|
{
|
||||||
size_t limiter = s.find("=");
|
size_t limiter = s.find("=");
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck * deck) :
|
Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck * deck) :
|
||||||
Damageable(observer, 20), mAvatarName("")
|
Damageable(observer, 20), mAvatarName(""), offerInterruptOnPhase(Constants::MTG_PHASE_DRAW)
|
||||||
{
|
{
|
||||||
if(deck == NULL && file != "testsuite" && file != "remote" && file != "")
|
if(deck == NULL && file != "testsuite" && file != "remote" && file != "")
|
||||||
deck = NEW MTGDeck(file.c_str(), MTGCollection());
|
deck = NEW MTGDeck(file.c_str(), MTGCollection());
|
||||||
@@ -18,7 +18,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
|
|||||||
game = NULL;
|
game = NULL;
|
||||||
deckFile = file;
|
deckFile = file;
|
||||||
deckFileSmall = fileSmall;
|
deckFileSmall = fileSmall;
|
||||||
handsize = 0;
|
handsize = 0;
|
||||||
manaPool = NEW ManaPool(this);
|
manaPool = NEW ManaPool(this);
|
||||||
nomaxhandsize = false;
|
nomaxhandsize = false;
|
||||||
poisonCount = 0;
|
poisonCount = 0;
|
||||||
@@ -34,6 +34,11 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
|
|||||||
game->setOwner(this);
|
game->setOwner(this);
|
||||||
deckName = deck->meta_name;
|
deckName = deck->meta_name;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
game = new MTGPlayerCards();
|
||||||
|
game->setOwner(this);
|
||||||
|
}
|
||||||
mDeck = deck;
|
mDeck = deck;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +64,7 @@ Player::~Player()
|
|||||||
SAFE_DELETE(mDeck);
|
SAFE_DELETE(mDeck);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::loadAvatar(string file)
|
bool Player::loadAvatar(string file, string resName)
|
||||||
{
|
{
|
||||||
if (mAvatarTex)
|
if (mAvatarTex)
|
||||||
{
|
{
|
||||||
@@ -67,8 +72,12 @@ void Player::loadAvatar(string file)
|
|||||||
mAvatarTex = NULL;
|
mAvatarTex = NULL;
|
||||||
}
|
}
|
||||||
mAvatarTex = WResourceManager::Instance()->RetrieveTexture(file, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR);
|
mAvatarTex = WResourceManager::Instance()->RetrieveTexture(file, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR);
|
||||||
if (mAvatarTex)
|
if (mAvatarTex) {
|
||||||
mAvatar = WResourceManager::Instance()->RetrieveQuad(file, 0, 0, 35, 50, "playerAvatar", RETRIEVE_NORMAL, TEXTURE_SUB_AVATAR);
|
mAvatar = WResourceManager::Instance()->RetrieveQuad(file, 0, 0, 35, 50, resName, RETRIEVE_NORMAL, TEXTURE_SUB_AVATAR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string Player::getDisplayName() const
|
const string Player::getDisplayName() const
|
||||||
@@ -93,6 +102,9 @@ int Player::getId()
|
|||||||
|
|
||||||
JQuadPtr Player::getIcon()
|
JQuadPtr Player::getIcon()
|
||||||
{
|
{
|
||||||
|
if(!mAvatarTex)
|
||||||
|
loadAvatar(mAvatarName);
|
||||||
|
|
||||||
return mAvatar;
|
return mAvatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +117,7 @@ Player * Player::opponent()
|
|||||||
HumanPlayer::HumanPlayer(GameObserver *observer, string file, string fileSmall, MTGDeck * deck) :
|
HumanPlayer::HumanPlayer(GameObserver *observer, string file, string fileSmall, MTGDeck * deck) :
|
||||||
Player(observer, file, fileSmall, deck)
|
Player(observer, file, fileSmall, deck)
|
||||||
{
|
{
|
||||||
loadAvatar("avatar.jpg");
|
mAvatarName = "avatar.jpg";
|
||||||
playMode = MODE_HUMAN;
|
playMode = MODE_HUMAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,6 +243,11 @@ bool Player::parseLine(const string& s)
|
|||||||
phaseRing = s.substr(limiter + 1);
|
phaseRing = s.substr(limiter + 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (areaS.compare("deckfile") == 0)
|
||||||
|
{
|
||||||
|
deckFile = s.substr(limiter + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (areaS.compare("offerinterruptonphase") == 0)
|
else if (areaS.compare("offerinterruptonphase") == 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Constants::NB_MTG_PHASES; i++)
|
for (int i = 0; i < Constants::NB_MTG_PHASES; i++)
|
||||||
@@ -259,5 +276,22 @@ bool Player::parseLine(const string& s)
|
|||||||
|
|
||||||
ostream& operator<<(ostream& out, const Player& p)
|
ostream& operator<<(ostream& out, const Player& p)
|
||||||
{
|
{
|
||||||
return out << *(p.game);
|
out << *(Damageable*)&p;
|
||||||
|
string manapoolstring = p.manaPool->toString();
|
||||||
|
if(manapoolstring != "")
|
||||||
|
out << "manapool=" << manapoolstring << endl;
|
||||||
|
if(p.mAvatarName != "")
|
||||||
|
out << "avatar=" << p.mAvatarName << endl;
|
||||||
|
if(p.phaseRing != "")
|
||||||
|
out << "customphasering=" << p.phaseRing << endl;
|
||||||
|
out << "offerinterruptonphase=" << Constants::MTGPhaseCodeNames[p.offerInterruptOnPhase] << endl;
|
||||||
|
if(p.deckFile != "")
|
||||||
|
out << "deckfile=" << p.deckFile << endl;
|
||||||
|
|
||||||
|
if(p.game)
|
||||||
|
{
|
||||||
|
out << *(p.game);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#include "Rules.h"
|
|
||||||
#include "MTGDefinitions.h"
|
#include "MTGDefinitions.h"
|
||||||
|
#include "Rules.h"
|
||||||
#include "ManaCost.h"
|
#include "ManaCost.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "AIMomirPlayer.h"
|
#include "AIMomirPlayer.h"
|
||||||
@@ -303,6 +303,8 @@ Player * Rules::initPlayer(GameObserver *g, int playerId)
|
|||||||
return loadPlayerRandom(g, isAI, GAME_TYPE_RANDOM1);
|
return loadPlayerRandom(g, isAI, GAME_TYPE_RANDOM1);
|
||||||
case GAME_TYPE_RANDOM2:
|
case GAME_TYPE_RANDOM2:
|
||||||
return loadPlayerRandom(g, isAI, GAME_TYPE_RANDOM2);
|
return loadPlayerRandom(g, isAI, GAME_TYPE_RANDOM2);
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO p may still be NULL, what do we do to handle this? Above switch has no default case to handle the case where p is NULL
|
//TODO p may still be NULL, what do we do to handle this? Above switch has no default case to handle the case where p is NULL
|
||||||
@@ -385,7 +387,7 @@ void Rules::initGame(GameObserver *g)
|
|||||||
p->preventable = initState.playerData[i].player->preventable;
|
p->preventable = initState.playerData[i].player->preventable;
|
||||||
if (initState.playerData[i].player->mAvatarName.size())
|
if (initState.playerData[i].player->mAvatarName.size())
|
||||||
{
|
{
|
||||||
p->loadAvatar(initState.playerData[i].player->mAvatarName);
|
p->mAvatarName = initState.playerData[i].player->mAvatarName;
|
||||||
}
|
}
|
||||||
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay };
|
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay };
|
||||||
MTGGameZone * loadedPlayerZones[] = { initState.playerData[i].player->game->graveyard,
|
MTGGameZone * loadedPlayerZones[] = { initState.playerData[i].player->game->graveyard,
|
||||||
@@ -590,7 +592,7 @@ int Rules::load(string _filename)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Rules::strToGameMode(string s)
|
GameType Rules::strToGameMode(string s)
|
||||||
{
|
{
|
||||||
if (s.compare("momir") == 0) return GAME_TYPE_MOMIR;
|
if (s.compare("momir") == 0) return GAME_TYPE_MOMIR;
|
||||||
if (s.compare("random1") == 0) return GAME_TYPE_RANDOM1;
|
if (s.compare("random1") == 0) return GAME_TYPE_RANDOM1;
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ void StoryDuel::init()
|
|||||||
game = new GameObserver(players);
|
game = new GameObserver(players);
|
||||||
|
|
||||||
rules->gamemode = GAME_TYPE_STORY;
|
rules->gamemode = GAME_TYPE_STORY;
|
||||||
game->startGame(rules);
|
game->startGame(GAME_TYPE_STORY, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
StoryDuel::StoryDuel(TiXmlElement* root, StoryFlow * mParent) :
|
StoryDuel::StoryDuel(TiXmlElement* root, StoryFlow * mParent) :
|
||||||
|
|||||||
+42
-11
@@ -19,14 +19,35 @@ namespace wagic
|
|||||||
}
|
}
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
using std::queue;
|
||||||
|
|
||||||
int randValuesCursor = -1;
|
int randValuesCursor = -1;
|
||||||
vector<int> randValues;
|
vector<int> randValues;
|
||||||
|
|
||||||
int loadRandValues(string s)
|
queue<int> loadedRandomValues;
|
||||||
|
queue<int> usedRandomValues;
|
||||||
|
|
||||||
|
ostream& saveRandValues(ostream& out)
|
||||||
{
|
{
|
||||||
randValues.clear();
|
while(usedRandomValues.size())
|
||||||
randValuesCursor = -1;
|
{
|
||||||
|
out << usedRandomValues.front();
|
||||||
|
if(usedRandomValues.size() >= 1)
|
||||||
|
out << ",";
|
||||||
|
|
||||||
|
usedRandomValues.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadRandValues(string s)
|
||||||
|
{
|
||||||
|
while(loadedRandomValues.size())
|
||||||
|
loadedRandomValues.pop();
|
||||||
|
while(usedRandomValues.size())
|
||||||
|
usedRandomValues.pop();
|
||||||
|
|
||||||
while (s.size())
|
while (s.size())
|
||||||
{
|
{
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
@@ -41,18 +62,28 @@ int loadRandValues(string s)
|
|||||||
value = atoi(s.c_str());
|
value = atoi(s.c_str());
|
||||||
s = "";
|
s = "";
|
||||||
}
|
}
|
||||||
if (value) randValues.push_back(value);
|
if (value) loadedRandomValues.push(value);
|
||||||
}
|
}
|
||||||
if (randValues.size()) randValuesCursor = 0;
|
}
|
||||||
return 1;
|
|
||||||
|
ptrdiff_t MRand (ptrdiff_t i)
|
||||||
|
{
|
||||||
|
return WRand()%i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WRand()
|
int WRand()
|
||||||
{
|
{
|
||||||
if (randValuesCursor == -1) return rand();
|
int result;
|
||||||
int result = randValues[randValuesCursor];
|
if (!loadedRandomValues.size())
|
||||||
randValuesCursor++;
|
{
|
||||||
if ((size_t) randValuesCursor >= randValues.size()) randValuesCursor = 0;
|
result = rand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = loadedRandomValues.front();
|
||||||
|
loadedRandomValues.pop();
|
||||||
|
}
|
||||||
|
usedRandomValues.push(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,4 +410,4 @@ std::string ensureFolder(const std::string & folderName)
|
|||||||
result.append("/");
|
result.append("/");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user