Connect 4 by Jose Javier Franco Benítez
A downloadable game
--------------------------------------------------------------------
CONNECT 4 - A Classic Game in just 10 lines for MSX 1st generation
--------------------------------------------------------------------
Connect 4 is a well-known classic game where you have to get four disks in the same diagonal, horizontal or vertical line.
The game starts answering who will be the first to move, if you press 'Y' or 'y', you will play the first, anything else
makes computer play. Use the left and right arrows to move your disk over the chosen colum and the down arrow to drop it,
afterwards the program takes a little time to check whether 4 disk-in-line is done, if so, you win, if not, computer thinks
and checks lines.
Once the game ends up, press 'return' to restart the program.
The game can be played on real computers but it is recommended to take advantage of emulators. The program takes 1 minute
and half or so to choose its movement. It is not very fast but... it is playable and the first game in 10liners contest on
its kind. If openmsx is used, you can press F9 key to hasten the program. Another option is to go to the msxpen web page and
'copy and paste' the code there, this online emulator also allows you to make the code faster.
--------------
INSTRUCTIONS
--------------
Real machines: save the cnt4.wav file in a real cassette for using it on your favorite MSX and type RUN"CAS:" plus return
Emulators: open the cnt4.wav file in BlueMSX/Openmsx/fmsx/RuMSX or whatelse and type RUN"CAS:" plus return
MSXPEN: Go to https://msxpen.com/ webpage and copy and paste the code inside cnt4.bas file
--------------
FILES INSIDE
--------------
cnt4.txt This text
cnt4.bas Game saved in ASCII mode (listeable on any text editor)
cnt4.png Picture
cnt4.wav Audio file program for emulators and real machines
---------------------------
Author and released year:
--------------------------
José Javier Franco Benítez as current MSXVR user :P
Copyleft 2021
Category: Extrem-256 - MSX1
-------------------------------------
Here you find the code explanation:
-------------------------------------
line 10
DEFINT A-Z ; Define as intenger all vars which initials go to A till Z
DIM B(50) ; Define B array which holds all gameboard values. It has more than it is needed, just 42 values are used
DIM L(7) ; Define L array for upper bounder for every colum
COLOR 7,1,1 ; Swicht color to light blue and black
SCREEN2,2,0 ; Set mode screen
OPEN"GRP:"AS#1 ; Allow to write on graphic mode
FOR I=0 TO 7 ; Retrive text messages from datas
READ T$(I)
NEXT
FOR J=0 TO 1 ; Define disk sprites (filled and empty one)
A$=""
FOR I=1 TO 32
READ D
A$=A$+CHR$(D)
NEXT
SPRITE$(J)=A$
NEXT
ON INTERVAL=100 GOSUB 100 ; Set interruption routine which will be executed every 2 seconds after activating
DEFUSR=&HB1 ; Set BIOS call for waiting for RETURN pressed
FOR I=5 TO 7 ; Set Title and allow you to decide who will start the game
PSET(2,I*8-16-120*(I=7))
PRINT#1,T$(I)
line 20
NEXT
FOR I=28 TO 32
CIRCLE(128,96),I,11
NEXT
A$=INPUT$(1) ; Wait for any key pressed
CLS ; Clear screen and draw gameboard
LINE(55,33)-(199,158),4,BF
FOR J=0 TO 5
FOR I=0 TO 6
X=I*20+67
Y=J*20+45
CIRCLE(X,Y),7,1
PAINT(X,Y),1,1
NEXT I,J
UX=120 ; Set variables: UX,uy horizontal valule in pixels for player disk and A is the fourth colum
UY=14
A=3
IF A$<>"Y" AND A$<>"y" THEN ; If A$ is any value different form Y or y then computer start playing...
PSET(56,170) ; ... send text message "LET ME THINK..."
PRINT#1,T$(3)
INTERVALON ; Turn on interruption routine
GOTO50 ; go to line 50 and end if
line 30 ; ---------------- PLAYER MOVE -------------------------------------------------------------------
INTERVAL OFF ; Turn off interruption routine
PSET(56,170) ; Set text message "MOVE"
PRINT#1,T$(4)
PUTSPRITE0,(UX,UY),11,0 ; Set initial disk player sprite
D=STICK(0) ; Arrow keys control
A=A+(D=7)-(D=3) ; Two decisions: a) if d=7 then a=a-1 b) if d=3 then a=1+1. Choose colum to play
A=A-(A<0)+(A>6) ; Two decisions: a) if a<0 then a=a+1 b) if a>6 then a=a-1. Horizontal limits police
UX=A*20+60 ; Set UX value needed for 'put sprite' instruction
IF D<>5 OR L(A)=6 GOTO 30 ELSE ; If d=5 and L(A) then dropping piece. A is the chosed colum, L(A)=6 means that colum A is filled...
PLAY"D" ; ...in other case make movement with little visual effect
FOR H=0 TO 5-L(A)
PUTSPRITE0,(UX,UY+H*20),11,0
FOR R T=0 TO 30 ; Simple delay
NEXTRT,H
PUTSPRITE0,(O,UY),0,0 ; remove sprite from screen and endif
line 40
B((5-L(A))*7+A)=1 ; Mark the gameboard array for the player move
L(A)=L(A)+1 ; Increase the upper bounder array
X=A*20+67 ; Set X and Y values for the final disk player position
Y=(6-L(A))*20+45
CIRCLE(X,Y),7,11
PAINT(X,Y),11
LINE(0,170)-(255,178),1,BF ; Erase text area for next message
P=1 ; Set P=1 (player mark)
GOSUB80 ; call check 4 lines routine to know if player win
PSET(56,170)
IF T>0 THEN PRINT#1,T$(0) ; if player win, send message "YOU WON"
A=USR(0) ; Wait for RETURN pressed
RUN ; Restart the program
ELSE ; ...else...
E=0 ; Set E as the first colum for thinking computer effect
PRINT#1,T$(3) ; Send message "LET ME THINK..."
INTERVAL ON ; Turn on interruption routine
line 50 ; ---------------- COMPUTER MOVE -----------------------------------------------------------------
A=INT(RND(-TIME)*6) ; choose colum using Random Basic service from 0 to 6 (seven values; seven colum)
IF L(A)>5 THEN 50 ; if L(A) (upper bounder array) is filled then got to take out another value going to the beginning of the line
ELSE
FOR E=0 TO 6 ; Go through every colum and check if four line is made by the player, if so, choose that colum to drop the disk
Z=-((5-L(E))*7+E)*(L(E)<6)-42*(L(E)>5) ; Avoid check out of gameboard limits
P=1 ; player mark for the gameboard array
B(Z)=1
GOSUB80
B(Z)=0
A=-E*(T>0)-A*(T=0) ; if not line is made by the player, keep on the random colum at the begining chosed. If line is made, swith colum
NEXT
FOR E=0 TO 6 ; Go through every colum and check if foru line is made by the computer. It is similar to the previous FOR...NEXT
Z=-((5-L(E))*7+E)*(L(E)<6)-42*(L(E)>5)
P=2 ; computer mark for the gameboard array
B(Z)=2
GOSUB80
B(Z)=0
A=-E*(T>0)-A*(T=0) ; if line is made by computer, switch colum, in other case keeping the previous one
G=-(T>0)ORG ; G holds T value for knowing computer victory later
NEXT
line 60
FOR H=0 TO 5-L(A) ; dropping disk effect
PUTSPRITE0,(A*20+60,UY+H*20),6,0
PUTSPRITE0,(0,0),0,0
NEXT
B((5-L(A))*7+A)=2 ; Mark gameboard array for computer move
X=A*20+67 ; Set X value for drawing computer disk
L(A)=L(A)+1 ; Increase upper bounder array
Y=(6-L(A))*20+45 ; Set Y value for drawing computer disk
PLAY"C" ; Emit simple C note (note DO)
CIRCLE(X,Y),7,6 ; Paint computer disk
PAINT(X,Y),6 ; Fill computer disk
LINE(0,170)-(255,178),1,BF ; Erase text area
PSET(56,170) ; Put text pointer at 56,170
A=3 ; Set initial colum at fourth position (colums are numered as 0,1,2,3,4,5,6)
IF G>0 THEN PRINT#1,T$(1) ; If G>0 (T>0) then print message "YOU LOST"...
A=USR(0) ; Wait for RETURN pressed
RUN ; restart and end if
line 70
PUT SPRITE 0,(0,0),0,0 ; Remove sprites from screen
PUT SPRITE 1,(0,0),0,1
F=F+2 ; Increase move counter
IF F<42 THEN 30 ELSE ; If F=42, all holes are filled, therefore It is draw
PRINT#1,T$(2) ; Send message "IT IS DRAW,NOBODY WON"
A=USR(0) ; Wait for RETURN pressed
RUN ; Restart program
line 80 ; ---------------- CHECK LINES -------------------------------------------------------------------
T=0 ; T holds number of 4 disk-in-line that were done
FOR H=0 TO 1 ; H=0 for checking vertical lines, H=1 for checking horizontal lines
FOR I=0 TO 5-(H=0) ; Main loop for checking horizontal and vertical lines
S=1 ; S offset position in every line
K=0 ; Partial line control, start at 0 disk in the line
FOR J=0 TO 5-(H=1) ; Sub-main loop for checking horizontal and vertical lines
M=(B(J+I*7)=P)*S*(H=1) ; Transform phisical 4 disks to concept 4 bits
+(B(J*7+I)=P)*S*(H=0)
K=-(K+M)*(M>0) ; Partial line control
S=S*2 ; Increase bit (8=1000,4=0100,2=0010,1=0001), if M=15 then 4 disk-in-line was made
FOR R=0 TO 2+H ; Checking if 4 disk-in-line was made
T=T-(K=2^R*15)
NEXTR,J,I,H
FOR I=0 TO 3 ; Algorithm for checking diagonal lines. Choose table (*see final note)
FOR J=0 TO 2 ; Choose diagonal line
K=0
FOR V=I+3 TO I+21 STEP 6 ; Adjust initial value for up-right to down-left orientation
K=K-(B(J*7+V)=P) ; Partial disk control
NEXT
line 90
T=T-(K=4) ; if K=4 then T=T+1 (add one filled line more)
K=0
FOR V=I TO I+24 STEP 8 ; Adjust initial value for up-left to down-rigth orientation
K=K-(B(J*7+V)=P) ; Partial disk control
NEXT
T=T-(K=4) ; if K=4 then T=T+1 (add one filled line more)
NEXTJ,I
RETURN
line 100
PUT SPRITE 0,(E*20+60,UY),9,1 ; Thinking effect. Rotate disks by the colums
PUT SPRITE 1,(A*20+60,UY),6,0
RETURN
-------
DATAS
-------
Datas are put on left lines (datas just hold text messages and sprites values)
DATA"YOU WON","YOU LOST","IT IS DRAW,NOBODY WON","LET ME THINK...",MOVE,"CONNECT 4 - 10LINERS CONTEST'21","by Javier Franco","DO YOU WANT RUN TO START(Y/y)?"
DATA3,15,31,63,127,127,255,255,255,255,127,127,63,31,15,3,192,240,248,252,254,254,255,255,255,255,254,254,252,248,240,192,3,12,16,32,64,64,128,128,128,128,64,64,32,16,12,3
DATA192,48,8,4,2,2,1,1,1,1,2,2,4,8,48,1
-------------
*FINAL NOTE
-------------
The gist to check diagonal lines is based on going through all elements according to the next tables using for-next loops:
3 4 5 6
9 10 10 11 11 12 12 13
15 16 17 16 17 18 17 18 19 18 19 20
21 22 23 22 23 24 23 24 25 24 25 26
28 29 29 30 30 31 31 32
35 26 37 28
0 1 2 3
7 8 8 9 9 10 10 11
14 15 16 15 16 17 16 17 18 17 18 19
22 23 24 23 24 25 24 25 26 25 26 27
30 31 31 32 32 33 33 34
38 39 40 41
Keep in mind that the B() array (gameboard array) is organized as:
0 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 32 33 34
35 36 37 38 39 40 41
Status | Released |
Author | BASIC 10Liner |
Genre | Strategy |
Tags | 8-Bit, basic, basic10liner, MSX |
Comments
Log in with itch.io to leave a comment.
congratulations, the line check algorithm is very difficult
felicidades, el algoritmo de comprobación de líneas es muy dificil