Пример #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;
}
Пример #2
0
int main(int argc, char *argv[])
{
    /* initialize your non-curses data structures here */

    signal(SIGINT, finish);      /* arrange interrupts to terminate */
    setlocale(LC_ALL,"");
    initscr();      /* initialize the curses library */
    keypad(stdscr, TRUE);  /* enable keyboard mapping */
    nonl();         /* tell curses not to do NL->CR/NL on output */
    cbreak();       /* take input chars one at a time, no wait for \n */
    noecho();       /* don't echo input */
    //nodelay(stdscr, true); 

    keypad(stdscr, TRUE);
    scrollok(stdscr, TRUE);

    if (has_colors())
    {
        start_color();

        /*
         * Simple color assignment, often all we need.
         */
        init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
        init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
        init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
        init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
        init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);

        init_color(COLOR_CYAN, 700, 700, 700); // lt grey
        init_color(COLOR_MAGENTA, 500, 500, 500); // dk grey
        init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
        init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
        init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
    }
    
    int x_max,y_max,z_max;
    uint32_t x_max_a,y_max_a,z_max_a;
    /*
    uint16_t tiletypes[16][16];
    DFHack::t_designation designations[16][16];
    uint8_t regionoffsets[16];
    */
    map <int16_t, uint32_t> materials;
    materials.clear();
    mapblock40d blocks[3][3];
    vector<DFHack::t_effect_df40d> effects;
    vector< vector <uint16_t> > layerassign;
    vector<t_vein> veinVector;
    vector<t_frozenliquidvein> IceVeinVector;
    vector<t_spattervein> splatter;
    vector<t_grassvein> grass;
    vector<t_worldconstruction> wconstructs;
    t_temperatures b_temp1;
    t_temperatures b_temp2;

    DFHack::Materials * Mats = 0;
    DFHack::Maps * Maps = 0;
    
    
    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context* DF;
    try
    {
        pDF = DF = DFMgr.getSingleContext();
        DF->Attach();
        Maps = DF->getMaps();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        finish(0);
    }
    bool hasmats = true;
    try
    {
        Mats = DF->getMaterials();
    }
    catch (exception& e)
    {
        hasmats = false;
    }
    
    // init the map
    if(!Maps->Start())
    {
        error = "Can't find a map to look at.";
        finish(0);
    }

    Maps->getSize(x_max_a,y_max_a,z_max_a);
    x_max = x_max_a;
    y_max = y_max_a;
    z_max = z_max_a;
    
    bool hasInorgMats = false;
    bool hasPlantMats = false;
    bool hasCreatureMats = false;

    if(hasmats)
    {
        // get stone matgloss mapping
        if(Mats->ReadInorganicMaterials())
        {
            hasInorgMats = true;
        }
        if(Mats->ReadCreatureTypes())
        {
            hasCreatureMats = true;
        }
        if(Mats->ReadOrganicMaterials())
        {
            hasPlantMats = true;
        }
    }
