//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code 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 3 of the License, or (at your option) any later version.

// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
// in the hope that it will be useful, but with permitted additional restrictions 
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
// distributed with this program. You should have received a copy of the 
// GNU General Public License along with permitted additional restrictions 
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection

/* $Header:   F:\projects\c&c\vcs\code\base.cpv   1.9   16 Oct 1995 16:48:56   JOE_BOSTIC  $ */
/***********************************************************************************************
 ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
 ***********************************************************************************************
 *                                                                                             *
 *                 Project Name : Command & Conquer                                            *
 *                                                                                             *
 *                    File Name : BASE.CPP                                                     *
 *                                                                                             *
 *                   Programmer : Bill Randolph                                                *
 *                                                                                             *
 *                   Start Date : 03/27/95                                                     *
 *                                                                                             *
 *                  Last Update : March 27, 1995                                               *
 *                                                                                             *
 *---------------------------------------------------------------------------------------------*
 * Functions:                                                                                  *
 *   BaseClass::Get_Building -- Returns ptr to the built building for the given node           *
 *   BaseClass::Get_Node -- Returns ptr to the node corresponding to given object              *
 *   BaseClass::Is_Built -- Tells if given item in the list has been built yet                 *
 *   BaseClass::Is_Node -- Tells if the given building is part of our base list                *
 *   BaseClass::Load -- loads from a saved game file                                           *
 *   BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built          *
 *   BaseClass::Read_INI -- INI reading routine                                                *
 *   BaseClass::Save -- saves to a saved game file                                             *
 *   BaseClass::Write_INI -- INI writing routine                                               *
 *   BaseNodeClass::operator != -- inequality operator                                         *
 *   BaseNodeClass::operator == -- equality operator                                           *
 *   BaseNodeClass::operator > -- greater-than operator                                        *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#include "function.h"


/***********************************************************************************************
 * BaseNodeClass::operator == -- equality operator                                             *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      node      node to test against                                                         *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      true = equal, false = not equal                                                        *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
int BaseNodeClass::operator == (BaseNodeClass const & node)
{
	return(Type == node.Type && Coord == node.Coord);
}


/***********************************************************************************************
 * BaseNodeClass::operator != -- inequality operator                                           *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      node      node to test against                                                         *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      comparison result                                                                      *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
int BaseNodeClass::operator !=(BaseNodeClass const & node)
{
	return(Type != node.Type || Coord != node.Coord);
}


/***********************************************************************************************
 * BaseNodeClass::operator > -- greater-than operator                                          *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      node      node to test against                                                         *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      comparison result                                                                      *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
int BaseNodeClass::operator > (BaseNodeClass const & )
{
	return(true);
}


/***********************************************************************************************
 * BaseClass::Read_INI -- INI reading routine                                                  *
 *                                                                                             *
 * INI entry format:                                                                           *
 *      BLDG=COORD                                                                             *
 *      BLDG=COORD                                                                             *
 *        ...                                                                                  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      buffer      pointer to loaded INI file                                                 *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      none.                                                                                  *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      This routines assumes there is only one base defined for the scenario.                 *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
void BaseClass::Read_INI(char *buffer)
{
	char buf[128];
	char uname[10];
	BaseNodeClass node;						// node to add to list

	/*
	**	First, determine the house of the human player, and set the Base's house
	**	accordingly.
	*/
	WWGetPrivateProfileString("BASIC", "Player", "GoodGuy", buf, 20, buffer);
	if (HouseTypeClass::From_Name(buf) == HOUSE_GOOD) {
		House = HOUSE_BAD;
	} else {
		House = HOUSE_GOOD;
	}

	/*
	**	Read the number of buildings that will go into the base node list
	*/
	int count = WWGetPrivateProfileInt (INI_Name(),"Count",0,buffer);

	/*
	**	Read each entry in turn, in the same order they were written out.
	*/
	for (int i = 0; i < count; i++) {

		/*
		** Get an INI entry
		*/
		sprintf(uname,"%03d",i);
		WWGetPrivateProfileString(INI_Name(), uname, NULL, buf, sizeof(buf)-1, buffer);

		/*
		** Set the node's building type
		*/
		node.Type = BuildingTypeClass::From_Name(strtok(buf,","));

		/*
		** Read & set the node's coordinate
		*/
		node.Coord = atol(strtok(NULL,","));

		/*
		** Add this node to the Base's list
		*/
		Nodes.Add(node);
	}
}


/***********************************************************************************************
 * BaseClass::Write_INI -- INI writing routine                                                 *
 *                                                                                             *
 * INI entry format:                                                                           *
 *      BLDG=COORD                                                                             *
 *      BLDG=COORD                                                                             *
 *        ...                                                                                  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      buffer      pointer to loaded INI file staging area                                    *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      none.                                                                                  *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      This routines assumes there is only one base defined for the scenario.                 *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
void BaseClass::Write_INI(char *buffer)
{
	char buf[128];
	char uname[10];

	/*
	**	Clear out all existing teamtype data from the INI file.
	*/
	WWWritePrivateProfileString(INI_Name(), NULL, NULL, buffer);

	/*
	**	Save the # of buildings in the Nodes list.  This is essential because
	**	they must be read in the same order they were created, so "000" must be
	**	read first, etc.
	*/
	WWWritePrivateProfileInt (INI_Name(),"Count",Nodes.Count(),buffer);

	/*
	**	Write each entry into the INI
	*/
	for (int i = 0; i < Nodes.Count(); i++) {
		sprintf(uname,"%03d",i);
		sprintf(buf,"%s,%d",
			BuildingTypeClass::As_Reference(Nodes[i].Type).IniName,
			Nodes[i].Coord);

		WWWritePrivateProfileString(INI_Name(), uname, buf, buffer);
	}
}


