/*
**  Copyright (C) 1996, 1997 Microsoft Corporation. All Rights Reserved.
**
**  File:	mapmakerigc.cpp
**
**  Author: Jeff Fink (jfink@microsoft.com)
**
**  Description:
**
**  History:
*/

#include    "pch.h"
#include    "mapmakerIGC.h"


//
// Static members.
// 08/30/04 -KGJV: added Titty Baby memorial sector name
const char * CMapData::smszClusterName[c_NumClusterNames] =
{
    "Aegis",        "Aeroflex",     "Ahto",         "Aredne",
    "Blenhem",      "Borsonis",     "Bragi",        "Caladonia", "Cirt",
    "Claytow",      "Denom",        "Dunatis",    /*"Earth",*/ "Eleesh",
    "Enlil",        "Fejfar",       "Fenris",       "Fierro",
    "Freya",        "Gala",         "Gery",
    "Gobo",         "Goron",        "Holokine",   /*"Jupiter",*/ "Jol",
    "Karlo",        "Kassano",      "Kassimier",    "Kik",
    "Kilvero",      "Kishoten",     "Kuat",         "L'Sau",
    "Larchis",      "Lemminakean",  "Leighton",     "Louhi",
    "Loviatar",     "Luerentia",  /*"Mars",*/       "Meesh", "Mercor",
  /*"Mercury",*/    "Miekko",       "Mielikki",     "Monmar",
    "Nadir",      /*"Neptune",*/    "Night",        "Oblivion",
    "Okanagon",     "Oxyl",       /*"Pluto",*/      "Pohjola",
    "Raiko",        "Resnik",       "Rib'zki",		"Rimin",  "Sleipener",
    "Solitaire",    "Soron",        "Sri Metsa",    "Surma",
    "Tathlum",      "Tierankeen",   "Tjeerd",       "Torc",
    "Touni",        "Tauceti",      "Titty Baby"    ,"Turakeen",   /*"Uranus",*/"Udar", "Virkinow",
  /*"Venus",*/      "Xuping"
} ;

const char * CmapMakerIGC::smszPlanetName[c_NumberOfPlanetPosters] =
{
    "nebplnt36bmp",
    "nebplnt35bmp",
    "nebplnt02bmp",
    "nebplnt23bmp",
    "nebplnt19bmp",
    "nebplnt01bmp",
	"nebplnt03bmp",
	"nebplnt04bmp",
	"nebplnt05bmp",
	"nebplnt06bmp",
	"nebplnt07bmp",
	"nebplnt08bmp",
	"nebplnt09bmp",
	"nebplnt10bmp",
	"nebplnt11bmp",
	"nebplnt12bmp",
	"nebplnt16bmp",
	"nebplnt19bmp",
	"nebplnt24bmp",
	"nebplnt25bmp",
	"nebplnt29bmp",
	"nebplnt30bmp",
	"nebplnt31bmp",
	"nebplnt33bmp",
	"nebplnt37bmp"
} ;

//
// Map data helper class.
//

CMapData::CMapData()
{
    SectorID sID;

    mpMission = NULL;
    mpMissionParams = NULL;

    ZeroMemory(mpCluster, sizeof(mpCluster));
    for(sID = 0; sID < c_NumClusterNames; sID++)
        mClusterNamesLeft[sID] = sID;
    mcClusterNamesLeft = c_NumClusterNames;


    mcTeamClustersPerTeam = 0;
    mcNeutralClustersPerTeam = 0;
    mcOtherClusters = 0;
    mIDNextWarp = 0;
}


CMapData::~CMapData()
{
    SectorID sID;

    for(sID = 0; sID < c_MaxClustersPerMap; sID++)
    {
        if (NULL != mpCluster[sID])
            mpCluster[sID]->Release();  
    }
}


VOID CMapData::SetCluster(SectorID sID, IclusterIGC * pCluster, SideID sideID)
{
    if (NULL != pCluster)
        pCluster->AddRef();
    if (NULL != mpCluster[sID])
        mpCluster[sID]->Release();
    mpCluster[sID] = pCluster;
    msideIDCluster[sID] = sideID;
}


VOID CMapData::GetNewClusterName(CHAR * szClusterName)
{
    INT n = randomInt(0, mcClusterNamesLeft - 1);

    strcpy(szClusterName, smszClusterName[mClusterNamesLeft[n]]);
    mcClusterNamesLeft--;
    mClusterNamesLeft[n] = mClusterNamesLeft[mcClusterNamesLeft];
}


const char* ImapMakerIGC::IsValid(const MissionParams* pmp)
{
    switch (pmp->mmMapType)
    {
        case c_mmSingleRing:
            return CmapMakerSingleRingIGC::IsValid(pmp);
        case c_mmDoubleRing:
            return CmapMakerDoubleRingIGC::IsValid(pmp);
        case c_mmPinWheel:
            return CmapMakerPinWheelIGC::IsValid(pmp);
        case c_mmDiamondRing:
            return CmapMakerDiamondRingIGC::IsValid(pmp);
        case c_mmSnowFlake:
            return CmapMakerSnowFlakeIGC::IsValid(pmp);
        case c_mmSplitBase:
            return CmapMakerSplitBaseIGC::IsValid(pmp);
        case c_mmLargeSplit:
            return CmapMakerLargeSplitIGC::IsValid(pmp);
        case c_mmBrawl:
            return CmapMakerBrawlIGC::IsValid(pmp);
        case c_mmBigRing:
            return CmapMakerBigRingIGC::IsValid(pmp);
        case c_mmHiLo:
            return CmapMakerHiLoIGC::IsValid(pmp);
        case c_mmHiHigher:
            return CmapMakerHiHigherIGC::IsValid(pmp);
        case c_mmStar:
            return CmapMakerStarIGC::IsValid(pmp);
        case c_mmInsideOut:
            return CmapMakerInsideOutIGC::IsValid(pmp);
        case c_mmGrid:
            return CmapMakerGridIGC::IsValid(pmp);
        case c_mmEastWest:
            return CmapMakerEastWestIGC::IsValid(pmp);
    }

    return "Invalid map type";
}

void    ImapMakerIGC::Create(Time                   now,
                             const MissionParams*   pmp,
                             ImissionIGC*           pmission)
{
    assert (pmp->nTeams >= 2);
    assert (pmp->nTeams <= c_cSidesMax);

#define MakeMap(x)  case c_mm##x:                                   \
                    {                                               \
                        CmapMaker##x##IGC mm;                       \
                        mm.GenerateMission(now, pmp, pmission);     \
                    }                                               \
                    break;                                          \

    switch(pmp->mmMapType)
    {
        MakeMap(SingleRing)
        MakeMap(DoubleRing)
        MakeMap(PinWheel)
        MakeMap(DiamondRing)
        MakeMap(SnowFlake)
        MakeMap(SplitBase)
        MakeMap(Brawl)
        MakeMap(BigRing)
        MakeMap(HiLo)
        MakeMap(HiHigher)
        MakeMap(Star)
        MakeMap(InsideOut)
        MakeMap(Grid)
        MakeMap(EastWest)
        MakeMap(LargeSplit)
        default:
            assert (false);
    }
#undef MakeMap
}

//
// Base class for the map maker.
//
CmapMakerIGC::CmapMakerIGC()
{
    mMMID = c_mmSingleRing;
    this->SetName("Single Ring");
}


CmapMakerIGC::~CmapMakerIGC()
{
}

static bool    FindPath(IclusterIGC*    p2,
                        int*            pStart,
                        int*            pStop,
                        IclusterIGC**   pclustersAdjacent,
                        IclusterIGC**   pclusterBackTrack,
                        bool*           bVisited)
{
    if (*pStart == *pStop)
        return false;

    IclusterIGC*    p1 = pclustersAdjacent[*pStart];
    assert (p1);

    if (p1 == p2)
        return true;

    (*pStart)++;

    for (WarpLinkIGC*   pwl = p1->GetWarps()->first(); (pwl != NULL); pwl = pwl->next())
    {
        IclusterIGC*    p = pwl->data()->GetDestination()->GetCluster();
        SectorID        id = p->GetObjectID();

        if ((pclusterBackTrack[id] == NULL) && !bVisited[id])
        {
            pclusterBackTrack[id] = p1;
            pclustersAdjacent[*pStop] = p;

            (*pStop)++;
        }
    }

    return FindPath(p2, pStart, pStop,
                    pclustersAdjacent,
                    pclusterBackTrack,
                    bVisited);
}

static bool    EnoughPaths(IclusterIGC**            pclusterBackTrack,
                           bool*                    bVisited,
                           const ClusterListIGC*    pclusters,
                           IwarpIGC*                pwarp,
                           int                      count)
{
    IclusterIGC*    pcluster1 = pwarp->GetCluster();
    IclusterIGC*    pcluster2 = pwarp->GetDestination()->GetCluster();

    for (int i = pclusters->n() - 1; (i >= 0); i--)
    {
        pclusterBackTrack[i] = NULL;
    }

    IclusterIGC**   pclustersAdjacent = (IclusterIGC**)alloca(pclusters->n() * pclusters->n() * sizeof(IclusterIGC*));
    int         nStart = 0;
    int         nStop = 0;
    for (WarpLinkIGC*   pwl = pcluster1->GetWarps()->first(); (pwl != NULL); pwl = pwl->next())
    {
        IwarpIGC*   pw = pwl->data();
        if (pw != pwarp)
        {
            IclusterIGC*    pcluster = pw->GetDestination()->GetCluster();
            SectorID        id = pcluster->GetObjectID();

            if (!bVisited[id])
            {
                pclustersAdjacent[nStop++] = pcluster;
                pclusterBackTrack[id] = pcluster1;
            }
        }
    }

    if (!FindPath(pcluster2, &nStart, &nStop, pclustersAdjacent, pclusterBackTrack, bVisited))
    {
        return false;
    }
    else if (count == 1)
    {
        return true;
    }
    else
    {
        //Mark everything on the path from p1 to p2 as visited so they can be used
        //by subsequent paths
        //Note: p2 is never marked as visited
        //      p1 is marked as visited (not that we care)
        IclusterIGC*    pcluster = pcluster2;
        SectorID    id = pcluster->GetObjectID();
        do
        {
            assert (pclusterBackTrack[id] != NULL);

            pcluster = pclusterBackTrack[id];
            id = pcluster->GetObjectID();

            bVisited[id] = true;
        }
        while (pcluster != pcluster1);

        return EnoughPaths(pclusterBackTrack,
                           bVisited,
                           pclusters,
                           pwarp,
                           --count);
    }
}