/*
    // get region geology
    if(!DF.ReadGeology( layerassign ))
    {
        error = "Can't read local geology.";
        pDF = 0;
        finish(0);
    }
*/
    // FIXME: could fail on small forts
    int cursorX = x_max/2 - 1;
    int cursorY = y_max/2 - 1;
    int cursorZ = z_max/2 - 1;
    
    
    bool dig = false;
    bool dump = false;
    bool digbit = false;
    bool dotwiddle;
    unsigned char twiddle = 0;
    int vein = 0;
    int filenum = 0;
    bool dirtybit = false;
    uint32_t blockaddr = 0;
    uint32_t blockaddr2 = 0;
    t_blockflags bflags;
    bflags.whole = 0;
    enum e_tempmode
    {
        TEMP_NO,
        TEMP_1,
        TEMP_2,
        WATER_SALT,
        WATER_STAGNANT
    };
    e_tempmode temperature = TEMP_NO;
    
    // resume so we don't block DF while we wait for input
    DF->Resume();
    
    for (;;)
    {
        dig = false;
        dump = false;
        dotwiddle = false;
        digbit = false;
        
        int c = getch();     /* refresh, accept single keystroke of input */
        flushinp();
        clrscr();
        /* process the command keystroke */
        switch(c)
        {
            case KEY_DOWN:
                cursorY ++;
                break;
            case KEY_UP:
                cursorY --;
                break;
            case KEY_LEFT:
                cursorX --;
                break;
            case KEY_RIGHT:
                cursorX ++;
                break;
            case KEY_NPAGE:
                cursorZ --;
                break;
            case KEY_PPAGE:
                cursorZ ++;
                break;
            case '+':
                vein ++;
                break;
            case 'd':
                dig = true;
                break;
            case 'o':
                dump = true;
                break;
            case '-':
                vein --;
                break;
            case 'z':
                digbit = true;
                break;
            case '/':
                if(twiddle != 0) twiddle--;
                break;
            case '*':
                twiddle++;
                break;
            case 't':
                dotwiddle = true;
                break;
            case 'b':
                temperature = TEMP_NO;
                break;
            case 'n':
                temperature = TEMP_1;
                break;
            case 'm':
                temperature = TEMP_2;
                break;
            case 'c':
                temperature = WATER_SALT;
                break;
            case 'v':
                temperature = WATER_STAGNANT;
                break;
            case 27: // escape key
                DF->Detach();
                return 0;
                break;
            default:
                break;
        }
        cursorX = max(cursorX, 0);
        cursorY = max(cursorY, 0);
        cursorZ = max(cursorZ, 0);
        
        cursorX = min(cursorX, x_max - 1);
        cursorY = min(cursorY, y_max - 1);
        cursorZ = min(cursorZ, z_max - 1);
        
        if(twiddle > 31)
            twiddle = 31;
        
        // clear data before we suspend
        memset(blocks,0,sizeof(blocks));
        veinVector.clear();
        IceVeinVector.clear();
        effects.clear();
        splatter.clear();
        grass.clear();
        dirtybit = 0;
        
        // Supend, read/write data
        DF->Suspend();
        // restart cleared modules
        Maps->Start();
        if(hasmats)
        {
            Mats->Start();
            if(hasInorgMats)
            {
                Mats->ReadInorganicMaterials();
            }
            if(hasPlantMats)
            {
                Mats->ReadOrganicMaterials();
            }
            if(hasCreatureMats)
            {
                Mats->ReadCreatureTypes();
            }
        }
        /*
        if(DF.InitReadEffects(effectnum))
        {
            for(uint32_t i = 0; i < effectnum;i++)
            {
                t_effect_df40d effect;
                DF.ReadEffect(i,effect);
                effects.push_back(effect);
            }
        }
        */
        for(int i = -1; i <= 1; i++) for(int j = -1; j <= 1; j++)
        {
            mapblock40d * Block = &blocks[i+1][j+1];
            if(Maps->isValidBlock(cursorX+i,cursorY+j,cursorZ))
            {
                Maps->ReadBlock40d(cursorX+i,cursorY+j,cursorZ, Block);
                // extra processing of the block in the middle
                if(i == 0 && j == 0)
                {
                    if(hasInorgMats)
                        do_features(DF, Block, cursorX, cursorY, 50,10, Mats->inorganic);
                    // read veins
                    Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,&veinVector,&IceVeinVector,&splatter,&grass, &wconstructs);

                    // get pointer to block
                    blockaddr = Maps->getBlockPtr(cursorX+i,cursorY+j,cursorZ);
                    blockaddr2 = Block->origin;

                    // dig all veins and trees
                    if(dig)
                    {
                        for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++)
                        {
                            int16_t tiletype = Block->tiletypes[x][y];
                            TileShape tc = tileShape(tiletype);
                            TileMaterial tm = tileMaterial(tiletype);
                            if( tc == WALL && tm == VEIN || tc == TREE_OK || tc == TREE_DEAD)
                            {
                                Block->designation[x][y].bits.dig = designation_default;
                            }
                        }
                        Maps->WriteDesignations(cursorX+i,cursorY+j,cursorZ, &(Block->designation));
                    }
                    
                    // read temperature data
                    Maps->ReadTemperatures(cursorX+i,cursorY+j,cursorZ,&b_temp1, &b_temp2 );
                    if(dotwiddle)
                    {
                        bitset<32> bs = Block->designation[0][0].whole;
                        bs.flip(twiddle);
                        Block->designation[0][0].whole = bs.to_ulong();
                        Maps->WriteDesignations(cursorX+i,cursorY+j,cursorZ, &(Block->designation));
                        dotwiddle = false;
                    }
                    
                    // do a dump of the block data
                    if(dump)
                    {
                        hexdump(DF,blockaddr,0x1E00,filenum);
                        filenum++;
                    }
                    // read/write dirty bit of the block
                    Maps->ReadDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit);
                    Maps->ReadBlockFlags(cursorX+i,cursorY+j,cursorZ,bflags);
                    if(digbit)
                    {
                        dirtybit = !dirtybit;
                        Maps->WriteDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit);
                    }
                }
            }
        }
        // Resume, print stuff to the terminal
        DF->Resume();
        for(int i = -1; i <= 1; i++) for(int j = -1; j <= 1; j++)
        {
            mapblock40d * Block = &blocks[i+1][j+1];
            for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++)
            {
                int color = COLOR_BLACK;
                color = pickColor(Block->tiletypes[x][y]);
                /*
                if(!Block->designation[x][y].bits.hidden)
                {
                    puttile(x+(i+1)*16,y+(j+1)*16,Block->tiletypes[x][y], color);
                }
                else*/
                {
                    
                    attron(A_STANDOUT);
                    puttile(x+(i+1)*16,y+(j+1)*16,Block->tiletypes[x][y], color);
                    attroff(A_STANDOUT);
                    
                }
            }
            // print effects for the center tile
            /*
            if(i == 0 && j == 0)
            {
                for(uint zz = 0; zz < effects.size();zz++)
                {
                    if(effects[zz].z == cursorZ && !effects[zz].isHidden)
                    {
                        // block coords to tile coords
                        uint16_t x = effects[zz].x - (cursorX * 16);
                        uint16_t y = effects[zz].y - (cursorY * 16);
                        if(x < 16 && y < 16)
                        {
                            putch(x + 16,y + 16,'@',COLOR_WHITE);
                        }
                    }
                }
            }
            */
        }
        gotoxy(50,0);
        cprintf("arrow keys, PGUP, PGDN = navigate");
        gotoxy(50,1);
        cprintf("+,-                    = switch vein");
        gotoxy(50,2);
        uint32_t mineralsize = veinVector.size();
        uint32_t icesize = IceVeinVector.size();
        uint32_t splattersize = splatter.size();
        uint32_t grasssize = grass.size();
        uint32_t wconstrsize = wconstructs.size();
        uint32_t totalVeinSize =  mineralsize+ icesize + splattersize + grasssize + wconstrsize;
        if(vein == totalVeinSize) vein = totalVeinSize - 1;
        if(vein < -1) vein = -1;
        cprintf("X %d/%d, Y %d/%d, Z %d/%d. Vein %d of %d",cursorX+1,x_max,cursorY+1,y_max,cursorZ,z_max,vein+1,totalVeinSize);
        if(!veinVector.empty() || !IceVeinVector.empty() || !splatter.empty() || !grass.empty() || !wconstructs.empty())
        {
            if(vein != -1 && vein < totalVeinSize)
            {
                uint32_t realvein = 0;
                if(vein < mineralsize)
                {
                    realvein = vein;
                    //iterate through vein rows
                    for(uint32_t j = 0;j<16;j++)
                    {
                        //iterate through the bits
                        for (uint32_t k = 0; k< 16;k++)
                        {
                            // and the bit array with a one-bit mask, check if the bit is set
                            bool set = !!(((1 << k) & veinVector[realvein].assignment[j]) >> k);
                            if(set)
                            {
                                putch(k+16,j+16,'$',COLOR_RED);
                            }
                        }
                    }
                    if(hasInorgMats)
                    {
                        gotoxy(50,3);
                        cprintf("Mineral: %s",Mats->inorganic[veinVector[vein].type].id);
                    }
                }
                else if (vein < mineralsize + icesize)
                {
                    realvein = vein - mineralsize;
                    t_frozenliquidvein &frozen = IceVeinVector[realvein];
                    for(uint32_t i = 0;i<16;i++)
                    {
                        for (uint32_t j = 0; j< 16;j++)
                        {
                            int color = COLOR_BLACK;
                            int tile = frozen.tiles[i][j];
                            color = pickColor(tile);
                            
                            attron(A_STANDOUT);
                            puttile(i+16,j+16,tile, color);
                            attroff(A_STANDOUT);
                        }
                    }
                    gotoxy(50,3);
                    cprintf("ICE");
                }
                else if(vein < mineralsize + icesize + splattersize)
                {
                    realvein = vein - mineralsize - icesize;
                    for(uint32_t yyy = 0; yyy < 16; yyy++)
                    {
                        for(uint32_t xxx = 0; xxx < 16; xxx++) 
                        {
                            uint8_t intensity = splatter[realvein].intensity[xxx][yyy];
                            if(intensity)
                            {
                                attron(A_STANDOUT);
                                putch(xxx+16,yyy+16,'*', COLOR_RED);
                                attroff(A_STANDOUT);
                            }
                        }
                    }
                    if(hasCreatureMats)
                    {
                        gotoxy(50,3);
                        cprintf("Spatter: %s",PrintSplatterType(splatter[realvein].mat1,splatter[realvein].mat2,Mats->race).c_str());
                    }
                }
                else if(vein < mineralsize + icesize + splattersize + grasssize)
                {
                    realvein = vein - mineralsize - icesize - splattersize;
                    t_grassvein & grassy =grass[realvein];
                    for(uint32_t yyy = 0; yyy < 16; yyy++)
                    {
                        for(uint32_t xxx = 0; xxx < 16; xxx++) 
                        {
                            uint8_t intensity = grassy.intensity[xxx][yyy];
                            if(intensity)
                            {
                                attron(A_STANDOUT);
                                putch(xxx+16,yyy+16,'X', COLOR_RED);
                                attroff(A_STANDOUT);
                            }
                        }
                    }
                    if(hasPlantMats)
                    {
                        gotoxy(50,3);
                        cprintf("Grass: 0x%x, %s",grassy.address_of, Mats->organic[grassy.material].id);
                    }
                }
                else
                {
                    realvein = vein - mineralsize - icesize - splattersize - grasssize;
                    t_worldconstruction & wconstr=wconstructs[realvein];
                    for(uint32_t j = 0; j < 16; j++)
                    {
                        for(uint32_t k = 0; k < 16; k++) 
                        {
                            bool set = !!(((1 << k) & wconstr.assignment[j]) >> k);
                            if(set)
                            {
                                putch(k+16,j+16,'$',COLOR_RED);
                            }
                        }
                    }
                    if(hasInorgMats)
                    {
                        gotoxy(50,3);
                        cprintf("Road: 0x%x, %d - %s", wconstr.address_of, wconstr.material,Mats->inorganic[wconstr.material].id);
                    }
                }
            }
Пример #3
0
int main (int numargs, const char ** args)
{
    map<string, string> buildCommands;
    buildCommands["building_stockpilest"]="";
    buildCommands["building_zonest"]="";
    buildCommands["building_construction_blueprintst"]="";
    buildCommands["building_wagonst"]="";
    buildCommands["building_armor_standst"]="a";
    buildCommands["building_bedst"]="b";
    buildCommands["building_seatst"]="c";
    buildCommands["building_burial_receptaclest"]="n";
    buildCommands["building_doorst"]="d";
    buildCommands["building_floodgatest"]="x";
    buildCommands["building_floor_hatchst"]="H";
    buildCommands["building_wall_gratest"]="W";
    buildCommands["building_floor_gratest"]="G";
    buildCommands["building_vertical_barsst"]="B";
    buildCommands["building_floor_barsst"]="alt-b";
    buildCommands["building_cabinetst"]="f";
    buildCommands["building_containerst"]="h";
    buildCommands["building_shopst"]="";
    buildCommands["building_workshopst"]="";
    buildCommands["building_alchemists_laboratoryst"]="wa";
    buildCommands["building_carpenters_workshopst"]="wc";
    buildCommands["building_farmers_workshopst"]="ww";
    buildCommands["building_masons_workshopst"]="wm";
    buildCommands["building_craftdwarfs_workshopst"]="wr";
    buildCommands["building_jewelers_workshopst"]="wj";
    buildCommands["building_metalsmiths_workshopst"]="wf";
    buildCommands["building_magma_forgest"]="";
    buildCommands["building_bowyers_workshopst"]="wb";
    buildCommands["building_mechanics_workshopst"]="wt";
    buildCommands["building_siege_workshopst"]="ws";
    buildCommands["building_butchers_shopst"]="wU";
    buildCommands["building_leather_worksst"]="we";
    buildCommands["building_tanners_shopst"]="wn";
    buildCommands["building_clothiers_shopst"]="wk";
    buildCommands["building_fisheryst"]="wh";
    buildCommands["building_stillst"]="wl";
    buildCommands["building_loomst"]="wo";
    buildCommands["building_quernst"]="wq";
    buildCommands["building_kennelsst"]="k";
    buildCommands["building_kitchenst"]="wz";
    buildCommands["building_asheryst"]="wy";
    buildCommands["building_dyers_shopst"]="wd";
    buildCommands["building_millstonest"]="wM";
    buildCommands["building_farm_plotst"]="p";
    buildCommands["building_weapon_rackst"]="r";
    buildCommands["building_statuest"]="s";
    buildCommands["building_tablest"]="t";
    buildCommands["building_paved_roadst"]="o";
    buildCommands["building_bridgest"]="g";
    buildCommands["building_wellst"]="l";
    buildCommands["building_siege enginest"]="i";
    buildCommands["building_catapultst"]="ic";
    buildCommands["building_ballistast"]="ib";
    buildCommands["building_furnacest"]="";
    buildCommands["building_wood_furnacest"]="ew";
    buildCommands["building_smelterst"]="es";
    buildCommands["building_glass_furnacest"]="ek";
    buildCommands["building_kilnst"]="ek";
    buildCommands["building_magma_smelterst"]="es";
    buildCommands["building_magma_glass_furnacest"]="ek";
    buildCommands["building_magma_kilnst"]="ek";
    buildCommands["building_glass_windowst"]="y";
    buildCommands["building_gem_windowst"]="Y";
    buildCommands["building_tradedepotst"]="D";
    buildCommands["building_mechanismst"]="";
    buildCommands["building_leverst"]="Tl";
    buildCommands["building_pressure_platest"]="Tp";
    buildCommands["building_cage_trapst"]="Tc";
    buildCommands["building_stonefall_trapst"]="Ts";
    buildCommands["building_weapon_trapst"]="Tw";
    buildCommands["building_spikest"]="";
    buildCommands["building_animal_trapst"]="m";
    buildCommands["building_screw_pumpst"]="Ms";
    buildCommands["building_water_wheelst"]="Mw";
    buildCommands["building_windmillst"]="Mm";
    buildCommands["building_gear_assemblyst"]="Mg";
    buildCommands["building_horizontal_axlest"]="Mh";
    buildCommands["building_vertical_axlest"]="Mv";
    buildCommands["building_supportst"]="S";
    buildCommands["building_cagest"]="j";
    buildCommands["building_archery_targetst"]="A";
    buildCommands["building_restraintst"]="v";

    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF = DFMgr.getSingleContext();
    
    try
    {
        DF->Attach();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    
    DFHack::Gui *Gui = DF->getGui();
    DFHack::VersionInfo* mem = DF->getMemoryInfo();
    DFHack::Process * p = DF->getProcess();
    OffsetGroup * OG_Maps = mem->getGroup("Maps");
    OffsetGroup * OG_MapBlock = OG_Maps->getGroup("block");
    OffsetGroup * OG_LocalFt = OG_Maps->getGroup("features")->getGroup("local");
    uint32_t designations = OG_MapBlock->getOffset("designation");
    uint32_t block_feature1 = OG_MapBlock->getOffset("feature_local");
    uint32_t block_feature2 = OG_MapBlock->getOffset("feature_global");
    uint32_t region_x_offset = OG_Maps->getAddress("region_x");
    uint32_t region_y_offset = OG_Maps->getAddress("region_y");
    uint32_t region_z_offset = OG_Maps->getAddress("region_z");
    uint32_t feature1_start_ptr = OG_LocalFt->getAddress("start_ptr");
    int32_t regionX, regionY, regionZ;
    
    // read position of the region inside DF world
    p->readDWord (region_x_offset, (uint32_t &)regionX);
    p->readDWord (region_y_offset, (uint32_t &)regionY);
    p->readDWord (region_z_offset, (uint32_t &)regionZ);
    while(1){
    int32_t cx1,cy1,cz1;
    cx1 = -30000;
    while(cx1 == -30000)
    {
        DF->ForceResume();
        cout << "Set cursor at first position, then press any key";
        cin.ignore();
        DF->Suspend();
        Gui->getCursorCoords(cx1,cy1,cz1);
    }

    uint32_t tx1,ty1,tz1;
    tx1 = cx1/16;
    ty1 = cy1/16;
    tz1 = cz1;

    int32_t cx2,cy2,cz2;
    cx2 = -30000;
    while(cx2 == -30000)
    {
        DF->Resume();
        cout << "Set cursor at second position, then press any key";
        cin.ignore();
        DF->Suspend();
        Gui->getCursorCoords(cx2,cy2,cz2);
    }
    uint32_t tx2,ty2,tz2;
    tx2 = cx2/16;
    ty2 = cy2/16;
    tz2 = cz2;
    sort(tx1,tx2);
    sort(ty1,ty2);
    sort(tz1,tz2);
    sort(cx1,cx2);
    sort(cy1,cy2);
    sort(cz1,cz2);

    vector <vector<vector<string> > >dig(cz2-cz1+1,vector<vector<string> >(cy2-cy1+1,vector<string>(cx2-cx1+1)));
    vector <vector<vector<string> > >build(cz2-cz1+1,vector<vector<string> >(cy2-cy1+1,vector<string>(cx2-cx1+1)));
    mapblock40d block;
    DFHack::Maps *Maps = DF->getMaps();
    Maps->Start();
    for(uint32_t y = ty1;y<=ty2;y++)
    {
        for(uint32_t x = tx1;x<=tx2;x++)
        {
            for(uint32_t z = tz1;z<=tz2;z++)
            {
                if(Maps->isValidBlock(x,y,z))
                {
                    if(Maps->ReadBlock40d(x,y,z,&block))
                    {
                        int ystart,yend,xstart,xend;
                        ystart=xstart=0;
                        yend=xend=15;
                        if(y == ty2)
                        {
                            yend = cy2 % 16;
                        }
                        if(y == ty1)
                        {
                            ystart = cy1 % 16;
                        }
                        if(x == tx2)
                        {
                            xend = cx2 % 16;
                        }
                        if(x == tx1)
                        {
                            xstart = cx1 % 16;
                        }
                        int zidx = z-tz1;
                        for(int yy = ystart; yy <= yend;yy++)
                        {
                            int yidx = yy+(16*(y-ty1)-(cy1%16));
                            for(int xx = xstart; xx <= xend;xx++)
                            {
                                int xidx = xx+(16*(x-tx1)-(cx1%16));
                                int16_t tt = block.tiletypes[xx][yy];
                                DFHack::TileShape ts = DFHack::tileShape(tt);
                                if(DFHack::isOpenTerrain(tt) || DFHack::isFloorTerrain(tt))
                                {
                                    dig[zidx][yidx][xidx] = "d";
                                }
                                else if(DFHack::STAIR_DOWN == ts)
                                {
                                    dig [zidx][yidx][xidx] = "j";
                                    build [zidx][yidx][xidx] = "Cd";
                                }
                                else if(DFHack::STAIR_UP == ts)
                                {
                                    dig [zidx][yidx][xidx] = "u";
                                    build [zidx][yidx][xidx] = "Cu";
                                }
                                else if(DFHack::STAIR_UPDOWN == ts)
                                {
                                    dig [zidx][yidx][xidx] = "i";
                                    build [zidx][yidx][xidx] = "Cx";
                                }
                                else if(DFHack::isRampTerrain(tt))
                                {
                                    dig [zidx][yidx][xidx] = "r";
                                    build [zidx][yidx][xidx] = "Cr";
                                }
                                else if(DFHack::isWallTerrain(tt))
                                {
                                    build [zidx][yidx][xidx] = "Cw";
                                }
                            }
                            yidx++;
                        }
                    }
                }
            }
        }
    }
    DFHack::Buildings * Bld = DF->getBuildings();
    std::map <uint32_t, std::string> custom_workshop_types;
    uint32_t numBuildings;
    if(Bld->Start(numBuildings))
    {
        Bld->ReadCustomWorkshopTypes(custom_workshop_types);
        for(uint32_t i = 0; i < numBuildings; i++)
        {
            DFHack::t_building temp;
            Bld->Read(i, temp);
            if(temp.type != 0xFFFFFFFF) // check if type isn't invalid
            {
                std::string typestr;
                mem->resolveClassIDToClassname(temp.type, typestr);
                if(temp.z == cz1 && cx1 <= temp.x1 && cx2 >= temp.x2 && cy1 <= temp.y1 && cy2 >= temp.y2)
                {
                    string currStr = build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1];
                    stringstream stream;
                    string newStr = buildCommands[typestr];
                    if(temp.x1 != temp.x2)
                    {
                        stream << "(" << temp.x2-temp.x1+1 << "x" << temp.y2-temp.y1+1 << ")";
                        newStr += stream.str();
                    }
                    build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1] = newStr + currStr;
                }
            }
        }
    }
// for testing purposes
    //ofstream outfile("test.txt");
//    printVecOfVec(outfile, dig,'\t');
//    outfile << endl;
//   printVecOfVec(outfile, build,'\t');
//    outfile << endl;
//    outfile.close();

    int32_t cx3,cy3,cz3,cx4,cy4,cz4;
    uint32_t tx3,ty3,tz3,tx4,ty4,tz4;
    char result;
    while(1){
        cx3 = -30000;
        while(cx3 == -30000){
            DF->Resume();
            cout << "Set cursor at new position, then press any key:";
            result = cin.get();
            DF->Suspend();
            Gui->getCursorCoords(cx3,cy3,cz3);
        }
        if(result == 'q'){
            break;
        }
        cx4 = cx3+cx2-cx1;
        cy4 = cy3+cy2-cy1;
        cz4 = cz3+cz2-cz1;
        tx3=cx3/16;
        ty3=cy3/16;
        tz3=cz3;
        tx4=cx4/16;
        ty4=cy4/16;
        tz4=cz4;
        DFHack::WindowIO * Win = DF->getWindowIO();
        designations40d designationBlock;
        for(uint32_t y = ty3;y<=ty4;y++)
        {
            for(uint32_t x = tx3;x<=tx4;x++)
            {
                for(uint32_t z = tz3;z<=tz4;z++)
                {
                    Maps->Start();
                    Maps->ReadBlock40d(x,y,z,&block);
                    Maps->ReadDesignations(x,y,z,&designationBlock);
                    int ystart,yend,xstart,xend;
                    ystart=xstart=0;
                    yend=xend=15;
                    if(y == ty4){
                        yend = cy4 % 16;
                    }
                    if(y == ty3){
                        ystart = cy3 % 16;
                    }
                    if(x == tx4){
                        xend = cx4 % 16;
                    }
                    if(x == tx3){
                        xstart = cx3 % 16;
                    }
                    int zidx = z-tz3;
                    for(int yy = ystart; yy <= yend;yy++){
                        int yidx = yy+(16*(y-ty3)-(cy3%16));
                        for(int xx = xstart; xx <= xend;xx++){
                            int xidx = xx+(16*(x-tx3)-(cx3%16));
                                if(dig[zidx][yidx][xidx] != ""){
                                    char test = dig[zidx][yidx][xidx].c_str()[0];
                                    switch (test){
                                        case 'd':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_default;
                                            break;
                                        case 'i':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_ud_stair;
                                            break;
                                        case 'u':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_u_stair;
                                            break;
                                        case 'j':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_d_stair;
                                            break;
                                        case 'r':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_ramp;
                                            break;
                                    }
                                
                                }
                        }
                        yidx++;
                    }
                    Maps->Start();
                    Maps->WriteDesignations(x,y,z,&designationBlock);
                }
            }
        }
    }
    }
    DF->Detach();
    #ifndef LINUX_BUILD
    std::cout << "Done. Press any key to continue" << std::endl;
    cin.ignore();
    #endif
    return 0;
}
Пример #4
0
int main (void)
{
    uint32_t x_max,y_max,z_max;
    DFHack::designations40d designations;
    
    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF;
    try
    {
        DF = DFMgr.getSingleContext();
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    
    DFHack::Maps *Maps =DF->getMaps();
    DFHack::Gui *Gui =DF->getGui();
    // walk the map, save the hide bits, reveal.
    cout << "Pausing..." << endl;

    // horrible hack to make sure the pause is really set
    // preblem here is that we could be 'arriving' at the wrong time and DF could be in the middle of a frame.
    // that could mean that revealing, even with suspending DF's thread, would mean unleashing hell *in the same frame* 
    // this here hack sets the pause state, resumes DF, waits a second for it to enter the pause (I know, BS value.) and suspends.
    Gui->SetPauseState(true);
    DF->Resume();
    waitmsec(1000);
    DF->Suspend();

    // init the map
    if(!Maps->Start())
    {
        cerr << "Can't init map." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    cout << "Revealing, please wait..." << endl;

    Maps->getSize(x_max,y_max,z_max);
    vector <hideblock> hidesaved;

    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++)
            {
                if(Maps->isValidBlock(x,y,z))
                {
                    hideblock hb;
                    hb.x = x;
                    hb.y = y;
                    hb.z = z;
                    // read block designations
                    Maps->ReadDesignations(x,y,z, &designations);
                    // change the hidden flag to 0
                    for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
                    {
                        hb.hiddens[i][j] = designations[i][j].bits.hidden;
                        designations[i][j].bits.hidden = 0;
                    }
                    hidesaved.push_back(hb);
                    // write the designations back
                    Maps->WriteDesignations(x,y,z, &designations);
                }
            }
        }
    }
    // FIXME: force game pause here!
    DF->Detach();
    cout << "Map revealed. The game has been paused for you." << endl;
    cout << "Unpausing can unleash the forces of hell!" << endl << endl;
    cout << "Press any key to unreveal." << endl;
    cout << "Close to keep the map revealed." << endl;
    cin.ignore();
    cout << "Unrevealing... please wait." << endl;
    // FIXME: do some consistency checks here!
    DF->Attach();
    Maps = DF->getMaps();
    Maps->Start();
    for(int i = 0; i < hidesaved.size();i++)
    {
        hideblock & hb = hidesaved[i];
        Maps->ReadDesignations(hb.x,hb.y,hb.z, &designations);
        for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
        {
            designations[i][j].bits.hidden = hb.hiddens[i][j];
        }
        Maps->WriteDesignations(hb.x,hb.y,hb.z, &designations);
    }
    #ifndef LINUX_BUILD
    cout << "Done. Press any key to continue" << endl;
    cin.ignore();
    #endif
    return 0;
}