Skip to content

Instantly share code, notes, and snippets.

@taeguk
Last active January 7, 2016 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taeguk/4960f486998132cb2d84 to your computer and use it in GitHub Desktop.
Save taeguk/4960f486998132cb2d84 to your computer and use it in GitHub Desktop.
Lua file for SSM SlimeWar AI Contest
--[[
Slime War Battle AI by taeguk
Recent modified in 2015-07-18
]]--
-- [applied methods]
-- Board:moveQSlime(fromx,fromy,tox,toy)
-- Board:moveSlime(fromx,fromy,tox,toy,number)
-- Board:getSlime(x,y)
-- Board:getTerritory(x,y)
-- Board:getMyQueenX()
-- Board:getMyQueenY()
-- Board:getEnemyQueenX()
-- Board:getEnemyQueenY()
-- global variables
eX = {1,1,9,9}
eY = {1,9,1,9}
homeX = 1
homeY = 1
b_dx = {0,-1,1,0}
b_dy = {1,0,0,-1}
dx = {}
dy = {}
prevQX = Board:getMyQueenX()
prevQY = Board:getMyQueenY()
queenFlag = 1
edgeFlag = false
edgeX = 1
edgeY = 1
spreadFlag = true
-- functions
function moveQueenCenter()
local qX = Board:getMyQueenX()
local qY = Board:getMyQueenY()
local tX = 5 tY = 5
local mDist = 11111
local mIdx = 1
for i=1,4 do
local nx = qX + dx[i]
local ny = qY + dy[i]
local dist = math.abs(tX-nx) + math.abs(tY-ny)
if not (nx < 1 or nx > 9 or ny < 1 or ny > 9) and dist < mDist then
mDist = dist
mIdx = i
end
end
if mDist <= 0 then
queenFlag = queenFlag + 1
end
Board:moveQSlime(qX, qY, qX + dx[mIdx], qY + dy[mIdx])
end
function moveQueenEdge()
local qX = Board:getMyQueenX()
local qY = Board:getMyQueenY()
local mX = qX - 1 < 9 - qX and 1 or (qX - 1 > 9 - qX and 9 or homeX)
local mY = qY - 1 < 9 - qY and 1 or (qY - 1 > 9 - qY and 9 or homeY)
if not edgeFlag then
if prevQX == qX then
edgeX = mX
edgeY = qY
else
edgeX = qX
edgeY = mY
end
edgeFlag = true
end
local cDist = math.abs(qX-edgeX) + math.abs(qY-edgeY)
if cDist <= 1 then
queenFlag = queenFlag + 1
end
for i = 1, 4 do
local nx = qX + dx[i]
local ny = qY + dy[i]
local nDist = math.abs(nx-edgeX) + math.abs(ny-edgeY)
if not (nx < 1 or nx > 9 or ny < 1 or ny > 9) and nDist < cDist then
Board:moveQSlime(qX, qY, nx, ny)
break
end
end
end
function moveQueenCorner()
local qX = Board:getMyQueenX()
local qY = Board:getMyQueenY()
local cDist = math.abs(qX-homeX) + math.abs(qY-homeY)
if cDist <= 1 then
queenFlag = queenFlag + 1
end
for i = 1, 4 do
local nx = qX + dx[i]
local ny = qY + dy[i]
local nDist = math.abs(nx-homeX) + math.abs(ny-homeY)
if not (nx < 1 or nx > 9 or ny < 1 or ny > 9) and nDist < cDist then
Board:moveQSlime(qX, qY, nx, ny)
break
end
end
return true
end
function escapeQueen()
local qX = Board:getMyQueenX()
local qY = Board:getMyQueenY()
local bDist = -1
local bX = qX bY = qY
for x=1,9 do
for y=1,9 do
if Board:getSlime(x,y) >= 0 then
local mDist = 11111
for i=1,9 do
for j=1,9 do
if Board:getSlime(i,j) < 0 then
local dist = math.abs(x-i) + math.abs(y-j)
if dist < mDist then mDist = dist end
end
end -- j loop
end -- i loop
if mDist > bDist then
bDist = mDist
bX = x
bY = y
end
end
end -- y loop
end -- x loop
local mDist = 11111
local mIdx = 1
for i=1,4 do
local nx = qX + dx[i]
local ny = qY + dy[i]
local dist = math.abs(bX-nx) + math.abs(bY-ny)
if not (nx < 1 or nx > 9 or ny < 1 or ny > 9) and Board:getSlime(nx,ny) >= 0 and dist < mDist then
mDist = dist
mIdx = i
end
end
Board:moveQSlime(qX, qY, qX + dx[mIdx],qY + dy[mIdx])
end
function mergeMode()
local qX = Board:getMyQueenX()
local qY = Board:getMyQueenY()
for x = 1, 9 do
for y = 1, 9 do
if Board:getSlime(x,y) > 0 then
local cDist = math.abs(x-qX) + math.abs(y-qY)
local mx = {} my = {}
local cnt = 0
for i = 1, 4 do
local nx = x + dx[i]
local ny = y + dy[i]
local nDist = math.abs(nx-qX) + math.abs(ny-qY)
if nDist <= cDist and not (nx < 1 or nx > 9 or ny < 1 or ny > 9) then
cnt = cnt + 1
mx[cnt] = nx
my[cnt] = ny
end
end
for i = 1, cnt do
Board:moveSlime(x, y, mx[i], my[i], math.floor((Board:getSlime(x,y)-1)/cnt))
end
end
end
end
end
function spreadMode()
local qX = homeX
local qY = homeY
for x = 1, 9 do
for y = 1, 9 do
if Board:getSlime(x,y) > 0 then
local cDist = math.abs(x-qX) + math.abs(y-qY)
local mx = {} my = {}
local cnt = 0
local gCnt = 0
for i = 1, 4 do
local nx = x + dx[i]
local ny = y + dy[i]
local nDist = math.abs(nx-qX) + math.abs(ny-qY)
if not (nx < 1 or nx > 9 or ny < 1 or ny > 9) and (Board:getSlime(nx,ny) <= 0 or nDist > cDist) then
cnt = cnt + 1
mx[cnt] = nx
my[cnt] = ny
if Board:getSlime(nx,ny) == 0 then
gCnt = gCnt + 1
mx[cnt], mx[gCnt] = mx[gCnt], mx[cnt]
my[cnt], my[gCnt] = my[gCnt], my[cnt]
end
end
end
local dn = cnt < Board:getSlime(x,y)-1 and cnt or Board:getSlime(x,y)-1
for i = 1, dn do
if Board:getSlime(mx[i],my[i]) >= 0 or (math.abs(Board:getSlime(mx[i],my[i])) < math.floor((Board:getSlime(x,y)-1)/dn)) then
Board:moveSlime(x, y, mx[i], my[i], math.floor((Board:getSlime(x,y)-1)/dn))
end
end
end
end
end
end
function attackMode()
local qX = Board:getEnemyQueenX()
local qY = Board:getEnemyQueenY()
for x = 1, 9 do
for y = 1, 9 do
if Board:getSlime(x,y) > 0 then
local cDist = math.abs(x-qX) + math.abs(y-qY)
local mIdx = 1
local mDist = 11111
for i = 1, 4 do
local nx = x + dx[i]
local ny = y + dy[i]
local nDist = math.abs(nx-qX) + math.abs(ny-qY)
if nx == qX and ny == qY then
Board:moveSlime(x,y,nx,ny,math.floor((Board:getSlime(x,y)-1)/3))
end
if nDist < mDist and not (nx < 1 or nx > 9 or ny < 1 or ny > 9) then
mDist = nDist
mIdx = i
end
end
if Board:getSlime(x+dx[mIdx],y+dy[mIdx]) >= 0 or (math.abs(Board:getSlime(x+dx[mIdx],y+dy[mIdx])) < math.floor(Board:getSlime(x,y)-1)) then
Board:moveSlime(x, y, x+dx[mIdx], y+dy[mIdx], math.floor(Board:getSlime(x,y)-1))
end
end
end
end
end
function detectEnemy()
local qX = Board:getMyQueenX()
local qY = Board:getMyQueenY()
for i=-1,1 do
for j=-1,1 do
local nx = qX + i
local ny = qY + j
if not (nx < 1 or nx > 9 or ny < 1 or ny > 9) and Board:getSlime(nx,ny) < 0 then
return true
end
end
end
return false
end
function defendMode()
local qX = Board:getMyQueenX()
local qY = Board:getMyQueenY()
for x = 1, 9 do
for y = 1, 9 do
if Board:getSlime(x,y) > 0 then
local mIdx = 1
local mDist = 11111
local flag = true
for i=1,4 do
local nx = x + dx[i]
local ny = y + dy[i]
local nDist = math.abs(nx-qX) + math.abs(ny-qY)
if not (nx < 1 or nx > 9 or ny < 1 or ny > 9) and (flag or Board:getSlime(nx,ny) < 0) and nDist <= mDist then
mDist = nDist
mIdx = i
if Board:getSlime(nx,ny) < 0 then
flag = false
end
end
end
Board:moveSlime(x, y, x+dx[mIdx], y+dy[mIdx], math.floor(Board:getSlime(x,y)-1))
end
end
end
end
function randomConstants()
local rIdxs = {}
local check = {false, false, false, false}
local idx = 1
while idx <= 4 do
local n = math.random(1,4)
if not check[n] then
check[n] = true
rIdxs[idx] = n
idx = idx + 1
end
end
for i=1,4 do
dx[i] = b_dx[rIdxs[i]]
dy[i] = b_dy[rIdxs[i]]
end
end
function init()
local qX = Board:getMyQueenX()
local qY = Board:getMyQueenY()
local mIdx = 1
local mDist = 11111
randomConstants()
for i=1,4 do
local dist = math.abs(eX[i]-qX) + math.abs(eY[i]-qY)
if dist < mDist then
mDist = dist
mIdx = i
end
end
homeX = eX[mIdx]
homeY = eY[mIdx]
end
function checkSparse()
local cnt = 0
for i=1,9 do
for j=1,9 do
if Board:getSlime(i,j) == 0 then
cnt = cnt + 1
end
end
end
if cnt <= 5 then
spreadFlag = false
end
end
function main()
for indexTurn = 1, 100 do
local b_prevQX = Board:getMyQueenX()
local b_prevQY = Board:getMyQueenY()
randomConstants()
if queenFlag == 1 then moveQueenCenter()
elseif queenFlag == 2 then moveQueenEdge()
elseif queenFlag == 3 then moveQueenCorner()
else escapeQueen()
end
if detectEnemy() then defendMode()
elseif spreadFlag and indexTurn < 20 then checkSparse() spreadMode()
else attackMode()
end
prevQX = b_prevQX
prevQY = b_prevQY
nextTurn()
end
end
-- The flow of code starts here
init()
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment