void SceneGame::pressKey(int k) { // delete if(k == GameAlphabetDEL) { IGLog("SceneGame touched DEL"); inverseAnswerKey[selectedChar-'A'] = '_'; updatePhrase(); removeKeyboard(); } // escape else if(k == GameAlphabetESC) { IGLog("SceneGame touched ESC"); removeKeyboard(); } // a letter else { char buffer[200]; sprintf(buffer, "SceneGame touched letter %c", 'A'+k); IGLog(buffer); // if there's a duplicate, get rid of it for(int i=0; i<26; i++) { if(inverseAnswerKey[i] == k+'A') inverseAnswerKey[i] = '_'; } inverseAnswerKey[selectedChar-'A'] = k+'A'; updatePhrase(); removeKeyboard(); } }
// method used to initialise a new phrase void CSabrinaPhraseInstance::beginPhrase(const ISabrinaPhraseModel* thePhrase) { #ifdef NL_DEBUG nlassert(_ThePhrase==NULL); nlassert(_State==Inactive); nlassert(_Target==NULL); #endif // setup basic data _ThePhrase=const_cast<ISabrinaPhraseModel*>(thePhrase); _NextEventTime=0; // setup the target _Target= _ThePhrase->requiresTarget()? _Actor->getTarget(): NULL; if (_Target!=NULL) _Target->addTargeter(this); // call the actor's init() callback _Actor->cbSabrinaActionBegin(this); // ask the model whether the phrase is valid (target's accessible, etc) // if the validation fails then close the phrase down and exit cleanly SABRINA::TEventCode validationResult=_ThePhrase->validate(this); if (!SABRINA::isSuccess(validationResult)) { abortPhrase(validationResult); return; } // ask the phrase model to calculate the pre-execution delay uint32 ticks= _ThePhrase->calculatePreExecutionDelay(this); // setup the state information _State= PreActionDelay; _NextEventTime= CTickEventHandler::getGameCycle()+ticks; // check whether the action time is '0' - requiring immediate action if (ticks==0) { updatePhrase(); } else { CSabrinaPhraseManager::setNextPhraseEvent(this,_NextEventTime); } }
void SceneGame::hint() { IGLog("pressed hint"); unsigned int i; int rnd, index; bool found = false; std::vector<int> notAnswered; std::vector<int> incorrectAnswers; std::vector<int> correctAnswers; // count how many answers, and how many of them are correct for(i=0; i<26; i++) { if(inverseAnswerKey[i] != '_') { if(inverseAnswerKey[i] == inverseKey[i]) correctAnswers.push_back(i); else incorrectAnswers.push_back(i); } else { notAnswered.push_back(i); } } // if there are no answers, supply a random one if(incorrectAnswers.size() + correctAnswers.size() == 0) { while(!found) { index = rand()%26; if(frequency[index] > 0) found = true; } } // if there are answers but some are wrong, fix one of the wrong answers else if(incorrectAnswers.size() > 0) { while(!found) { rnd = rand()%incorrectAnswers.size(); index = incorrectAnswers[rnd]; if(frequency[index] > 0) found = true; } } // otherwise supply a random answer that hasn't been answered else { while(!found) { rnd = rand()%notAnswered.size(); index = notAnswered[rnd]; if(frequency[index] > 0) found = true; } } // if there's a duplicate, get rid of it for(int i=0; i<26; i++) { if(inverseAnswerKey[i] == inverseKey[index]) inverseAnswerKey[i] = '_'; } // give the hint and update the phrase inverseAnswerKey[index] = inverseKey[index]; updatePhrase(); }
// game scene SceneGame::SceneGame() { IGScene::IGScene(); IGLog("SceneGame init"); unsigned int i, j; // load the game phraseId = 0; savedGameDB = new SQLite3Wrapper("savedGame.db"); loadGame(); // init physical keyboard array s3eKeys[0]=s3eKeyA; s3eKeys[1]=s3eKeyB; s3eKeys[2]=s3eKeyC; s3eKeys[3]=s3eKeyD; s3eKeys[4]=s3eKeyE; s3eKeys[5]=s3eKeyF; s3eKeys[6]=s3eKeyG; s3eKeys[7]=s3eKeyH; s3eKeys[8]=s3eKeyI; s3eKeys[9]=s3eKeyJ; s3eKeys[10]=s3eKeyK; s3eKeys[11]=s3eKeyL; s3eKeys[12]=s3eKeyM; s3eKeys[13]=s3eKeyN; s3eKeys[14]=s3eKeyO; s3eKeys[15]=s3eKeyP; s3eKeys[16]=s3eKeyQ; s3eKeys[17]=s3eKeyR; s3eKeys[18]=s3eKeyS; s3eKeys[19]=s3eKeyT; s3eKeys[20]=s3eKeyU; s3eKeys[21]=s3eKeyV; s3eKeys[22]=s3eKeyW; s3eKeys[23]=s3eKeyX; s3eKeys[24]=s3eKeyY; s3eKeys[25]=s3eKeyZ; // load resources, background image IGSprite* spriteBackground = NULL; switch(Settings::getInstance()->theme) { case SettingsThemeHacker: IwGetResManager()->LoadGroup("game_hacker.group"); spriteBackground = new IGSprite("GameHackerBackground", IGPoint(240,160), 0); break; case SettingsThemeDetective: IwGetResManager()->LoadGroup("game_detective.group"); spriteBackground = new IGSprite("GameDetectiveBackground", IGPoint(240,160), 0); break; case SettingsThemeEspionage: IwGetResManager()->LoadGroup("game_espionage.group"); spriteBackground = new IGSprite("GameEspionageBackground", IGPoint(240,160), 0); break; } this->addChild(spriteBackground); // buttons GameButtonNewPuzzle* buttonNewPuzzle = new GameButtonNewPuzzle(); GameButtonHint* buttonHint = new GameButtonHint(); GameButtonMenu* buttonMenu = new GameButtonMenu(); this->addChild(buttonNewPuzzle); this->addChild(buttonHint); this->addChild(buttonMenu); // time int sec = (int)(time%60); int min = (int)(time/60); GameTimeLabel* timeLabel = new GameTimeLabel(min,sec); this->addChild(timeLabel); // draw the phrase const unsigned int maxCols = 18; // used to be 21 const unsigned int maxRows = 4; int columnCount[4] = {0,0,0,0}; // count number of columns per row unsigned int col = 0; unsigned int row = 0; for(i=0; i<strlen(ciphertext); i++) { // if it's a space in the first column, skip this one while(col == 0 && ciphertext[i] == ' ') i++; // if it's a word, see if there's enough space in this line if(ciphertext[i] != ' ') { for(j=i+1; j<strlen(ciphertext); j++) { if(ciphertext[j] == ' ' || ciphertext[j] == '\0') break; } if(col + (j-i) >= maxCols) { col = 0; row++; } } // if it's a letter, draw empty box and an empty plaintext label if(ciphertext[i] >= 'A' && ciphertext[i] <= 'Z') { GameSlot* slot = new GameSlot(row, col, SceneGameTagSlots+i); GamePlaintextLabel* plaintextLabel = new GamePlaintextLabel(' ', row, col, SceneGameTagPlaintextLabels+i); this->addChild(slot); this->addChild(plaintextLabel); } // otherwise draw the character else { if(ciphertext[i] != ' ') { GamePlaintextLabel* plaintextLabel = new GamePlaintextLabel(ciphertext[i], row, col, SceneGameTagPlaintextLabels+i); this->addChild(plaintextLabel); } } // draw the ciphertext if(ciphertext[i] != ' ') { GameCiphertextLabel* ciphertextLabel = new GameCiphertextLabel(ciphertext[i], row, col, SceneGameTagCiphertextLabels+i); this->addChild(ciphertextLabel); } // count the columns columnCount[row]++; // increment the column col++; if(col == maxCols) { col = 0; row++; } } // center the text, total width=468, letter width=26 for(i=0; i<4; i++) { int width = columnCount[i]; int index = -1; for(j=0; j<=i; j++) index += columnCount[j]; if(ciphertext[index] == ' ') width--; centerOffset[i] = (468 - (width*26)) / 2; } row = 0; for(i=0; i<strlen(ciphertext); i++) { GameSlot* slot = (GameSlot*)this->getChildByTag(SceneGameTagSlots+i); if(slot != NULL) { row = slot->row; slot->position.x += centerOffset[row]; } GamePlaintextLabel* plaintextLabel = (GamePlaintextLabel*)this->getChildByTag(SceneGameTagPlaintextLabels+i); if(plaintextLabel != NULL) plaintextLabel->position.x += centerOffset[row]; GameCiphertextLabel* ciphertextLabel = (GameCiphertextLabel*)this->getChildByTag(SceneGameTagCiphertextLabels+i); if(ciphertextLabel != NULL) ciphertextLabel->position.x += centerOffset[row]; } // draw the key IGLabel* labelAlphabet = new IGLabel("FontFixedSys14", "alphabet: ", IGPoint(123,230), IGRect(90,20), 2, SceneGameTagLabelAlphabet); IGLabel* labelAnswerKey = new IGLabel("FontFixedSys14", " key: ", IGPoint(123,250), IGRect(90,20), 2, SceneGameTagLabelAnswerKey); IGLabel* labelAlphabetLetter = new IGLabel("FontFixedSys14", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", IGPoint(294,230), IGRect(234,20), 2, SceneGameTagLabelAlphabetLetters); IGLabel* labelAnswerKeyLetter = new IGLabel("FontFixedSys14", "__________________________", IGPoint(294,250), IGRect(234,20), 2, SceneGameTagLabelAnswerKeyLetters); switch(Settings::getInstance()->theme) { case SettingsThemeHacker: labelAnswerKey->setColor(140,140,140,255); labelAlphabet->setColor(140,140,140,255); labelAnswerKeyLetter->setColor(210,220,210,255); labelAlphabetLetter->setColor(210,220,210,255); break; case SettingsThemeDetective: case SettingsThemeEspionage: labelAnswerKey->setColor(80,80,80,255); labelAlphabet->setColor(80,80,80,255); labelAnswerKeyLetter->setColor(20,20,20,255); labelAlphabetLetter->setColor(20,20,20,255); break; break; } this->addChild(labelAnswerKey); this->addChild(labelAlphabet); this->addChild(labelAnswerKeyLetter); this->addChild(labelAlphabetLetter); // keyboard keyboardUp = false; // update the phrase updatePhrase(); }
// update routine called on event triggers // returns true if _NextEventTime == current time (otherwise false) bool CSabrinaPhraseInstance::updatePhrase() { // if the phrase' timer's been changed then this event is not valid so ignore it... NLMISC::TGameCycle curTime=CTickEventHandler::getGameCycle(); if (_NextEventTime != curTime) return false; // change the value of '_NextEventTime' to avoid multiple executions of the action phrase // when the phrase end date is set to the same time more than once... --_NextEventTime; // depending on state do something... switch (_State) { case PreActionDelay: { // ask the model whether the phrase is valid (target's accessible, etc) // if the validation fails then close the phrase down and exit cleanly SABRINA::TEventCode validationResult=_ThePhrase->validate(this); if (!SABRINA::isSuccess(validationResult)) { _Actor->cbSabrinaActionFailure(this,validationResult); terminate(); break; } // ask the model to execute the phrase action and apply results to whoever necessary // if execution failed then exit cleanly SABRINA::TEventCode executionResult= _ThePhrase->executeAndApplyResults(this); if (SABRINA::isSuccess(executionResult)) { _Actor->cbSabrinaActionSuccess(this,executionResult); } else { _Actor->cbSabrinaActionFailure(this,executionResult); terminate(); break; } // ask the phrase model to calculate the post-execution delay uint32 ticks=_ThePhrase->calculatePostExecutionDelay(this); // setup the state information _State= PostActionDelay; _NextEventTime= CTickEventHandler::getGameCycle()+ticks; // check whether the action time is '0' - requiring immediate action if (ticks==0) { updatePhrase(); } else { CSabrinaPhraseManager::setNextPhraseEvent(this,_NextEventTime); } break; } case PostActionDelay: terminate(); break; case Inactive: break; } return true; }