static bool OkToRemove(const ClusterListIGC*    pclusters, IwarpIGC* pwarp)
{
    IclusterIGC**   pclusterBackTrack = (IclusterIGC**)alloca(pclusters->n() * sizeof(IclusterIGC*));
    bool*           bVisited = (bool*)alloca(pclusters->n() * sizeof(bool));

    {
        for (int i = pclusters->n() - 1; (i >= 0); i--)
            bVisited[i] = false;
    }

    bVisited[pwarp->GetCluster()->GetObjectID()] = true;

    return EnoughPaths(pclusterBackTrack, bVisited, pclusters, pwarp, 2);
}

VOID CmapMakerIGC::GenerateMission(Time now,
                                    const MissionParams * pmp,
                                    ImissionIGC * pMission)
{
    CMapData MapData;

    assert(NULL == ImapMakerIGC::IsValid(pmp));

    MapData.SetTime(now);
    MapData.SetMissionParams(pmp);
    MapData.SetMission(pMission);

    //
    // First generate the sides.
    //
    //this->GenerateSides(&MapData);

    //
    // Next generate the sector layout.
    //
    this->GenerateLayout(&MapData);

    {
        //Adjust the position of all alephs in all clusters
        float   majorRadius = pMission->GetFloatConstant(c_fcidRadiusUniverse);
        for (ClusterLinkIGC*    pcl = pMission->GetClusters()->first(); (pcl != NULL); pcl = pcl->next())
        {
            IclusterIGC*    pcluster = pcl->data();

            const WarpListIGC*  pwarps = pcluster->GetWarps();
            if (pwarps->n() != 0)
            {
                float   nWarps = (float)(pwarps->n());

                const int c_maxWarps = 10;
                assert (pwarps->n() <= c_maxWarps);

                float   offset[c_maxWarps] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f};
                float   displacement;
                if (pwarps->n() > 1)
                {
                    displacement =  sin(pi/nWarps) * 2.0f / 3.0f;
                    for (int index = 0; (index < pwarps->n()); index++)
                    {
                        int swap = randomInt(0, pwarps->n() - 1);
                        if (swap != index)
                        {
                            float   t = offset[index];
                            offset[index] = offset[swap];
                            offset[swap] = t;
                        }
                    }
                }
                else
                    displacement = 2.0f / 3.0f;

                {
                    float   bias = random(0.0f, 2.0f * pi);
                    int     index = 0;

                    for (WarpLinkIGC*   pwl = pwarps->first(); (pwl != NULL); pwl = pwl->next())
                    {
                        IwarpIGC*   pwarp = pwl->data();

                        float       r = pwarp->GetPosition().z * majorRadius;

                        float       angle = bias + offset[index++] * (2.0f * pi) / nWarps;

                        Vector      position;
                        position = Vector::RandomPosition(r * displacement);

                        position.x  += cos(angle) * r;
                        position.y  += sin(angle) * r;
                        position.z  *= 1.2f;

                        pwarp->SetPosition(position);
                        Orientation o(-position);
                        pwarp->SetOrientation(o);

                        pwarp->GetHitTest()->UpdateStaticBB();
                    }
                }
            }
        }
    }

    //Randomize the map if appropriate
    if (pmp->iRandomEncounters > 1)
    {
        const WarpListIGC*      pwarpList = pMission->GetWarps();
        IwarpIGC**  pwarps = (IwarpIGC**)(alloca(pwarpList->n() * sizeof(IwarpIGC*)));

        //Actually allocate twice as much space as we need since we are only storing a single instance for
        //both sides of the aleph
        int nWarps = 0;
        {
            for (WarpLinkIGC*   pwl = pwarpList->first(); (pwl != NULL); pwl = pwl->next())
            {
                IwarpIGC*   pwarp = pwl->data();
                if ((pwarp->GetObjectID() < pwarp->GetDestination()->GetObjectID()) &&
                    (randomInt(0, pmp->iRandomEncounters) > 1))
                {
                    assert (nWarps < pwarpList->n());
                    pwarps[nWarps++] = pwarp;
                }
            }
        }

        const ClusterListIGC*   pclusters = pMission->GetClusters();
        while (nWarps > 0)
        {
            int         index = randomInt(0, nWarps - 1);
            IwarpIGC*   pwarp = pwarps[index];

            //Can we remove pwarp without destroying the map's connectivity?
            if (OkToRemove(pclusters, pwarp))
            {
                pwarp->GetDestination()->Terminate();
                pwarp->Terminate();
            }

            pwarps[index] = pwarps[--nWarps];
        }
    }

    this->PopulateClusters(&MapData);

    //
    // If the show home sector flag is on, show it to the teams.
    //
    if (TRUE == pmp->bShowHomeSector)
        this->RevealHomeClusters(pMission);

    if (TRUE == pmp->bShowMap)
        this->RevealMap(pMission);

    //
    // We're done with everything, so activate the sides.
    //
    this->ActivateSides(pMission);
}


//
// Base class implementation of the map maker.
//
/*
VOID CmapMakerIGC::GenerateSides(CMapData * pMapData)
{
    static const float sideColors[c_cSidesMax][3] =
                                { {200.0f/255.0f,  15.0f/255.0f, 200.0f/255.0f}, //purple
                                  {  8.0f/255.0f, 184.0f/255.0f, 184.0f/255.0f}, //teal
                                  {  0.0f/255.0f,   0.0f/255.0f, 233.0f/255.0f}, //blue
                                  {184.0f/255.0f, 184.0f/255.0f,  50.0f/255.0f}, //icky yellow
                                  {184.0f/255.0f,  92.0f/255.0f,   0.0f/255.0f}, //icky orange
                                  {123.0f/255.0f,  61.0f/255.0f,  61.0f/255.0f}};//icky magenta
    static const char* sideNames[c_cSidesMax] =
                        { "Crusaders",
                          "Unity",
                          "Survivors",
                          "Protectorate",
                          "Colossal Mining Corp",
                          "Midnight Runners" };

    for (SideID sid = 0; sid < pMapData->GetTeams(); sid++)
    {
        IcivilizationIGC*   pcivilization = pMapData->GetMission()->
            GetCivilization(pMapData->GetMissionParams()->rgCivID[sid]);

        DataSideIGC ds;
        ds.sideID = sid;
        ds.civilizationID = pMapData->GetCivID(sid);
        ds.color.SetRGBA(sideColors[sid][0],
                         sideColors[sid][1],
                         sideColors[sid][2]);
        strcpy(ds.name, sideNames[sid]);
        ds.ttbmDevelopmentTechs = pcivilization->GetBaseTechs();
        ds.conquest = 100 / pMapData->GetTeams();
        ds.nKills = ds.nDeaths = 0;

        IObject*    o = pMapData->GetMission()->CreateObject(
                                                pMapData->GetTime(),
                                                OT_side,
                                                &ds,
                                                sizeof(ds));
        assert (o);
        o->Release();
    }

    assert (pMapData->GetMission()->GetSides()->n() == pMapData->GetTeams());
}
*/


VOID CmapMakerIGC::GenerateTeamClusterScreenPosition(CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float flTheta;

    flTheta = (float) (2.0 * pi * sID / pMapData->GetTotalClusters());

    pdc->screenX = cos(flTheta) * 0.8f;
    pdc->screenY = sin(flTheta) * 0.8f;
}


IclusterIGC * CmapMakerIGC::GenerateTeamCluster(CMapData * pMapData,
                                                SectorID sID)
{
    DataClusterIGC dc;
    INT n; 

    dc.bHomeSector = true;

    dc.clusterID = sID;
    dc.activeF = true;

    dc.lightColor = 0xffffffff;
    dc.lightDirection = Vector::RandomDirection();

    pMapData->GetNewClusterName(dc.name);

    strcpy(dc.posterName, "globe");
    dc.posterName[5] = '0' + randomInt(1, 8);
    dc.posterName[6] = '\0';

    n = randomInt(0, c_NumberOfPlanetPosters - 1);
    strcpy(dc.planetName, smszPlanetName[n]);
    dc.planetSinLatitude = random(0.0f, 1.0f);
    dc.planetLongitude = random(0.0f, 1.0f);
    dc.planetRadius = (unsigned char)randomInt(50, 100);

    dc.starSeed = rand();
    dc.nDebris = randomInt(250, 750);
    dc.nStars = randomInt(250, 750);

    //
    // Position cluster on the screen.
    //
    this->GenerateTeamClusterScreenPosition(pMapData, &dc, sID);

    IclusterIGC * o = (IclusterIGC *) pMapData->GetMission()->CreateObject(
                                                    pMapData->GetTime(),
                                                    OT_cluster,
                                                    &dc,
                                                    sizeof(dc));
    assert(o);
    return(o);
}


VOID CmapMakerIGC::GenerateNeutralClusterScreenPosition(CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float flTheta;

    flTheta = (float) (2.0 * pi * sID / pMapData->GetTotalClusters());
    pdc->screenX = cos(flTheta) * 0.4f;
    pdc->screenY = sin(flTheta) * 0.4f;
}


IclusterIGC * CmapMakerIGC::GenerateNeutralCluster(CMapData * pMapData,
                                                    SectorID sID)
{
    DataClusterIGC dc;

    dc.bHomeSector = false;

    dc.clusterID = sID;
    dc.activeF = true;

    dc.lightColor = 0xffffffff;
    dc.lightDirection = Vector::RandomDirection();

    pMapData->GetNewClusterName(dc.name);

    strcpy(dc.posterName, "globe");
    dc.posterName[5] = '0' + randomInt(1, 8);
    dc.posterName[6] = '\0';
    dc.planetName[0] = '\0';

    dc.starSeed = rand();
    dc.nDebris = randomInt(250, 750);
    dc.nStars = randomInt(250, 750);

    //
    // Position cluster on the screen.  Since we're doing all the
    // player clusters first, we need to space them appropriately.
    //
    this->GenerateNeutralClusterScreenPosition(pMapData, &dc, sID);

    IclusterIGC * o = (IclusterIGC *) pMapData->GetMission()->CreateObject(
                                                    pMapData->GetTime(),
                                                    OT_cluster,
                                                    &dc,
                                                    sizeof(dc));
    assert(o);
    return(o);
}


