FORTRAN Computer Games


Wumpus

Hunt the Wumpus is an early text-based adventure game, originally written in BASIC by Gregory Yob, and released in 1973. The player moves through 20 connected caves to hunt the gruesome Wumpus. The dungeon resembles the vertices and edges of a dodecahedron (d12 dice). The hero carries a bow and five magic arrows which can travel through multiple caves on a given trail. Beside the Wumpus, two bottomless pits and two Super Bats have to be avoided.

Gameplay

Wumpus in FORTRAN 77

Functions & Subroutines

The program is split into eight functions and subroutines:

RESULT = IADJAC(IFROM)
Returns random room (INTEGER) adjacent to room IFROM (INTEGER).
RESULT = INPUT()
Returns input from player (INTEGER), either 1, 2, or 3.
RESULT = IRANDR()
Returns number of random empty room (INTEGER).
RESULT = EMPTY(IROOM)
Returns .TRUE. if given room (INTEGER) is empty, else .FALSE..
CALL HELP()
Prints intructions to standard output.
CALL INIT()
Initialises a new game.
CALL MOVE()
Asks for input and moves the player character.
CALL TURN(NEXT)
Runs the next turn of the game. Output variable NEXT (LOGICAL) is set to .FALSE. if the game is over, else to .TRUE..

Additionally, three procedures that are not part of the ANSI/ISO FORTRAN 77 language standard are required:

RESULT = TIME()
Returns timestamp in seconds (INTEGER). Required for the initialisation of the pseudo-random number generator.
RESULT = RAND(I)
Returns the next random number (REAL).
CALL SRAND(ISEED)
Initialises the pseudo-random number generator with given seed value (INTEGER).

Most modern compilers provide these through extensions.

Program Listing

The program in structured FORTRAN 77 has about 400 lines, including comments. Save the code as wumpus.f.

C     ****************************************************************
C
C     WUMPUS
C
C     THE TEXT-BASED ADVENTURE GAME "HUNT THE WUMPUS" FROM 1973: FIND
C     AND KILL THE HORRENDOUS BEAST WUMPUS THAT LURKS IN A CAVE FULL
C     OF DANGERS. ORIGINALLY WRITTEN BY GREGORY YOB IN BASIC. PORTED
C     TO FORTRAN IN 2023 BY THE ILLUSTRIOUS PHILIPP ENGEL.
C
C     ****************************************************************
      PROGRAM WUMPUS
      EXTERNAL HELP, INIT, TURN

      CHARACTER A
      INTEGER   ISEED, ISTAT
      LOGICAL   NEXT
C
C     SEED THE RANDOM NUMBER GENERATOR.
C
      ISEED = ABS(TIME())
      CALL SRAND(ISEED)
C
C     ASK FOR INSTRUCTIONS.
C
      PRINT 100
      READ (*, 200, IOSTAT=ISTAT) A
      IF (A .EQ. 'Y' .OR. A .EQ. 'y') CALL HELP()
C
C     INITIALISE THE GAME.
C
      CALL INIT()
C
C     RUN UNTIL GAME IS OVER.
C
   10 CONTINUE
      CALL TURN(NEXT)
      IF (NEXT) GOTO 10

  100 FORMAT (' HUNT THE WUMPUS',/,/,' INSTRUCTIONS? (Y/N) ',$)
  200 FORMAT (A)
      END
C     ****************************************************************
      INTEGER FUNCTION IADJAC(IFROM)
C
C     RETURNS RANDOM ROOM ADJACENT TO IFROM.
C
      INTEGER IFROM
      INTEGER I
      INTEGER IROOMY(20, 3)
      COMMON /WORLD/ IROOMY

      I = 1 + INT(RAND(0) * 3)
      IADJAC = IROOMY(IFROM, I)
      END
C     ******************************************************************
      INTEGER FUNCTION INPUT()
C
C     READS PLAYER INPUT (1, 2, OR 3).
C
      INTEGER ISTAT

   10 CONTINUE
      READ (*, 100, IOSTAT=ISTAT) INPUT
      IF (ISTAT .NE. 0 .OR. INPUT .LT. 1 .OR. INPUT .GT. 3) THEN
        PRINT 200
        GOTO 10
      END IF

  100 FORMAT (I1)
  200 FORMAT (' INVALID INPUT. TRY AGAIN: ',$)
      END
C     ****************************************************************
      INTEGER FUNCTION IRANDR()
C
C     RETURNS RANDOM EMPTY ROOM.
C
      LOGICAL EMPTY

   10 CONTINUE
      IRANDR = 1 + INT(RAND(0) * 20)
      IF (.NOT. EMPTY(IRANDR)) GOTO 10
      END
