The Farmer, Goat, Wolf & Cabbage Logic Riddle
My youngest daughter is a freshman in college. She showed me a logic problem in her computer class. She had to design a circuit to solve the riddle (or indicate an error state). The circuit consists of a power source, toggle switches, boolean operators & led displays - each of the pieces connects to one another. I vaguely remember this riddle from long ago. I thought it would be fun to create a simple PC/370 application to track & evaluate the movements:
General Instructions:
A farmer must carry a goat, a wolf and a head of cabbage across the river (on the right). He can only carry one item at a time. The farmer must be on the same side as the item he will carry. <F1> moves the farmer only while <F2> thru <F4> moves the farmer and the object. The goat cannot be left alone with the cabbage or the wolf. If so, the goat or cabbage will be eaten.
Not too complicated. The key sequence to solve the puzzle correctly is:
<F2> <F1> <F3> <F2> <F4> <F1> <F2>
Above: Screen animation of puzzle completion.
Above: Error Message if farmer leaves goat alone with the wolf - *** WOLF EATS THE GOAT ***.
Above: All items are safely across the river. ***WINNER***!
There are three key elements of code. First is the main loop that detects function key input. The only keys active are <F1> thru <F4> to move the characters/items, <F10> to reset the game from scratch & the <ESC> key to Exit. The second element is the TOGGLE routine that moves the farmer alone or with an item from LEFT to RIGHT or vice versa. The farmer is the central character since he's doing all the work. The third element is the VALIDATE routine that tests if the farmer is with the goat - and if not, is the goat alone with the wolf or the cabbage? If so, that's an error...
LOOP EQU *
BAL 6,VALIDATE VALIDATE STATE
BAL 6,SCREEN BUILD SCREEN
*
CLI KEY,@K#ESC KEY = ESCAPE ???
BE LOOPX YES - EXIT PLEASE
*
CLI KEY,@K#F1 KEY = F1 ???
BE LOOPF1 YES - PROCESS KEY
CLI KEY,@K#F2 KEY = F2 ???
BE LOOPF2 YES - PROCESS KEY
CLI KEY,@K#F3 KEY = F3 ???
BE LOOPF3 YES - PROCESS KEY
CLI KEY,@K#F4 KEY = F4 ???
BE LOOPF4 YES - PROCESS KEY
*
CLI KEY,@K#F10 KEY = F10 ???
BNE LOOP NO - LOOP AGAIN
LOOPF10 EQU *
MVC XF(4),=CL4'LLLL' ALL BACK TO THE LEFT
MVC SCRFL,=CL7'FARMER' INIT LEFT FARMER
MVC SCRFR,=CL7' ' INIT RIGHT FARMER
MVC SCRGL,=CL7'GOAT' INIT LEFT GOAT
MVC SCRGR,=CL7' ' INIT RIGHT GOAT
MVC SCRWL,=CL7'WOLF' INIT LEFT WOLF
MVC SCRWR,=CL7' ' INIT RIGHT WOLF
MVC SCRCL,=CL7'CABBAGE' INIT LEFT CABBAGE
MVC SCRCR,=CL7' ' INIT RIGHT CABBAGE
MVI SCRMSG,C' ' MOVE BLANK TO MSG
MVC SCRMSG+1(L'SCRMSG-1),SCRMSG PROPAGATE THROUGHOUT
B LOOP DISPLAY SCREEN AGAIN
LOOPF1 EQU *
LA 4,XF SET STATE ADDRESS
LA 5,SCRFL SET SCREEN ADDRESS
BAL 6,TOGGLE TOGGLE POSITIONS
B LOOP DISPLAY SCREEN AGAIN
LOOPF2 EQU *
LA 4,XG SET STATE ADDRESS
LA 5,SCRGL SET SCREEN ADDRESS
BAL 6,TOGGLE TOGGLE POSITIONS
B LOOP DISPLAY SCREEN AGAIN
LOOPF3 EQU *
LA 4,XW SET STATE ADDRESS
LA 5,SCRWL SET SCREEN ADDRESS
BAL 6,TOGGLE TOGGLE POSITIONS
B LOOP DISPLAY SCREEN AGAIN
LOOPF4 EQU *
LA 4,XC SET STATE ADDRESS
LA 5,SCRCL SET SCREEN ADDRESS
BAL 6,TOGGLE TOGGLE POSITIONS
B LOOP DISPLAY SCREEN AGAIN
LOOPX EQU *
The TOGGLE routine flips the orientation of the farmer/item & moves it to the new destination. Exclusive OR (XOC) is used to isolate & swap the bits - producing the "toggle" effect.
***********************************************************************
* TOGGLE POSITIONS *
***********************************************************************
DC F'0' RETURN ADDRESS SAVE AREA
TOGGLE EQU *
ST 6,*-4 SAVE RETURN ADDRESS
*
CLC XF,0(4) FARMER STATE EQUAL?
BNE LOOP NO - IGNORE KEY
*
CLI XF,C'L' CURRENT STATE LEFT?
BE *+12 YES - SET TO RIGHT
MVI XF,C'L' NO - SET TO LEFT
B *+8 CONTINUE PLEASE
MVI XF,C'R' SET STATE = RIGHT
*
XC SCRFL,SCRFR ISOLATE UNIQUE BITS
XC SCRFR,SCRFL REPLACE RIGHT SIDE
XC SCRFL,SCRFR REPLACE LEFT SIDE
*
CLI KEY,@K#F1 KEY = F1 ???
BE TOGGLEX YES - EXIT ROUTINE
*
MVC 0(1,4),XF SYNCHRONIZE STATE
XC 0(7,5),8(5) ISOLATE UNIQUE BITS
XC 8(7,5),0(5) REPLACE RIGHT SIDE
XC 0(7,5),8(5) REPLACE LEFT SIDE
TOGGLEX EQU *
L 6,TOGGLE-4 RESTORE LINK REGISTER
BR 6 BRANCH ON LINK REGISTER
***********************************************************************
EJECT
Not much else to say about that... except to add some PC/370 source code.
TDFGWC.ALC - Full Source Code:
As usual, this is the full source code minus the Copybooks for Screen, Video & Key handling. Also, some commonly used variables & copybooks may appear although they aren't utilized - this makes cloning for other exercises quicker.
TITLE 'TDFGWC - PC/370 4.2 // DELIA'
***********************************************************************
* *
* MODULE: TDFGWC. *
* AUTHOR: TONY DELIA. *
* DATE: 10/22/2020. *
* DESC: PC/370 FARMER GAME. *
* NOTE: PC/370 RELEASE 4.2 *
* *
***********************************************************************
EJECT
***********************************************************************
* T D F G W C P R O G R A M *
***********************************************************************
TDFGWC START 0 START PROGRAM
STM 14,12,12(13) SAVE REGISTERS
LR 12,15 LOAD PROGRAM ENTRY POINT
USING TDFGWC+0*4096,12 BASE REGISTER 1
L 11,BASE2 LOAD BASE REGISTER 2
USING TDFGWC+1*4096,11 TELL ASSEMBLER ABOUT BASE2
L 10,BASE3 LOAD BASE REGISTER 3
USING TDFGWC+2*4096,10 TELL ASSEMBLER ABOUT BASE3
ST 13,SAVE+4 SAVE EXTERNAL SAVE ADDRESS
LR 14,13 XFER ADDRESS TO TEMP R14
LA 13,SAVE LOAD INTERNAL SAVE ADDRESS
ST 13,8(14) SAVE IN EXTERNAL SAVE AREA
B GO BRANCH TO PROCESSING RTN
***********************************************************************
RETURN EQU * TIME TO RETURN
L 13,SAVE+4 RESTORE REGISTER 13
LM 14,12,12(13) RESTORE REMAINING REGS
SR 15,15 CLEAR RETURN CODE
BR 14 BRANCH TO CALLING PROGRAM
***********************************************************************
SAVE DC 18F'0' S A V E A R E A
***********************************************************************
BASE2 DC A(TDFGWC+1*4096) BASE2 DISPLACEMENT
BASE3 DC A(TDFGWC+2*4096) BASE3 DISPLACEMENT
***********************************************************************
GO EQU * BEGIN PROCESSING ...
***********************************************************************
EJECT
***********************************************************************
* MAINLINE PROCEDURE *
***********************************************************************
PRINT NOGEN
SVC @TRACE ISSUE SUPERVISOR CALL
DC CL4'IOF ' KEYBOARD INTERRUPT OFF
*
LOOP EQU *
BAL 6,VALIDATE VALIDATE STATE
BAL 6,SCREEN BUILD SCREEN
*
CLI KEY,@K#ESC KEY = ESCAPE ???
BE LOOPX YES - EXIT PLEASE
*
CLI KEY,@K#F1 KEY = F1 ???
BE LOOPF1 YES - PROCESS KEY
CLI KEY,@K#F2 KEY = F2 ???
BE LOOPF2 YES - PROCESS KEY
CLI KEY,@K#F3 KEY = F3 ???
BE LOOPF3 YES - PROCESS KEY
CLI KEY,@K#F4 KEY = F4 ???
BE LOOPF4 YES - PROCESS KEY
*
CLI KEY,@K#F10 KEY = F10 ???
BNE LOOP NO - LOOP AGAIN
LOOPF10 EQU *
MVC XF(4),=CL4'LLLL' ALL BACK TO THE LEFT
MVC SCRFL,=CL7'FARMER' INIT LEFT FARMER
MVC SCRFR,=CL7' ' INIT RIGHT FARMER
MVC SCRGL,=CL7'GOAT' INIT LEFT GOAT
MVC SCRGR,=CL7' ' INIT RIGHT GOAT
MVC SCRWL,=CL7'WOLF' INIT LEFT WOLF
MVC SCRWR,=CL7' ' INIT RIGHT WOLF
MVC SCRCL,=CL7'CABBAGE' INIT LEFT CABBAGE
MVC SCRCR,=CL7' ' INIT RIGHT CABBAGE
MVI SCRMSG,C' ' MOVE BLANK TO MSG
MVC SCRMSG+1(L'SCRMSG-1),SCRMSG PROPAGATE THROUGHOUT
B LOOP DISPLAY SCREEN AGAIN
LOOPF1 EQU *
LA 4,XF SET STATE ADDRESS
LA 5,SCRFL SET SCREEN ADDRESS
BAL 6,TOGGLE TOGGLE POSITIONS
B LOOP DISPLAY SCREEN AGAIN
LOOPF2 EQU *
LA 4,XG SET STATE ADDRESS
LA 5,SCRGL SET SCREEN ADDRESS
BAL 6,TOGGLE TOGGLE POSITIONS
B LOOP DISPLAY SCREEN AGAIN
LOOPF3 EQU *
LA 4,XW SET STATE ADDRESS
LA 5,SCRWL SET SCREEN ADDRESS
BAL 6,TOGGLE TOGGLE POSITIONS
B LOOP DISPLAY SCREEN AGAIN
LOOPF4 EQU *
LA 4,XC SET STATE ADDRESS
LA 5,SCRCL SET SCREEN ADDRESS
BAL 6,TOGGLE TOGGLE POSITIONS
B LOOP DISPLAY SCREEN AGAIN
LOOPX EQU *
B RETURN EXIT PROGRAM PLEASE
***********************************************************************
EJECT
***********************************************************************
* TOGGLE POSITIONS *
***********************************************************************
DC F'0' RETURN ADDRESS SAVE AREA
TOGGLE EQU *
ST 6,*-4 SAVE RETURN ADDRESS
*
CLC XF,0(4) FARMER STATE EQUAL?
BNE LOOP NO - IGNORE KEY
*
CLI XF,C'L' CURRENT STATE LEFT?
BE *+12 YES - SET TO RIGHT
MVI XF,C'L' NO - SET TO LEFT
B *+8 CONTINUE PLEASE
MVI XF,C'R' SET STATE = RIGHT
*
XC SCRFL,SCRFR ISOLATE UNIQUE BITS
XC SCRFR,SCRFL REPLACE RIGHT SIDE
XC SCRFL,SCRFR REPLACE LEFT SIDE
*
CLI KEY,@K#F1 KEY = F1 ???
BE TOGGLEX YES - EXIT ROUTINE
*
MVC 0(1,4),XF SYNCHRONIZE STATE
XC 0(7,5),8(5) ISOLATE UNIQUE BITS
XC 8(7,5),0(5) REPLACE RIGHT SIDE
XC 0(7,5),8(5) REPLACE LEFT SIDE
TOGGLEX EQU *
L 6,TOGGLE-4 RESTORE LINK REGISTER
BR 6 BRANCH ON LINK REGISTER
***********************************************************************
EJECT
***********************************************************************
* VALIDATE STATE *
***********************************************************************
DC F'0' RETURN ADDRESS SAVE AREA
VALIDATE EQU *
ST 6,*-4 SAVE RETURN ADDRESS
*
MVI SCRMSG,C' ' MOVE BLANK TO MSG
MVC SCRMSG+1(L'SCRMSG-1),SCRMSG PROPAGATE THROUGHOUT
*
CLC XG,XF GOAT WITH FARMER?
BE VALIDATZ YES - NO DANGER
*
CLC XG,XW GOAT WITH WOLF???
BNE *+14 NO - OKAY SO FAR
MVC SCRMSG,ERRW YES - ERROR MESSAGE
B VALIDATX EXIT ROUTINE NOW
*
CLC XG,XC GOAT WITH CABBAGE???
BNE VALIDATX NO - EXIT ROUTINE
MVC SCRMSG,ERRC YES - ERROR MESSAGE
B VALIDATX EXIT ROUTINE NOW
VALIDATZ EQU *
CLC XF(4),=C'RRRR' ALL ITEMS ON RIGHT?
BNE VALIDATX NO - EXIT ROUTINE
MVC SCRMSG,WINMSG YES - GAME IS WON!
VALIDATX EQU *
L 6,VALIDATE-4 RESTORE LINK REGISTER
BR 6 BRANCH ON LINK REGISTER
***********************************************************************
EJECT
***********************************************************************
* BUILD SCREEN *
***********************************************************************
DC F'0' RETURN ADDRESS SAVE AREA
SCREEN EQU *
ST 6,*-4 SAVE RETURN ADDRESS
*
MVI VBITS,@BKWT SET BG(BLACK)/FG(WHITE)
BAL 6,VRESET CHANGE SCREEN ATTRIBUTES
*
* DISPLAY SINGLE BOX
*
MVC VBX,VBOX2 LOAD BOX FRAME
MVC VBXRC,BXTAB LOAD BOX COORDINATES
BAL 6,VBOX DISPLAY BOX FRAME
*
* DISPLAY SCREEN TEXT
*
LA 5,SCTAB LOAD TABLE ADDRESS
SC1LP EQU *
CLI 0(5),X'FF' END OF TABLE ???
BE SC1LPX YES - EXIT LOOP PLEASE
*
MVC VXYS,0(5) MOVE CURSOR POSITION
BAL 6,VXYSET SET CURSOR POSITION
L 2,4(5) LOAD MESSAGE ADDRESS
SVC @WTO ISSUE SUPERVISOR CALL
*
LA 5,8(,5) BUMP TABLE POINTER
B SC1LP TEST NEXT TABLE ENTRY
SC1LPX EQU *
*
* ACCEPT KEYSTROKE
*
BAL 6,KBGET READ KEYBOARD INPUT
MVC KEY,KBCHR STORE KEYSTROKE
*
CLI KEY,@K#ESC KEY = ESCAPE ???
BE SC2LPX YES - EXIT ROUTINE
CLI KEY,@K#F1 KEY = F1 ???
BE SC2LPX YES - EXIT ROUTINE
CLI KEY,@K#F2 KEY = F2 ???
BE SC2LPX YES - EXIT ROUTINE
CLI KEY,@K#F3 KEY = F3 ???
BE SC2LPX YES - EXIT ROUTINE
CLI KEY,@K#F4 KEY = F4 ???
BE SC2LPX YES - EXIT ROUTINE
CLI KEY,@K#F10 KEY = F10 ???
BE SC2LPX YES - EXIT ROUTINE
*
B SC1LPX BACK TO KEYBOARD
SC2LPX EQU *
MVI VBITS,@BKWT SET BG(BLACK)/FG(WHITE)
BAL 6,VRESET CHANGE SCREEN ATTRIBUTES
SCREENX EQU *
L 6,SCREEN-4 RESTORE LINK REGISTER
BR 6 BRANCH ON LINK REGISTER
***********************************************************************
EJECT
***********************************************************************
* WORKING STORAGE *
***********************************************************************
DUBB DC D'0' DOUBLEWORD
FULL DC F'0' FULLWORD
HALF DC H'0' HALFWORD
KEY DC CL1' ' KEY STROKE (@RDKEY)
CHAR DC CL1' ',C'$' KEY CHARACTER
@YES EQU C'Y' YES
@NO EQU C'N' NO
@ESC EQU 27 ESCAPE KEY
@CR EQU 13 CARRIAGE RETURN
@LF EQU 10 LINE FEED
@KEYLO EQU 32 ASCII KEY - LO VALUE
@KEYHI EQU 126 ASCII KEY - HI VALUE
XF DC CL1'L' STATE - FARMER
XG DC CL1'L' STATE - GOAT
XW DC CL1'L' STATE - WOLF
XC DC CL1'L' STATE - CABBAGE
ERRW DC CL60'ERROR *** WOLF EATS THE GOAT ***'
ERRC DC CL60'ERROR *** GOAT EATS THE CABBAGE ***'
WINMSG DC CL60'***WINNER*** THE FARMER DID IT! ***'
***********************************************************************
LTORG LITERAL POOL
***********************************************************************
* COPYBOOKS *
***********************************************************************
COPY CPY/TDBOX.CPY COPYBOOK - BOX DISPLAY
COPY CPY/TDVID.CPY COPYBOOK - VIDEO UTILITY
COPY CPY/TDKBD.CPY COPYBOOK - KEYBOARD INPUT
COPY CPY/TDKEY.CPY COPYBOOK - KEYSTROKES
COPY CPY/TDCLR.CPY COPYBOOK - COLORS
COPY CPY/TDSVC.CPY COPYBOOK - SUPERVISOR
***********************************************************************
* BOX COMPONENTS (COORDINATES/FRAME) *
***********************************************************************
BXTAB DS 0F
DC AL1(0,0,23,79) BOX COORDINATES/FRAME
***********************************************************************
* SCREEN DISPLAY COMPONENTS *
***********************************************************************
SCTAB DS 0F
DC AL1(0,0,2,2),A(SCR01) SCREEN COORDINATES/MSG
DC AL1(0,0,4,13),A(SCR02L) SCREEN COORDINATES/MSG
DC AL1(0,0,4,34),A(SCR02R) SCREEN COORDINATES/MSG
DC AL1(0,0,5,13),A(SCR03L) SCREEN COORDINATES/MSG
DC AL1(0,0,5,34),A(SCR03R) SCREEN COORDINATES/MSG
DC AL1(0,0,6,13),A(SCRFL) SCREEN COORDINATES/MSG
DC AL1(0,0,6,34),A(SCRFR) SCREEN COORDINATES/MSG
DC AL1(0,0,7,13),A(SCRGL) SCREEN COORDINATES/MSG
DC AL1(0,0,7,34),A(SCRGR) SCREEN COORDINATES/MSG
DC AL1(0,0,8,13),A(SCRWL) SCREEN COORDINATES/MSG
DC AL1(0,0,8,34),A(SCRWR) SCREEN COORDINATES/MSG
DC AL1(0,0,9,13),A(SCRCL) SCREEN COORDINATES/MSG
DC AL1(0,0,9,34),A(SCRCR) SCREEN COORDINATES/MSG
DC AL1(0,0,10,13),A(SCR03L) SCREEN COORDINATES/MSG
DC AL1(0,0,10,34),A(SCR03R) SCREEN COORDINATES/MSG
DC AL1(0,0,12,2),A(SCR04A) SCREEN COORDINATES/MSG
DC AL1(0,0,12,13),A(SCRMSG) SCREEN COORDINATES/MSG
DC AL1(0,0,14,2),A(SCR05A) SCREEN COORDINATES/MSG
DC AL1(0,0,14,11),A(SCR05B) SCREEN COORDINATES/MSG
DC AL1(0,0,15,11),A(SCR06A) SCREEN COORDINATES/MSG
DC AL1(0,0,16,11),A(SCR07A) SCREEN COORDINATES/MSG
DC AL1(0,0,17,11),A(SCR08A) SCREEN COORDINATES/MSG
DC AL1(0,0,18,11),A(SCR09A) SCREEN COORDINATES/MSG
DC AL1(0,0,19,11),A(SCR10A) SCREEN COORDINATES/MSG
DC AL1(0,0,21,11),A(SCR11A) SCREEN COORDINATES/MSG
DC XL1'FF' END OF TABLE
***********************************************************************
SCR01 DC C'<F1>=FARMER* <F2>=GOAT <F3>=WOLF <F4>=CABBAGE '
DC C'<F10>=RESET <ESC>=EXIT',C'$'
SCR02L DC C'LEFT',C'$'
SCR02R DC C'RIGHT',C'$'
SCR03L DC C'==========',C'$'
SCR03R DC C'==========',C'$'
SCRFL DC CL7'FARMER',C'$'
SCRFR DC CL7' ',C'$'
SCRGL DC CL7'GOAT',C'$'
SCRGR DC CL7' ',C'$'
SCRWL DC CL7'WOLF',C'$'
SCRWR DC CL7' ',C'$'
SCRCL DC CL7'CABBAGE',C'$'
SCRCR DC CL7' ',C'$'
SCR04A DC C'MESSAGE:',C'$'
SCRMSG DC CL60' ',C'$'
SCR05A DC C' RULES:',C'$'
SCR05B EQU *
DC C'A FARMER MUST CARRY A GOAT, A WOLF AND '
DC C'A HEAD OF CABBAGE ACROSS',C'$'
SCR06A EQU *
DC C'THE RIVER (ON THE RIGHT). HE CAN ONLY '
DC C'CARRY ONE THING AT A TIME.',C'$'
SCR07A EQU *
DC C'THE FARMER MUST BE ON THE SAME SIDE AS '
DC C'THE ITEM HE WILL CARRY.',C'$'
SCR08A EQU *
DC C'<F1> MOVES THE FARMER ONLY WHILE <F2> '
DC C'THRU <F4> MOVES THE FARMER',C'$'
SCR09A EQU *
DC C'AND THE OBJECT. THE GOAT CANNOT BE LEFT '
DC C'ALONE WITH THE CABBAGE OR',C'$'
SCR10A EQU *
DC C'THE WOLF. IF SO, THE GOAT OR CABBAGE '
DC C'WILL BE EATEN!',C'$'
SCR11A EQU *
DC C'THE <F1>-<F4> KEYS TOGGLE THE ITEMS TO '
DC C'THE LEFT & RIGHT.',C'$'
***********************************************************************
END TDFGWC
That was simple but fun... my next post will be a bit more complex. Another idea from my daughter's class - this time creating a fully functional Cardiac CPU Simulator - complete with it's own assembly instructions & machine code.