diff options
author | Thomas Günther <tom@toms-cafe.de> | 2005-05-15 00:18:18 +0200 |
---|---|---|
committer | Thomas Günther <tom@toms-cafe.de> | 2005-05-15 00:18:18 +0200 |
commit | 1b80a09e835a6cd68d4160f9799a7268e54a5b53 (patch) | |
tree | fa5f92848ed602216ed76ed84980921c9af95a07 /game.c | |
download | vdr-plugin-spider-1b80a09e835a6cd68d4160f9799a7268e54a5b53.tar.gz vdr-plugin-spider-1b80a09e835a6cd68d4160f9799a7268e54a5b53.tar.bz2 |
Initial versionv0.1.0
Diffstat (limited to 'game.c')
-rw-r--r-- | game.c | 403 |
1 files changed, 403 insertions, 0 deletions
@@ -0,0 +1,403 @@ +/* + * Spider-Arachnid: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + +#include "game.h" +#include "deck.h" +#include "tableau.h" +#include "heap.h" +#include "setup.h" +#include "bitmap.h" +#include "i18n.h" +#include <vdr/config.h> +#include <vdr/osdbase.h> +#include <vdr/osd.h> + +// Compatibility to older vdr versions +#if VDRVERSNUM < 10307 + #define tColor eDvbColor + #define DrawRectangle Fill + #define DrawBitmap SetBitmap + #define cOsdProvider cOsd + #define NewOsd OpenRaw + struct tArea { int x1, y1, x2, y2, bpp; }; + #define SetAreas(a,n) Create(a->x1, a->y1,\ + a->x2 - a->x1 + 1, a->y2 - a->y1 + 1,\ + a->bpp, true) + #define clrGray50 clrBackground + #define Color GetColor +#endif + + +// Defintions for bitmaps +const int cursorWidth = 16; +const int cursorHeight = 22; +const int cardWidth = 71; +const int cardHeight = 96; + +const char* cursorName = "cursor"; +const char* coverName = "cover"; +const char* suitNames[] = { "herz", "karo", "pik", "kreuz" }; +const char* rankNames[] = { "ace", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", + "jack", "queen", "king" }; +const int suitCount = sizeof(suitNames) / sizeof(*suitNames); +const int rankCount = sizeof(rankNames) / sizeof(*rankNames); + +Bitmap* cursor = NULL; +Bitmap* back = NULL; +Bitmap* frame = NULL; +Bitmap* cards[suitCount][rankCount]; + + +/** --- class SpiderGame --------------------------------------------------- **/ + +/** Constructor */ +SpiderGame::SpiderGame(const SpiderSetup& setup, const char* confdir) : + cOsdObject(true), setup(setup), confdir(confdir) +{ + width = 504; + height = 360; + xPos = (720 - width) / 2; + yPos = (576 - height) / 2; + xDist = 1; + yDist = cardHeight / 6; + osd = NULL; + deck = NULL; + tableau = NULL; + currentPile = 0; + status = cursorOnPile; + info = new Bitmap(width * 2 / 3, 60); + infoText = NULL; +} + +/** Destructor */ +SpiderGame::~SpiderGame() +{ + delete deck; + delete tableau; + delete info; + delete osd; + for (int s = 0; s < suitCount; ++s) + for (int r = 0; r < rankCount; ++r) + delete cards[s][r]; + delete frame; + delete back; + delete cursor; + frame = back = cursor = NULL; +} + +/** Display the game on the OSD */ +void SpiderGame::Show() +{ + osd = cOsdProvider::NewOsd(0, 0); + if (osd) + { + tArea areas[] = { xPos, yPos, xPos + width - 1, yPos + height - 1, 4 }; + osd->SetAreas(areas, 1); + start(); + paint(); + } +} + +/** Process user events */ +eOSState SpiderGame::ProcessKey(eKeys key) +{ + eOSState state = cOsdObject::ProcessKey(key); + if (state == osUnknown) + { + if (key == kBack) + return osEnd; + if (key == kBlue || (status == gameOver && key == kOk)) + { + start(); + status = cursorOnPile; + currentPile = 0; + } + else if (status == cursorOnPile) + { + switch (key) + { + case kLeft: + case kLeft|k_Repeat: + if (currentPile > 0) + --currentPile; + break; + case kRight: + case kRight|k_Repeat: + if (currentPile < tableau->piles.size() - 1) + ++currentPile; + break; + case kUp: + status = cursorOnPack; + break; + case kOk: + if (!tableau->piles[currentPile]->empty()) + { + tableau->select(currentPile); + status = selectedPile; + } + break; + case kGreen: + tableau->backward(); + break; + case kYellow: + tableau->forward(); + break; + default: + return osContinue; + } + } + else if (status == selectedPile) + { + int selected = tableau->selected->selected(); + int destination; + switch (key) + { + case kLeft: + destination = tableau->autoMoveLeft(currentPile); + if (destination >= 0) + { + currentPile = destination; + tableau->select(currentPile, selected); + } + break; + case kRight: + destination = tableau->autoMoveRight(currentPile); + if (destination >= 0) + { + currentPile = destination; + tableau->select(currentPile, selected); + } + break; + case kUp: + case kUp|k_Repeat: + tableau->selected->select(selected + 1); + if (key == kUp) + { + if (selected == deck->cardsInSuit) + { + tableau->remove(); + status = cursorOnPile; + } + else if (selected == tableau->selected->selected()) + infoText = tr("Only complete suits are allowed to remove"); + } + break; + case kDown: + case kDown|k_Repeat: + if (selected > 1) + tableau->selected->select(selected - 1); + break; + case kOk: + tableau->unselect(); + status = cursorOnPile; + break; + default: + return osContinue; + } + } + else if (status == cursorOnPack) + { + switch (key) + { + case kDown: + status = cursorOnPile; + currentPile = 0; + break; + case kOk: + if (tableau->pack->empty()) + infoText = tr("No cards left"); + else if (!tableau->noPileEmpty()) + infoText = tr("Deal not allowed with empty piles"); + else + tableau->deal(); + break; + default: + return osContinue; + } + } + if (tableau->gameOver()) + { + status = gameOver; + infoText = tr("Congratulations!\nPress OK to start a new game"); + } + paint(); + state = osContinue; + } + return state; +} + +/** Start a new game */ +void SpiderGame::start() +{ + // Load bitmaps + if (cursor == NULL) + { + cursor = new Bitmap(cursorWidth, cursorHeight, confdir, cursorName); + back = new Bitmap(cardWidth, cardHeight, confdir, coverName); + frame = new Bitmap(cardWidth, cardHeight, clrWhite, clrGray50); + + for (int s = 0; s < suitCount; ++s) + for (int r = 0; r < rankCount; ++r) + cards[s][r] = new Bitmap(cardWidth, cardHeight, confdir, + suitNames[s], rankNames[r]); + } + + delete deck; + delete tableau; + deck = NULL; + tableau = NULL; + + int deckCount, dealCount, pileCount; + + if (setup.variation == SpiderSetup::Mini) + { + deckCount = 1; + dealCount = 4; + pileCount = 7; + } + else // normal variation + { + deckCount = 2; + dealCount = 5; + pileCount = 10; + xDist = -23; + } + + if (pileCount > rankCount * suitCount * deckCount) + pileCount = rankCount * suitCount * deckCount; + int finalCount = suitCount * deckCount; + deck = new Deck(rankCount, suitCount, deckCount); + tableau = new Tableau(*deck, pileCount, finalCount, dealCount); +} + +/** Paint all pieces of the game */ +void SpiderGame::paint() +{ + int x1 = xPos; + int x2 = xPos + width - 1; + int y1 = yPos; + int y2 = yPos + height - 1; + osd->DrawRectangle(x1, y1, x2, y2, clrGray50); + osd->DrawRectangle(x1, y1, x2, y1 + 1, clrRed); + osd->DrawRectangle(x1, y1, x1 + 1, y2, clrRed); + osd->DrawRectangle(x1, y2 - 1, x2, y2, clrRed); + osd->DrawRectangle(x2 - 1, y1, x2, y2, clrRed); + + paintPack(); + + unsigned int f; + for (f = 0; f < tableau->finals.size(); ++f) + if (tableau->finals[f]->empty()) + break; + unsigned int count = f; + for (f = tableau->finals.size(); f-- > count;) + paintFinal(f); + for (f = 0; f < count; ++f) + paintFinal(f); + + unsigned int p; + for (p = tableau->piles.size(); p-- > currentPile + 1;) + paintPile(p); + for (p = 0; p <= currentPile; ++p) + paintPile(p); + + if (infoText) + { + info->text(infoText); + osd->DrawBitmap(xPos + (width - info->Width()) / 2, yPos + 10, *info); + infoText = NULL; + } + osd->Flush(); +} + +/** Paint the pack */ +void SpiderGame::paintPack() +{ + int packX = xPos + 1; + int packY = yPos + 1; + if (tableau->pack->empty()) + paintFrame(packX, packY); + else + paintBack(packX, packY); + if (status == cursorOnPack) + paintCursor(packX, packY); +} + +/** Paint a final heap */ +void SpiderGame::paintFinal(unsigned int f) +{ + int offset = tableau->piles.size() - tableau->finals.size(); + int finalX = xPos + 1 + (f + offset) * (cardWidth + xDist); + int finalY = yPos + 1; + if (tableau->finals[f]->empty()) + paintFrame(finalX, finalY); + else + paintCard(finalX, finalY, tableau->finals[f]->top()); +} + +/** Paint a pile */ +void SpiderGame::paintPile(unsigned int p) +{ + int pileX = xPos + 1 + p * (cardWidth + xDist); + int pileY = yPos + 1 + cardHeight + 1; + paintFrame(pileX, pileY); + + int count = tableau->piles[p]->count(); + int closed = count - tableau->piles[p]->open(); + int unselected = count - tableau->piles[p]->selected(); + int dist = yDist; + if (pileY + (count + 1) * dist > yPos + height) + dist = (yPos + height - pileY) / (count + 1); + + for (int c = 0; c < count; ++c, pileY += dist) + { + if (c == unselected) + pileY += dist; + if (c < closed) + paintBack(pileX, pileY); + else + paintCard(pileX, pileY, tableau->piles[p]->card(c)); + } + if (count > 0) + pileY -= dist; + if ((status == cursorOnPile || status == selectedPile) && p == currentPile) + paintCursor(pileX, pileY); +} + +/** Paint the cursor onto a card */ +void SpiderGame::paintCursor(int x, int y) +{ + int x0 = x + (cardWidth - cursorWidth) / 2; + int y0 = y + (cardHeight - cursorHeight) / 2; + tColor color = clrBlue; + if (status == selectedPile) + color = clrYellow; + for (x = 0; x < cursorWidth; ++x) + for (y = 0; y < cursorHeight; ++y) + if (cursor->Color(*cursor->Data(x, y)) != clrTransparent) + osd->DrawRectangle(x0 + x, y0 + y, x0 + x, y0 + y, color); +} + +/** Paint an empty card frame */ +void SpiderGame::paintFrame(int x, int y) +{ + osd->DrawBitmap(x, y, *frame); +} + +/** Paint a card back */ +void SpiderGame::paintBack(int x, int y) +{ + osd->DrawBitmap(x, y, *back); +} + +/** Paint a card */ +void SpiderGame::paintCard(int x, int y, const Card& card) +{ + osd->DrawBitmap(x, y, *cards[card.suit][card.rank]); +} |