2D Dungeon Crawler

9

1

Your program has to take a multi-lined string, like this:

#############
#           #
#     p     #
#           #
#############

p is the player and # is a block.

Now under that in the terminal should be an input line saying:

How do you want to move?

If the player types l he has to walk left when there isn't a block, else, when there is a block, he can't go through and doesn't move of course, now the output in the terminal has to be updated (and the previous output cleared/overwritten):

#############
#           #
#    p      #
#           #
#############

He can type l for left, r for right, u for up and d for down.

The input will always be multiline, but won't always be padded with spaces into a perfect rectangle. In addition, the hashes can be anywhere in the string, and won't always be connected to each other. For example:

##  ##
#  #
## p
     #

is a valid dungeon. (note the lack of trailing spaces on each line)

If the player goes outside of the string, he doesn't have to be displayed. But if he comes back later, he must be displayed again.

And the boundaries of "outside" the string are the length(longest_line) by number_of_lines rectangle, so even if one line isn't padded with spaces on the right, that location isn't considered out of bounds. Example using the earlier dungeon:

##  ##
#  #p
##  
     #

The second line didn't have a space where the p is now, but that doesn't matter.

Finally, your program must loop forever taking input.

Test cases

Test case 1:

####
# p#
#
####

How do you want to move?
d

####
#  #
# p
####

Test case 2:

####
  p#
   #
####

How do you want to move?
l

####
 p #
   #
####

How do you want to move?
d

####
   #
 p #
####

How do you want to move?
l

####
   #
p  #
####

How do you want to move?
l

####
   #
   #
####

How do you want to move?
r

####
   #
p  #
####

Of course, these aren't complete. Your code should loop forever and clear the screen between each output.

Your output is allowed to prompt for input as How do you want to move?\n<input> or How do you want to move?<input> (i.e. you don't need the input on a blank line), and you don't need a empty line between the final line of the dungeon and the prompt. (they can't be on the same line however)

Standard loopholes are disallowed ! This is code-golf, so the shortest code in bytes wins!

LMD

Posted 2016-12-13T14:53:56.250

Reputation: 377

2Is it acceptable if the input is a letter followed by enter? Also, I suggest getting rid of having to print that string, which doesn't seem to add anything to the challenge – Luis Mendo – 2016-12-13T16:03:45.613

2I think this is re-openable, but my suggestion is that the input prompt (for l, r, u, or d) can be anything, not just "How do you want to move"? It doesn't really affect the answers except for golfyness. – Rɪᴋᴇʀ – 2016-12-14T21:15:25.933

@EasterlyIrk : I wouldnt agree. Because in this case, the golfers will have to think about how to compress the string to save bytes. – LMD – 2016-12-15T13:17:19.670

2

@user7185318 Keep this in mind, basically stick with 1 problem per challenge. Compressing the string is a completely separate problem then making a dungeon crawler, and thus probably shouldn't be tacked on to that challenge.

– Rɪᴋᴇʀ – 2016-12-15T16:47:28.410

Yes, it is. You're right. – LMD – 2016-12-15T17:00:38.957

1Is it acceptable if the player is displayed when they are out of bounds, or do they need to disappear? – MattWH – 2016-12-18T07:15:24.067

Yes, it is. More is always better tahn less. – LMD – 2016-12-18T08:22:27.170

What if a language can't clear the terminal? – Lord Ratte – 2016-12-21T10:49:15.140

No problem. Print out new 'Dungeon' – LMD – 2016-12-22T12:41:47.780

Answers

1

MATLAB, 268 247 246 bytes

Probably not competitive, but it was fun. Golfed version:

function f(s);d=char(split(s,'\n'));[y,x]=ind2sub(size(d),find(d=='p'));while 1;d
c=uint8(input('How do you want to move?','s'))-100;v=y+~c-(c==17);w=x+(c==14)-(c==8);try;d(y,x)=' ';end;try;if'#'==d(v,w);v=y;w=x;end;d(v,w)='p';end;y=v;x=w;clc;end

Readable version:

function f(s)
% Split the string on newlines and convert to a padded char array
d = char(split(s,'\n'));

% Get the initial indices of p
[y,x] = ind2sub(size(d),find(d=='p'));

% Loop forever
while 1
    % Implicitly display the dungeon
    d

    % Get the ASCII of the user input, minus 100 (saves a few bytes in
    % the comparisons)
    c=uint8(input('How do you want to move?','s'))-100;

    % Get the new y from the ASCII
    v = y+~c-(c==17);

    % Get the new x from the ASCII
    w = x+(c==14)-(c==8);

    % Clear the player from the dungeon if they are in it
    try
        d(y,x)=' ';
    end

    % Check if new position is a #, and revert to old position if so
    try
        if '#'==d(v,w)
            v=y;w=x;
        end
        d(v,w)='p';
    end
    % Update x and y
    y=v;
    x=w;

    % Clear the screen
    clc;
end

The try blocks are to prevent the function from crashing on out of bounds errors. I'm sure that two of them is overkill, but I can't golf it down any better than that.

It's worth noting that MATLAB will expand the array downwards and to the right, but the player will disappear when moving to an 'unexplored' area for the first time. For example, if you move outside the dungeon's current boundaries to the right by one space, you will disappear, but next turn MATLAB will expand the array to include the new column (or row, if you are moving downwards). '#'==d(y,x) saves a byte compared to d(y,x)=='#', since you don't need a space between if and '#'

MattWH

Posted 2016-12-13T14:53:56.250

Reputation: 331

Nice answer ! I hope this time not something very short wins, here the common languages should have a chance too, because the bigger the challenge, the better are java etc. :) – LMD – 2016-12-18T11:43:52.840

1

Coffee-script: 580 Bytes

I've squeezed everything I could out of this particular algorithm and my tired brain. I need a holiday.

C=console
e='length'
N=null
f=(S)->
    x=y=X=Y=N
    q=(c,v)->
        X=[x+c,N][+(-1<x+c<w)]
        Y=[y+v,N][+(-1<y+v<h)]
        try L[y+v][x+c]!='#'catch
            1
    r=(s)->
        if (X||Y)
            return
        L[y]=((t=L[y].split '')[x]=s)
        L[y]=t.join ''
    while 1
        L=S.split '\n'
        [h,w]=[L[e],L[0][e]]
        x=[X,x][+(x?)]
        y=[Y,y][+(y?)]
        for k in[0..h*w-1]
            if L[k//h][k%w]=='p'
                x=k%w
                y=k//h
        C.clear()
        C.log S
        r(' ')
        switch prompt("How do you want to move?")
            when'l'
                q(-1,0)&&x--
            when'r'
                q(1,0)&&x++
            when'u'
                q(0,-1)&&y--
            when'd'
                q(0,1)&&y++
        r('p')
        S=L.join '\n'

Lord Ratte

Posted 2016-12-13T14:53:56.250

Reputation: 111

nice solution, Lord Ratte – LMD – 2016-12-22T12:41:04.827