Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

scene.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/kyra/scene.cpp $
 * $Id: scene.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */

#include "kyra/kyra.h"
#include "kyra/screen.h"

namespace Kyra {

int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
      debugC(9, kDebugLevelMain, "KyraEngine::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize);
      x &= 0xFFFC; toX &= 0xFFFC;
      y &= 0xFFFE; toY &= 0xFFFE;
      x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY;
      
      if (x == toY && y == toY) {
            moveTable[0] = 8;
            return 0;
      }
      
      int curX = x;
      int curY = y;
      int tempValue = 0;
      int lastUsedEntry = 0;
      int *pathTable1 = new int[0x7D0];
      int *pathTable2 = new int[0x7D0];
      assert(pathTable1 && pathTable2);
      
      while (true) {
            int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
            changePosTowardsFacing(curX, curY, newFacing);

            if (curX == toX && curY == toY) {
                  if (!lineIsPassable(curX, curY))
                        break;
                  moveTable[lastUsedEntry++] = newFacing;
                  break;
            }

            if (lineIsPassable(curX, curY)) {
                  if (lastUsedEntry == moveTableSize) {
                        delete [] pathTable1;
                        delete [] pathTable2;
                        return 0x7D00;
                  }
                  // debug drawing
                  /*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
                        screen()->setPagePixel(0, curX, curY, 11);
                        screen()->updateScreen();
                        //waitTicks(5);
                  }*/
                  moveTable[lastUsedEntry++] = newFacing;
                  x = curX;
                  y = curY;
                  continue;
            }

            int temp = 0;
            while (true) {
                  newFacing = getFacingFromPointToPoint(curX, curY, toX, toY);
                  changePosTowardsFacing(curX, curY, newFacing);
                  // debug drawing
                  /*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
                        screen()->setPagePixel(0, curX, curY, 8);
                        screen()->updateScreen();
                        //waitTicks(5);
                  }*/
                  
                  if (!lineIsPassable(curX, curY)) {
                        if (curX != toX || curY != toY)
                              continue;
                  }

                  if (curX == toX && curY == toY) {
                        if (!lineIsPassable(curX, curY)) {
                              tempValue = 0;
                              temp = 0;
                              break;
                        }
                  }
                  
                  temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0);
                  tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0);
                  if (curX == toX && curY == toY) {
                        if (temp == 0x7D00 && tempValue == 0x7D00) {
                              delete [] pathTable1;
                              delete [] pathTable2;
                              return 0x7D00;
                        }
                  }
                  
                  if (temp != 0x7D00 || tempValue != 0x7D00)
                        break;
            }
            
            if (temp < tempValue) {
                  if (lastUsedEntry + temp > moveTableSize) {
                        delete [] pathTable1;
                        delete [] pathTable2;
                        return 0x7D00;
                  }
                  memcpy(&moveTable[lastUsedEntry], pathTable1, temp*sizeof(int));
                  lastUsedEntry += temp;
            } else {
                  if (lastUsedEntry + tempValue > moveTableSize) {
                        delete [] pathTable1;
                        delete [] pathTable2;
                        return 0x7D00;
                  }
                  memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue*sizeof(int));
                  lastUsedEntry += tempValue;
            }
            x = curX;
            y = curY;
            if (curX == toX && curY == toY)
                  break;
      }

      delete [] pathTable1;
      delete [] pathTable2;
      moveTable[lastUsedEntry] = 8;
      return lastUsedEntry;
}

int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) {
      debugC(9, kDebugLevelMain, "KyraEngine::findSubPath(%d, %d, %d, %d, %p, %d, %d)", x, y, toX, toY, (const void *)moveTable, start, end);
      // only used for debug specific code
      //static uint16 unkTable[] = { 8, 5 };
      static const int8 facingTable1[] = {  7,  0,  1,  2,  3,  4,  5,  6,  1,  2,  3,  4,  5,  6,  7,  0 };
      static const int8 facingTable2[] = { -1,  0, -1,  2, -1,  4, -1,  6, -1,  2, -1,  4, -1,  6, -1,  0 };
      static const int8 facingTable3[] = {  2,  4,  4,  6,  6,  0,  0,  2,  6,  6,  0,  0,  2,  2,  4,  4 };
      static const int8 addPosTableX[] = { -1,  0, -1,  4, -1,  0, -1, -4, -1, -4, -1,  0, -1,  4, -1,  0 };
      static const int8 addPosTableY[] = { -1,  2, -1,  0, -1, -2, -1,  0, -1,  0, -1,  2, -1,  0, -1, -2 };
      
      // debug specific
      /*++unkTable[start];
      while (screen()->getPalette(0)[unkTable[start]] != 0x0F) {
            ++unkTable[start];
      }*/
      
      int xpos1 = x, xpos2 = x;
      int ypos1 = y, ypos2 = y;
      int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
      int position = 0;
      
      while (position != end) {
            int newFacing2 = newFacing;
            while (true) {
                  changePosTowardsFacing(xpos1, ypos1, facingTable1[start*8 + newFacing2]);
                  if (!lineIsPassable(xpos1, ypos1)) {
                        if (facingTable1[start*8 + newFacing2] == newFacing)
                              return 0x7D00;
                        newFacing2 = facingTable1[start*8 + newFacing2];
                        xpos1 = x;
                        ypos1 = y;
                        continue;
                  }
                  newFacing = facingTable1[start*8 + newFacing2];
                  break;
            }
            // debug drawing
            /*if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) {
                  screen()->setPagePixel(0, xpos1, ypos1, unkTable[start]);
                  screen()->updateScreen();
                  //waitTicks(5);
            }*/
            if (newFacing & 1) {
                  int temp = xpos1 + addPosTableX[newFacing + start * 8];
                  if (toX == temp) {
                        temp = ypos1 + addPosTableY[newFacing + start * 8];
                        if (toY == temp) {
                              moveTable[position++] = facingTable2[newFacing + start * 8];
                              return position;
                        }
                  }
            }

            moveTable[position++] = newFacing;
            x = xpos1;
            y = ypos1;

            if (x == toX && y == toY)
                  return position;
            
            if (xpos1 == xpos2 && ypos1 == ypos2)
                  break;

            newFacing = facingTable3[start*8 + newFacing];
      }

      return 0x7D00;
}

