Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+845
@@ -0,0 +1,845 @@
|
||||
#include "munga.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "tree.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeNode ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// TreeNode
|
||||
//###########################################################################
|
||||
//
|
||||
TreeNode::TreeNode(
|
||||
Tree *tree,
|
||||
Plug *plug
|
||||
):
|
||||
Link(tree, plug)
|
||||
{
|
||||
less = NULL;
|
||||
greater = NULL;
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// ~TreeNode
|
||||
//###########################################################################
|
||||
//
|
||||
TreeNode::~TreeNode()
|
||||
{
|
||||
Tree *tree = Cast_Object(Tree*, socket);
|
||||
|
||||
Check(this);
|
||||
Check(tree);
|
||||
|
||||
//
|
||||
//-------------------------------------------
|
||||
// Notify iterators that deletion is occuring
|
||||
//-------------------------------------------
|
||||
//
|
||||
tree->SendIteratorMemo(PlugRemoved, this);
|
||||
|
||||
//
|
||||
//-----------------------------------
|
||||
// Tell the tree to release this node
|
||||
//-----------------------------------
|
||||
//
|
||||
tree->SeverFromTreeNode(this);
|
||||
|
||||
//
|
||||
//------------------------------------------
|
||||
// Remove this link from any plug references
|
||||
//------------------------------------------
|
||||
//
|
||||
ReleaseFromPlug();
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------
|
||||
// Tell the node to release this link. Note that this link
|
||||
// is not referenced by the plug or the chain at this point in
|
||||
// time.
|
||||
//-------------------------------------------------------------
|
||||
//
|
||||
if (tree->GetReleaseNode() != NULL)
|
||||
{
|
||||
Check(tree->GetReleaseNode());
|
||||
tree->GetReleaseNode()->ReleaseLinkHandler(tree, plug);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// TestInstance
|
||||
//###########################################################################
|
||||
//
|
||||
Logical
|
||||
TreeNode::TestInstance() const
|
||||
{
|
||||
Link::TestInstance();
|
||||
|
||||
if (less != NULL)
|
||||
{
|
||||
Check_Signature(less);
|
||||
}
|
||||
if (greater != NULL)
|
||||
{
|
||||
Check_Signature(greater);
|
||||
}
|
||||
if (parent != NULL)
|
||||
{
|
||||
Check_Signature(parent);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// SetupTreeLinks
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
TreeNode::SetupTreeLinks(
|
||||
TreeNode *less,
|
||||
TreeNode *greater,
|
||||
TreeNode *parent
|
||||
)
|
||||
{
|
||||
this->less = less;
|
||||
this->greater = greater;
|
||||
this->parent = parent;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tree ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// Tree
|
||||
//###########################################################################
|
||||
//
|
||||
Tree::Tree(
|
||||
Node *node,
|
||||
Logical has_unique_entries
|
||||
):
|
||||
SortedSocket(node, has_unique_entries)
|
||||
{
|
||||
root = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// ~Tree
|
||||
//###########################################################################
|
||||
//
|
||||
Tree::~Tree()
|
||||
{
|
||||
SetReleaseNode(NULL);
|
||||
while (root != NULL)
|
||||
{
|
||||
Unregister_Object(root);
|
||||
delete root;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// TestInstance
|
||||
//###########################################################################
|
||||
//
|
||||
Logical
|
||||
Tree::TestInstance() const
|
||||
{
|
||||
SortedSocket::TestInstance();
|
||||
|
||||
//
|
||||
// Check root if not null
|
||||
//
|
||||
if (root != NULL)
|
||||
{
|
||||
Check(root);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// AddImplementation
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
Tree::AddImplementation(
|
||||
Plug *plug
|
||||
)
|
||||
{
|
||||
AddValueImplementation(plug, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// AddValueImplementation
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
Tree::AddValueImplementation(
|
||||
Plug *plug,
|
||||
const void *value
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(plug);
|
||||
|
||||
/*
|
||||
* Verify that value has not been added
|
||||
*/
|
||||
Verify(HasUniqueEntries() ? SearchForValue(value) == NULL : (Logical)True);
|
||||
|
||||
/*
|
||||
* Make new tree node
|
||||
*/
|
||||
TreeNode *node;
|
||||
|
||||
node = MakeTreeNode(plug, value);
|
||||
Register_Object(node);
|
||||
|
||||
/*
|
||||
* Add to the tree and send iterators memo to
|
||||
* update pointers
|
||||
*/
|
||||
AddTreeNode(node);
|
||||
SendIteratorMemo(PlugAdded, node);
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// FindImplementation
|
||||
//###########################################################################
|
||||
//
|
||||
Plug*
|
||||
Tree::FindImplementation(
|
||||
const void *value
|
||||
)
|
||||
{
|
||||
TreeNode *node;
|
||||
|
||||
if ((node = SearchForValue(value)) != NULL)
|
||||
{
|
||||
Check(node);
|
||||
return node->GetPlug();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// MakeTreeNode
|
||||
//###########################################################################
|
||||
//
|
||||
TreeNode*
|
||||
Tree::MakeTreeNode(
|
||||
Plug*,
|
||||
const void*
|
||||
)
|
||||
{
|
||||
Fail("Tree::MakeTreeNode - Shoule never reach here");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// CompareTreeNodes
|
||||
//###########################################################################
|
||||
//
|
||||
int
|
||||
Tree::CompareTreeNodes(
|
||||
TreeNode*,
|
||||
TreeNode*
|
||||
)
|
||||
{
|
||||
Fail("Tree::CompareTreeNodes - Shoule never reach here");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// CompareValueToTreeNode
|
||||
//###########################################################################
|
||||
//
|
||||
int
|
||||
Tree::CompareValueToTreeNode(
|
||||
const void*,
|
||||
TreeNode*
|
||||
)
|
||||
{
|
||||
Fail("Tree::CompareValueToTreeNode - Shoule never reach here");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// AddTreeNode
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
Tree::AddTreeNode(
|
||||
TreeNode *newNode
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(newNode);
|
||||
|
||||
/*
|
||||
* If root is NULL this is the first item
|
||||
*/
|
||||
if (root == NULL)
|
||||
{
|
||||
newNode->SetupTreeLinks(NULL, NULL, NULL);
|
||||
root = newNode;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for insertion point
|
||||
*/
|
||||
TreeNode *node;
|
||||
|
||||
node = root;
|
||||
while (node != NULL)
|
||||
{
|
||||
Check(node);
|
||||
|
||||
if (CompareTreeNodes(newNode, node) < 0)
|
||||
{
|
||||
if (node->less == NULL)
|
||||
{
|
||||
newNode->SetupTreeLinks(NULL, NULL, node);
|
||||
node->less = newNode;
|
||||
break;
|
||||
}
|
||||
else
|
||||
node = node->less;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node->greater == NULL)
|
||||
{
|
||||
newNode->SetupTreeLinks(NULL, NULL, node);
|
||||
node->greater = newNode;
|
||||
break;
|
||||
}
|
||||
else
|
||||
node = node->greater;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// SeverFromTreeNode
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
Tree::SeverFromTreeNode(
|
||||
TreeNode *node
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(node);
|
||||
|
||||
if (node->greater == NULL)
|
||||
{
|
||||
if (node->less == NULL)
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
// The node has no subtrees
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
if (node == root)
|
||||
{
|
||||
//
|
||||
// Tree is now empty, set root to null
|
||||
//
|
||||
root = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Set appropiate branch to NULL
|
||||
//
|
||||
Check(node->parent);
|
||||
if (node->parent->less == node)
|
||||
node->parent->less = NULL;
|
||||
else
|
||||
node->parent->greater = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
// The node has a less subtree
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
Check(node->less);
|
||||
|
||||
if (node == root)
|
||||
{
|
||||
//
|
||||
// Node is root... Set subtree to new root
|
||||
//
|
||||
root = node->less;
|
||||
node->less->parent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Node is not root
|
||||
// Set parents pointer to subtree
|
||||
//
|
||||
Check( node->parent );
|
||||
if (node->parent->less == node)
|
||||
{
|
||||
node->parent->less = node->less;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->parent->greater = node->less;
|
||||
}
|
||||
//
|
||||
// Set subtree parent to node parent
|
||||
//
|
||||
node->less->parent = node->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node->less == NULL)
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
// The node has a greater subtree
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
Check( node->greater );
|
||||
if (node == root)
|
||||
{
|
||||
//
|
||||
// Node is root
|
||||
// Set subtree to new root
|
||||
//
|
||||
root = node->greater;
|
||||
//
|
||||
// Set new root to have null parent
|
||||
//
|
||||
node->greater->parent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Node is not root
|
||||
// Set parents pointer to subtree
|
||||
//
|
||||
Check( node->parent );
|
||||
if (node->parent->less == node)
|
||||
node->parent->less = node->greater;
|
||||
else
|
||||
node->parent->greater = node->greater;
|
||||
//
|
||||
// Set subtree parent to node parent
|
||||
//
|
||||
node->greater->parent = node->parent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
// The node has lesser and greater sub-trees
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
TreeNode *successor;
|
||||
|
||||
Check(node->less);
|
||||
Check(node->greater);
|
||||
|
||||
successor = node->greater;
|
||||
while (successor->less != NULL)
|
||||
{
|
||||
successor = successor->less;
|
||||
Check(successor);
|
||||
}
|
||||
|
||||
//
|
||||
// Set successor's parent to subtree
|
||||
//
|
||||
Check(successor->parent);
|
||||
if (successor->parent->less == successor)
|
||||
successor->parent->less = successor->greater;
|
||||
else
|
||||
successor->parent->greater = successor->greater;
|
||||
|
||||
//
|
||||
// Set successor's subtree to parent
|
||||
//
|
||||
if (successor->greater != NULL)
|
||||
{
|
||||
Check(successor->greater);
|
||||
successor->greater->parent = successor->parent;
|
||||
}
|
||||
|
||||
//
|
||||
// Place at node
|
||||
//
|
||||
successor->parent = node->parent;
|
||||
successor->less = node->less;
|
||||
successor->greater = node->greater;
|
||||
|
||||
if (root == node)
|
||||
{
|
||||
//
|
||||
// Node was root
|
||||
//
|
||||
root = successor;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Set nodes parent to successor
|
||||
//
|
||||
Check(successor->parent);
|
||||
if (successor->parent->less == node)
|
||||
successor->parent->less = successor;
|
||||
else
|
||||
successor->parent->greater = successor;
|
||||
}
|
||||
|
||||
//
|
||||
// Set subtrees parent to successor
|
||||
//
|
||||
if (successor->greater != NULL)
|
||||
{
|
||||
Check(successor->greater);
|
||||
successor->greater->parent = successor;
|
||||
}
|
||||
if (successor->less != NULL)
|
||||
{
|
||||
Check(successor->less);
|
||||
successor->less->parent = successor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// SearchForValue
|
||||
//###########################################################################
|
||||
//
|
||||
TreeNode*
|
||||
Tree::SearchForValue(
|
||||
const void *value
|
||||
)
|
||||
{
|
||||
TreeNode *node;
|
||||
int ret;
|
||||
|
||||
node = root;
|
||||
while (node != NULL)
|
||||
{
|
||||
Check(node);
|
||||
if ((ret = CompareValueToTreeNode(value, node)) == 0)
|
||||
break;
|
||||
node = (ret < 0) ? node->less : node->greater;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// TreeIterator
|
||||
//###########################################################################
|
||||
//
|
||||
TreeIterator::TreeIterator(Tree *tree):
|
||||
SortedIterator(tree)
|
||||
{
|
||||
First();
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
//###########################################################################
|
||||
//
|
||||
TreeIterator::~TreeIterator()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// TestInstance
|
||||
//###########################################################################
|
||||
//
|
||||
Logical
|
||||
TreeIterator::TestInstance() const
|
||||
{
|
||||
SortedIterator::TestInstance();
|
||||
|
||||
if (currentNode != NULL)
|
||||
{
|
||||
Check(currentNode);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// First
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
TreeIterator::First()
|
||||
{
|
||||
TreeNode *node;
|
||||
|
||||
node = Cast_Object(Tree*, socket)->root;
|
||||
if (node != NULL)
|
||||
{
|
||||
Check(node);
|
||||
while (node->less != NULL)
|
||||
{
|
||||
node = node->less;
|
||||
Check(node);
|
||||
}
|
||||
}
|
||||
currentNode = node;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// Last
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
TreeIterator::Last()
|
||||
{
|
||||
//
|
||||
// Should never reach here
|
||||
//
|
||||
#ifdef __BCPLUSPLUS__
|
||||
#pragma warn -ccc
|
||||
Verify(False);
|
||||
#pragma warn +ccc
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// Next
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
TreeIterator::Next()
|
||||
{
|
||||
TreeNode *node;
|
||||
|
||||
if ((node = currentNode) == NULL)
|
||||
return;
|
||||
|
||||
Check(node);
|
||||
if (node->greater != NULL)
|
||||
{
|
||||
node = node->greater;
|
||||
Check(node);
|
||||
while (node->less != NULL)
|
||||
{
|
||||
node = node->less;
|
||||
Check(node);
|
||||
}
|
||||
currentNode = node;
|
||||
return;
|
||||
}
|
||||
|
||||
currentNode = NULL;
|
||||
while (node->parent != NULL)
|
||||
{
|
||||
Check(node->parent);
|
||||
if (node == node->parent->less)
|
||||
{
|
||||
currentNode = node->parent;
|
||||
return;
|
||||
}
|
||||
node = node->parent;
|
||||
Check(node);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// Previous
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
TreeIterator::Previous()
|
||||
{
|
||||
//
|
||||
// Should never reach here
|
||||
//
|
||||
#ifdef __BCPLUSPLUS__
|
||||
#pragma warn -ccc
|
||||
Verify(False);
|
||||
#pragma warn +ccc
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
//
|
||||
//###########################################################################
|
||||
// ReadAndNextImplementation
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
*TreeIterator::ReadAndNextImplementation()
|
||||
{
|
||||
void *plug;
|
||||
|
||||
if ((plug = GetCurrentImplementation()) != NULL)
|
||||
{
|
||||
Next();
|
||||
}
|
||||
return plug;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
//
|
||||
//###########################################################################
|
||||
// ReadAndPreviousImplementation
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
*TreeIterator::ReadAndPreviousImplementation()
|
||||
{
|
||||
#ifdef __BCPLUSPLUS__
|
||||
#pragma warn -ccc
|
||||
Verify(False);
|
||||
#pragma warn +ccc
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// GetCurrentImplementation
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
*TreeIterator::GetCurrentImplementation()
|
||||
{
|
||||
if (currentNode != NULL)
|
||||
{
|
||||
Check(currentNode);
|
||||
return currentNode->GetPlug();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// GetSize
|
||||
//###########################################################################
|
||||
//
|
||||
CollectionSize
|
||||
TreeIterator::GetSize()
|
||||
{
|
||||
TreeIterator iterator(Cast_Object(Tree*, socket));
|
||||
CollectionSize i = 0;
|
||||
|
||||
while (iterator.ReadAndNextImplementation() != NULL)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//
|
||||
//###########################################################################
|
||||
// GetNthImplementation
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
*TreeIterator::GetNthImplementation(
|
||||
CollectionSize index
|
||||
)
|
||||
{
|
||||
CollectionSize i = 0;
|
||||
void *plug;
|
||||
|
||||
First();
|
||||
while ((plug = GetCurrentImplementation()) != NULL)
|
||||
{
|
||||
if (i == index)
|
||||
return plug;
|
||||
Next();
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// Remove
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
TreeIterator::Remove()
|
||||
{
|
||||
if (currentNode != NULL)
|
||||
{
|
||||
Unregister_Object(currentNode);
|
||||
delete currentNode;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// FindImplementation
|
||||
//###########################################################################
|
||||
//
|
||||
Plug*
|
||||
TreeIterator::FindImplementation(
|
||||
const void *value
|
||||
)
|
||||
{
|
||||
TreeNode *node;
|
||||
|
||||
if ((node = Cast_Object(Tree*, socket)->SearchForValue(value)) != NULL)
|
||||
{
|
||||
Check(node);
|
||||
return (currentNode = node)->GetPlug();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
//###########################################################################
|
||||
// ReceiveMemo
|
||||
//###########################################################################
|
||||
//
|
||||
void
|
||||
TreeIterator::ReceiveMemo(
|
||||
IteratorMemo memo,
|
||||
void *content
|
||||
)
|
||||
{
|
||||
if (memo == PlugRemoved)
|
||||
{
|
||||
if (content == currentNode)
|
||||
Next();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TEST_CLASS)
|
||||
# include "tree.tcp"
|
||||
#endif
|
||||
Reference in New Issue
Block a user