PATIENCE
by Mike Eida
from ZX Computing Feb/Mar.1984

Have you got the patience to play
Mike Eida's excellent card game program?


This started life as a programming exercise but soon
developed into a challenge. When finished I not only had a
good game but had also used just about every programming
procedure in the book - it was this that made me think that
it would be useful to others who may be struggling a bit.

The game played is the 'standard' Patience. There are seven
piles of cards each having one more card than that to its
left. The first pile has only one card and the last card on
each pile is face up. The remaining cards form a reserve. To
play, any card may be placed on top of another of the other
colour and it must be one less in value; ie. nine of clubs
on ten of hearts. You win with four columns from King down
to Ace. You may play a variation whereby the Aces are placed
above the play and you can put on each Ace the next card of
that suit. In this case you win by having four complete
suits.

The game starts by the ZX81 telling you what it is doing and
laying out the starting position with only seven cards
showing. If you cannot go, press Newline and one of the
reserve cards will be shown. If that card is used the card
under it becomes visible and is playable if required. The
reserve cards are turned over in threes. You have lost when
no more moves are possible. At this point an input of 'R'
will give a shuffle and a new deal.

To place one card on another type first the card to be moved
followed by the card to be covered. To put an Ace above the
playing area input it alone. The same applies to build on
the Ace. The program will not let you cheat and is utterly
'mugproof'. Be warned - if you input a card that is not
visible or try to place one card in the middle of a line
then the computer won't play!!


How it works

Now lets see how it all works. The pack of cards is made in
lines 2 to 35. It resides in the string C$. Many programs
use an array at this point but that at times makes it harder
to use later on. Line 2 is essential to initialise the
string; ie. to tell the computer to expect it. Then when it
gets to line 25 the C$ after the = won't cause an error.
Also in this line we use the handy adding or concatenation
(horrible word), of strings. This just makes C$ equal to one
string containing the various titles. In this part two loops
are used one inside and the other to join the numbers of the
cards to the sits [sic] which are in strings E$ and B$. The
first time through the loop B$(N) will be 'H' and will
remain so while E$ takes on the values of A to K as M goes
from 1 to 13. Only then will the program run past line 30
and let N increase to 2. When complete C$ will =
"AH2H3H.......JSQSKS".

Lines 40 to 70 shuffle the pack just made. First a loop is
set up the length of C$ (52 cards * 2 letters per card =
104) and we want to look at each card in turn - STEP 2. Line
45 follows A to take on a random number from 0 to 103
inclusive. Now the beginning of each card name in string C$
is an odd number from the start so line 50 makes A always
odd. If it were even then the statement would be true, INT
the whole number part of the division would equal the
division A/2, and A would be increased by one making it odd.
Line 55 stores the first card in our string in D$. This is
only a temporary store. The first card in the string C$ is
even then changed for the card selected by the random A. We
now have two cards the same so line 65 lets the random card
be equal to what was the first card from the temporary store
D$. By the time N reaches 104 the pack is well and truly
shuffled.

Lines 74 to 93 set up variables to be used later. Z is made
equal to the start of the display file pIus 66. This is the
address of the beginning of the third line on the screen
when the game is displayed so the computer will know where
to start looking for the cards.

The next loop (lines 95 to 109) prints the card to the
screen. C specifies the line and B the column into which the
card is placed: C$ (A TO A+1) but only if it is the first
card in that line: line 100 sees to that. Line 103 prints
the blanks and puts the CHR$ A so the computer knows which
card is hidden. In this way we are playing with a real pack
and not with randomly selected cards. This may be more
important for some games. A is then increased by two to look
at the next card in C$. Line 114 changes the line, 115
spaces the cards and 117 reduces the number of cards in each
line. Line 120 checks to see if D has reached 0 and if not
it goes back for more cards. This works thus: 'IF variable
is not zero THEN carry this out'.

V$ contains the rest of the cards not dealt. There is
nothing after the word TO. The computer will assume 'to the
end of the string' if we don't tell it where to stop.

Line 130 will let us INPUT a card to the game.


Getting into action

Now we come to a series of instructions so that the input
can be translated into actions. 131 shuffle and deal again.
135 not enough input do it again. 136 if a king is to be
moved to an empty column and the game rules state that ONLY
a king may do this, then do it. 137 to make sure the cards
are of the other colour. The codes of H and D are odd and C
and S are even so only one of each pair together will come
out odd. If they are even then input again. 138 a subroutine
explained later. 139 V$ is the reserve pack if it has all
gone the next line won't work so skip it. 140 if the first
card you input is the one showing on the reserve pile then
another subroutine is required. This time GOSUB may be used
instead of GOTO because the program will always come back to
142; ie. the subroutine will not send it elsewhere. If it
did then return addresses would pile up on the GOSUB stack
and clog the memory with information that would never be
used. 142 prepare another string.

Another loop from 144 to 150. This one looks at the cards on
the screen. Remember we set Z earlier on. Now if we add N to
it we can look along the screen lines for the card we want.
If we PEEK the address of a spot on the screen we will get
the CODE of whatever is printed there. 0 is a space. 145 if
a space then next one please. 146 we're using X here to say
whether we're looking at the first card in the input A$ or
the second - 0 is the first card. Well if A$ is only one
card LEN + 2, how can it be the second one we look at? This
is because it is a card already laid in the game and we want
to put it on its suit pile above the playing area. 147 if
the first card equals a card in the game go to a subroutine.
148 if it's one card skip the next line. 149 if the second
card equals one on the game go to subroutine.

