Problem #356
Tags:
lua
games
special
c-1
This task has a Challenge attached.
You may
View Stats
or read a Help on Challenges.
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.
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.
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()