/*=========================================================================
* MSWay.cpp : MSWay's functions
* Version              1.0
* Creation date        January 21, 1997
* Revision date
*
* That file needs to be compatible for all platforms.
*
* (c) Ubi Studios 1996
*==========================================================================
* Remarks :
* Allocation of MSWay fields are made inside the AI module memory block
* Error raised when handling MSWay fields are raised from AI error module
*==========================================================================*/
 
/*******************************************************/
/**** For the structures and variables declarations ****/
/*******************************************************/
#define D_MSWay_StructureDefine
#define D_MSWay_VariableDefine
 
#include "ToolsCPA.h"
 
#include "Options/Options.h"
#include "Macros.h"
 
#include "Actions/AllActs.h"
 
#include "Structur/MemGame.h"
#include "Structur/ErrGame.h"
#include "Structur/Objects.h"
#include "Structur/GameScpt.h"
#include "Structur/StdObjSt.h"
#include "Structur/EngMode.h"
 
#include "Basic.h"
#include "ObjInit.h"
#include "ZeMem.h"
/*ANNECY JMD{*/
#define _WP_D_WPGRAPH_FRIEND_
#include "AI/AIBASE/WPgraphe.h"
#undef _WP_D_WPGRAPH_FRIEND_
/*ENDANNECY JMD }*/
 
#include "AI.h"
 
#include "safe.h" /*BART*/
 
 
/*-----------------------------------------------------------------------------
*  Description : MSWay's object action script callback
*-----------------------------------------------------------------------------
*  Input :         Object pointer
*  Output :        None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96            Author : Francois
*-----------------------------------------------------------------------------
*  Modification date :                 Modification Author : Albert Pais
*  Modifications :
*  Effective implementation for MS Way
*-----------------------------------------------------------------------------
*  Script Section Template for MS Way :
* :MSWay(NbrOfWay)
*   Way(FileName,SectionNameOfWay1)
*   Way(FileName,SectionNameOfWay2)
*   ....
*   Way(FileName,SectionNameOfWayNbrOfWay)
* :EndSection
*---------------------------------------------------------------------------*/
#if defined(GAM_USE_SCRIPT)
SCR_tde_Anl_ReturnValue fn_eMSWayScriptCallBack(SCR_tdst_File_Description *_p_stHandle,char *_p_szName,char *_d_szPars[],SCR_tde_Anl_Action	_eAction)
{
  SCRIPT_tdeReturnValue eReturnValue = R_SCRIPT_NormalReturn;
  MS_tdxHandleToMSWay h_MSWay;
  struct tdstEngineObject_ *p_stEngineObject;
 
  SCR_M_RdL0_GetSectionLong(C_ParentSection,0,struct tdstEngineObject_ *, p_stEngineObject);
 
  if (M_IsTitle)
  {
    MMG_fn_vBeginMemoryInfo (MMG_C_lTypeMiniStructure , MMG_C_lSubTypeMSWay , p_stEngineObject);
    h_MSWay = fn_h_MSWayRealAlloc();
    MMG_fn_vEndMemoryInfo ();
    p_stEngineObject->h_MSWay=h_MSWay;
 
    /* Push the result :*/
    SCR_M_RdL0_SetSectionLong(C_ThisSection,0,h_MSWay);
  }
  return(eReturnValue);
}
#endif /* GAM_USE_SCRIPT */
 
/*-----------------------------------------------------------------------------
*  Description : MSWay's mini-structure sizeof
*-----------------------------------------------------------------------------
*  Input :         None
*  Output :        Size of
*-----------------------------------------------------------------------------
*  Creation date : 14/10/96            Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : January 21,1997 Modification Author : Albert Pais
*  Modifications : Effective implementation for MS Way
*---------------------------------------------------------------------------*/
unsigned long fn_ulMSWaySizeOf()
{
  return(sizeof(struct tdstMSWay_));
}
 
