Can the cursor reach the bottom?

APL (Dyalog Unicode), 60 bytesSBCS

Full program. Prompts for character matrix from stdin. Prints 1 or 0 to stdout. Requires zero-indexing (⎕IO←0) which is default on many systems.

P←{' '0∊⍨s←(×⍨≢⍺)⊃,⍵:1∊⍵⋄s}
1∊⊢⌿{P⌺3 3⊢(⍴⍵)⍴1@0P⌺3,⍵}⍣≡3/3⌿⎕

Try it online! (space characters replaced by for clarity)

The method here is basically to seed fill from the top left corner, but alternating between 1D and 2D seed fill to account for line wrapping and vertical/diagonal motion. Diagonal motion is simple horizontal motion followed by vertical motion, since the cursor sits in between adjacent characters.

The first line defines a helper function P(rocess) which will be called on each neighbourhood.

P←{} "dfn"; is the neighborhood, is the number of padded elements for each dimension:

,⍵ ravel (flatten) the neighbourhood into a list

()⊃ pick the following element from that:

   the paddings per dimension (so a 1 or 2 element list, depending on being 1D or 2D)

   the tally of that (1 or 2)

  ×⍨ the square of that (lit. multiplication selfie; 1 or 4)

s← assign to s(elf; i.e. the centre of the neighbourhood)

' '0∊⍨ is that a member of [" ",0]?

: if so:

  1∊⍵ return whether the neighbourhood has a one


  s return s(elf unmodified, i.e. leave as-is for now)

The second line is the main part of the program:

 prompt for evaluated input via the console (stdin)

3⌿ triplicate each row (ensures we have at least 3 — makes no difference to connectivity)

3/ triplicate each column (ensures we have at least 3 — makes no difference to connectivity)

{}⍣≡ apply this function repeatedly until two successive results are identical (i.e. until stable):

,⍵ ravel (flatten) the matrix into a list

P⌺3 apply P to each neighbourhood of 3 elements

1@0 replace the current value at position 0 with a 1 (this seeds the top left corner)

()⍴reshape that into the following shape:

  ⍴⍵ the original shape of the matrix

⊢⌿ get the bottom row (lit. vertical right-reduction)

1∊ is there any 1 there?

Jelly, 47 43 bytes


Try it online!

A full program that takes a list of strings as its argument and returns 1 if the bottom line is reachable and 0 if not.


Helper link

Test moves up, down left and right and extend reachable position list. Left argument: most recently added reachable position list; right argument: boolean list of whether each possible position is valid

 p®            | Cartesian product with each of the values stored in the register (the width of the position list, 1 and the negation of each)
   §           | Sum each of these
    F          | Flatten
     Q         | Uniquify
      æ%L}     | Symmetric mod using the length of the valid position list: this will mean any positions that move off the top or bottom will be negative
          >Ƈ0  | Filter out those reachable positions which are negative
            ịƇ | Filter out those which are invalid

Main link

Takes a single argument, a list of Jelly strings representing the grid

=⁶                             | Check of equal to space
   oŻ$€                        | Logical or each row with itself prepended with zero; this yields rows 1 longer, and will indicate whether each cursor position is valid
       µ                       | Start a new monadic chain
        ZL                     | Zip and get the length (will be the length of each row)
          ;1                   | Concatenate 1
            ;N$©               | Concatenate the negations and store in the register (i.e. width, 1, -width, -1)
                ṛF             | Replace with the flattened grid of position validity
                  1çƬ          | Call the helper link, starting with 1 as left argument and using the flattened position validities as right. Repeat until unchanged. Return all collected values. 
                     F         | Flatten, getting all reachable positions (may include duplicates)
                      Ṁ        | Maximum position reached
                       ’       | Decrease by 1 (because of 1-indexing)
                        :®     | Integer divide by the register
                          Ḣ    | Head (will effectively be max position integer divided by width)
                           ‘   | Increase by 1
                            =L | Check if equal to length (i.e. height) of position grid