diff options
-rw-r--r-- | common/array.h | 73 | ||||
-rw-r--r-- | dists/macosx/scummvm_appcast.xml | 10 | ||||
-rw-r--r-- | engines/agi/graphics.cpp | 6 | ||||
-rw-r--r-- | engines/scumm/he/logic/moonbase_logic.cpp | 25 | ||||
-rw-r--r-- | engines/scumm/he/moonbase/ai_main.cpp | 4 | ||||
-rw-r--r-- | engines/scumm/he/moonbase/ai_main.h | 2 | ||||
-rw-r--r-- | engines/scumm/he/moonbase/ai_tree.cpp | 53 | ||||
-rw-r--r-- | engines/scumm/he/moonbase/ai_tree.h | 13 |
8 files changed, 143 insertions, 43 deletions
diff --git a/common/array.h b/common/array.h index db1a62ba34..869d79b68b 100644 --- a/common/array.h +++ b/common/array.h @@ -361,6 +361,79 @@ protected: }; +/** + * Double linked list with sorted nodes. + */ +template<class T> +class SortedArray : public Array<T> { +public: + typedef T *iterator; + typedef uint size_type; + + SortedArray(int (*comparator)(const void *, const void *)) { + _comparator = comparator; + } + + /** + * Inserts element at the sorted position. + */ + void insert(const T &element) { + T *where = (T *)bsearchMin(element, this->front(), this->_size, sizeof(T), _comparator); + insert(where, element); + } + + T &operator[](size_type idx) { + error("Operation not allowed with SortedArray"); + } + + void insert_at(size_type idx, const T &element) { + error("Operation not allowed with SortedArray"); + } + + void insert_at(size_type idx, const Array<T> &array) { + error("Operation not allowed with SortedArray"); + } + + void insert(iterator pos, const T &element) { + error("Operation not allowed with SortedArray"); + } + + void push_back(const T &element) { + error("Operation not allowed with SortedArray"); + } + + void push_back(const Array<T> &array) { + error("Operation not allowed with SortedArray"); + } + +private: + // Based on code Copyright (C) 2008-2009 Ksplice, Inc. + // Author: Tim Abbott <tabbott@ksplice.com> + // Licensed under GPLv2+ + void *bsearchMin(const void *key, const void *base, uint num, uint size, + int (*cmp)(const void *key, const void *elt)) { + uint start = 0, end = num; + int result; + + while (start < end) { + uint mid = start + (end - start) / 2; + + result = cmp(key, (byte *)base + mid * size); + if (result < 0) + end = mid; + else if (result > 0) + start = mid + 1; + else + return (void *)((byte *)base + mid * size); + } + + return (void *)((byte *)base + start * size); + } + +private: + int (*_comparator)(const void *, const void *); +}; + } // End of namespace Common #endif diff --git a/dists/macosx/scummvm_appcast.xml b/dists/macosx/scummvm_appcast.xml index 3d47c94bbc..35fbc54908 100644 --- a/dists/macosx/scummvm_appcast.xml +++ b/dists/macosx/scummvm_appcast.xml @@ -6,6 +6,16 @@ <description>Most recent changes with links to updates.</description> <language>en</language> <item> + <title>Version 1.8.1</title> + <sparkle:releaseNotesLink> + https://scummvm.org/frs/scummvm/1.8.1/ReleaseNotes + </sparkle:releaseNotesLink> + <pubDate>Wed, 25 May 2016 19:26:00 +0000</pubDate> + <enclosure url="https://www.scummvm.org/frs/scummvm/1.8.1/scummvm-1.8.1-macosx.dmg" + sparkle:version="1.8.1" length="15791070" type="application/octet-stream" + sparkle:dsaSignature="MC0CFQDF0u/pGH51pMPzCbsv07eCNxuGDQIUdrKWVTznbF69fzuzIieR4Lc0U2Y=" /> + </item> + <item> <title>Version 1.8.0</title> <sparkle:releaseNotesLink> https://scummvm.org/frs/scummvm/1.8.0/ReleaseNotes diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp index 6d3563a451..c7d643d6a0 100644 --- a/engines/agi/graphics.cpp +++ b/engines/agi/graphics.cpp @@ -1178,13 +1178,17 @@ void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte #define SHAKE_HORIZONTAL_PIXELS 4 // Sierra used some EGA port trickery to do it, we have to do it by copying pixels around +// +// Shaking locations: +// - Fanmade "Enclosure" right during the intro +// - Space Quest 2 almost right at the start when getting captured (after walking into the space ship) void GfxMgr::shakeScreen(int16 repeatCount) { int shakeNr, shakeCount; uint8 *blackSpace; int16 shakeHorizontalPixels = SHAKE_HORIZONTAL_PIXELS * (2 + _displayWidthMulAdjust); int16 shakeVerticalPixels = SHAKE_VERTICAL_PIXELS * (1 + _displayHeightMulAdjust); - if ((blackSpace = (uint8 *)calloc(shakeVerticalPixels * _displayScreenWidth, 1)) == NULL) + if ((blackSpace = (uint8 *)calloc(shakeHorizontalPixels * _displayScreenWidth, 1)) == NULL) return; shakeCount = repeatCount * 8; // effectively 4 shakes per repeat diff --git a/engines/scumm/he/logic/moonbase_logic.cpp b/engines/scumm/he/logic/moonbase_logic.cpp index a32356614f..d5100cef71 100644 --- a/engines/scumm/he/logic/moonbase_logic.cpp +++ b/engines/scumm/he/logic/moonbase_logic.cpp @@ -23,6 +23,7 @@ #include "scumm/he/intern_he.h" #include "scumm/he/logic_he.h" #include "scumm/he/moonbase/moonbase.h" +#include "scumm/he/moonbase/ai_main.h" namespace Scumm { @@ -48,7 +49,7 @@ private: int op_set_fow_image(int op, int numArgs, int32 *args); void op_ai_test_kludge(int op, int numArgs, int32 *args); - void op_ai_master_control_program(int op, int numArgs, int32 *args); + int op_ai_master_control_program(int op, int numArgs, int32 *args); void op_ai_reset(int op, int numArgs, int32 *args); void op_ai_set_type(int op, int numArgs, int32 *args); void op_ai_clean_up(int op, int numArgs, int32 *args); @@ -137,14 +138,12 @@ int32 LogicHEmoonbase::dispatch(int op, int numArgs, int32 *args) { break; case OP_SET_FOW_IMAGE: return op_set_fow_image(op, numArgs, args); - break; case OP_AI_TEST_KLUDGE: op_ai_test_kludge(op, numArgs, args); break; case OP_AI_MASTER_CONTROL_PROGRAM: - op_ai_master_control_program(op, numArgs, args); - break; + return op_ai_master_control_program(op, numArgs, args); case OP_AI_RESET: op_ai_reset(op, numArgs, args); break; @@ -226,24 +225,24 @@ void LogicHEmoonbase::op_ai_test_kludge(int op, int numArgs, int32 *args) { LogicHE::dispatch(op, numArgs, args); } -void LogicHEmoonbase::op_ai_master_control_program(int op, int numArgs, int32 *args) { - warning("STUB: op_ai_master_control_program()"); - LogicHE::dispatch(op, numArgs, args); +int LogicHEmoonbase::op_ai_master_control_program(int op, int numArgs, int32 *args) { + warning("op_ai_master_control_program()"); + return masterControlProgram(numArgs, args); } void LogicHEmoonbase::op_ai_reset(int op, int numArgs, int32 *args) { - warning("STUB: op_ai_reset)"); - LogicHE::dispatch(op, numArgs, args); + warning("op_ai_reset())"); + resetAI(_vm); } void LogicHEmoonbase::op_ai_set_type(int op, int numArgs, int32 *args) { - warning("STUB: op_ai_set_type()"); - LogicHE::dispatch(op, numArgs, args); + warning("op_ai_set_type()"); + setAIType(numArgs, args); } void LogicHEmoonbase::op_ai_clean_up(int op, int numArgs, int32 *args) { - warning("STUB: op_ai_clean_up()"); - LogicHE::dispatch(op, numArgs, args); + warning("op_ai_clean_up()"); + cleanUpAI(); } LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) { diff --git a/engines/scumm/he/moonbase/ai_main.cpp b/engines/scumm/he/moonbase/ai_main.cpp index 1a191a1328..6844d2f7dd 100644 --- a/engines/scumm/he/moonbase/ai_main.cpp +++ b/engines/scumm/he/moonbase/ai_main.cpp @@ -168,7 +168,9 @@ const int *MCP_params; Common::Array<int> lastXCoord[5]; Common::Array<int> lastYCoord[5]; -void resetAI() { +void resetAI(ScummEngine_v90he *vm) { + _vm = vm; + AIstate = STATE_CHOOSE_BEHAVIOR; warning("----------------------> Resetting AI"); diff --git a/engines/scumm/he/moonbase/ai_main.h b/engines/scumm/he/moonbase/ai_main.h index 4937eced0f..7b5ad3ca40 100644 --- a/engines/scumm/he/moonbase/ai_main.h +++ b/engines/scumm/he/moonbase/ai_main.h @@ -86,7 +86,7 @@ enum { static int energyHogType = 0; -void resetAI(); +void resetAI(ScummEngine_v90he *vm); void cleanUpAI(); void setAIType(const int paramCount, const int *params); int masterControlProgram(const int paramCount, const int *params); diff --git a/engines/scumm/he/moonbase/ai_tree.cpp b/engines/scumm/he/moonbase/ai_tree.cpp index efbf3e3a99..7bd44f6644 100644 --- a/engines/scumm/he/moonbase/ai_tree.cpp +++ b/engines/scumm/he/moonbase/ai_tree.cpp @@ -25,10 +25,16 @@ namespace Scumm { +static int compareTreeNodes(const void *a, const void *b) { + return ((const TreeNode *)a)->value - ((const TreeNode *)b)->value; +} + Tree::Tree() { pBaseNode = new Node; _maxDepth = MAX_DEPTH; _maxNodes = MAX_NODES; + + _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes); } Tree::Tree(IContainedObject *contents) { @@ -36,6 +42,8 @@ Tree::Tree(IContainedObject *contents) { pBaseNode->setContainedObject(contents); _maxDepth = MAX_DEPTH; _maxNodes = MAX_NODES; + + _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes); } Tree::Tree(IContainedObject *contents, int maxDepth) { @@ -43,6 +51,8 @@ Tree::Tree(IContainedObject *contents, int maxDepth) { pBaseNode->setContainedObject(contents); _maxDepth = maxDepth; _maxNodes = MAX_NODES; + + _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes); } Tree::Tree(IContainedObject *contents, int maxDepth, int maxNodes) { @@ -50,6 +60,8 @@ Tree::Tree(IContainedObject *contents, int maxDepth, int maxNodes) { pBaseNode->setContainedObject(contents); _maxDepth = maxDepth; _maxNodes = maxNodes; + + _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes); } void Tree::duplicateTree(Node *sourceNode, Node *destNode) { @@ -68,6 +80,7 @@ Tree::Tree(const Tree *sourceTree) { pBaseNode = new Node(sourceTree->getBaseNode()); _maxDepth = sourceTree->getMaxDepth(); _maxNodes = sourceTree->getMaxNodes(); + _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes); duplicateTree(sourceTree->getBaseNode(), pBaseNode); } @@ -80,7 +93,6 @@ Tree::~Tree() { while (pNodeItr != NULL) { // If any children are left, move to one of them if (!(pNodeItr->getChildren().empty())) { - //int size = (pNodeItr->getChildren()).size(); pNodeItr = pNodeItr->popChild(); } else { // Delete this node, and move up to the parent for further processing @@ -90,13 +102,12 @@ Tree::~Tree() { pTemp = NULL; } } -} + delete _currentMap; +} Node *Tree::aStarSearch() { - return NULL; -#if 0 - fnpMMap mmfpOpen; + Common::SortedArray<TreeNode *> mmfpOpen(compareTreeNodes); Node *currentNode = NULL; float currentT; @@ -106,24 +117,24 @@ Node *Tree::aStarSearch() { float temp = pBaseNode->getContainedObject()->calcT(); if (static_cast<int>(temp) != SUCCESS) { - - mmfpOpen.insert(fnpMMap::value_type(pBaseNode->getObjectT(), pBaseNode)); + mmfpOpen.insert(new TreeNode(pBaseNode->getObjectT(), pBaseNode)); while (mmfpOpen.size() && (retNode == NULL)) { - currentNode = mmfpOpen.begin()->second; + currentNode = mmfpOpen.front()->node; mmfpOpen.erase(mmfpOpen.begin()); if ((currentNode->getDepth() < _maxDepth) && (Node::getNodeCount() < _maxNodes)) { // Generate nodes - int numChildren = currentNode->generateChildren(); Common::Array<Node *> vChildren = currentNode->getChildren(); for (Common::Array<Node *>::iterator i = vChildren.begin(); i != vChildren.end(); i++) { IContainedObject *pTemp = (*i)->getContainedObject(); currentT = pTemp->calcT(); - if (currentT == SUCCESS) retNode = *i; - else mmfpOpen.insert(fnpMMap::value_type(currentT, (*i))); + if (currentT == SUCCESS) + retNode = *i; + else + mmfpOpen.insert(new TreeNode(currentT, (*i))); } } else { retNode = currentNode; @@ -134,7 +145,6 @@ Node *Tree::aStarSearch() { } return retNode; -#endif } @@ -146,8 +156,7 @@ Node *Tree::aStarSearch_singlePassInit() { float temp = pBaseNode->getContainedObject()->calcT(); if (static_cast<int>(temp) != SUCCESS) { - //_currentMap.insert(fnpMMap::value_type(pBaseNode->getObjectT(), pBaseNode)); - //assert(_currentMap.size()); + _currentMap->insert(new TreeNode(pBaseNode->getObjectT(), pBaseNode)); } else { retNode = pBaseNode; } @@ -157,10 +166,9 @@ Node *Tree::aStarSearch_singlePassInit() { Node *Tree::aStarSearch_singlePass(Node **currentNode) { currentNode = NULL; + float currentT; Node *retNode = NULL; -#if 0 - float currentT; static int maxTime = 0; if (currentChildIndex == 1) { @@ -168,13 +176,13 @@ Node *Tree::aStarSearch_singlePass(Node **currentNode) { } if (currentChildIndex) { - if (!(_currentMap.size())) { + if (!(_currentMap->size())) { retNode = _currentNode; return retNode; } - _currentNode = _currentMap.begin()->second; - _currentMap.erase(_currentMap.begin()); + _currentNode = _currentMap->front()->node; + _currentMap->erase(_currentMap->begin()); } if ((_currentNode->getDepth() < _maxDepth) && (Node::getNodeCount() < _maxNodes) && ((!maxTime) || (getTimerValue(3) < maxTime))) { @@ -184,7 +192,7 @@ Node *Tree::aStarSearch_singlePass(Node **currentNode) { if (currentChildIndex) { Common::Array<Node *> vChildren = _currentNode->getChildren(); - if (!vChildren.size() && !_currentMap.size()) { + if (!vChildren.size() && !_currentMap->size()) { currentChildIndex = 0; retNode = _currentNode; } @@ -197,11 +205,11 @@ Node *Tree::aStarSearch_singlePass(Node **currentNode) { retNode = *i; i = vChildren.end() - 1; } else { - _currentMap.insert(fnpMMap::value_type(currentT, (*i))); + _currentMap->insert(new TreeNode(currentT, (*i))); } } - if (!(_currentMap.size()) && (currentT != SUCCESS)) { + if (!(_currentMap->size()) && (currentT != SUCCESS)) { assert(_currentNode != NULL); retNode = _currentNode; } @@ -209,7 +217,6 @@ Node *Tree::aStarSearch_singlePass(Node **currentNode) { } else { retNode = _currentNode; } -#endif return retNode; } diff --git a/engines/scumm/he/moonbase/ai_tree.h b/engines/scumm/he/moonbase/ai_tree.h index 1097665a7a..908786ad9a 100644 --- a/engines/scumm/he/moonbase/ai_tree.h +++ b/engines/scumm/he/moonbase/ai_tree.h @@ -23,16 +23,21 @@ #ifndef SCUMM_HE_MOONBASE_AI_TREE_H #define SCUMM_HE_MOONBASE_AI_TREE_H -#include "common/hash-str.h" +#include "common/array.h" #include "scumm/he/moonbase/ai_node.h" namespace Scumm { -//typedef std::multimap< float, Node *, std::less<float> > fnpMMap; - const int MAX_DEPTH = 100; const int MAX_NODES = 1000000; +struct TreeNode { + float value; + Node *node; + + TreeNode(float v, Node *n) { value = v; node = n; } +}; + class Tree { private: Node *pBaseNode; @@ -42,7 +47,7 @@ private: int currentChildIndex; - Common::StringMap _currentMap; + Common::SortedArray<TreeNode *> *_currentMap; Node *_currentNode; public: |