Page 1 of 2 12 LastLast
Results 1 to 20 of 30

Thread: Total Campaign Generator 1.0

  1. #1

    Default Total Campaign Generator 1.0

    Total Campaign Generator 1.0
    App for windows

    This app generates random campaign maps (including terrain and regions) for Medieval II: Total War at the click of a button.

    Features

    • Random world generation
    • Generates multiple nations
    • Choose alliances and wealth
    • Map types: Inland, Coastal
    • Small or Large campaign worlds
    • Customize world terrain including rivers, hills and plains
    • Explored or unexplored world
    • Brief or long campaigns with many factions
    • Generate campaigns for Americas, Britannia, Crusades and Teutonic expansion campaigns
    • 5 climate types


    Download:
    http://sourceforge.net/projects/totalcampaigngenerator/



    Video and example map:

    https://www.youtube.com/watch?v=e_TCSWZdwoc




  2. #2

    Default Re: Total Campaign Generator 1.0

    A screenshot of the gui:


  3. #3
    The Holy Pilgrim's Avatar In Memory of Blackomur
    Citizen

    Join Date
    Feb 2009
    Location
    Someplace other than here
    Posts
    11,913

    Default Re: Total Campaign Generator 1.0

    This looks absolutely fantastic!

    Can it be modified to work with mods, or no? Also, how does it handle character attributes and traits?

    +rep, regardless

  4. #4
    KEA's Avatar Senator
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    1,104

    Default Re: Total Campaign Generator 1.0

    Looks really good

  5. #5
    Frunk's Avatar Form Follows Function
    Moderator Emeritus

    Join Date
    Jun 2009
    Location
    Gold Coast
    Posts
    6,493

    Default Re: Total Campaign Generator 1.0

    Great work! I'm keen to try it out sometime.
    FrunkSpace | Mod Announcements | Colonies & Empires

    Under the patronage of Iskar of the House of Siblesz. I am the proud patron of:

    atthias | PaulH | Athos187

  6. #6

    Default Re: Total Campaign Generator 1.0

    Quote Originally Posted by The Holy Pilgrim View Post
    This looks absolutely fantastic!

    Can it be modified to work with mods, or no? Also, how does it handle character attributes and traits?

    +rep, regardless
    It generates a new campaign and uses the default campaign switch(in the .cfg)so that it temprorarily overwrites the default campaign for whatever mode your running (Americas, Crusades, etc). You'd have to move the campaign manually over to any additional mods folder. It will only use vanilla units, but if the mod overwrites them I suppose it could work.

    Characters are randomly generated, you get a random number of spies, diplomats and armies currently 1 princess. All chracters (including the faction leader) have random names assigned.

  7. #7

    Default Re: Total Campaign Generator 1.0

    The regions are divided up equally between factions, no rebel provinces at the moment.

  8. #8

    Default Re: Total Campaign Generator 1.0

    Hardest part was to divide the terrain up into regions and have random settlement locations. It was quite a coding challenge and took me 5 months.

  9. #9
    +Mr.Crow+'s Avatar VIVERE MILITARE EST
    Join Date
    Aug 2009
    Location
    Apulia, Kingdom of Sicily
    Posts
    1,359

    Default Re: Total Campaign Generator 1.0

    Hi mtwgamer0,

    your work is great!

    I'm a java programmer and i'm really interested in image elaborations and filters.

    I'm really interested to know something more about this:

    Quote Originally Posted by mtwgamer0 View Post
    Hardest part was to divide the terrain up into regions and have random settlement locations. It was quite a coding challenge and took me 5 months.
    Can i ask you to show how this part of your code works?

    Best Regards,
    +Mr.Crow+
    BELLUM CRUCIS 7.0 Co-Director
    PERSONAL PROJECTS: CSUR || WARWAGON

    Quote Originally Posted by Cyprian2 View Post
    As far as I'm concerned, you've done something that CA should have thought of a long time ago. You should be on their pay-roll!

  10. #10

    Default Re: Total Campaign Generator 1.0

    Quote Originally Posted by +Mr.Crow+ View Post
    Hi mtwgamer0,

    your work is great!

    I'm a java programmer and i'm really interested in image elaborations and filters.

    I'm really interested to know something more about this:

    Can i ask you to show how this part of your code works?

    Best Regards,
    +Mr.Crow+
    Its a very long set of functions I wrote in c++.

    Generally:

    Terrain is generated using libnoise (an open source c++ library), then an island is generated (if coastal map). Regions are chosen on a grid like form. I used a voronoii diagram to get iregular country or province-like regions. Terrain is elevated around these region points Then I offset the settlements inside each voronoii region.


    Here is the main function:

    Code:
    //----------------------------------------------------------
    // Complicated function generating the terrain and the regions
    //----------------------------------------------------------
    void VoronoiDiagram::VoronoiTiles(Bitmap *bmpHeights, Bitmap *bmp0, int number_of_regions, region *regions)
    {
        for(int x = 0; x < bmpHeights->height; x++)
        {
            for(int y = 0; y < bmpHeights->width; y++)
            {
                if(bmpHeights->map[x][y].b == 255)
                {
                    rm.belowSea[rm.belowSeaCount].x = x;
                    rm.belowSea[rm.belowSeaCount].y = y;
                    rm.belowSeaCount++;
                }
                if(bmpHeights->map[x][y].b != 255)
                {
                    rm.aboveSeaLevel[rm.aboveCount].y = y/2;
                    rm.aboveSeaLevel[rm.aboveCount].x = x/2;
                    rm.aboveCount++;
                }
            }
        }
    
        int rows = settings.rows;
        int columns = settings.columns;
        int columnSpacing = bmp0->width / (columns + 1);// Is width
        int rowSpacing = bmp0->height / (rows + 1); //Is height
    
        int number_of_points = 200;//Number of fragments
        voronoi_point points[4096];
        voronoi_point regionPoints[4096];
    
        int height = bmp0->height;
        int width = bmp0->width;
    
        //Bitmap bmpV(width, height);
        //clearToRGB(0,0,0);
    
        //Generate voronoii points
        for(unsigned __int8 n = 0; n < number_of_points; n++)
        {
            points[n].x = (0.10 * height) + rand()%int(0.80 * height);
            points[n].y = (0.10 * width) + rand()%int(0.80 * width);
            points[n].col.r = rand()%255;
            points[n].col.g = rand()%255;
            points[n].col.b = rand()%255;
        }
    
        //Select region points from rows and columns if inland
        if(settings.mapType == "inland")
        {
            cout << "Map type: inland.";
            //
            //***Generate these points in a snaking pattern***
            //Region points from number of rows and columns
            //
            int curX = 0;
            int curY = 0;
            int n = 0;
            int total = rows * columns;
    
            for(int a = 0; a < rows; a++)
            {
                curY += rowSpacing;
                curX = 0;
    
                for(int b = 0; b < columns; b++)
                {
                    curX += columnSpacing;
                
                    regionPoints[n].y = curX;
                    regionPoints[n].x = curY;
                    regionPoints[n].col.r = regions[n].colour.r;
                    regionPoints[n].col.g = regions[n].colour.g;
                    regionPoints[n].col.b = regions[n].colour.b;
                    n++;
                }
            
                a++;
                curY += rowSpacing;
                for(int b = columns-1; b >= 0; b--)
                {
                    regionPoints[n].y = curX;
                    regionPoints[n].x = curY;
                    regionPoints[n].col.r = regions[n].colour.r;
                    regionPoints[n].col.g = regions[n].colour.g;
                    regionPoints[n].col.b = regions[n].colour.b;
                    n++;
                    curX -= columnSpacing;
                }
                //cout << "region points = " << n << endl;
            }
        }
    
        //Put region color around the point
        //
        //--------------------------
        //    1) Get grid positions
        //--------------------------
        //
        if(settings.mapType == "coastal2")
        {
            //
            //***Generate these points in a snaking pattern***
            //Region points from number of rows and columns
            //
            int curX = 0;
            int curY = 0;
            int n = 0;
            int total = rows * columns;
    
            for(__int8 a = 0; a < rows; a++)
            {
                curY += rowSpacing;
                curX = 0;
    
                for(__int8 b = 0; b < columns; b++)
                {
                    curX += columnSpacing;
                
                    regionPoints[n].y = curX;
                    regionPoints[n].x = curY;
                    regionPoints[n].col.r = regions[n].colour.r;
                    regionPoints[n].col.g = regions[n].colour.g;
                    regionPoints[n].col.b = regions[n].colour.b;
                    n++;
                }
            
                a++;
                curY += rowSpacing;
                for(__int8 b = columns-1; b >= 0; b--)
                {
                    regionPoints[n].y = curX;
                    regionPoints[n].x = curY;
                    regionPoints[n].col.r = regions[n].colour.r;
                    regionPoints[n].col.g = regions[n].colour.g;
                    regionPoints[n].col.b = regions[n].colour.b;
                    n++;
                    curX -= columnSpacing;
                }
                //cout << "region points = " << total << endl;
            }
        }
    
        //Use original algorithm
        /*
        //Randomize the region points
        for(__int8 n2 = 0; n2 < number_of_regions; n2++)
        {
            int rndX = -3 + rand()%6;
            int rndY = -3 + rand()%6;
            
            if(regionPoints[n2].x + rndX > 0 && regionPoints[n2].x + rndX < width){regionPoints[n2].x = regionPoints[n2].x + rndX;};
            if(regionPoints[n2].y + rndY > 0 && regionPoints[n2].y + rndY < height){regionPoints[n2].y = regionPoints[n2].y + rndY;};
        }
        */
    
        //Draw settlement positions
        for(__int8 n2 = 0; n2 < number_of_regions; n2++)
        {
            //bmpV.map[regionPoints[n2].x][regionPoints[n2].y].r = 255;
            //bmpV.map[regionPoints[n2].x][regionPoints[n2].y].g = 255;
            //bmpV.map[regionPoints[n2].x][regionPoints[n2].y].b = 255;
            //Update the region position for each region (the row & column grid location)
            regions[n2].regionPos.x = regionPoints[n2].x;
            regions[n2].regionPos.y = regionPoints[n2].y;
    
            regions[n2].settlementPos.x = regionPoints[n2].y;
            regions[n2].settlementPos.y = regionPoints[n2].x;
        }
    
        //TGA tga2;
        //tga2.write_tga( "C:\\Users\\User\\Desktop\\voronoii_2.tga" , &bmpV );
        //system("PAUSE");
        //return  &bmpV;
        
        //Slightly randomize region point position
        /*
        if(settings->randomizeSettlementPositions)
        {
            for(int n = 0; n < number_of_regions; n++)
            {
                regionPoints[n].x = (0.10 * height) + rand()%int(0.80 * height);
                regionPoints[n].y = (0.10 * width) + rand()%int(0.80 * width);
                regionPoints[n].col.r = regions[n].colour.r;
                regionPoints[n].col.g = regions[n].colour.g;
                regionPoints[n].col.b = regions[n].colour.b;
            }
        }
        */
        
        /*
        //Output voronoii bitmap
        for(int x = 0; x < height; x++)
        {
            for(int y = 0; y < width; y++)
            {    
                //Find closest point to current pixel...
                int closestIndex = 0;
                float closestDistance = height * width + 100;
                for(int n = 0; n < number_of_points; n++)
                {
                    float curDist = distance(x, y, 0, points[n].x, points[n].y, 0);
                    if(curDist < closestDistance)
                    {
                        closestIndex = n;
                        closestDistance = curDist;
                    }
                }    
                bmpV.map[x][y].r = points[closestIndex].col.r; bmpV.map[x][y].g = points[closestIndex].col.g; bmpV.map[x][y].b = points[closestIndex].col.b;
            }
        }
        */
    
        /*
        //Draw settlement positions (Only if fixed positions selected)
        if(!settings.randomizeSettlementPositions)
        {
            for(int n = 0; n < number_of_regions; n++)
            {
                bmpV.map[regionPoints[n].x][regionPoints[n].y].r = 0;
                bmpV.map[regionPoints[n].x][regionPoints[n].y].g = 0;
                bmpV.map[regionPoints[n].x][regionPoints[n].y].b = 0;
            }
        }
        TGA tga;
        tga.write_tga( "C:\\Users\\User\\Desktop\\voronoii.tga" , &bmpV );
        */
    
        //--------------------------
        //    2) Get coloured regions
        //--------------------------
        //Change voronoii point colors to correspond to nearest region point
        for(unsigned __int8 i = 0; i < number_of_points; i++)
        {
            int x = points[i].x;
            int y = points[i].y;
            //Find closest point to current pixel
            int closestIndex = 0;
            float closestDistance = height * width + 100;
            for(unsigned __int8 n = 0; n < number_of_regions; n++)
            {
                float curDist = distance(x, y, 0, regionPoints[n].x, regionPoints[n].y, 0);
                if(curDist < closestDistance)
                {
                    closestIndex = n;
                    closestDistance = curDist;
                }
            }
            points[i].col.r = regionPoints[closestIndex].col.r;
            points[i].col.g = regionPoints[closestIndex].col.g;
            points[i].col.b = regionPoints[closestIndex].col.b;
        }
    
    
    //------------------------------------------------------
    
    
        //-----------------------------------------
        //3) Draw islands at positions on terrain
        //-----------------------------------------
    
        //Joins all provinces in grid like form
        //Settlement is the region point
        for(unsigned __int8 n = 0; n < number_of_regions; n++)
        {
            //bmp0->map[regionPoints[n].x][regionPoints[n].y].r = 0;
            //bmp0->map[regionPoints[n].x][regionPoints[n].y].g = 0;
            //bmp0->map[regionPoints[n].x][regionPoints[n].y].b = 0;
    
            /*
            //Surround region point with region color
            rgb curCol;
            curCol.r = 255;//regionPoints[n].col.r;
            curCol.g = 255;//regionPoints[n].col.g;
            curCol.b = 255;//regionPoints[n].col.b;
    
            //Surround region point with region color
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y].r = curCol.r;
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y].g = curCol.g;
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y].b = curCol.b;
            
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y - 1].r = curCol.r;
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y - 1].g = curCol.g;
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y - 1].b = curCol.b;
    
            bmp0->map[regionPoints[n].x][regionPoints[n].y - 1].r = curCol.r;
            bmp0->map[regionPoints[n].x][regionPoints[n].y - 1].g = curCol.g;
            bmp0->map[regionPoints[n].x][regionPoints[n].y - 1].b = curCol.b;
    
            bmp0->map[regionPoints[n].x][regionPoints[n].y + 1].r = curCol.r;
            bmp0->map[regionPoints[n].x][regionPoints[n].y + 1].g = curCol.g;
            bmp0->map[regionPoints[n].x][regionPoints[n].y + 1].b = curCol.b;
    
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y + 1].r = curCol.r;
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y + 1].g = curCol.g;
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y + 1].b = curCol.b;
    
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y].r = curCol.r;
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y].g = curCol.g;
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y].b = curCol.b;
    
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y - 1].r = curCol.r;
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y - 1].g = curCol.g;
            bmp0->map[regionPoints[n].x + 1][regionPoints[n].y - 1].b = curCol.b;
    
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y + 1].r = curCol.r;
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y + 1].g = curCol.g;
            bmp0->map[regionPoints[n].x - 1][regionPoints[n].y + 1].b = curCol.b;
            */
    
    
            regions[n].actualSettlementPos.x = regionPoints[n].x;
            regions[n].actualSettlementPos.y = regionPoints[n].y;
    
            pos2d pos;
            pos.x = (regions[n].actualSettlementPos.x*2) + 1;
            pos.y = (regions[n].actualSettlementPos.y*2) + 1;
    
            if(settings.mapType != "inland")//Inland
            {
                rm.GenerateIslandAtPosition(pos);
            }
        }
        
        //Smooth the terrain map before assigning region colors
        rm.smooth();
    
        //-----------------------------------------
        // 4) Colorize the bitmap pixels & make sure they are above sea level
        //-----------------------------------------
        for(int x = 0; x < height; x++)
        {
            for(int y = 0; y < width; y++)
            {
                //Find closest point to current pixel...
                int closestIndex = 0;
                float closestDistance = height * width + 100;
                for(int n = 0; n < number_of_points; n++)
                {
                    float curDist = distance(x, y, 0, points[n].x, points[n].y, 0);
                    if(curDist < closestDistance)
                    {
                        closestIndex = n;
                        closestDistance = curDist;
                    }
                }
    
                bool found = false;
    
                for(int a = 0; a < number_of_regions-1; a++)
                {
                    //rm.makePassable((regions[a].actualSettlementPos.x), (regions[a].actualSettlementPos.y), (regions[a+1].actualSettlementPos.x), (regions[a+1].actualSettlementPos.y));
                }
    
                found = false;
                if (rm.terrain[(x*2)+1][(y*2)+1] > settings.seaHeight + 5){found = true;}//Above sea level
                if (rm.mustBePassableSmall[x][y] == true){found = true;}//Above sea level
                
                if(found == true)
                {
                    bmp0->map[x][y].r = points[closestIndex].col.r; bmp0->map[x][y].g = points[closestIndex].col.g; bmp0->map[x][y].b = points[closestIndex].col.b;
                }
                else
                {
                    bmp0->map[x][y].r = 41; bmp0->map[x][y].g = 140; bmp0->map[x][y].b = 233;//Sea
                }
            }
        }
    
    
    
    
        
        
    
        //------------------------------------------------------------------------
        // !!!!!!!!!!!    This fails to allocate settlements if land mass is small    !!!!!!!!!!!
        //------------------------------------------------------------------------
        //5) Put settlement at centre of mass
    
        //if(settings.mapType != "inland")
        pos2d curRegion[4096];
        int curRegionPxCount;
        if(1==1)
        {
            //Put the settlement in the centre of mass of each region
            //Regions must be of minimum size
            //Generate the region points array
            for(int h = 0; h < number_of_regions; h++)
            {
                int curR = regions[h].colour.r;
                int curG = regions[h].colour.g;
                int curB = regions[h].colour.b;
                
                curRegionPxCount = 0;
                for(int g = 0; g < width; g++)
                {
                    for(int w = 0; w < height; w++)
                    {
                        if(bmp0->map[w][g].r == curR && bmp0->map[w][g].g  == curG && bmp0->map[w][g].b  == curB)
                        {
                            curRegion[curRegionPxCount].x = g;
                            curRegion[curRegionPxCount].y = w;
                            curRegionPxCount++;
                        }
                    }
                }
    
                //Generate edge list
                rm.edgePointCount = 0;
    
    
    
                //-------------------
                //For every pixel in the current region
                //-------------------
                for(int i = 0; i < curRegionPxCount; i++)
                {
                    //cout << "crpc: " << curRegionPxCount << endl;
                    pos2d curPoint = curRegion[i];
                    int curX = curPoint.x;
                    int curY = curPoint.y;
                    //Greatest and least values for current pixel
                    int greatestY = -1;
                    int greatestX = -1;
                    int leastX = 1000;
                    int leastY = 1000;
                    int curEdge = 0;
                        //IDENTIFY HIGHEST AND LOWEST FOR CURRENT PIXEL
                        for( int k = 0 ; k < curRegionPxCount ; k++ )
                        {
                            pos2d scanPoint2 = curRegion[k];
                            if(scanPoint2.y == curY && scanPoint2.x >= greatestX)
                            {
                                greatestX = scanPoint2.x;
                            } 
    
                            if(scanPoint2.y == curY && scanPoint2.x <= leastX)
                            {
                                leastX = scanPoint2.x;
                            } 
    
                            if(scanPoint2.x == curX && scanPoint2.y <= leastY)
                            {
                                leastY = scanPoint2.y;
                            }
    
                            if(scanPoint2.x == curX && scanPoint2.y >= greatestY)
                            {
                                greatestY = scanPoint2.y;
                            }
                        }
                        if(curX >= greatestX)
                        {
                            rm.edgePoints[rm.edgePointCount].x = curPoint.x;
                            rm.edgePoints[rm.edgePointCount].y = curY;
                            rm.edgePointCount++;
                        } 
                        if(curX <= leastX)
                        {
                            rm.edgePoints[rm.edgePointCount].x = curPoint.x;
                            rm.edgePoints[rm.edgePointCount].y = curY;
                            rm.edgePointCount++;
                        } 
                        if(curY <= leastY)
                        {
                            rm.edgePoints[rm.edgePointCount].x = curPoint.x;
                            rm.edgePoints[rm.edgePointCount].y = curY;
                            rm.edgePointCount++;
                        } 
                        if(curY >= greatestY)
                        {
                            rm.edgePoints[rm.edgePointCount].x = curPoint.x;
                            rm.edgePoints[rm.edgePointCount].y = curY;
                            rm.edgePointCount++;
                        } 
                    }
                    //----------------------------------
    
                    /*
                        //Draw edges
                        for( int k = 0 ; k < rm.edgePointCount ; k++ )
                        {
                            //For border rivers...
                            rm.edgePositions[rm.edgePositionCount].x = rm.edgePoints[k].x;
                            rm.edgePositions[rm.edgePositionCount].y = rm.edgePoints[k].y; 
                            rm.edgePositionCount++;    
                            //cout << rm.edgePositionCount << endl;
                            bmp0->map[rm.edgePoints[k].y][rm.edgePoints[k].x].r = 255;
                            bmp0->map[rm.edgePoints[k].y][rm.edgePoints[k].x].g = 255;
                            bmp0->map[rm.edgePoints[k].y][rm.edgePoints[k].x].b = 255;
                        }
                    */
    
    
                //-----------------------------------------
                //Region loop end (int h)
                //MessageBoxA(NULL, "reg",  "reg", MB_OK | MB_ICONINFORMATION);
    
                    int ic = 0;
                    float distances[8192];
                    int closestIndex;
                    int closestDist = 1000;
    
                    //Put the settlement at point furthest away from all edges.
                    for( int j = 0 ; j < curRegionPxCount ; j++ )
                    {
                        pos2d scanPoint = curRegion[j];
                        closestDist = 10000;
    
                        //Find pixel's closest edge
                        for(int u = 0; u < rm.edgePointCount; u++)
                        {
                            pos2d edgePoint = rm.edgePoints[u];
                            float dist = distance((float)scanPoint.x, (float)scanPoint.y, 0, (float)edgePoint.x, (float)edgePoint.y, 0);
                            if(dist <= closestDist)
                            {
                                closestIndex = j;
                                closestDist = dist;
                            } 
                        }
                        distances[ic] = closestDist;  //  Distance for this point  //
                        ic++;
                    }    
                    int maxDist = 0;
                    int maxIndex = 0;
    
                    //Maximum distance from edge
                    
                    for(int a = 0; a < ic; a++)
                    {
                        //cout << distances[a] << endl;
                        if(distances[a] > maxDist)
                        {
                            //cout << distances[a] << endl;
                            maxIndex = a;
                            maxDist = distances[a];
                        }    
                    }
                    
                    //
                    //stringstream f;
                    int inside[8192];//Inside index int
                    int insideCount = 0;
                    //Greater than 5 from edge
                    for(int a = 0; a < ic; a++)
                    {
                        //cout << distances[a] << endl;
                        if(distances[a] > 1)
                        {
                
                    //f << distances[a] << ", ";
                    //MessageBoxA(NULL, f.str().c_str(),  "Message", MB_OK | MB_ICONINFORMATION);
                            inside[insideCount] = a;
                            insideCount++;
                        }    
                    }
                    //MessageBoxA(NULL, f.str().c_str(),  "Message", MB_OK | MB_ICONINFORMATION);
    
                    //Furthest index:
                    int mx;// = curRegion[maxIndex].x;
                    int my;// = curRegion[maxIndex].y;
                    int indexI = 0;
                    if(insideCount > 0)
                    {
                        indexI = inside[rand()%insideCount];
                    }
    
                    mx = curRegion[indexI].y;
                    my = curRegion[indexI].x;
    
                    //cout << "m " << mx << " "<< my;
                    //system("PAUSE");
    
                    bmp0->map[ mx ] [ my ].r = 0;
                    bmp0->map[ mx ] [ my ].g = 0;
                    bmp0->map[ mx ] [ my ].b = 0;
    
                    //rm.makePassable((regions[h].actualSettlementPos.x), (regions[h].actualSettlementPos.y), (regions[h+1].actualSettlementPos.x), (regions[h+1].actualSettlementPos.y));
    
                    regions[h].actualSettlementPos.y = my;
                    regions[h].actualSettlementPos.x = mx;
    
                    rm.hill_1((mx * 2) + 1, (my * 2) + 1, 0, 10, 50);
    
                    //stringstream f;
                    //f << number_of_regions;
                    //MessageBoxA(NULL, f.str().c_str(),  "sp", MB_OK | MB_ICONINFORMATION);
                }
    
          }
    
    
        //Surround settlement point with region color
        for(unsigned __int8 n = 0; n < number_of_regions; n++)
        {
            rgb curCol;
            curCol.r = regionPoints[n].col.r;
            curCol.g = regionPoints[n].col.g;
            curCol.b = regionPoints[n].col.b;
    
            pos2d point;
            point = regions[n].actualSettlementPos;
    
            bmp0->map[point.x - 1][point.y].r = curCol.r;
            bmp0->map[point.x - 1][point.y].g = curCol.g;
            bmp0->map[point.x - 1][point.y].b = curCol.b;
            
            bmp0->map[point.x - 1][point.y - 1].r = curCol.r;
            bmp0->map[point.x - 1][point.y - 1].g = curCol.g;
            bmp0->map[point.x - 1][point.y - 1].b = curCol.b;
    
            bmp0->map[point.x][point.y - 1].r = curCol.r;
            bmp0->map[point.x][point.y - 1].g = curCol.g;
            bmp0->map[point.x][point.y - 1].b = curCol.b;
    
            bmp0->map[point.x][point.y + 1].r = curCol.r;
            bmp0->map[point.x][point.y + 1].g = curCol.g;
            bmp0->map[point.x][point.y + 1].b = curCol.b;
    
            bmp0->map[point.x + 1][point.y + 1].r = curCol.r;
            bmp0->map[point.x + 1][point.y + 1].g = curCol.g;
            bmp0->map[point.x + 1][point.y + 1].b = curCol.b;
    
            bmp0->map[point.x + 1][point.y].r = curCol.r;
            bmp0->map[point.x + 1][point.y].g = curCol.g;
            bmp0->map[point.x + 1][point.y].b = curCol.b;
    
            bmp0->map[point.x + 1][point.y - 1].r = curCol.r;
            bmp0->map[point.x + 1][point.y - 1].g = curCol.g;
            bmp0->map[point.x + 1][point.y - 1].b = curCol.b;
    
            bmp0->map[point.x - 1][point.y + 1].r = curCol.r;
            bmp0->map[point.x - 1][point.y + 1].g = curCol.g;
            bmp0->map[point.x - 1][point.y + 1].b = curCol.b;
        }

  11. #11
    +Mr.Crow+'s Avatar VIVERE MILITARE EST
    Join Date
    Aug 2009
    Location
    Apulia, Kingdom of Sicily
    Posts
    1,359

    Default Re: Total Campaign Generator 1.0

    Thx for your answer. I really appreciate it.

    I know voronoi and i've immediately supposed that you used it in your code.

    Which type of voronoi did you use? Manhattan or Minkovski?
    BELLUM CRUCIS 7.0 Co-Director
    PERSONAL PROJECTS: CSUR || WARWAGON

    Quote Originally Posted by Cyprian2 View Post
    As far as I'm concerned, you've done something that CA should have thought of a long time ago. You should be on their pay-roll!

  12. #12

    Default Re: Total Campaign Generator 1.0

    Method I used was to add multiple random points to a bitmap, assign each point a color. Then loop through every pixel in the bitmap and color it depending on which of those coloured points is nearest to the current pixel.

  13. #13
    +Mr.Crow+'s Avatar VIVERE MILITARE EST
    Join Date
    Aug 2009
    Location
    Apulia, Kingdom of Sicily
    Posts
    1,359

    Default Re: Total Campaign Generator 1.0

    Quote Originally Posted by mtwgamer0 View Post
    Method I used was to add multiple random points to a bitmap, assign each point a color. Then loop through every pixel in the bitmap and color it depending on which of those coloured points is nearest to the current pixel.
    This is the generic voronoi algorithm. My question is which type of voronoi did you use? In other words, I wish to know how you calculate pixel proximity.

    There are 3 most common used voronoi type: Euclidean, Manhattan and Minkowski.

    For example, let's take Medieval 2 map_height:

    Spoiler Alert, click show to read: 




    Using a java code made by me, i've create 199 random regions using all this 3 voronoi types.

    Euclidean:

    Spoiler Alert, click show to read: 




    Manhattan:

    Spoiler Alert, click show to read: 




    Minkowski:

    Spoiler Alert, click show to read: 




    As you can see, the last type (Minkowski) seems to be the better voronoi type to create Medieval 2 regions.

    All this 3 voronoi types work as you wrote. The only difference between them is the pixel proximity calculation. Calling the distance "d", this is how it's calculated:

    Euclidean: d = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));

    Manhattan: d = Math.abs(x1 - x2) + Math.abs(y1 - y2);

    Minkowski: d = Math.pow(Math.pow(Math.abs(x1 - x2), p) + Math.pow(Math.abs(y1 - y2), p), (1 / p));
    BELLUM CRUCIS 7.0 Co-Director
    PERSONAL PROJECTS: CSUR || WARWAGON

    Quote Originally Posted by Cyprian2 View Post
    As far as I'm concerned, you've done something that CA should have thought of a long time ago. You should be on their pay-roll!

  14. #14

    Default Re: Total Campaign Generator 1.0

    When programming I use the following function to calc distance:

    Code:
    //----------------------------------------------------------
    //
    //----------------------------------------------------------
    float distance(float x1, float y1, float z1, float x2, float y2, float z2)
    {
        return(sqrt (pow((float)(x2-x1),(float)2) + pow((float)(y2-y1), (float)2) + pow((float)(z2-z1), (float)2)));
    }

  15. #15
    +Mr.Crow+'s Avatar VIVERE MILITARE EST
    Join Date
    Aug 2009
    Location
    Apulia, Kingdom of Sicily
    Posts
    1,359

    Default Re: Total Campaign Generator 1.0

    If i'm not wrong, this is the Riemannian type, a 4th type of voronoi.

    I've just used it in my application and it seems to work even better then Minkowski type:

    Spoiler Alert, click show to read: 





    Good work mtwgamer0! And thx for your answers
    BELLUM CRUCIS 7.0 Co-Director
    PERSONAL PROJECTS: CSUR || WARWAGON

    Quote Originally Posted by Cyprian2 View Post
    As far as I'm concerned, you've done something that CA should have thought of a long time ago. You should be on their pay-roll!

  16. #16
    Hexdragon's Avatar Libertus
    Join Date
    Nov 2005
    Location
    South America / Peru / Lima City
    Posts
    81

    Default Re: Total Campaign Generator 1.0

    Great work
    +rep


    In order to allow people to find this tool more easily, I would suggest to move this thread to: Medieval II Mod Workshop - Tools, Tutorials, and Resources


    Also add to this index:
    http://www.twcenter.net/forums/showt...rces-amp-Tools






  17. #17

    Default Re: Total Campaign Generator 1.0

    The latest version is soon to be released.

    It currenty has the following features:

    -Optional forts
    -Merchants and map resources
    -Early period start (no units or development)



  18. #18

  19. #19

    Default Re: Total Campaign Generator 1.0

    oh... any chance for Rome Total war?
    this tool looks extreme awesome!

  20. #20

    Default Re: Total Campaign Generator 1.0

    Hi, does anybody have a copy of this tool?

    It seems that it's not available at sourceforge.net.

    I'd like to try it.

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •