/*---------------------------------------------------------------------------*/
/* Action table functions for intelligence engine*/
/* author : Olivier Couvreur*/
/* modify : 07/11/96 Olivier Couvreur  */
/* modify : 03/02/97 Olivier Couvreur Lint 0 warnings */
/* modify : 26/02/97 Olivier Couvreur added Schedule support + Lint 0 warnings*/
/* modify : 05/03/97 Olivier Couvreur added Schedule function + Lint 0 warnings*/
/* modify : 25/03/97 Olivier Couvreur added REVERSE_RULES support + optimizations (not yet activated)*/
/*---------------------------------------------------------------------------*/
#include "AIUseCPA.h"
#include "specif/AIOption.h"
 
#include "specif/ActTable.h"
#include "StrIntel.h"
#include "Action.h"
 
/*****************************************************************************************************/
/* here we can have more than one action in action table */
/* XB 20/05/1999 */
#ifndef D_THROW_COMPLEX_ACTION_TABLE
/* OPTIMIZE_ACTION_TABLE is defined in AIOption.h*/
 
/* check if a rule is in action table : return entry number*/
unsigned char fn_ucIsRuleInActionTable(tdstIntelligence *p_stIntelligence,unsigned char ucNumRule)
{
	/* Modif YLG*/
    unsigned char ucNbEntries;
	ucNbEntries = M_ActionTableNbEntries(p_stIntelligence);
 
    if (M_IsActionTableUsed(p_stIntelligence))
    {
        unsigned char ucCurrentEntry;
		struct tdstActionTableEntry_ *p_stEntry;
 
		p_stEntry = &(M_ActionTableEntryN(p_stIntelligence, 0));
        for (ucCurrentEntry=0;ucCurrentEntry<ucNbEntries;ucCurrentEntry++, p_stEntry++)
        {
			if (p_stEntry->bUsed)
            {
                if (p_stEntry->ucNumRule==ucNumRule)
                {
                    return(ucCurrentEntry);
                }
            }
        }
    }	
	return (ucNbEntries);
}
 
 
/* check if a rule and a node are in action table : return entry number*/
unsigned char fn_ucIsRuleAndNodeInActionTable(tdstIntelligence *p_stIntelligence,unsigned char ucNumRule,tdstNodeInterpret *p_stNode)
{
	/* Modif YLG*/
    unsigned char ucNbEntries;
 
	ucNbEntries = M_ActionTableNbEntries(p_stIntelligence);
    if (M_IsActionTableUsed(p_stIntelligence))
    {
        unsigned char ucCurrentEntry;       
		struct tdstActionTableEntry_ *p_stEntry;
 
		p_stEntry = &(M_ActionTableEntryN(p_stIntelligence, 0));
 
        for (ucCurrentEntry=0;ucCurrentEntry<ucNbEntries;ucCurrentEntry++, p_stEntry++)
        {
/*            if (M_ActionTableUseFlag(p_stIntelligence,ucCurrentEntry))*/
			if (p_stEntry->bUsed)
            {
/*                if (M_ActionTableNumRule(p_stIntelligence,ucCurrentEntry)==ucNumRule)*/
                if (p_stEntry->ucNumRule==ucNumRule)
                {
/*                    if (M_ActionTableNumNode(p_stIntelligence,ucCurrentEntry)==p_stNode)*/
                    if (p_stEntry->p_stNode ==p_stNode)
                    {
                        return(ucCurrentEntry);
                    }
                }
            }
        }
    }	
/*    return(M_ActionTableNbEntries(p_stIntelligence));*/
	return (ucNbEntries);
}
 
/* find a free entry in action table : return entry number*/
unsigned char fn_ucFindPlaceInActionTable(tdstIntelligence *p_stIntelligence)
{
	/* Modif YLG*/
    unsigned char ucCurrentEntry;   
    unsigned char ucNbEntries;
        
	ucNbEntries = M_ActionTableNbEntries(p_stIntelligence);
/*    if (M_ActionTableNbEntriesUsed(p_stIntelligence)<M_ActionTableNbEntries(p_stIntelligence))*/
    if (M_ActionTableNbEntriesUsed(p_stIntelligence)<ucNbEntries)
    {
		struct tdstActionTableEntry_ *p_stEntry;
 
		p_stEntry = &(M_ActionTableEntryN(p_stIntelligence, 0));
 
		/*        for (ucCurrentEntry=0;ucCurrentEntry<M_ActionTableNbEntries(p_stIntelligence);ucCurrentEntry++)*/
        for (ucCurrentEntry=0;ucCurrentEntry<ucNbEntries;ucCurrentEntry++,p_stEntry++)
        {
/*            if (!M_ActionTableUseFlag(p_stIntelligence,ucCurrentEntry))*/
			if (!p_stEntry->bUsed)
            {
                return(ucCurrentEntry);
            }
        }
    }
/*    return(M_ActionTableNbEntries(p_stIntelligence));*/
	return (ucNbEntries);
}
 
