0 clear 49999:let a$="abcdefghijklmnopqrstuvwxyANCDEFGHIJKLMNOPQRSTUVZXYabcdefghijklmnopqrstuvwxyANCDEFGHIJKLMNOPQRSTUVZXY":let mx=65535:dim r(25)
#put variables in predictable bit of memory
1 rem Code Names by Andy 'uglifruit' Jenkinson based on the cardgame by Vlaada Chvátil

2 let l=usr 64900:rem set up the #7 stream for printing
#set up the input#7
3 let ad=0:let og=1:let du=0

4 poke 23676,249:poke 23675,56:rem UDG sysvar
#UDG stored at 249*256+56=63800
5 POKE 23658,0
6 print #7;at 23,15;paper 255;inverse 0;"PRESS ANY KEY"
7 gosub 9000:randomize :let seed=int (rnd*65535)+1:randomize seed
8 border 0:paper 0:ink 6:bright 0:flash 0:cls:goto 1000

10 let l=usr 50000:rem draw board
#draw board
11 randomize seed
15 let q$="00000"+str$(seed):print #7;ink 65;paper 0;at 23,27;"GAME ID:";chr$(peek 50031);q$((len q$-4) to );paper 255

19 print #7;at 23,0;paper 0;ink 7;"CHOOSING WORDS";paper 255
#20 dim r(25)
20 let offset=0:let nofrom=1180
21 if ad=0 then let offset=(380):let nofrom=nofrom-380:if og=0 then let offset=(780)
22 if og=0 then let nofrom=nofrom-400
23 if du=0 then let nofrom=nofrom-400
24 rem offset=start;nofrom=number of cards


30 for a=1 to 25
40 let r(a)=(int (nofrom*rnd)+1)+offset:if (ad and (not og) and du) then if r(a)>380 then let r(a)=r(a)+400
50 for b=1 to a-1:if r(b)=r(a) then goto 40
60 next b
70 let no=a-1:gosub 4050:print #7;at x,y;inverse 1;

74 let mx=r(a):let l=usr 50032
#get's the value from the VARS
#75 let l=int (r(a)/256)
#print r(a):pause 0:print l:pause 0:print r(a)-(l*256):pause0
#76 poke 50036,l:poke 50035,r(a)-(l*256)
#77 let l=usr 50032

#80 let b=50820+11*(r(a)-1):let l=int(b/256):poke 64821,l:poke 64820,b-(256*l):poke 64823,11:poke 64824,0
#85 let l=usr 64819:rem print #7 string
#to print an 11byte string at memory location 256*MSB+LSB
#poke 64820,LSB:poke 64821,MSB:poke 64823,11:poke 64824,0:let b=usr 64819

90 next a
95 print #7;inverse 0;at 23,0;"               "

99 print #7;at 23,0;paper 0;ink 7;"SETTING UP GAME";paper 255
100 for a=1 to 25:let a$(a)=chr$(7):let a$(25+a)=chr$(6):next a
105 let b=2+3*int (rnd*2):rem either 5 or 2
110 let a=int (rnd*25)+1:let a$(a)=chr$(b)
115 let a=int (rnd*25)+1:if a$(a)=chr$(b) then goto 115
120 let a$(a)=chr$(7*8)
125 for a=1 to 8
130 let c=int (rnd*25)+1:if a$(c)<>chr$ 7 then goto 130
135 let a$(c)=chr$ 2
140 let c=int (rnd*25)+1:if a$(c)<>chr$ 7 then goto 140
145 let a$(c)=chr$ 5
150 next a

160 print #7;at 23,0;paper 0;ink 65;"FIRST TEAM: ";ink b;inverse 1;" ";inverse 0;"   ";paper 255

#170 let l=usr 50006
#180 gosub 9000
185 let l=usr 50009
#190 pause 50:if inkey$="" then goto 170

200 let red=8+(b=2):let blue=8+(b=5)
210 print ink 2;at 18,5;"\a\b\c";at 19,5;"\e\e\g";at 20,5;"\d\e\f"
220 print ink 5;at 18,24;"\a\b\c";at 19,24;"\e\e\g";at 20,24;"\d\e\f"