int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) {
      debugC(9, kDebugLevelMain, "KyraEngine::getFacingFromPointToPoint(%d, %d, %d, %d)", x, y, toX, toY);
      static const int facingTable[] = {
            1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6
      };
      
      int facingEntry = 0;
      int ydiff = y - toY;
      if (ydiff < 0) {
            ++facingEntry;
            ydiff = -ydiff;
      }     
      facingEntry <<= 1;
      
      int xdiff = toX - x;
      if (xdiff < 0) {
            ++facingEntry;
            xdiff = -xdiff;
      }
      
      if (xdiff >= ydiff) {
            int temp = ydiff;
            ydiff = xdiff;
            xdiff = temp;

            facingEntry <<= 1;
      } else {
            facingEntry <<= 1;
            facingEntry += 1;
      }
      int temp = (ydiff + 1) >> 1;
      
      if (xdiff < temp) {
            facingEntry <<= 1;
            facingEntry += 1;
      } else {
            facingEntry <<= 1;
      }

      assert(facingEntry < ARRAYSIZE(facingTable));
      return facingTable[facingEntry];
}


int KyraEngine::getOppositeFacingDirection(int dir) {
      debugC(9, kDebugLevelMain, "KyraEngine::getOppositeFacingDirection(%d)", dir);
      switch (dir) {
      case 0:
            return 2;
      case 1:
            return 1;
      case 3:
            return 7;
      case 4:
            return 6;
      case 5:
            return 5;
      case 6:
            return 4;
      case 7:
            return 3;
      default:
            break;
      }
      return 0;
}

void KyraEngine::changePosTowardsFacing(int &x, int &y, int facing) {
      debugC(9, kDebugLevelMain, "KyraEngine::changePosTowardsFacing(%d, %d, %d)", x, y, facing);
      x += _addXPosTable[facing];
      y += _addYPosTable[facing];
}

int KyraEngine::getMoveTableSize(int *moveTable) {
      debugC(9, kDebugLevelMain, "KyraEngine::getMoveTableSize(%p)", (const void *)moveTable);
      int retValue = 0;
      if (moveTable[0] == 8)
            return 0;
      
      static const int facingTable[] = {
            4, 5, 6, 7, 0, 1, 2, 3
      };
      static const int unkTable[] = {
            -1, -1,  1,  2, -1,  6,  7, -1,
            -1, -1, -1, -1,  2, -1,  0, -1,
             1, -1, -1, -1,  3,  4, -1,  0,
             2, -1, -1, -1, -1, -1,  4, -1,
            -1,  2,  3, -1, -1, -1,  5,  6,
             6, -1,  4, -1, -1, -1, -1, -1,
             7,  0, -1,  4,  5, -1, -1, -1,
            -1, -1,  0, -1,  6, -1, -1, -1
      };
      
      int *oldPosition = moveTable;
      int *tempPosition = moveTable;
      int *curPosition = moveTable + 1;
      retValue = 1;

      while (*curPosition != 8) {
            if (*oldPosition == facingTable[*curPosition]) {
                  retValue -= 2;
                  *oldPosition = 9;
                  *curPosition = 9;
                  
                  while (tempPosition != moveTable) {
                        --tempPosition;
                        if (*tempPosition != 9)
                              break;
                  }
                  
                  if (tempPosition == moveTable && *tempPosition == 9) {
                        while (*tempPosition != 8 && *tempPosition == 9)
                              ++tempPosition;

                        if (*tempPosition == 8)
                              return 0;
                  }
                  
                  oldPosition = tempPosition;
                  curPosition = oldPosition+1;

                  while (*curPosition != 8 && *curPosition == 9)
                        ++curPosition;

                  continue;
            }
            
            if (unkTable[*curPosition+((*oldPosition)*8)] != -1) {
                  --retValue;
                  *oldPosition = unkTable[*curPosition+((*oldPosition)*8)];
                  *curPosition = 9;
                  
                  if (tempPosition != oldPosition) {
                        curPosition = oldPosition;
                        oldPosition = tempPosition;
                        while (true) {
                              if (tempPosition == moveTable)
                                    break;

                              --tempPosition;
                              if (*tempPosition != 9)
                                    break;

                        }
                  } else {
                        while (true) {
                              ++curPosition;
                              if (*curPosition != 9)
                                    break;
                        }
                  }
                  continue;
            }
            
            tempPosition = oldPosition;
            oldPosition = curPosition;
            ++retValue;

            while (true) {
                  ++curPosition;
                  if (*curPosition != 9)
                        break;
            }
      }

      return retValue;
}

} // end of namespace Kyra

Generated by  Doxygen 1.6.0   Back to index