/***********************************************************************************************
 * BaseClass::Load -- loads from a saved game file                                             *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      file      open file                                                                    *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      true = success, false = failure                                                        *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
bool BaseClass::Load(FileClass &file)
{
	int num_struct;
	int i;
	BaseNodeClass node;

	/*
	** Read in & check the size of this class
	*/
	if (file.Read(&i, sizeof(i)) != sizeof(i)) {
		return(false);
	}

	if (i != sizeof(*this)) {
		return(false);
	}

	/*
	** Read in the House & the number of structures in the base
	*/
	if (file.Read(&House,sizeof(House)) != sizeof(House)) {
		return(false);
	}

	if (file.Read(&num_struct,sizeof(num_struct)) != sizeof(num_struct)) {
		return(false);
	}

	/*
	** Read each node entry & add it to the list
	*/
	for (i = 0; i < num_struct; i++) {
		if (file.Read(&node,sizeof(node)) != sizeof(node)) {
			return(false);
		}
		Nodes.Add(node);
	}

	return(true);
}


/***********************************************************************************************
 * BaseClass::Save -- saves to a saved game file                                               *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      file      open file                                                                    *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      true = success, false = failure                                                        *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
bool BaseClass::Save(FileClass &file)
{
	int num_struct;
	int i;
	BaseNodeClass node;

	/*
	** Write the size of this class
	*/
	i = sizeof(*this);
	if (file.Write(&i,sizeof(i)) != sizeof(i)) {
		return(false);
	}

	/*
	** Write the House & the number of structures in the base
	*/
	if (file.Write(&House,sizeof(House)) != sizeof(House)) {
		return(false);
	}

	num_struct = Nodes.Count();
	if (file.Write(&num_struct,sizeof(num_struct)) != sizeof(num_struct)) {
		return(false);
	}

	/*
	** Write each node entry
	*/
	for (i = 0; i < num_struct; i++) {
		node = Nodes[i];
		if (file.Write(&node,sizeof(node)) != sizeof(node)) {
			return(false);
		}
	}

	return(true);
}


/***********************************************************************************************
 * BaseClass::Is_Built -- Tells if given item in the list has been built yet                   *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      index      index into base list                                                        *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      true = yes, false = no                                                                 *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
bool BaseClass::Is_Built(int index)
{
	if (Get_Building(index) != NULL) {
		return(true);
	} else {
		return(false);
	}
}


/***********************************************************************************************
 * BaseClass::Get_Building -- Returns ptr to the built building for the given node             *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      obj      pointer to building to test                                                   *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      ptr to already-built building, NULL if none                                            *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
BuildingClass * BaseClass::Get_Building(int index)
{
	BuildingClass *bldg;
	ObjectClass *obj[4];

	/*
	** Check the location on the map where this building should be; if it's
	** there, return a pointer to it.
	*/
	CELL cell = Coord_Cell(Nodes[index].Coord);

	obj[0] = Map[cell].Cell_Building();
	obj[1] = Map[cell].Overlapper[0];
	obj[2] = Map[cell].Overlapper[1];
	obj[3] = Map[cell].Overlapper[2];

	bldg = NULL;
	for (int i = 0; i < 4; i++) {
		if (obj[i] &&
			obj[i]->Coord == Nodes[index].Coord &&
			obj[i]->What_Am_I() == RTTI_BUILDING &&
			((BuildingClass *)obj[i])->Class->Type == Nodes[index].Type) {

				bldg = (BuildingClass *)obj[i];
				break;
		}
	}

	return(bldg);
}


/***********************************************************************************************
 * BaseClass::Is_Node -- Tells if the given building is part of our base list                  *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      obj      pointer to building to test                                                   *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      true = building is a node in the list, false = isn't                                   *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
bool BaseClass::Is_Node(BuildingClass *obj)
{
	if (Get_Node(obj) != NULL) {
		return(true);
	} else {
		return(false);
	}
}


/***********************************************************************************************
 * BaseClass::Get_Node -- Returns ptr to the node corresponding to given object                *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      obj      pointer to building to test                                                   *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      ptr to node                                                                            *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
BaseNodeClass * BaseClass::Get_Node(BuildingClass *obj)
{
	for (int i = 0; i < Nodes.Count(); i++) {
		if (obj->Class->Type == Nodes[i].Type && obj->Coord == Nodes[i].Coord) {
			return(&Nodes[i]);
		}
	}
	return(NULL);
}


/***********************************************************************************************
 * BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built            *
 *                                                                                             *
 * If 'type' is not NONE, returns ptr to the next "hole" in the list of the given type.        *
 * Otherwise, returns ptr to the next hole in the list of any type.                            *
 *                                                                                             *
 * INPUT:                                                                                      *
 *      type      type of building to check for                                                *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *      ptr to a BaseNodeClass, NULL if none                                                   *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *      none.                                                                                  *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   03/24/1995 BRR : Created.                                                                 *
 *=============================================================================================*/
BaseNodeClass * BaseClass::Next_Buildable(StructType type)
{
	/*
	** Loop through all node entries, returning a pointer to the first
	** un-built one that matches the requested type.
	*/
	for (int i = 0; i < Nodes.Count(); i++) {

		/*
		** For STRUCT_NONE, return the first hole found
		*/
		if (type == STRUCT_NONE) {
			if (!Is_Built(i)) {
				return(&Nodes[i]);
			}

		} else {

			/*
			** For a "real" building type, return the first hold for that type
			*/
			if (Nodes[i].Type==type && !Is_Built(i)) {
				return(&Nodes[i]);
			}
		}
	}


// If no entry could be found, then create a fake one that will allow
// placement of the building. Make it static and reuse the next time this
// routine is called.

	return(NULL);
}