VOID CmapMakerIGC::GenerateRingClusters(CMapData * pMapData)
{
    SectorID sID, cTotalRingClusters;
    IclusterIGC * pCluster;

    cTotalRingClusters = pMapData->GetTotalClusters() -
                            pMapData->GetOtherClusters();

    for(sID = 0; sID < cTotalRingClusters; sID++)
    {
        if (sID % pMapData->GetClustersPerTeam() <
            pMapData->GetTeamClustersPerTeam())
        {
            pCluster = this->GenerateTeamCluster(pMapData, sID);
            pMapData->SetCluster(sID,
                                pCluster,
                                sID / pMapData->GetClustersPerTeam());
        } else
        {
            pCluster = this->GenerateNeutralCluster(pMapData, sID);
            pMapData->SetCluster(sID, pCluster, NA);
        }
        pCluster->Release();
    }

    while(sID < pMapData->GetTotalClusters())
    {
        pCluster = this->GenerateNeutralCluster(pMapData, sID);
        pMapData->SetCluster(sID, pCluster, NA);
        sID++;
    }
}


VOID CmapMakerIGC::GenerateWarp(CMapData * pMapData,
                                IclusterIGC * pCluster,
                                DataWarpIGC * pdw)
{
    //
    // Add it to the cluster.
    //
    pdw->forward.x = pdw->forward.y = 0.0f;
    pdw->forward.z = 1.0f;

    pdw->rotation.axis(pdw->forward);
    pdw->rotation.angle(0.0f);

    pdw->warpDef.radius = 100;

    IObject * o = pMapData->GetMission()->CreateObject(pMapData->GetTime(),
                                                       OT_warp,
                                                       pdw,
                                                       sizeof(*pdw));
    assert(o);
    o->Release();
}


VOID CmapMakerIGC::LinkClusters(CMapData* pMapData,
                                SectorID  sID1,
                                SectorID  sID2,
                                int       alephType)
{
    DataWarpIGC dw;

    static const char*  c_pszIconNeutral = "neutralaleph";
    static const char*  c_pszIconPlayer = "homealeph";

    static const char*  c_pszTextureNeutral = "plnt19";
    static const char*  c_pszTexturePlayer = "plnt42";

    float signature1 = 1.0f;
    float signature2 = 1.0f;

    float radius1 = 0.6f;
    float radius2 = 0.6f;

    if (alephType == NA)
    {
        SideID  side1 = pMapData->GetClusterSide(sID1);
        SideID  side2 = pMapData->GetClusterSide(sID2);
        if (NA == side1)
        {
            if (NA == side2)
            {
                alephType = c_NeutralAleph;
            }
            else
            {
                alephType = c_NeutralToPlayerAleph;
            }
        }
        else if (side1 == side2)
        {
            alephType = c_FriendlyAleph;
        }
        else if (NA != side2)
        {
            alephType = c_EnemyAleph;
        }
        else
        {
            alephType = c_PlayerToNeutralAleph;
        }
    }

    const char* pszTexture1;
    const char* pszTexture2;

    const char* pszIcon1;
    const char* pszIcon2;
    switch (alephType)
    {
        case c_FriendlyAleph:
            pszIcon1 = pszIcon2 = c_pszIconPlayer;
            pszTexture1 = pszTexture2 = c_pszTexturePlayer;
        break;

        case c_EnemyAleph:
            pszIcon1 = pszIcon2 = c_pszIconPlayer;
            pszTexture1 = pszTexture2 = c_pszTexturePlayer;
            signature1 = signature2 = 0.33f;
            radius1 = radius2 = 0.85f;
        break;

        case c_NeutralToPlayerAleph:
            pszIcon1 = c_pszIconPlayer;
            pszTexture1 = c_pszTexturePlayer;
            signature1 = 0.67f;

            pszIcon2 = c_pszIconNeutral;
            pszTexture2 = c_pszTextureNeutral;
        break;

        case c_PlayerToNeutralAleph:
            pszIcon2 = c_pszIconPlayer;
            pszTexture2 = c_pszTexturePlayer;
            signature2 = 0.67f;

            pszIcon1 = c_pszIconNeutral;
            pszTexture1 = c_pszTextureNeutral;
        break;

        case c_NeutralAleph:
            pszIcon1 = pszIcon2 = c_pszIconNeutral;
            pszTexture1 = pszTexture2 = c_pszTextureNeutral;
        break;

        case c_HiddenToPlayerAleph:
            pszIcon2 = c_pszIconPlayer;
            pszTexture2 = c_pszTexturePlayer;
            signature2 = 0.33f;
            radius2 = 0.85f;

            pszIcon1 = c_pszIconNeutral;
            pszTexture1 = c_pszTextureNeutral;
        break;

        default:
            assert (false);
    }

    //
    // Build the alephs.
    //
    dw.warpDef.warpID = pMapData->GetNextWarpID();
    dw.clusterID = sID1;
    strcpy(dw.warpDef.textureName, pszTexture1);
    strcpy(dw.warpDef.iconName, pszIcon1);
    strcpy(dw.name, pMapData->GetCluster(sID2)->GetName());
    dw.signature = signature1;
    dw.position.x = dw.position.y = 0.0f;
    dw.position.z = radius1;
    dw.warpDef.destinationID = dw.warpDef.warpID + 1;

    this->GenerateWarp(pMapData, pMapData->GetCluster(sID1), &dw);

    dw.warpDef.warpID = pMapData->GetNextWarpID();
    dw.clusterID = sID2;
    strcpy(dw.warpDef.textureName, pszTexture2);
    strcpy(dw.warpDef.iconName, pszIcon2);
    strcpy(dw.name, pMapData->GetCluster(sID1)->GetName());
    dw.signature = signature2;
    dw.position.x = dw.position.y = 0.0f;
    dw.position.z = radius2;
    dw.warpDef.destinationID = dw.warpDef.warpID - 1;

    this->GenerateWarp(pMapData, pMapData->GetCluster(sID2), &dw);
}


VOID CmapMakerIGC::CrossLinkClusters(CMapData * pMapData, SectorID sFirstID)
{
    SectorID sMax, sWrap;

    sMax = pMapData->GetTotalClusters();
    if (pMapData->GetTeams() < 4)
        sMax = 0;
    else if (pMapData->GetTeams() == 4)
        sMax /= 2;

    while(sFirstID < sMax)
    {
        sWrap = (sFirstID + 2 * pMapData->GetClustersPerTeam()) %
                    pMapData->GetTotalClusters();
        LinkClusters(pMapData, sFirstID, sWrap);
        sFirstID += pMapData->GetClustersPerTeam();
    }
}


VOID CmapMakerIGC::LinkClusters(CMapData * pMapData)
{
    SectorID sID, cTotalSectors;

    //
    // Default implementation is a single ring.
    //
    cTotalSectors = pMapData->GetTotalClusters();

    for(sID = 0; sID < cTotalSectors - 1; sID++)
        this->LinkClusters(pMapData, sID, sID + 1);

    this->LinkClusters(pMapData, sID, 0);

    //
    // If more than 3 teams, link the neutral sectors.
    //
    this->CrossLinkClusters(pMapData, pMapData->GetTeamClustersPerTeam());
}


VOID CmapMakerIGC::GenerateLayout(CMapData * pMapData)
{
    //SectorID    s = pMapData->GetMaxPlayersOnTeam() >= 30 ? 2 : 1;
	//KGJV-: changed, use now MapSize parameter
    SectorID    s = pMapData->GetMapSize() != 0 ? 2 : 1;
    pMapData->SetTeamClustersPerTeam(s);
    pMapData->SetNeutralClustersPerTeam(1);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}


VOID CmapMakerIGC::GenerateStarbase(CMapData*       pMapData,
                                    IclusterIGC*    pcluster)
{
    //
    // Note that before calling this function, the alephs should
    // be created so that the side visibility takes effect when
    // the station is created.
    //
    DataStationIGC ds;

    SideID      sideID = pMapData->GetClusterSide(pcluster->GetObjectID());
    IsideIGC*   pSide = pMapData->GetMission()->GetSide(sideID);
    assert(pSide);

    ds.clusterID = pcluster->GetObjectID();
    ds.position = Vector::GetZero();
    ds.forward.x = ds.forward.y = 0.0f;
    ds.forward.z = 1.0f;
    ds.up.x = 1.0f;
    ds.up.y = ds.up.z = 0.0f;

    ds.rotation.axis(ds.forward);
    ds.rotation.angle(0.0f);

    ds.bpHull = 1.0f;
    ds.bpShield = 1.0f;

    ds.sideID = sideID;
    ds.stationID = pMapData->GetMission()->GenerateNewStationID();

    IstationTypeIGC*    pst = pSide->GetCivilization()->GetInitialStationType();
    assert (pst);
    //Allow for an upgrade to the station being available
    pst = pst->GetSuccessorStationType(pSide);

    ds.stationTypeID = pst->GetObjectID();
    strcpy(ds.name, pst->GetName());

    IObject * o = pMapData->GetMission()->CreateObject(
                                        pMapData->GetTime(),
                                        OT_station,
                                        &ds,
                                        sizeof(ds));
    assert(o);
    o->Release();
}


VOID CmapMakerIGC::PopulateCluster(CMapData*     pMapData,
                                   IclusterIGC*  pcluster,
                                   float         amountHe3)
{
    ::PopulateCluster(pMapData->GetMission(), pMapData->GetMissionParams(), pcluster, amountHe3);
}


VOID CmapMakerIGC::PopulateClusters(CMapData* pMapData)
{
    float   amountHe3 = pMapData->GetMission()->GetFloatConstant(c_fcidAmountHe3) *
                        pMapData->GetMissionParams()->fHe3Density *
                        float(pMapData->GetTeams()) / float(pMapData->GetMinableAsteroids());


    for (ClusterLinkIGC*    pcl = pMapData->GetMission()->GetClusters()->first(); (pcl != NULL); pcl = pcl->next())
    {
        IclusterIGC*    pcluster = pcl->data();
        if (pcluster->GetHomeSector())
            GenerateStarbase(pMapData, pcluster);

        PopulateCluster(pMapData, pcluster, amountHe3);
    }
}

