Retrocomputing

Othello

Program listing

5 on error goto 9000
10 rem START OF PROGRAM
20 width 0
100 rem INITIALIZE
105 gosub 400
110 bd$="...........................XO......OX..........................."
120 print cl$
130 print chr$(27)+"cA02E00000000000000100000000000000000"+chr$(19)
140 print chr$(27)+"cA12E00000000000000100000000000000000"+chr$(19)
145 gosub 1100:rem set display with board
149 pf%=1:rem panic factor
150 gosub 6900:rem read position values from panic table
399 goto 500
400 rem read the ttycap file to extract the terminal capabilities
401 open old "/etc/termcap" as 2
402 rem 1=cursor home
403 rem 2=cursor up, 3=cursor down, 4=cursor left, 5=cursor right
404 rem 6=clear screen, 9=erase to EOL, 10=set dim, 11=set normal
405 rem 7=position cursor parameter string, see crt_termcap document
406 rem input tc=value from table, output tc$=string of interest
410 rem read a string at the time and put it in correct place
420 tc%=1:gosub 490:ch$=tc$
421 tc%=9:gosub 490:ce$=tc$:rem read erase to EOL
422 tc%=10:gosub 490:pd$=tc$
423 tc%=11:gosub 490:pn$=tc$
424 tc%=6:gosub 490:cl$=tc$
425 tc%=5:gosub 490:cf$=tc$:rem cursor forward
426 tc%=3:gosub 490:cd$=tc$:rem cursor down
427 tc%=4:gosub 490:cb$=tc$
428 tc%=2:gosub 490:cu$=tc$:rem cursor up
489 return
490 tc$=""
491 position #2,2*val(term$),mode 0:rem read the address in file of terminal
492 let po$=inch$(2)+inch$(2):position #2,2*tc%+2+cvt$%(po$),mode 0
493 let po$=inch$(2)+inch$(2):position #2,cvt$%(po$)-2*tc%-4,mode 1
495 let tc$=tc$+inch$(2):if right$(tc$,1)<>chr$(0) goto 495
499 return
500 close 2
510 p$="X":s$="O"
520 cm%=0:rem common area pointer
525 print ch$;string$(chr$(10),11);
530 print "       The higher, the better (1-9):";
532 i$=inch$(0)
533 dl%=(asc(i$)-48):if dl%<1 or dl%>9 goto 532
600 rem set up used variables and comment them
610 dim my%(7):rem index for board string instead of multiply
620 for my%=0 to 7:my%(my%)=8*my%:next my%:rem See..its done here instead
630 dim px%(64):dim py%(64)
640 for qy%=0 to 7:for qx%=1 to 8:px%(8*qy%+qx%)=qx%-1:py%(8*qy%+qx%)=qy%:next qx%:next qy%
650 dim sa(64)
660 sx%=18:hx%=47
670 dim da%(64):rem holding direction detection flags on board..!#$
680 restore 8900:for a%=1 to 64:read da%(a%):next a%
690 dim do%(20)
695 restore 696:for a%=0 to 20:read do%(a%):next a%
696 data -9,-8,-7,-1,0,0,0,0,0,1,0,7,0,0,0,0,0,8,9,0,0
1000 rem MAINLOOP
1010 gosub 1200:rem ask for side
1015 if CB$="X" goto 1060
1020 gosub 2000:rem player inputs, and play help!
1025 if nm%=1 and vm$="" goto 1500:rem no moves any part
1030 gosub 1100:rem update display
1040 gosub 5000:if x%=1 goto 1500:rem end of game detected
1050 swap p$,s$:rem swap side
1052 if mo%>56 and pf%<>6 then pf%=6:gosub 6900
1055 om%=tm%
1057 for i%=0 to 64:sa(i%)=0:next i%
1058 print ch$;string$(chr$(10),19);"   ";
1060 tm=second:gosub 4000:tm=second-tm
1065 print ch$;string$(chr$(10),17);"  ";tm%-om%;"moves took";int(tm+.5);"seconds   ";
1070 gosub 3700:rem move selection
1075 gosub 1100:rem update display
1080 swap p$,s$:goto 1020
1100 rem print borard
1101 print ch$;string$(chr$(10),1);
1105 print "       "+" 1  2  3  4  5  6  7  8"
1110 for qy%=0 to 7
1115 print "    ";qy%+1;pd$;
1117 for qx%=1 to 8
1120 print " ";mid$(bd$,8*qy%+qx%,1);" ";
1130 next qx%
1135 print pn$
1140 next qy%
1145 print op$
1199 return
1200 rem ask for side
1203 print
1205 print "      X will start !   "
1210 print "      WHAT LETTER DO YOU WANT ? (O/X) :";
1220 let i$=inch$(0):if i$<>"o" and i$<>"x" and i$<>"O" and i$<>"X" goto 1220
1230 if i$="X" or i$="x" then CB$="O" else CB$="X":rem opposite of player.
1240 if CB$="X" then OB$="O" else OB$="X"
1250 print ch$;string$(chr$(10),11);spc(40)
1251 print spc(45)
1252 print spc(45)
1253 print spc(45)
1260 print ch$;string$(chr$(10),11);"   YOU HAVE ";pd$;" ";OB$;" ";pn$
1262 print
1264 print "   I look ";dl%;" moves ahead";
1290 print
1299 return
1300 rem PRINT POSSIBLE MOVES
1310 print ch$;chr$(10);chr$(10);string$(cf$,40);" YOUR POSSIBLE MOVES:"
1315 if vm$="" then print chr$(10);string$(cf$,40);" You can't move, of course!":return
1320 print
1330 print string$(cf$,40);" use ENTER to select the position"
1340 print string$(cf$,40);" use SPACE to select another position"
1399 return
1400 rem INPUT A MOVE SELECTION
1405 if vm$="" then return
1415 i%=len(vm$)
1416 v%=1
1417 print ch$;string$(chr$(10),2+py%(asc(mid$(vm$,v%,1))));string$(cf$,7);pd$;chr$(8);chr$(8);
1418 print string$(cf$+cf$+cf$,1+px%(asc(mid$(vm$,v%,1))));"*";chr$(8);
1420 i$=inch$(0)
1421 if i$<>" " and i$<>chr$(13) then print chr$(8);"*";chr$(8);:goto 1420
1422 if i$=" " then v%=1-(v%<i%)*v%:print chr$(8);".";:goto 1417
1460 vm$=mid$(vm$,v%,1)
1490 print ch$;string$(chr$(10),2);string$(cf$,40);
1491 i%=5
1492 print ce$;chr$(10);
1493 i%=i%-1:if i%>0 goto 1492
1495 print pn$
1499 return
1500 rem END OF GAME
1505 x%=0:o%=0:for i%=1 to 64:let x%=x%-(mid$(bd$,i%,1)="X"):o%=o%-(mid$(bd$,i%,1)="O"):next i%
1507 print ch$;string$(chr$(10),11);string$(cf$,40);pd$;" X ";pn$;"= ";x%;"  ";pd$;" O ";pn$;"= ";o%;
1510 print ch$;string$(chr$(10),7);string$(cf$,40);"End of game..again? (y/n):";
1520 i$=inch$(0)
1530 if i$="y" or i$="Y" goto 5
1540 if i$<>"n" and i$<>"N" goto 1520
1590 goto 9000
1599 stop
2000 rem USER MOVE INPUT AND CHECK
2010 gosub 3600:rem investigate board for valid moves
2015 if vm$="" and nm%=1 then return
2020 gosub 1300:rem print possible moves
2030 gosub 1400:rem input a valid selection
2040 i%=asc(vm$):gosub 3200
2050 mo%=mo%+1
2099 return
3000 rem CHECK FOR VALID MOVES (examine area for opponent)
3001 if mo%<50 goto 3100
3005 a%=0:t$=left$(bd$,hx%)
3010 i%=instr(i%+1,t$,".")
3011 if i%=0 then return
3013 dt%=-10
3014 dt%=do%(dt%+10):if dt% then t%=i% else goto 3010
3015 for a%=0 to 10
3016 t%=t%+dt%:if t%<1 or t%>64 goto 3014
3017 if da%(t%)+da%(t%-dt%)=0 goto 3014
3018 q$=mid$(bd$,t%,1)
3019 if q$="." goto 3014
3021 if q$=s$ then next a%
3022 if q$=p$ and a% then return
3030 goto 3014
3100 rem check for valid moves
3105 t$=left$(bd$,hx%)
3107 if dt% goto 3114
3110 o%=instr(o%+1,t$,p$)
3111 if o%=0 then i%=0:return
3113 dt%=-10
3114 dt%=do%(dt%+10):if dt% then t%=o% else goto 3110
3115 for a%=0 to 10
3116 t%=t%+dt%:if t%<1 or t%>64 goto 3114
3117 if da%(t%)+da%(t%-dt%)=0 goto 3114
3118 q$=mid$(bd$,t%,1)
3119 if q$=p$ goto 3114
3121 if q$=s$ then next a%
3122 if q$="." and a% then i%=t%:goto 3140
3130 goto 3114
3140 rem
3145 return
3200 rem DO A MOVE
3210 xx%=px%(i%):yy%=py%(i%)
3215 for dx%=-1 to 1:for dy%=-1 to 1
3220 if dx% or dy% then goto 3221 else goto 3260
3221 mx%=xx%:my%=yy%
3225 mx%=mx%+dx%:my%=my%+dy%
3230 if (8 and (mx% or my%))>7 goto 3260
3235 a$=mid$(bd$,my%(my%)+mx%+1,1)
3240 if a$="." goto 3260
3242 if a$=s$ goto 3225
3250 mx%=mx%-dx%:my%=my%-dy%
3253 bd$=left$(bd$,my%(my%)+mx%)+p$+mid$(bd$,my%(my%)+mx%+2)
3255 SC%=SC%+((asc(mid$(pv$,my%(my%)+mx%+1))-40)*((p$=OB$)-(p$=CB$)))*(8/(cl%+1))
3257 if mx%-xx% or my%-yy% goto 3250
3258 if sx%+9>i% then sx%=i%-10:if sx%<0 then sx%=0
3259 if hx%-9<i% then hx%=i%+10:if hx%>64 then hx%=64
3260 next dy%:next dx%
3262 tm%=tm%+1
3269 return
3600 rem examine for valid moves. for opponent
3605 vm$=""
3610 i%=sx%:o%=sx%
3625 gosub 3000
3630 if a% then vm$=vm$+chr$(i%)
3640 if i%<>0 goto 3625
3650 return
3700 rem SELECT A MOVE FROM THE SCORE ARRAY
3710 sc=-30000:v%=0
3720 for i%=1 to 64 
3730 if sa(i%)>=sc+2*rnd(0) and sa(i%)<>0 then sc=sa(i%):v%=i%
3740 next i%
3750 if v%=0 goto 3790
3780 i%=v%:gosub 3200
3785 mo%=mo%+1
3790 print ch$;string$(chr$(10),15);string$(cf$,3);"I MOVED :";
3795 if v%=0 then print "Can't move"; else print 1+xx%;",";1+yy%;
3797 print ",total moves";tm%;
3798 print chr$(7);
3799 return
4000 rem RECURSIVE EVALUATOR:stop on 1:memory out 2:game end 3:defined depth
4010 cm%=cm%+128:common cm%:rem add on to common area, push variables
4011 field common,64 as BD$,1 as P$,2 as iv$,2 as sc$,1 as sx$,1 as hx$,1 as dt$
4015 lset sc$=cvt%$(SC%):lset BD$=bd$:lset P$=p$:lset sx$=chr$(sx%):lset hx$=chr$(hx%)
4020 i%=sx%:dt%=0:o%=sx%:cl%=cl%+1:rem set up used variables
4025 gosub 3000
4030 if i%=0 goto 4080:rem exit if no more
4040 if cl%=1 then I%=i%:print ".";
4045 gosub 3200:rem execute the move found
4050 gosub 5000:if x%=0 then swap p$,s$:lset dt$=chr$(dt%+32):lset iv$=chr$(i%)+chr$(o%):gosub 4000:i%=asc(iv$):o%=asc(right$(iv$,1)):dt%=asc(dt$)-32
4060 sa(I%)=sa(I%)+SC%:rem add deepest score in movearray
4065 bd$=BD$:SC%=cvt$%(sc$):p$=P$:sx%=asc(sx$):hx%=asc(hx$):rem restore board,score and side
4068 if p$="X" then s$="O" else s$="X"
4075 goto 4025:rem examine moves until fully explored in all levels
4080 rem exit recursive loop, restore variables
4085 cm%=cm%-128:cl%=cl%-1
4086 if cm% then common cm%:field common,64 as BD$,1 as P$,2 as iv$,2 as sc$,1 as sx$,1 as hx$,1 as dt$
4099 return
5000 rem EVALUATE IF RECURSIVE LOOP MUST STOP: x%=0 if not.
5005 x%=1
5010 if instr(1,bd$,"X")=0 or instr(1,bd$,"O")=0 or instr(1,bd$,".")=0 then return
5020 if mem(0)>50000 then print ch$;string$(cf$,10);"Migraine";:return
5090 x%=(dl%=cl%)
5099 return
6900 rem read position values, dependent on number of moves left
6901 rem                                and the panic factor
6905 on pf% gosub 6911,6912,6913,6914,6915,6916,6917,6918,6919
6907 PF%=pf%
6910 return
6911 restore 8020:goto 6920
6912 restore 8010:goto 6920
6913 restore 8030:goto 6920
6914 restore 8040:goto 6920
6916 restore 8030:goto 6920
6920 rem loop reading values
6921 pv$=""
6922 for q%=0 to 7
6925 read v$:pv$=pv$+v$
6930 next q%
6949 return
7000 rem SPECIAL GAMES CONTROLS
7010 print ch$;string$(chr$(10),21);"  ENTER new deepest level:";
7020 input dl%
7030 dl%=dl%+(dl%>0)
7099 resume 
8019 rem board values for pf%=1
8020 data "laceecal"
8021 data "a.ABBA.a"
8022 data "cAJDDJAc"
8023 data "eBGCCGBe"
8024 data "eBGCCGBe"
8025 data "cAJDDJAc"
8026 data "a.ABBA.a"
8027 data "laceecal"
8030 rem End game values
8031 data "AAAAAAAA"
8032 data "AAAAAAAA"
8033 data "AAAAAAAA"
8034 data "AAAAAAAA"
8035 data "AAAAAAAA"
8036 data "AAAAAAAA"
8037 data "AAAAAAAA"
8038 data "AAAAAAAA"
8900 rem board edge detection flags
8901 data 1,2,3,4,5,6,7,-1
8902 data 1,2,3,4,5,6,7,-1
8903 data 1,2,3,4,5,6,7,-1
8904 data 1,2,3,4,5,6,7,-1
8905 data 1,2,3,4,5,6,7,-1
8906 data 1,2,3,4,5,6,7,-1
8907 data 1,2,3,4,5,6,7,-1
8908 data 1,2,3,4,5,6,7,-1
9000 rem ERROR HANDLER
9010 if err=8 then resume 9900:rem END OF FILE
9020 if err=34 then resume 9900
9800 rem UNKNOWN ERROR HANDLER
9810 if err<>0 then exec,"basicerror"+str$(err)
9820 if err<>0 then print "      in line "+str$(erl)
9890 if err<>0 then resume 9900
9900 rem EXIT PROGRAM
9910 print chr$(27)+"cA02E00000000000000000000003030000000"+chr$(19)
9911 print chr$(27)+"cA12E00000000000000000000003030000000"+chr$(19)
9999 end