static void fn_vInitActionTableEntry(tdstIntelligence *p_stIntelligence,unsigned char ucNEntry,unsigned char ucNumRule,tdstNodeInterpret *p_stNode,unsigned char bfUsed)
{    
	/* modif YLG*/
	M_ActionTableUseActionReturn(p_stIntelligence,ucNEntry) = g_ucUseDefaultActionReturn;
    M_ActionTableNewActionReturn(p_stIntelligence,ucNEntry) = g_ucNewActionReturn;
    M_ActionTableUseFlag(p_stIntelligence,ucNEntry)=bfUsed;  
    M_ActionTableNumNode(p_stIntelligence,ucNEntry)=p_stNode;
    M_ActionTableNumRule(p_stIntelligence,ucNEntry)=ucNumRule;
    memset(&(M_ActionTableParam(p_stIntelligence,ucNEntry)),0,sizeof(M_ActionTableParam(p_stIntelligence,ucNEntry)));
}
 
#if !defined(OPTIMIZE_ACTION_TABLE)
/* internal function*/
void fn_vUpdateActionTable(tdstIntelligence *p_stIntelligence)
{
    unsigned char ucCurrentEntry;
    
    M_ActionTableNbEntriesUsed(p_stIntelligence)=0;
    for (ucCurrentEntry=0;ucCurrentEntry<M_ActionTableNbEntries(p_stIntelligence);ucCurrentEntry++)
    {
        if (M_ActionTableUseFlag(p_stIntelligence,ucCurrentEntry))
        {
            /*update NbEntriesUsed */
            M_ActionTableNbEntriesUsed(p_stIntelligence)+=1;
        }
    }
}
#endif
 
/* use current entry in action table*/
void fn_vUseCurrentActionTableEntry(tdstIntelligence *p_stIntelligence,unsigned char ucNRule,tdstNodeInterpret *p_stNode)
{
#if defined(OPTIMIZE_ACTION_TABLE)
    unsigned char ucCurrentEntry=M_ActionTableCurrentEntry(p_stIntelligence);
    if (!M_ActionTableUseFlag(p_stIntelligence,ucCurrentEntry))
    {
        fn_vInitActionTableEntry(p_stIntelligence,ucCurrentEntry,ucNRule,p_stNode,1);
        M_ActionTableNbEntriesUsed(p_stIntelligence)++;
    }
#else
    /* reinit current entry in action table*/
    fn_vInitActionTableEntry(p_stIntelligence,M_ActionTableCurrentEntry(p_stIntelligence),ucNRule,p_stNode,1);
    
    /* update action table*/
    fn_vUpdateActionTable(p_stIntelligence);
#endif    /* reinit current entry in action table*/
}
 
/* free current entry in action table*/
void fn_vUnuseCurrentActionTableEntry(tdstIntelligence *p_stIntelligence)
{
/* YLG Modif*/
#if defined(OPTIMIZE_ACTION_TABLE)
    unsigned char ucCurrentEntry=M_ActionTableCurrentEntry(p_stIntelligence);
    if (M_ActionTableUseFlag(p_stIntelligence,ucCurrentEntry))
    {
        fn_vInitActionTableEntry(p_stIntelligence,ucCurrentEntry,0,NULL,0);
        M_ActionTableNbEntriesUsed(p_stIntelligence)--;
    }
#else
    /* reinit current entry in action table*/
    fn_vInitActionTableEntry(p_stIntelligence,M_ActionTableCurrentEntry(p_stIntelligence),0,NULL,0);
    
    /* update action table*/
    fn_vUpdateActionTable(p_stIntelligence);
#endif
}
 