VOID CmapMakerIGC::RevealHomeClusters(ImissionIGC * pMission)
{
    //
    // Show every side everything about its home
    //
    for (SideLinkIGC * psl = pMission->GetSides()->first();
        (psl != NULL);
        psl = psl->next())
    {
        IsideIGC*   pside = psl->data();

        for (StationLinkIGC * pstnl = pside->GetStations()->first();
            (pstnl != NULL);
            pstnl = pstnl->next())
        {
            //
            // Make every model in the station's cluster visible to the side
            //
            for (ModelLinkIGC * pml =
                    pstnl->data()->GetCluster()->GetModels()->first();
                (pml != NULL);
                pml = pml->next())
            {
                pml->data()->SetSideVisibility(pside, true);
            }
        }
    }
}

VOID CmapMakerIGC::RevealMap(ImissionIGC * pMission)
{
    //
    // Show every side every warp
    //
    for (WarpLinkIGC * pwl = pMission->GetWarps()->first();
        (pwl != NULL);
        pwl = pwl->next())
    {
        IwarpIGC*   pwarp = pwl->data();

        for (SideLinkIGC * psl = pMission->GetSides()->first();
            (psl != NULL);
            psl = psl->next())
        {
            pwarp->SetSideVisibility(psl->data(), true);
        }
    }
}

VOID CmapMakerIGC::ActivateSides(ImissionIGC * pMission)
{
    const SideListIGC * psideList = pMission->GetSides();

    for (SideLinkIGC * psidelink = psideList->first();
        NULL != psidelink;
        psidelink = psidelink->next())
    {
        psidelink->data()->SetActiveF(true);
    }
}


//
// Double ring implementation.
//
CmapMakerDoubleRingIGC::CmapMakerDoubleRingIGC()
{
    mMMID = c_mmDoubleRing;
    this->SetName("Double Ring");
}

VOID CmapMakerDoubleRingIGC::GenerateTeamClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float   flTheta = (float) (2.0 * pi * sID / pMapData->GetTotalClusters());
    pdc->screenX = cos(flTheta) * 0.9f;
    pdc->screenY = sin(flTheta) * 0.9f;
}


VOID CmapMakerDoubleRingIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float   flTheta = (float) (2.0 * pi * sID / pMapData->GetTotalClusters());
    float   flRadius = (pMapData->GetTeams() == 2) && (pMapData->GetTeamClustersPerTeam() == 2)
                       ? 0.2f
                       : 0.3f;
    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}


VOID CmapMakerDoubleRingIGC::LinkClusters(CMapData * pMapData)
{
    SectorID sID, cTotalSectors, sWrapID, sIndex;

    //
    // Link each team's group of sectors.
    //
    cTotalSectors = pMapData->GetTotalClusters();
    for(sID = 0; sID < cTotalSectors; sID += pMapData->GetClustersPerTeam())
    {
        sWrapID = (sID + cTotalSectors - 1) % cTotalSectors;

        for(sIndex = 0; sIndex < pMapData->GetTeamClustersPerTeam(); sIndex++)
        {
            CmapMakerIGC::LinkClusters(pMapData,
                                    sID + sIndex,
                                    sID + pMapData->GetTeamClustersPerTeam());
            CmapMakerIGC::LinkClusters(pMapData,
                                    sID + sIndex,
                                    sWrapID);
        }
    }

    //
    // Link the ring around the outside.
    //
    sWrapID = cTotalSectors - 1 - pMapData->GetNeutralClustersPerTeam();
    for(sID = 0; sID < cTotalSectors; sID++)
    {
        if (NA != pMapData->GetClusterSide(sID))
        {
            CmapMakerIGC::LinkClusters(pMapData, sID, sWrapID);
            sWrapID = sID;
        }
    }

    //
    // Link the ring around the inside.
    //
    sWrapID = cTotalSectors - 1;
    for(sID = 0; sID < cTotalSectors; sID++)
    {
        if (NA == pMapData->GetClusterSide(sID))
        {
            CmapMakerIGC::LinkClusters(pMapData, sID, sWrapID);
            sWrapID = sID;
        }
    }
}

//
// Big ring implementation.
//
CmapMakerBigRingIGC::CmapMakerBigRingIGC()
{
    mMMID = c_mmBigRing;
    this->SetName("Big Ring");
}

VOID CmapMakerBigRingIGC::GenerateLayout(CMapData * pMapData)
{
    //SectorID    s = pMapData->GetMaxPlayersOnTeam() >= 30 ? 2 : 1;
	//KGJV-: changed, use now MapSize parameter
    SectorID    s = pMapData->GetMapSize() != 0 ? 2 : 1;
    pMapData->SetTeamClustersPerTeam(s);
    pMapData->SetNeutralClustersPerTeam(2);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}

VOID CmapMakerBigRingIGC::GenerateTeamClusterScreenPosition(CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID    s = (pMapData->GetTeamClustersPerTeam() == 1) ? (sID / 3) : ((sID + 1) / 2);
    SectorID    n = pMapData->GetTeamClusters();
    float flTheta = (float) (2.0 * pi * s / n);

    pdc->screenX = cos(flTheta) * 0.9f;
    pdc->screenY = sin(flTheta) * 0.9f;
}
VOID CmapMakerBigRingIGC::GenerateNeutralClusterScreenPosition(CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float       flTheta;

    SectorID    n = pMapData->GetNeutralClusters();
    if (pMapData->GetTeamClustersPerTeam() == 1)
    {
        SectorID    s = (sID - 1 - sID/3);
        flTheta = (float) (2.0 * pi * (s + 0.5f) / n);
    }
    else
    {
        SectorID    s =  ((sID + 1) / 2);
        flTheta = (float) (2.0 * pi * s / n);
    }

    pdc->screenX = cos(flTheta) * 0.6f;
    pdc->screenY = sin(flTheta) * 0.6f;
}

VOID CmapMakerBigRingIGC::LinkClusters(CMapData * pMapData)
{
    //
    // Link the ring
    //
    SectorID    cTotalSectors = pMapData->GetTotalClusters();
    {
        SectorID    sWrapID = cTotalSectors - 1;
        for(SectorID    sID = 0; sID < cTotalSectors; sID++)
        {
            CmapMakerIGC::LinkClusters(pMapData, sID, sWrapID);
            sWrapID = sID;
        }
    }


    if (pMapData->GetTeams() > 2)
    {
        SectorID    n = pMapData->GetTeamClustersPerTeam();
        for (SideID i = 0; (i < pMapData->GetTeams()); i++)
        {
            SectorID    sID = i * pMapData->GetClustersPerTeam();
            CmapMakerIGC::LinkClusters(pMapData, sID + n, (sID + 3 + 2*n) % cTotalSectors);
            if (pMapData->GetTeams() > 3)
                CmapMakerIGC::LinkClusters(pMapData, sID + n + 1, (cTotalSectors + (sID - 2)) % cTotalSectors);
        }
    }
}
//
// HiLo implementation.
//
CmapMakerHiLoIGC::CmapMakerHiLoIGC()
{
    mMMID = c_mmHiLo;
    this->SetName("HiLo");
}

VOID CmapMakerHiLoIGC::GenerateLayout(CMapData * pMapData)
{
    //pMapData->SetTeamClustersPerTeam(pMapData->GetMaxPlayersOnTeam() >= 30 ? 2 : 1);
	//KGJV-: changed, use now MapSize parameter
    pMapData->SetTeamClustersPerTeam(pMapData->GetMapSize() != 0 ? 2 : 1);
                                    
    pMapData->SetNeutralClustersPerTeam(3);

    pMapData->SetOtherClusters(1);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}

VOID CmapMakerHiLoIGC::GenerateTeamClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float flTheta, flRadius;
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    sID = sID % pMapData->GetClustersPerTeam();

    flTheta = (float) (2.0f * pi * float(sTeam) / float(pMapData->GetTeams()));
    flRadius = 0.5f + 0.4f * sID;

    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}

VOID CmapMakerHiLoIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    if (sTeam < pMapData->GetTeams())
    {
        sID = (sID % pMapData->GetClustersPerTeam()) - pMapData->GetTeamClustersPerTeam();

        float flTheta1 = (float) (2.0 * pi * sTeam / pMapData->GetTeams());
        float flTheta2 = (float) (2.0 * pi * (sTeam + 1) / pMapData->GetTeams());

        float   flTheta;
        float   flRadius;
        switch (sID)
        {
            case 0:
                flTheta = (flTheta1 + flTheta2) / 2.0f;
                flRadius = 0.4f;
            break;
            case 1:
                flTheta = (2.0f * flTheta1 + flTheta2) / 3.0f;
                flRadius = 0.8f;
            break;
            case 2:
                flTheta = (flTheta1 + 2.0f * flTheta2) / 3.0f;
                flRadius = 0.8f;
            break;
        }

        pdc->screenX = cos(flTheta) * flRadius;
        pdc->screenY = sin(flTheta) * flRadius;
    }
    else
        pdc->screenX = pdc->screenY = 0.0f;
}

VOID CmapMakerHiLoIGC::LinkClusters(CMapData * pMapData)
{
    if (pMapData->GetTeamClustersPerTeam() != 1)
    {
        //Link the split base clusters for each team
        for (SideID i = 0; (i < pMapData->GetTeams()); i++)
        {
            SectorID    sID = i * pMapData->GetClustersPerTeam();
            CmapMakerIGC::LinkClusters(pMapData, sID, sID + 1);
        }
    }

    {
        SectorID    sidCenter = pMapData->GetTotalClusters() - 1;

        for (SideID i = 0; (i < pMapData->GetTeams()); i++)
        {
            SectorID    sID = i * pMapData->GetClustersPerTeam() +
                              pMapData->GetTeamClustersPerTeam();

            //Inner ring to center
            CmapMakerIGC::LinkClusters(pMapData, sID, sidCenter);

            //Inner ring to inner previous team cluster
            SectorID    sidPrevious = i * pMapData->GetClustersPerTeam();
            CmapMakerIGC::LinkClusters(pMapData, sID, sidPrevious);

            //Inner ring to inner next team cluster
            SectorID    sidNext = ((i+1)%pMapData->GetTeams()) * pMapData->GetClustersPerTeam();
            CmapMakerIGC::LinkClusters(pMapData, sID, sidNext);

            //Outer ring 1 to outer ring 2
            CmapMakerIGC::LinkClusters(pMapData, sID + 1, sID + 2);

            //Outer ring 1 to previous team
            CmapMakerIGC::LinkClusters(pMapData, sID + 1, sidPrevious + pMapData->GetTeamClustersPerTeam() - 1);

            //Outer ring 2 to previous team
            CmapMakerIGC::LinkClusters(pMapData, sID + 2, sidNext + pMapData->GetTeamClustersPerTeam() - 1);
        }
    }
}

