Hangman game using qp a 16x2 LCD and joystick.

Dependencies:   TextLCD mbed qp

host.cpp

Committer:
tylerjw
Date:
2012-02-09
Revision:
1:4efaebc256d3
Parent:
0:1521c946a57b

File content as of revision 1:4efaebc256d3:

#include "qp_port.h"
#include "hangman.h"
#include "bsp.h"

Q_DEFINE_THIS_FILE

class Host : public QActive {
private:
    char* word;
    uint8_t selected_word;
    uint8_t num_letters;
    uint8_t incorrect_letters;
    char* used_letters;

    char letter;
    char output1[17]; // buffer for display
    char output2[17];

public:
    Host();

private:
    static QState initial(Host *me, QEvent const *e);
    static QState welcome(Host *me, QEvent const *e);
    static QState playing(Host *me, QEvent const *e);
};

#define BANK_SIZE   4
char* const word_bank[] = { "hangmann", "global", "micro", "sensor" };
char* const win_msg = "   You Win!";
char* const loose_msg = "   You suck!";
char* const press_play_msg = "Push to continue";


// Local objects -------------------------------------------------------------
static Host l_host;                                    // local Host object

// Public-scope objects ------------------------------------------------------
QActive * const AO_Host = &l_host;                    // "opaque" AO pointer

//............................................................................
Host::Host() : QActive((QStateHandler)&Host::initial) {
}

//............................................................................
QState Host::initial(Host *me, QEvent const *e) {

    QS_OBJ_DICTIONARY(&l_host);
    QS_FUN_DICTIONARY(&QHsm::top);
    QS_FUN_DICTIONARY(&Host::initial);
    QS_FUN_DICTIONARY(&Host::playing);

    QS_SIG_DICTIONARY(TERMINATE_SIG, 0); // global signal

    QS_SIG_DICTIONARY(START_SIG, me);     // signals for Host
    QS_SIG_DICTIONARY(SCROLL_SIG, me);
    QS_SIG_DICTIONARY(SELECT_SIG, me);

    me->subscribe(TERMINATE_SIG);

    // output welcome message
    BSP_lcdUpdate("Push btn to play mbed hangman!","");
    wait(2.0);  // pause for 2 seconds

    return Q_TRAN(&Host::welcome);
}

//............................................................................
QState Host::welcome(Host *me, QEvent const *e) {
    HostEvt *pe;

    switch (e->sig) {
        case START_SIG: {
            uint8_t idx;

            // init the game
            time_t seconds = time(NULL);
            me->selected_word = seconds % BANK_SIZE;
            me->word = word_bank[me->selected_word];
            me->num_letters = strlen(me->word);
            me->incorrect_letters = 0;
            for (int i = 0; i < 17; i++) { // clear output
                me->output1[i] = ' ';
                me->output2[i] = ' ';
            }

            for (idx = 0; idx < me->num_letters; idx++) {
                me->output1[idx] = '_';
            }
            for (; idx < 16; idx++) {
                me->output1[idx] = ' ';
            }
            me->letter = 'a';
            idx = 16;
            me->output1[idx] = me->letter;
            // clear output2
            for (idx = 0; idx < 17; idx++)
                me->output2[idx] = ' ';

            BSP_lcdUpdate(me->output1, me->output2); // update display

            // post play to player
            pe = Q_NEW(HostEvt, PLAY_SIG);
            pe->scroll_pos = 0; // center
            QF::PUBLISH(pe, me);

            return Q_TRAN(&Host::playing);
        }
        case TERMINATE_SIG: {
            QF::stop();
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&QHsm::top);
}

//............................................................................
QState Host::playing(Host *me, QEvent const *e) {

    HostEvt *pe;

    switch (e->sig) {
        case SCROLL_SIG: {
            if (((HostEvt const *)e)->scroll_pos < 0) { // go down
                if (me->letter == 'a') // wrap around
                    me->letter = 'z';
                else
                    me->letter--;
            } else if (((HostEvt const *)e)->scroll_pos > 0) { // go up
                if (me->letter == 'z') // wrap around
                    me->letter = 'a';
                else
                    me->letter++;
            }
            me->output1[16] = me->letter;
            BSP_lcdUpdate(me->output1,me->output2);

            return Q_HANDLED();
        }
        case SELECT_SIG: {
            // test for letter in word
            char * pch;
            pch=strchr(me->word,me->letter);
            if (pch != NULL) { // found in word
                do {
                    me->word[pch-me->word] = ' ';
                    me->output1[pch-me->word] = me->letter;
                    pch=strchr(pch+1,me->letter);
                } while (pch!=NULL);
                // update screen
                BSP_lcdUpdate(me->output1,me->output2);
                // test for win
                if (strpbrk(me->word,"abcdefghijklmnopqrs") == NULL) { // win!
                    BSP_lcdScrollIn(win_msg, press_play_msg); // win msg
                    // post play to player
                    HostEvt *pe = Q_NEW(HostEvt, FINISHED_SIG);
                    pe->scroll_pos = 1; // win
                    QF::PUBLISH(pe, me);

                    // go to welcome state
                    return Q_TRAN(&Host::welcome);
                }
            } else {
                if (++me->incorrect_letters >= MAX_LETTERS) { // loose
                    BSP_lcdScrollIn(loose_msg, press_play_msg); // message
                    // post play to player
                    HostEvt *pe = Q_NEW(HostEvt, FINISHED_SIG);
                    pe->scroll_pos = 0; // loss
                    QF::PUBLISH(pe, me);

                    // go to welcome state
                    return Q_TRAN(&Host::welcome);
                } else {
                    // post to used letters
                    me->output2[me->incorrect_letters-1] = (char)(me->letter - 33); // make uppercase
                    BSP_lcdUpdate(me->output1,me->output2); // update screen
                }
            }
            return Q_HANDLED();
        }
        case TERMINATE_SIG: {
            QF::stop();
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&QHsm::top);
}