C     ****************************************************************
      LOGICAL FUNCTION EMPTY(IROOM)
C
C     RETURNS .TRUE. IF GIVEN ROOM IS EMPTY.
C
      INTEGER IROOM
      INTEGER IBATY(2), IPITY(2), IWUMP, IHERO, NARROW
      COMMON /STATE/ IBATY, IPITY, IWUMP, IHERO, NARROW

      EMPTY = .FALSE.
      IF (IROOM .EQ. IHERO    .OR. IROOM .EQ. IWUMP    .OR.
     &    IROOM .EQ. IBATY(1) .OR. IROOM .EQ. IBATY(2) .OR.
     &    IROOM .EQ. IPITY(1) .OR. IROOM .EQ. IPITY(2)) RETURN
      EMPTY = .TRUE.
      END
C     ****************************************************************
      SUBROUTINE HELP()
C
C     PRINTS INSTRUCTIONS.
C
      CHARACTER A
      INTEGER   ISTAT

      PRINT 200
      READ (*, 100, IOSTAT=ISTAT) A
      PRINT 300
      READ (*, 100, IOSTAT=ISTAT) A
      PRINT 400
      READ (*, 100, IOSTAT=ISTAT) A
      PRINT 500
      READ (*, 100, IOSTAT=ISTAT) A

  100 FORMAT (A)
  200 FORMAT (/,' WELCOME TO "HUNT THE WUMPUS"',/,/,
     &' THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM HAS THREE',/,
     &' TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A DODECAHEDRON TO',/,
     &' SEE HOW THIS WORKS -- IF YOU DON''T KNOW WHAT A DODECAHEDRON',/,
     &' IS, ASK SOMEONE.)',/,/,
     &' HAZARDS:',/,/,
     &2X,'BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM.',/,
     &4X,'IF YOU GO THERE, YOU FALL INTO THE PIT (AND LOSE).',/,/,
     &2X,'SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU GO',/,
     &4X,'THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER ROOM',/,
     &4X,'AT RANDOM. (WHICH MIGHT BE TROUBLESOME)',/,/,
     &' PRESS RETURN.',$)
  300 FORMAT (/,' WUMPUS:',/,/,
     &2X,'THE WUMPUS IS NOT BOTHERED BY THE HAZARDS (HE HAS SUCKER',/,
     &2X,'FEET AND IS TOO BIG FOR A BAT TO LIFT). USUALLY HE IS',/,
     &2X,'ASLEEP. TWO THINGS WAKE HIM UP: YOUR ENTERING HIS ROOM OR',/,
     &2X,'YOUR SHOOTING AN ARROW.',/,/,
     &2X,'IF THE WUMPUS WAKES, HE MOVES (P=.75) ONE ROOM OR STAYS',/,
     &2X,'STILL (P=.25). AFTER THAT, IF HE IS WHERE YOU ARE, HE EATS',/,
     &2X,'YOU UP (AND YOU LOSE).',/,/,
     &' PRESS RETURN.',$)
  400 FORMAT (/,' YOU:',/,/,
     &2X,'EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW.',/,/,
     &2X,'MOVING: YOU CAN GO ONE ROOM (THRU ONE TUNNEL).',/,
     &2X,'ARROWS: YOU HAVE 5 ARROWS. YOU LOSE WHEN YOU RUN OUT.',/,/,
     &2X,'EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING',/,
     &2X,'THE COMPUTER THE ROOMS YOU WANT THE ARROW TO GO TO.',/,
     &2X,'IF THE ARROW CAN''T GO THAT WAY (I.E. NO TUNNEL) IT',/,
     &2X,'MOVES AT RAMDOM TO THE NEXT ROOM.',/,/,
     &2X,'IF THE ARROW HITS THE WUMPUS, YOU WIN.',/,
     &2X,'IF THE ARROW HITS YOU, YOU LOSE.',/,/,
     &' PRESS RETURN.',$)
  500 FORMAT (/,' WARNINGS:',/,/,
     &2X,'WHEN YOU ARE ONE ROOM AWAY FROM WUMPUS OR HAZARD,',/,
     &2X,'THE COMPUTER SAYS:',/,/,
     &2X,'WUMPUS - "YOU SMELL A WUMPUS!"',/,
     &2X,'BAT    - "BATS NEARBY!"',/,
     &2X,'PIT    - "YOU FEEL A DRAFT!"',/,/,
     &' PRESS RETURN.',$)
      END
C     ****************************************************************
      SUBROUTINE INIT()