230 print #7;at 19,13;INVERSE 0;ink 7;paper 0;"MOVE:Q,A,O,P";at 20,14;"GUESS:SPC/ENT";at 21,15;"REVEAL:R LOOK:L";paper 255

240 print #7;inverse 1;paper 255;at 19,8;red;at 19,33;blue


300 let no=10
310 let x1=int (no/3):let y1=no-(x1*3):if no=24 then let y1=1:let x1=8
315 print at x1*2,y1*10+1;over 1;bright 1;ink 8;"        + ";at x1*2+1,y1*10+1;over 1;bright 1;"          "
320 let i$=inkey$
325 if i$="r" then goto 390
326 if i$="R" then let l=usr 50006:goto 395
327 if i$="l" then gosub 700
330 if i$="" then goto 320
333 if i$=" " or i$=chr$13 then goto 400

335 let no=no+(i$="p" and y1<2)-(i$="o" and y1>0 and no<>24)
345 let no=no+3*(i$="a" and x1<8)-3*(i$="q" and x1>0)+(no=24)
350 if no>23 then let no=24

370 print at x1*2,y1*10+1;over 1;bright 0;ink 8;"        + ";at x1*2+1,y1*10+1;over 1;bright 0;"          "
380 goto 310

390 beep .1,20:print #7;at 19,13;INVERSE 0;ink 7;paper 0;"Are YOU Spymaster";at 20,13;" & are ALL others";at 21,13;"looking away? Y/N";paper 255
391 let i$=inkey$:if i$<>"y" and i$<>"n" then goto 391
392 if i$="n" then goto 397
393 let l=usr 50006:rem reveal cols
394 print #7;at 19,13;INVERSE 0;ink 7;paper 0;"                 ";at 20,13;" Any Key Returns ";at 21,13;"                 ";paper 255:gosub 9000
395 let i$=inkey$:if i$="R" then goto 395
396 let l=usr 50009:beep .1,-12
397 print #7;at 19,13;INVERSE 0;ink 7;paper 0;"MOVE:Q,A,O,P     ";at 20,13;" GUESS:SPC/ENT   ";at 21,13;"  REVEAL:R LOOK:L";paper 255
399 goto 370

400 let q=code a$(no+26):if q<>6 then goto 370
405 let l=usr 50022:rem sfx
410 let q=code a$(no+1): let a$(no+26)=a$(no+1)
420 let l=usr 50009
430 if q=56 then goto 600:rem killer
435 poke 50015,no+1:let l=usr 50012:rem draw a card
440 if q=5 then let blue=blue-1
450 if q=2 then let red=red-1
460 print #7;inverse 1;paper 255;at 19,8;red;at 19,33;blue
470 if red=0 or blue=0 then goto 500:rem someone has won!
490 goto 310

500 rem winner
510 for a=-12 to 12 step 3:beep .05,a:beep .05,a+6:next a
520 print #7;at 19,3+(q=5)*34;inverse 0;ink q;paper 0;"WIN";paper 255
530 print #7;at 23,0;paper 0;ink 66;inverse 0;"Any Key to show Owners";paper 255
538 gosub 9000
540 let l=usr 50006:print #7;at 23,0;paper 0;ink 66;inverse 0;"Any Key to show All Words";paper 255:gosub 9000
545 gosub 3500
546 print #7;at 23,0;paper 0;ink 66;inverse 0;"Press 'M' for Menu       ";paper 255
547 let i$=inkey$:if i$<>"m" then goto 547
550 goto 1000

600 rem loser
610 for a=12 to -12 step -3:beep .05,a:beep .05,a+6:next a
615 goto 530

699 rem look under card
700 let i$="":let noo=no
720 let no=no:if a$(no+26)=chr$6 then goto 800
725 beep .1,32
730 gosub 4050:print #7;at x,y;inverse 1;paper 0;paper 255;
740 let b=50820+11*(r(no+1)-1):let l=int(b/256):poke 64821,l:poke 64820,b-(256*l):poke 64823,11:poke 64824,0
750 let l=usr 64819:rem print a string
760 if inkey$<>"" then goto 760
765 beep .1,0
770 gosub 4050:print #7;at x,y;inverse 1;paper 255;"           "
#775 let b=55000+11*(r(a)-1):let l=int(b/256):poke 64821,l:poke 64820,b-(256*l):poke 64823,11:poke 64824,0
#780 let l=usr 64819
790 print #7;paper 255
800 let no=noo:return