/*-----------------------------------------------------------------------------
*  Description : MSWay's object action allocation
*-----------------------------------------------------------------------------
*  Input :         Object pointer
*  Output :        None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96            Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : January 21,1997 Modification Author : Albert Pais
*  Modifications : Effective implementation for MS Way
*---------------------------------------------------------------------------*/
void fn_vMSWayAlloc(struct tdstEngineObject_ *p_stObject)
{
  if (p_stObject==NULL)
    M_GameFatalError(E_uwGameMiniStructObjectNull);
 
  if (MSWAY_M_hGetMSWayFromEngineObject(p_stObject)!=MSWAY_M_hInvalidMsWayHandle)
    M_GameFatalError(E_uwGameMiniStructAllocAlreadyAlloc);
 
  MMG_fn_vBeginMemoryInfo (MMG_C_lTypeMiniStructure , MMG_C_lSubTypeMSWay , p_stObject);
  MSWAY_M_hGetMSWayFromEngineObject(p_stObject) = fn_h_MSWayRealAlloc();
  MMG_fn_vEndMemoryInfo ();
}
 
MS_tdxHandleToMSWay fn_h_MSWayRealAlloc()
{
  MS_tdxHandleToMSWay h_MSWay;
 
  h_MSWay = (MS_tdxHandleToMSWay)M_p_GameMallocInHLM(fn_ulMSWaySizeOf());
  MSWay_fn_vInitPath (h_MSWay);
  return(h_MSWay);
}
 
/*-----------------------------------------------------------------------------
*  Description : MSWay's object action free
*-----------------------------------------------------------------------------
*  Input :         Object pointer
*  Output :        None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96            Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : January 22,1997 Modification Author : Alb
*  Modifications : Effective implementation for MS Way
*---------------------------------------------------------------------------*/
void fn_vMSWayFree(struct tdstEngineObject_ *p_stObject)
{
  MS_tdxHandleToMSWay hMSWay;
 
  if (p_stObject==NULL)
    M_GameFatalError(E_uwGameMiniStructObjectNull);
 
  hMSWay = MSWAY_M_hGetMSWayFromEngineObject(p_stObject);
  if (hMSWay==MSWAY_M_hInvalidMsWayHandle)
    M_GameFatalError(E_uwGameMiniStructNull);
 
/*ANNECY Bart#02 27/05/98 {*/
  MSWay_fn_vDesinitPath(hMSWay);
/*ENDANNECY Bart#02 }*/
 
  /* Destroy the object :*/
  /* dfm
  MSWay_fn_v_DestroyListOfWay
  (
  MSWAY_M_hGetMSWayFromEngineObject(p_stObject)
  );
  */
  MMG_fn_vAddMemoryInfo( MMG_C_lTypeMiniStructure , MMG_C_lSubTypeMSWay , p_stObject );
  M_GameFreeInHLM(p_stObject->h_MSWay);
}
 
/*-----------------------------------------------------------------------------
*  Description : MSWay's object action initialisation
*-----------------------------------------------------------------------------
*  Input :         When this function's called (see ObjInit.h)
*  Output :        None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96            Author : Francois
*-----------------------------------------------------------------------------
*  Modification date :                 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
void fn_vMSWayInit(struct tdstEngineObject_ *p_stObject,enum tdeObjectTreeInit_ eObjectInit)
{
  MS_tdxHandleToMSWay hMSWay;
 
  if (p_stObject==NULL)
    M_GameFatalError(E_uwGameMiniStructObjectNull);
 
  hMSWay = MSWAY_M_hGetMSWayFromEngineObject(p_stObject);
  if (hMSWay==MSWAY_M_hInvalidMsWayHandle)
    M_GameFatalError(E_uwGameMiniStructNull);
 
  MSWay_fn_vInitPath (hMSWay);
 
}
 
/*-----------------------------------------------------------------------------
*  Description : MSWay's object action desinitialisation
*-----------------------------------------------------------------------------
*  Input :         When this function's called (see ObjInit.h)
*  Output :        None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96            Author : Francois
*-----------------------------------------------------------------------------
*  Modification date :                 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
void fn_vMSWayDesinit(struct tdstEngineObject_ *p_stObject,enum tdeObjectTreeInit_ eObjectInit)
{
  MS_tdxHandleToMSWay hMSWay;
 
  if (p_stObject==NULL)
    M_GameFatalError(E_uwGameMiniStructObjectNull);
 
  hMSWay = MSWAY_M_hGetMSWayFromEngineObject(p_stObject);
  if (hMSWay==MSWAY_M_hInvalidMsWayHandle)
    M_GameFatalError(E_uwGameMiniStructNull);
 
  MSWay_fn_vDesinitPath(hMSWay);
}
 
/*-----------------------------------------------------------------------------
*  Description : MSWay's object copy clone action
*-----------------------------------------------------------------------------
*  Input :         Handle to destination, handle to source
*  Output :        None
*-----------------------------------------------------------------------------
*  Creation date : 30/06/97            Author : Olivier Jourdan
*-----------------------------------------------------------------------------
*  Modification date :                 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
void fn_vMSWayCopyClone(struct tdstEngineObject_ * _p_stObjectDest,struct tdstEngineObject_ * _p_stObjectSrc)
{
/*ANNECY Bart#02 27/05/98 {*/
  MSWay_fn_vDesinitPath(_p_stObjectDest->h_MSWay); /* Just To Be Sure !*/
