Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

board.cpp

Go to the documentation of this file.
00001 
00002 
00003 #if defined( KDE2_PORT )
00004 #include <kapp.h>
00005 #include <klocale.h>
00006 #endif
00007 
00008 #include <qmessagebox.h>
00009 #include <qfile.h>
00010 #include <qtextstream.h>
00011 
00012 #include "board.h"
00013 #include "bitmaps.h"
00014 
00015 Board::Board(int size) : QArray<int> (size)
00016 {
00017     sz = size;                          // set size of board
00018 
00019     map = "";                   
00020     mapName = "";                       // no map loaded so far
00021 
00022     init(None);                         // initialize varibales
00023 }
00024 
00025 void Board::init(Image image, QString levelName)
00026 {
00027     prisonEntry = OUT;
00028     prisonExit = OUT;
00029     fruitHome = OUT;
00030     fruitPosition = OUT;
00031     pacmanHome = OUT;
00032     pacmanPosition = OUT;
00033     for (int m = 0; m < 8; m++) {
00034         monsterHome[m] = OUT;
00035         monsterPosition[m] = OUT;
00036     }
00037     for (int e = 0; e < 8; e++) {
00038         energizerPosition[e] = OUT;
00039     }
00040     for (int e = 0; e < 8; e++) {
00041         tunnelPosition[e] = OUT;
00042     }
00043 
00044     fill(0);
00045     numPoints = 0;
00046     numEnergizers = 0;
00047     numMonsters = 0;
00048     numTunnels = 0;
00049 
00050     if (!levelName.isNull() && !levelName.isEmpty())
00051         if (mapName == levelName)
00052             image = File;
00053         else {
00054             QFile levelFile(levelName);
00055             if (!levelFile.open(IO_ReadOnly)) {
00056 
00057                 QString msg = "The levelmap could not be constructed.\n\n"
00058                                    "The file '@LEVELNAME@' does not exist,\n"
00059                                    "or could not be opened for reading.";
00060                 msg.replace(QRegExp("@LEVELNAME@"), levelName);
00061                 // QMessageBox::information(0, tr("Initialization Error"), msg);
00062                 printf("%s\n", msg.data());
00063             } else {
00064                 map.fill(' ', BoardHeight*BoardWidth);
00065                 int height = 0; 
00066 
00067                 QTextStream levelStream(&levelFile);
00068                 while (!levelStream.eof() && height < BoardHeight) {
00069                     QString line = levelStream.readLine();
00070                 
00071                     if (line.find(QRegExp("^ *;")) == -1) {     
00072 
00073                         line.replace(QRegExp(";.*"), "");       // strip off comments
00074                         line.replace(QRegExp("\" *$"), "");     // strip off trailing "
00075                         line.replace(QRegExp("^ *\""), "");     // strip off leading "
00076 
00077                         map.replace(height*BoardWidth,
00078                                     (line.length() > BoardWidth) ? BoardWidth : line.length(),
00079                                     line.data());
00080 
00081                         height++;
00082                     }
00083                 }
00084                 mapName = levelName;
00085                 levelFile.close();
00086                 image = File;
00087             }
00088         }
00089 
00090     switch (image) {
00091         case Intro : // setup(demo_bits);
00092                      break;
00093         case Demo  : setup(demo_bits);
00094                      break;
00095         case Level : setup(demo_bits);
00096                      break;
00097         case File  : setup((uchar *) map.data());
00098                      break;
00099         default    : break;
00100     }
00101 }
00102 
00103 void Board::setup(const uchar *buf)
00104 {
00105     for ( int index = 0; buf[index] != 0 && index < BoardWidth*BoardHeight; index++ ) {
00106         switch (buf[index]) {
00107             case '*' : set(index, brick); break;
00108             case '+' : set(index, out); break;
00109             case '#' : set(index, prison); break;
00110             case '-' : set(index, gate); break;
00111             case 'E' : set(index, tunnel); break;
00112             case '.' : set(index, Point); break;
00113             case 'o' : set(index, energizer); break;
00114             case 'I' : set(index, prisonentry); break;
00115             case 'O' : set(index, prisonexit); break;
00116             case 'F' : set(index, fruithome); break;
00117             case 'P' : set(index, pacmanhome);  break;
00118             default  : if (buf[index] >= '0' && buf[index] <= '7') {
00119                            set(index, monsterhome, buf[index]-(uchar)'0');
00120                        }
00121         }
00122     }
00123 }
00124 
00125 bool Board::inBounds(int pos)
00126 {
00127   return ( pos < 0 || pos > sz-1 ? FALSE : TRUE);
00128 }
00129 
00130 void Board::set(int pos, Square sq, int m)
00131 {
00132     if (inBounds(pos))
00133         switch (sq) {
00134             case out         : at(pos) = OUT; break;
00135             case Point       : at(pos) |= pointBit; numPoints++; break;
00136             case tunnel      : at(pos) = sq;
00137                                for (int e = 0; e < numTunnels; e++) {           // if tunnel is already on board
00138                                    if (tunnelPosition[e] == pos)                // don't do it again.
00139                                        pos = OUT;
00140                                }
00141                                if (pos != OUT) {
00142                                    tunnelPosition[numTunnels] = pos;
00143                                    numTunnels++;
00144                                }
00145                                break;
00146             case energizer   : at(pos) |= energizerBit;
00147                                for (int e = 0; e < numEnergizers; e++) {
00148                                    if (energizerPosition[e] == pos)     
00149                                        pos = OUT;
00150                                }
00151                                if (pos != OUT) {
00152                                    energizerPosition[numEnergizers] = pos;
00153                                    numEnergizers++;
00154                                }
00155                                break;
00156             case fruit       : at(pos) |= fruitBit; fruitPosition = pos; break;
00157             case pacman      : at(pos) |= pacmanBit; pacmanPosition = pos; break;
00158             case monster     : at(pos) |= (monsterBit << m); 
00159                                monsterPosition[m] = pos; break;
00160             case prisonentry : prisonEntry = pos; at(pos) = empty; break;
00161             case prisonexit  : prisonExit = pos; at(pos) = empty; break;
00162             case fruithome   : fruitHome = pos; at(pos) = empty; break;
00163             case pacmanhome  : pacmanHome = pos; at(pos) = empty; break;
00164             case monsterhome : monsterHome[m] = pos; at(pos) = empty; 
00165                                if (m == 0 && prisonExit == OUT)
00166                                    prisonExit = pos;
00167                                if (m == 1 && prisonEntry == OUT)
00168                                    prisonEntry = pos;
00169                                numMonsters++;
00170                                break;
00171             default          : at(pos) = sq;
00172         }
00173 }
00174 
00175 void Board::reset(int pos, Square sq, int m)
00176 {
00177     bool found = FALSE;
00178     if (inBounds(pos))
00179         switch (sq) {
00180             case out       : at(pos) = empty; break;
00181             case Point     : at(pos) &= ~ pointBit; numPoints--; break;
00182             case energizer : at(pos) &= ~ energizerBit;
00183                              for (int e = 0; e < numEnergizers; e++) {          // delete the position of the eaten
00184                                  if (found)                                     // energizer in the position array
00185                                      energizerPosition[e-1] = energizerPosition[e];
00186                                  if (energizerPosition[e] == pos)               
00187                                      found = TRUE;
00188                              }
00189                              energizerPosition[numEnergizers--] = OUT;
00190                              break;
00191             case fruit     : at(pos) &= ~ fruitBit; fruitPosition = OUT; break;
00192             case pacman    : at(pos) &= ~ pacmanBit; pacmanPosition = OUT; break;
00193             case monster   : at(pos) &= ~ (monsterBit << m);
00194                              monsterPosition[m] = OUT; break;
00195             default        : at(pos) = at(pos) & varBits;
00196         }
00197 }
00198 
00199 int Board::position(Square sq, int m)
00200 {
00201     switch(sq) {
00202         case prisonentry  : return prisonEntry;
00203         case prisonexit   : return prisonExit;
00204         case fruit        : return fruitPosition;
00205         case fruithome    : return fruitHome;
00206         case pacman       : return pacmanPosition;
00207         case pacmanhome   : return pacmanHome;
00208         case monster      : return monsterPosition[m];
00209         case monsterhome  : return monsterHome[m];
00210         case energizer    : return energizerPosition[m];
00211         case tunnel       : return tunnelPosition[m];
00212         default           : return OUT;
00213     }
00214 }
00215 
00216 bool Board::isOut(int pos)
00217 {
00218     if (inBounds(pos))
00219         return (at(pos) == OUT ? TRUE : FALSE);
00220     return TRUE;
00221 }
00222 
00223 bool Board::isEmpty(int pos)
00224 {
00225     if (inBounds(pos))
00226         return ((at(pos) & fixBits) == empty ? TRUE : FALSE);
00227     return TRUE;
00228 }
00229 
00230 bool Board::isBrick(int pos)
00231 {
00232     if (inBounds(pos))
00233         return ((at(pos) & fixBits) == brick ? TRUE : FALSE);
00234     return FALSE;
00235 }
00236 
00237 bool Board::isPrison(int pos)
00238 {
00239     if (inBounds(pos))
00240         return ((at(pos) & fixBits) == prison ? TRUE : FALSE);
00241     return FALSE;
00242 }
00243 
00244 bool Board::isGate(int pos)
00245 {
00246     if (inBounds(pos))
00247         return ((at(pos) & fixBits) == gate ? TRUE : FALSE);
00248     return FALSE;
00249 }
00250 
00251 bool Board::isTunnel(int pos)
00252 {
00253     if (inBounds(pos))
00254         return ((at(pos) & fixBits) == tunnel ? TRUE : FALSE);
00255     return FALSE;
00256 }
00257 
00258 bool Board::isPoint(int pos)
00259 {
00260     if (inBounds(pos) && at(pos) != OUT)
00261         return ((at(pos) & pointBit) != 0 ? TRUE : FALSE);
00262     return FALSE;
00263 }
00264 
00265 bool Board::isEnergizer(int pos)
00266 {
00267     if (inBounds(pos) && at(pos) != OUT)
00268         return ((at(pos) & energizerBit) != 0 ? TRUE : FALSE);
00269     return FALSE;
00270 }
00271 
00272 bool Board::isFruit(int pos)
00273 {
00274     if (inBounds(pos) && at(pos) != OUT)
00275         return ((at(pos) & fruitBit) != 0 ? TRUE : FALSE);
00276     return FALSE;
00277 }
00278 
00279 bool Board::isPacman(int pos)
00280 {
00281     if (inBounds(pos) && at(pos) != OUT)
00282         return ((at(pos) & pacmanBit) != 0 ? TRUE : FALSE);
00283     return FALSE;
00284 }
00285 
00286 bool Board::isMonster(int pos)
00287 {
00288     if (inBounds(pos) && at(pos) != OUT)
00289         return ((at(pos) & monsterBits) != 0 ? TRUE : FALSE);
00290     return FALSE;
00291 }
00292 
00293 bool Board::isWay(int pos, int dir, Square sq) {
00294     int p1 = move(pos, dir, 2);
00295     if (p1 == OUT)
00296         return (sq == out ? TRUE : FALSE);
00297     int p2, p3;
00298     if (dir == N || dir == S) {
00299         p2 = move(p1, E);
00300         p3 = move(p1, W);
00301     } else {
00302         p2 = move(p1, N);
00303         p3 = move(p1, S);
00304     }
00305     switch (sq) {
00306         case out    : return isOut(p1) | isOut(p2) | isOut(p3); 
00307         case empty  : return isEmpty(p1) & isEmpty(p2) & isEmpty(p3);
00308         case brick  : return isBrick(p1) | isBrick(p2) | isBrick(p3);
00309         case prison : return isPrison(p1) | isPrison(p2) | isPrison(p3);
00310         case gate   : return isGate(p1) & isGate(p2) & isGate(p3);
00311         case tunnel : return isTunnel(p1) &
00312                              (isTunnel(p2) || isEmpty(p2)) &
00313                              (isTunnel(p3) || isEmpty(p3));
00314         default     : return FALSE;
00315     }
00316 }
00317 
00318 bool Board::isJump(int pos, int dir) {
00319     switch (dir) {
00320         case NW: return pos < BoardWidth || x(pos) == 0;
00321         case N:  return pos < BoardWidth;
00322         case NE: return pos < BoardWidth || x(pos) == BoardWidth-1;
00323         case W:  return x(pos) == 0;
00324         case E:  return x(pos) == BoardWidth-1;
00325         case SW: return pos >= sz-BoardWidth || x(pos) == 0;
00326         case S:  return pos >= sz-BoardWidth;
00327         case SE: return pos >= sz-BoardWidth || x(pos) == BoardWidth-1;
00328     }
00329     return FALSE;
00330 }
00331 
00332 int Board::move(int pos, int dir, int steps)
00333 {
00334     if (steps < 0) {                    // move backwards
00335         dir = turn(dir);                // turn around and do your steps
00336         steps *= -1;
00337     }
00338 
00339     while (steps-- != 0) {              // until all steps are gone
00340         switch (dir) {
00341             case NW: pos = pos >= BoardWidth && x(pos) > 0 ? (pos-BoardWidth)-1 : sz-1;
00342                      break;
00343             case N:  pos = pos >= BoardWidth ? pos-BoardWidth : (sz-BoardWidth)+x(pos);
00344                      break;
00345             case NE: pos = pos >= BoardWidth && x(pos) < BoardWidth-1 ?
00346                         (pos-BoardWidth)+1 : sz-BoardWidth;
00347                      break;
00348             case W:  pos = x(pos) > 0 ? pos-1 : pos+(BoardWidth-1);
00349                      break;
00350             case E:  pos = x(pos) < BoardWidth-1 ? pos+1 : pos-(BoardWidth-1);
00351                      break;
00352             case SW: pos = pos < sz-BoardWidth && x(pos) > 0 ? (pos+BoardWidth)-1 : BoardWidth-1;
00353                      break;
00354             case S:  pos = pos < sz-BoardWidth ? pos+BoardWidth : x(pos);
00355                      break;
00356             case SE: pos = pos < sz-BoardWidth && x(pos) < BoardWidth-1 ? (pos+BoardWidth)+1 : 0;
00357                      break;
00358         }
00359     }
00360     return pos;                         // here we are
00361 }
00362 
00363 int Board::closeup(int pos, int dir, int target)
00364 {
00365     if (dir == N || dir == S) {
00366         if (x(target) < x(pos))
00367             return W;
00368         if (x(target) > x(pos))
00369             return E;
00370     } else {
00371         if (y(target) < y(pos))
00372             return N;
00373         if (y(target) > y(pos))
00374             return S;
00375     }
00376     return dir;
00377 }
00378 
00379 int Board::x(int pos)
00380 {
00381     return pos % BoardWidth;
00382 }
00383 
00384 int Board::y(int pos)
00385 {
00386     return pos/BoardWidth;
00387 }
00388 
00389 int Board::turn(int dir)
00390 {
00391     switch (dir) {
00392         case N  : return S;
00393         case NE : return SW;
00394         case E  : return W;
00395         case SE : return NW;
00396         case S  : return N;
00397         case SW : return NE;
00398         case W  : return E;
00399         case NW : return SE;
00400         default : return dir;
00401     }
00402 }
00403 
00404 int Board::points()
00405 {
00406     return numPoints;
00407 }
00408 
00409 int Board::energizers()
00410 {
00411     return numEnergizers;
00412 }
00413 
00414 int Board::monsters()
00415 {
00416     return numMonsters;
00417 }
00418 
00419 int Board::tunnels()
00420 {
00421     return numTunnels;
00422 }

Generated on Sat Nov 5 16:17:20 2005 for OPIE by  doxygen 1.4.2