- 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
|
||||
};
|
||||
|
||||
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 TransitionBase;
|
||||
|
||||
@@ -73,7 +57,7 @@ private:
|
||||
GameState* mGameStates[GAME_STATE_MAX];
|
||||
public:
|
||||
|
||||
int gameType;
|
||||
GameType gameType;
|
||||
Rules * rules;
|
||||
CardEffect *effect;
|
||||
#ifdef NETWORK_SUPPORT
|
||||
|
||||
@@ -26,10 +26,21 @@ class GameObserver{
|
||||
protected:
|
||||
MTGCardInstance * cardWaitingForTargets;
|
||||
queue<WEvent *> eventsQueue;
|
||||
list<string> actionsList;
|
||||
|
||||
int untap(MTGCardInstance * card);
|
||||
bool WaitForExtraPayment(MTGCardInstance* card);
|
||||
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:
|
||||
int currentPlayerId;
|
||||
@@ -49,6 +60,7 @@ class GameObserver{
|
||||
vector<Player *> players; //created outside
|
||||
time_t startedAt;
|
||||
Rules * mRules;
|
||||
GameType mGameType;
|
||||
|
||||
TargetChooser * getCurrentTargetChooser();
|
||||
void stackObjectClicked(Interruptible * action);
|
||||
@@ -74,10 +86,9 @@ class GameObserver{
|
||||
void gameStateBasedEffects();
|
||||
void enchantmentStatus();
|
||||
void Affinity();
|
||||
void eventOccured();
|
||||
void addObserver(MTGAbility * observer);
|
||||
bool removeObserver(ActionElement * observer);
|
||||
void startGame(Rules * rules);
|
||||
void startGame(GameType, Rules * rules);
|
||||
void untapPhase();
|
||||
MTGCardInstance * isCardWaiting(){ return cardWaitingForTargets; }
|
||||
int isInPlay(MTGCardInstance * card);
|
||||
@@ -90,6 +101,14 @@ class GameObserver{
|
||||
|
||||
int receiveEvent(WEvent * event);
|
||||
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
|
||||
|
||||
@@ -78,9 +78,10 @@ public:
|
||||
MENUITEM_MAIN_MENU = -13,
|
||||
MENUITEM_EVIL_TWIN = kEvilTwinMenuID,
|
||||
MENUITEM_MULLIGAN = -15,
|
||||
MENUITEM_UNDO = -16,
|
||||
#ifdef NETWORK_SUPPORT
|
||||
MENUITEM_REMOTE_CLIENT = -16,
|
||||
MENUITEM_REMOTE_SERVER = -17,
|
||||
MENUITEM_REMOTE_CLIENT = -17,
|
||||
MENUITEM_REMOTE_SERVER = -18,
|
||||
#endif
|
||||
MENUITEM_MORE_INFO = kInfoMenuID
|
||||
};
|
||||
|
||||
@@ -210,9 +210,8 @@ public:
|
||||
|
||||
static MTGCardInstance ExtraRules[2];
|
||||
|
||||
bool parseLine(const string& ss);
|
||||
};
|
||||
|
||||
ostream& operator<<(ostream&, const MTGCardInstance&);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,23 @@ const float DEFAULT_TEXT_FONT_SCALE = 1.0f;
|
||||
|
||||
#include <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
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -83,6 +83,7 @@ class MTGGameZone {
|
||||
void debugPrint();
|
||||
MTGCardInstance * removeCard(MTGCardInstance * card, int createCopy = 1);
|
||||
MTGCardInstance * hasCard(MTGCardInstance * card);
|
||||
size_t getIndex(MTGCardInstance * card);
|
||||
void cleanupPhase();
|
||||
void beforeBeginPhase();
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@ class Player: public Damageable
|
||||
{
|
||||
protected:
|
||||
ManaPool * manaPool;
|
||||
JTexture * mAvatarTex;
|
||||
JQuadPtr mAvatar;
|
||||
bool loadAvatar(string file, string resName = "playerAvatar");
|
||||
|
||||
|
||||
public:
|
||||
enum ENUM_PLAY_MODE
|
||||
@@ -25,8 +29,6 @@ public:
|
||||
};
|
||||
|
||||
string mAvatarName;
|
||||
JTexture * mAvatarTex;
|
||||
JQuadPtr mAvatar;
|
||||
int playMode;
|
||||
bool nomaxhandsize;
|
||||
MTGPlayerCards * game;
|
||||
@@ -35,7 +37,7 @@ public:
|
||||
string deckFileSmall;
|
||||
string deckName;
|
||||
string phaseRing;
|
||||
int offerInterruptOnPhase;
|
||||
int offerInterruptOnPhase;
|
||||
Player(GameObserver *observer, string deckFile, string deckFileSmall, MTGDeck * deck = NULL);
|
||||
virtual ~Player();
|
||||
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.
|
||||
*/
|
||||
std::string GetCurrentDeckStatsFile();
|
||||
bool parseLine(const string& s);
|
||||
friend ostream& operator<<(ostream&, const Player&);
|
||||
};
|
||||
|
||||
class HumanPlayer: public Player
|
||||
{
|
||||
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
|
||||
|
||||
@@ -43,7 +43,7 @@ protected:
|
||||
Player * loadPlayerRandom(GameObserver* observer, int isAI, int mode);
|
||||
Player * initPlayer(GameObserver *observer, int playerId);
|
||||
MTGDeck * buildDeck(int playerId);
|
||||
int strToGameMode(string s);
|
||||
GameType strToGameMode(string s);
|
||||
bool postUpdateInitDone;
|
||||
public:
|
||||
enum
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
string bg;
|
||||
string filename;
|
||||
int gamemode;
|
||||
GameType gamemode;
|
||||
bool hidden;
|
||||
string displayName;
|
||||
int unlockOption;
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
|
||||
public:
|
||||
int startTime, endTime;
|
||||
int gameType;
|
||||
GameType gameType;
|
||||
unsigned int seed;
|
||||
int nbFailed, nbTests, nbAIFailed, nbAITests;
|
||||
TestSuite(const char * filename);
|
||||
|
||||
@@ -63,9 +63,11 @@ std::string wordWrap(const std::string& s, float width, int fontId);
|
||||
//basic hash function
|
||||
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 WRand();
|
||||
ptrdiff_t MRand (ptrdiff_t i);
|
||||
|
||||
#ifdef LINUX
|
||||
void dumpStack();
|
||||
|
||||
@@ -97,7 +97,7 @@ int AIAction::clickMultiAct(vector<Targetable*>& actionTargets)
|
||||
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.
|
||||
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);
|
||||
}
|
||||
}
|
||||
std::random_shuffle(potentialTargets.begin(), potentialTargets.end());
|
||||
std::random_shuffle(potentialTargets.begin(), potentialTargets.end(), MRand);
|
||||
if(potentialTargets.size())
|
||||
clickstream.push(NEW AIAction(this, NULL,tc->source,potentialTargets));
|
||||
while(clickstream.size())
|
||||
@@ -257,7 +257,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(GameObserver *observer, MTGAllCards *
|
||||
{
|
||||
bool isOpponentAI = opponent->isAI() == 1;
|
||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI);
|
||||
if ( meta->getVictoryPercentage() >= 65)
|
||||
if ( meta && meta->getVictoryPercentage() >= 65)
|
||||
deckSetting = HARD;
|
||||
}
|
||||
|
||||
|
||||
@@ -1410,7 +1410,7 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
|
||||
if(tc->belongsToAbility.size())
|
||||
{
|
||||
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);
|
||||
delete withoutGuessing;
|
||||
}
|
||||
@@ -1458,7 +1458,7 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
|
||||
if(tc->maxtargets != 1 && tc->belongsToAbility.size())
|
||||
{
|
||||
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);
|
||||
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 (!mAvatarTex)
|
||||
if(avatarFile != "")
|
||||
{
|
||||
avatarFile = "baka.jpg";
|
||||
mAvatarTex = WResourceManager::Instance()->RetrieveTexture(avatarFile, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR);
|
||||
if(!loadAvatar(avatarFile, "bakaAvatar"))
|
||||
{
|
||||
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")
|
||||
mAvatar->SetHFlip(true);
|
||||
|
||||
|
||||
@@ -589,6 +589,7 @@ int ActionStack::setIsInterrupting(Player * player)
|
||||
int playerId = (player == observer->players[1]) ? 1 : 0;
|
||||
interruptDecision[playerId] = -1;
|
||||
observer->isInterrupting = player;
|
||||
observer->logAction(player, "yes");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -960,6 +961,7 @@ void ActionStack::cancelInterruptOffer(int cancelMode)
|
||||
askIfWishesToInterrupt = NULL;
|
||||
observer->isInterrupting = NULL;
|
||||
timer = -1;
|
||||
observer->logAction(playerId, "no");
|
||||
}
|
||||
|
||||
void ActionStack::endOfInterruption()
|
||||
@@ -967,6 +969,7 @@ void ActionStack::endOfInterruption()
|
||||
int playerId = (observer->isInterrupting == observer->players[1]) ? 1 : 0;
|
||||
interruptDecision[playerId] = 0;
|
||||
observer->isInterrupting = NULL;
|
||||
observer->logAction(playerId, "endinterruption");
|
||||
}
|
||||
|
||||
bool ActionStack::CheckUserInput(JButton key)
|
||||
|
||||
@@ -2360,6 +2360,7 @@ int MenuAbility::reactToChoiceClick(Targetable * object,int choice,int control)
|
||||
game->mLayers->stackLayer()->cancelInterruptOffer();
|
||||
this->forceDestroy = 1;
|
||||
removeMenu = true;
|
||||
game->logAction(source->controller(), "choice " + choice);
|
||||
return reactToTargetClick(object);
|
||||
}
|
||||
|
||||
|
||||
@@ -661,7 +661,6 @@ void CardGui::AlternateRender(MTGCard * card, const Pos& pos)
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -994,7 +993,6 @@ void CardGui::TinyCropRender(MTGCard * card, const Pos& pos, JQuad * quad)
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
@@ -305,6 +305,10 @@ ostream& DamageStack::toString(ostream& out) const
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,8 +182,13 @@ DeckManager* DeckManager::GetInstance()
|
||||
// p2 is the opponent
|
||||
int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player)
|
||||
{
|
||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename(player->deckFile, (player->isAI() == 1) );
|
||||
return meta->getDifficulty();
|
||||
if(player->deckFile != "")
|
||||
{
|
||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename(player->deckFile, (player->isAI() == 1) );
|
||||
return meta->getDifficulty();
|
||||
}
|
||||
else
|
||||
return EASY;
|
||||
}
|
||||
|
||||
DeckManager::~DeckManager()
|
||||
|
||||
@@ -79,8 +79,9 @@ void DuelLayers::Update(float dt, Player * currentPlayer)
|
||||
for (int i = 0; i < nbitems; ++i)
|
||||
objects[i]->Update(dt);
|
||||
int isAI = currentPlayer->isAI();
|
||||
if (isAI)
|
||||
if (isAI && !currentPlayer->getObserver()->isLoading())
|
||||
currentPlayer->Act(dt);
|
||||
|
||||
CheckUserInput(isAI);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,14 +10,12 @@
|
||||
#include <JRenderer.h>
|
||||
#include "MTGGamePhase.h"
|
||||
#include "GuiPhaseBar.h"
|
||||
|
||||
GameObserver::GameObserver()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
#include "AIPlayerBaka.h"
|
||||
#include "MTGRules.h"
|
||||
|
||||
void GameObserver::initialize()
|
||||
{
|
||||
mGameType = GAME_TYPE_CLASSIC;
|
||||
currentPlayer = NULL;
|
||||
currentActionPlayer = NULL;
|
||||
isInterrupting = NULL;
|
||||
@@ -32,6 +30,61 @@ void GameObserver::initialize()
|
||||
combatStep = BLOCKERS;
|
||||
mRules = NULL;
|
||||
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)
|
||||
@@ -43,12 +96,6 @@ void GameObserver::setPlayers(vector<Player *> _players)
|
||||
}
|
||||
}
|
||||
|
||||
GameObserver::GameObserver(vector<Player *> _players)
|
||||
{
|
||||
initialize();
|
||||
setPlayers(_players);
|
||||
}
|
||||
|
||||
int GameObserver::getCurrentGamePhase()
|
||||
{
|
||||
return currentGamePhase;
|
||||
@@ -231,7 +278,7 @@ void GameObserver::userRequestNextGamePhase()
|
||||
{
|
||||
nextGamePhase();
|
||||
}
|
||||
|
||||
logAction(currentPlayer, "next");
|
||||
}
|
||||
|
||||
int GameObserver::forceShuffleLibraries()
|
||||
@@ -250,8 +297,9 @@ int GameObserver::forceShuffleLibraries()
|
||||
return result;
|
||||
}
|
||||
|
||||
void GameObserver::startGame(Rules * rules)
|
||||
void GameObserver::startGame(GameType gtype, Rules * rules)
|
||||
{
|
||||
mGameType = gtype;
|
||||
turn = 0;
|
||||
mRules = rules;
|
||||
if (rules)
|
||||
@@ -266,6 +314,11 @@ void GameObserver::startGame(Rules * rules)
|
||||
currentPlayer = players[0];
|
||||
currentActionPlayer = currentPlayer;
|
||||
phaseRing = NEW PhaseRing(this);
|
||||
|
||||
stringstream stream;
|
||||
stream << *this;
|
||||
startupGameSerialized = stream.str();
|
||||
|
||||
if (rules)
|
||||
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)
|
||||
@@ -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)
|
||||
{
|
||||
Player * player = currentPlayer;
|
||||
@@ -890,8 +948,12 @@ bool GameObserver::WaitForExtraPayment(MTGCardInstance * card)
|
||||
int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
||||
{
|
||||
Player * clickedPlayer = NULL;
|
||||
if (!card)
|
||||
if (!card) {
|
||||
clickedPlayer = ((Player *) object);
|
||||
logAction(clickedPlayer);
|
||||
} else {
|
||||
logAction(card);
|
||||
}
|
||||
if (targetChooser)
|
||||
{
|
||||
int result;
|
||||
@@ -928,8 +990,8 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (WaitForExtraPayment(card))
|
||||
return 1;
|
||||
if (WaitForExtraPayment(card))
|
||||
return 1;
|
||||
|
||||
int reaction = 0;
|
||||
|
||||
@@ -959,18 +1021,18 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
||||
}
|
||||
|
||||
reaction = mLayers->actionLayer()->isReactingToClick(card);
|
||||
if (reaction == -1)
|
||||
return mLayers->actionLayer()->reactToClick(card);
|
||||
if (reaction == -1)
|
||||
return mLayers->actionLayer()->reactToClick(card);
|
||||
}
|
||||
else
|
||||
{//this handles abilities on a menu...not just when card is being played
|
||||
reaction = mLayers->actionLayer()->isReactingToTargetClick(object);
|
||||
if (reaction == -1)
|
||||
return mLayers->actionLayer()->reactToTargetClick(object);
|
||||
if (reaction == -1)
|
||||
return mLayers->actionLayer()->reactToTargetClick(object);
|
||||
}
|
||||
|
||||
if (!card)
|
||||
return 0;
|
||||
if (!card)
|
||||
return 0;
|
||||
|
||||
//Current player's hand
|
||||
if (currentPlayer->game->hand->hasCard(card) && currentGamePhase == Constants::MTG_PHASE_CLEANUP
|
||||
@@ -998,7 +1060,6 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int GameObserver::untap(MTGCardInstance * card)
|
||||
@@ -1118,3 +1179,247 @@ int GameObserver::targetListIsSet(MTGCardInstance * card)
|
||||
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 "DeckMetaData.h"
|
||||
#include "MTGRules.h"
|
||||
#include "Credits.h"
|
||||
#include "Translate.h"
|
||||
#include "Rules.h"
|
||||
@@ -267,11 +266,7 @@ void GameStateDuel::loadTestSuitePlayers()
|
||||
game->setPlayers(mPlayers);
|
||||
mParent->gameType = testSuite->gameType;
|
||||
|
||||
game->startGame(mParent->rules);
|
||||
if (mParent->gameType == GAME_TYPE_MOMIR)
|
||||
{
|
||||
game->addObserver(NEW MTGMomirRule(game, -1, MTGCollection()));
|
||||
}
|
||||
game->startGame(mParent->gameType, mParent->rules);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -447,19 +442,7 @@ void GameStateDuel::Update(float dt)
|
||||
if (!game)
|
||||
{
|
||||
game = new GameObserver(mPlayers);
|
||||
game->startGame(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));
|
||||
}
|
||||
game->startGame(mParent->gameType, mParent->rules);
|
||||
|
||||
//start of in game music code
|
||||
musictrack = "";
|
||||
@@ -539,6 +522,7 @@ void GameStateDuel::Update(float dt)
|
||||
}
|
||||
//END almosthumane - mulligan
|
||||
menu->Add(MENUITEM_MAIN_MENU, "Back to main menu");
|
||||
menu->Add(MENUITEM_UNDO, "Undo");
|
||||
menu->Add(MENUITEM_CANCEL, "Cancel");
|
||||
}
|
||||
setGamePhase(DUEL_STATE_MENU);
|
||||
@@ -922,10 +906,14 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
|
||||
menu->Close();
|
||||
setGamePhase(DUEL_STATE_CANCEL);
|
||||
break;
|
||||
|
||||
//END almosthumane - mulligan
|
||||
case MENUITEM_UNDO:
|
||||
{
|
||||
game->undo();
|
||||
menu->Close();
|
||||
setGamePhase(DUEL_STATE_CANCEL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -389,8 +389,8 @@ void GuiCombat::Render()
|
||||
damage = 0;
|
||||
if (activeAtk->card->has(Constants::TRAMPLE))
|
||||
{
|
||||
observer->opponent()->mAvatar->SetHotSpot(18, 25);
|
||||
enemy_avatar.Render(observer->opponent()->mAvatar.get());
|
||||
observer->opponent()->getIcon()->SetHotSpot(18, 25);
|
||||
enemy_avatar.Render(observer->opponent()->getIcon().get());
|
||||
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
||||
mFont->SetColor(ARGB(255, 255, 64, 0));
|
||||
{
|
||||
|
||||
@@ -64,6 +64,12 @@ bool GuiHand::isInHand(CardView* card)
|
||||
GuiHandOpponent::GuiHandOpponent(GameObserver* observer, MTGHand* 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()
|
||||
@@ -92,6 +98,13 @@ GuiHandSelf::GuiHandSelf(GameObserver* observer, MTGHand* hand) :
|
||||
backpos.x = SCREEN_WIDTH - 30 * 7 - 14;
|
||||
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()
|
||||
|
||||
@@ -56,27 +56,27 @@ void GuiAvatar::Render()
|
||||
float x0 = actX;
|
||||
float y0 = actY;
|
||||
|
||||
if (player->mAvatar.get())
|
||||
if (player->getIcon().get())
|
||||
{
|
||||
if (corner == BOTTOM_RIGHT)
|
||||
{
|
||||
x0 -= player->mAvatar->mWidth * actZ;
|
||||
y0 -= player->mAvatar->mHeight * actZ;
|
||||
x0 -= player->getIcon()->mWidth * actZ;
|
||||
y0 -= player->getIcon()->mHeight * actZ;
|
||||
}
|
||||
switch (corner)
|
||||
{
|
||||
case TOP_LEFT:
|
||||
player->mAvatar->SetHotSpot(0, 0);
|
||||
player->getIcon()->SetHotSpot(0, 0);
|
||||
break;
|
||||
case BOTTOM_RIGHT:
|
||||
player->mAvatar->SetHotSpot(35, 50);
|
||||
player->getIcon()->SetHotSpot(35, 50);
|
||||
break;
|
||||
}
|
||||
player->mAvatar->SetColor(ARGB((int)actA, 255, avatarRed, avatarRed));
|
||||
r->RenderQuad(player->mAvatar.get(), actX, actY, actT, actZ, actZ);
|
||||
player->getIcon()->SetColor(ARGB((int)actA, 255, avatarRed, avatarRed));
|
||||
r->RenderQuad(player->getIcon().get(), actX, actY, actT, actZ, actZ);
|
||||
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)
|
||||
{
|
||||
int result = 0;
|
||||
@@ -669,7 +681,7 @@ void MTGGameZone::cleanupPhase()
|
||||
|
||||
void MTGGameZone::shuffle()
|
||||
{
|
||||
std::random_shuffle(cards.begin(), cards.end());
|
||||
std::random_shuffle(cards.begin(), cards.end(), MRand );
|
||||
}
|
||||
|
||||
void MTGGameZone::addCard(MTGCardInstance * card)
|
||||
@@ -999,16 +1011,15 @@ ostream& MTGInPlay::toString(ostream& out) const
|
||||
}
|
||||
ostream& operator<<(ostream& out, const MTGGameZone& z)
|
||||
{
|
||||
return z.toString(out);
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream& out, const MTGPlayerCards& z)
|
||||
{
|
||||
out << z.library->nb_cards << " ";
|
||||
for (int i = 0; i < z.library->nb_cards; i++)
|
||||
out << z.library->cards[i]->getMTGId() << " ";
|
||||
|
||||
for (int i = 0; i < z.nb_cards; i++)
|
||||
{
|
||||
out << z.cards[i]->getMTGId();
|
||||
if(i < z.nb_cards - 1)
|
||||
out << ",";
|
||||
}
|
||||
return out;
|
||||
|
||||
// return z.toString(out);
|
||||
}
|
||||
|
||||
bool MTGGameZone::parseLine(const string& ss)
|
||||
@@ -1022,6 +1033,7 @@ bool MTGGameZone::parseLine(const string& ss)
|
||||
}
|
||||
cards.clear();
|
||||
cardsMap.clear();
|
||||
nb_cards = 0;
|
||||
|
||||
while(s.size())
|
||||
{
|
||||
@@ -1072,6 +1084,28 @@ bool MTGGameZone::parseLine(const string& ss)
|
||||
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)
|
||||
{
|
||||
size_t limiter = s.find("=");
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#endif
|
||||
|
||||
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 != "")
|
||||
deck = NEW MTGDeck(file.c_str(), MTGCollection());
|
||||
@@ -18,7 +18,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
|
||||
game = NULL;
|
||||
deckFile = file;
|
||||
deckFileSmall = fileSmall;
|
||||
handsize = 0;
|
||||
handsize = 0;
|
||||
manaPool = NEW ManaPool(this);
|
||||
nomaxhandsize = false;
|
||||
poisonCount = 0;
|
||||
@@ -34,6 +34,11 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
|
||||
game->setOwner(this);
|
||||
deckName = deck->meta_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
game = new MTGPlayerCards();
|
||||
game->setOwner(this);
|
||||
}
|
||||
mDeck = deck;
|
||||
}
|
||||
|
||||
@@ -59,7 +64,7 @@ Player::~Player()
|
||||
SAFE_DELETE(mDeck);
|
||||
}
|
||||
|
||||
void Player::loadAvatar(string file)
|
||||
bool Player::loadAvatar(string file, string resName)
|
||||
{
|
||||
if (mAvatarTex)
|
||||
{
|
||||
@@ -67,8 +72,12 @@ void Player::loadAvatar(string file)
|
||||
mAvatarTex = NULL;
|
||||
}
|
||||
mAvatarTex = WResourceManager::Instance()->RetrieveTexture(file, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR);
|
||||
if (mAvatarTex)
|
||||
mAvatar = WResourceManager::Instance()->RetrieveQuad(file, 0, 0, 35, 50, "playerAvatar", RETRIEVE_NORMAL, TEXTURE_SUB_AVATAR);
|
||||
if (mAvatarTex) {
|
||||
mAvatar = WResourceManager::Instance()->RetrieveQuad(file, 0, 0, 35, 50, resName, RETRIEVE_NORMAL, TEXTURE_SUB_AVATAR);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const string Player::getDisplayName() const
|
||||
@@ -93,6 +102,9 @@ int Player::getId()
|
||||
|
||||
JQuadPtr Player::getIcon()
|
||||
{
|
||||
if(!mAvatarTex)
|
||||
loadAvatar(mAvatarName);
|
||||
|
||||
return mAvatar;
|
||||
}
|
||||
|
||||
@@ -105,7 +117,7 @@ Player * Player::opponent()
|
||||
HumanPlayer::HumanPlayer(GameObserver *observer, string file, string fileSmall, MTGDeck * deck) :
|
||||
Player(observer, file, fileSmall, deck)
|
||||
{
|
||||
loadAvatar("avatar.jpg");
|
||||
mAvatarName = "avatar.jpg";
|
||||
playMode = MODE_HUMAN;
|
||||
}
|
||||
|
||||
@@ -231,6 +243,11 @@ bool Player::parseLine(const string& s)
|
||||
phaseRing = s.substr(limiter + 1);
|
||||
return true;
|
||||
}
|
||||
else if (areaS.compare("deckfile") == 0)
|
||||
{
|
||||
deckFile = s.substr(limiter + 1);
|
||||
return true;
|
||||
}
|
||||
else if (areaS.compare("offerinterruptonphase") == 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 "Rules.h"
|
||||
#include "MTGDefinitions.h"
|
||||
#include "Rules.h"
|
||||
#include "ManaCost.h"
|
||||
#include "Player.h"
|
||||
#include "AIMomirPlayer.h"
|
||||
@@ -303,6 +303,8 @@ Player * Rules::initPlayer(GameObserver *g, int playerId)
|
||||
return loadPlayerRandom(g, isAI, GAME_TYPE_RANDOM1);
|
||||
case 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
|
||||
@@ -385,7 +387,7 @@ void Rules::initGame(GameObserver *g)
|
||||
p->preventable = initState.playerData[i].player->preventable;
|
||||
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 * loadedPlayerZones[] = { initState.playerData[i].player->game->graveyard,
|
||||
@@ -590,7 +592,7 @@ int Rules::load(string _filename)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Rules::strToGameMode(string s)
|
||||
GameType Rules::strToGameMode(string s)
|
||||
{
|
||||
if (s.compare("momir") == 0) return GAME_TYPE_MOMIR;
|
||||
if (s.compare("random1") == 0) return GAME_TYPE_RANDOM1;
|
||||
|
||||
@@ -324,7 +324,7 @@ void StoryDuel::init()
|
||||
game = new GameObserver(players);
|
||||
|
||||
rules->gamemode = GAME_TYPE_STORY;
|
||||
game->startGame(rules);
|
||||
game->startGame(GAME_TYPE_STORY, rules);
|
||||
}
|
||||
|
||||
StoryDuel::StoryDuel(TiXmlElement* root, StoryFlow * mParent) :
|
||||
|
||||
@@ -19,14 +19,35 @@ namespace wagic
|
||||
}
|
||||
|
||||
using std::vector;
|
||||
using std::queue;
|
||||
|
||||
int randValuesCursor = -1;
|
||||
vector<int> randValues;
|
||||
|
||||
int loadRandValues(string s)
|
||||
queue<int> loadedRandomValues;
|
||||
queue<int> usedRandomValues;
|
||||
|
||||
ostream& saveRandValues(ostream& out)
|
||||
{
|
||||
randValues.clear();
|
||||
randValuesCursor = -1;
|
||||
while(usedRandomValues.size())
|
||||
{
|
||||
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())
|
||||
{
|
||||
unsigned int value;
|
||||
@@ -41,18 +62,28 @@ int loadRandValues(string s)
|
||||
value = atoi(s.c_str());
|
||||
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()
|
||||
{
|
||||
if (randValuesCursor == -1) return rand();
|
||||
int result = randValues[randValuesCursor];
|
||||
randValuesCursor++;
|
||||
if ((size_t) randValuesCursor >= randValues.size()) randValuesCursor = 0;
|
||||
int result;
|
||||
if (!loadedRandomValues.size())
|
||||
{
|
||||
result = rand();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = loadedRandomValues.front();
|
||||
loadedRandomValues.pop();
|
||||
}
|
||||
usedRandomValues.push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -379,4 +410,4 @@ std::string ensureFolder(const std::string & folderName)
|
||||
result.append("/");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user