Example #1
0
 coord_vec points(MapCache & mc, DFHack::DFCoord start)
 {
     coord_vec v;
     bool juststarted = true;
     while (mc.testCoord(start))
     {
         uint16_t tt = mc.tiletypeAt(start);
         if(DFHack::LowPassable(tt) || juststarted && DFHack::HighPassable(tt))
         {
             v.push_back(start);
             juststarted = false;
             start.z++;
         }
         else break;
     }
     return v;
 };
Example #2
0
int main (int argc, char* argv[])
{
    // Command line options
    bool updown = false;
    if(argc > 1 && strcmp(argv[1],"-x") == 0)
        updown = true;

    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;
    }

    uint32_t x_max,y_max,z_max;
    DFHack::Maps * Maps = DF->getMaps();
    DFHack::Gui * Gui = DF->getGui();

    // init the map
    if(!Maps->Start())
    {
        cerr << "Can't init map. Make sure you have a map loaded in DF." << endl;
        DF->Detach();
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    int32_t cx, cy, cz;
    Maps->getSize(x_max,y_max,z_max);
    uint32_t tx_max = x_max * 16;
    uint32_t ty_max = y_max * 16;

    Gui->getCursorCoords(cx,cy,cz);
    while(cx == -30000)
    {
        cerr << "Cursor is not active. Point the cursor at a vein." << endl;
        DF->Resume();
        cin.ignore();
        DF->Suspend();
        Gui->getCursorCoords(cx,cy,cz);
    }
    DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
    if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
    {
        cerr << "I won't dig the borders. That would be cheating!" << endl;
        DF->Detach();
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    MapCache * MCache = new MapCache(Maps);

    DFHack::t_designation des = MCache->designationAt(xy);
    int16_t tt = MCache->tiletypeAt(xy);
    int16_t veinmat = MCache->veinMaterialAt(xy);

    if( veinmat == -1 )
    {
        cerr << "This tile is non-vein. Bye :)" << endl;
        delete MCache;
        DF->Detach();
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    printf("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);
    stack <DFHack::DFCoord> flood;
    flood.push(xy);


    while( !flood.empty() )
    {
        DFHack::DFCoord current = flood.top();
        flood.pop();
        int16_t vmat2 = MCache->veinMaterialAt(current);
        tt = MCache->tiletypeAt(current);
        if(!DFHack::isWallTerrain(tt))
            continue;
        if(vmat2!=veinmat)
            continue;

        // found a good tile, dig+unset material
        DFHack::t_designation des = MCache->designationAt(current);
        DFHack::t_designation des_minus;
        DFHack::t_designation des_plus;
        des_plus.whole = des_minus.whole = 0;
        int16_t vmat_minus = -1;
        int16_t vmat_plus = -1;
        bool below = 0;
        bool above = 0;
        if(updown)
        {
            if(MCache->testCoord(current-1))
            {
                below = 1;
                des_minus = MCache->designationAt(current-1);
                vmat_minus = MCache->veinMaterialAt(current-1);
            }

            if(MCache->testCoord(current+1))
            {
                above = 1;
                des_plus = MCache->designationAt(current+1);
                vmat_plus = MCache->veinMaterialAt(current+1);
            }
        }
        if(MCache->testCoord(current))
        {
            MCache->clearMaterialAt(current);
            if(current.x < tx_max - 2)
            {
                flood.push(DFHack::DFCoord(current.x + 1, current.y, current.z));
                if(current.y < ty_max - 2)
                {
                    flood.push(DFHack::DFCoord(current.x + 1, current.y + 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z));
                }
                if(current.y > 1)
                {
                    flood.push(DFHack::DFCoord(current.x + 1, current.y - 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z));
                }
            }
            if(current.x > 1)
            {
                flood.push(DFHack::DFCoord(current.x - 1, current.y,current.z));
                if(current.y < ty_max - 2)
                {
                    flood.push(DFHack::DFCoord(current.x - 1, current.y + 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z));
                }
                if(current.y > 1)
                {
                    flood.push(DFHack::DFCoord(current.x - 1, current.y - 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z));
                }
            }
            if(updown)
            {
                if(current.z > 0 && below && vmat_minus == vmat2)
                {
                    flood.push(current-1);

                    if(des_minus.bits.dig == DFHack::designation_d_stair)
                        des_minus.bits.dig = DFHack::designation_ud_stair;
                    else
                        des_minus.bits.dig = DFHack::designation_u_stair;
                    MCache->setDesignationAt(current-1,des_minus);

                    des.bits.dig = DFHack::designation_d_stair;
                }
                if(current.z < z_max - 1 && above && vmat_plus == vmat2)
                {
                    flood.push(current+ 1);

                    if(des_plus.bits.dig == DFHack::designation_u_stair)
                        des_plus.bits.dig = DFHack::designation_ud_stair;
                    else
                        des_plus.bits.dig = DFHack::designation_d_stair;
                    MCache->setDesignationAt(current+1,des_plus);

                    if(des.bits.dig == DFHack::designation_d_stair)
                        des.bits.dig = DFHack::designation_ud_stair;
                    else
                        des.bits.dig = DFHack::designation_u_stair;
                }
            }
            if(des.bits.dig == DFHack::designation_no)
                des.bits.dig = DFHack::designation_default;
            MCache->setDesignationAt(current,des);
        }
    }
    MCache->WriteAll();
    delete MCache;
    DF->Detach();
    #ifndef LINUX_BUILD
        cout << "Done. Press any key to continue" << endl;
        cin.ignore();
    #endif
    return 0;
}
Example #3
0
command_result df_liquids_execute(color_ostream &out)
{
    // create brush type depending on old parameters
    Brush * brush;

    if (brushname == "point")
    {
        brush = new RectangleBrush(1,1,1,0,0,0);
        //width = 1;
        //height = 1;
        //z_levels = 1;
    }
    else if (brushname == "range")
    {
        brush = new RectangleBrush(width,height,z_levels,0,0,0);
    }
    else if(brushname == "block")
    {
        brush = new BlockBrush();
    }
    else if(brushname == "column")
    {
        brush = new ColumnBrush();
    }
    else if(brushname == "flood")
    {
        brush = new FloodBrush(&Core::getInstance());
    }
    else
    {
        // this should never happen!
        out << "Old brushtype is invalid! Resetting to point brush.\n";
        brushname = "point";
        width = 1;
        height = 1;
        z_levels = 1;
        brush = new RectangleBrush(width,height,z_levels,0,0,0);
    }

    CoreSuspender suspend;

    do
    {
        if (!Maps::IsValid())
        {
            out << "Can't see any DF map loaded." << endl;
            break;;
        }
        int32_t x,y,z;
        if(!Gui::getCursorCoords(x,y,z))
        {
            out << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
            break;
        }
        out << "cursor coords: " << x << "/" << y << "/" << z << endl;
        MapCache mcache;
        DFHack::DFCoord cursor(x,y,z);
        coord_vec all_tiles = brush->points(mcache,cursor);
        out << "working..." << endl;

        // Force the game to recompute its walkability cache
        df::global::world->reindex_pathfinding = true;

        if(mode == "obsidian")
        {
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                mcache.setTiletypeAt(*iter, tiletype::LavaWall);
                mcache.setTemp1At(*iter,10015);
                mcache.setTemp2At(*iter,10015);
                df::tile_designation des = mcache.designationAt(*iter);
                des.bits.flow_size = 0;
                des.bits.flow_forbid = false;
                mcache.setDesignationAt(*iter, des);
                iter ++;
            }
        }
        if(mode == "obsidian_floor")
        {
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                mcache.setTiletypeAt(*iter, findRandomVariant(tiletype::LavaFloor1));
                iter ++;
            }
        }
        else if(mode == "riversource")
        {
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                mcache.setTiletypeAt(*iter, tiletype::RiverSource);

                df::tile_designation a = mcache.designationAt(*iter);
                a.bits.liquid_type = tile_liquid::Water;
                a.bits.liquid_static = false;
                a.bits.flow_size = 7;
                mcache.setTemp1At(*iter,10015);
                mcache.setTemp2At(*iter,10015);
                mcache.setDesignationAt(*iter,a);

                Block * b = mcache.BlockAt((*iter)/16);
                DFHack::t_blockflags bf = b->BlockFlags();
                bf.bits.update_liquid = true;
                bf.bits.update_liquid_twice = true;
                b->setBlockFlags(bf);

                iter++;
            }
        }
        else if(mode=="wclean")
        {
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                DFHack::DFCoord current = *iter;
                df::tile_designation des = mcache.designationAt(current);
                des.bits.water_salt = false;
                des.bits.water_stagnant = false;
                mcache.setDesignationAt(current,des);
                iter++;
            }
        }
        else if(mode== "magma" || mode== "water" || mode == "flowbits")
        {
            set <Block *> seen_blocks;
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                DFHack::DFCoord current = *iter; // current tile coord
                DFHack::DFCoord curblock = current /16; // current block coord
                // check if the block is actually there
                if(!mcache.BlockAt(curblock))
                {
                    iter ++;
                    continue;
                }
                df::tile_designation des = mcache.designationAt(current);
                df::tiletype tt = mcache.tiletypeAt(current);
                // don't put liquids into places where they don't belong...
                if(!DFHack::FlowPassable(tt))
                {
                    iter++;
                    continue;
                }
                if(mode != "flowbits")
                {
                    if(setmode == "s.")
                    {
                        des.bits.flow_size = amount;
                    }
                    else if(setmode == "s+")
                    {
                        if(des.bits.flow_size < amount)
                            des.bits.flow_size = amount;
                    }
                    else if(setmode == "s-")
                    {
                        if (des.bits.flow_size > amount)
                            des.bits.flow_size = amount;
                    }
                    if(amount != 0 && mode == "magma")
                    {
                        des.bits.liquid_type =  tile_liquid::Magma;
                        mcache.setTemp1At(current,12000);
                        mcache.setTemp2At(current,12000);
                    }
                    else if(amount != 0 && mode == "water")
                    {
                        des.bits.liquid_type =  tile_liquid::Water;
                        mcache.setTemp1At(current,10015);
                        mcache.setTemp2At(current,10015);
                    }
                    else if(amount == 0 && (mode == "water" || mode == "magma"))
                    {
                        // reset temperature to sane default
                        mcache.setTemp1At(current,10015);
                        mcache.setTemp2At(current,10015);
                    }
                    // mark the tile passable or impassable like the game does
                    des.bits.flow_forbid = des.bits.flow_size &&
                        (des.bits.liquid_type == tile_liquid::Magma || des.bits.flow_size > 3);
                    mcache.setDesignationAt(current,des);
                }
                seen_blocks.insert(mcache.BlockAt(current / 16));
                iter++;
            }
            set <Block *>::iterator biter = seen_blocks.begin();
            while (biter != seen_blocks.end())
            {
                DFHack::t_blockflags bflags = (*biter)->BlockFlags();
                if(flowmode == "f+")
                {
                    bflags.bits.update_liquid = true;
                    bflags.bits.update_liquid_twice = true;
                    (*biter)->setBlockFlags(bflags);
                }
                else if(flowmode == "f-")
                {
                    bflags.bits.update_liquid = false;
                    bflags.bits.update_liquid_twice = false;
                    (*biter)->setBlockFlags(bflags);
                }
                else
                {
                    out << "flow bit 1 = " << bflags.bits.update_liquid << endl; 
                    out << "flow bit 2 = " << bflags.bits.update_liquid_twice << endl;
                }
                biter ++;
            }
        }
        if(mcache.WriteAll())
            out << "OK" << endl;
        else
            out << "Something failed horribly! RUN!" << endl;
    } while (0);

    // cleanup
    delete brush;
    return CR_OK;
}
Example #4
0
command_result df_liquids_execute(color_ostream &out, OperationMode &cur_mode, df::coord cursor)
{
    // create brush type depending on old parameters
    Brush *brush;

    switch (cur_mode.brush)
    {
    case B_POINT:
        brush = new RectangleBrush(1,1,1,0,0,0);
        break;
    case B_RANGE:
        brush = new RectangleBrush(cur_mode.size.x,cur_mode.size.y,cur_mode.size.z,0,0,0);
        break;
    case B_BLOCK:
        brush = new BlockBrush();
        break;
    case B_COLUMN:
        brush = new ColumnBrush();
        break;
    case B_FLOOD:
        brush = new FloodBrush(&Core::getInstance());
        break;
    default:
        // this should never happen!
        out << "Old brushtype is invalid! Resetting to point brush.\n";
        cur_mode.brush = B_POINT;
        brush = new RectangleBrush(1,1,1,0,0,0);
    }

    std::auto_ptr<Brush> brush_ref(brush);

    if (!Maps::IsValid())
    {
        out << "Can't see any DF map loaded." << endl;
        return CR_FAILURE;
    }

    MapCache mcache;
    coord_vec all_tiles = brush->points(mcache,cursor);

    // Force the game to recompute its walkability cache
    df::global::world->reindex_pathfinding = true;

    switch (cur_mode.paint)
    {
    case P_OBSIDIAN:
        {
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                mcache.setTiletypeAt(*iter, tiletype::LavaWall);
                mcache.setTemp1At(*iter,10015);
                mcache.setTemp2At(*iter,10015);
                df::tile_designation des = mcache.designationAt(*iter);
                des.bits.flow_size = 0;
                des.bits.flow_forbid = false;
                mcache.setDesignationAt(*iter, des);
                iter ++;
            }
            break;
        }
    case P_OBSIDIAN_FLOOR:
        {
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                mcache.setTiletypeAt(*iter, findRandomVariant(tiletype::LavaFloor1));
                iter ++;
            }
            break;
        }
    case P_RIVER_SOURCE:
        {
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                mcache.setTiletypeAt(*iter, tiletype::RiverSource);

                df::tile_designation a = mcache.designationAt(*iter);
                a.bits.liquid_type = tile_liquid::Water;
                a.bits.liquid_static = false;
                a.bits.flow_size = 7;
                mcache.setTemp1At(*iter,10015);
                mcache.setTemp2At(*iter,10015);
                mcache.setDesignationAt(*iter,a);

                Block * b = mcache.BlockAt((*iter)/16);
                b->enableBlockUpdates(true);

                iter++;
            }
            break;
        }
    case P_WCLEAN:
        {
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                DFHack::DFCoord current = *iter;
                df::tile_designation des = mcache.designationAt(current);
                des.bits.water_salt = false;
                des.bits.water_stagnant = false;
                mcache.setDesignationAt(current,des);
                iter++;
            }
            break;
        }
    case P_MAGMA:
    case P_WATER:
    case P_FLOW_BITS:
        {
            set <Block *> seen_blocks;
            coord_vec::iterator iter = all_tiles.begin();
            while (iter != all_tiles.end())
            {
                DFHack::DFCoord current = *iter; // current tile coord
                DFHack::DFCoord curblock = current /16; // current block coord
                // check if the block is actually there
                auto block = mcache.BlockAt(curblock);
                if(!block)
                {
                    iter ++;
                    continue;
                }
                auto raw_block = block->getRaw();
                df::tile_designation des = mcache.designationAt(current);
                df::tiletype tt = mcache.tiletypeAt(current);
                // don't put liquids into places where they don't belong...
                if(!DFHack::FlowPassable(tt))
                {
                    iter++;
                    continue;
                }
                if(cur_mode.paint != P_FLOW_BITS)
                {
                    unsigned old_amount = des.bits.flow_size;
                    unsigned new_amount = old_amount;
                    df::tile_liquid old_liquid = des.bits.liquid_type;
                    df::tile_liquid new_liquid = old_liquid;
                    // Compute new liquid type and amount
                    switch (cur_mode.setmode)
                    {
                    case M_KEEP:
                        new_amount = cur_mode.amount;
                        break;
                    case M_INC:
                        if(old_amount < cur_mode.amount)
                            new_amount = cur_mode.amount;
                        break;
                    case M_DEC:
                        if (old_amount > cur_mode.amount)
                            new_amount = cur_mode.amount;
                    }
                    if (cur_mode.paint == P_MAGMA)
                        new_liquid = tile_liquid::Magma;
                    else if (cur_mode.paint == P_WATER)
                        new_liquid = tile_liquid::Water;
                    // Store new amount and type
                    des.bits.flow_size = new_amount;
                    des.bits.liquid_type = new_liquid;
                    // Compute temperature
                    if (!old_amount)
                        old_liquid = tile_liquid::Water;
                    if (!new_amount)
                        new_liquid = tile_liquid::Water;
                    if (old_liquid != new_liquid)
                    {
                        if (new_liquid == tile_liquid::Water)
                        {
                            mcache.setTemp1At(current,10015);
                            mcache.setTemp2At(current,10015);
                        }
                        else
                        {
                            mcache.setTemp1At(current,12000);
                            mcache.setTemp2At(current,12000);
                        }
                    }
                    // mark the tile passable or impassable like the game does
                    des.bits.flow_forbid = (new_liquid == tile_liquid::Magma || new_amount > 3);
                    mcache.setDesignationAt(current,des);
                    // request flow engine updates
                    block->enableBlockUpdates(new_amount != old_amount, new_liquid != old_liquid);
                }
                if (cur_mode.permaflow != PF_KEEP && raw_block)
                {
                    auto &flow = raw_block->liquid_flow[current.x&15][current.y&15];
                    flow.bits.perm_flow_dir = permaflow_id[cur_mode.permaflow];
                    flow.bits.temp_flow_timer = 0;
                }
                seen_blocks.insert(block);
                iter++;
            }
            set <Block *>::iterator biter = seen_blocks.begin();
            while (biter != seen_blocks.end())
            {
                switch (cur_mode.flowmode)
                {
                case M_INC:
                    (*biter)->enableBlockUpdates(true);
                    break;
                case M_DEC:
                    if (auto block = (*biter)->getRaw())
                    {
                        block->flags.clear(block_flags::update_liquid);
                        block->flags.clear(block_flags::update_liquid_twice);
                    }
                    break;
                case M_KEEP:
                    {
                        auto block = (*biter)->getRaw();
                        out << "flow bit 1 = " << block->flags.is_set(block_flags::update_liquid) << endl; 
                        out << "flow bit 2 = " << block->flags.is_set(block_flags::update_liquid_twice) << endl;
                    }
                }
                biter ++;
            }
            break;
        }
    }

    if(!mcache.WriteAll())
    {
        out << "Something failed horribly! RUN!" << endl;
        return CR_FAILURE;
    }

    return CR_OK;
}
Example #5
0
command_result revflood(color_ostream &out, vector<string> & params)
{
    for(size_t i = 0; i < params.size();i++)
    {
        if(params[i] == "help" || params[i] == "?")
            return CR_WRONG_USAGE;
    }
    CoreSuspender suspend;
    uint32_t x_max,y_max,z_max;
    if (!Maps::IsValid())
    {
        out.printerr("Map is not available!\n");
        return CR_FAILURE;
    }
    if(revealed != NOT_REVEALED)
    {
        out.printerr("This is only safe to use with non-revealed map.\n");
        return CR_FAILURE;
    }
    t_gamemodes gm;
    World::ReadGameMode(gm);
    if(!World::isFortressMode(gm.g_type) || gm.g_mode != game_mode::DWARF )
    {
        out.printerr("Only in proper dwarf mode.\n");
        return CR_FAILURE;
    }
    int32_t cx, cy, cz;
    Maps::getSize(x_max,y_max,z_max);
    uint32_t tx_max = x_max * 16;
    uint32_t ty_max = y_max * 16;

    Gui::getCursorCoords(cx,cy,cz);
    if(cx == -30000)
    {
        out.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n");
        return CR_FAILURE;
    }
    DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
    MapCache * MCache = new MapCache;
    df::tiletype tt = MCache->tiletypeAt(xy);
    if(isWallTerrain(tt))
    {
        out.printerr("Point the cursor at some empty space you want to be unhidden.\n");
        delete MCache;
        return CR_FAILURE;
    }
    // hide all tiles, flush cache
    Maps::getSize(x_max,y_max,z_max);

    for(size_t i = 0; i < world->map.map_blocks.size(); i++)
    {
        df::map_block * b = world->map.map_blocks[i];
        // change the hidden flag to 0
        for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++)
        {
            b->designation[x][y].bits.hidden = 1;
        }
    }
    MCache->trash();

    typedef std::pair <DFCoord, bool> foo;
    std::stack < foo > flood;
    flood.push( foo(xy,false) );

    while( !flood.empty() )
    {
        foo tile = flood.top();
        DFCoord & current = tile.first;
        bool & from_below = tile.second;
        flood.pop();

        if(!MCache->testCoord(current))
            continue;
        df::tiletype tt = MCache->baseTiletypeAt(current);
        df::tile_designation des = MCache->designationAt(current);
        if(!des.bits.hidden)
        {
            continue;
        }
        bool below = 0;
        bool above = 0;
        bool sides = 0;
        bool unhide = 1;
        // by tile shape, determine behavior and action
        switch (tileShape(tt))
        {
        // walls:
        case tiletype_shape::WALL:
            if(from_below)
                unhide = 0;
            break;
        // air/free space
        case tiletype_shape::EMPTY:
        case tiletype_shape::RAMP_TOP:
        case tiletype_shape::STAIR_UPDOWN:
        case tiletype_shape::STAIR_DOWN:
        case tiletype_shape::BROOK_TOP:
            above = below = sides = true;
            break;
        // has floor
        case tiletype_shape::FORTIFICATION:
        case tiletype_shape::STAIR_UP:
        case tiletype_shape::RAMP:
        case tiletype_shape::FLOOR:
        case tiletype_shape::BRANCH:
        case tiletype_shape::TRUNK_BRANCH:
        case tiletype_shape::TWIG:
        case tiletype_shape::SAPLING:
        case tiletype_shape::SHRUB:
        case tiletype_shape::BOULDER:
        case tiletype_shape::PEBBLES:
        case tiletype_shape::BROOK_BED:
        case tiletype_shape::ENDLESS_PIT:
            if(from_below)
                unhide = 0;
            above = sides = true;
            break;
        }
        if (tileMaterial(tt) == tiletype_material::PLANT || tileMaterial(tt) == tiletype_material::MUSHROOM)
        {
            if(from_below)
                unhide = 0;
            above = sides = true;
        }
        if(unhide)
        {
            des.bits.hidden = false;
            MCache->setDesignationAt(current,des);
        }
        if(sides)
        {
            flood.push(foo(DFCoord(current.x + 1, current.y ,current.z),false));
            flood.push(foo(DFCoord(current.x + 1, current.y + 1 ,current.z),false));
            flood.push(foo(DFCoord(current.x, current.y + 1 ,current.z),false));
            flood.push(foo(DFCoord(current.x - 1, current.y + 1 ,current.z),false));
            flood.push(foo(DFCoord(current.x - 1, current.y ,current.z),false));
            flood.push(foo(DFCoord(current.x - 1, current.y - 1 ,current.z),false));
            flood.push(foo(DFCoord(current.x, current.y - 1 ,current.z),false));
            flood.push(foo(DFCoord(current.x + 1, current.y - 1 ,current.z),false));
        }
        if(above)
        {
            flood.push(foo(DFCoord(current.x, current.y ,current.z + 1),true));
        }
        if(below)
        {
            flood.push(foo(DFCoord(current.x, current.y ,current.z - 1),false));
        }
    }
    MCache->WriteAll();
    delete MCache;
    return CR_OK;
}
Example #6
0
int main (int argc, const char* argv[])
{
    // Command line options
    bool updown = false;
    bool quiet = true;
    // let's be more useful when double-clicked on windows
    #ifndef LINUX_BUILD
    quiet = false;
    #endif
    int dig_up_n = 5;
    int dig_down_n = 5;

    for(int i = 1; i < argc; i++)
    {
        string arg_cur = argv[i];
        string arg_next = "";
	int arg_next_int = -99999;
	/* Check if argv[i+1] is a number >= 0 */
	if (i < argc-1) {
	    arg_next = argv[i+1];
	    arg_next_int = strtoint(arg_next);
	    if (arg_next != "0" && arg_next_int == 0) {
		arg_next_int = -99999;
	    }
	}
	if (arg_cur == "-x")
	{
	    updown = true;
	}
	else if (arg_cur == "-q")
	{
	    quiet = true;
	}
	else if(arg_cur == "-u" && i < argc-1)
	{
	    if (arg_next_int < 0 || arg_next_int >= 99999) {
		usage(argc, argv);
		return 1;
	    }
	    dig_up_n = arg_next_int;
	    i++;
	}
	else if(arg_cur == "-d" && i < argc-1)
	{
	    if (arg_next_int < 0 || arg_next_int >= 99999) {
		usage(argc, argv);
		return 1;
	    }
	    dig_down_n = arg_next_int;
	    i++;
	}
	else
	{
	    usage(argc, argv);
	    return 1;
	}
    }

    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context * DF;
    try
    {
        DF = DFMgr.getSingleContext();
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << "Error getting context: " << e.what() << endl;
        if (!quiet)
            cin.ignore();

        return 1;
    }

    uint32_t x_max,y_max,z_max;
    DFHack::Maps * Maps = DF->getMaps();
    DFHack::Gui * Gui = DF->getGui();

    // init the map
    if(!Maps->Start())
    {
        cerr << "Can't init map. Make sure you have a map loaded in DF." << endl;
        DF->Detach();
        if (!quiet)
            cin.ignore();

        return 1;
    }

    int32_t cx, cy, cz;
    Maps->getSize(x_max,y_max,z_max);
    uint32_t tx_max = x_max * 16;
    uint32_t ty_max = y_max * 16;

    Gui->getCursorCoords(cx,cy,cz);
    if (cx == -30000)
    {
        cerr << "Cursor is not active. Point the cursor at the position to dig at." << endl;
        DF->Detach();
        if (!quiet)
	{
            cin.ignore();
	}
	return 1;
    }

    DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
    if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
    {
        cerr << "I won't dig the borders. That would be cheating!" << endl;
        DF->Detach();
        if (!quiet)
	{
            cin.ignore();
	}
        return 1;
    }
    MapCache * MCache = new MapCache(Maps);

    DFHack::t_designation des = MCache->designationAt(xy);
    int16_t tt = MCache->tiletypeAt(xy);
    int16_t veinmat = MCache->veinMaterialAt(xy);

    /*
    if( veinmat == -1 )
    {
        cerr << "This tile is non-vein. Bye :)" << endl;
        delete MCache;
        DF->Detach();
        if (!quiet) {
            cin.ignore();
	}
        return 1;
    }
    */
    printf("Digging at (%d/%d/%d), tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);

    // 1 < xy.x < tx_max - 1
    // 1 < xy.y < ty_max - 1
    // xy.z

    // X____
    // X_XXX
    // XXXXX
    // __XXX
    // __XXX
    // _____
    pos map[] = 
    {
	  { 0,0 }
	, { 0,1 }
	, { 0,2 }         , { 2,2 }, { 3,2 }, { 4,2 }
	, { 0,3 }, { 1,3 }, { 2,3 }, { 3,3 }, { 4,3 }
	                  , { 2,4 }, { 3,4 }, { 4,4 }
    // this is mirrored, goes left instead of right
	                  , {-2,2 }, {-3,2 }, {-4,2 }
	         , {-1,3 }, {-2,3 }, {-3,3 }, {-4,3 }
	                  , {-2,4 }, {-3,4 }, {-4,4 }
    };

    DFHack::DFCoord npos = xy;

    if (dig_up_n > 0)
    {
	for (int j = 0; j < dig_up_n; j++)
	{
	    for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++) 
	    {
		npos=xy;
		npos.x += map[i].x;
		npos.y -= 4*j + map[i].y;
		printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z);
		digat(MCache, npos);
	    }
	}
    }
    if (dig_down_n > 0)
    {
	for (int j = 0; j < dig_down_n; j++)
	{
	    for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++) 
	    {
		npos=xy;
		npos.x += map[i].x;
		npos.y += 4*j + map[i].y;
		printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z);
		digat(MCache, npos);
	    }
	}
    }

    MCache->WriteAll();
    delete MCache;
    DF->Detach();
    if (!quiet) {
        cout << "Done. Press any key to continue" << endl;
        cin.ignore();
    }
    return 0;
}
Example #7
0
static command_result autodump_main(color_ostream &out, vector <string> & parameters)
{
    // Command line options
    bool destroy = false;
    bool here = false;
    bool need_visible = false;
    bool need_hidden = false;
    bool need_forbidden = false;
    for (size_t i = 0; i < parameters.size(); i++)
    {
        string & p = parameters[i];
        if(p == "destroy")
            destroy = true;
        else if (p == "destroy-here")
            destroy = here = true;
        else if (p == "visible")
            need_visible = true;
        else if (p == "hidden")
            need_hidden = true;
        else if (p == "forbidden")
            need_forbidden = true;
        else
            return CR_WRONG_USAGE;
    }

    if (need_visible && need_hidden)
    {
        out.printerr("An item can't be both hidden and visible.\n");
        return CR_WRONG_USAGE;
    }

    //DFHack::VersionInfo *mem = Core::getInstance().vinfo;
    if (!Maps::IsValid())
    {
        out.printerr("Map is not available!\n");
        return CR_FAILURE;
    }
    size_t numItems = world->items.all.size();

    MapCache MC;
    int i = 0;
    int dumped_total = 0;

    int cx, cy, cz;
    DFCoord pos_cursor;
    if(!destroy || here)
    {
        if (!Gui::getCursorCoords(cx,cy,cz))
        {
            out.printerr("Cursor position not found. Please enable the cursor.\n");
            return CR_FAILURE;
        }
        pos_cursor = DFCoord(cx,cy,cz);
    }
    if (!destroy)
    {
        {
            Block * b = MC.BlockAt(pos_cursor / 16);
            if(!b)
            {
                out.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n");
                return CR_FAILURE;
            }
            df::tiletype ttype = MC.tiletypeAt(pos_cursor);
            if(!DFHack::isWalkable(ttype) || DFHack::isOpenTerrain(ttype))
            {
                out.printerr("Cursor should be placed over a floor.\n");
                return CR_FAILURE;
            }
        }
    }

    // proceed with the dumpification operation
    for(size_t i=0; i< numItems; i++)
    {
        df::item * itm = world->items.all[i];
        DFCoord pos_item(itm->pos.x, itm->pos.y, itm->pos.z);

        // only dump the stuff marked for dumping and laying on the ground
        if (   !itm->flags.bits.dump
//          || !itm->flags.bits.on_ground
            ||  itm->flags.bits.construction
            ||  itm->flags.bits.in_building
            ||  itm->flags.bits.in_chest
//          ||  itm->flags.bits.in_inventory
            ||  itm->flags.bits.artifact
        )
            continue;

        if (need_visible && itm->flags.bits.hidden)
            continue;
        if (need_hidden && !itm->flags.bits.hidden)
            continue;
        if (need_forbidden && !itm->flags.bits.forbid)
            continue;
        if (!need_forbidden && itm->flags.bits.forbid)
            continue;

        if(!destroy) // move to cursor
        {
            // Change flags to indicate the dump was completed, as if by super-dwarfs
            itm->flags.bits.dump = false;
            itm->flags.bits.forbid = true;

            // Don't move items if they're already at the cursor
            if (pos_cursor != pos_item)
            {
                if (!Items::moveToGround(MC, itm, pos_cursor))
                    out.print("Could not move item: %s\n",
                              Items::getDescription(itm, 0, true).c_str());
            }
        }
        else // destroy
        {
            if (here && pos_item != pos_cursor)
                continue;

            itm->flags.bits.garbage_collect = true;

            // Cosmetic changes: make them disappear from view instantly
            itm->flags.bits.forbid = true;
            itm->flags.bits.hidden = true;
        }

        dumped_total++;
    }

    // write map changes back to DF.
    if(!destroy)
        MC.WriteAll();

    out.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for destruction" : "quickdumped");
    return CR_OK;
}
Example #8
0
static command_result autodump_main(Core * c, vector <string> & parameters)
{
    // Command line options
    bool destroy = false;
    bool here = false;
    if(parameters.size() > 0)
    {
        string & p = parameters[0];
        if(p == "destroy")
            destroy = true;
        else if (p == "destroy-here")
            destroy = here = true;
        else if(p == "?" || p == "help")
        {
            c->con.print(
                "This utility lets you quickly move all items designated to be dumped.\n"
                "Items are instantly moved to the cursor position, the dump flag is unset,\n"
                "and the forbid flag is set, as if it had been dumped normally.\n"
                "Be aware that any active dump item tasks still point at the item.\n\n"
                "Options:\n"
                "destroy       - instead of dumping, destroy the items instantly.\n"
                "destroy-here  - only affect the tile under cursor.\n"
                        );
            return CR_OK;
        }
    }
    c->Suspend();
    DFHack::VersionInfo *mem = c->vinfo;
    DFHack::Gui * Gui = c->getGui();
    DFHack::Items * Items = c->getItems();
    DFHack::Maps *Maps = c->getMaps();

    vector <df_item*> p_items;
    if(!Items->readItemVector(p_items))
    {
        c->con.printerr("Can't access the item vector.\n");
        return CR_FAILURE;
    }
    std::size_t numItems = p_items.size();

    // init the map
    if(!Maps->Start())
    {
        c->con.printerr("Can't initialize map.\n");
        return CR_FAILURE;
    }
    MapCache MC (Maps);
    int i = 0;
    int dumped_total = 0;

    int cx, cy, cz;
    DFCoord pos_cursor;
    if(!destroy || here)
    {
        if (!Gui->getCursorCoords(cx,cy,cz))
        {
            c->con.printerr("Cursor position not found. Please enabled the cursor.\n");
            return CR_FAILURE;
        }
        pos_cursor = DFCoord(cx,cy,cz);
    }
    if (!destroy)
    {
        {
            Block * b = MC.BlockAt(pos_cursor / 16);
            if(!b)
            {
                c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n");
                return CR_FAILURE;
            }
            uint16_t ttype = MC.tiletypeAt(pos_cursor);
            if(!DFHack::isFloorTerrain(ttype))
            {
                c->con.printerr("Cursor should be placed over a floor.\n");
                return CR_FAILURE;
            }
        }
    }
    coordmap counts;
    // proceed with the dumpification operation
    for(std::size_t i=0; i< numItems; i++)
    {
        df_item * itm = p_items[i];
        DFCoord pos_item(itm->x, itm->y, itm->z);

        // keep track how many items are at places. all items.
        coordmap::iterator it = counts.find(pos_item);
        if(it == counts.end())
        {
            std::pair< coordmap::iterator, bool > inserted = counts.insert(std::make_pair(pos_item,1));
            it = inserted.first;
        }
        else
        {
            it->second ++;
        }
        // iterator is valid here, we use it later to decrement the pile counter if the item is moved

        // only dump the stuff marked for dumping and laying on the ground
        if (   !itm->flags.dump
            || !itm->flags.on_ground
            ||  itm->flags.construction
            ||  itm->flags.hidden
            ||  itm->flags.in_building
            ||  itm->flags.in_chest
            ||  itm->flags.in_inventory
            ||  itm->flags.artifact1
        )
            continue;

        if(!destroy) // move to cursor
        {
            // Change flags to indicate the dump was completed, as if by super-dwarfs
            itm->flags.dump = false;
            itm->flags.forbid = true;

            // Don't move items if they're already at the cursor
            if (pos_cursor == pos_item)
                continue;

            // Do we need to fix block-local item ID vector?
            if(pos_item/16 != pos_cursor/16)
            {
                // yes...
                cerr << "Moving from block to block!" << endl;
                df_block * bl_src = Maps->getBlock(itm->x /16, itm->y/16, itm->z);
                df_block * bl_tgt = Maps->getBlock(cx /16, cy/16, cz);
                if(bl_src)
                {
                    std::remove(bl_src->items.begin(), bl_src->items.end(),itm->id);
                }
                else
                {
                    cerr << "No source block" << endl;
                }
                if(bl_tgt)
                {
                    bl_tgt->items.push_back(itm->id);
                }
                else
                {
                    cerr << "No target block" << endl;
                }
            }

            // Move the item
            itm->x = pos_cursor.x;
            itm->y = pos_cursor.y;
            itm->z = pos_cursor.z;
        }
        else // destroy
        {
            if (here && pos_item != pos_cursor)
                continue;

            itm->flags.garbage_colect = true;

            // Cosmetic changes: make them disappear from view instantly
            itm->flags.forbid = true;
            itm->flags.hidden = true;
        }
        // keeping track of item pile sizes ;)
        it->second --;
        dumped_total++;
    }
    if(!destroy) // TODO: do we have to do any of this when destroying items?
    {
        // for each item pile, see if it reached zero. if so, unset item flag on the tile it's on
        coordmap::iterator it = counts.begin();
        coordmap::iterator end = counts.end();
        while(it != end)
        {
            if(it->second == 0)
            {
                t_occupancy occ = MC.occupancyAt(it->first);
                occ.bits.item = false;
                MC.setOccupancyAt(it->first, occ);
            }
            it++;
        }
        // Set "item here" flag on target tile, if we moved any items to the target tile.
        if (dumped_total > 0)
        {
            // assume there is a possibility the cursor points at some weird location with missing block data
            Block * b = MC.BlockAt(pos_cursor / 16);
            if(b)
            {
                t_occupancy occ = MC.occupancyAt(pos_cursor);
                occ.bits.item = 1;
                MC.setOccupancyAt(pos_cursor,occ);
            }
        }
        // write map changes back to DF.
        MC.WriteAll();
        // Is this necessary?  Is "forbid" a dirtyable attribute like "dig" is?
        Maps->WriteDirtyBit(cx/16, cy/16, cz, true);
    }
    c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for desctruction" : "quickdumped");
    return CR_OK;
}
Example #9
0
static command_result autodump_main(color_ostream &out, vector <string> & parameters)
{
    // Command line options
    bool destroy = false;
    bool here = false;
    bool need_visible = false;
    bool need_hidden = false;
    bool need_forbidden = false;
    for (size_t i = 0; i < parameters.size(); i++)
    {
        string & p = parameters[i];
        if(p == "destroy")
            destroy = true;
        else if (p == "destroy-here")
            destroy = here = true;
        else if (p == "visible")
            need_visible = true;
        else if (p == "hidden")
            need_hidden = true;
        else if (p == "forbidden")
            need_forbidden = true;
        else
            return CR_WRONG_USAGE;
    }

    if (need_visible && need_hidden)
    {
        out.printerr("An item can't be both hidden and visible.\n");
        return CR_WRONG_USAGE;
    }

    //DFHack::VersionInfo *mem = Core::getInstance().vinfo;
    if (!Maps::IsValid())
    {
        out.printerr("Map is not available!\n");
        return CR_FAILURE;
    }
    size_t numItems = world->items.all.size();

    MapCache MC;
    int i = 0;
    int dumped_total = 0;

    int cx, cy, cz;
    DFCoord pos_cursor;
    if(!destroy || here)
    {
        if (!Gui::getCursorCoords(cx,cy,cz))
        {
            out.printerr("Cursor position not found. Please enabled the cursor.\n");
            return CR_FAILURE;
        }
        pos_cursor = DFCoord(cx,cy,cz);
    }
    if (!destroy)
    {
        {
            Block * b = MC.BlockAt(pos_cursor / 16);
            if(!b)
            {
                out.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n");
                return CR_FAILURE;
            }
            df::tiletype ttype = MC.tiletypeAt(pos_cursor);
            if(!DFHack::isFloorTerrain(ttype))
            {
                out.printerr("Cursor should be placed over a floor.\n");
                return CR_FAILURE;
            }
        }
    }
    coordmap counts;
    // proceed with the dumpification operation
    for(size_t i=0; i< numItems; i++)
    {
        df::item * itm = world->items.all[i];
        DFCoord pos_item(itm->pos.x, itm->pos.y, itm->pos.z);

        // keep track how many items are at places. all items.
        coordmap::iterator it = counts.find(pos_item);
        if(it == counts.end())
        {
            pair< coordmap::iterator, bool > inserted = counts.insert(make_pair(pos_item,1));
            it = inserted.first;
        }
        else
        {
            it->second ++;
        }
        // iterator is valid here, we use it later to decrement the pile counter if the item is moved

        // only dump the stuff marked for dumping and laying on the ground
        if (   !itm->flags.bits.dump
            || !itm->flags.bits.on_ground
            ||  itm->flags.bits.construction
            ||  itm->flags.bits.in_building
            ||  itm->flags.bits.in_chest
            ||  itm->flags.bits.in_inventory
            ||  itm->flags.bits.artifact1
        )
            continue;

        if (need_visible && itm->flags.bits.hidden)
            continue;
        if (need_hidden && !itm->flags.bits.hidden)
            continue;
        if (need_forbidden && !itm->flags.bits.forbid)
            continue;
        if (!need_forbidden && itm->flags.bits.forbid)
            continue;

        if(!destroy) // move to cursor
        {
            // Change flags to indicate the dump was completed, as if by super-dwarfs
            itm->flags.bits.dump = false;
            itm->flags.bits.forbid = true;

            // Don't move items if they're already at the cursor
            if (pos_cursor == pos_item)
                continue;

            // Do we need to fix block-local item ID vector?
            if(pos_item/16 != pos_cursor/16)
            {
                // yes...
                cerr << "Moving from block to block!" << endl;
                df::map_block * bl_src = Maps::getBlockAbs(itm->pos.x, itm->pos.y, itm->pos.z);
                df::map_block * bl_tgt = Maps::getBlockAbs(cx, cy, cz);
                if(bl_src)
                {
                    remove(bl_src->items.begin(), bl_src->items.end(),itm->id);
                }
                else
                {
                    cerr << "No source block" << endl;
                }
                if(bl_tgt)
                {
                    bl_tgt->items.push_back(itm->id);
                }
                else
                {
                    cerr << "No target block" << endl;
                }
            }

            // Move the item
            itm->pos.x = pos_cursor.x;
            itm->pos.y = pos_cursor.y;
            itm->pos.z = pos_cursor.z;
        }
        else // destroy
        {
            if (here && pos_item != pos_cursor)
                continue;

            itm->flags.bits.garbage_colect = true;

            // Cosmetic changes: make them disappear from view instantly
            itm->flags.bits.forbid = true;
            itm->flags.bits.hidden = true;
        }
        // keeping track of item pile sizes ;)
        it->second --;
        dumped_total++;
    }
    if(!destroy) // TODO: do we have to do any of this when destroying items?
    {
        // for each item pile, see if it reached zero. if so, unset item flag on the tile it's on
        coordmap::iterator it = counts.begin();
        coordmap::iterator end = counts.end();
        while(it != end)
        {
            if(it->second == 0)
            {
                df::tile_occupancy occ = MC.occupancyAt(it->first);
                occ.bits.item = false;
                MC.setOccupancyAt(it->first, occ);
            }
            it++;
        }
        // Set "item here" flag on target tile, if we moved any items to the target tile.
        if (dumped_total > 0)
        {
            // assume there is a possibility the cursor points at some weird location with missing block data
            Block * b = MC.BlockAt(pos_cursor / 16);
            if(b)
            {
                df::tile_occupancy occ = MC.occupancyAt(pos_cursor);
                occ.bits.item = 1;
                MC.setOccupancyAt(pos_cursor,occ);
            }
        }
        // write map changes back to DF.
        MC.WriteAll();
        // Is this necessary?  Is "forbid" a dirtyable attribute like "dig" is?
        Maps::WriteDirtyBit(cx/16, cy/16, cz, true);
    }
    out.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for destruction" : "quickdumped");
    return CR_OK;
}