#3499 rem reveal all cards (at end)
#3500 for a=1 to 25
#3510 let no=a-1:gosub 4050:print #7;at x,y;inverse 1;
#3520 let b=55000+11*(r(a)-1):let l=int(b/256):poke 64821,l:poke 64820,b-(256*l):poke 64823,11:poke 64824,0
#3530 let l=usr 64819:rem print #7 string
#3540 next a
#3550 return

1000 border 0:ink 6:bright 0:paper 0:over 0:cls

1030 print at 1,2;ink 7;"\a\c \a\c \b\c \a\b \b\c \a\b \b\b\c \a\b \a\c";\
at 2,0;paper 2;"  \g\g \g\g \g\g \e\b \g\g \g\g \g\g\g \e\b \d\c  ";\
at 3,0;paper 2;"  \g\b \g\g \g\g \e\b \g\g \g\g \g\g\g \e\b \g\g  ";\
at 4,2;paper 0;"\d\f \d\f \e\f \d\e \g\g \d\e \g\g\g \d\e \d\f"

1035 let i$=chr$13+"         "
1040 print #7;ink 6;paper 0;at 6,3;inverse 0;"Based on the game by Vlaada Chvatil"

1050 print #7;at 9,0;ink 5;"Word Sets Being Used:";i$;"[1] DEEP UNDERCOVER (18+)";i$;i$;"[2] ORIGINAL";i$;i$;"[3] DUETS"

1051 print #7;ink 5;at 21,9;"[0] START GAME ";paper 255

1053 let q$="00000"+str$(seed):print #7;ink 6;at 16,9;"[4] GAME ID/SEED : ";q$((len q$-4) to );at 18,9;"[5] INSTRUCTIONS"

#show word sets' statuses
1055 print at 10,28;ink ad*3+1;"\g";\
at 12,28;ink og*3+1;"\g";\
at 14,28;ink du*3+1;"\g"


2000 let i$=inkey$:if i$>"5" or i$<"0" then goto 2000
2010 if i$="0" then goto 2600
2015 if i$="5" then goto 5000
2020 if i$<>"4" then goto 2300
2025 let k$=""
2030 POKE 23658,8:input ink 6;"Game ID/Seed: [ENT=rand] ";line x$:POKE 23658,0:if x$="" then goto 2500
2040 if x$(1)<"0" or x$(1)>"9" then let k$=x$(1):let x$=x$(2 to)
2050 for a=1 to len x$: if x$(a)<"0" or x$(a)>"9" then beep .5,-7:goto 2030
2060 next a

2070 if k$="" then let k$=chr$(ad+2*og+4*du+64)
2080 poke 50031,code k$:let ad=usr 50028:let og=usr 50028:let du=usr 50028
2090 if peek 50031<>8 then beep .5,-7:goto 2030
2095 let l=val ("0"+x$):if l>65535 then beep .5,-7:goto 2030
2100 let seed=l

2200 let l=usr 50025:goto 1053

2300 rem change the options
2310 if i$="1" then let ad=not ad
2320 if i$="2" then let og=not og
2330 if i$="3" then let du=not du
2340 let l=usr 50025:goto 1055

2500 rem generate random seed
2510 randomize :let seed=int (rnd*65535)+1:randomize seed
2520 let l=usr 50025:goto 1053

2600 rem final check and start game setup
2610 let l=(ad+2*og+4*du+64)
2620 if l=64 then beep .5,-7:print #7;at 23,1;"You must have a word-set selected to play":goto 2000
2630 poke 50031,l
2640 goto 10


3499 rem reveal all cards (at end)
#3500 for a=1 to 25
#3510 let no=a-1:gosub 4050:print #7;at x,y;inverse 1;
#3520 let b=50820+11*(r(a)-1):let l=int(b/256):poke 64821,l:poke 64820,b-(256*l):poke 64823,11:poke 64824,0
#3530 let l=usr 64819:rem print #7 string
#3540 next a
3500 print #7;inverse 1;over 0;
3510 let l=usr 50037:rem print all cards in correct position
3550 return


