Roguelike pathfinding
previous solutions (part of them) can be found in the footer container in the tio link (those are probably more readable)

JavaScript (Node.js),883 436 411 360,345 311 bytes



g=&gt;g.map((r,y)=&gt;[...r].map((c,x)=&gt;A+=c=="$"&amp;&amp;P(g,x,y)),A=0)|A
P=(g,x,y,m={},p={},I=i=9,M={})=&gt;{if(/[.$]/.test(c=(g[y]||0)[x])){for(;i--;)if(/^[^.@$#]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])){if(m[C])return
M[C]=1}for(;I--;)if(!p[(X=x+~-(I/3))+","+(Y=y+I%3-1)]&amp;&amp;P(g,X,Y,M,{...p,[x+","+y]:1}))return 1}return c=="@"}


Try it online!

Explantion -

instead of going from the player to the cash i went from the case to the @. i think i should be faster because i know when to stop looking (reach the @) , and when you look for cash you need to always keep moving until you covered all of the spots (and the ways to get to them). so the algo is pretty simple that way - the main function 
g.map((r,y)=&gt;[...r].map((c,x)=&gt;A+=c=="$"&amp;&amp;P(g,x,y)),A=0)|A:
find cash -> if you found it -> start looking for the player -> if you found him -> increment A
now lets got to the path finder aka P
if(/[.$]/.test(c=(g[y]||[])[x])) just check if the current cell is "special" -> if so we want to return if its a player. special cases : @#(monster)

for(;i--;)
if(/^[a-zA-Z*&amp;]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])) -&gt; if my neighbor is a monster
{if(m[C])return false -&gt; and it already was in the previous turn - this path is not value
M[C]=1} -&gt; if not just add it to the neighbors monsters
for(;I--;)
if(!p[(X=x+~-(I / 3))+","+(Y=y+I%3-1)]&amp;&amp;P(g,X,Y,M,{...p,[x+","+y]:1}))return true iterate neighbors again - if i wasn't already there (p is the path taken)
continue path (call P)