Code
--keep first line blank
--Jon Weinberg
--Code 871
if dialog==nil then --if running outside foldit (eg. terminal)
-- https://www.codeproject.com/Articles/228212/Lua-Interpreter
--by Liu Junfeng
--only for Windows, uses exe sadly, so IDK if it works, I have Mac
print("Plz Run as Foldit recipe")
dialog = Gui.Form{}
end
--user="Zergling" --don't overwrite user
userTeam="Zergling"
farm="farmland"
local opt = dialog.CreateDialog("Player "..user.GetPlayerName() .." is "..userTeam)
grid = {}
rows=3
cols=rows
for i = 1, rows do
grid[i] = {}
for j = 1, cols do
grid[i][j] = farm -- Fill the values here
end
end
cell=grid
debug=false
opt.labelMsg=dialog.AddLabel("Zerglings play first (fastest). Terrans 2nd")
roundWorld=false
repeat
isFed={{false,false},{false,false}}
print("In a real game, Player " .. user.GetPlayerName())
print (" can forfeit Round 1 to save time.")
--Jon copied from Bruno Kestomont's JET 3.
slash=""
backslash=""
dash=""
space=" " --still default to space so maintain symmetric
roundWorldCode=0
if roundWorld then
toggleLabel="Flat"
else
toggleLabel="Round"
end
opt.roundWorld=dialog.AddButton(toggleLabel.." world",roundWorldCode)
--dialog.AddCheckbox("Round world", true)
-- zergling------zergling
longspace=" "
if(roundWorld) then
opt.l0=dialog.AddLabel(" "..longspace.."---||---"..longspace.." ") --because of sans serif
opt.l1=dialog.AddLabel(" / "..longspace.." | "..longspace.."\\ ")
--because of sans serif and regex
--opt.l2=dialog.AddLabel(" | ".." ".." | ".." ".." | ")
slash="/"
backslash="\\"
dash="--"
space=" "
else
opt.l0=dialog.AddLabel("") --south pole gone
opt.l1=dialog.AddLabel("")
end
opt.row1 = dialog.AddLabel(
space..space..dash..cell[1][1].."-----"..cell[1][2].."-----"..cell[1][3]..dash) --globe
opt.AddAlgorithm5 = dialog.AddLabel(
slash..space..space..space.." | "..longspace.." | "..longspace.." | "..space..space..space..backslash)
--because of sans serif
opt.row2 = dialog.AddLabel(dash..dash..cell[2][1].."------"..cell[2][2].."------"..cell[2][3]..dash..dash)
opt.AddRowLines2 = dialog.AddLabel(
backslash..space..space..space.." | "..longspace.." | "..longspace.." | "..space..space..space..slash)
--because of sans serif
opt.AddRow3 = dialog.AddLabel(
space..space..dash..cell[3][1].."-----"..cell[3][2].."-----"..cell[3][3]..dash)
if(roundWorld) then
--opt.l3=dialog.AddLabel(" | ".. " ".." | ".." ".." | ")
--because of sans serif
opt.l4=dialog.AddLabel(" \\ "..longspace.." | "..longspace.."/ ")
--because of sans serif and regex
opt.l5=dialog.AddLabel(" "..longspace.."---||---"..longspace.." ")
--because of sans serif and regex
else
opt.l4=dialog.AddLabel("") --south pole gone
opt.l5=dialog.AddLabel("") --south pole gone
end
opt.label0=dialog.AddLabel("If old unhibernated pawns do have access")
opt.label1=dialog.AddLabel(" to empty farmland or supply lines, they will starve. ") --attempt at linebreak")
opt.label2=dialog.AddLabel("Unburrow/place stone (soldier/pawn) at row,col.: ") --attempt at linebreak
--buttons will always be at the bottom of the dialog no matter the order in code
--even below sliders
--jon:
--table dialog.AddSlider(string label, number value, number minimum, number maximum, number precision)
--0 precision: 1, 2, 3,
--1 precision: 0.1,0.2,0.3
--2 prec. 0.01?
tengen=math.ceil(rows/2) --Ceiling to find a center cell
default=tengen
opt.row= dialog.AddSlider("Row ", default, 1, 3, 0)--desctrip, default, min, max, precision
opt.col= dialog.AddSlider("Column ", default, 1, 3, 0)--desctrip, default, min, max, precision
opt.placeStone=dialog.AddButton("Unburrow", 6)
opt.pass = dialog.AddButton("Pass", 5)
opt.cancel = dialog.AddButton("Cancel", -1)
res=dialog.Show(opt)
cpuTurn=false
msg=""
function canEat(eaterColor,placementCell) --more like attack
if cell[(res+1)%4]==eaterColor and cell[(res+1)%4]~=eaterColor
and cell[(res+1)%4]~=farm then
--cell[2]~=eaterColor and cell[2]~=farm) and cell[4]==eaterColor) then
return true
end
return false
end
function checkFed()
--avoid this scenario with multiple deliveries of food:
--white white
--white empty
--starved white
--white empty
--This is taxicab geometry so it takes width*2 iterations to deliver food
-- from one corner to the opposite.
--This is why living far from farms is dangerous during pandemics.
-- but traveling is dangerous too.
for numDeliveries=1,#cell*#cell[1] do
--multiply by width and height of matrix for safety to follow Go rules,
-- but is a laggy [yet intuitive] implementation of the rules.
-- Another implementation is to make an array (group) of chained pawns.
--Width+length iterations may not be enough, because there can be a snake:
--black black black white black
--black white black white black
--empty white black black black
if debug then
print("numDeliveries of food is "..numDeliveries)
end
if(roundWorld) then
for row=1, #cell do
for col=1,#cell do
if cell[row][col]==farm then --liberty
--round world, though same as normal flat world rules of Go if 2x2
isFed[(row)%#cell+1][col]=true --feed to the one below
isFed[row][(col)%#cell+1]=true --feed to the right-hand
isFed[(row-2)%#cell+1][col]=true --feed to the one above
isFed[row][(col-2)%#cell+1]=true --feed to the left-hand
--minus 2 instead of 1 because arrays in lua start with 1 instead of 0
-- +1 for same reason
-- (3-2)%3+1=2
-- (2-2)%3+1=1
-- (1-2)%3+1=2+1=3
else
if cell[(row)%#cell+1][col]==cell[row][col] and isFed[row][col] then
--supply lines
isFed[(row)%#cell+1][col]=true --round world
end
if cell[(row-2)%#cell+1][col]==cell[row][col] and isFed[row][col] then
--supply lines
isFed[(row-2)%#cell+1][col]=true --round world
end
if cell[row][(col)%#cell+1]==cell[row][col] and isFed[row][col] then
isFed[row][(col)%#cell+1]=true
end
if cell[row][(col-2)%#cell+1]==cell[row][col] and isFed[row][col] then
isFed[row][(col-2)%#cell+1]=true
end
end
end
end
else --flat
print("flat")
for row=1, #cell-1 do
for col=1,#cell do
if cell[row][col]==farm then --liberty
isFed[(row)+1][col]=true --feed to the one below
else
if cell[(row)+1][col]==cell[row][col] and isFed[row][col] then --supply lines
isFed[(row)+1][col]=true
end
end
end
end
for row=1, #cell do
for col=1,#cell-1 do
if cell[row][col]==farm then --liberty
--taxes to both factions
isFed[row][(col)+1]=true --feed to the right-hand
else
if cell[row][(col)+1]==cell[row][col] and isFed[row][col] then
isFed[row][(col)+1]=true
end
end
end
end
for row=2, #cell do
for col=1,#cell do
if cell[row][col]==farm then --a Go Liberty, Wings of Libery LOL
isFed[(row)-1][col]=true --feed to the one above
else
if cell[(row)-1][col]==cell[row][col] and isFed[row][col] then --supply lines
isFed[(row)-1][col]=true
end
end
end
end
for row=1, #cell do
for col=2,#cell do
if cell[row][col]==farm then --liberty
isFed[row][(col)-1]=true --feed to the one to the left
else
if cell[row][(col)-1]==cell[row][col] and isFed[row][col] then --supply lines
isFed[row][(col)-1]=true
end
end
end
end
end
if debug then
print("fed: ")
for row=1,#cell do
rowString=""
for col=1,#cell do
rowString=rowString..tostring(isFed[row][col]).." "
end
print(rowString)
end
end
end
end
function starve()
for row=1, #cell do
for col=1,#cell do
--Lua can't do ~true
if cell[row][col]~=farm and isFed[row][col]~=true then --no liberty
msg=msg..cell[row][col]..row..","..col.." starved. "
cell[row][col]=farm --died, decomposed to fertilizer D:
end
end
end
if debug then
print("after famine: ")
for row=1,#cell do
rowString=""
for col=1,#cell do
rowString=rowString..tostring(isFed[row][col]).." "
end
print(rowString)
end
end
end
if(res==roundWorldCode) then
roundWorld= not roundWorld
else
if(res==5) then cpuTurn=true --userTeam passes
else
row=opt.row.value
col=opt.col.value
if cell[row][col]==farm then
--print("canEat is "..tostring(canEat(userTeam,res))) --old algorithm for capturing,
-- confusing with eat and starve.
--If Zerglings, Terrans' Firebats, or Protoss Zealot swordsmen surround you
-- on all sides, you die.
--In real life and also in pro 3 way games, though, surrounding enemies on all sides
-- goes against the Art of War (Bing Fa),
-- because it makes you and your rival weakened and vulnerable to a 3rd faction.
--In nixboard github code, it uses the can_eat algorithm to tell if a capture is available, which is called atari.
-- Atari in Go is like check in Chess.
--Capturing is kind of like white blood cells engulfing,
-- and eating infected cells. In Go, though, one color is not more evil than the other.
--In my own simple code, I rename things so that the stones eat vegetables from farmland, though there is war and seige.
cell[row][col]=userTeam
isFed={{false,false,false},{false,false,false},{false,false,false}}
--let white starve after black seiges
isFed[row][col]=true
print(userTeam.." played "..row..","..col..". ")
checkFed()
starve()
isFed={{false,false,false},{false,false,false},{false,false,false}}
--after giving a chance to capture, see if it was suicide
checkFed()
starve()
cpuTurn=true
else opt.labelMsg=dialog.AddLabel("Can't place at cell "..row..", "..col)
end
end
function ai(team) --which faction
isFed={{false,false,false},{false,false,false},{false,false,false}}
farms={}
for row=1, #cell do
for col=1,#cell do
if(cell[row][col]==farm) then
table.insert(farms,{cornrow=row,corncol=col}) --,row=row}) --also works
end
end
end
if #farms==0 then
opt.labelMsg=dialog.AddLabel("White passes. ")
return false --pass
else
randFarm=math.random(#farms)
print("corn "..farms[randFarm].cornrow)
--print("row "..farms[randFarm].row)
row=farms[randFarm].cornrow
col=farms[randFarm].corncol
cell[row][col]=team
isFed={{false,false,false},{false,false,false},{false,false,false}}
--let black starve after white seiges
isFed[row][col]=true
msg=msg..team.." played"..row..","..col..". " --save space
print(team.." played "..row..","..col..". ")
checkFed()
starve()
isFed={{false,false,false},{false,false,false},{false,false,false}}
--after giving a chance to capture, see if it was suicide
checkFed()
starve()
opt.labelMsg=dialog.AddLabel(msg)
return true
--fixed indents in Sublime
end
end
if cpuTurn then
----Minerals --width
----Farmland --checking text width
----Crystals --checking text width
--ai("Zergling") --looks more compact in Sans Serif
ai("Terrans")
ai("Protoss")
end
end
until res==-1