void fn_vUnuseAllRulesWhichHaveGreaterNumRule(struct tdstIntelligence_ *p_stIntelligence,unsigned char ucNumRule)
{
	/* Modif YLG*/
    unsigned char ucNbEntries;
      
	ucNbEntries = M_ActionTableNbEntries(p_stIntelligence);
    /* action table not used*/
    if (M_IsActionTableUsed(p_stIntelligence))
    {
        unsigned char					ucCurrentEntry;
		struct tdstActionTableEntry_	*p_stEntry;
 
		p_stEntry = &(M_ActionTableEntryN(p_stIntelligence, 0));       
        for (ucCurrentEntry=0;ucCurrentEntry<ucNbEntries;ucCurrentEntry++, p_stEntry++)
        {
/*            if (M_ActionTableUseFlag(p_stIntelligence,ucCurrentEntry))*/
			if (p_stEntry->bUsed)
            {
                if (
                    /* exclude rule from schedule*/
/*                    (M_ActionTableNumRule(p_stIntelligence,ucCurrentEntry)>0)*/
/*                   &&(M_ActionTableNumRule(p_stIntelligence,ucCurrentEntry)>ucNumRule)*/
					p_stEntry -> ucNumRule > ucNumRule
                    )
                {
                    fn_vInitActionTableEntry(p_stIntelligence,ucCurrentEntry,0,NULL,0);
                    M_ActionTableNbEntriesUsed(p_stIntelligence)--;
                }
            }
        }
        /* update action table*/
#if !defined(OPTIMIZE_ACTION_TABLE)
        fn_vUpdateActionTable(p_stIntelligence);
#endif
    }
}
 