C
C     INITIALISES THE GAME.
C
      INTEGER IRANDR

      INTEGER IBATY(2), IPITY(2), IWUMP, IHERO, NARROW
      COMMON /STATE/ IBATY, IPITY, IWUMP, IHERO, NARROW

      IBATY(1) = IRANDR()
      IBATY(2) = IRANDR()
      IPITY(1) = IRANDR()
      IPITY(2) = IRANDR()
      IWUMP = IRANDR()
      IHERO = IRANDR()
      NARROW = 5
      END
C     ****************************************************************
      SUBROUTINE MOVE()
C
C     MOVES PLAYER.
C
      INTEGER IBATY(2), IPITY(2), IWUMP, IHERO, NARROW
      INTEGER IROOMY(20, 3)
      COMMON /STATE/ IBATY, IPITY, IWUMP, IHERO, NARROW
      COMMON /WORLD/ IROOMY

      INTEGER IROOM, ISTAT

      PRINT 100

   10 CONTINUE
      READ (*, *, IOSTAT=ISTAT) IROOM

      IF (ISTAT .NE. 0 .OR. IROOM .LT. 1 .OR. IROOM .GT. 20) THEN
        PRINT 200
        GOTO 10
      END IF

      IF (IROOM .NE. IROOMY(IHERO, 1) .AND.
     &    IROOM .NE. IROOMY(IHERO, 2) .AND.
     &    IROOM .NE. IROOMY(IHERO, 3)) THEN
        PRINT 200
        GOTO 10
      END IF

      IHERO = IROOM

  100 FORMAT (' WHICH ROOM DO YOU WANT TO ENTER? ',$)
  200 FORMAT (' INVALID INPUT. TRY AGAIN: ',$)
      END
C     ****************************************************************
      SUBROUTINE SHOOT()
C
C     SHOOTS INTO ROOM.
C
C
      INTEGER IADJAC

      INTEGER IBATY(2), IPITY(2), IWUMP, IHERO, NARROW
      INTEGER IROOMY(20, 3)
      COMMON /STATE/ IBATY, IPITY, IWUMP, IHERO, NARROW
      COMMON /WORLD/ IROOMY

      INTEGER IDIRY(5)
      INTEGER I, ISTAT, LAST, N, NEXT

      PRINT 100

   10 CONTINUE
C
C     INITIALISE DIRECTION ARRAY.
C
      DO 20 I = 1, SIZE(IDIRY)
      IDIRY(I) = 0
   20 CONTINUE
C
C     READ LIST OF ROOMS TO SHOOT INTO.
C
      READ (*, 200, IOSTAT=ISTAT) IDIRY

      IF (ISTAT .NE. 0) THEN
        PRINT 300
        GOTO 10
      END IF
C
C     VALIDATE INPUT.
C
      N = 0

      DO 30 I = 1, SIZE(IDIRY)
      IF (IDIRY(I) .GT. 0) N = I
   30 CONTINUE

      IF (N .EQ. 0) THEN
        PRINT 300
        GOTO 10
      END IF

      IF (IDIRY(1) .EQ. IHERO) THEN
        PRINT 400
        GOTO 10
      END IF
C
C     SHOOT ARROW IN UP TO FIVE ROOMS.
C
      NARROW = NARROW - 1
      LAST = IHERO

      DO 40 I = 1, N
      NEXT = IDIRY(I)

      IF ((NEXT .EQ. LAST) .OR. (NEXT .LT. 1) .OR. (NEXT .GT. 20) .OR.
     &    (NEXT .NE. IROOMY(LAST, 1) .AND.
     &     NEXT .NE. IROOMY(LAST, 2) .AND.
     &     NEXT .NE. IROOMY(LAST, 3))) THEN
        NEXT = IADJAC(LAST)
      END IF

      IF (NEXT .EQ. IHERO) THEN
        IHERO = 0
        RETURN
      END IF

      IF (NEXT .EQ. IWUMP) THEN
        IWUMP = 0
        RETURN
      END IF

      LAST = NEXT
   40 CONTINUE
C
C     WAKE UP THE WUMPUS.
C
      IF (RAND(0) .LT. 0.75) IWUMP = IADJAC(IWUMP)

  100 FORMAT (' ENTER A LIST OF ROOMS TO SHOOT INTO (UP TO 5): ',$)
  200 FORMAT (5(I2,1X))
  300 FORMAT (' INVALID INPUT. TRY AGAIN: ',$)
  400 FORMAT (' YOU HAVE TO AIM INTO AN ADJACENT ROOM, STUPID.')
      END
C     ****************************************************************
      SUBROUTINE TURN(NEXT)