/*ENDANNECY Bart#02 }*/
 
  memcpy(_p_stObjectDest->h_MSWay,_p_stObjectSrc->h_MSWay,fn_ulMSWaySizeOf());
 
/*ANNECY Bart#02 27/05/98 {*/
  MSWay_fn_vInitPath (_p_stObjectDest->h_MSWay); /* Just To Be Sure !*/
/*ENDANNECY Bart#02 }*/
}
 
/*-----------------------------------------------------------------------------
*  Description :   compute the second pass for :
*                  - list of way
*					- waypoint
*					- way
*-----------------------------------------------------------------------------
*  Input :         None
*  Output :        None
*-----------------------------------------------------------------------------
*  Creation date : 13/05/97            Author : Jacques Thénoz
*-----------------------------------------------------------------------------
*  Modification date :                 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
#if defined(GAM_USE_SCRIPT)
void fn_vWaypointSecondPass (void)
{
  WP_fnv_WayPoint_LinkTableSecondPass ();
}
#endif /* GAM_USE_SCRIPT */
 
/*JMD*************************************************************************
* manage graph ( the m_hPath member )
*****************************************************************************
*
* waypoint are stored in the reversed order the last one is at index 0
* (see WPG_fn_hShortestPath() that built the list from the destination
* to the source, that the algorithme !) so we must read them in reverse
* order
*****************************************************************************/
void MSWay_fn_vInitPath (MS_tdxHandleToMSWay hWay)
{
  /*
  if ( hWay ) {
    hWay->m_hPath = NULL ;
    hWay->m_lIndex = -1 ;
    hWay->m_bIsCircular = 0;
  }
  */
  MSWay_fn_vDesinitPath(hWay); /* because we want to be sure that this new graph does not ecrase an old one that would not been desalloued*/
}
 
void MSWay_fn_vDesinitPath(MS_tdxHandleToMSWay hWay)
{
  if ( hWay )
  {
    if ( hWay->m_hPath )
    {
#ifdef GAM_USE_SCRIPT
      if (hWay->m_hPath->m_szReferenceSection[0] == '@') /*BART*/
#endif
        WPG_fn_vDestroy (hWay->m_hPath) ;
    }
    hWay->m_hPath = NULL ;
    hWay->m_lIndex = -1 ;
    hWay->m_bIsCircular = 0;
  }
}
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
WP_tdHandleOfGraph MSWay_fn_hGetPathFormPerso (HIE_tdxHandleToSuperObject hSuperObject)
{
  MS_tdxHandleToMSWay h_MSWay;
 
  h_MSWay = M_GetMSHandle(hSuperObject, MSWay);
  if ( h_MSWay )
    return ( h_MSWay->m_hPath ) ;
  return (NULL) ;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
void MSWay_fn_vSetPath(MS_tdxHandleToMSWay hWay, WP_tdHandleOfGraph hPath, char _bIsCircular)
{
  if ( hWay && hPath )
  {
    if ( hWay->m_hPath != NULL )
    {
#ifdef GAM_USE_SCRIPT
      /*if (hWay->m_hPath->m_szNameOfGraph[0] == 0) // no name => not a real graph, so you can destroy it ! !*/
      if (hWay->m_hPath->m_szReferenceSection[0] == '@') /*BART*/
#endif
        WPG_fn_vDestroy (hWay->m_hPath) ;
    }
    hWay->m_hPath = hPath ;
    /*		hWay->m_lIndex = WPG_fn_lNumberOfWaypointOfGraph (hPath) - 1 ;*/
    hWay->m_lIndex = 0 ;
    hWay->m_bIsCircular = _bIsCircular;
  }
}
 
long MSWay_fn_lGetNumberWayPointInPath (MS_tdxHandleToMSWay hWay)
{
  if ( hWay && hWay->m_hPath )
    return (LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode)) ;
  return (-1) ;
}
 
