Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: getone -- Getting a script to run  (Read 3181 times)

Thorfinn

  • Bay Watcher
    • View Profile
getone -- Getting a script to run
« on: March 22, 2018, 04:30:09 pm »

I'm trying to get this to run and can't figure out where it goes. Or maybe I'm making a mistake invoking it. Not sure.

getone
Spoiler (click to show/hide)

I've saved it as getone.lua in hack/lua. If so, nothing I've tried works to run it. Unfortunately, I've already uninstalled my 43.05, so I can't see how I used it there.

Any tips?

Logged

Thorfinn

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #1 on: March 22, 2018, 04:49:57 pm »

Never mind.

It was supposed to be saved in hack/scripts, if anyone else ever sees this and made the same mistake.
Logged

PatrikLundell

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #2 on: March 24, 2018, 01:58:23 am »

The script posted above is broken because indices have been gobbled up by the forum at some point.

This is the latest version (as of this writing...) of the script, which collect paper plants and allows collection of multiples rather than single plants by changing the constant at the top:
Code: [Select]
[code]function getone ()
  local number_to_get = 1  --  Change this number if you want more of each. Note that the number of plants
                           --  actually collected is reduced by the number of seeds already at hand.
 
  for i, v in ipairs (df.global.world.raws.plants.all) do
    local paper_plant = false
   
    for k, material in ipairs (v.material) do
      for l, reaction in ipairs (material.reaction_class) do
        if reaction.value == "PAPER_PLANT" then
          paper_plant = true
          break
        end
      end
    end   
   
    if (v.flags.DRINK or
        v.flags.THREAD or
        paper_plant) and
       not v.flags.SAPLING and
       not v.flags.TREE and
       not v.flags.GRASS and
       not v.flags.BIOME_SUBTERRANEAN_WATER and
       not v.flags.BIOME_SUBTERRANEAN_CHASM and
       not v.flags.BIOME_SUBTERRANEAN_LAVA then
      local seeds = 0
      local found = 0
      local designated = 0
      local skip = false
 
      for k, seed in ipairs (df.global.world.items.other.SEEDS) do
        if seed.mat_index == i then
          seeds = seeds + 1
         
          if seeds >= number_to_get then
            skip = true
            dfhack.println ("Skipping " .. v.id .. " as sufficient seeds are already available")
            break
          end
        end
      end
     
      found = seeds
     
      if not skip then
        for k, plant in ipairs (df.global.world.plants.all) do
          if plant.material == i then
            local cur = dfhack.maps.getTileBlock (plant.pos)
            local x = plant.pos.x % 16
            local y = plant.pos.y % 16
            local skip
   
            if cur.tiletype [x] [y] == df.tiletype.Shrub then
              if cur.designation [x] [y].dig == df.tile_dig_designation.No then
                current = df.global.world.jobs.list
                skip = false
 
                while current ~= nil do
                  if current.item ~= nil and
                     current.item.job_type == df.job_type.GatherPlants and
                     current.item.pos.x == plant.pos.x and
                     current.item.pos.y == plant.pos.y and
                     current.item.pos.z == plant.pos.z then
                    skip = true
                    break
                  end
   
                  current = current.next
                end
                       
                if not skip then
                  for l, u in ipairs (df.global.world.jobs.postings) do
                    if u.job ~= nil and
                       u.job.job_type == df.job_type.GatherPlants and
                       u.job.pos.x == plant.pos.x and
                       u.job.pos.y == plant.pos.y and
                       u.job.pos.z == plant.pos.z then
                      skip = true
                      break
                    end
                  end
                end
           
                if not skip then
                  found = found + 1
                  designated = true
                 
                  for l, growth in ipairs (v.growths) do
                    if growth.id == "FRUIT" and
                       (df.global.cur_year_tick < growth.timing_1 or
                        df.global.cur_year_tick > growth.timing_2) then
                      designated = false
                      break
                    end
                  end
               
                  if designated then
                    cur.designation [x] [y].dig = df.tile_dig_designation.Default
                    cur.flags.designated = true
                    dfhack.println ("Designated " .. v.id)
                   
                    if found >= number_to_get then
                      break
                    end
                  end
                end
              end
            end
          end       
        end
      end
     
      if not skip then
        if found == seeds then
          dfhack.println ("Failed to find any " .. v.id)
         
        elseif not designated then
          dfhack.println ("Found " .. v.id .. " but it's not ripe")
       
        elseif found < number_to_get then
          dfhack.println ("Failed to find sufficient " .. v.id)
        end
      end
    end
  end
end

getone()
[/code]

The script (and others) can also be found here: https://github.com/PatrikLundell/scripts/tree/own_scripts.
Logged

Thorfinn

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #3 on: March 24, 2018, 12:30:26 pm »

Hey, awesome! I was having troubles getting it to run right, and now that you mention it, I did have to tweak it from what I copied from the forum last spring. Completely forgot about it.

Incidentally, anyone who wants to get a jumpstart on surface farming, this works great. Much faster than hunting throughout your embark looking for a plant you are missing. Run the script and anyone with herbalism will go grab one plant of each type you don't already have seed for. (I see you've added the ability to edit the minimum number of seeds you want to have on hand -- even better!) Brew them and you have seeds for your grower.

Thanks!

« Last Edit: March 24, 2018, 12:36:00 pm by Thorfinn »
Logged

Thorfinn

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #4 on: March 24, 2018, 02:40:55 pm »

After running it, I remember the other thing I changed -- I started the search closer to the center of the world rather than the NW corner. But I hardcoded it for a 4x4, and it was sloppy, and there are certainly more elegant ways to code it than I did, like maybe starting from the wagon and spiralling out. If you are taking suggestions... ;)

Too bad I only saved my embark profiles, raw changes, and .inits before deleting 43.05. Dopey me, I even lost my macros, like magma filling and dumping stations, qsps, and all my stockpile settings.
Logged

PatrikLundell

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #5 on: March 25, 2018, 09:03:24 am »

Here's a new version that selects plants closest to the center of the embark first. It also handles the case that the plants have been designated but not yet transferred into jobs (basically what you get when running the script twice while paused).

My fairly limited testing indicates it works...

Code: [Select]
[code]local number_to_get = 1  --  Change this number if you want more of each. Note that the number of plants
                         --  actually collected is reduced by the number of seeds already at hand.
 
--====================================

local max_x, max_y, max_z = dfhack.maps.getTileSize()
local center_x = max_x / 2
local center_y = max_y / 2
 
--====================================

function distance_2 (x, y)
  local dx = center_x - x
  local dy = center_y - y
  return dx * dx + dy * dy
end

--====================================

function closer (x1, y1, x2, y2)
  return distance_2 (x1, y1) < distance_2 (x2, y2)
end

--====================================

function getone ()
  for i, v in ipairs (df.global.world.raws.plants.all) do
    local paper_plant = false
   
    for k, material in ipairs (v.material) do
      for l, reaction in ipairs (material.reaction_class) do
        if reaction.value == "PAPER_PLANT" then
          paper_plant = true
          break
        end
      end
    end   
   
    if (v.flags.DRINK or
        v.flags.THREAD or
        paper_plant) and
       not v.flags.SAPLING and
       not v.flags.TREE and
       not v.flags.GRASS and
       not v.flags.BIOME_SUBTERRANEAN_WATER and
       not v.flags.BIOME_SUBTERRANEAN_CHASM and
       not v.flags.BIOME_SUBTERRANEAN_LAVA then
      local seeds = 0
      local found = 0
      local designated = 0
      local skip = false
 
      for k, seed in ipairs (df.global.world.items.other.SEEDS) do
        if seed.mat_index == i then
          seeds = seeds + 1
         
          if seeds >= number_to_get then
            skip = true
            dfhack.println ("Skipping " .. v.id .. " as sufficient seeds are already available")
            break
          end
        end
      end
     
      found = seeds
      local candidates = {}
     
      if not skip then
        for k, plant in ipairs (df.global.world.plants.all) do
          if plant.material == i then
            local cur = dfhack.maps.getTileBlock (plant.pos)
            local x = plant.pos.x % 16
            local y = plant.pos.y % 16
            local skip_inner
   
            if cur.tiletype [x] [y] == df.tiletype.Shrub then
              if cur.designation [x] [y].dig == df.tile_dig_designation.No then
                current = df.global.world.jobs.list
                skip_inner = false
 
                while current ~= nil do
                  if current.item ~= nil and
                     current.item.job_type == df.job_type.GatherPlants and
                     current.item.pos.x == plant.pos.x and
                     current.item.pos.y == plant.pos.y and
                     current.item.pos.z == plant.pos.z then
                    table.insert (candidates, {plant, true})
                    skip_inner = true
                    break
                  end
   
                  current = current.next
                end
                       
                if not skip_inner then
                  for l, u in ipairs (df.global.world.jobs.postings) do
                    if u.job ~= nil and
                       u.job.job_type == df.job_type.GatherPlants and
                       u.job.pos.x == plant.pos.x and
                       u.job.pos.y == plant.pos.y and
                       u.job.pos.z == plant.pos.z then
                      table.insert (candidates, {plant, true})
                      skip_inner = true
                      break
                    end
                  end
                end
           
                if not skip_inner then
                  table.insert (candidates, {plant, false})
                end
               
              elseif cur.designation [x] [y].dig == df.tile_dig_designation.Default then
                table.insert (candidates, {plant, true})
              end             
            end 
          end   
        end
       
        if #candidates + seeds >= number_to_get then  --  Need to sort the list   
          local temp
         
          for l = 1, #candidates - 1 do
            if not candidates [l] [2] then  --  Already designated ones are kept. Don't know with certainty how to replace those.
              for m = l + 1, #candidates do
                if candidates [m] [2] then
                  temp = candidates [l]
                  candidates [l] = candidates [m]
                  candidates [m] = temp
                  break
                end
               
                if distance_2 (candidates [l] [1].pos.x, candidates [l] [1].pos.y) > distance_2 (candidates [m] [1].pos.x, candidates [m] [1].pos.y) then
                  temp = candidates [l]
                  candidates [l] = candidates [m]
                  candidates [m] = temp
                end
              end
            end
          end
        end
       
        for l, growth in ipairs (v.growths) do
          if growth.id == "FRUIT" and
             (df.global.cur_year_tick < growth.timing_1 or
              df.global.cur_year_tick > growth.timing_2) then
            dfhack.println ("Found " .. v.id .. " but it's not ripe")
            designated = false
            break
          end
        end
       
        if designated then
          local last = #candidates
       
          if #candidates > number_to_get - seeds then
            last = number_to_get - seeds
          end
       
                 
          for l = 1, last do
            if candidates [l] [2] then
              dfhack.println ("Already designated " .. v.id, candidates [l] [1].pos.x, candidates [l] [1].pos.y, candidates [l] [1].pos.z)
             
            else
              local cur = dfhack.maps.getTileBlock (candidates [l] [1].pos)
              local x = candidates [l] [1].pos.x % 16
              local y = candidates [l] [1].pos.y % 16
           
              cur.designation [x] [y].dig = df.tile_dig_designation.Default
              cur.flags.designated = true
              dfhack.println ("Designated " .. v.id, candidates [l] [1].pos.x, candidates [l] [1].pos.y, candidates [l] [1].pos.z)
            end
          end
        end
      end
     
      if not skip then
        if #candidates == 0 then
          dfhack.println ("Failed to find any " .. v.id)
         
        elseif not designated then
          --  Not ripe
       
        elseif #candidates < number_to_get - seeds then
          dfhack.println ("Failed to find sufficient " .. v.id)
        end
      end
    end
  end