void fn_vUnuseAllRulesFromSchedule(struct tdstIntelligence_ *p_stIntelligence)
{
	/* Modif YLG*/
    unsigned char ucNbEntries;
 
    /* action table not used*/
    if (M_IsActionTableUsed(p_stIntelligence))
    {
        unsigned char ucCurrentEntry;
		struct tdstActionTableEntry_	*p_stEntry;
 
		ucNbEntries = M_ActionTableNbEntries(p_stIntelligence);
		p_stEntry = &(M_ActionTableEntryN(p_stIntelligence, 0));       
        
/*        for (ucCurrentEntry=0;ucCurrentEntry<M_ActionTableNbEntries(p_stIntelligence);ucCurrentEntry++)*/
        for (ucCurrentEntry=0;ucCurrentEntry<ucNbEntries;ucCurrentEntry++, p_stEntry++)
        {
/*            if (M_ActionTableUseFlag(p_stIntelligence,ucCurrentEntry))*/
	   		  if (p_stEntry->bUsed)
              {
                /* only rule from schedule*/
/*                if (M_ActionTableNumRule(p_stIntelligence,ucCurrentEntry)==0)*/
                if (p_stEntry->ucNumRule==0)
                {
                    fn_vInitActionTableEntry(p_stIntelligence,ucCurrentEntry,0,NULL,0);
                    /*M_ActionTableNbEntriesUsed(p_stIntelligence)--;*/
					ucNbEntries --;
                }
            }
        }
        M_ActionTableNbEntriesUsed(p_stIntelligence) = ucNbEntries;
#if !defined(OPTIMIZE_ACTION_TABLE)
        /* update action table*/
        fn_vUpdateActionTable(p_stIntelligence);
#endif
    }
}
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
tdstNodeInterpret *fn_p_stGetScheduleFromActionTableAndClearIt(tdstIntelligence *p_stIntelligence)
{
	/* MOdif ylg*/
    tdstNodeInterpret	*p_stFoundSchedule=NULL;
    unsigned char		ucNbEntries;
    
    /* action table not used*/
    if (M_IsActionTableUsed(p_stIntelligence))
    {
        unsigned char					ucCurrentEntry;
		struct tdstActionTableEntry_	*p_stEntry;
 
		ucNbEntries = M_ActionTableNbEntries(p_stIntelligence);
		p_stEntry = &(M_ActionTableEntryN(p_stIntelligence, 0));       
        
        /* loop in action table*/
/*        for (ucCurrentEntry=0;ucCurrentEntry<M_ActionTableNbEntries(p_stIntelligence);ucCurrentEntry++)*/
        for (ucCurrentEntry=0;ucCurrentEntry<ucNbEntries;ucCurrentEntry++, p_stEntry++)
        {
            /* is this entry used ?*/
/*            if (M_ActionTableUseFlag(p_stIntelligence,ucCurrentEntry))*/
	   		if (p_stEntry->bUsed)
            {
                /* is this entry belonging to schedule (==0) ?*/
                /*if (M_ActionTableNumRule(p_stIntelligence,ucCurrentEntry)==0)*/
                if (p_stEntry->ucNumRule==0)
                {
                    /* keep the first one found*/
                    /*
                    if (p_stFoundSchedule==NULL) 
                    {
                    p_stFoundSchedule=M_ActionTableNumNode(p_stIntelligence,ucCurrentEntry);
                    }
                    */
                    
                    /* keep the first one found or the first one in the schedule*/
/*                    if ( (p_stFoundSchedule==NULL) || (M_ActionTableNumNode(p_stIntelligence,ucCurrentEntry)<p_stFoundSchedule) )*/
                    if ( (p_stFoundSchedule==NULL) || (p_stEntry->p_stNode<p_stFoundSchedule) )
                    {
/*                        p_stFoundSchedule=M_ActionTableNumNode(p_stIntelligence,ucCurrentEntry);*/
                        p_stFoundSchedule=p_stEntry->p_stNode;
                    }
                    
                    /* clear schedule entry*/
                    fn_vInitActionTableEntry(p_stIntelligence,ucCurrentEntry,0,NULL,0);
/*                    M_ActionTableNbEntriesUsed(p_stIntelligence)--;*/
					ucNbEntries --;
                }
            }
        }
        M_ActionTableNbEntriesUsed(p_stIntelligence) = ucNbEntries;
 
#if !defined(OPTIMIZE_ACTION_TABLE)
        /* update action table*/
        fn_vUpdateActionTable(p_stIntelligence);
#endif
    }	
    return(p_stFoundSchedule);
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/* used by InitPerso*/
void fn_vInitActionTable(tdstIntelligence *p_stIntelligence)
{
	/* Modif YLG*/
    unsigned char	ucNEntry; 
    unsigned char	ucNbEntries;
    
    M_ActionTableNbEntriesUsed(p_stIntelligence)=0;
    M_ActionTableCurrentEntry(p_stIntelligence)=0;
	ucNbEntries = M_ActionTableNbEntries(p_stIntelligence);
/*    for (ucNEntry=0;ucNEntry<M_ActionTableNbEntries(p_stIntelligence);ucNEntry++)*/
    for (ucNEntry=0;ucNEntry<ucNbEntries;ucNEntry++)
    {
        fn_vInitActionTableEntry(p_stIntelligence,ucNEntry,0,NULL,0);
    }
}
 
tdstNodeInterpret *fn_p_stGetTableAction(tdstIntelligence *p_stIntelligence, unsigned char ucNEntry)
{
/* Modif YLG*/
/*    fn_vSetUseDefaultActionReturnValue(M_ActionTableUseActionReturn(p_stIntelligence,ucNEntry));*/
	g_ucUseDefaultActionReturn = M_ActionTableUseActionReturn(p_stIntelligence,ucNEntry);
/*   fn_vSetNewActionReturnValue(M_ActionTableNewActionReturn(p_stIntelligence,ucNEntry));*/
	g_ucNewActionReturn = M_ActionTableNewActionReturn(p_stIntelligence,ucNEntry);
    return M_ActionTableNumNode(p_stIntelligence, ucNEntry);
}

/*****************************************************************************************************/
/* here only one action in action table */
#else /* D_THROW_COMPLEX_ACTION_TABLE */

/* check if a rule is in action table : return entry number*/
unsigned char fn_ucIsRuleInActionTable(tdstIntelligence *p_stIntelligence,unsigned char ucNumRule)
{
	if(M_ActionTable(p_stIntelligence))
	{
		struct tdstActionTableEntry_ *p_stEntry;

		p_stEntry = &(M_ActionTableEntry0(p_stIntelligence));

		if((p_stEntry->bUsed == TRUE) &&
			 (p_stEntry->ucNumRule == ucNumRule))
		{
			return 0;
		}
	}	

	return 1;
}
 
 
/* check if a rule and a node are in action table : return entry number*/
unsigned char fn_ucIsRuleAndNodeInActionTable(tdstIntelligence *p_stIntelligence,unsigned char ucNumRule,tdstNodeInterpret *p_stNode)
{
	if(M_ActionTable(p_stIntelligence))
	{
		struct tdstActionTableEntry_ *p_stEntry;

		p_stEntry = &(M_ActionTableEntry0(p_stIntelligence));

		if((p_stEntry->bUsed == TRUE) &&
		   (p_stEntry->ucNumRule == ucNumRule) &&
			 (p_stEntry->p_stNode == p_stNode))
		{
			return 0;
		}
	}	
	return 1;
}
 
/* find a free entry in action table : return entry number*/
unsigned char fn_ucFindPlaceInActionTable(tdstIntelligence *p_stIntelligence)
{
	if(M_ActionTable(p_stIntelligence))
	{
		if(!(M_ActionTableUseFlag0(p_stIntelligence)))
		{
			return 0;
		}
	}

	return 1;
}
 
static void fn_vInitActionTableEntry(tdstIntelligence *p_stIntelligence,unsigned char ucNumRule,tdstNodeInterpret *p_stNode,unsigned char bfUsed)
{    
	struct tdstActionTableEntry_ *p_stEntry;

	p_stEntry = &(M_ActionTableEntry0(p_stIntelligence));

	p_stEntry->bUseDefaultActionReturn=g_ucUseDefaultActionReturn;
	p_stEntry->ucNewActionReturn=g_ucNewActionReturn;
	p_stEntry->bUsed=bfUsed;
	p_stEntry->p_stNode=p_stNode;
	p_stEntry->ucNumRule=ucNumRule;

	memset(&(p_stEntry->stActionParam),0,sizeof(p_stEntry->stActionParam));
}
 
/* use current entry in action table*/
void fn_vUseCurrentActionTableEntry(tdstIntelligence *p_stIntelligence,unsigned char ucNRule,tdstNodeInterpret *p_stNode)
{
	if(!M_ActionTableUseFlag0(p_stIntelligence))
	{
		fn_vInitActionTableEntry(p_stIntelligence,ucNRule,p_stNode,1);
	}
}
 
/* free current entry in action table*/
void fn_vUnuseCurrentActionTableEntry(tdstIntelligence *p_stIntelligence)
{
	if (M_ActionTableUseFlag0(p_stIntelligence))
	{
		fn_vInitActionTableEntry(p_stIntelligence,0,NULL,0);
	}
}
 
void fn_vUnuseAllRulesWhichHaveGreaterNumRule(struct tdstIntelligence_ *p_stIntelligence,unsigned char ucNumRule)
{
	if(M_ActionTable(p_stIntelligence))
	{
		struct tdstActionTableEntry_ *p_stEntry;

		p_stEntry = &(M_ActionTableEntry0(p_stIntelligence));

		if((p_stEntry->bUsed) &&
			 (p_stEntry->ucNumRule>ucNumRule))
		{
			fn_vInitActionTableEntry(p_stIntelligence,0,NULL,0);
		}
	}
}
 
void fn_vUnuseAllRulesFromSchedule(struct tdstIntelligence_ *p_stIntelligence)
{
	if (M_ActionTable(p_stIntelligence))
	{
		struct tdstActionTableEntry_ *p_stEntry;

		p_stEntry = &(M_ActionTableEntry0(p_stIntelligence));

		/* only rule from schedule*/
		if((p_stEntry->bUsed) &&
		   (p_stEntry->ucNumRule==0))
		{
			fn_vInitActionTableEntry(p_stIntelligence,0,NULL,0);
		}
	}
}
 
/* used by InitPerso*/
void fn_vInitActionTable(tdstIntelligence *p_stIntelligence)
{
	if(M_ActionTable(p_stIntelligence))
	{
		fn_vInitActionTableEntry(p_stIntelligence,0,NULL,0);
	}
}
 
tdstNodeInterpret *fn_p_stGetTableAction(tdstIntelligence *p_stIntelligence, unsigned char ucNEntry)
{
	struct tdstActionTableEntry_ *p_stEntry;

	p_stEntry = &(M_ActionTableEntry0(p_stIntelligence));

	g_ucUseDefaultActionReturn	= p_stEntry->bUseDefaultActionReturn;
	g_ucNewActionReturn					= p_stEntry->ucNewActionReturn;

  return p_stEntry->p_stNode;
}

#endif /* D_THROW_COMPLEX_ACTION_TABLE */
/* End XB 20/05/1999 */
