Robots Game Autoplay

Problem #356

Tags: lua games special c-1

This task has a Challenge attached.
You may View Stats or read a Help on Challenges.

No translations... yet

This problem again is to be coded in Lua but as you probably have seen the previous task mentioned below, you should be all right with it :)

After we got acquainted with the ancient Robots Game it is natural to try creating algorithm which helps player to escape from robots or at least wreck as many of them as possible!

The rules are slightly different and simpler, after the manner of BSD Robots variation:

Also there are no disintegrating charges this time, but player has teleporting device, which allows to move to the cell symmetrically opposite relative to the centre of the field.

Let's have an example:

Move #1
. . . . . . . . . . . . . . . X . . . .
. . . X . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . @ . . . . . . . . . . . .
. . . . . . . . . . . . . . . X . . . .

Let player move Up three times, then with robots getting always closer, situation changes to this:

Move #4
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . X . . . . . . .
. . . . . . X @ . . . . . . . . . . . .
. . . . . . . . . . . . X . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .

Now player starts moving Right, and after the first such step two robots on the right collide and leave wreckage. Two more steps and player gets close to that heap:

Move #7
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . X @ # . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .

Now player rounds the heap in Up-Right, Down-Right manner and the last robot happily integrates into the wreckage.

Teleporting works the following way. If player was X cells from the left border and Y cells from the top border, after teleporting new position is X cells from the right border and Y cells from the bottom.

Problem Statement

Consider game code below. Note the decision function, into which we get current game state - the field, and how many teleport "jumps" we have yet. In this "manual" program we can print the field, analyze it and produce the instructions to move (using letters U, L, R, D or T for teleport). Actually you are recommended to run this code with lua (perhaps loading it into the online emulator) and play a bit.

Replace the code within this function so that it analyzes situation and returns movement command automatically.

Checker will run your function in several games. To pass you need wreck at least some robots in at least two of the games. Total score is reported as sum of score over all games, each wrecked robot gives you points equal to jumps_remain + 1 - i.e. if you wreck 2 robots before any teleportation is made, you are awarded 8 points for this.

As the checker is appended to your code, make sure you don't submit something preventing it from execution (e.g. it is all right to have function definitions and variable initializations in your code). Don't print or input anything.

show/hide the game code

function decision(field, jumps)
    for _, row in ipairs(field) do print(table.concat(row, ' ')) end
    print('Jumps', jumps)
    return io.read('*l')
end

function sgn(x)
  return (x > 0 and 1 or 0) - (0 > x and 1 or 0)
end

function randPos()
    local x = math.floor(math.random() * cols + 1)
    local y = math.floor(math.random() * rows + 1)
    return x, y
end

function userMove()
    local oldX, oldY = userX, userY
    local ur = decision(field, jumps)
    ur = ur:upper()
    if ur == 'T' then
        if jumps > 0 then
            userX = cols + 1 - userX
            userY = rows + 1 - userY
            jumps = jumps - 1
        end
    else
        local dx, dy = 0, 0
        if ur:find('U') ~= nil then
            dy = -1
        elseif ur:find('D') ~= nil then
            dy = 1
        end
        if ur:find('L') ~= nil then
            dx = -1
        elseif ur:find('R') ~= nil then
            dx = 1
        end
        userX = userX + dx
        userY = userY + dy
    end
    if 1 > userX or userX > cols then userX = oldX end
    if 1 > userY or userY > rows then userY = oldY end
    field[oldY][oldX] = '.'
    if field[userY][userX] ~= '.' then
        return false
    end
    field[userY][userX] = '@'
    return true
end

function robotsMove()
    local newpos = {}
    for y = 1, rows do
        for x = 1, cols do
            if field[y][x] == 'X' then
                field[y][x] = '.'
                table.insert(newpos, {x + sgn(userX - x), y + sgn(userY - y)})
            end
        end
    end
    bots = 0
    for _, p in ipairs(newpos) do
        local x, y = table.unpack(p)
        if field[y][x] == '@' then
            return false
        elseif field[y][x] == 'X' then
            field[y][x] = '#'
            bots = bots - 1
        elseif field[y][x] == '.' then
            field[y][x] = 'X'
            bots = bots + 1
        end
    end
    return true
end

function initField()
    field = {}
    for i = 1, rows do
        local r = {}
        for j = 1, cols do r[j] = '.' end
        field[i] = r
    end
    userX, userY = randPos()
    field[userY][userX] = '@'
    local b = 0
    while b ~= bots do
        local x, y = randPos()
        if field[y][x] == '.' then
            field[y][x] = 'X'
            b = b + 1
        end
    end
end

function gameLoop()
    while true do
        if not userMove() then
            print('lost by hit')
            break
        end
        if not robotsMove() then
            print('lost by capture')
            break
        end
        if bots == 0 then
            print('win')
            break
        end
    end
end

rows = 13
cols = 20
bots = 5
jumps = 3

math.randomseed(os.time())

initField()
gameLoop()
You need to login to get test data and submit solution.