end

getone()
[/code]
Logged

Thorfinn

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #6 on: December 31, 2020, 02:13:55 pm »

Just noticed this is no longer shipped with DFHack, at least in the latest LNP, 47.04.r11. It was included in 47.04.r10.

Topping the thread because I find this a really useful script.
Logged

PatrikLundell

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #7 on: January 01, 2021, 07:07:41 am »

I don't think the script has been included in DFHack, so I suspect your usage of it with -r10 is a result of you copying the script at some time.
Logged

Thorfinn

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #8 on: January 02, 2021, 11:19:14 am »

Huh. I told LNP not to import anything, and manually copy things like stockpiles and macros and embark profiles and my own version of getone, so I get only the things I really want, not all the fluff I fill those directories up with. Don't remember doing it, but I must have. Probably something to do with being retirement age.

Never mind.  ???
Logged

lethosor

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #9 on: January 05, 2021, 01:23:01 am »

Some packs bundle additional scripts that DFHack doesn't include - maybe that's it?

We could probably fix and include this one, but it doesn't seem to include documentation, so I'm not quite sure what it does.
Logged
DFHack - Dwarf Manipulator (Lua) - DF Wiki talk

There was a typo in the siegers' campfire code. When the fires went out, so did the game.

PatrikLundell

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #10 on: January 05, 2021, 05:27:41 am »

The latest version of the script can be found here https://github.com/PatrikLundell/scripts/blob/own_scripts/getone.lua. Note that it's a web page with the script on it, not a file with the script, so you'd need to press "Raw" to get only the contents displayed.

The main purpose of the script is to get seeds to get your farming going. It's somewhat similar to the getplants plugin.
Logged

lethosor

  • Bay Watcher
    • View Profile
Re: getone -- Getting a script to run
« Reply #11 on: January 05, 2021, 10:28:45 pm »

Whoops, it was very late when I saw this, and I misread it and thought the issue was that the script no longer worked:
Just noticed this is no longer shipped with DFHack, at least in the latest LNP, 47.04.r11. It was included in 47.04.r10.

If you're just trying to obtain the script itself, see PatrikLundell's link. If it would be useful to include in the standard DFHack distribution, we can make that happen too.
Logged
DFHack - Dwarf Manipulator (Lua) - DF Wiki talk

There was a typo in the siegers' campfire code. When the fires went out, so did the game.