C
C     RUNS NEXT TURN.
C
      EXTERNAL MOVE, SHOOT
      INTEGER  INPUT

      LOGICAL NEXT

      INTEGER IBATY(2), IPITY(2), IWUMP, IHERO, NARROW
      INTEGER IROOMY(20, 3)
      COMMON /STATE/ IBATY, IPITY, IWUMP, IHERO, NARROW
      COMMON /WORLD/ IROOMY

      INTEGER I, IROOM, K

      NEXT = .FALSE.

      IF (IWUMP .EQ. 0) THEN
        PRINT 200
        RETURN
      END IF

      IF (IHERO .EQ. IWUMP) THEN
        PRINT 300
        PRINT 100
        RETURN
      END IF

      IF (IHERO .EQ. 0) THEN
        PRINT 400
        PRINT 100
        RETURN
      END IF

      IF (NARROW .LT. 1) THEN
        PRINT 500
        PRINT 100
        RETURN
      END IF

      IF (IHERO .EQ. IPITY(1) .OR. IHERO .EQ. IPITY(2)) THEN
        PRINT 600
        PRINT 100
        RETURN
      END IF

      IF (IHERO .EQ. IBATY(1) .OR. IHERO .EQ. IBATY(2)) THEN
        PRINT 700
        IHERO = IRANDR()
      END IF

      PRINT 800, IHERO

      DO 10, I = 3, 1, -1
      IROOM = IROOMY(IHERO, I)
      IF (IROOM .EQ. IWUMP) PRINT 900
      IF (IROOM .EQ. IBATY(1) .OR. IROOM .EQ. IBATY(2)) PRINT 1000
      IF (IROOM .EQ. IPITY(1) .OR. IROOM .EQ. IPITY(2)) PRINT 1100
   10 CONTINUE

      PRINT 1200, NARROW, IROOMY(IHERO, 1), IROOMY(IHERO, 2),
     &            IROOMY(IHERO, 3)

      K = INPUT()

      IF (K .EQ. 1) THEN
        CALL MOVE()
      ELSE IF (K .EQ. 2) THEN
        CALL SHOOT()
      ELSE IF (K .EQ. 3) THEN
        RETURN
      END IF

      NEXT = .TRUE.

  100 FORMAT (' GAME OVER.')
  200 FORMAT (' AHA! YOU GOT THE WUMPUS!')
  300 FORMAT (' YOU FIND YOURSELF FACE TO FACE WITH THE WUMPUS.',
     &' IT EATS YOU WHOLE.')
  400 FORMAT (' OUCH! ARROW GOT YOU!')
  500 FORMAT (' YOU HAVE RUN OUT OF ARROWS!')
  600 FORMAT (' AAAAAAAAAAA! YOU HAVE FALLEN INTO A BOTTOMLESS PIT.')
  700 FORMAT (' A BAT HAS CARRIED YOU INTO ANOTHER EMPTY ROOM.')
  800 FORMAT (/,' YOU ARE IN ROOM ',I2,'.')
  900 FORMAT (' YOU SMELL A WUMPUS!')
 1000 FORMAT (' BATS NEARBY!')
 1100 FORMAT (' YOUR FEEL A DRAFT!')
 1200 FORMAT (' YOU HAVE ',I1,' ARROWS. TUNNELS LEAD TO ',I2,', ',I2,
     &' AND ',I2,'.',/,' (1) MOVE  (2) SHOOT  (3) QUIT: ',$)
      END
C     ****************************************************************
      BLOCK DATA
C
C     COMMON VARIABLES:
C
C     IBATY  - ROOMS OF BATS (2).
C     IPITY  - ROOMS OF PITS (2).
C     IWUMP  - ROOM OF WUMPUS.
C     IHERO  - ROOM OF PLAYER.
C     NARROW - NUMBER OF ARROWS LEFT.
C     IROOMY - CONNECTIONS BETWEEN ROOMS.
C
      INTEGER IBATY(2), IPITY(2), IWUMP, IHERO, NARROW
      INTEGER IROOMY(20, 3)
      COMMON /STATE/ IBATY, IPITY, IWUMP, IHERO, NARROW
      COMMON /WORLD/ IROOMY
      DATA IROOMY /2,1,2,3,1,5,6,1,8,2,10,3,12,4,6,15,7,9,11,13,
     &5,3,4,5,4,7,8,7,10,9,12,11,14,13,14,17,16,17,18,16,
     &8,10,12,14,6,15,17,9,18,11,19,13,20,15,16,20,18,19,20,19/
      END

Build Instructions

UNIXFlang/F18$ flang -o wumpus wumpus.f
GNU Fortran$ gfortran -o wumpus wumpus.f
Intel Fortran Compiler$ ifort -o wumpus wumpus.f
Win32Digital/Compaq Visual Fortran> fl32.exe wumpus.f /Fe=wumpus.exe

References


Home