Does the fishy road have an end?

Non-compliant ><> answer

You wanted ><>, I give you ><> !

I believe the only sane way to do this in ><> is by copying the input in the codespace and letting the interpreter decide by itself if the input leads somewhere. Since ><> doesn't implement threading anymore, that leaves us with a big problem : if the input has a loop, we'll get stuck into it.

These considerations taken into account, I decided to make a solution compatible with ><> online interpreter so that it would be possible to assert if the interpreter is stuck in the input or just taking ages to do everything. I also had to add trailing lines to the code so the online interpreter shows the added code and doesn't crash when trying to write to it.

Oh and since I'm clearly disqualified by now, I didn't bother with golfing the code.

Without further ado, the code in all its glory :

50i:0(?v   :"^"=?v:"v"=?v:">"=?v:"<"=?v:"/"=?v:"\"=?v:"|"=?v:"-"=?va=?v1+10.
>.!603f<         v"."~                                     <      <   >~1+010.
>.!01+1p}:$}:}v! <      <      <      <      <      <
  ;oooo"true" <<
              ^

To use it, copy it in the online interpreter, add enough trailing lines to handle your input, submit the code, give it the input as ;-separated lines and enjoy the ride.

A few tests :

With

+--------------------+
|>\/  this way >\/>  | this one ends here
| v^            \/   |
| v^   ^.^           |
| \/\         >v     |
| /\/         ^<     |
+--------------------+` 

Final codespace :

50i:0(?v   :"^"=?v:"v"=?v:">"=?v:"<"=?v:"/"=?v:"\"=?v:"|"=?v:"-"=?va=?v1+10.
>.!603f<         v"."~                                     <      <   >~1+010.
>.!01+1p}:$}:}v! <      <      <      <      <      <
  ;oooo"true" <<
            ^
 ....................
.>\/           >\/>  .                   
. v^            \/   .
. v^   ^ ^           .
. \/\         >v     .
. /\/         ^<     .
 ....................

Outputs "true" and stops.


With

+--------+
|>>\ This|
|\\   is |
|  \\ a  |
| \ /trap| 
+--------+

Final codespace :

50i:0(?v   :"^"=?v:"v"=?v:">"=?v:"<"=?v:"/"=?v:"\"=?v:"|"=?v:"-"=?va=?v1+10.
>.!603f<         v"."~                                     <      <   >~1+010.
>.!01+1p}:$}:}v! <      <      <      <      <      <
  ;oooo"true" <<
            ^
 ........ 
.>>\     .
.\\      .
.  \\    .
. \ /    .
 ........

Loops forever.


JavaScript, ES6, 177 161 145 bytes

f=(s,i=1,M=[],D)=>D==5||!~M[O="indexOf"](D+i)&&f(s,i-[M.push(D+i),L=s[O]('|'),-L,1,-1][D=`431255${5-D+'X3412'[D]}`['><^v-|/\\'[O](s[i+L])]||D],M,D)

We can detect a cycle by traversing the path and detecting a repeat of the tuple

  • location
  • coming-from direction

That is, if we are entering some position (x,y) coming from some direction D for the second time, we know that this cycle will repeat forever. Therefore, the code keeps track of all locations that were visited, and from what direction, and checks against that record each time a new space is visited.

The directions up, down, left, and right are assigned the numbers 1, 2, 3, and 4. The code considers the current symbol being visited (s[i+L]) and changes the current direction (D), then the new direction is used to recursively call the function and evaluate the next space. 5 as a direction indicates a wall, and a true termination of the program.

Here is an explanation of less-golfed code:

f=
(s,     // input string
 i=1,   // current location as offset string index
 M=[],  // record of previously visited spaces
 D      // current direction
  )=>(
    L=s[O="indexOf"]('|'), // find arena width `L` by index of first `|`

    // if D is 5, return true, or...
    D==5 ||

    // if direction + position is not new, return false
    !~M[O](D+i) &&

    // otherwise, save this direction + position
    M.push(D+i) &&

    // recursively call `f` with new direction and position
    f(s,
      i-[,L,-L,1,-1][D=            // modify position based on active direction
        `431255${5-D+'X3412'[D]}`  // from these possible directions...
          [                        // chose the one at the index...
            '><^v-|/\\'[O](        // based on the index of the symbol 
                           s[i+L]  // of the current character
                                 )
          ]
        ||D     // or preserve old D if symbol is not directional
      ],
      M,D)

The template string `431255${5-D+'X3412'[D]}` has a nested expression that handles the mirrors: because the directions are numbers, they can also be used as indexes. The expression 'X3412'[D], evaluates to the 8th character in the possible-direction string, and so corresponds to \, the 8th character in the symbol string '><^v-|/\\'). The expression says,

  • If current direction D is 1 (up), then the new direction on hitting a \ mirror will be 3 (left)
  • If current direction D is 2 (down), then the new direction on hitting a \ mirror will be 4 (right)
  • etc.

The other mirror / would use the expression 'X4321'[D], but since that's simply an ordered count-down from 4, we can express it more simply as 5-D.