Hunt The Wumpus/APL

From Rosetta Code
Hunt The Wumpus/APL is part of Hunt_The_Wumpus. You may find other members of Hunt_The_Wumpus at Category:Hunt_The_Wumpus.
Works with: GNU APL
#!/usr/local/bin/apl --script -f --

⍝ Unfortunately, GNU APL does not support ⍞-input in script mode very well
⍝ Therefore, this function reads STDIN directly to do it. It supports no
⍝ terminal control except backspace, and no Unicode either, which I suppose
⍝ makes it period-correct.
 lReadLine;k;z;data
        data''         ⍝ Start out with empty string

        ⍝⍝⍝ Keyboard input
in:     k1⎕fio[41]1    ⍝ Read byte from stdin
handle: (k>127)/skip   ⍝ Unicode is not supported (Wumpus doesn't need it)
        (k8 127)/back ⍝ Handle backspace
        (k=10)/done    ⍝ Newline = Enter key pressed
        (k<32)/in      ⍝ For simplicity, disregard terminal control entirely
        zk⎕fio[42]0    ⍝ Echo key to stdout
        datadata,k     ⍝ Append key to data
        in             ⍝ Go get next key

        ⍝⍝ Skip UTF-8 input (read until byte ≤ 127)
skip:   k1⎕fio[41]1  (k>127)/skip  handle
             
        ⍝⍝ Backspace
back:   (0=⍴data)/in   ⍝ If nothing to delete, ignore
        zk⎕fio[42]0    ⍝ Backspace to terminal
        data¯1data    ⍝ Remove last character
        in             ⍝ Get next key
        
        ⍝⍝ We are done, return the line as text
done:   z10⎕fio[42]0   ⍝ Newline
        l⎕UCS data


⍝ Read a positive number from the keyboard, keep trying until input is valid.
 nReadNum;l
try:    lReadLine              ⍝ Get input
        (l.'0123456789')/ok  ⍝ Valid number?
        'Please enter a number: '
        try
ok:     nl

    

⍝ Define which rooms are adjacent
 cCave
        c  (2 3 4)(1 5 6)(1 7 8)(1 9 10)(2 9 11)
        cc⍪⊃(2 7 12)(3 6 13)(3 10 14)(4 5 15)(4 8 16)
        cc⍪⊃(5 12 17)(6 11 18)(7 14 18)(8 13 19)(9 16 17)
        cc⍪⊃(10 15 19)(11 20 15)(12 13 20)(14 16 20)(17 18 19)


initPRNG
  ⍝⍝ Seed the internal PRNG used by APL ? operator
  ⎕rl  +/ ⎕ts   ⍝⍝ Not great... but good enough


⍝ Get N random empty rooms
 rn Empty rooms;z
        rz[n?⍴z(rooms=0)/⍳⍴rooms]


⍝ Play the game
 Game;z;arrows;rooms;player;msg;adj;cur;inp;tgt
        '∘∘∘ HUNT THE WUMPUS ∘∘∘'
        ''
        'In search of glory and wumpus fur, you have descended into the'
        'wumpus cave. Can you kill the wumpus, and make it out alive?'
        ''
        
      
        ⍝⍝ Initialization
        initPRNG                    ⍝ Initialize random seed from time
        arrows5                    ⍝ Start with 5 arrows
        rooms20/0                  ⍝ 20 empty rooms
        rooms[1 Empty rooms]1      ⍝ Place wumpus in random room
        rooms[2 Empty rooms]2      ⍝ Place two bats in random empty rooms
        rooms[2 Empty rooms]3      ⍝ Place two pits in random empty rooms
        player1 Empty rooms        ⍝ Put player in random empty room
        
        ⍝⍝ Player enters a room
enter:  currooms[player]           ⍝ What is in the current room?
        adjrooms[Cave[player;]]    ⍝ What is in the adjacent rooms?
        (cur=1 2 3)/wump bat pit   ⍝ Did the player walk into something bad?
        
        ⍝⍝ Give player information about current room.
        msg'You are in room ', (player), '.'
        msgmsg,⊂'You have ', (arrows), ' arrows left.'
        msgmsg,⊂'Tunnels lead to: ', ,⍕Cave[player;]
        ⍝⍝ The '~ ↓' (instead of / or ↑) avoids a weird debug message here.
        msgmsg,(~1adj)↓⊂'You smell something terrible nearby.'
        msgmsg,(~2adj)↓⊂'You hear a rustling.'
        msgmsg,(~3adj)↓⊂'You feel a cold wind blowing from a nearby cavern.'
        msg 
        
        ⍝⍝ Move or shoot
input:  ''
        'Do you want to _m_ove or _s_hoot? '
        inpReadLine  (~(inp)'mMsS')/input
 
        'Which room? '
        tgtReadNum
        ((tgtCave[player;])'mMsS'=↑inp)/move move shoot shoot
        'That is not possible.'
        input
        
move:   playertgt  enter
shoot:  arrowsarrows-1
        (rooms[tgt]=1)/win         ⍝ Hit the wumpus?
        'You missed!'
        ''
        (arrows=0)/empty           ⍝ Out of arrows?
        (4=?4)/enter               ⍝ 25% chance of wumpus not waking up
        'Your noise has awoken the wumpus.'
        'He moves to another room in search of some peace and quiet.'
        ''
        z(rooms=1)/⍳⍴rooms         ⍝ Current wumpus location
        rooms[z,Cave[z;?3]]0 1     ⍝ Wumpus moves to adjacent room
        enter 

        ⍝⍝ You hit the target
win:    'You hear a painful roar coming from the passage.'
        'Upon entering, you find the wumpus in a pool of its own blood.'
        'You have won!'
        0
        
        ⍝⍝ Out of arrows.
empty:  'You have shot your last arrow.'
        'Just as you realize how defenseless you are, you hear a large'
        ' beast approaching.'
        over
        
        ⍝⍝ Player enters the room with the wumpus in it.
wump:   'You find yourself face to face with the wumpus.'
        'It devours you whole.'
        ''
        over
        
        ⍝⍝ Player enters a room with a bat in it
bat:    'You walk into a bat''s cave.'
        'It is not amused, and carries you out.'
        ''
        player1 Empty rooms        ⍝ Put player in random empty room. 
        enter
        
        ⍝⍝ Player walks into a pit
pit:    'As you confidently stride into this room, you realize it has'
        ' no floor.'
        ''
        'You ponder the consequences of your actions as you fall to your'
        ' death.'
        
over:   ''
        'Game over!'



Game
)OFF