//
// HiHigher implementation.
//
CmapMakerHiHigherIGC::CmapMakerHiHigherIGC()
{
    mMMID = c_mmHiHigher;
    this->SetName("HiHigher");
}

VOID CmapMakerHiHigherIGC::GenerateLayout(CMapData * pMapData)
{
    pMapData->SetTeamClustersPerTeam((mMMID == c_mmHiHigher)
                                     //? (pMapData->GetMaxPlayersOnTeam() >= 30 ? 2 : 1)
									 //KGJV-: changed, use now MapSize parameter
									 ? (pMapData->GetMapSize() != 0 ? 2 : 1)
                                     : ((mMMID == c_mmLargeSplit)
                                        ? 2
                                        : 1));
                                    
    pMapData->SetNeutralClustersPerTeam(5);

    pMapData->SetOtherClusters(1);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}

VOID CmapMakerHiHigherIGC::GenerateTeamClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam = sID / pMapData->GetClustersPerTeam();
    sID = (sID % pMapData->GetClustersPerTeam());

    float flTheta;
    float flRadius;
    if (mMMID == c_mmInsideOut)
    {
        flTheta = (float) (2.0 * pi * (sTeam + 0.5f) / pMapData->GetTeams());
        flRadius = 0.3f;
    }
    else
    {
        flTheta = (float) (2.0 * pi * sTeam / pMapData->GetTeams());
        flRadius = (pMapData->GetTeamClustersPerTeam() == 1) ? 1.0f : (0.75f + 0.25f * sID);
    }

    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}

VOID CmapMakerHiHigherIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    if (sTeam < pMapData->GetTeams())
    {
        sID = (sID % pMapData->GetClustersPerTeam()) - pMapData->GetTeamClustersPerTeam();

        float flTheta1 = (float) (2.0 * pi * sTeam / pMapData->GetTeams());
        float flTheta2 = (float) (2.0 * pi * (sTeam + 1) / pMapData->GetTeams());

        float   flTheta;
        float   flRadius;
        switch (sID)
        {
            case 0:
                flTheta = (3.0f * flTheta1 + flTheta2) / 4.0f;
                flRadius = 0.6f;
            break;
            case 1:
                if (mMMID == c_mmInsideOut)
                {
                    flTheta = flTheta1;
                    flRadius = 1.0f;
                }
                else
                {
                    flTheta = (flTheta1 + flTheta2) / 2.0f;
                    flRadius = 0.3f;
                }
            break;
            case 2:
                flTheta = (flTheta1 + 3.0f * flTheta2) / 4.0f;
                flRadius = 0.6f;
            break;
            case 3:
                flTheta = (2.0f * flTheta1 + flTheta2) / 3.0f;
                flRadius = 1.0f;
            break;
            case 4:
                flTheta = (flTheta1 + 2.0f * flTheta2) / 3.0f;
                flRadius = 1.0f;
            break;
        }

        pdc->screenX = cos(flTheta) * flRadius;
        pdc->screenY = sin(flTheta) * flRadius;
    }
    else
        pdc->screenX = pdc->screenY = 0.0f;
}

VOID CmapMakerHiHigherIGC::LinkClusters(CMapData * pMapData)
{
    if ((pMapData->GetTeamClustersPerTeam() != 1) && (mMMID != c_mmLargeSplit))
    {
        //Link the split base clusters for each team
        for (SideID i = 0; (i < pMapData->GetTeams()); i++)
        {
            SectorID    sID = i * pMapData->GetClustersPerTeam();
            CmapMakerIGC::LinkClusters(pMapData, sID, sID + 1);
        }
    }

    {
        SectorID    sidCenter = pMapData->GetTotalClusters() - 1;

        for (SideID i = 0; (i < pMapData->GetTeams()); i++)
        {
            SectorID    sIDp = i * pMapData->GetClustersPerTeam();
            SectorID    sID0 = sIDp +
                               pMapData->GetTeamClustersPerTeam();

            SectorID    sID1 = sID0 + 1;
            SectorID    sID2 = sID0 + 2;
            SectorID    sID3 = sID0 + 3;
            SectorID    sID4 = sID0 + 4;

            SectorID    sIDn = ((i+1)%pMapData->GetTeams()) * pMapData->GetClustersPerTeam();

            if (mMMID == c_mmInsideOut)
            {
                assert (pMapData->GetTeamClustersPerTeam() == 1);
                sID1 = sIDp;
                sIDp = sID0 + 1;
                sIDn = ((i+1)%pMapData->GetTeams()) * pMapData->GetClustersPerTeam() + 1 + 1;
            }

            //Inner ring to center
            CmapMakerIGC::LinkClusters(pMapData, sID1, sidCenter,
                                       (mMMID == c_mmInsideOut) ? c_HiddenToPlayerAleph : NA);

            CmapMakerIGC::LinkClusters(pMapData, sID0, sID1);
            CmapMakerIGC::LinkClusters(pMapData, sID1, sID2);

            CmapMakerIGC::LinkClusters(pMapData, sID0, sID3);
            CmapMakerIGC::LinkClusters(pMapData, sID2, sID4);

            CmapMakerIGC::LinkClusters(pMapData, sID3, sID4);

            CmapMakerIGC::LinkClusters(pMapData, sID0, sIDp);
            CmapMakerIGC::LinkClusters(pMapData, sID2, sIDn);

            CmapMakerIGC::LinkClusters(pMapData, sID3, sIDp + pMapData->GetTeamClustersPerTeam() - 1);
            CmapMakerIGC::LinkClusters(pMapData, sID4, sIDn + pMapData->GetTeamClustersPerTeam() - 1);

            if (pMapData->GetMissionParams()->iRandomEncounters != 0)
                CmapMakerIGC::LinkClusters(pMapData, sID2, 
                                           (mMMID == c_mmInsideOut)
                                           ? (sIDn - 1)
                                           : (sIDn + pMapData->GetTeamClustersPerTeam()));
        }
    }
}

//
// Star implementation.
//
CmapMakerStarIGC::CmapMakerStarIGC()
{
    mMMID = c_mmStar;
    this->SetName("Star");
}

VOID CmapMakerStarIGC::GenerateLayout(CMapData * pMapData)
{
    //pMapData->SetTeamClustersPerTeam(pMapData->GetMaxPlayersOnTeam() >= 30 ? 2 : 1);
	//KGJV-: changed, use now MapSize parameter
    pMapData->SetTeamClustersPerTeam(pMapData->GetMapSize() != 0 ? 2 : 1);
                                    
    pMapData->SetNeutralClustersPerTeam(5);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}

VOID CmapMakerStarIGC::GenerateTeamClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam = sID / pMapData->GetClustersPerTeam();
    sID = sID % pMapData->GetClustersPerTeam();

    float   flDelta = (2.0f * pi / float(pMapData->GetTeams()));
    float   flTheta = flDelta * float(sTeam);

    if (pMapData->GetTeamClustersPerTeam() == 2)
        flTheta += flDelta * (float(sID) - 0.5f) * 0.5f;

    pdc->screenX = cos(flTheta);
    pdc->screenY = sin(flTheta);
}

VOID CmapMakerStarIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam = sID / pMapData->GetClustersPerTeam();
    sID = sID % pMapData->GetClustersPerTeam() - pMapData->GetTeamClustersPerTeam();

    float   flRadius;
    float   flDelta = (2.0f * pi / float(pMapData->GetTeams()));
    float   flTheta = flDelta * float(sTeam);
    switch (sID)
    {
        case 0:
        case 1:
        {
            flRadius = 0.7f;
            flTheta += flDelta * (float(sID) - 0.5f) * 0.5f;
        }
        break;
        case 3:
        {
            flTheta += flDelta * 0.5f;
        }
        //no break
        case 2:
        {
            flRadius = 0.5f;
        }
        break;

        case 4:
        {
            flRadius = 0.2f;
        }
        break;
    }

    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}

VOID CmapMakerStarIGC::LinkClusters(CMapData * pMapData)
{
    {
        SectorID    sidCenter = pMapData->GetTotalClusters() - 1;

        for (SideID i = 0; (i < pMapData->GetTeams()); i++)
        {
            SectorID    sID = i * pMapData->GetClustersPerTeam() +
                              pMapData->GetTeamClustersPerTeam();

            //Inner starting sectors to neutral sectors
            if (pMapData->GetTeamClustersPerTeam() == 1)
            {
                CmapMakerIGC::LinkClusters(pMapData, sID,     sID - 1);
                CmapMakerIGC::LinkClusters(pMapData, sID + 1, sID - 1);
            }
            else
            {
                CmapMakerIGC::LinkClusters(pMapData, sID - 1, sID - 2);
                CmapMakerIGC::LinkClusters(pMapData, sID,     sID - 2);
                CmapMakerIGC::LinkClusters(pMapData, sID + 1, sID - 1);
            }

            CmapMakerIGC::LinkClusters(pMapData, sID, sID + 2);
            CmapMakerIGC::LinkClusters(pMapData, sID + 1, sID + 2);
            CmapMakerIGC::LinkClusters(pMapData, sID + 1, sID + 3);

            CmapMakerIGC::LinkClusters(pMapData, sID + 2, sID + 3);
            CmapMakerIGC::LinkClusters(pMapData, sID + 2, sID + 4);

            {
                SectorID    s = (sID + pMapData->GetTotalClusters() - pMapData->GetClustersPerTeam()) % pMapData->GetTotalClusters();
                CmapMakerIGC::LinkClusters(pMapData, s + 3, sID);
                CmapMakerIGC::LinkClusters(pMapData, s + 3, sID + 2);
            }

            {
                SideID      j = (i + pMapData->GetTeams()/2) % pMapData->GetTeams();
                SectorID    s = j * pMapData->GetClustersPerTeam() +
                                pMapData->GetTeamClustersPerTeam();
                if (pMapData->GetTeams() % 2 == 0)
                {
                    CmapMakerIGC::LinkClusters(pMapData, sID + 4, s + 4);
                }
                else
                {
                    CmapMakerIGC::LinkClusters(pMapData, sID + 4, s + 4);
                    CmapMakerIGC::LinkClusters(pMapData, sID + 4, (s + 4 + pMapData->GetClustersPerTeam()) % pMapData->GetTotalClusters());
                }
            }
        }
    }
}

