Python, 978 <s>980</s> <s>981</s>
=

    import sys,random
    f=open(sys.argv[1]).read().split('\n')
    s=t=[]
    d=p=x=y=k=0
    r='n'
    h='0123456789abcdef'
    while h:
     c=f[y][x]
     if k:k=0
     elif p:
      if c==p:p=0
      else:s+=[ord(c)]
     else:
      for l in (h+'''0123456789abcdef`s+=[h.find(c)]
    ><^v`d='><^v'.find(c)
    x`d=random.randint(0,3)
    /`d=(d+2)%4
    \`d=3-d
    |#`if d<2:d=1-d
    _#`if d>1:d=5-d
    +-*,%=)($gp`a,b=s[-2:];s=s[:-2]
    +-*%`s+=[eval('a%sb'%c)]
    ,`s+=[a/b]
    =`s+=[a==b]
    (`s+=[a<b]
    )`s+=[a>b]
    '"`p=c
    !?`if(not s)or'!'==c or s[-1]==0:k=1
    :`s+=s[-1:]
    ~`s.pop()
    $`s+=[b,a]
    @`s=s[:-3]+s[-1:]+s[-3:-1]
    &`s,r=(s[:-1],s[-1])if r=='n'else (s+[r],'n')
    .`s,t=t,s
    r`s.reverse()
    }`s=[:-1]+s[-1:]
    {`s=s[1:]+s[:1]
    m`s,t=[],s+t
    g`s+=[f[b][a]]
    p`f[s.pop()][b]=a
    on`z=chr if c=='o'else str;sys.stdout.write(z(s.pop()));sys.stdout.flush()
    i`s+=[int(sys.stdin.read(1))]
    ;`h=0''').split('\n'):
       l=l.split('`')
       if c in l[0]:
        try:exec(l[1])
        except:0
     if d<2:x=(x-d*2+1)%len(f[y])
     else:
      while 1:
       try:y=(y+d*2-5)%len(f);f[y][x];break
       except:0

Doesn't support threading.

Versions:  
&nbsp;1. 981  
&nbsp;2. 980: Fixed `p` instruction; small improvement.  
&nbsp;3. 978: Fixed `?` instruction.