Exemple #1
0
// FIXME: use block cache, break into manageable bits
int main (void)
{
    srand ( (unsigned int)time(NULL) );

    //Message of intent
    cout <<
         "DF Hole" << endl <<
         "This tool will instantly dig a chasm, pit, pipe, etc through hell, wherever your cursor is." << endl <<
         "This can not be undone!  End program now if you don't want hellish fun." << endl
         ;

    //User selection of settings should have it own routine, a structure for settings, I know
    //sloppy mess, but this is just a demo utility.

    //Pit Types.
    e_pitType pittype = selectPitType();

    //Here are all the settings.
    //Default values are set here.
    int pitdepth=0;
    int roof=-1;
    int holeradius=6;
    int wallthickness=1;
    int wallpillar=1;
    int holepillar=1;
    int exposehell = 0;
    int fillmagma=0;
    int fillwater=0;
    int stopatmagma=0;
    int exposemagma=0;
    int aquify=0;

    //The Tile Type to use for the walls lining the hole
    //263 is semi-molten rock, 331 is obsidian
    uint32_t whell=263, wmolten=263, wmagma=331, wcave=331;
    //The Tile Type to use for the hole's floor at bottom of the map
    //35 is chasm, 42 is eerie pit , 340 is obsidian floor, 344 is featstone floor, 264 is 'magma flow' floor
    uint32_t floor=35, cap=340;
    int floorvar=0;


    //Modify default settings based on pit type.
    switch ( pittype )
    {
        case pitTypeChasm:
            floor=35;
            break;
        case pitTypeEerie:
            floor=42;
            break;
        case pitTypeFloor:
            floor=344;
            floorvar=3;
            break;
        case pitTypeSolid:
            holeradius=0;
            wallthickness=7;
            wallpillar=4;
            break;
        case pitTypeOasis:
            stopatmagma=-1;
            fillwater=-1;
            holeradius=5;
            wallthickness=2;
            //aquify=-1;
            floor=340;
            floorvar=3;
            break;
        case pitTypeOPool:
            pitdepth=5;
            fillwater=-1;
            holeradius=5;
            wallthickness=2;
            //aquify=-1;
            floor=340;
            floorvar=3;
            break;
        case pitTypeMagma:
            stopatmagma=-1;
            exposemagma=-1;
            wallthickness=2;
            fillmagma=-1;
            floor=264;
            break;
        case pitTypeMPool:
            pitdepth=5;
            wallthickness=2;
            fillmagma=-1;
            floor=340;
            floorvar=3;
            break;
    }


    //Should tiles be revealed?
    int reveal=0;


    int accept = getyesno("Use default settings?",1);

    while ( !accept )
    {
        //Pit Depth
        pitdepth = getint( "Enter max depth (0 for bottom of map)", 0, INT_MAX, pitdepth );

        //Hole Size
        holeradius = getint( "Enter hole radius, 0 to 16", 0, 16, holeradius );

        //Wall thickness
        wallthickness = getint( "Enter wall thickness, 0 to 16", 0, 16, wallthickness );

        //Obsidian Pillars
        holepillar = getint( "Number of Obsidian Pillars in hole, 0 to 255", 0, 255, holepillar );
        wallpillar = getint( "Number of Obsidian Pillars in wall, 0 to 255", 0, 255, wallpillar );

        //Open Hell?
        exposehell=getyesno("Expose the pit to hell (no walls in hell)?",exposehell);

        //Stop when magma sea is hit?
        stopatmagma=getyesno("Stop at magma sea?",stopatmagma);
        exposemagma=getyesno("Expose magma sea (no walls in magma)?",exposemagma);

        //Fill?
        fillmagma=getyesno("Fill with magma?",fillmagma);
        if (fillmagma) aquify=fillwater=0;
        fillwater=getyesno("Fill with water?",fillwater);
        //aquify=getyesno("Aquifer?",aquify);


        ///////////////////////////////////////////////////////////////////////////////////////////////
        //Print settings.
        //If a settings struct existed, this could be in a routine
        printf("Using Settings:\n");
        printf("Pit Type......: %d = %s\n", pittype, pitTypeDesc[pittype]);
        printf("Depth.........: %d\n",  pitdepth);
        printf("Hole Radius...: %d\n",  holeradius);
        printf("Wall Thickness: %d\n",  wallthickness);
        printf("Pillars, Hole.: %d\n",  holepillar);
        printf("Pillars, Wall.: %d\n",  wallpillar);
        printf("Expose Hell...: %c\n", (exposehell?'Y':'N') );
        printf("Stop at Magma.: %c\n", (stopatmagma?'Y':'N') );
        printf("Expose Magma..: %c\n", (exposemagma?'Y':'N') );
        printf("Magma Fill....: %c\n", (fillmagma?'Y':'N') );
        printf("Water Fill....: %c\n", (fillwater?'Y':'N') );
        printf("Aquifer.......: %c\n", (aquify?'Y':'N') );

        accept = getyesno("Accept these settings?",1);
    }


    int64_t n;
    uint32_t x_max,y_max,z_max;


    //Pattern to dig
    unsigned char pattern[16][16];


    for (int regen=1;regen; )
    {
        regen=0;

        memset(pattern,0,sizeof(pattern));

        //Calculate a randomized circle.
        //These values found through experimentation.
        int x=0, y=0, n=0;

        //Two concentric irregular circles
        //Outer circle, solid.
        if ( wallthickness )
        {
            drawcircle(holeradius+wallthickness, pattern, 2);
        }
        //Inner circle, hole.
        if ( holeradius )
        {
            drawcircle(holeradius, pattern, 1);
        }


        //Post-process to be certain the wall totally encloses hole.
        if (wallthickness)
        {
            for (y=0;y<16;++y)
            {
                for (x=0;x<16;++x)
                {
                    if ( 1==pattern[x][y] )
                    {
                        //No hole at edges.
                        if ( x<1 || x>14 || y<1 || y>14 )
                        {
                            pattern[x][y]=2;
                        }
                    }
                    else if ( 0==pattern[x][y] )
                    {
                        //check neighbors
                        checkneighbors( pattern , x,y, 1, 2);
                    }
                }
            }
        }

        //Makes sure that somewhere random gets a vertical pillar of rock which is safe
        //to dig stairs down, to permit access to anywhere within the pit from the top.
        for (n=holepillar; n ; --n)
        {
            settileat( pattern , 1 , 3 , rand()&255 );
        }
        for (n=wallpillar; n ; --n)
        {
            settileat( pattern , 2 , 3 , rand()&255 );
        }

        //Note:
        //At this point, the pattern holds:
        //0 for all tiles which will be ignored.
        //1 for all tiles set to empty pit space.
        //2 for all normal walls.
        //3 for the straight obsidian top-to-bottom wall.
        //4 is randomized between wall or floor (!not implemented!)

        printf("\nPattern:\n");
        const char patternkey[] = ".cW!?567890123";

        //Print the pattern
        for (y=0;y<16;++y)
        {
            for (x=0;x<16;++x)
            {
                cout << patternkey[ pattern[x][y] ];
            }
            cout << endl;
        }
        cout << endl;

        regen = !getyesno("Acceptable Pattern?",1);
    }

    //Post-process settings to fix problems here
    if (pitdepth<1)
    {
        pitdepth=INT_MAX;
    }


    ///////////////////////////////////////////////////////////////////////////////////////////////


    cerr << "Loading memory map..." << endl;

    //Connect to DF!
    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF = DFMgr.getSingleContext();



    //Init
    cerr << "Attaching to DF..." << endl;
    try
    {
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    // init the map
    DFHack::Maps *Mapz = DF->getMaps();
    if (!Mapz->Start())
    {
        cerr << "Can't init map.  Exiting." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    Mapz->getSize(x_max,y_max,z_max);


    //Get cursor
    int32_t cursorX, cursorY, cursorZ;
    DFHack::Gui *Gui = DF->getGui();
    Gui->getCursorCoords(cursorX,cursorY,cursorZ);
    if (-30000==cursorX)
    {
        cout << "No cursor position found.  Exiting." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    //Block coordinates
    int32_t bx=cursorX/16, by=cursorY/16, bz=cursorZ;
    //Tile coordinates within block
    int32_t tx=cursorX%16, ty=cursorY%16, tz=cursorZ;

    /*
    //Access the DF interface to pause the game.
    //Copied from the reveal tool.
    DFHack::Gui *Gui =DF->getGui();
    cout << "Pausing..." << endl;
    Gui->SetPauseState(true);
    DF->Resume();
    waitmsec(1000);
    DF->Suspend();
    */

    //Verify that every z-level at this location exists.
    for (int32_t Z = 0; Z<= bz ;Z++)
    {
        if ( ! Mapz->isValidBlock(bx,by,Z) )
        {
            cout << "This block does't exist!  Exiting." << endl;
            #ifndef LINUX_BUILD
                cin.ignore();
            #endif
            return 1;
        }
    }

    //Get all the map features.
    vector<DFHack::t_feature> global_features;
    if (!Mapz->ReadGlobalFeatures(global_features))
    {
        cout << "Couldn't load global features! Probably a version problem." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> > local_features;
    if (!Mapz->ReadLocalFeatures(local_features))
    {
        cout << "Couldn't load local features! Probably a version problem." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    //Get info on current tile, to determine how to generate the pit
    mapblock40d topblock;
    Mapz->ReadBlock40d( bx, by, bz , &topblock );
    //Related block info
    DFCoord pc(bx,by);
    mapblock40d block;
    const TileRow * tp;
    t_designation * d;

    //////////////////////////////////////
    //From top to bottom, dig this thing.
    //////////////////////////////////////

    //Top level, cap.
    //Might make this an option in the future
    //For now, no wall means no cap.
    if (wallthickness)
    {
        Mapz->ReadBlock40d( bx, by, bz , &block );
        for (uint32_t x=0;x<16;++x)
        {
            for (uint32_t y=0;y<16;++y)
            {
                if ( (pattern[x][y]>1) || (roof && pattern[x][y]) )
                {
                    tp = getTileRow(block.tiletypes[x][y]);
                    d = &block.designation[x][y];
                    //Only modify this level if it's 'empty'
                    if ( EMPTY != tp->shape && RAMP_TOP != tp->shape && STAIR_DOWN != tp->shape && DFHack::TILE_STREAM_TOP != tp->special)
                    {
                        continue;
                    }

                    //Need a floor for empty space.
                    if (reveal)
                    {
                        d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
                    }
                    //Always clear the dig designation.
                    d->bits.dig = designation_no;
                    //unlock fluids, so they fall down the pit.
                    d->bits.flow_forbid = d->bits.liquid_static=0;
                    block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;
                    //Remove aquifer, to prevent bugginess
                    d->bits.water_table=0;
                    //Set the tile.
                    block.tiletypes[x][y] = cap + rand()%4;
                }
            }
        }
        //Write the block.
        Mapz->WriteBlockFlags(bx,by,bz, block.blockflags );
        Mapz->WriteDesignations(bx,by,bz, &block.designation );
        Mapz->WriteTileTypes(bx,by,bz, &block.tiletypes );
        Mapz->WriteDirtyBit(bx,by,bz,1);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    //All levels in between.
    int done=0;
    uint32_t t,v;
    int32_t z = bz-1;
    int32_t bottom = max(0,bz-pitdepth-1);
    assert( bottom>=0 && bottom<=bz );
    for ( ; !done && z>=bottom ; --z)
    {
        int watercount=0;
        int magmacount=0;
        int moltencount=0;
        int rockcount=0;
        int veincount=0;
        int emptycount=0;
        int hellcount=0;
        int templecount=0;
        int adamcount=0;
        int featcount=0;
        int tpat;

        cout << z << endl;
        assert( Mapz->isValidBlock(bx,by,z) );
        if (!Mapz->ReadBlock40d( bx, by, z , &block ))
        {
            cout << "Bad block! " << bx << "," << by << "," << z << endl;
        }

        //Pre-process this z-level, to get some tile statistics.
        for (int32_t x=0;x<16;++x)
        {
            for (int32_t y=0;y<16;++y)
            {
                t=0;
                tp = getTileRow(block.tiletypes[x][y]);
                d = &block.designation[x][y];
                tpat=pattern[x][y];

                //Tile type material categories
                switch ( tp->material )
                {
                    case AIR:
                        ++emptycount;
                        break;
                    case MAGMA:
                        ++moltencount;
                        break;
                    case VEIN:
                        ++veincount;
                        break;
                    case FEATSTONE:
                    case HFS:
                    case OBSIDIAN:
                        //basicly, ignored.
                        break;
                    default:
                        if ( EMPTY == tp->shape || RAMP_TOP == tp->shape || STAIR_DOWN == tp->shape )
                        {
                            ++emptycount;
                        }
                        else
                        {
                            ++rockcount;
                        }
                        break;
                }

                //Magma and water
                if ( d->bits.flow_size )
                {
                    if (d->bits.liquid_type)
                    {
                        ++magmacount;
                    }
                    else
                    {
                        ++watercount;
                    }
                }


                //Check for Features
                if ( block.local_feature > -1 || block.global_feature > -1 )
                {
                    //Count tiles which actually are in the feature.
                    //It is possible for a block to have a feature, but no tiles to be feature.
                    if ( d->bits.feature_global || d->bits.feature_local )
                    {
                        //All features
                        ++featcount;

                        if ( d->bits.feature_global && d->bits.feature_local )
                        {
                            cout << "warn:tile is global and local at same time!" << endl;
                        }

                        n=0;
                        if ( block.global_feature > -1 && d->bits.feature_global )
                        {
                            n=global_features[block.global_feature].type;
                            switch ( n )
                            {
                                case feature_Other:
                                    //no count
                                    break;
                                case feature_Adamantine_Tube:
                                    ++adamcount;
                                    break;
                                case feature_Underworld:
                                    ++hellcount;
                                    break;
                                case feature_Hell_Temple:
                                    ++templecount;
                                    break;
                                default:
                                    //something here. for debugging, it may be interesting to know.
                                    if (n) cout << '(' << n << ')';
                            }
                        }

                        n=0;
                        if ( block.local_feature > -1 && d->bits.feature_local )
                        {
                            n=local_features[pc][block.local_feature]->type;
                            switch ( n )
                            {
                                case feature_Other:
                                    //no count
                                    break;
                                case feature_Adamantine_Tube:
                                    ++adamcount;
                                    break;
                                case feature_Underworld:
                                    ++hellcount;
                                    break;
                                case feature_Hell_Temple:
                                    ++templecount;
                                    break;
                                default:
                                    //something here. for debugging, it may be interesting to know.
                                    if (n) cout << '[' << n << ']';
                            }
                        }
                    }
                }
            }
        }


        //If stopping at magma, and no no non-feature stone in this layer, and magma found, then we're either at
        //or below the magma sea / molten rock.
        if ( stopatmagma && (moltencount || magmacount) && (!exposemagma || !rockcount) )
        {
            //If not exposing magma, quit at the first sign of magma.
            //If exposing magma, quite once magma is exposed.
            done=-1;
        }


        /////////////////////////////////////////////////////////////////////////////////////////////////
        //Some checks, based on settings and stats collected
        //First check, are we at illegal depth?
        if ( !done && hellcount && stopatmagma )
        {
            //Panic!
            done=-1;
            tpat=0;
            cout << "error: illegal breach of hell!" << endl;
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////
        //Actually process the current z-level.
        //These loops do the work.
        for (int32_t x=0;!done && x<16;++x)
        {
            for (int32_t y=0;!done && y<16;++y)
            {
                t=0;
                tp = getTileRow(block.tiletypes[x][y]);
                d = &block.designation[x][y];
                tpat=pattern[x][y];

                //Up front, remove aquifer, to prevent bugginess
                //It may be added back if aquify is set.
                d->bits.water_table=0;

                //Change behaviour based on settings and stats from this z-level

                //In hell?
                if ( tpat && tpat!=3 && isfeature(global_features, local_features,block,pc,x,y,feature_Underworld ) )
                {
                    if ( exposehell )
                    {
                        tpat=0;
                    }
                }

                //Expose magma?
                if ( tpat && tpat!=3 && exposemagma )
                {
                    //Leave certain tiles unchanged.
                    switch ( tp->material )
                    {
                        case HFS:
                        case FEATSTONE:
                        case MAGMA:
                            tpat=0;
                        default:
                            break;
                    }
                    //Adamantine may be left unchanged...
                    if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) )
                    {
                        tpat=0;
                    }
                    //Leave magma sea unchanged.
                    if ( d->bits.flow_size && d->bits.liquid_type)
                    {
                        tpat=0;
                    }
                }


                //For all situations...
                //Special modification for walls, always for adamantine.
                if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) )
                {
                    if ( 2==pattern[x][y] || 3==pattern[x][y] )
                    {
                        tpat=2;
                    }
                }


                //Border or space?
                switch (tpat)
                {
                    case 0:
                        continue;
                        break;
                    case 1:
                        //Empty Space
                        t=32;
                        //d->bits.light = topblock.designation[x][y].bits.light;
                        //d->bits.skyview = topblock.designation[x][y].bits.skyview;
                        //d->bits.subterranean = topblock.designation[x][y].bits.subterranean;

                        //Erase special markers?
                        //d->bits.feature_global = d->bits.feature_local = 0;

                        //Water? Magma?
                        if (fillmagma || fillwater)
                        {
                            d->bits.flow_size=7;
                            d->bits.water_stagnant = false;
                            d->bits.water_salt = false;
                            if (fillmagma)
                            {
                                d->bits.liquid_type=liquid_magma;
                            }
                            else
                            {
                                d->bits.liquid_type=liquid_water;
                            }
                        }
                        else
                        {
                            //Otherwise, remove all liquids.
                            d->bits.flow_size=0;
                            d->bits.water_stagnant = false;
                            d->bits.water_salt = false;
                            d->bits.liquid_type = liquid_water;
                        }

                        break;
                    case 2:
                        //Wall.
                        //First guess based on current material
                        switch ( tp->material )
                        {
                            case OBSIDIAN:
                                t=wmagma;
                                break;
                            case MAGMA:
                                t=wmolten;
                                break;
                            case HFS:
                                //t=whell;
                                break;
                            case VEIN:
                                t=440; //Solid vein block
                                break;
                            case FEATSTONE:
                                t=335; //Solid feature stone block
                                break;
                            default:
                                t=wcave;
                        }
                        //Adamantine (a local feature) trumps veins.
                        {
                            //Local Feature?
                            if ( block.local_feature > -1  )
                            {
                                switch ( n=local_features[pc][block.local_feature]->type )
                                {
                                    case feature_Underworld:
                                    case feature_Hell_Temple:
                                        //Only adopt these if there is no global feature present
                                        if ( block.global_feature >-1 )
                                        {
                                            break;
                                        }
                                    case feature_Adamantine_Tube:
                                        //Always for adamantine, sometimes for others
                                        //Whatever the feature is made of. "featstone wall"
                                        d->bits.feature_global = 0;
                                        d->bits.feature_local = 1;
                                        t=335;
                                        break;
                                }
                            }
                            //Global Feature?
                            else if (block.global_feature > -1 && !d->bits.feature_local )
                            {
                                switch ( n=global_features[block.global_feature].type )
                                {
                                    case feature_Adamantine_Tube:
                                    case feature_Underworld:
                                    case feature_Hell_Temple:
                                        //Whatever the feature is made of. "featstone wall"
                                        d->bits.feature_global = 1;
                                        t=335;
                                        break;
                                }
                            }
                        }

                        //Erase any liquids, as they cause problems.
                        d->bits.flow_size=0;
                        d->bits.water_stagnant = false;
                        d->bits.water_salt = false;
                        d->bits.liquid_type=liquid_water;

                        //Placing an aquifer?
                        //(bugged, these aquifers don't generate water!)
                        if ( aquify )
                        {
                            //Only normal stone types can be aquified
                            if ( tp->material!=MAGMA && tp->material!=FEATSTONE && tp->material!=HFS  )
                            {
                                //Only place next to the hole.
                                //If no hole, place in middle.
                                if ( checkneighbors(pattern,x,y,1) || (7==x && 7==y) )
                                {
                                    d->bits.water_table = 1;
                                    //t=265; //soil wall
                                }
                            }
                        }
                        break;
                    case 3:
                        ////No obsidian walls on bottom of map!
                        //if(z<1 && (d->bits.feature_global || d->bits.feature_local) ) {
                        //  t=335;
                        //}

                        //Special wall, always sets to obsidian, to give a stairway
                        t=331;

                        //Erase special markers
                        d->bits.feature_global = d->bits.feature_local = 0;

                        //Erase any liquids, as they cause problems.
                        d->bits.flow_size=0;
                        d->bits.water_stagnant = false;
                        d->bits.water_salt = false;
                        d->bits.liquid_type=liquid_water;
                        break;
                    default:
                        cout << ".error,bad pattern.";
                }

                //For all tiles.
                if (reveal)
                {
                    d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
                }
                //Always clear the dig designation.
                d->bits.dig=designation_no;
                //Make it underground, because it is capped
                d->bits.subterranean=1;
                d->bits.light=0;
                d->bits.skyview=0;
                //unlock fluids, so they fall down the pit.
                d->bits.flow_forbid = d->bits.liquid_static=0;
                block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;
                //Set the tile.
                block.tiletypes[x][y] = t;

            }
        }

        //Write the block.
        Mapz->WriteBlockFlags(bx,by,z, block.blockflags );
        Mapz->WriteDesignations(bx,by,z, &block.designation );
        Mapz->WriteTileTypes(bx,by,z, &block.tiletypes );
        Mapz->WriteDirtyBit(bx,by,z,1);

    }

    //Re-process the last z-level handled above.
    z++;
    assert( z>=0 );


    ///////////////////////////////////////////////////////////////////////////////////////////////
    //The bottom level is special.
    if (-1)
    {
        if (!Mapz->ReadBlock40d( bx, by, z , &block ))
        {
            cout << "Bad block! " << bx << "," << by << "," << z << endl;
        }
        for (uint32_t x=0;x<16;++x)
        {
            for (uint32_t y=0;y<16;++y)
            {
                t=floor;
                v=floorvar;
                tp = getTileRow(block.tiletypes[x][y]);
                d = &block.designation[x][y];

                if ( exposehell )
                {
                    //Leave hell tiles unchanged when exposing hell.
                    if ( isfeature(global_features,local_features,block,pc,x,y,feature_Underworld) )
                    {
                        continue;
                    }
                }

                //Does expose magma need anything at this level?
                if ( exposemagma && stopatmagma )
                {
                    continue;
                }

                switch (pattern[x][y])
                {
                    case 0:
                        continue;
                        break;
                    case 1:
                        //Empty becomes floor.

                        //Base floor type on the z-level first, features, then tile type.
                        if (!z) {
                            //Bottom of map, use the floor specified, always.
                            break;
                        }

                        ////Only place floor where ground is already solid when exposing
                        //if( EMPTY == tp->c || RAMP_TOP == tp->c || STAIR_DOWN == tp->c ){
                        //  continue;
                        //}

                        if ( d->bits.feature_global || d->bits.feature_global ) {
                            //Feature Floor!
                            t=344;
                            break;
                        }

                        //Tile material check.
                        switch ( tp->material )
                        {
                            case OBSIDIAN:
                                t=340;
                                v=3;
                                break;
                            case MAGMA:
                                v=0;
                                t=264; //magma flow
                                break;
                            case HFS:
                                //should only happen at bottom of map
                                break;
                            case VEIN:
                                t=441;  //vein floor
                                v=3;
                                break;
                            case FEATSTONE:
                                t=344;
                                v=3;
                                break;
                        }

                        break;
                    case 2:
                    case 3:
                        //Walls already drawn.
                        //Ignore.
                        continue;
                        break;
                }

                //For all tiles.
                if (reveal) d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
                //Always clear the dig designation.
                d->bits.dig=designation_no;
                //unlock fluids
                d->bits.flow_forbid = d->bits.liquid_static=0;
                block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;

                //Set the tile.
                block.tiletypes[x][y] = t + ( v ? rand()&v : 0 );
            }
        }
        //Write the block.
        Mapz->WriteBlockFlags(bx,by,z, block.blockflags );
        Mapz->WriteDesignations(bx,by,z, &block.designation );
        Mapz->WriteTileTypes(bx,by,z, &block.tiletypes );
        Mapz->WriteDirtyBit(bx,by,z,1);
    }

    DF->Detach();
#ifndef LINUX_BUILD
    cout << "Done. Press any key to continue" << endl;
    cin.ignore();
#endif
    return 0;
}
Exemple #2
0
int main (void)
{
    int32_t x,y,z,tx,ty;
    //DFHack::designations40d designations;
    DFHack::tiletypes40d tiles;
    //DFHack::t_temperatures temp1,temp2;
    uint32_t x_max,y_max,z_max;
    int32_t oldT, newT;
	int count, dirty;

	//Brush defaults
	DFHack::TileShape BrushClass = DFHack::WALL;
	DFHack::TileMaterial BrushMat = DFHack::tilematerial_invalid;
	int BrushType = -1;

    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF;
    DFHack::Maps * Maps;
    DFHack::Gui * Gui;
    try
    {
        DF=DFMgr.getSingleContext();
        DF->Attach();
        Maps = DF->getMaps();
        Maps->Start();
        Maps->getSize(x_max,y_max,z_max);
        Gui = DF->getGui();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    bool end = false;
    cout << "Welcome to the Tile Drawing tool.\nType 'help' or ? for a list of available commands, 'q' to quit" << endl;
    string mode = "wall";
    string command = "";

	while(!end)
	{
        DF->Resume();

		cout << endl << ":";
		getline(cin, command);
		int ch = command[0];
		if(command.length()<=0) ch=0;
		if( ((int)command.find("help")) >=0 ) ch='?';  //under windows, find was casting unsigned!
		switch(ch)
        {
		case '?':
            cout << "Modes:" << endl
				 << "O             - draw Open Space" << endl
                 << "M             - draw material only (shape unchanged)" << endl
                 << "m number      - use Material value entered" << endl
                 << "r             - use Rock/stone material" << endl
                 << "l             - use Soil material" << endl
                 << "v             - use Vein material" << endl
                 << "H             - draw tile shape only (material unchanged)" << endl
				 << "h number      - draw Tile Shape value entered" << endl
                 << "w             - draw Wall tiles" << endl
                 << "f             - draw Floor tiles" << endl
				 << "t number      - draw exact tile type entered" << endl
                 << "Commands:" << endl
                 << "p             - print tile shapes and materials, and current brush" << endl
                 << "P             - print all tile types" << endl
                 << "q             - quit" << endl
                 << "help OR ?     - print this list of commands" << endl
                 << "d             - being drawing" << endl
                 << endl
                 << "Usage:\nChoose a mode (default is walls), then enter 'd' to being drawing.\nMove the cursor in DF wherever you want to draw.\nPress any key to pause drawing." << endl;
			break;
		case 'p':
			//Classes
			printf("\nTile Type Classes:\n");
			for(int i=0;i<DFHack::tileshape_count;++i)
			{
				printf("%4i ; %s\n", i, DFHack::TileShapeString[i] ,0 );
			}
			//Materials
			printf("\nTile Type Materials:\n");
			for(int i=0;i<DFHack::tilematerial_count;++i)
			{
				printf("%4i ; %s\n", i, DFHack::TileMaterialString[i] ,0 );
			}
			//fall through...
		case 10:
		case 13:
		case 0:
			//Print current cursor & brush settings.
			cout << "\nCurrent Brush:\n";
			cout << "tile = ";
			if(BrushClass<0) cout<<"(not drawing)"; else cout<<DFHack::TileShapeString[BrushClass]; cout << endl;
			cout << "mat  = ";
			if(BrushMat<0) cout<<"(not drawing)"; else cout<<DFHack::TileMaterialString[BrushMat]; cout << endl;
			cout << "type = ";
			if(BrushType<0){
				cout<<"(not drawing)";
			}else{
				printtiletype(BrushType);
			}
			break;
		case 'P':
			cout << "\nAll Valid Tile Types:\n";
			for(int i=0;i<TILE_TYPE_ARRAY_LENGTH;++i)
			{
				if( DFHack::tileTypeTable[i].name )
					printtiletype(i);
			}
		case 'w':
			BrushType=-1;
            BrushClass = DFHack::WALL;
            cout << "Tile brush shape set to Wall." << endl;
			break;
		case 'f':
			BrushType=-1;
            BrushClass = DFHack::FLOOR;
            cout << "Tile brush shape set to Floor." << endl;
			break;
		case 'h':
			BrushType=-1;
			BrushClass = (DFHack::TileShape)atol( command.c_str()+1 );
            cout << "Tile brush shape set to " << BrushClass << endl;
			break;
		case 'M':
            BrushClass = DFHack::tileshape_invalid;
            cout << "Tile brush will not draw tile shape." << endl;
			break;
		case 'r':
			BrushType=-1;
            BrushMat = DFHack::STONE;
            cout << "Tile brush material set to Rock." << endl;
			break;
		case 'l':
			BrushType=-1;
            BrushMat = DFHack::SOIL;
            cout << "Tile brush material set to Soil." << endl;
			break;
		case 'v':
			BrushType=-1;
            BrushMat = DFHack::VEIN;
            cout << "Tile brush material set to Vein." << endl;
			break;
		case 'm':
			BrushType=-1;
			BrushMat = (DFHack::TileMaterial)atol( command.c_str()+1 );
            cout << "Tile brush material set to " << BrushMat << endl;
			break;
		case 'H':
            BrushMat = DFHack::tilematerial_invalid;
            cout << "Tile brush will not draw material." << endl;
			break;
		case 'O':
			BrushType=-1;
			BrushClass = DFHack::EMPTY;
			BrushMat = DFHack::AIR;
            cout << "Tile brush will draw Open Space." << endl;
			break;
		case 't':
			BrushClass = DFHack::tileshape_invalid ;
			BrushMat = DFHack::tilematerial_invalid;
			BrushType = atol( command.c_str()+1 );
			cout << "Tile brush type set to:" << endl;
			printtiletype(BrushType);
			break;
		case 'q':
            end = true;
            cout << "Bye!" << endl;
			break;
		case 'd':
        {
			count=0;
			cout << "Beginning to draw at cursor." << endl << "Press any key to stop drawing." << endl;
            //DF->Suspend();
			kbhit(); //throw away, just to be sure.
            for(;;)
            {
				if(!Maps->Start())
                {
                    cout << "Can't see any DF map loaded." << endl;
                    break;
                }
                if(!Gui->getCursorCoords(x,y,z))
                {
                    cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
                    break;
                }
                //cout << "cursor coords: " << x << "/" << y << "/" << z << endl;
				tx=x%16; ty=y%16;

                if(!Maps->isValidBlock(x/16,y/16,z))
                {
                    cout << "Invalid block." << endl;
                    break;
                }

				//Read the tiles.
				dirty=0;
				Maps->ReadTileTypes((x/16),(y/16),z, &tiles);
                oldT = tiles[tx][ty];

				newT = -1;
				if( 0<BrushType ){
					//Explicit tile type set.  Trust the user.
					newT = BrushType;
				}else if( 0==BrushMat && 0==BrushClass ){
					//Special case, Empty Air.
					newT = 32;
				}else if( BrushMat>=0 && BrushClass>=0 && ( BrushClass != DFHack::tileTypeTable[oldT].shape || BrushMat != DFHack::tileTypeTable[oldT].material) ){
					//Set tile material and class
					newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tileTypeTable[oldT].variant , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
					if(newT<0) newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tilevariant_invalid, DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
					if(newT<0) newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , (uint32_t)0 );
				}else if( BrushMat<0 && BrushClass>=0 && BrushClass != DFHack::tileTypeTable[oldT].shape ){
					//Set current tile class only, as accurately as can be expected
                    newT = DFHack::findSimilarTileType(oldT,BrushClass);
				}else if( BrushClass<0 && BrushMat>=0 && BrushMat != DFHack::tileTypeTable[oldT].material ){
					//Set current tile material only
					newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tileTypeTable[oldT].variant , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
					if(newT<0) newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
					if(newT<0) newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , (uint32_t)0 );
				}
                //If no change, skip it (couldn't find a good tile type, or already what we want)
				if ( newT > 0 && oldT != newT ){
                    //Set new tile type
                    tiles[tx][ty] = newT;
                    dirty=-1;
				}
                //If anything was changed, write it all.
                if (dirty)
                {
                    //Maps->WriteDesignations(x/16,y/16,z/16, &designations);
                    Maps->WriteTileTypes(x/16,y/16,z, &tiles);
					printf("(%4d,%4d,%4d)",x,y,z);
                    ++count;
                }

                Maps->Finish();

				Sleep(10);
				if( kbhit() ) break;				
            }
			cin.clear();
			cout << endl << count << " tiles were drawn." << endl << "Drawing halted.  Entering command mode." << endl;
		}
			continue;
			break;
		default:
			cout << "Unknown command: " << command << endl;
		}

    }
    DF->Detach();
    #ifndef LINUX_BUILD
    cout << "Done. Press any key to continue" << endl;
    cin.ignore();
    #endif
    return 0;
}
Exemple #3
0
DFhackCExport command_result tubefill(DFHack::Core * c, std::vector<std::string> & params)
{
    uint32_t x_max,y_max,z_max;
    DFHack::designations40d designations;
    DFHack::tiletypes40d tiles;

    int32_t oldT, newT;
    uint64_t count = 0;

    int dirty=0;
    for(int i = 0; i < params.size();i++)
    {
        if(params[i] == "help" || params[i] == "?")
        {
            c->con.print("Replenishes mined out adamantine and hollow adamantine tubes.\n"
                         "May cause !!FUN!!\n"
            );
            return CR_OK;
        }
    }
    c->Suspend();
    DFHack::Maps *Mapz = c->getMaps();

    // init the map
    if (!Mapz->Start())
    {
        c->con.printerr("Can't init map.\n");
        c->Resume();
        return CR_FAILURE;
    }

    Mapz->getSize(x_max,y_max,z_max);
    if(!Mapz->StartFeatures())
    {
        c->con.printerr("Can't get map features.\n");
        c->Resume();
        return CR_FAILURE;
    }

    // walk the map
    for (uint32_t x = 0; x< x_max;x++)
    {
        for (uint32_t y = 0; y< y_max;y++)
        {
            for (uint32_t z = 0; z< z_max;z++)
            {
                DFHack::t_feature * locf = 0;
                DFHack::t_feature * glof = 0;
                if (Mapz->ReadFeatures(x,y,z,&locf,&glof))
                {
                    // we're looking for addy tubes
                    if(!locf) continue;
                    if(locf->type != DFHack::feature_Adamantine_Tube) continue;

                    dirty=0;
                    Mapz->ReadDesignations(x,y,z, &designations);
                    Mapz->ReadTileTypes(x,y,z, &tiles);

                    for (uint32_t ty=0;ty<16;++ty)
                    {
                        for (uint32_t tx=0;tx<16;++tx)
                        {
                            if(!designations[tx][ty].bits.feature_local) continue;
                            oldT = tiles[tx][ty];
                            if ( DFHack::tileShape(oldT) != DFHack::WALL )
                            {
                                //Current tile is not a wall.
                                //Set current tile, as accurately as can be expected
                                //newT = DFHack::findSimilarTileType(oldT,DFHack::WALL);
                                newT = DFHack::findTileType( DFHack::WALL, DFHack::FEATSTONE, DFHack::tilevariant_invalid, DFHack::TILE_NORMAL, DFHack::TileDirection() );

                                //If no change, skip it (couldn't find a good tile type)
                                if ( oldT == newT) continue;
                                //Set new tile type, clear designation
                                tiles[tx][ty] = newT;
                                dirty=1;
                                ++count;
                            }
                        }
                    }
                    //If anything was changed, write it all.
                    if (dirty)
                    {
                        Mapz->WriteTileTypes(x,y,z, &tiles);
                    }
                }
            }
        }
    }
    c->Resume();
    c->con.print("Found and changed %d tiles.\n", count);
    return CR_OK;
}
int main (void)
{
    bool temporary_terminal = TemporaryTerminal();
    uint32_t x_max,y_max,z_max;
    DFHack::designations40d designations;
    DFHack::tiletypes40d tiles;

    int32_t oldT, newT;
    uint64_t count = 0;

    int dirty=0;

    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF = DFMgr.getSingleContext();

    //Init
    try
    {
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        if(temporary_terminal)
            cin.ignore();
        return 1;
    }
    DFHack::Maps *Mapz = DF->getMaps();

    // init the map
    if (!Mapz->Start())
    {
        cerr << "Can't init map." << endl;
        if(temporary_terminal)
            cin.ignore();
        return 1;
    }

    Mapz->getSize(x_max,y_max,z_max);
    if(!Mapz->StartFeatures())
    {
        cerr << "Can't get features." << endl;
        if(temporary_terminal)
            cin.ignore();
        return 1; 
    }

    // walk the map
    for (uint32_t x = 0; x< x_max;x++)
    {
        for (uint32_t y = 0; y< y_max;y++)
        {
            for (uint32_t z = 0; z< z_max;z++)
            {
                DFHack::t_feature * locf = 0;
                DFHack::t_feature * glof = 0;
                if (Mapz->ReadFeatures(x,y,z,&locf,&glof))
                {
                    // we're looking for addy tubes
                    if(!locf) continue;
                    if(locf->type != DFHack::feature_Adamantine_Tube) continue;

                    dirty=0;
                    Mapz->ReadDesignations(x,y,z, &designations);
                    Mapz->ReadTileTypes(x,y,z, &tiles);

                    for (uint32_t ty=0;ty<16;++ty)
                    {
                        for (uint32_t tx=0;tx<16;++tx)
                        {
                            if(!designations[tx][ty].bits.feature_local) continue;
                            oldT = tiles[tx][ty];
                            if ( DFHack::tileShape(oldT) != DFHack::WALL )
                            {
                                //Current tile is not a wall.
                                //Set current tile, as accurately as can be expected
                                //newT = DFHack::findSimilarTileType(oldT,DFHack::WALL);
                                newT = DFHack::findTileType( DFHack::WALL, DFHack::FEATSTONE, DFHack::tilevariant_invalid, DFHack::TILE_NORMAL, DFHack::TileDirection() );

                                //If no change, skip it (couldn't find a good tile type)
                                if ( oldT == newT) continue;
                                //Set new tile type, clear designation
                                tiles[tx][ty] = newT;
                                dirty=1;
                                ++count;
                            }
                        }
                    }
                    //If anything was changed, write it all.
                    if (dirty)
                    {
                        Mapz->WriteTileTypes(x,y,z, &tiles);
                    }
                }
            }
        }
    }
    DF->Detach();
    cout << "Found and changed " << count << " tiles." << endl;
    if(temporary_terminal)
    {
        cout << "Done. Press any key to continue" << endl;
        cin.ignore();
    }
    return 0;
}