//
// Brawl
//
CmapMakerBrawlIGC::CmapMakerBrawlIGC()
{
    mMMID = c_mmBrawl;
    this->SetName("Brawl");
}


const char* CmapMakerBrawlIGC::IsValid(const MissionParams * pmp)
{
	// yp your_persona removed march 24 2006
    //if (pmp->nMaxPlayersPerTeam * pmp->nTeams > 36)
    //    return("Brawl maps must have less than 37 players; "
    //            "please change the map type, number of players per team, "
    //            "or number of teams.");

    return(NULL);
}


VOID CmapMakerBrawlIGC::GenerateLayout(CMapData * pMapData)
{
    pMapData->SetTeamClustersPerTeam(0);

    pMapData->SetOtherClusters(1);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}


VOID CmapMakerBrawlIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    pdc->screenX = 0.0f;
    pdc->screenY = 0.0f;
}


VOID CmapMakerBrawlIGC::LinkClusters(CMapData * pMapData)
{
}


VOID CmapMakerBrawlIGC::PopulateCluster(CMapData*    pMapData,
                                        IclusterIGC* pcluster,
                                        float        amountHe3)
{
    SectorID    sID = pcluster->GetObjectID();

    //Place all the space stations ... 1/side
    for (SideID sideID = 0; (sideID < pMapData->GetTeams()); sideID++)
    {
        DataStationIGC ds;

        IsideIGC*  pSide = pMapData->GetMission()->GetSide(sideID);
        assert(pSide);

        ds.clusterID = sID;
        {
            const float c_startRadius = 2500.0f;

            float   angle = 2.0f * pi * float(sideID) / float(pMapData->GetTeams());
            ds.position.x = c_startRadius * cos(angle);
            ds.position.y = c_startRadius * sin(angle);
            ds.position.z = 0.0f;
        }
        ds.forward.x = ds.forward.y = 0.0f;
        ds.forward.z = 1.0f;
        ds.up.x = 1.0f;
        ds.up.y = ds.up.z = 0.0f;

        ds.rotation.axis(ds.forward);
        ds.rotation.angle(0.0f);

        ds.bpHull = 1.0f;
        ds.bpShield = 1.0f;

        ds.sideID = sideID;
        ds.stationID = pMapData->GetMission()->GenerateNewStationID();

        IstationTypeIGC*    pst = pSide->GetCivilization()->GetInitialStationType();
        assert (pst);

        ds.stationTypeID = pst->GetObjectID();
        strcpy(ds.name, pst->GetName());

        IstationIGC*    pstation = (IstationIGC*)pMapData->GetMission()->CreateObject(pMapData->GetTime(),
                                                                                       OT_station,
                                                                                       &ds,
                                                                                       sizeof(ds));
        assert(pstation);

        pstation->Release();

    }

    for (int i = randomInt(3, 5); (i >= 0); i--)
    {
        CreateAsteroid(pMapData->GetMission(), pcluster, IasteroidIGC::GetRandomType(0), 0.0f);
    }

    ::PopulateCluster(pMapData->GetMission(), pMapData->GetMissionParams(), pcluster, amountHe3,
                    true, true,
                    1, -3 * (pMapData->GetTeams()/2));
}

//
// PinWheel
//
CmapMakerPinWheelIGC::CmapMakerPinWheelIGC()
{
    mMMID = c_mmPinWheel;
    this->SetName("PinWheel");
}


const char* CmapMakerPinWheelIGC::IsValid(const MissionParams * pmp)
{
	// yp your_persona removed march 24 2006
    //if (pmp->nMaxPlayersPerTeam > 200)
    //  return("Pinwheel maps must have less than 201 player per team; "
    //"please change the map type, or number of players per team.");
	//
    return(NULL);
}


VOID CmapMakerPinWheelIGC::GenerateLayout(CMapData * pMapData)
{
    pMapData->SetTeamClustersPerTeam(1);

	//if (pMapData->GetMaxPlayersInMission() <= 30)
    //KGJV-: changed, use now MapSize parameter
    if (pMapData->GetMapSize() == 0)
        pMapData->SetOtherClusters(1);
    else
        pMapData->SetNeutralClustersPerTeam(1);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}


VOID CmapMakerPinWheelIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float flTheta;

    if (0 != pMapData->GetNeutralClustersPerTeam())
    {
        sID = sID / pMapData->GetClustersPerTeam();
        flTheta = (float) (2.0 * pi * sID / pMapData->GetNeutralClusters());
        pdc->screenX = cos(flTheta) * 0.4f;
        pdc->screenY = sin(flTheta) * 0.4f;
    } else
        pdc->screenX = pdc->screenY = 0.0f;
}


VOID CmapMakerPinWheelIGC::LinkClusters(CMapData * pMapData)
{
    SectorID sID, cTotalClusters, sWrapID, sFirstNA;

    cTotalClusters = pMapData->GetTotalClusters();
    if (0 != pMapData->GetNeutralClustersPerTeam())
    {
        //
        // Multiple sectors in the center.
        //
        sWrapID = NA;
        for(sID = 0; sID < cTotalClusters; sID++)
        {
            if (NA != pMapData->GetClusterSide(sID))
                CmapMakerIGC::LinkClusters(pMapData, sID, sID + 1);
            else
            {
                if (NA != sWrapID)
                    CmapMakerIGC::LinkClusters(pMapData, sID, sWrapID);
                else
                    sFirstNA = sID;
                sWrapID = sID;
            }
        }

        if (pMapData->GetTeams() > 2)
            CmapMakerIGC::LinkClusters(pMapData, sWrapID, sFirstNA);
        this->CrossLinkClusters(pMapData, pMapData->GetTeamClustersPerTeam());
    }
    else
    {
        //
        // Single sector in the middle.
        //
        for(sID = 0; sID < cTotalClusters; sID++)
        {
            if (NA != pMapData->GetClusterSide(sID))
                CmapMakerIGC::LinkClusters(pMapData, sID, cTotalClusters - 1);
        }
    }
}

VOID CmapMakerPinWheelIGC::PopulateCluster(CMapData*    pMapData,
                                           IclusterIGC* pcluster,
                                           float        amountHe3)
{
    short   k;
    if (pcluster->GetHomeSector() ||
        (pMapData->GetNeutralClustersPerTeam() != 0))
    {
        k = 1;
    }
    else
        k = 2;

    ::PopulateCluster(pMapData->GetMission(), pMapData->GetMissionParams(), pcluster, amountHe3,
                    true, true,
                    k, k, k);
}


//
// Diamond ring.
//
CmapMakerDiamondRingIGC::CmapMakerDiamondRingIGC()
{
    mMMID = c_mmDiamondRing;
    this->SetName("Diamond Ring");
}


const char* CmapMakerDiamondRingIGC::IsValid(const MissionParams * pmp)
{
    if (pmp->nTeams < 3)
        return("Diamond ring maps must have more than 2 teams; "
               "please change the map type, or number of teams.");

    return(NULL);
}


VOID CmapMakerDiamondRingIGC::GenerateLayout(CMapData * pMapData)
{
    //pMapData->SetTeamClustersPerTeam(pMapData->GetMaxPlayersOnTeam() >= 30 ? 2 : 1);
	//KGJV-: changed, use now MapSize parameter
    pMapData->SetTeamClustersPerTeam(pMapData->GetMapSize() != 0 ? 2 : 1);
    pMapData->SetNeutralClustersPerTeam(2);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}


VOID CmapMakerDiamondRingIGC::GenerateTeamClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float flTheta, flAdjust, flRadius;
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    sID = sID % pMapData->GetTeamClustersPerTeam();

    flTheta = (float) (2.0 * pi * sTeam / pMapData->GetTeams());
    switch(pMapData->GetTeamClustersPerTeam())
    {
        case 2:
            flAdjust = (float) (pi / 8.0f);
            if (1 == sID)
                flAdjust = -flAdjust;
            break;
        case 3:
            flAdjust = (sID - 1) * (float) (pi / 6.0f);
            break;
        default:
            flAdjust = 0.0f;
            break;
    }
    flTheta += flAdjust;
    flRadius = 0.55f;
    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}


VOID CmapMakerDiamondRingIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float flTheta, flRadius;
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    sID = (sID % pMapData->GetClustersPerTeam()) -
            pMapData->GetTeamClustersPerTeam();
    if (0 == (sID & 0x01))
    {
        flRadius = 0.3f;
    } else
        flRadius = 0.8f;

    flTheta = (float) (2.0 * pi * sTeam / pMapData->GetTeams());
    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}


VOID CmapMakerDiamondRingIGC::LinkClusters(CMapData * pMapData)
{
    SectorID sID, cTotalSectors, sNeutralID, sIndex;

    //
    // Link each team's group of sectors.
    //
    cTotalSectors = pMapData->GetTotalClusters();
    for(sID = 0; sID < cTotalSectors; sID += pMapData->GetClustersPerTeam())
    {
        sNeutralID = sID + pMapData->GetTeamClustersPerTeam();

        for(sIndex = 0; sIndex < pMapData->GetTeamClustersPerTeam(); sIndex++)
        {
            CmapMakerIGC::LinkClusters(pMapData,
                                        sID + sIndex,
                                        sNeutralID);
            CmapMakerIGC::LinkClusters(pMapData,
                                        sID + sIndex,
                                        sNeutralID + 1);
        }
    }

    //
    // Link the rings.
    //
    for(sID = 0; sID < cTotalSectors; sID++)
    {
        if (NA == pMapData->GetClusterSide(sID))
        {
            sNeutralID = (sID + pMapData->GetClustersPerTeam()) % cTotalSectors;
            CmapMakerIGC::LinkClusters(pMapData, sID, sNeutralID);
        }
    }

    //
    // Link the center sectors.
    //
    this->CrossLinkClusters(pMapData, pMapData->GetTeamClustersPerTeam());
}


