/*******************************************************************
/*  DiskRecUnit.cpp
/*  Author: Vadim Berman
/*
/*  Description:
/*  implementation of non-member functions used to load data composed in
/*  Data Manager
/*
/*  The contents of this file are subject to the Brainiac Public License.
/*  Version 1.0 (the "License"); you may not use this file except in
/*  compliance with the License. You may obtain a copy of the License at
/*  http://www.twilightminds.com
/*
/*  Software distributed under the License is distributed on an "AS IS"
/*  basis WITHOUT WARRANTY OF ANY KIND, either express or implied. See
/*  the License for the specific language governing rights and limitations
/*  under the License.
/*
/*  Copyright (C) 1999 Twilight Minds. All rights reserved.
/********************************************************************/
//---------------------------------------------------------------------------
#include "DiskRecUnit.h"

extern GoalDefNodeP 		GoalListHead;
extern ActionDefNodeP		ActionListHead;
extern StrategyDefNodeP	    StrategyListHead;
extern MindDefNodeP         MindListHead;
extern HMODULE hBE;
extern ModuleEntry *Modules;
extern unsigned short nExtModules;

//***************************************************************************
//Buf2GoalRec
//********** Description: **************
//read Goal record from buffer and return it through reference
//********** Parameters:  **************
//BYTE *RecBuf               - buffer
//GoalFileRec& GoalRecordBuf - holder for a goal record
//---------------------------------------------------------------------------
void BBECALL Buf2GoalRec(BYTE *RecBuf,GoalFileRec& GoalRecordBuf)
{
    long i = 0;
	GoalRecordBuf.GoalItself = RecBuf[i++];
    GoalRecordBuf.GoalImportance = RecBuf[i++];
    GoalRecordBuf.CompType = RecBuf[i++];
    GoalRecordBuf.AllowedEnvironment = RecBuf[i++];
    GoalRecordBuf.IdFlag1 = RecBuf[i++];
    GoalRecordBuf.IdFlag2 = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LWickedness = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HWickedness = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAnarchy = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAnarchy = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAtt2Eval = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAtt2Eval = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAttByEval = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAttByEval = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAtt2StrObj = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAtt2StrObj = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAttByStrObj = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAttByStrObj = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAtt2LastInit = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAtt2LastInit = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAttByLastInit = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAttByLastInit = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAtt2RefActObj = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAtt2RefActObj = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LAttByRefActObj = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HAttByRefActObj = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.AttRefAct = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LUserDefAtt = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HUserDefAtt = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.UserDefAttId = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LMeanness = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HMeanness = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LSeemMean = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HSeemMean = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LWealth = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HWealth = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LSeemWeal = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HSeemWeal = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LBeauty = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HBeauty = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LSeemInt = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HSeemInt = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LForeignness = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HForeignness = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LIntelligence = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HIntelligence = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LCourage = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HCourage = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;

    memcpy(GoalRecordBuf.Descr,RecBuf+i,26);
    i += 26;
    memcpy(GoalRecordBuf.Unused,RecBuf+i,28);
    i += 26;
    GoalRecordBuf.IncGoalID = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.AttDir = RecBuf[i++];
    GoalRecordBuf.Dead = RecBuf[i++];
    GoalRecordBuf.LUser1 = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HUser1 = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LUser2 = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HUser2 = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.LUser3 = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    GoalRecordBuf.HUser3 = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;

    GoalRecordBuf.IsDeleted = RecBuf[i];
}

//***************************************************************************
//Buf2ActRec
//********** Description: **************
//read Action record from buffer and return it through reference
//********** Parameters:  **************
//BYTE *RecBuf              - buffer
//GoalFileRec& ActRecordBuf - holder for an Action record
//-----------------------------------------------------------------------------
void BBECALL Buf2ActRec(BYTE *RecBuf,ActFileRec& ActRecordBuf)
{
    long i = 0;
	ActRecordBuf.ActionID = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    memcpy(ActRecordBuf.Verb,(unsigned char*)(RecBuf+i),VERB_LEN);
    i += VERB_LEN;
    ActRecordBuf.AType = (ActionType)RecBuf[i++];
    ActRecordBuf.AttitudeChange = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    ActRecordBuf.FModule = RecBuf[i++];
    memcpy(ActRecordBuf.FunctionLabel,RecBuf+i,FUNCTION_LEN);
    i += FUNCTION_LEN;
    ActRecordBuf.MinIntel = RecBuf[i++];
    ActRecordBuf.ReqCourage = RecBuf[i++];
    ActRecordBuf.Difficulty = RecBuf[i++];
	ActRecordBuf.Wickedness = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    ActRecordBuf.Anarchy = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    ActRecordBuf.MinAttitude = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    ActRecordBuf.MaxAttitude = (signed short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    memcpy(ActRecordBuf.Reserved,RecBuf+i,20);
    i += 20;
    ActRecordBuf.IsDeleted = RecBuf[i];
}

//***************************************************************************
//Buf2StrRec
//********** Description: **************
//read Strategy record from buffer and return it through reference
//********** Parameters:  **************
//BYTE *RecBuf              - buffer
//GoalFileRec& StrRecordBuf - holder for a Strategy record
//-----------------------------------------------------------------------------
void BBECALL Buf2StrRec(BYTE *RecBuf,StrFileRec& StrRecordBuf)
{
    unsigned long i = 0, j, nCurPos;

	StrRecordBuf.StrategyID = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    memmove(StrRecordBuf.StrategyName,RecBuf+i,16);
    i += 16;
    memmove(StrRecordBuf.Descr,RecBuf+i,51);
    i += 51;
    StrRecordBuf.GoalItself = RecBuf[i++];
    StrRecordBuf.GoalImportance = RecBuf[i++];
    StrRecordBuf.MaxIntel = RecBuf[i++];
    for(j = 0; j < 99 ;j++ )
    {
        nCurPos = j*(sizeof(unsigned short) + 3*sizeof(unsigned char))
            + i;
        StrRecordBuf.Actions[j].ActionIDs = (unsigned short)(RecBuf[nCurPos] + RecBuf[nCurPos + 1]*256);
        StrRecordBuf.Actions[j].TAC = RecBuf[nCurPos + 2];
        StrRecordBuf.Actions[j].ReferencedTAC = RecBuf[nCurPos + 3];
        StrRecordBuf.Actions[j].ConditionalGoto = RecBuf[nCurPos + 4];
    }
    i += (99 * (sizeof(unsigned short) + 3*sizeof(unsigned char)));
    StrRecordBuf._Type = RecBuf[i++];
    memmove(StrRecordBuf.MiscFlags,RecBuf+i,4);
    i += 4;
    StrRecordBuf.IsDeleted = RecBuf[i];

}

//***************************************************************************
//AddNewGoalNode
//********** Description: **************
//add a new Goal / criterion node read from the given record
//********** Parameters:  **************
//GoalFileRec rec - Goal record
//-----------------------------------------------------------------------------
BOOL BBECALL AddNewGoalNode(GoalFileRec rec)
{
    if (rec.IsDeleted || rec.GoalItself == 0)
    {
    	return TRUE;
    }

    GoalDefNodeP gp = new struct _GoalDefNode;
    if (gp == NULL)
    	return FALSE;

    memset(gp,ERROR_PERCENTAGE,sizeof(struct _GoalDefNode));

    gp->goal.Itself = rec.GoalItself;
    gp->goal.Importance = rec.GoalImportance;
    gp->CompType = rec.CompType;

    memcpy(gp->Descr, rec.Descr, 26);
    gp->LoReqs.alType = alTrueNeutral;
    gp->HiReqs.alType = alTrueNeutral;
	gp->LoReqs.Wickedness = (percentage)rec.LWickedness;
	gp->HiReqs.Wickedness = (percentage)rec.HWickedness;
  	gp->LoReqs.Anarchy = (percentage)rec.LAnarchy;
  	gp->HiReqs.Anarchy = (percentage)rec.HAnarchy;

    //here target's attitude to evaluator is stored
    if(rec.LAttByEval == ERROR_UBYTE
        || rec.HAttByEval == ERROR_UBYTE)
    {
  	    gp->LoReqs.InitialAttitude = ERROR_PERCENTAGE;
  	    gp->HiReqs.InitialAttitude = ERROR_PERCENTAGE;
    }
    else
    {
  	    gp->LoReqs.InitialAttitude = (percentage)rec.LAttByEval; //CRIT_ATT_BY_EVAL
  	    gp->HiReqs.InitialAttitude = (percentage)rec.HAttByEval; //CRIT_ATT_BY_EVAL
    }

    gp->LoReqs.AttitudeChangeUnit = ERROR_PERCENTAGE;
    gp->HiReqs.AttitudeChangeUnit = ERROR_PERCENTAGE;
  	gp->LoReqs.SuddenChange = ERROR_PERCENTAGE;
  	gp->HiReqs.SuddenChange = ERROR_PERCENTAGE;
  	gp->LoReqs.LieProbability = ERROR_PERCENTAGE;
  	gp->HiReqs.LieProbability = ERROR_PERCENTAGE;
  	gp->LoReqs.Meanness[0] = (percentage)rec.LMeanness;
  	gp->LoReqs.Meanness[1] = (percentage)rec.LMeanness;
  	gp->HiReqs.Meanness[0] = (percentage)rec.HMeanness;
  	gp->HiReqs.Meanness[1] = (percentage)rec.HMeanness;
    gp->LoReqs.Wealth[0] = (percentage)rec.LWealth;
    gp->LoReqs.Wealth[1] = (percentage)rec.LWealth;
    gp->HiReqs.Wealth[0] = (percentage)rec.HWealth;
    gp->HiReqs.Wealth[1] = (percentage)rec.HWealth;
    gp->LoReqs.Beauty = (percentage)rec.LBeauty;
    gp->HiReqs.Beauty = (percentage)rec.HBeauty;
    gp->LoReqs.Intelligence[0] = (percentage)rec.LSeemInt;
    gp->HiReqs.Intelligence[0] = (percentage)rec.HSeemInt;
	gp->LoReqs.Foreignness = (percentage)rec.LForeignness;
	gp->HiReqs.Foreignness = (percentage)rec.HForeignness;
	gp->LoReqs.Intelligence[1] = (percentage)rec.LIntelligence;
	gp->HiReqs.Intelligence[1] = (percentage)rec.HIntelligence;
  	gp->LoReqs.Courage = (percentage)rec.LCourage;
  	gp->HiReqs.Courage = (percentage)rec.HCourage;
  	gp->LoReqs.attId = 0;
  	gp->HiReqs.attId = 0;
  	gp->LoReqs.attPersonal = NULL;
  	gp->HiReqs.attPersonal = NULL;
  	gp->LoReqs.UserDefined[0] = rec.LUser1;
  	gp->HiReqs.UserDefined[0] = rec.HUser1;
  	gp->LoReqs.UserDefined[1] = rec.LUser2;
  	gp->HiReqs.UserDefined[1] = rec.HUser2;
  	gp->LoReqs.UserDefined[2] = rec.LUser3;
  	gp->HiReqs.UserDefined[2] = rec.HUser3;
    //limit the interaction environment
    gp->LoReqs.CurrentEnvironment = rec.AllowedEnvironment;
    gp->HiReqs.CurrentEnvironment = rec.AllowedEnvironment;
    switch(rec.Dead)
    {
        case 0:
            gp->LoReqs.Dead = FALSE;
            gp->HiReqs.Dead = FALSE;
            break;
        case 1:
            gp->LoReqs.Dead = TRUE;
            gp->HiReqs.Dead = TRUE;
            break;
        default:
            gp->LoReqs.Dead = FALSE;
            gp->HiReqs.Dead = TRUE;
            break;
    }

    gp->AttDir = rec.AttDir;
    gp->IdFlag1 = rec.IdFlag1;
    gp->IdFlag2 = rec.IdFlag2;
    gp->IncGoalID = rec.IncGoalID;

    if(rec.LAtt2Eval != ERROR_UBYTE && rec.HAtt2Eval != ERROR_UBYTE)
    {
        AddAttitude(CRIT_ATT2EVAL,rec.LAtt2Eval,&(gp->LoReqs.attPersonal));
        AddAttitude(CRIT_ATT2EVAL,rec.HAtt2Eval,&(gp->HiReqs.attPersonal));
        //that's we way I store it
        gp->LoReqs.AttitudeChangeUnit = rec.LAtt2Eval;
        gp->HiReqs.AttitudeChangeUnit = rec.HAtt2Eval;
    }

    if(rec.LAtt2StrObj != ERROR_UBYTE && rec.HAtt2StrObj != ERROR_UBYTE)
    {
        AddAttitude(CRIT_ATT2STROBJ,rec.LAtt2StrObj,&(gp->LoReqs.attPersonal));
        AddAttitude(CRIT_ATT2STROBJ,rec.HAtt2StrObj,&(gp->HiReqs.attPersonal));
    }

    if(rec.LAttByStrObj != ERROR_UBYTE && rec.HAttByStrObj != ERROR_UBYTE)
    {
        AddAttitude(CRIT_ATT_BY_STROBJ,rec.LAttByStrObj,&(gp->LoReqs.attPersonal));
        AddAttitude(CRIT_ATT_BY_STROBJ,rec.HAttByStrObj,&(gp->HiReqs.attPersonal));
    }

    if(rec.LAtt2LastInit != ERROR_UBYTE && rec.HAtt2LastInit != ERROR_UBYTE)
    {
        AddAttitude(CRIT_ATT2LASTINIT,rec.LAtt2LastInit,&(gp->LoReqs.attPersonal));
        AddAttitude(CRIT_ATT2LASTINIT,rec.HAtt2LastInit,&(gp->HiReqs.attPersonal));
    }

    if(rec.LAtt2LastInit != ERROR_UBYTE && rec.HAtt2LastInit != ERROR_UBYTE)
    {
        AddAttitude(CRIT_ATT_BY_LASTINIT,rec.LAttByStrObj,&(gp->LoReqs.attPersonal));
        AddAttitude(CRIT_ATT_BY_LASTINIT,rec.HAttByStrObj,&(gp->HiReqs.attPersonal));
    }

    gp->AttRefAct = rec.AttRefAct;
    if(gp->AttRefAct)
    {
        if(rec.LAtt2RefActObj != ERROR_UBYTE && rec.HAtt2RefActObj != ERROR_UBYTE)
        {
            AddAttitude(CRIT_ATT2REFACTOBJ,rec.LAtt2RefActObj,
                &(gp->LoReqs.attPersonal));
            AddAttitude(CRIT_ATT2REFACTOBJ,rec.HAtt2RefActObj,
                &(gp->HiReqs.attPersonal));
        }

        if(rec.LAttByRefActObj != ERROR_UBYTE && rec.HAttByRefActObj != ERROR_UBYTE)
        {
            AddAttitude(CRIT_ATT_BY_REFACTOBJ,rec.LAttByRefActObj,
                &(gp->LoReqs.attPersonal));
            AddAttitude(CRIT_ATT_BY_REFACTOBJ,rec.HAttByRefActObj,
                &(gp->HiReqs.attPersonal));
        }
    }

    if(rec.LUserDefAtt != ERROR_UBYTE && rec.HUserDefAtt != ERROR_UBYTE)
    {
        AddAttitude(rec.UserDefAttId,rec.LUserDefAtt,&(gp->LoReqs.attPersonal));
        AddAttitude(rec.UserDefAttId,rec.HUserDefAtt,&(gp->HiReqs.attPersonal));
    }
    gp->UserDefAttID = rec.UserDefAttId;

	//add this... thingy to list
    gp->next = GoalListHead;
    GoalListHead = gp;
    return TRUE;
}

//***************************************************************************
//AddNewActNode
//********** Description: **************
//add a new Action node read from the given record
//********** Parameters:  **************
//ActFileRec rec            - Action record
//int (*DefActionFn)(void*) - default Action handler
//-----------------------------------------------------------------------------
BOOL BBECALL AddNewActNode(ActFileRec rec,int (BBECALL *DefActionFn)(void*))
{
    HMODULE hFnMod;
    if (rec.IsDeleted || rec.ActionID == 0)
    {
    	return TRUE;
    }
	ActionDefNodeP ap = new struct _ActionDefNode;
    if (ap == NULL)
    	return FALSE;
	ap->ActionID = rec.ActionID;
	strncpy(ap->Verb, rec.Verb, 16);
    ap->_Type = rec.AType;
    ap->Difficulty = rec.Difficulty;
    ap->Wickedness = (percentage)rec.Wickedness;
    ap->Anarchy = (percentage)rec.Anarchy;
	ap->AttitudeChange = rec.AttitudeChange;
    ap->MinIntel = rec.MinIntel;
    ap->ReqCourage = rec.ReqCourage;
	ap->Difficulty = rec.Difficulty;
    ap->MinAttitude = (percentage)rec.MinAttitude;
    ap->MaxAttitude = (percentage)rec.MaxAttitude;
    ap->ModNum = rec.FModule;
    hFnMod = hBE;
    if(ap->ModNum != MODULE_BE)
        for(int i = 0; i < nExtModules; i++)
            if(Modules[i].ModId == ap->ModNum)
            {
                hFnMod = Modules[i].hMod;
                break;
            }
    ap->ActionFn = (int(BBECALL *)(void*))GetProcAddress(hFnMod,rec.FunctionLabel);
    if(ap->ActionFn == NULL)
        ap->ActionFn = DefActionFn;

    //add this one to list
    ap->next = ActionListHead;
    ActionListHead = ap;
    return TRUE;
}

//***************************************************************************
//AddDummyActNode
//********** Description: **************
//add a dummy Action node for compatibility with verbal Action contents
//********** Parameters:  **************
//none
//-----------------------------------------------------------------------------
BOOL BBECALL AddDummyActNode()
{
    ActionDefNodeP ap = new struct _ActionDefNode;
    if (ap == NULL)
    	return FALSE;
    ap->ActionID = SAME_ACTION;
    strncpy(ap->Verb, "<initiator>", 16);
    ap->_Type = UNDEFINED;
    ap->Difficulty = 0;
    ap->Wickedness = 0;
    ap->Anarchy = 0;
    ap->AttitudeChange = 0;
    ap->MinIntel = 0;
    ap->ReqCourage = 0;
    ap->Difficulty = 0;
    ap->ModNum = 0;
    ap->ActionFn = NULL;
    ap->next = ActionListHead;
    ActionListHead = ap;
    return TRUE;
}

//***************************************************************************
//AddNewStrNode
//********** Description: **************
//add a new Strategy node read from the given record
//********** Parameters:  **************
//StrFileRec rec - Action record
//-----------------------------------------------------------------------------
BOOL BBECALL AddNewStrNode(StrFileRec rec)
{
    ID i, j, v1, v2, idVerbalActionContent, nTotalActionsNum;
    BOOL PreviousWasVerbal = FALSE;
    unsigned short NewDiff;
    if (rec.IsDeleted || rec.StrategyID == 0)
    {
    	return TRUE;
    }
    StrategyDefNodeP isp, sav_isp, sp = new struct _StrategyDefNode;
    if (sp == NULL)
        return FALSE;

	sp->StrategyID = rec.StrategyID;
	strncpy(sp->Name, rec.StrategyName, 16);
	strncpy(sp->Descr, rec.Descr, 51);
    sp->TheGoal.Itself = rec.GoalItself;
    sp->TheGoal.Importance = rec.GoalImportance;
    sp->MaxIntel = rec.MaxIntel;
    sp->ActionIDs = NULL;
    sp->TACs = NULL;
    sp->Verbal1Ind = NULL;
    sp->Verbal2Ind = NULL;
    sp->Verbal1 = NULL;
    sp->Verbal1TACs = NULL;
    sp->Verbal2 = NULL;
    sp->Verbal2TACs = NULL;
    sp->_Type = rec._Type;
    sp->ActionsNo = 0;

    //add all, including verbal actions' contents
    v1 = v2 = 0;
    for(i = 0 ; (rec.Actions[ i ].ActionIDs != 0) &&
    	(i < MAX_ACTIONS); i++)
    {
        if (!(rec.Actions[ i ].ActionIDs &
                0x8000))
        {
            sp->ActionsNo++;
            PreviousWasVerbal = FALSE;
        }
        else
        {
            if(PreviousWasVerbal)
                v2++;
            else
                v1++;
            PreviousWasVerbal = TRUE;
        }
    }

    if( sp->ActionsNo )
    {
        sp->ActionIDs = new ID[ sp->ActionsNo ];
        sp->TACs = new unsigned char[ sp->ActionsNo ];
        sp->ReferencedTACs = new unsigned char[ sp->ActionsNo ];
        sp->ConditionalGoto = new unsigned char[ sp->ActionsNo ];
        sp->Verbal1Ind = new unsigned char[ sp->ActionsNo ];
        sp->Verbal2Ind = new unsigned char[ sp->ActionsNo ];
    }
    if( v1 )
    {
        sp->Verbal1 = new ID[ v1 ];
        sp->Verbal1TACs = new unsigned char[ v1 ];
        sp->v1ReferencedTACs = new unsigned char[ v1 ];
        sp->v1ConditionalGoto = new unsigned char[ v1 ];
    }
    if( v2 )
    {
        sp->Verbal2 = new ID[ v2 ];
        sp->Verbal2TACs = new unsigned char[ v2 ];
        sp->v2ReferencedTACs = new unsigned char[ v2 ];
        sp->v2ConditionalGoto = new unsigned char[ v2 ];
    }

    nTotalActionsNum = i;
    v1 = v2 = 0;
    j = -1;
    PreviousWasVerbal = FALSE;
    for(i = 0 ; (rec.Actions[ i ].ActionIDs != 0) &&
    	(i < nTotalActionsNum); i++)
    {
        if(!(rec.Actions[ i ].ActionIDs &
                0x8000))
        {
            ++j;
		    sp->ActionIDs[ j ] = rec.Actions[ i ].ActionIDs;
            sp->TACs[ j ] = rec.Actions[ i ].TAC;
            sp->ReferencedTACs[ j ] = rec.Actions[ i ].ReferencedTAC;
            sp->ConditionalGoto[ j ] = rec.Actions[ i ].ConditionalGoto;
            sp->Verbal1Ind[ j ] = 0xFF;
            sp->Verbal2Ind[ j ] = 0xFF;
            PreviousWasVerbal = FALSE;
        }
        else
        {
            idVerbalActionContent = (ID)(rec.Actions[ i ].ActionIDs &
                0x7FFF);
            if(PreviousWasVerbal)
            {
                sp->Verbal2Ind[ j ] = v2;
                sp->Verbal2[ v2 ] = idVerbalActionContent;
                sp->Verbal2TACs[ v2 ] = rec.Actions[ i ].TAC;
                sp->v2ReferencedTACs[ v2 ] = rec.Actions[ i ].ReferencedTAC;
                sp->v2ConditionalGoto[ v2 ] = rec.Actions[ i ].ConditionalGoto;
                v2++;
            }
            else
            {
                sp->Verbal1Ind[ j ] = v1;
                sp->Verbal1[ v1 ] = idVerbalActionContent;
                sp->Verbal1TACs[ v1 ] = rec.Actions[ i ].TAC;
                sp->v1ReferencedTACs[ v1 ] = rec.Actions[ i ].ReferencedTAC;
                sp->v1ConditionalGoto[ v1 ] = rec.Actions[ i ].ConditionalGoto;
                v1++;
            }
            PreviousWasVerbal = TRUE;
        }
    }

    if(!StrategyListHead)
    {
        sp->next = FALSE;
        StrategyListHead = sp;
        return TRUE;
    }

    NewDiff = QuickDiffCalc(sp);
    isp = StrategyListHead;
    sav_isp = StrategyListHead;

    //add, sorting by difficulty, ascending
    while(isp)
    {
        if (QuickDiffCalc(isp) > NewDiff)
            break;
        sav_isp = isp;
        isp = isp->next;
    }

    //add this one to list
    sp->next = isp;
    if(isp == StrategyListHead)
    {
        sav_isp = StrategyListHead;
        StrategyListHead = sp;
        sp->next = sav_isp;
    }
    else
    {
        sav_isp->next = sp;
        sp->next = isp;
    }
    return TRUE;
}

//***************************************************************************
//QuickDiffCalc
//********** Description: **************
//calculate approximate difficulty for the given Strategy node
//********** Parameters:  **************
//StrategyDefNodeP stp - Strategy definition record
//-----------------------------------------------------------------------------
unsigned short BBECALL QuickDiffCalc(StrategyDefNodeP stp)
{
    unsigned short OverallDiff = 0, ActionDiff;
    ActionDefNodeP ap;
    long i;
    for(i = 0;(i < stp->ActionsNo) && (i < MAX_ACTIONS); i++)
    {
        ap = GetActionNode(stp->ActionIDs[i]);
        if(!ap)
            continue;
        ActionDiff = ap->Difficulty;
        OverallDiff += ActionDiff;
    }
    return OverallDiff;
}

//***************************************************************************
//GetGoalNode
//********** Description: **************
//return Goal definition node by the given ID
//********** Parameters:  **************
//ID argGoalID - ID of the Goal to find
//-----------------------------------------------------------------------------
GoalDefNodeP BBECALL GetGoalNode(ID argGoalID)
{
	GoalDefNodeP gp;
    for (gp = GoalListHead; gp != NULL; gp = gp->next)
    {
    	if (gp->goal.Itself == argGoalID)
        	return gp;
    }
    return NULL;
}

//***************************************************************************
//GetActionNode
//********** Description: **************
//return Action definition node by the given ID
//********** Parameters:  **************
//ID argActionID - ID of the Action to find
//-----------------------------------------------------------------------------
ActionDefNodeP BBECALL GetActionNode(ID argActionID)
{
	ActionDefNodeP ap;
    for (ap = ActionListHead; ap != NULL; ap = ap->next)
    	if (ap->ActionID == argActionID)
        	return ap;
    return NULL;
}

//***************************************************************************
//LinkFnToAction
//********** Description: **************
//link user-defined Action handler to the proper Action definition node
//********** Parameters:  **************
//ID argActionID            - ID of the Action node to link to
//int (*argActionFn)(void*) - user-defined Action handler
//-----------------------------------------------------------------------------
ActionDefNodeP BBECALL LinkFnToAction(ID argActionID, int (BBECALL *argActionFn)(void*))
{
    ActionDefNodeP ap;
    for (ap = ActionListHead; ap != NULL; ap = ap->next)
        if (ap->ActionID == argActionID)
        {
            ap->ActionFn = argActionFn;
            return ap;
        }
    return NULL;
}

//***************************************************************************
//GetStrategyNode
//********** Description: **************
//return Strategy definition node by the given ID
//********** Parameters:  **************
//ID argStrategyID - ID of the Strategy to find
//-----------------------------------------------------------------------------
StrategyDefNodeP BBECALL GetStrategyNode(ID argStrategyID)
{
	StrategyDefNodeP sp;
    for (sp = StrategyListHead; sp != NULL; sp = sp->next)
        if (sp->StrategyID == argStrategyID)
            return sp;
    return NULL;
}

//***************************************************************************
//Buf2ModRec
//********** Description: **************
//read Module ("Parameter") record from buffer and return it through reference
//********** Parameters:  **************
//BYTE *RecBuf            - buffer
//ModuleRec& ModRecordBuf - holder for a module record
//-----------------------------------------------------------------------------
BOOL BBECALL Buf2ModRec(BYTE *RecBuf,ModuleRec& ModRecordBuf)
{
    long i = 0;
	ModRecordBuf.ParGroup = RecBuf[i++];
    if(ModRecordBuf.ParGroup != PARAM_MODULE)
    {
        return FALSE;
    }
    ModRecordBuf.ModuleID = (ID)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    memcpy(ModRecordBuf.szModuleName,RecBuf+i,MAX_MODULE_NAME);
    i += MAX_MODULE_NAME;
    ModRecordBuf.IsDeleted = RecBuf[i];
    return TRUE;
}

//***************************************************************************
//AddNewModuleNode
//********** Description: **************
//add a new Module entry read from the given record
//********** Parameters:  **************
//ModuleRec& ModRecordBuf - Module record
//ID idSlot               - entry index
//-----------------------------------------------------------------------------
BOOL BBECALL AddNewModuleNode(ModuleRec& ModRecordBuf, ID idSlot)
{
    HMODULE hNew;
    hNew = LoadLibrary(ModRecordBuf.szModuleName);//GetModuleHandle(ModRecordBuf.szModuleName);
    if(hNew == NULL)
        return FALSE;
    Modules[idSlot].hMod = hNew;
    Modules[idSlot].ModId = ModRecordBuf.ModuleID;
    return TRUE;
}

//***************************************************************************
//Buf2MindRec
//********** Description: **************
//read Mindset record from buffer and return it through reference
//********** Parameters:  **************
//BYTE *RecBuf   - buffer
//ModuleRec& rec - holder for a Mindset record
//-----------------------------------------------------------------------------
void BBECALL Buf2MindRec(BYTE *RecBuf,MindFileRec& rec)
{
    long i = 0;
    rec.MindID = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    memcpy(rec.Descr, RecBuf+i, 26);
    i += 26;

    rec.LWick = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.HWick = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.LAnar = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.HAnar = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InitialAttitude = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.AttitudeChangeUnit = RecBuf[i++];
    rec.SuddenChangeProb = RecBuf[i++];

    rec.InflMean = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InflMeanDiff = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InflBeau = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InflBeauDiff = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InflWeal = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InflWealDiff = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InflInt = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InflIntDiff = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.InflSocGrpDiff = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.ItemInflMean = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.ItemInflBeau = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.ItemInflWeal = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    rec.ItemInflIntel = (unsigned short)(RecBuf[i] + RecBuf[i+1]*256);
    i += 2;
    memcpy(rec.Reserved,RecBuf+i,30);
    i += 30;
    rec.IsDeleted = RecBuf[i];
}

//***************************************************************************
//AddNewMindNode
//********** Description: **************
//add a new Mindset node read from the given record
//********** Parameters:  **************
//MindFileRec rec - Mindset record
//-----------------------------------------------------------------------------
BOOL BBECALL AddNewMindNode(MindFileRec rec)
{
    if (rec.IsDeleted || rec.MindID == 0)
    {
    	return TRUE;
    }

    MindDefNodeP mp = new struct _MindDefNode;
    if (mp == NULL)
    	return FALSE;

    mp->MindID = rec.MindID;
    strncpy(mp->Descr,rec.Descr,26);
    mp->LWick = rec.LWick;
    mp->HWick = rec.HWick;
    mp->LAnar = rec.LAnar;
    mp->HAnar = rec.HAnar;
    mp->InitialAttitude = rec.InitialAttitude;
    mp->AttitudeChangeUnit = rec.AttitudeChangeUnit;
    mp->SuddenChange = rec.SuddenChangeProb;
    mp->AbsMeanness = rec.InflMeanDiff;
    mp->Meanness = rec.InflMean;
    mp->AbsWealth = rec.InflWealDiff;
    mp->Wealth = rec.InflWeal;
    mp->AbsBeauty = rec.InflBeauDiff;
    mp->Beauty = rec.InflBeau;
    mp->AbsIntelligence = rec.InflIntDiff;
    mp->Intelligence = rec.InflInt;
    mp->Foreignness = rec.InflSocGrpDiff;
    mp->ItemMeanness = rec.ItemInflMean;
    mp->ItemBeauty = rec.ItemInflBeau;
    mp->ItemWealth = rec.ItemInflWeal;
    mp->ItemIntelligence = rec.ItemInflIntel;
    mp->next = MindListHead;
    MindListHead = mp;
    return TRUE;
}

//***************************************************************************
//GetMindNode
//********** Description: **************
//return Mindset definition node by the given ID
//********** Parameters:  **************
//ID argMindID - ID of the Mindset to find
//-----------------------------------------------------------------------------
MindDefNodeP BBECALL GetMindNode(ID argMindID)
{
	MindDefNodeP mp;
    for (mp = MindListHead; mp != NULL; mp = mp->next)
        if (mp->MindID == argMindID)
            return mp;
    return NULL;
}

//***************************************************************************
//GetMindDesc
//********** Description: **************
//return Mindset description by the given ID
//********** Parameters:  **************
//ID argMindID - ID of the Mindset to find
//-----------------------------------------------------------------------------
char *BBECALL GetMindDesc(ID argMindID)
{
	MindDefNodeP mp;
    for (mp = MindListHead; mp != NULL; mp = mp->next)
        if (mp->MindID == argMindID)
            return mp->Descr;
    return "custom";
}

//***************************************************************************
//FillBufferWithMindPtrs
//********** Description: **************
//dump pointers to all the Mindset nodes to buffer
//********** Parameters:  **************
//MindDefNodeP *mppBuf - Mindset definition node pointers' array
//int nMaxLen          - array length
//-----------------------------------------------------------------------------
int BBECALL FillBufferWithMindPtrs(MindDefNodeP *mppBuf, int nMaxLen)
{
	MindDefNodeP mp;
    int i = 0;
    for (mp = MindListHead; (mp != NULL) && (i < nMaxLen); mp = mp->next)
        mppBuf[i++] = mp;

    return i;
}

//***************************************************************************
//GetMatchMindNode
//********** Description: **************
//try to locate and return a Mindset node matching the given values
//********** Parameters:  **************
//percentage WickArg - wickedness value
//percentage AnarArg - anarchy value
//-----------------------------------------------------------------------------
MindDefNodeP BBECALL GetMatchMindNode(percentage WickArg,percentage AnarArg)
{
	MindDefNodeP mp;
    for (mp = MindListHead; mp != NULL; mp = mp->next)
        if (WickArg >= mp->LWick && WickArg <= mp->HWick
                && AnarArg >= mp->LAnar && AnarArg <= mp->HAnar)
            return mp;
    return NULL;
}

//***************************************************************************
//FillBufferWithActionPtrs
//********** Description: **************
//dump pointers to all the Action nodes to buffer
//********** Parameters:  **************
//ActionDefNodeP *adpBuf - Action definition node pointers' array
//int nMaxLen            - array length
//---------------------------------------------------------------------------
int BBECALL FillBufferWithActionPtrs(ActionDefNodeP *adpBuf, int nMaxLen)
{
	ActionDefNodeP ap;
    int i = 0;
    for (ap = ActionListHead; (ap != NULL) && (i < nMaxLen); ap = ap->next)
        adpBuf[i++] = ap;

    return i;
}
//-----------------------------------------------------------------------------