4000 rem generates x,y co-ordinates from 'no' (0-24)
4010 let no=no:let x=int (no/3):let y=no-(x*3):if no=24 then let y=1:let x=8
4020 let x=x*2:let y=y*10+1:return

4050 rem generates x,y #7 co-ordinates from 'no' (0-24)
4060 let x=int (no/3):let y=no-(x*3):if no=24 then let y=1
4070 let x=2*x+1:let y=y*14+2:if y>10 then let y=y-1
4080 return

4999 rem instructions
5000 gosub 7000
5010 print #7;at 6,2;ink 6;bright 0;flash 42;paper 0;"A game for 2 teams.  Each team selects  a SPYMASTER who must give a SINGLE WORD   clue that links the team's words together.  This CLUE WORD must be followed by a    number, indicating how many words are     linked."
5030 print #7;"  An example might be the clue ";ink5;"'FEET, 3'";ink6;"  which could be trying to link ";ink5;"SHOE, INCH ";ink 6;" and ";ink 5;"HOOF. ";ink6;" But be careful!  You don't wantto accidentally link OPPONENTS words (e.g.";ink2;"SOLE";ink6;" )"
5040 print #7;"  The team guess words ONE AT A TIME, to  see if they are ";ink5;"THEIR TEAM'S";ink 6;" words - but  if they pick a word which is ";ink7;"NEUTRAL ";ink 6;"or   the ";ink 2;"OPPONENT'S ";ink 6;"then the turn is over."
5050 print #7;"  Accidentally guessing the ";inverse 1;ink 7;" KILLER ";inverse 0;ink 6;" word immediately loses the game!"
5060 gosub 9000:gosub 7000
5070 print #7;at 6,2;"The team has UP TO ONE MORE guess than  the number given in the clue, so the team could guess up to 4 words with the        previous clue.  A clue with ZERO on the   end is a special case which allows as manyguesses as the team dares!"
5075 print #7;chr$13;"  The guessing team can give up at any    time and end their team's go.";chr$13
5080 print #7;"  Whilst playing, the SPYMASTERS (alone)  can reveal the owners of all words to     think up their clues whilst everyone else looks away."
5082 print #7;chr$13;"  Anyone can look under a previously      guessed word to check what it was at any  time."
5085 gosub 9000:gosub 7000
5090 print #7;at 6,2;"After one team has made their guesses,  then the other team's SPYMASTER gives a   clue for THEIR team."
5100 print #7;chr$13;"  Once one team has revealed ALL of their words successfully, they win!"
5110 print #7;chr$13;"  Remember: revealing a word NOT from yourteam ends your team's turn even if you    have guesses left, and revealing the      KILLER word loses the game."
5150 gosub 9000:gosub 7000

5220 print #7;chr$13;at 6,2;"This version of Codenames includes all  of the words from the Original card game, the DEEP UNDERCOVER (18+) release, and theDUETS words - which can be mixed freely,  or played with as individual sets."
5230 print #7;chr$13;"  If you are playing online (via ZOOM, or similar), you will need to ensure all     players have the same board state.  This  is done using the GAME ID/SEED.  When you start a game you are given a GAME ID.  If this is entered into the menu of another  game it will select the same word set and board layout enabling remote play."
5240 gosub 9000:gosub 7000
5250 print #7;at 6,3;"Ideally for remote play you'll have thetwo SPYMASTERS looking at one copy of the game, and everyone else looking at a      different copy - but as long as there are NO CHEATERS you can all play remotely     quite happily."
5260 print #7;at 22,0;"Game design: Vlaada Chvatil.";chr$13;"ZX Spectrum version: Andy Jenkinson."


5900 gosub 9000:gosub 7000:goto 1035

7000 print at 0,0;:input ink 2;at 0,0;"\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''";at 17,0;:return

8999 rem debounced 'pause 0'
9000 let i$=inkey$:if i$<>"" then goto 9000
9001 let i$=inkey$:if i$="" then goto 9001
9002 return


9998 save "C"code 50000,15536:save "C" line 0:stop
9999 clear 49999:print #0; "load":gosub 9000:load "" code:run