CmapMakerSnowFlakeIGC::CmapMakerSnowFlakeIGC()
{
    mMMID = c_mmSnowFlake;
    this->SetName("SnowFlake");
}


VOID CmapMakerSnowFlakeIGC::GenerateLayout(CMapData * pMapData)
{
    //SectorID    s = pMapData->GetMaxPlayersOnTeam() >= 30 ? 2 : 1;
	//KGJV-: changed, use now MapSize parameter
    SectorID    s = pMapData->GetMapSize() != 0 ? 2 : 1;
    pMapData->SetTeamClustersPerTeam(s);
    pMapData->SetNeutralClustersPerTeam(3);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}


VOID CmapMakerSnowFlakeIGC::GenerateTeamClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float flRadius, flTheta, flAdjust;
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    sID = sID % pMapData->GetClustersPerTeam();

    flTheta = (float) (2.0 * pi * sTeam / pMapData->GetTeams());
    flAdjust = pMapData->GetTeamClustersPerTeam() == 1 ? 0.0f : (float) (pi / (2.0f * pMapData->GetTeams()));

    flRadius = 0.9f;

    if (pMapData->GetTeamClustersPerTeam() == sID + 1)
        flAdjust = -flAdjust;
    flTheta += flAdjust;
    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}


VOID CmapMakerSnowFlakeIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    float flRadius, flTheta, flAdjust;
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    sID = (sID % pMapData->GetClustersPerTeam()) -
            pMapData->GetTeamClustersPerTeam();

    flTheta = (float) (2.0 * pi * sTeam / pMapData->GetTeams());
    if (sID % 3 < 2)
    {
        //
        // This cluster is in the second ring.
        //
        flRadius = 0.65f;

        flAdjust = (float) (pi / (2.0f * pMapData->GetTeams()));
        if (0 == sID)
            flAdjust = -flAdjust;
    }
    else
    {
        flRadius = 0.3f;
        flAdjust = 0.0f;
    }

    flTheta += flAdjust;
    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}


VOID CmapMakerSnowFlakeIGC::LinkClusters(CMapData * pMapData)
{
    SectorID sID, cTotalClusters, cTeamClustersPerTeam, sIndex;
    SectorID cClustersPerTeam;

    cTotalClusters = pMapData->GetTotalClusters();
    cTeamClustersPerTeam = pMapData->GetTeamClustersPerTeam();
    cClustersPerTeam = pMapData->GetClustersPerTeam();

    for(sID = 0; sID < cTotalClusters; sID += cClustersPerTeam)
    {
        //
        // Link friendly clusters.
        //
        if (cTeamClustersPerTeam > 1)
        {
            for(sIndex = 0; sIndex < cTeamClustersPerTeam - 1; sIndex++)
            {
                CmapMakerIGC::LinkClusters(pMapData,
                                            sID + sIndex,
                                            sID + sIndex + 1);
            }
            CmapMakerIGC::LinkClusters(pMapData, sID + sIndex, sID);
        }

        //
        // Link Neutral clusters.
        //
        sIndex = sID + cTeamClustersPerTeam;
        CmapMakerIGC::LinkClusters(pMapData, sIndex, sIndex + 2);
        CmapMakerIGC::LinkClusters(pMapData, sIndex + 1, sIndex + 2);
        
        //
        // Now we need to link the friendly to the neutral.
        //
        switch(cTeamClustersPerTeam)
        {
            case 3:
                CmapMakerIGC::LinkClusters(pMapData, sID + 1, sIndex);
                CmapMakerIGC::LinkClusters(pMapData, sID + 1, sIndex + 1);
                CmapMakerIGC::LinkClusters(pMapData, sID + 2, sIndex);
                CmapMakerIGC::LinkClusters(pMapData, sID + 2, sIndex + 1);
                break;
            case 2:
                CmapMakerIGC::LinkClusters(pMapData, sID, sIndex);
                CmapMakerIGC::LinkClusters(pMapData, sID, sIndex + 1);
                CmapMakerIGC::LinkClusters(pMapData, sID + 1, sIndex);
                CmapMakerIGC::LinkClusters(pMapData, sID + 1, sIndex + 1);
                break;
            default:
                CmapMakerIGC::LinkClusters(pMapData, sID, sIndex);
                CmapMakerIGC::LinkClusters(pMapData, sID, sIndex + 1);
                break;
        }
    }

    //
    // Now we need to link the second neutral ring.
    //
    sIndex = NA;
    for(sID = cTeamClustersPerTeam;
        sID < cTotalClusters;
        sID += cClustersPerTeam)
    {
        CmapMakerIGC::LinkClusters(pMapData, sID, sID + 1);
        if (NA != sIndex)
            CmapMakerIGC::LinkClusters(pMapData, sIndex, sID);
        sIndex = sID + 1;
    }
    CmapMakerIGC::LinkClusters(pMapData, sIndex, cTeamClustersPerTeam);

    //
    // Cross link the center sectors.
    //
    CmapMakerIGC::CrossLinkClusters(pMapData, cTeamClustersPerTeam + 2);

    //
    // If less than 4 teams, cross linking doesn't do anything.  So
    // make a ring out of them.
    //
    if (pMapData->GetTeams() < 4)
    {
        sIndex = NA;
        for(sID = cTeamClustersPerTeam + 2;
            sID < cTotalClusters;
            sID += cClustersPerTeam)
        {
            if (NA != sIndex)
                CmapMakerIGC::LinkClusters(pMapData, sID, sIndex);
            sIndex = sID;
        }
        if (pMapData->GetTeams() > 2)
        {
            CmapMakerIGC::LinkClusters(pMapData,
                                        sIndex,
                                        cTeamClustersPerTeam + 2);
        }
    }
}


//
// Split Base
//

const char* CmapMakerLargeSplitIGC::IsValid(const MissionParams * pmp)
{
	// yp your_persona removed march 24 2006
    //if (pmp->nMinPlayersPerTeam < 10)
    //  return("Large split maps must have at least 10 players per team; "
    //          "please change the map type, or number of players per team.");
	//
    return(NULL);
}

CmapMakerLargeSplitIGC::CmapMakerLargeSplitIGC()
{
    mMMID = c_mmLargeSplit;
    this->SetName("LargeSplit");
}

CmapMakerInsideOutIGC::CmapMakerInsideOutIGC()
{
    mMMID = c_mmInsideOut;
    this->SetName("Inside out");
}

CmapMakerGridIGC::CmapMakerGridIGC()
{
    mMMID = c_mmGrid;
    this->SetName("Grid");
}


VOID CmapMakerGridIGC::GenerateLayout(CMapData * pMapData)
{
    //pMapData->SetTeamClustersPerTeam(pMapData->GetMaxPlayersOnTeam() >= 30 ? 2 : 1);
	//KGJV-: changed, use now MapSize parameter
    pMapData->SetTeamClustersPerTeam(pMapData->GetMapSize() != 0 ? 2 : 1);
                                    
    pMapData->SetNeutralClustersPerTeam(4);

    pMapData->SetOtherClusters(0);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}

VOID CmapMakerGridIGC::GenerateTeamClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam = sID / pMapData->GetClustersPerTeam();
    sID = (sID % pMapData->GetClustersPerTeam());

    float flTheta;
    float flRadius;
    if (pMapData->GetTeamClustersPerTeam() == 1)
    {
        flTheta = (float) (2.0 * pi * sTeam / pMapData->GetTeams());

        static const float  radii[c_cSidesMax + 1] = {0.0f, 0.0f, 0.55f, 0.6f, 0.65f, 0.70f, 0.75f};
        assert (pMapData->GetTeams() <= c_cSidesMax);
        flRadius = radii[pMapData->GetTeams()];
    }
    else
    {
        flTheta = (float) (2.0 * pi * sTeam / pMapData->GetTeams());

        static const float  radii0[c_cSidesMax + 1] = {0.0f, 0.0f, 0.475f, 0.525f, 0.575f, 0.625f, 0.675f};
        static const float  radii1[c_cSidesMax + 1] = {0.0f, 0.0f, 0.625f, 0.675f, 0.725f, 0.775f, 0.825f};

        assert (pMapData->GetTeams() <= c_cSidesMax);
        flRadius = (sID == 0)
                   ? radii0[pMapData->GetTeams()]
                   : radii1[pMapData->GetTeams()];
    }

    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}

VOID CmapMakerGridIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    sID = (sID % pMapData->GetClustersPerTeam()) - pMapData->GetTeamClustersPerTeam();

    float flTheta1 = (float) (2.0 * pi * sTeam / pMapData->GetTeams());
    float flTheta2 = (float) (2.0 * pi * (sTeam + 1) / pMapData->GetTeams());

    float   flTheta;
    float   flRadius;
    switch (sID)
    {
        case 0:
            flTheta = (5.0f * flTheta1 + flTheta2) / 6.0f;
            flRadius = 1.0f;
        break;
        case 1:
            flTheta = (3.0f * flTheta1 + flTheta2) / 4.0f;
            flRadius = 0.5f;
        break;
        case 2:
            flTheta = (3.0f * flTheta2 + flTheta1) / 4.0f;
            flRadius = 0.5f;
        break;
        case 3:
            flTheta = (5.0f * flTheta2 + flTheta1) / 6.0f;
            flRadius = 1.0f;
        break;
    }

    pdc->screenX = cos(flTheta) * flRadius;
    pdc->screenY = sin(flTheta) * flRadius;
}

