I had offered to make an Applescript that will send commands to DF to dig out a circle of arbitrary radius. Here it is. This works similarly to AutoHotKey on Windows.
The circle is a solid ring with no pass-through space. That is, if you wanted to build a single tile thickness wall which had no open diagonals to walk through, this is what the script will draw out. From there, it's trivial to select the interior to dig out a large round room. Small circles (radius 3 or os) are a little squared off, IMO. They're mathematically accurate, but sometimes you need to exaggerate features to make them aesthetically pleasing. Large circles look quite good, IMO.
The script tosses up two dialogs. The first asks you for the radius of the circle. The second asks you for the action. Right now it supports 'Dig' which executes d->d and then digs out a circle underground. The other is 'Traffic' which executes d->o->h, and draws out a high traffic circle on a surface. It's not too bad a way to mark out a circle on the ground to build walls on top of. I chose traffic because it works on any surface and doesn't have any meaningful action on your dwarves. The code is reasonably well documented so you should be able to add your own options there, or ask away and I'll expand it. I can have it do the actual build of the wall, but there is no way to tell what material is being selected, so you'd risk getting a mixed-media wall of wood, stone, blocks, and metal bars. Speak up if you'd like something like that.
Installation:
Open up Script Editor in Applications/Applescript, copy and paste this in, hit the compile button, and save it. You can either double-click the script and run it out of Script Editor or save it as an application and just run it as such. I put mine in the script menu in the menu bar. Save the file to /Library/Scripts/Dwarf Fortress/Dig Circle, open the Applescript Utility in the Applications/Applescript and select Show Script Menu in Menubar. For doubleplusgoodness, get Fastscripts (
http://www.red-sweater.com/fastscripts/) or a similar utility and you can put a command key on the script and bang out circles without hitting the mouse.
-- Dig a circle
global home_x
global home_y
set home_x to 0
set home_y to 0
set action_list to {"Dig", "Traffic"}
set radius_response to display dialog ("Circle radius: ") default answer "9"
set radius to text returned of radius_response
set df_action to {choose from list action_list}
set df_action to df_action as string
tell application "Dwarf Fortress"
activate
tell application "System Events"
if df_action = "Dig" then
sendDFcommand("designate") of me
sendDFcommand("dig") of me
else if df_action = "Traffic" then
sendDFcommand("designate") of me
sendDFcommand("traffic") of me
sendDFcommand("high_traffic") of me
end if
-- move up the radius
moveDFcursor(0, -1 * radius) of me
-- dig this tile
sendDFcommand("select") of me
sendDFcommand("select") of me
-- remember where the top is so we can bail when we get there again
set start_x to home_x
set start_y to home_y
set started to false
repeat while ((home_y is not start_y) or (home_x is not start_x)) or started is not true
if home_x is less than or equal to 0 and home_y > 0 then
-- top right quadrant
set move_x to 1
set move_y to 0
set shift_x to 0
set shift_y to 1
else if home_x < 0 and home_y is less than or equal to 0 then
-- bottom right quadrant
set move_x to 0
set move_y to 1
set shift_x to -1
set shift_y to 0
else if home_x is greater than or equal to 0 and home_y < 0 then
-- bottom left quadrant
set move_x to -1
set move_y to 0
set shift_x to 0
set shift_y to -1
else if home_x > 0 and home_y is greater than or equal to 0 then
-- top left quadrant
set move_x to 0
set move_y to -1
set shift_x to 1
set shift_y to 0
end if
set distance to (((((home_x - shift_x) ^ 2) ^ 0.5)) ^ 2 + ((((home_y - shift_y) ^ 2) ^ 0.5)) ^ 2) ^ (0.5)
if (distance > radius - 0.5) then
-- shift
moveDFcursor(shift_x, shift_y) of me
-- dig
sendDFcommand("select") of me
sendDFcommand("select") of me
else
-- move
moveDFcursor(move_x, move_y) of me
-- dig
sendDFcommand("select") of me
sendDFcommand("select") of me
end if
set started to true
end repeat
-- Go back to the starting point
moveDFhome(home_x, home_y) of me
end tell
end tell
on sendDFcommand(keycommand)
tell application "System Events"
-- designate top level menu
if (keycommand = "designate") then
keystroke "d"
else if (keycommand = "dig") then
-- submenus to designate
keystroke "d"
else if (keycommand = "undesignate") then
keystroke "x"
else if (keycommand = "u/d stair") then
keystroke "i"
else if (keycommand = "traffic") then
-- traffic submenu
keystroke "o"
else if (keycommand = "high_traffic") then
keystroke "h"
else if keycommand = "select" then
key code 36
end if
end tell
end sendDFcommand
on moveDFhome(home_x, home_y)
moveDFcursor(home_x, home_y)
set home_x to 0
set home_y to 0
end moveDFhome
on moveDFcursor(x, y)
tell application "Dwarf Fortress"
activate
tell application "System Events"
repeat while x > 0
-- move right 1
key code 124
delay 0.1
set x to x - 1
set home_x to home_x - 1
end repeat
repeat while x < 0
-- move left 1
key code 123
delay 0.1
set x to x + 1
set home_x to home_x + 1
end repeat
repeat while y > 0
-- move down 1
key code 125
delay 0.1
set y to y - 1
set home_y to home_y - 1
end repeat
repeat while y < 0
-- move up 1
key code 126
delay 0.1
set y to y + 1
set home_y to home_y + 1
end repeat
end tell
end tell
end moveDFcursor
Tomorrow I'll provide a script that will dig out an arbitrary space using various techniques. If you have standard building patterns, it can be worth the effort to set up a script to do it. I'll also offer up a script to adjust job functions. Again, it can't read what is selected or not, so it's an invert function, which I find is handy for flipping hauling functions on and off. These three scripts should give you enough idea how to approach scripting DF so you can automate whatever suits you.
Updates2009.02.07 - modified script to address problem some people were having with large moves.