When this loop ends and we reach 155 it must mean that one
or other cards did not exist. You've been caught cheating!!

Lines 160 and 168 move the selected card and uncover the one
beneath. 160 if the card above the one picked is not a
covered card then subroutine. It finds the one above by
taking 33 from the present position. There are 32 characters
to each line and each line is followed by a Newline
character so that the memory knows where the lines end. 161
if we try to move a card to its suit pile and it's not on
the end of a column then input again. 162 & 163 rub out the
card to be moved. 164 Y has collected a value from a
subroutine the card is the top one in a column, then go to
subroutine. If + 33 = 0 (a space) it must be the top. Line
160 told us there was no card above. 166 & 167 look at the
blank above the wiped out card and read its CODE. We put
that there earlier so that we knew which card was hidden.
This will tell us where it is in C$. Now we have to convert
it, the card in C$ that is, to CODE so that it may be POKEd.
168 to blank out the extra character used for face down
cards. 187 if there are more cards under the one just rubbed
out go to subroutines to remember them. 188 add one to X.
189 zero Y. 190 if we have not looked at both cards of the
input go back and look at the second one. 191 we've looked
at both go back for more input.


On the other hand

192 & 193 a subroutine to print two full stops at the top of
an empty column. 197 to 202 all the second cards of the
input come here. If the second input is not "..." then 33 is
added. You are now looking at the line below the rubbed out
first card and if it's not blank (line 200) then you are
trying to place one card on another, cheating AGAIN!!!! If
the second entry is "..." then 197 will look at the line
above and line 198 will cancel it and look at the correct
line to find the dots. 199 if the dots are there go ahead
and print the King. The fact it is a King has been checked
already - we'll get to that subroutine later.

201 and 208 prints the rubbed out card and any that were
below it, beneath the card selected by the second input.
That is the second card of the input A$. 201 & 202 print
rubbed out card. 203 if no more cards under rubbed out card
go back to say second part of operation complete; ie. X now
is 2. 204 get next line ready. 205 & 206 print next card in
Z$. 207 let Z$ equal what it was less the first card already
printed. 208 if there are more cards in Z$ - go back and
print them. 209 Z$ is empty go back - operation complete.

220 & 230 is one of the routines to find out which suit the
first card is by comparing it with B$.

237 & 238 subroutine to put a single card on its suit pile
above the game. N is the suit found above times 3 then POKE
it in position two lines above the game Z-66 and along N
times suit spaces along that line.

252 to 255 subroutine to select a card from the reserve pack
and print it below the game. 252 move along 3 cards. 253 if
F gets too small start at the beginning again. 254 if V$ is
empty don't try to print it in the next line. 255 print the
card where indicated.

280 to 295 subroutine to rub out reserve card used and print
in its place the one underneath. 280 the card printed is V$
(F TO F+1); this line removes it from V$. 282 if V$ is empty
then skip the lines used to print it. 284 F must be at least
3 so that V$(F-2) may be printed. 286 print the card one
less than V$ (F TO F+1); ie. the one underneath. 287 adjust
F so that the next card printed from the reserve will be 3
on from the underneath card and not from the original. 293
let user know reserve pack is empty. 294 let computer know
that step is completed. 295 go to line after GOSUB statement
that brought us to line 280 in the first place. 300 to 307
is a loop to make sure the two cards in input A$ are only
one number different and that the first one is the lower.
301 if there are two cards in input skip the next two lines.
302 if there is one card and it's not an Ace and there are
no cards already laid above the game then you can't do it.
303 this is a way of re-using the IF statement. If there is
something in the suit pile above the game and if the card is
not the next one as compared with string E$ then you can't
do it. 304 if only one card skip the next line. 305 if the
numbers of the two input cards do not follow correctly start
again.


Checking up

Now the last loop was looking for those cards which were NOT
correct. Loops are usually used to find items which satisfy
criteria but using it this way round allows us to use the
same loop twice and send the correct items in each pass to
different places in the program. 308 if X is not zero go to
one place. 310 if X therefore is zero then go to another.

315 to 325 are statements to show cheating and to stop the
game. There must eventually be some punishment for
persistent short cut takers!

330 this has been put here purposely to show that a SAVE
statement need not be put at the end of the program. If you
start your tape and enter GOTO 330 then NEWLINE, the program
will be saved with the title "P". When you play it back with
LOAD "P" it will do so when it sees line 335 RUN without
listing the program first. This can be very important with
programs which have variables stored in memory and these are
needed to make it work. RUN will destroy all memory so if
you put GOTO after the SAVE statement then you won't rub
them out in error.

Lines 350 to 355 end subroutine - all inputs come here to
find out if there are cards above or below. 350 identify
blank above - top of column. 351 one card only in input and
it's not the bottom card in column; illegal. 352 give value
to Y so that the difference can be seen between a blank
above the first card entered, exposed card above or a
covered card above.

Having played the game and studied the program with these
notes it is hoped that not only do you understand how it
works but that the various methods used will enable you to
write better programs yourself.


--
Another Fine Product transcribed by:
Jim Grimwood (jimg@globalnet.co.uk), Weardale, England
--
