content: package rabbitescape.engine.logic;
  
  import static org.hamcrest.CoreMatchers.*;
  import static org.hamcrest.MatcherAssert.*;
  import static rabbitescape.engine.textworld.TextWorldManip.*;
  import static rabbitescape.engine.util.WorldAssertions.*;
  import static rabbitescape.engine.Tools.*;
  import static rabbitescape.engine.Rabbit.Type.*;
  
  import org.junit.Test;
  
  import rabbitescape.engine.Direction;
  import rabbitescape.engine.Rabbit;
  import rabbitescape.engine.World;
  
  public class TestBridging
  {
      @Test
      public void Bridge_on_the_flat()
      {
          assertWorldEvolvesLike(
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              " ri         ij " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "  rB       Ej  " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "  r[       ]j  " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "  r{       }j  " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "    B     E    " + "\n" +
              "   r       j   " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "    [     ]    " + "\n" +
              "   r       j   " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "               " + "\n" +
              "    {     }    " + "\n" +
              "   r       j   " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "     B   E     " + "\n" +
              "    r     j    " + "\n" +
              "   (       )   " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "     [   ]     " + "\n" +
              "    r     j    " + "\n" +
              "   (       )   " + "\n" +
              "###############",
  
              "               " + "\n" +
              "               " + "\n" +
              "     {   }     " + "\n" +
              "    r     j    " + "\n" +
              "   (       )   " + "\n" +
              "###############",
  
              "               " + "\n" +
              "      ' !      " + "\n" +
              "     r   j     " + "\n" +
              "    (     )    " + "\n" +
              "   (       )   " + "\n" +
              "###############",
  
              "               " + "\n" +
              "      r j      " + "\n" +
              "     (f f)     " + "\n" +
              "    ( f f )    " + "\n" +
              "   (       )   " + "\n" +
              "###############"
          );
      }
  
      @Test
      public void Bridge_on_an_up_slope()
      {
          assertWorldEvolvesLike(
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "  i           i  " + "\n" +
              "r /           \\ j" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              " r~           `j " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "   B         E   " + "\n" +
              "  r           j  " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "   [         ]   " + "\n" +
              "  r           j  " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "   {         }   " + "\n" +
              "  r           j  " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "    B       E    " + "\n" +
              "   r         j   " + "\n" +
              "  /           \\  " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "    [       ]    " + "\n" +
              "   r         j   " + "\n" +
              "  /           \\  " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "    {       }    " + "\n" +
              "   r         j   " + "\n" +
              "  /           \\  " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "     B     E     " + "\n" +
              "    r       j    " + "\n" +
              "   (         )   " + "\n" +
              "  /           \\  " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "     [     ]     " + "\n" +
              "    r       j    " + "\n" +
              "   (         )   " + "\n" +
              "  /           \\  " + "\n" +
              "#################",
  
              "                 " + "\n" +
              "     {     }     " + "\n" +
              "    r       j    " + "\n" +
              "   (         )   " + "\n" +
              "  /           \\  " + "\n" +
              "#################",
  
              "      '   !      " + "\n" +
              "     r     j     " + "\n" +
              "    (       )    " + "\n" +
              "   (         )   " + "\n" +
              "  /           \\  " + "\n" +
              "#################",
  
              "      r   j      " + "\n" +
              "     (f   f)     " + "\n" +
              "    ( f   f )    " + "\n" +
              "   (         )   " + "\n" +
              "  /           \\  " + "\n" +
              "#################"
          );
      }
  
      @Test
      public void Bridge_on_a_down_slope()
      {
          assertWorldEvolvesLike(
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "ri             ij" + "\n" +
              "#\\             /#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "#rB           Ej#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "#r[           ]j#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "#r{           }j#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "   B         E   " + "\n" +
              "#\\r           j/#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "   [         ]   " + "\n" +
              "#\\r           j/#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "                 " + "\n" +
              "   {         }   " + "\n" +
              "#\\r           j/#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "    B       E    " + "\n" +
              "   r         j   " + "\n" +
              "#\\(           )/#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "    [       ]    " + "\n" +
              "   r         j   " + "\n" +
              "#\\(           )/#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "                 " + "\n" +
              "    {       }    " + "\n" +
              "   r         j   " + "\n" +
              "#\\(           )/#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "     '     !     " + "\n" +
              "    r       j    " + "\n" +
              "   (         )   " + "\n" +
              "#\\(           )/#" + "\n" +
              "##\\           /##" + "\n" +
              "#################",
  
              "                 " + "\n" +
              "     r     j     " + "\n" +
              "    (f     f)    " + "\n" +
              "   ( f     f )   " + "\n" +
              "#\\(           )/#" + "\n" +
              "##\\           /##" + "\n" +
              "#################"
          );
      }
  
      @Test
      public void Stop_bridging_when_hit_a_wall()
      {
          assertWorldEvolvesLike(
              "#          #" + "\n" +
              "# ij    ri #" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#Ej      rB#" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#]j      r[#" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#}j      r{#" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#|        ?#" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#r_      +j#" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#)r>    <j(#" + "\n" +
              "############"
          );
      }
  
      @Test
      public void Dont_stop_bridging_when_2_above_head_at_start()
      {
          assertWorldEvolvesLike(
              "# #      # #" + "\n" +
              "#          #" + "\n" +
              "# ij    ri #" + "\n" +
              "############",
  
              "# #      # #" + "\n" +
              "#          #" + "\n" +
              "#Ej      rB#" + "\n" +
              "############"
          );
      }
  
      @Test
      public void Can_bridge_out_from_under_block()
      {
          assertWorldEvolvesLike(
              "#          #" + "\n" +
              "# #        #" + "\n" +
              "#ri        #" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "# #        #" + "\n" +
              "# rB       #" + "\n" +
              "############"
          );
      }
  
      @Test
      public void Dont_bridge_when_hit_head_in_front_at_start()
      {
          assertWorldEvolvesLike(
              "##        ##" + "\n" +
              "# ij    ri #" + "\n" +
              "############",
  
              "##        ##" + "\n" +
              "#<i      i>#" + "\n" +
              "############"
          );
      }
  
      @Test
      public void Two_rabbits_next_to_each_other_bridge_next_to_each_other()
      {
          assertWorldEvolvesLike(
              "#           " + "\n" +
              "#           " + "\n" +
              "#           " + "\n" +
              "#rrii       " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#           " + "\n" +
              "#           " + "\n" +
              "# r>B       " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#           " + "\n" +
              "#           " + "\n" +
              "#  r[       " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#           " + "\n" +
              "#           " + "\n" +
              "#  r{B      " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#           " + "\n" +
              "#    B      " + "\n" +
              "#   r[      " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#           " + "\n" +
              "#    [      " + "\n" +
              "#   r{      " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#           " + "\n" +
              "#    {B     " + "\n" +
              "#   rr      " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#     B     " + "\n" +
              "#    r[     " + "\n" +
              "#   (r      " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#     [     " + "\n" +
              "#    r{     " + "\n" +
              "#   (r      " + "\n" +
              "############",
  
              "#           " + "\n" +
              "#     {B    " + "\n" +
              "#    rr     " + "\n" +
              "#   ((      " + "\n" +
              "############"
          );
      }
  
      @Test
      public void Stop_bridging_when_hit_head_here_later()
      {
          assertWorldEvolvesLike(
              "#  #    #  #" + "\n" +
              "#          #" + "\n" +
              "#   ijri   #" + "\n" +
              "############",
  
              "#  #    #  #" + "\n" +
              "#          #" + "\n" +
              "#  Ej  rB  #" + "\n" +
              "############",
  
              "#  #    #  #" + "\n" +
              "#          #" + "\n" +
              "#  ]j  r[  #" + "\n" +
              "############",
  
              "#  #    #  #" + "\n" +
              "#          #" + "\n" +
              "#  }j  r{  #" + "\n" +
              "############",
  
              "#  #    #  #" + "\n" +
              "# !      ' #" + "\n" +
              "#  j    r  #" + "\n" +
              "############"
          );
      }
  
      @Test
      public void Stop_bridging_when_hit_head_in_front_later()
      {
          assertWorldEvolvesLike(
              "# #      # #" + "\n" +
              "#          #" + "\n" +
              "#   ijri   #" + "\n" +
              "############",
  
              "# #      # #" + "\n" +
              "#          #" + "\n" +
              "#  Ej  rB  #" + "\n" +
              "############",
  
              "# #      # #" + "\n" +
              "#          #" + "\n" +
              "#  ]j  r[  #" + "\n" +
              "############",
  
              "# #      # #" + "\n" +
              "#          #" + "\n" +
              "#  }j  r{  #" + "\n" +
              "############",
  
              "# #      # #" + "\n" +
              "# !      ' #" + "\n" +
              "#  j    r  #" + "\n" +
              "############"
          );
      }
  
      // TODO: Stop_bridging_when_hit_a_ceiling
  
      @Test
      public void Stop_bridging_when_skim_a_wall_top()
      {
          assertWorldEvolvesLike(
              "            " + "\n" +
              "#          #" + "\n" +
              "#  ij  ri  #" + "\n" +
              "############",
  
              "            " + "\n" +
              "#          #" + "\n" +
              "# Ej    rB #" + "\n" +
              "############",
  
              "            " + "\n" +
              "#          #" + "\n" +
              "# ]j    r[ #" + "\n" +
              "############",
  
              "            " + "\n" +
              "#          #" + "\n" +
              "# }j    r{ #" + "\n" +
              "############",
  
              "            " + "\n" +
              "#E        B#" + "\n" +
              "# j      r #" + "\n" +
              "############",
  
              "            " + "\n" +
              "#]        [#" + "\n" +
              "# j      r #" + "\n" +
              "############",
  
              "            " + "\n" +
              "#}        {#" + "\n" +
              "# j      r #" + "\n" +
              "############",
  
              "!          '" + "\n" +
              "#j        r#" + "\n" +
              "# )      ( #" + "\n" +
              "############"
          );
      }
  
      @Test
      public void Stop_bridging_when_join_opposite_bridge_long()
      {
          assertWorldEvolvesLike(
              "#   (   )   #" + "\n" +
              "#  (     )  #" + "\n" +
              "# ( ij ri ) #" + "\n" +
              "#############",
  
              "#   (   )   #" + "\n" +
              "#  (     )  #" + "\n" +
              "# (Ej   rB) #" + "\n" +
              "#############",
  
              "#   (   )   #" + "\n" +
              "#  (     )  #" + "\n" +
              "# (]j   r[) #" + "\n" +
              "#############",
  
              "#   (   )   #" + "\n" +
              "#  (     )  #" + "\n" +
              "# (}j   r{) #" + "\n" +
              "#############",
  
              "#   (   )   #" + "\n" +
              "#  (     )  #" + "\n" +
              "# mj     r& #" + "\n" +
              "#############"
          );
      }
  
      @Test
      public void Dont_bridge_and_turn_when_hit_back_slope()
      {
          assertWorldEvolvesLike(
              "#   /   \\   #" + "\n" +
              "#  /     \\  #" + "\n" +
              "# / ij ri \\ #" + "\n" +
              "#############",
  
              "#   /   \\   #" + "\n" +
              "#  /     \\  #" + "\n" +
              "# /<i   i>\\ #" + "\n" +
              "#############",
  
              "#   /   \\   #" + "\n" +
              "#  /     \\  #" + "\n" +
              "# /|i   i?\\ #" + "\n" +
              "#############"
          );
      }
  
      @Test
      public void Stop_bridging_and_turn_when_hit_back_slope_later()
      {
          assertWorldEvolvesLike(
              "#   /       \\   #" + "\n" +
              "#  /         \\  #" + "\n" +
              "# /   ij ri   \\ #" + "\n" +
              "#################",
  
              "#   /       \\   #" + "\n" +
              "#  /         \\  #" + "\n" +
              "# /  Ej   rB  \\ #" + "\n" +
              "#################",
  
              "#   /       \\   #" + "\n" +
              "#  /         \\  #" + "\n" +
              "# /  ]j   r[  \\ #" + "\n" +
              "#################",
  
              "#   /       \\   #" + "\n" +
              "#  /         \\  #" + "\n" +
              "# /  }j   r{  \\ #" + "\n" +
              "#################",
  
              "#   /       \\   #" + "\n" +
              "#  /!       '\\  #" + "\n" +
              "# /  j     r  \\ #" + "\n" +
              "#################"
          );
      }
  
      @Test
      public void Stop_bridging_when_join_opposite_bridge_short()
      {
          assertWorldEvolvesLike(
              "#           #" + "\n" +
              "# ( ij ri ) #" + "\n" +
              "#############",
  
              "#           #" + "\n" +
              "# (Ej   rB) #" + "\n" +
              "#############",
  
              "#           #" + "\n" +
              "# (]j   r[) #" + "\n" +
              "#############",
  
              "#           #" + "\n" +
              "# (}j   r{) #" + "\n" +
              "#############",
  
              "#           #" + "\n" +
              "# mj     r& #" + "\n" +
              "#############"
          );
      }
  
      @Test
      public void Stop_bridging_when_join_opposite_bridge_long_later()
      {
          assertWorldEvolvesLike(
              "#   (       )   #" + "\n" +
              "#  (         )  #" + "\n" +
              "# (   ij ri   ) #" + "\n" +
              "#################",
  
              "#   (       )   #" + "\n" +
              "#  (         )  #" + "\n" +
              "# (  Ej   rB  ) #" + "\n" +
              "#################",
  
              "#   (       )   #" + "\n" +
              "#  (         )  #" + "\n" +
              "# (  ]j   r[  ) #" + "\n" +
              "#################",
  
              "#   (       )   #" + "\n" +
              "#  (         )  #" + "\n" +
              "# (  }j   r{  ) #" + "\n" +
              "#################",
  
              "#   (       )   #" + "\n" +
              "#  (E       B)  #" + "\n" +
              "# (  j     r  ) #" + "\n" +
              "#################",
  
              "#   (       )   #" + "\n" +
              "#  (]       [)  #" + "\n" +
              "# (  j     r  ) #" + "\n" +
              "#################",
  
              "#   (       )   #" + "\n" +
              "#  (}       {)  #" + "\n" +
              "# (  j     r  ) #" + "\n" +
              "#################",
  
              "#   (       )   #" + "\n" +
              "#  mj       r&  #" + "\n" +
              "# (  )     (  ) #" + "\n" +
              "#################"
          );
      }
  
      @Test
      public void Stop_bridging_when_offset_join_opposite_bridge_long_later()
      {
          assertWorldEvolvesLike(
              "#   (    )   #" + "\n" +
              "#  (      )  #" + "\n" +
              "# (  ijri  ) #" + "\n" +
              "##############",
  
              "#   (    )   #" + "\n" +
              "#  (      )  #" + "\n" +
              "# ( Ej  rB ) #" + "\n" +
              "##############",
  
              "#   (    )   #" + "\n" +
              "#  (      )  #" + "\n" +
              "# ( ]j  r[ ) #" + "\n" +
              "##############",
  
              "#   (    )   #" + "\n" +
              "#  (      )  #" + "\n" +
              "# ( }j  r{ ) #" + "\n" +
              "##############",
  
              // Build a bridge and leave an annoying gap
              "#   (    )   #" + "\n" +
              "#  !      '  #" + "\n" +
              "# ( j    r ) #" + "\n" +
              "##############",
  
              "#   (    )   #" + "\n" +
              "#  j      r  #" + "\n" +
              "# (f)    (f) #" + "\n" +
              "##############"
          );
      }
  
      @Test
      public void Stop_bridging_when_join_opposite_bridge_short_later()
      {
          assertWorldEvolvesLike(
              "#              #" + "\n" +
              "#  (        )  #" + "\n" +
              "# (   ijri   ) #" + "\n" +
              "################",
  
              "#              #" + "\n" +
              "#  (        )  #" + "\n" +
              "# (  Ej  rB  ) #" + "\n" +
              "################",
  
              "#              #" + "\n" +
              "#  (        )  #" + "\n" +
              "# (  ]j  r[  ) #" + "\n" +
              "################",
  
              "#              #" + "\n" +
              "#  (        )  #" + "\n" +
              "# (  }j  r{  ) #" + "\n" +
              "################",
  
              "#              #" + "\n" +
              "#  (E      B)  #" + "\n" +
              "# (  j    r  ) #" + "\n" +
              "################",
  
              "#              #" + "\n" +
              "#  (]      [)  #" + "\n" +
              "# (  j    r  ) #" + "\n" +
              "################",
  
              "#              #" + "\n" +
              "#  (}      {)  #" + "\n" +
              "# (  j    r  ) #" + "\n" +
              "################",
  
              "#              #" + "\n" +
              "#  mj      r&  #" + "\n" +
              "# (  )    (  ) #" + "\n" +
              "################"
          );
      }
  
      @Test
      public void Walker_immediately_behind_bridger_continues_past()
      {
          assertWorldEvolvesLike(
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#rri    #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#       #" + "\n" +
              "# r>B   #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#  r[   #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#  r{>  #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#    B  #" + "\n" +
              "#   rr> #" + "\n" +
              "#########"
          );
      }
  
      @Test
      public void Walker_2_behind_bridger_continues_past()
      {
          assertWorldEvolvesLike(
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#r ri   #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#       #" + "\n" +
              "# r>rB  #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#  r>[  #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#   r{  #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#     B #" + "\n" +
              "#    r> #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#     [ #" + "\n" +
              "#    rr>#" + "\n" +
              "#########"
          );
      }
  
      @Test
      public void Walker_3_behind_bridger_climbs_and_falls()
      {
          assertWorldEvolvesLike(
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#r  ri    #" + "\n" +
              "###########",
  
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#         #" + "\n" +
              "# r> rB   #" + "\n" +
              "###########",
  
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#  r>r[   #" + "\n" +
              "###########",
  
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#   r>{   #" + "\n" +
              "###########",
  
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#      B  #" + "\n" +
              "#    r~   #" + "\n" + // Climbs on
              "###########",
  
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#      [  #" + "\n" +
              "#     r   #" + "\n" + // Jumps off end
              "###########",
  
              "#         #" + "\n" +
              "#         #" + "\n" +
              "#      {  #" + "\n" +
              "#     rf  #" + "\n" + // Falls
              "###########",
  
              "#         #" + "\n" +
              "#       B #" + "\n" +
              "#      r  #" + "\n" +
              "#     (r> #" + "\n" + // Walks away
              "###########"
          );
      }
  
      @Test
      public void Walker_4_behind_bridger_climbs_and_falls()
      {
          assertWorldEvolvesLike(
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#r   ri    #" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#          #" + "\n" +
              "# r>  rB   #" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#  r> r[   #" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#   r>r{   #" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#       B  #" + "\n" +
              "#    r>r   #" + "\n" +
              "############",
  
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#       [  #" + "\n" +
              "#     r~   #" + "\n" + // Climbs on
              "############",
  
              "#          #" + "\n" +
              "#          #" + "\n" +
              "#       {  #" + "\n" +
              "#      r   #" + "\n" + // Jumps off end
              "############",
  
              "#          #" + "\n" +
              "#        B #" + "\n" +
              "#       r  #" + "\n" +
              "#      (f  #" + "\n" + // Falls
              "############",
  
              "#          #" + "\n" +
              "#        [ #" + "\n" +
              "#       r  #" + "\n" +
              "#      (r> #" + "\n" + // Walks away
              "############"
          );
      }
  
      @Test
      public void Bridge_token_next_to_wall_makes_you_bridge_towards_it()
      {
          assertWorldEvolvesLike(
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#    ri#" + "\n" +
              "########",
  
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#     B#" + "\n" +
              "########",
  
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#     [#" + "\n" +
              "########",
  
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#     {#" + "\n" +
              "########",
  
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#     ?#" + "\n" +
              "########"
          );
      }
  
      @Test
      public void Bridge_token_next_to_short_wall_makes_you_bridge_towards_it()
      {
          assertWorldEvolvesLike(
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#ri#   #" + "\n" +
              "########",
  
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "# B#   #" + "\n" +
              "########",
  
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "# [#   #" + "\n" +
              "########",
  
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#      #" + "\n" +
              "# {#   #" + "\n" +
              "########",
  
              "#      #" + "\n" +
              "#      #" + "\n" +
              "#  '   #" + "\n" +
              "# r#   #" + "\n" +
              "########"
          );
      }
  
      @Test
      public void Bridge_token_next_to_back_slope_makes_you_bridge_towards_it()
      {
          assertWorldEvolvesLike(
              "           " + "\n" +
              "           " + "\n" +
              "           " + "\n" +
              "/ij     ri)" + "\n" +
              "###########",
  
              "           " + "\n" +
              "           " + "\n" +
              "           " + "\n" +
              "/E       B)" + "\n" +
              "###########",
  
              "           " + "\n" +
              "           " + "\n" +
              "           " + "\n" +
              "/]       [)" + "\n" +
              "###########",
  
              "           " + "\n" +
              "           " + "\n" +
              "           " + "\n" +
              "/}       {)" + "\n" +
              "###########",
  
              "           " + "\n" +
              "           " + "\n" +
              "           " + "\n" +
              "mj       r&" + "\n" +
              "###########"
          );
      }
  
      @Test
      public void Bridge_token_at_top_of_bridge_continues()
      {
          assertWorldEvolvesLike(
              "#       #" + "\n" +
              "#   i   #" + "\n" +
              "#   (   #" + "\n" +
              "# r(    #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#   $   #" + "\n" +
              "#  r    #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#    B  #" + "\n" +
              "#   r   #" + "\n" +
              "#  (    #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#    [  #" + "\n" +
              "#   r   #" + "\n" +
              "#  (    #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#    {  #" + "\n" +
              "#   r   #" + "\n" +
              "#  (    #" + "\n" +
              "#########",
  
              "#     B #" + "\n" +
              "#    r  #" + "\n" +
              "#   (   #" + "\n" +
              "#  (    #" + "\n" +
              "#########"
          );
      }
  
      @Test
      public void Bridge_token_at_top_of_bridge_by_wall_continues_reversed()
      {
          assertWorldEvolvesLike(
              "#       #" + "\n" +
              "#      i#" + "\n" +
              "#      (#" + "\n" +
              "#    r( #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#      $#" + "\n" +
              "#     r #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#      ?#" + "\n" +
              "#     ( #" + "\n" +
              "#########",
  
              "#       #" + "\n" +
              "#       #" + "\n" +
              "#     Ej#" + "\n" +
              "#     ( #" + "\n" +
              "#########"
          );
      }
  
      @Test
      public void Bridger_ignores_bridging_tokens()
      {
          assertWorldEvolvesLike(
              "   i     " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "  i      " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "ri       " + "\n" +
              "#########",
  
              "         " + "\n" +
              "   i     " + "\n" +
              "   f     " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "  i      " + "\n" +
              "  f      " + "\n" +
              "         " + "\n" +
              " rB      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "   i     " + "\n" +
              "   f     " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "  i      " + "\n" +
              "  f      " + "\n" +
              " r[      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "   i     " + "\n" +
              "   f     " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "  i      " + "\n" +
              " rf      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "   i     " + "\n" +
              "   f     " + "\n" +
              "         " + "\n" +
              "   B     " + "\n" +
              "  i      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "   i     " + "\n" +
              "   f     " + "\n" +
              "   [     " + "\n" +
              "  i      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "   i     " + "\n" +
              "   f     " + "\n" +
              "  i      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "    B    " + "\n" +
              "   i     " + "\n" +
              "  i      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "    [    " + "\n" +
              "   i     " + "\n" +
              "  i      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "    {    " + "\n" +
              "   i     " + "\n" +
              "  i      " + "\n" +
              "#########",
  
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "         " + "\n" +
              "     '   " + "\n" +
              "    r    " + "\n" +
              "   i     " + "\n" +
              "  i      " + "\n" +
              "#########"
          );
      }
  
      @Test
      public void Bridge_out_of_a_hole()
      {
          // Drop bridge tokens on a rabbit in a hole
  
          assertWorldEvolvesLike(
              "  i  " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "  i  " + "\n" +
              "     " + "\n" +
              "##r##" + "\n" +
              "## ##" + "\n" +
              "##i##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "  i  " + "\n" +
              "  f  " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "  i  " + "\n" +
              "##f##" + "\n" +
              "## ##" + "\n" +
              "##B##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "  i  " + "\n" +
              "  f  " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "##i##" + "\n" +
              "##f##" + "\n" +
              "##[##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "  i  " + "\n" +
              "  f  " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "## ##" + "\n" +
              "##i##" + "\n" +
              "##f##" + "\n" + // Finish first bridge
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "  i  " + "\n" +
              "  f  " + "\n" +
              "     " + "\n" +
              "## ##" + "\n" +
              "## ##" + "\n" +
              "##?##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "  i  " + "\n" +
              "  f  " + "\n" +
              "## ##" + "\n" +
              "##E##" + "\n" +
              "##j##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "  i  " + "\n" +
              "##f##" + "\n" +
              "##]##" + "\n" +
              "##j##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "##i##" + "\n" +
              "##f##" + "\n" + // Finish second bridge
              "##j##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "## ##" + "\n" +
              "##|##" + "\n" +
              "##(##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "##B##" + "\n" +
              "##r##" + "\n" +
              "##(##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "##[##" + "\n" +
              "##r##" + "\n" +
              "##(##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "##{##" + "\n" +
              "##r##" + "\n" +
              "##(##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "   ' " + "\n" +
              "##r##" + "\n" +
              "##)##" + "\n" +
              "##(##" + "\n" +
              "#####",
  
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "     " + "\n" +
              "   r>" + "\n" +
              "##(##" + "\n" +
              "##)##" + "\n" +
              "##(##" + "\n" +
              "#####"
          );
      }
  
      @Test
      public void Two_rabbits_cant_pick_up_the_same_token()
      {
          World world = createWorld(
              "         ",
              "         ",
              "  i      ",
              "#########"
          );
  
          // Add 2 rabbits in the same place
          world.rabbits.add( new Rabbit( 2, 2, Direction.RIGHT, RABBIT ) );
          world.rabbits.add( new Rabbit( 2, 2, Direction.RIGHT, RABBIT ) );
  
          world.step();
          assertThat(
              renderWorld( world, false, false ),
              equalTo(
                  "         ",
                  "         ",
                  " ri      ",
                  "#########"
              )
          );
  
          world.step();
          assertThat(
              renderWorld( world, true, false ),
              equalTo(
                  "         ",
                  "         ",
                  "  r>     ",  // One is walking, one is bridging
                  "#########"
              )
          );
  
          world.step();
          assertThat(
              renderWorld( world, true, false ),
              equalTo(
                  "         ",
                  "         ",
                  "  r[>    ",
                  "#########"
              )
          );
  
          world.step();
          assertThat(
              renderWorld( world, true, false ),
              equalTo(
                  "         ",
                  "         ",
                  "  r{r>   ",
                  "#########"
              )
          );
      }
  
      @Test
      public void No_build_through_blocker()
      {
          World world = createWorld(
            "r   ",
            "  rO",
            " ik#",
            "####"
          );
  
          for ( int i = 0; i < 5 ; i++ )
          {
              world.step();
          }
  
          // rabbit has been turned by blocker and is bridging the other way.
          assertThat(
              renderWorld( world, true, false ),
              equalTo(
                  "    ",
                  "   O",
                  "}jH#",
                  "####"
              )
          );
      }
  
      @Test
      public void Bridge_out_of_bounds()
      {
          World world = createWorld(
              "       *",
              "*     ##",
              "###  ###",
              "        ",
              "ij    ri",
              "###  ###",
              "        ",
              "        ",
              " ij  ri ",
              "###  ###",
              ":*=ij",
              ":*=ir"
          );
  
          // The test will find out of
          // bounds exceptions from rendering
          // bridges outside the world.
          assertWorldEvolvesLike(
              world,
              10,
              new String[] {
                  "  (   ) ",
                  " (    ##",
                  "###  ###",
                  "        ",
                  "        ",
                  "###  ###",
                  "        ",
                  "        ",
                  ")      (",
                  "###  ###",
              });
  
          assertThat( world.num_killed, equalTo ( 6 ) );
      }
  
      @Test
      public void Bridging_preserves_water()
      {
          World world = createWorld(
              "        ",
              "        ",
              "r       ",
              "#*NNNN*#",
              "########",
              ":*=\\ni",
              ":*=/n",
              ":n=1,3,512",
              ":n=6,3,512"
          );
  
          assertWorldEvolvesLike(
              world,
              10,
              new String[] {
                  "        ",
                  "    *   ",
                  "   (    ",
                  "#**NNN*#",
                  "########",
                  ":*=(r{Bridging.bridgeType:UP,index:1,onSlope:true}",
                  ":*=\\n",
                  ":*=(N",
                  ":*=/n",
              });
      }
  
      @Test
      public void Roof_prevents_bridging_even_when_in_a_hole_issue_511()
      {
          assertWorldEvolvesLike(
              "## " + "\n" +
              "#ij" + "\n" +
              "#)#" + "\n" +
              "###",
  
              "## " + "\n" +
              "#j " + "\n" +
              "#a#" + "\n" +
              "###",
  
              "## " + "\n" +
              "#  " + "\n" +
              "#|#" + "\n" +
              "###",
  
              "## " + "\n" +
              "#  " + "\n" +
              "#]#" + "\n" + // Does not bridge - would hit head
              "###",
  
              "## " + "\n" +
              "#  " + "\n" +
              "#|#" + "\n" +
              "###"
          );
      }
  
      @Test
      public void Roof_does_not_prevent_bridging_when_higher()
      {
          assertWorldEvolvesLike(
              "###" + "\n" +
              "   " + "\n" +
              "#i#" + "\n" +
              "r( " + "\n" +
              "###",
  
              "###" + "\n" +
              "   " + "\n" +
              "#B#" + "\n" +
              " r " + "\n" + // Starts bridging
              "###",
  
              "###" + "\n" +
              "   " + "\n" +
              "#[#" + "\n" +
              " r " + "\n" +
              "###"
          );
      }
  
      @Test
      public void Bridge_roof_does_not_prevent_bridging()
      {
          assertWorldEvolvesLike(
              "#( " + "\n" +
              "#ij" + "\n" +
              "#)#" + "\n" +
              "###",
  
              "#( " + "\n" +
              "#j " + "\n" +
              "#a#" + "\n" +
              "###",
  
              "#( " + "\n" +
              "#  " + "\n" +
              "#|#" + "\n" +
              "###",
  
              "#( " + "\n" +
              "#B " + "\n" +
              "#r#" + "\n" + // Starts bridging
              "###"
          );
      }
  }
  