VOID CmapMakerGridIGC::LinkClusters(CMapData * pMapData)
{
    if (pMapData->GetTeamClustersPerTeam() != 1)
    {
        //Link the split base clusters for each team
        for (SideID i = 0; (i < pMapData->GetTeams()); i++)
        {
            SectorID    sID = i * pMapData->GetClustersPerTeam();
            CmapMakerIGC::LinkClusters(pMapData, sID, sID + 1);
        }
    }

    {
        SectorID    sidCenter = pMapData->GetTotalClusters() - 1;

        for (SideID i = 0; (i < pMapData->GetTeams()); i++)
        {
            SectorID    sIDh = i * pMapData->GetClustersPerTeam();
            SectorID    sID0 = sIDh +
                               pMapData->GetTeamClustersPerTeam();

            SectorID    sID1 = sID0 + 1;
            SectorID    sID2 = sID0 + 2;
            SectorID    sID3 = sID0 + 3;

            SectorID    sIDn  = ((i+1)%pMapData->GetTeams()) * pMapData->GetClustersPerTeam();
            SectorID    sIDn0 = sIDn +
                                pMapData->GetTeamClustersPerTeam();

            CmapMakerIGC::LinkClusters(pMapData, sID0, sID1);
            CmapMakerIGC::LinkClusters(pMapData, sID1, sID2);
            CmapMakerIGC::LinkClusters(pMapData, sID2, sID3);
            CmapMakerIGC::LinkClusters(pMapData, sID3, sID0);

            CmapMakerIGC::LinkClusters(pMapData, sID2, sIDn0 + 1);
            CmapMakerIGC::LinkClusters(pMapData, sID3, sIDn0 + 0);

            CmapMakerIGC::LinkClusters(pMapData, sID0, sIDh + pMapData->GetTeamClustersPerTeam() - 1);
            CmapMakerIGC::LinkClusters(pMapData, sID1, sIDh);

            CmapMakerIGC::LinkClusters(pMapData, sID2, sIDn);
            CmapMakerIGC::LinkClusters(pMapData, sID3, sIDn + pMapData->GetTeamClustersPerTeam() - 1);

            if (pMapData->GetMissionParams()->iRandomEncounters != 0)
            {
                if (pMapData->GetTeams() == 2)
                    CmapMakerIGC::LinkClusters(pMapData, sID1 + i, sIDn0 + 1 + i);
            }
        }
    }
}

const char* CmapMakerEastWestIGC::IsValid(const MissionParams * pmp)
{
    if (pmp->nTeams != 2) 
        return("East West maps must have exactly two teams; "
                "please change the map type, or the number of teams.");
	// yp your_persona removed march 24 2006
    // else if (pmp->nMinPlayersPerTeam < 10)
    //     return("East West maps must have at least 10 players per team; "
    //            "please change the map type, or the number or players per team.");

    return(NULL);
}

CmapMakerEastWestIGC::CmapMakerEastWestIGC()
{
    mMMID = c_mmEastWest;
    this->SetName("EastWest");
}


VOID CmapMakerEastWestIGC::GenerateLayout(CMapData * pMapData)
{
    pMapData->SetTeamClustersPerTeam(2);
                                    
    pMapData->SetNeutralClustersPerTeam(11);

    pMapData->SetOtherClusters(0);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}

VOID CmapMakerEastWestIGC::GenerateTeamClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam = sID / pMapData->GetClustersPerTeam();
    sID = (sID % pMapData->GetClustersPerTeam());

    pdc->screenX = sTeam == 0     ?  0.70f : -0.70f;
    pdc->screenY = (sID == sTeam) ? -0.55f :  0.55f;
}

VOID CmapMakerEastWestIGC::GenerateNeutralClusterScreenPosition(
                                                    CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID sTeam;

    sTeam = sID / pMapData->GetClustersPerTeam();
    sID = (sID % pMapData->GetClustersPerTeam()) - pMapData->GetTeamClustersPerTeam();

    static const float  x[11] = { 1.0f,  1.0f,  0.4f,  0.4f, 1.0f, 1.0f, 0.4f, 0.4f,  0.15f, 0.15f, 0.15f };
    static const float  y[11] = {-0.9f, -0.2f, -0.9f, -0.2f, 0.2f, 0.9f, 0.2f, 0.9f, -0.55f, 0.00f, 0.55f };

    if (sTeam == 0)
    {
        pdc->screenX = x[sID];
        pdc->screenY = y[sID];
    }
    else
    {
        pdc->screenX = -x[sID];
        pdc->screenY = -y[sID];
    }
}

VOID CmapMakerEastWestIGC::LinkClusters(CMapData * pMapData)
{
    assert (pMapData->GetTeams() == 2);
    assert (pMapData->GetClustersPerTeam() == 13);
    assert (pMapData->GetTeamClustersPerTeam() == 2);

    for (SideID i = 0; (i < 2); i++)
    {
        SectorID    sIDf0 = i * 13;
        SectorID    sIDf1 = sIDf0 + 1;
        SectorID    sID0  = sIDf1 + 1;

        CmapMakerIGC::LinkClusters(pMapData, sIDf0, sID0 + 0);
        CmapMakerIGC::LinkClusters(pMapData, sIDf0, sID0 + 1);
        CmapMakerIGC::LinkClusters(pMapData, sIDf0, sID0 + 2);
        CmapMakerIGC::LinkClusters(pMapData, sIDf0, sID0 + 3);



        CmapMakerIGC::LinkClusters(pMapData, sIDf1, sID0 + 4);
        CmapMakerIGC::LinkClusters(pMapData, sIDf1, sID0 + 5);
        CmapMakerIGC::LinkClusters(pMapData, sIDf1, sID0 + 6);
        CmapMakerIGC::LinkClusters(pMapData, sIDf1, sID0 + 7);

        CmapMakerIGC::LinkClusters(pMapData, sID0 + 0, sID0 + 1);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 1, sID0 + 3);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 3, sID0 + 2);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 2, sID0 + 0);

        CmapMakerIGC::LinkClusters(pMapData, sID0 + 4, sID0 + 5);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 5, sID0 + 7);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 7, sID0 + 6);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 6, sID0 + 4);


        CmapMakerIGC::LinkClusters(pMapData, sID0 + 4, sID0 + 1);

        CmapMakerIGC::LinkClusters(pMapData, sID0 + 8, sID0 + 2);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 8, sID0 + 3);

        CmapMakerIGC::LinkClusters(pMapData, sID0 + 9, sID0 + 3);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 9, sID0 + 6);

        CmapMakerIGC::LinkClusters(pMapData, sID0 + 10, sID0 + 6);
        CmapMakerIGC::LinkClusters(pMapData, sID0 + 10, sID0 + 7);
    }

    CmapMakerIGC::LinkClusters(pMapData, 10, 25);
    CmapMakerIGC::LinkClusters(pMapData, 11, 24);
    CmapMakerIGC::LinkClusters(pMapData, 12, 23);
}

VOID CmapMakerEastWestIGC::PopulateCluster(CMapData*    pMapData,
                                           IclusterIGC* pcluster,
                                           float        amountHe3)
{
    SectorID    localID = (pcluster->GetObjectID() % pMapData->GetClustersPerTeam());

    static const short  cMineable[13] = {2, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1};
    static const short  cSpecial[13]  = {0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0};

    ::PopulateCluster(pMapData->GetMission(), pMapData->GetMissionParams(), pcluster, amountHe3,
                    true, true,
                    cMineable[localID], cSpecial[localID]);
}

const char* CmapMakerSplitBaseIGC::IsValid(const MissionParams * pmp)
{
	// yp your_persona removed  march 24 2006
    //if (pmp->nTeams * pmp->nMinPlayersPerTeam < 30)
    //    return("Split base maps must have at least 30 players; "
    //           "please change the map type, the number of teams, or number of players per team.");

    return(NULL);
}
CmapMakerSplitBaseIGC::CmapMakerSplitBaseIGC()
{
    mMMID = c_mmSplitBase;
    this->SetName("Split Base");
}
VOID CmapMakerSplitBaseIGC::GenerateLayout(CMapData * pMapData)
{
    pMapData->SetTeamClustersPerTeam(2);
    pMapData->SetNeutralClustersPerTeam(2);

    this->GenerateRingClusters(pMapData);

    //
    // Now that we have the clusters, link them together.
    //
    this->LinkClusters(pMapData);
}

VOID CmapMakerSplitBaseIGC::GenerateTeamClusterScreenPosition(CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID    n = pMapData->GetTeamClusters();
    SectorID    s = (sID + 1) / 2;
    float flTheta = (float) (2.0 * pi * s / n);
    //float flRadius = pMapData->GetTotalClusters() <= 18 ? 0.8f : 1.0f;
    pdc->screenX = cos(flTheta) * 0.9f;
    pdc->screenY = sin(flTheta) * 0.9f;
}

VOID CmapMakerSplitBaseIGC::GenerateNeutralClusterScreenPosition(CMapData * pMapData,
                                                    DataClusterIGC * pdc,
                                                    SectorID sID)
{
    SectorID    n = pMapData->GetTeamClusters();
    SectorID    s = (sID + 1) / 2;
    float flTheta = (float) (2.0 * pi * s / n);
    //float flRadius = pMapData->GetTotalClusters() <= 18 ? 0.5f : 0.7f;
    pdc->screenX = cos(flTheta) * 0.6f;
    pdc->screenY = sin(flTheta) * 0.6f;
}

VOID CmapMakerSplitBaseIGC::LinkClusters(CMapData * pMapData)
{
    SectorID    cTotalSectors = pMapData->GetTotalClusters();
    for (SideID i = 0; (i < pMapData->GetTeams()); i++)
    {
        SectorID    sID = i * pMapData->GetClustersPerTeam();

        CmapMakerIGC::LinkClusters(pMapData, sID + 1, sID + 2);
        CmapMakerIGC::LinkClusters(pMapData, sID + 2, sID + 3);
        CmapMakerIGC::LinkClusters(pMapData, sID + 3, (sID + 4) % cTotalSectors);
        CmapMakerIGC::LinkClusters(pMapData, sID + 2, (cTotalSectors + (sID - 1)) % cTotalSectors);

        if (pMapData->GetTeams() > 2)
        {
            CmapMakerIGC::LinkClusters(pMapData, sID + 2, (sID + 7) % cTotalSectors);
            if (pMapData->GetTeams() > 3)
                CmapMakerIGC::LinkClusters(pMapData, sID + 3, (cTotalSectors + (sID - 2)) % cTotalSectors);
        }
    }
}