- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
319 lines
9.1 KiB
C++
319 lines
9.1 KiB
C++
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* BINIMP.CPP */
|
|
/* */
|
|
/* Copyright (c) 1993, 1994 Borland International */
|
|
/* All Rights Reserved */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
#if !defined( CLASSLIB_BINIMP_H )
|
|
#include <classlib/binimp.h>
|
|
#endif
|
|
|
|
TBinarySearchTreeBase::TBinarySearchTreeBase() :
|
|
Root(0),
|
|
ItemsInContainer(0)
|
|
{
|
|
}
|
|
|
|
int TBinarySearchTreeBase::InsertNode( BinNode *node )
|
|
{
|
|
BinNode *Current = Root;
|
|
BinNode *Parent = 0;
|
|
while( Current )
|
|
{
|
|
Parent = Current;
|
|
Current = LessThan( node, Current ) ? Current->Left : Current->Right;
|
|
}
|
|
if( Parent == 0 )
|
|
Root = node;
|
|
else
|
|
{
|
|
if( LessThan( node, Parent ) )
|
|
Parent->Left = node;
|
|
else
|
|
Parent->Right = node;
|
|
}
|
|
ItemsInContainer++;
|
|
return 1;
|
|
}
|
|
|
|
int TBinarySearchTreeBase::RemoveNode( BinNode *node, int del )
|
|
{
|
|
BinNode *Current = Root;
|
|
BinNode *Parent = 0;
|
|
while( Current )
|
|
{
|
|
if( EqualTo( node, Current ) )
|
|
return RemNode( Current, Parent, del );
|
|
else
|
|
{
|
|
Parent = Current;
|
|
Current = LessThan( node, Current ) ? Current->Left :
|
|
Current->Right;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
TBinarySearchTreeBase::BinNode *TBinarySearchTreeBase::FindNode( BinNode *node )
|
|
{
|
|
BinNode *Current = Root;
|
|
while( Current )
|
|
{
|
|
if( EqualTo( node, Current ) )
|
|
return Current;
|
|
else
|
|
Current = LessThan( node, Current ) ? Current->Left :
|
|
Current->Right;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int TBinarySearchTreeBase::RemNode( BinNode *node, BinNode *parent, int del )
|
|
{
|
|
// See R. Sedgewick, "Algorithms, 2nd edition",
|
|
// Addison-Wesley 1988, p.210.
|
|
BinNode *Original = node;
|
|
if( Original->Right == 0 )
|
|
node = node->Left;
|
|
else if( Original->Right->Left )
|
|
{
|
|
BinNode *Current = Original->Right;
|
|
while( Current->Left->Left )
|
|
Current = Current->Left;
|
|
node = Current->Left;
|
|
Current->Left = node->Right;
|
|
node->Left = Original->Left;
|
|
node->Right = Original->Right;
|
|
}
|
|
else
|
|
{
|
|
node = node->Right;
|
|
node->Left = Original->Left;
|
|
}
|
|
if( parent == 0 )
|
|
Root = node;
|
|
else if( LessThan( Original, parent ) )
|
|
parent->Left = node;
|
|
else
|
|
parent->Right = node;
|
|
|
|
DeleteNode( Original, del );
|
|
ItemsInContainer--;
|
|
return 1;
|
|
}
|
|
|
|
class TBinaryTreeKiller : public TBinaryTreeInternalIteratorBase
|
|
{
|
|
|
|
public:
|
|
|
|
TBinaryTreeKiller( TBinarySearchTreeBase& tree, int del ) :
|
|
TBinaryTreeInternalIteratorBase( tree, TBinarySearchTreeBase::PostOrder ),
|
|
Del(del) {}
|
|
|
|
private:
|
|
|
|
virtual void Apply( TBinarySearchTreeBase::BinNode _FAR *node,
|
|
TBinarySearchTreeBase::BinNode _FAR *parent );
|
|
|
|
int Del;
|
|
|
|
TBinaryTreeKiller( const TBinaryTreeKiller& );
|
|
const TBinaryTreeKiller& operator = ( const TBinaryTreeKiller& );
|
|
|
|
};
|
|
|
|
void TBinaryTreeKiller::Apply( TBinarySearchTreeBase::BinNode _FAR *node,
|
|
TBinarySearchTreeBase::BinNode _FAR *parent )
|
|
{
|
|
Tree().RemNode( node, parent, Del );
|
|
}
|
|
|
|
void TBinarySearchTreeBase::Flush( int del )
|
|
{
|
|
if( Root != 0 )
|
|
TBinaryTreeKiller( *this, del ).Iterate();
|
|
}
|
|
|
|
void TBinaryTreeInternalIteratorBase::Iterate()
|
|
{
|
|
TBinarySearchTreeBase::BinNode _FAR *Current = Node;
|
|
TBinarySearchTreeBase::BinNode _FAR *Prev = 0;
|
|
TBinarySearchTreeBase::BinNode _FAR *Next = 0;
|
|
step2:
|
|
if( Order == TBinarySearchTreeBase::PreOrder )
|
|
Apply( Current, 0 );
|
|
Next = Current->Left;
|
|
if( Next != 0 )
|
|
{
|
|
Current->Left = Prev;
|
|
Prev = Current;
|
|
Current = Next;
|
|
goto step2;
|
|
}
|
|
step4:
|
|
if( Order == TBinarySearchTreeBase::InOrder )
|
|
Apply( Current, 0 );
|
|
Next = Current->Right;
|
|
if( Next != 0 )
|
|
{
|
|
Current->Right = Prev;
|
|
Prev = Current;
|
|
Current = Next;
|
|
goto step2;
|
|
}
|
|
step6:
|
|
if( Prev == 0 )
|
|
{
|
|
if( Order == TBinarySearchTreeBase::PostOrder )
|
|
Apply( Current, 0 );
|
|
return;
|
|
}
|
|
if( Tree().LessThan( Current, Prev ) )
|
|
{
|
|
TBinarySearchTreeBase::BinNode _FAR *Temp = Current;
|
|
Next = Prev->Left;
|
|
Prev->Left = Current;
|
|
Current = Prev;
|
|
Prev = Next;
|
|
if( Order == TBinarySearchTreeBase::PostOrder )
|
|
Apply( Temp, Current );
|
|
goto step4;
|
|
}
|
|
else
|
|
{
|
|
TBinarySearchTreeBase::BinNode _FAR *Temp = Current;
|
|
Next = Prev->Right;
|
|
Prev->Right = Current;
|
|
Current = Prev;
|
|
Prev = Next;
|
|
if( Order == TBinarySearchTreeBase::PostOrder )
|
|
Apply( Temp, Current );
|
|
goto step6;
|
|
}
|
|
}
|
|
|
|
TBinaryTreeExternalIteratorBase::TBinaryTreeExternalIteratorBase( TBinarySearchTreeBase& tree, TBinarySearchTreeBase::IteratorOrder order ) :
|
|
Stack( new TStackAsList<TBinarySearchTreeBase::BinNode _BIDSFAR *> ),
|
|
Tree(&tree),
|
|
Current( tree.Root ),
|
|
Order( order )
|
|
{
|
|
Restart();
|
|
}
|
|
|
|
TBinaryTreeExternalIteratorBase::~TBinaryTreeExternalIteratorBase()
|
|
{
|
|
delete Stack;
|
|
}
|
|
|
|
void TBinaryTreeExternalIteratorBase::Restart()
|
|
{
|
|
Stack->Flush();
|
|
Current = Tree->Root;
|
|
LeftVisited = RightVisited = 0;
|
|
Processed = 0;
|
|
}
|
|
|
|
TBinarySearchTreeBase::BinNode *TBinaryTreeExternalIteratorBase::Next()
|
|
{
|
|
if( Current == 0 )
|
|
return 0;
|
|
for(;;)
|
|
{
|
|
if( Order == TBinarySearchTreeBase::PreOrder && !Processed )
|
|
{
|
|
Processed = 1;
|
|
return Current;
|
|
}
|
|
|
|
if( Current->Left != 0 && !LeftVisited )
|
|
{
|
|
Stack->Push( Current );
|
|
Current = Current->Left;
|
|
LeftVisited = RightVisited = 0;
|
|
Processed = 0;
|
|
}
|
|
else if( Current->Right != 0 && !RightVisited )
|
|
{
|
|
TBinarySearchTreeBase::BinNode *Res = 0;
|
|
if( Order == TBinarySearchTreeBase::InOrder )
|
|
Res = Current;
|
|
Stack->Push( Current );
|
|
Current = Current->Right;
|
|
LeftVisited = RightVisited = 0;
|
|
Processed = 0;
|
|
if( Res != 0 )
|
|
return Res;
|
|
}
|
|
else
|
|
{
|
|
if( Stack->IsEmpty() )
|
|
{
|
|
if( Processed == 0 )
|
|
{
|
|
Processed = 1;
|
|
}
|
|
else
|
|
{
|
|
Current = 0;
|
|
}
|
|
return Current;
|
|
}
|
|
else
|
|
{
|
|
TBinarySearchTreeBase::BinNode *Res;
|
|
switch( Order )
|
|
{
|
|
case TBinarySearchTreeBase::PreOrder:
|
|
// This node has already been
|
|
// processed, so we have further to go.
|
|
Res = 0;
|
|
|
|
// This node's parent has
|
|
// already been processed
|
|
Processed = 1;
|
|
|
|
break;
|
|
|
|
case TBinarySearchTreeBase::InOrder:
|
|
if( IsInOrder() )
|
|
{
|
|
// This node needs to be processed.
|
|
Res = Current;
|
|
}
|
|
else
|
|
{
|
|
// Node has already been processed.
|
|
Res = 0;
|
|
}
|
|
// If we're the right-hand child, our parent
|
|
// has already been processed.
|
|
Processed = Stack->Top()->Right == Current;
|
|
|
|
break;
|
|
|
|
case TBinarySearchTreeBase::PostOrder:
|
|
// This node needs to be processed.
|
|
Res = Current;
|
|
|
|
// This node's parent has not been processed.
|
|
Processed = 0;
|
|
|
|
break;
|
|
}
|
|
|
|
LeftVisited = 1;
|
|
RightVisited = Stack->Top()->Right == Current;
|
|
Current = Stack->Pop();
|
|
if( Res != 0 )
|
|
return Res;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|