long MSWay_fn_lGetCurrentIndexInPath (MS_tdxHandleToMSWay hWay)
{
  if (hWay && hWay->m_hPath)
    return (hWay->m_lIndex) ;
  return (-1) ;
}
 
long MSWay_fn_lGetLastIndexInPath (MS_tdxHandleToMSWay hWay)
{
  if ( hWay && hWay->m_hPath )
    return (LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode)-1) ;
  /*    return (0) ;*/
  return (-1) ;
}
 
long MSWay_fn_lGetFirstIndexInPath (MS_tdxHandleToMSWay hWay)
{
  if ( hWay && hWay->m_hPath )
    return (0) ;
  return (-1) ;
}
 
long MSWay_fn_lSetCurrentIndexInPath (MS_tdxHandleToMSWay hWay, long _lIndex)
{
  long lNbOfElts;
  if ( hWay != NULL && hWay->m_hPath )
  {
    lNbOfElts = LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode);
    if (hWay->m_bIsCircular)
    {
      _lIndex %= lNbOfElts;
      if (_lIndex<0) _lIndex+=lNbOfElts;
    }
    if (_lIndex>=lNbOfElts)
      _lIndex = lNbOfElts-1;
    if (_lIndex<0)
      _lIndex = 0;
    hWay->m_lIndex = _lIndex ;
    return (hWay->m_lIndex) ;
  }
  return (-1) ;
}
 
long MSWay_fn_lLookForWPInMSWay(MS_tdxHandleToMSWay _hWay, WP_tdhWayPoint _hWayPoint)
{
  long lNbOfElts;
  int iIndex;
  WP_tdhGraphNode hElement;
 
  if ( _hWay && _hWay->m_hPath )
  {
    lNbOfElts = LST2_M_DynamicGetNumberOfElements(&_hWay->m_hPath->m_hListOfNode);
 
    LST2_M_DynamicForEachElementOf(&_hWay->m_hPath->m_hListOfNode, hElement, iIndex)
    {
      if (_hWayPoint == hElement->m_hWayPoint)
        return ((long)(lNbOfElts - iIndex - 1) );
    }
  }
  return(-1);
}
 
 
long MSWay_fn_lIncrementCurrentIndexInPath (MS_tdxHandleToMSWay hWay, int iStep)
{
  long lNbOfElts;
 SAF_M_AssertWithMsg((hWay != NULL),"MsWay non alloue")
 
  if (hWay == NULL)
    return (-1);
 
 SAF_M_AssertWithMsg((hWay->m_hPath != NULL),"MsWay non initialise")
 
  if ( hWay->m_hPath )
  {
    lNbOfElts = LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode);
    if (hWay->m_bIsCircular)
    {
      hWay->m_lIndex += iStep;
      hWay->m_lIndex %= lNbOfElts;
      if (hWay->m_lIndex<0) hWay->m_lIndex+=lNbOfElts;
      return (hWay->m_lIndex);
    }
    else
    {
      if ( (hWay->m_lIndex + iStep >= 0) &&
        (hWay->m_lIndex + iStep < lNbOfElts ) )
      {
        hWay->m_lIndex += iStep  ;
        return (hWay->m_lIndex) ;
      }
    }
  }
  return (-1) ;
}
 
WP_tdhWayPoint MSWay_fn_hGetWayPointOfPath (MS_tdxHandleToMSWay hWay, int iIndex)
{
  WP_tdhGraphNode hElement ;
  int i, k ;
  long lNbOfElts;
 
  if ( hWay && hWay->m_hPath)
  {
    lNbOfElts = LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode);
    if (hWay->m_bIsCircular)
    {
      iIndex %= lNbOfElts;
      if (iIndex<0) iIndex+=lNbOfElts;
    }
    else
    {
			if (iIndex < 0 || iIndex >= lNbOfElts )
        return(NULL);
    }
 
    k = lNbOfElts - iIndex - 1;
    LST2_M_DynamicGetElementNumber(&hWay->m_hPath->m_hListOfNode, hElement, k, i)
    return (hElement->m_hWayPoint);
  }
  return (NULL) ;
}
 
