Files
wagic/projects/mtg/src/GameStateDuel.cpp
wagic.the.homebrew@gmail.com fab150414b Erwan
- Added name effect for Momir
- Fixed a couple bugs with "moveTo", see test/Amugaba.txt
2009-04-11 03:59:46 +00:00

553 lines
15 KiB
C++

#include "../include/config.h"
#include "../include/GameStateDuel.h"
#include "../include/GameOptions.h"
#include "../include/utils.h"
#include "../include/AIPlayer.h"
#include "../include/AIMomirPlayer.h"
#include "../include/PlayerData.h"
#include "../include/DeckStats.h"
#include "../include/MTGRules.h"
#ifdef TESTSUITE
#include "../include/TestSuiteAI.h"
#endif
enum ENUM_DUEL_STATE
{
DUEL_STATE_START,
DUEL_STATE_END,
DUEL_STATE_CHOOSE_DECK1,
DUEL_STATE_CHOOSE_DECK1_TO_2,
DUEL_STATE_CHOOSE_DECK2,
DUEL_STATE_CHOOSE_DECK2_TO_PLAY,
DUEL_STATE_ERROR_NO_DECK,
DUEL_STATE_CANCEL,
DUEL_STATE_PLAY,
DUEL_STATE_BACK_TO_MAIN_MENU,
DUEL_STATE_MENU
};
enum ENUM_DUEL_MENUS
{
DUEL_MENU_GAME_MENU,
DUEL_MENU_CHOOSE_DECK,
DUEL_MENU_CHOOSE_OPPONENT
};
GameStateDuel::GameStateDuel(GameApp* parent): GameState(parent) {
for (int i = 0; i<2; i ++){
deck[i]=NULL;
mPlayers[i]=NULL;
}
game = NULL;
deckmenu = NULL;
opponentMenu = NULL;
opponentMenuFont = NULL;
menu = NULL;
#ifdef TESTSUITE
testSuite = NULL;
#endif
showMsg = 0;
unlockedTex = NULL;
unlockedQuad = NULL;
}
GameStateDuel::~GameStateDuel() {
End();
}
void GameStateDuel::Start()
{
JRenderer * renderer = JRenderer::GetInstance();
renderer->ResetPrivateVRAM();
renderer->EnableVSync(true);
#ifdef TESTSUITE
if (testSuite) delete testSuite;
testSuite = NEW TestSuite(RESPATH"/test/_tests.txt",mParent->collection);
#endif
mGamePhase = DUEL_STATE_CHOOSE_DECK1;
mFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT);
mFont->SetBase(0);
opponentMenuFont = mFont;
unlocked = -1;
menu = NEW SimpleMenu(DUEL_MENU_GAME_MENU, this, mFont, SCREEN_WIDTH/2-100, 25);
menu->Add(12,"Back to main menu");
menu->Add(13, "Cancel");
int decksneeded = 0;
for (int i = 0; i<2; i ++){
if (mParent->players[i] == PLAYER_TYPE_HUMAN){
if (!deckmenu){
decksneeded = 1;
deckmenu = NEW SimpleMenu(DUEL_MENU_CHOOSE_DECK, this, mFont, 35, 25, "Choose a Deck");
char buffer[100];
for (int j=1; j<6; j++){
sprintf(buffer, RESPATH"/player/deck%i.txt",j);
std::ifstream file(buffer);
if(file){
deckmenu->Add(j, GameState::menuTexts[j]);
file.close();
decksneeded = 0;
}
}
}
}
}
if (decksneeded)
mGamePhase = DUEL_STATE_ERROR_NO_DECK;
}
void GameStateDuel::loadPlayerMomir(int playerId, int isAI){
char * deckFile = RESPATH"/player/momir.txt";
char * deckFileSmall = "momir";
MTGDeck * tempDeck = NEW MTGDeck(deckFile, NULL, mParent->collection);
deck[playerId] = NEW MTGPlayerCards(mParent->collection,tempDeck);
if (!isAI){ //Human Player
mPlayers[playerId] = NEW HumanPlayer(deck[playerId],deckFileSmall);
}else{
mPlayers[playerId] = NEW AIMomirPlayer(deck[playerId],deckFile,"");
}
delete tempDeck;
}
void GameStateDuel::loadPlayer(int playerId, int decknb, int isAI){
if (decknb){
if (!isAI){ //Human Player
char deckFile[255];
sprintf(deckFile, RESPATH"/player/deck%i.txt",decknb);
char deckFileSmall[255];
sprintf(deckFileSmall, "player_deck%i",decknb);
//int deck_cards_ids[100];
//int nb_elements = readfile_to_ints(deckFile, deck_cards_ids);
MTGDeck * tempDeck = NEW MTGDeck(deckFile, NULL, mParent->collection);
deck[playerId] = NEW MTGPlayerCards(mParent->collection,tempDeck);
delete tempDeck;
mPlayers[playerId] = NEW HumanPlayer(deck[playerId],deckFileSmall);
}else{ //AI Player, chose deck
AIPlayerFactory playerCreator;
mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection,NULL,decknb);
deck[playerId] = mPlayers[playerId]->game;
}
}else{
AIPlayerFactory playerCreator;
mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection,NULL);
deck[playerId] = mPlayers[playerId]->game;
}
}
#ifdef TESTSUITE
void GameStateDuel::loadTestSuitePlayers(){
OutputDebugString ("loading suite 1\n");
if (!testSuite) return;
for (int i = 0; i < 2; i++){
if (mPlayers[i]){
delete mPlayers[i];
}
mPlayers[i] = NEW TestSuiteAI(testSuite, i);
OutputDebugString ("loading suite 2\n");
deck[i] = mPlayers[i]->game;
}
mParent->gameType = testSuite->gameType;
if (game) delete game;
game = NULL;
if (!game){
GameObserver::Init(mPlayers, 2);
OutputDebugString ("loading suite 3\n");
game = GameObserver::GetInstance();
OutputDebugString ("loading suite 4\n");
game->startGame(0,0);
OutputDebugString ("loading suite 5\n");
if (mParent->gameType == GAME_TYPE_MOMIR){
game->addObserver(NEW MTGMomirRule(-1, mParent->collection));
for (int i = 0; i < 2; i++){
game->players[i]->life+=4;
}
}
}
}
#endif
void GameStateDuel::End()
{
#if defined (WIN32) || defined (LINUX)
OutputDebugString("Ending GamestateDuel\n");
#endif
SAFE_DELETE(deckmenu);
JRenderer::GetInstance()->EnableVSync(false);
if (mPlayers[0] && mPlayers[1]) mPlayers[0]->End();
GameObserver::EndInstance();
game = NULL;
for (int i = 0; i < 2; i++){
SAFE_DELETE(mPlayers[i]);
SAFE_DELETE(deck[i]);
}
SAFE_DELETE(unlockedQuad);
SAFE_DELETE(unlockedTex);
SAFE_DELETE(menu);
SAFE_DELETE(opponentMenu);
#ifdef TESTSUITE
SAFE_DELETE(testSuite);
#endif
}
void GameStateDuel::Update(float dt)
{
switch (mGamePhase)
{
case DUEL_STATE_ERROR_NO_DECK:
if (PSP_CTRL_CIRCLE == mEngine->ReadButton())
mParent->SetNextState(GAME_STATE_DECK_VIEWER);
break;
case DUEL_STATE_CHOOSE_DECK1:
if (mParent->gameType == GAME_TYPE_MOMIR){
for (int i = 0; i < 2; i++){
int isAI = 1;
if (mParent->players[i] == PLAYER_TYPE_HUMAN) isAI = 0;
loadPlayerMomir(i, isAI);
}
mGamePhase = DUEL_STATE_PLAY;
}else if (mParent->players[0] == PLAYER_TYPE_HUMAN)
deckmenu->Update(dt);
#ifdef TESTSUITE
else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE){
if (testSuite && testSuite->loadNext()){
loadTestSuitePlayers();
mGamePhase = DUEL_STATE_PLAY;
testSuite->initGame();
char buf[4096];
sprintf(buf, "nb cards in player2's graveyard : %i\n",mPlayers[1]->game->graveyard->nb_cards);
LOG(buf);
}else{
mGamePhase = DUEL_STATE_END;
}
}
#endif
else{
loadPlayer(0);
mGamePhase = DUEL_STATE_CHOOSE_DECK2;
}
break;
case DUEL_STATE_CHOOSE_DECK1_TO_2:
if (deckmenu->closed) mGamePhase = DUEL_STATE_CHOOSE_DECK2;
else deckmenu->Update(dt);
break;
case DUEL_STATE_CHOOSE_DECK2:
if (mParent->players[1] == PLAYER_TYPE_HUMAN){
deckmenu->Update(dt);
}
else{
if (mParent->players[0] == PLAYER_TYPE_HUMAN){
if (!opponentMenu){
opponentMenu = NEW SimpleMenu(DUEL_MENU_CHOOSE_OPPONENT, this, opponentMenuFont, 35, 25, "Choose Opponent");
opponentMenu->Add(0,"Random");
nbAIDecks = 0;
int found = 1;
while (found){
found = 0;
char buffer[512];
char aiSmallDeckName[512];
char deckDesc[512];
sprintf(buffer, RESPATH"/ai/baka/deck%i.txt",nbAIDecks+1);
if(fileExists(buffer)){
found = 1;
nbAIDecks++;
sprintf(aiSmallDeckName, "ai_baka_deck%i",nbAIDecks);
DeckStats * stats = DeckStats::GetInstance();
stats->load(mPlayers[0]);
int percentVictories = stats->percentVictories(string(aiSmallDeckName));
string difficulty;
if (percentVictories < 34){
difficulty = "(hard)";
}else if (percentVictories < 67){
difficulty = "";
}else{
difficulty = "(easy)";
}
sprintf(deckDesc, "Deck %i %s",nbAIDecks, difficulty.c_str());
opponentMenu->Add(nbAIDecks,deckDesc);
}
}
}
opponentMenu->Update(dt);
}else{
loadPlayer(1);
mGamePhase = DUEL_STATE_PLAY;
}
}
break;
case DUEL_STATE_CHOOSE_DECK2_TO_PLAY:
if (mParent->players[1] == PLAYER_TYPE_HUMAN){
if (deckmenu->closed) mGamePhase = DUEL_STATE_PLAY;
else deckmenu->Update(dt);
}
else
{
if (opponentMenu->closed) mGamePhase = DUEL_STATE_PLAY;
else opponentMenu->Update(dt);
}
break;
case DUEL_STATE_PLAY:
//Stop the music before starting the game
if (GameApp::music){
JSoundSystem::GetInstance()->StopMusic(GameApp::music);
SAFE_DELETE(GameApp::music);
}
if (!game){
GameObserver::Init(mPlayers, 2);
game = GameObserver::GetInstance();
game->startGame();
if (mParent->gameType == GAME_TYPE_MOMIR){
game->addObserver(NEW MTGMomirRule(-1, mParent->collection));
for (int i = 0; i < 2; i++){
game->players[i]->life+=4;
}
}
}
game->Update(dt);
if (game->gameOver){
showMsg = (rand() % 5);
if (!mPlayers[0]->isAI() && mPlayers[1]->isAI() && mPlayers[0]!= game->gameOver){
PlayerData * playerdata = NEW PlayerData(mParent->collection);
playerdata->credits+= 500;
playerdata->save();
delete playerdata;
if (unlocked == -1){
unlocked = isDifficultyUnlocked();
if (unlocked){
unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/unlocked.png", TEX_TYPE_USE_VRAM);
unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96);
GameOptions::GetInstance()->values[OPTIONS_DIFFICULTY_MODE_UNLOCKED] = GameOption(1);
GameOptions::GetInstance()->save();
}else{
unlocked = isMomirUnlocked();
if (unlocked){
unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/momir_unlocked.png", TEX_TYPE_USE_VRAM);
unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96);
GameOptions::GetInstance()->values[OPTIONS_MOMIR_MODE_UNLOCKED] = GameOption(1);
GameOptions::GetInstance()->save();
}
}
if (unlocked){
JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/bonus.wav");
if (sample) JSoundSystem::GetInstance()->PlaySample(sample);
}
}
}else{
unlocked = 0;
}
mGamePhase = DUEL_STATE_END;
#ifdef TESTSUITE
if (mParent->players[1] == PLAYER_TYPE_TESTSUITE){
if (testSuite->loadNext()){
loadTestSuitePlayers();
mGamePhase = DUEL_STATE_PLAY;
testSuite->initGame();
}else{
mGamePhase = DUEL_STATE_END;
}
}else
#endif
if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU){
End();
Start();
}
mFont->SetColor(ARGB(255,255,255,255));
}
if (mEngine->GetButtonClick(PSP_CTRL_START)){
mGamePhase = DUEL_STATE_MENU;
}
break;
case DUEL_STATE_MENU:
menu->Update(dt);
break;
case DUEL_STATE_CANCEL:
menu->Update(dt);
if (menu->closed)
mGamePhase = DUEL_STATE_PLAY;
break;
case DUEL_STATE_BACK_TO_MAIN_MENU:
menu->Update(dt);
if (menu->closed)
mParent->SetNextState(GAME_STATE_MENU);
break;
default:
if (PSP_CTRL_CIRCLE == mEngine->ReadButton()){
mParent->SetNextState(GAME_STATE_MENU);
}
}
}
void GameStateDuel::Render()
{
//Erase
LOG("Start Render\n");
JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0));
if (game)
game->Render();
switch (mGamePhase)
{
case DUEL_STATE_END:
{
JRenderer * r = JRenderer::GetInstance();
r->ClearScreen(ARGB(200,0,0,0));
char buffer[50];
int p0life = mPlayers[0]->life;
if (!mPlayers[0]->isAI() && mPlayers[1]->isAI() ){
if (game->gameOver != mPlayers[0]){
sprintf (buffer, "Victory! Congratulations, You earn 500 credits");
}else{
sprintf (buffer, "You have been defeated");
}
}else{
int winner = 2;
if (game->gameOver !=mPlayers[0]){
winner = 1;
}
sprintf(buffer, "Player %i wins (%i)", winner, p0life );
}
mFont->SetScale(1);
mFont->DrawString(buffer, 10, 150);
if (unlockedQuad){
r->RenderQuad(unlockedQuad, 20, 20);
}
if (showMsg == 1){
JLBFont * f = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT);
mFont->DrawString("Please support this project !" ,10,180);
f->DrawString("Wagic is free, open source, and developed on the little free time I have" ,10,196);
f->DrawString("If you enjoy this game, please consider donating a few bucks" ,10,208);
f->DrawString("I'll drink a beer in your name!" ,10,220);
f->DrawString("Thanks in advance for your support." ,10,232);
mFont->DrawString("-> http://wololo.net/wagic" ,10,244);
}
break;
}
case DUEL_STATE_CHOOSE_DECK1:
case DUEL_STATE_CHOOSE_DECK1_TO_2:
case DUEL_STATE_CHOOSE_DECK2:
case DUEL_STATE_CHOOSE_DECK2_TO_PLAY:
if (opponentMenu){
opponentMenu->Render();
}else if (deckmenu){
deckmenu->Render();
}
break;
case DUEL_STATE_ERROR_NO_DECK:
mFont->DrawString("NO DECK AVAILABLE,",0,SCREEN_HEIGHT/2);
mFont->DrawString("PRESS CIRCLE TO GO TO THE DECK EDITOR!",0,SCREEN_HEIGHT/2 + 20);
break;
case DUEL_STATE_MENU:
case DUEL_STATE_CANCEL:
case DUEL_STATE_BACK_TO_MAIN_MENU:
menu->Render();
}
LOG("End Render\n");
}
void GameStateDuel::ButtonPressed(int controllerId, int controlId)
{
switch (controllerId){
case DUEL_MENU_CHOOSE_OPPONENT:
{
switch(controlId){
case 0:
loadPlayer(1);
opponentMenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY;
break;
default:
loadPlayer(1,controlId,1);
opponentMenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY;
break;
}
break;
}
default:
{
switch (controlId)
{
case 1:
case 2:
case 3:
case 4:
case 5:
{
if (mGamePhase == DUEL_STATE_CHOOSE_DECK1){
loadPlayer(0,controlId);
deckmenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK1_TO_2;
}else{
loadPlayer(1,controlId);
deckmenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY;
}
break;
}
case 12:
menu->Close();
mGamePhase = DUEL_STATE_BACK_TO_MAIN_MENU;
break;
case 13:
menu->Close();
mGamePhase = DUEL_STATE_CANCEL;
break;
}
}
}
}
int GameStateDuel::isDifficultyUnlocked(){
if (GameOptions::GetInstance()->values[OPTIONS_DIFFICULTY_MODE_UNLOCKED].getIntValue()) return 0;
nbAIDecks = 0;
int found = 1;
int wins = 0;
DeckStats * stats = DeckStats::GetInstance();
stats->load(mPlayers[0]);
while (found){
found = 0;
char buffer[512];
char aiSmallDeckName[512];
sprintf(buffer, RESPATH"/ai/baka/deck%i.txt",nbAIDecks+1);
if(fileExists(buffer)){
found = 1;
nbAIDecks++;
sprintf(aiSmallDeckName, "ai_baka_deck%i",nbAIDecks);
int percentVictories = stats->percentVictories(string(aiSmallDeckName));
if (percentVictories >=67) wins++;
if (wins >= 10) return 1;
}
}
return 0;
}
int GameStateDuel::isMomirUnlocked(){
if (GameOptions::GetInstance()->values[OPTIONS_MOMIR_MODE_UNLOCKED].getIntValue()) return 0;
Player *p = mPlayers[0];
if (p->game->inPlay->countByType("land") == 8) return 1;
return 0;
}