//
// Author: Brett Kraabel
// Date: April 11, 2000
// file: piece.cpp
//
// Description:
// This is the implementation file for the header file piece.h.
// See the documentation for a complete description of the program.
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************

#ifndef piece_h
#include "piece.h"
#endif

#ifndef __OSTREAM_H
#include <ostream.h>
#endif

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// public constructor
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

piece::piece(index mNum, index mInSize) : sID(mNum), sSize(mInSize)
{
// set the size of the vectors in sBody to sSize
sBody.resize(sSize);
for (index i = 0; i < sSize; ++i)
{ sBody[i].resize(sSize);
for (index j = 0; j < sSize; ++j)
sBody[i][j].resize(sSize);
}
for (index i = 0; i < sSize; ++i)
for (index j = 0; j < sSize; ++j)
for (index k = 0; k < sSize; ++k)
sBody[i][j][k] = 0;
}
//end constructor

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// public copy constructor
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

piece::piece(const piece& mInput) : sID(mInput.sID), sSize(mInput.sSize)
{
sBody.resize(mInput.sSize);
for (index i = 0; i < mInput.sSize; ++i)
{ sBody[i].resize(mInput.sSize);
for (index j = 0; j < mInput.sSize; ++j)
sBody[i][j].resize(mInput.sSize);
}
//end for loop
for (index i = 0; i < mInput.sSize; ++i)
for (index j = 0; j < mInput.sSize; ++j)
for (index k = 0; k < mInput.sSize; ++k)
sBody[i][j][k] = mInput.sBody[i][j][k];
}
//end copy constructor

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// public assignment operator
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

piece& piece::operator=(const piece& rhs)
{
if (*this != rhs)
{ sID = rhs.sID;
sSize = rhs.sSize;
sBody.resize(rhs.sSize);
for (index i = 0; i < rhs.sSize; ++i)
{ sBody[i].resize(rhs.sSize);
for (index j = 0; j < rhs.sSize; ++j)
sBody[i][j].resize(rhs.sSize);
}
//end for loop
for (index i = 0; i < rhs.sSize; ++i)
for (index j = 0; j < rhs.sSize; ++j)
for (index k = 0; k < rhs.sSize; ++k)
sBody[i][j][k] = rhs.sBody[i][j][k];
}
//end if
return *this;
}
//end copy assignment

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// public method: getCentroid
// Returns centroid of piece cast into base 10 form. This means the Z
// coordinate of the centroid is multiplied by 100, the Y coordinate by 10,
// and the X coordinate by 1 (i.e. the Z coordinate is the "most
// significant digit, followed by the Y coordinate and then the X
// coordinate.) This allows us to easily compare the positions of
// identical pieces to see if one has been translated more than the other.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

float piece::getCentroid() const
{
float tCentroidX = 0, tCentroidY = 0, tCentroidZ = 0;
float tNumX = 0, tNumY = 0, tNumZ = 0;

for (index z = 0; z < sSize; ++z)
for (index y = 0; y < sSize; ++y)
for (index x = 0; x < sSize; ++x)
if (sBody[x][y][z])
//this position is occupied
{ tCentroidX += x;
tCentroidY += y;
tCentroidZ += z;
++tNumX;
++tNumY;
++tNumZ;
}
if (tNumX > 0 && tNumY > 0 && tNumZ > 0)
return tCentroidZ*100/tNumZ + tCentroidY*10/tNumY + tCentroidX/tNumX;
else
return 0;
}
//end getCentroid

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// public method: operator==
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

bool piece::operator==(const piece& rhs)
{
if (sSize == rhs.sSize)
{ for (index i = 0; i < sSize; ++i)
for (index j = 0; j < sSize; ++j)
for (index k = 0; k < sSize; ++k)
//pieces must be EXACLTY alike, i.e. have same color
if (sBody[i][j][k] != rhs.sBody[i][j][k])
return false;
}
//end if
else
return false;

return true;
}
//end operator==

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// public method operator!=
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

bool piece::operator!=(const piece& rhs)
{
return !(*this == rhs);
}
//end operator!=

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// public method: operator[]
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

vector<vector<piece_type> >& piece::operator[](const index& i)
{
return sBody[i];
}
//end operator[]

// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// friend method: operator<<
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

ostream& operator<<(ostream& mOS, const piece& mInput)
{
for ( index z = 0; z < mInput.sSize; ++z)
{ for ( index y = 0; y < mInput.sSize; ++y)
{ mOS << endl;
for ( index x = 0; x < mInput.sSize; ++x)
mOS << mInput.sBody[x][y][z];
}
//end for loop
} //end for loop
mOS << endl;
return mOS;
}
//end operator<<