unsigned long MSWay_fn_ulGetCapsForNextWayPointOfPath (MS_tdxHandleToMSWay hWay, int iIndex)
{
  WP_tdhWayPoint hWayPoint1, hWayPoint2 ;
  unsigned long ulNewCaps ;
  long lNbOfElts;
 
  if ( hWay && hWay->m_hPath != NULL)
  {
    lNbOfElts = LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode);
    if (hWay->m_bIsCircular)
    {
      iIndex %= lNbOfElts;
      if (iIndex<0) iIndex+=lNbOfElts;
    }
    if ( iIndex >= 0 && iIndex < lNbOfElts )
    {
      hWayPoint1 = MSWay_fn_hGetWayPointOfPath(hWay, iIndex ) ;
      hWayPoint2 = MSWay_fn_hGetWayPointOfPath(hWay, iIndex+1 ) ;
      if ( hWayPoint2 )
      {
        if (WPG_fn_lGetLinkCapabilities (hWay->m_hPath, hWayPoint1, hWayPoint2, &ulNewCaps)== -1 )
          return (0);
        return ( ulNewCaps ) ;
      }
    }
  }
  return (0) ;
}
 
long MSWay_fn_lChangeCapsForNextWayPointOfPath (MS_tdxHandleToMSWay hWay, int iIndex, unsigned long ulNewCaps, long lValue)
{
  WP_tdhWayPoint hWayPoint1, hWayPoint2 ;
  long lNbOfElts;
 
  if ( hWay && hWay->m_hPath != NULL)
  {
    lNbOfElts = LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode);
    if (hWay->m_bIsCircular)
    {
      iIndex %= lNbOfElts;
      if (iIndex<0) iIndex+=lNbOfElts;
    }
    if ( iIndex >= 0 && iIndex < lNbOfElts )
    {
      hWayPoint1 = MSWay_fn_hGetWayPointOfPath(hWay, iIndex ) ;
      hWayPoint2 = MSWay_fn_hGetWayPointOfPath(hWay, iIndex+1 ) ;
      if ( hWayPoint2 )
      {
        return (WPG_fn_lChangeLinkCapabilities (hWay->m_hPath, hWayPoint1, hWayPoint2, ulNewCaps, lValue)); /* -1 if error*/
      }
    }
  }
  return (-1) ;
}
 
long MSWay_fn_lGetWeightForNextWayPointOfPath (MS_tdxHandleToMSWay hWay, int iIndex)
{
  WP_tdhWayPoint hWayPoint1, hWayPoint2 ;
  long lValue ;
  long lNbOfElts;
 
  if ( hWay && hWay->m_hPath != NULL)
  {
    lNbOfElts = LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode);
    if (hWay->m_bIsCircular)
    {
      iIndex %= lNbOfElts;
      if (iIndex<0) iIndex+=lNbOfElts;
    }
    if ( iIndex >= 0 && iIndex < lNbOfElts )
    {
      hWayPoint1 = MSWay_fn_hGetWayPointOfPath(hWay, iIndex ) ;
      hWayPoint2 = MSWay_fn_hGetWayPointOfPath(hWay, iIndex+1 ) ;
      if ( hWayPoint2 )
      {
        if (WPG_fn_lGetLinkWeight (hWay->m_hPath, hWayPoint1, hWayPoint2, &lValue)== -1 )
          return (0);
        return ( lValue ) ;
      }
    }
  }
  return (0) ;
}
 
long MSWay_fn_lChangeWeightForNextWayPointOfPath (MS_tdxHandleToMSWay hWay, int iIndex, long lWeight)
{
  WP_tdhWayPoint hWayPoint1, hWayPoint2 ;
  long lNbOfElts;
 
  if ( hWay && hWay->m_hPath != NULL)
  {
    lNbOfElts = LST2_M_DynamicGetNumberOfElements(&hWay->m_hPath->m_hListOfNode);
    if (hWay->m_bIsCircular)
    {
      iIndex %= lNbOfElts;
      if (iIndex<0) iIndex+=lNbOfElts;
    }
    if ( iIndex >= 0 && iIndex < lNbOfElts )
    {
      hWayPoint1 = MSWay_fn_hGetWayPointOfPath(hWay, iIndex ) ;
      hWayPoint2 = MSWay_fn_hGetWayPointOfPath(hWay, iIndex+1 ) ;
      if ( hWayPoint2 )
      {
        return (WPG_fn_lChangeLinkWeight (hWay->m_hPath, hWayPoint1, hWayPoint2, lWeight)); /* -1 if error*/
      }
    }
  }
  return (-1) ;
}
 
 
