'===========================================================================
' Subject: EGA CONNECT FOUR                   Date: 09-09-95 (09:29)       
'  Author: The ABC Programmer                 Code: QB, QBasic, PDS        
'  Origin: EGA,CONNECT,FOUR                 Packet: GAMES.ABC
'===========================================================================
'===================================================
' EGA CONNECT FOUR by William Yu  (09-09-95)
' Yes!  I can document!  Not very well though.
' I took two hours programming this, and I bet I
' used almost a third of it trying to document it.
'
' INSTRUCTIONS For Game Play:
'   Object of the game is to connect your coloured
'   chips four in a row, horizontally, vertically or
'   diagonally before the other person does.
'
' MODIFICATIONS To Make:
'   Make the computer think
'   You can change the grid size to any dimension
'   Better intro and ending screens
'   Better Game Play, with commands
'   Multiple games are possible
'   Save/Continue played games
'
' Alright, so I haven't added computer difficulty.
' That's up to you, I programmed this for two
' players.  You can probably add modem features to
' play head-to-head via modem.
'
' FOR MODEM PLAY:
'   All that needs to be sent are X values via modem
'   You can replace/modify ComputerTurn to wait for
'   the modem to send something and call the
'   DropChip subroutine to validate it.
'===================================================

DEFINT A-Z
DECLARE SUB DrawGrid ()
DECLARE SUB DrawChip (X%, ChipColor%)
DECLARE SUB EraseChip (X%)
DECLARE SUB DropChip (X%, ChipColor%, Valid%)
DECLARE SUB SwitchTurn (X%, ChipColor%, ChipColor2%)
DECLARE SUB CheckForWin (Row%, Col%, ChipColor%)
DECLARE SUB WhoWon (ChipColor%)
DECLARE SUB ComputerTurn (ChipColor%, ChipColor2%)

DIM SHARED Grid(8, 8)' Do not change unless you know what you're doing
CONST True = 1       ' Define Constants
CONST False = 0
CONST Computer = 12  ' Define Colors for Computer/User
CONST User = 9       ' Computer = Red / User = Blue
                     ' Computer <> User
CONST Player = 1     ' One or Two Players
                     ' If two players then Player Two = Computer
CONST Level = 0      ' Level of difficulty against computer
                     ' 0 = Moronic
                     ' 1 = Easy          Please implement
                     ' 2 = Normal        computer difficulty
                     ' 3 = Hard
                     ' 4 = Really Hard
SCREEN 7, 0, 0, 0    ' Change to other screen modes if desired

DrawGrid             ' Call DrawGrid Subroutine (Draws Playing Field)


GoesFirst = True     ' User goes first (Change to False to go second)

IF GoesFirst THEN
  ChipColor = User          ' Using two variables for swapping later
  ChipColor2 = Computer
ELSE
  ChipColor = Computer
  ChipColor2 = User
  ComputerTurn ChipColor, ChipColor2
END IF

X = 144              ' X value changes ñ 28
                     ' Leftend value  = 60
                     ' Rightend value = 256
Drops = 0            ' Setup Counter  (Max of 64 Drops before grid is filled)

DO
  IF Drops = 64 THEN GOTO TieBreak
  DrawChip X, ChipColor
  DO
    Key$ = INKEY$
  LOOP UNTIL Key$ <> ""

  SELECT CASE Key$
    CASE CHR$(0) + "M"          ' User Pressed RIGHT ARROW
      EraseChip X
      IF X < 256 THEN           ' Make sure it's not end of grid
        X = X + 28
      ELSE                      ' Else go back to beginning
        X = 60
      END IF
    CASE CHR$(0) + "K"          ' User Pressed LEFT ARROW
      EraseChip X
      IF X > 60 THEN            ' Make sure it's not at beginning of grid
        X = X - 28
      ELSE                      ' Else go to the end of the grid
        X = 256
      END IF
    CASE CHR$(0) + "P", CHR$(13)    ' User Pressed ENTER or DOWN
      DropChip X, ChipColor, Valid  ' Drop the Chip
      IF Valid = True THEN          ' Valid Drop
        SwitchTurn X, ChipColor, ChipColor2
        Drops = Drops + 1           ' Increase counter
        Valid = False
        IF Player = 1 AND Drops <> 64 THEN ComputerTurn ChipColor, ChipColor2
      END IF
    CASE CHR$(27)               ' User Pressed ESC  (Quit Program)
      GOTO ProgramEND
  END SELECT

LOOP

TieBreak:
  LOCATE 1, 1: COLOR 15: PRINT "It's a tie!"

ProgramEND:
  END

SUB CheckForWin (Row, Col, ChipColor)

'              <--- Column --->
'              1 2 3 4 5 6 7 8  XY
'              ----------------+
'              o o o o o o o o | 1
'              o o o o o o o o | 2
'              o o o o o o o o | 3
'              o o o o o o o o | 4
'  Start to -> o o o o o o o o | 5
'   Check      o o o o o o o o | 6
'    Down      o o o o o o o o | 7
'              o o o o o o o o | 8
'
' Here's what is checked first:
'
'   HORIZONTAL then VERTICAL then DIAGONAL
'
' You can change the order if you wish.

Connect = 1

FOR C = Col - 1 TO Col - 3 STEP -1
  IF C = 0 THEN EXIT FOR
  IF Grid(C, Row) = ChipColor THEN Connect = Connect + 1 ELSE EXIT FOR
NEXT C
IF Connect = 4 THEN WhoWon ChipColor
FOR C = Col + 1 TO Col + 3
  IF C = 9 THEN EXIT FOR
  IF Grid(C, Row) = ChipColor THEN Connect = Connect + 1 ELSE EXIT FOR
NEXT C
IF Connect = 4 THEN WhoWon ChipColor ELSE Connect = 1

' Check Vertical, only if dropped chip is high enough to count downwards
' If not, forget checking

IF Row < 6 THEN
  FOR C = Row + 1 TO Row + 3
    IF Grid(Col, C) = ChipColor THEN Connect = Connect + 1 ELSE EXIT FOR
  NEXT C
END IF
IF Connect = 4 THEN WhoWon ChipColor ELSE Connect = 1


' Diagonal Check (Left Up/Down)

BackRow = Row
FOR C = Col - 1 TO Col - 3 STEP -1
  IF C = 0 THEN EXIT FOR
  IF Row = 1 THEN EXIT FOR
  Row = Row - 1
  IF Grid(C, Row) = ChipColor THEN Connect = Connect + 1 ELSE EXIT FOR
NEXT C
IF Connect = 4 THEN WhoWon ChipColor
Row = BackRow
FOR C = Col + 1 TO Col + 3
  IF C = 9 THEN EXIT FOR
  IF Row = 8 THEN EXIT FOR
  Row = Row + 1
  IF Grid(C, Row) = ChipColor THEN Connect = Connect + 1 ELSE EXIT FOR
NEXT C
IF Connect = 4 THEN WhoWon ChipColor ELSE Connect = 1


' Diagonal Check (Right Up/Down)

Row = BackRow
FOR C = Col + 1 TO Col + 3
  IF C = 9 THEN EXIT FOR
  IF Row = 1 THEN EXIT FOR
  Row = Row - 1
  IF Grid(C, Row) = ChipColor THEN Connect = Connect + 1 ELSE EXIT FOR
NEXT C
IF Connect = 4 THEN WhoWon ChipColor
Row = BackRow
FOR C = Col - 1 TO Col - 3 STEP -1
  IF C = 0 THEN EXIT FOR
  IF Row = 8 THEN EXIT FOR
  Row = Row + 1
  IF Grid(C, Row) = ChipColor THEN Connect = Connect + 1 ELSE EXIT FOR
NEXT C
IF Connect = 4 THEN WhoWon ChipColor ELSE Connect = 1

END SUB

SUB ComputerTurn (ChipColor, ChipColor2)

SELECT CASE Level
  CASE 0
    DO
      RANDOMIZE TIMER
      Col = INT(RND * 8) + 1
      X = 60 + ((Col - 1) * 28)
      DropChip X, ChipColor, Valid
    LOOP UNTIL Valid = True
  CASE 1
  CASE 2
  CASE 3
  CASE 4
END SELECT

SwitchTurn X, ChipColor, ChipColor2

END SUB

SUB DrawChip (X, ChipColor)

  CIRCLE (X, 7), 8, ChipColor
  PAINT (X, 7), ChipColor

END SUB

SUB DrawGrid

LINE (45, 20)-(270, 180), 14, BF
LINE (51, 17)-(275, 17), 14
LINE (275, 17)-(275, 175), 14
LINE (51, 17)-(45, 20), 14
LINE (275, 17)-(270, 20), 14
LINE (275, 175)-(270, 180), 14
PAINT (273, 100), 6, 14
LINE (45, 181)-(270, 181), 12
LINE (276, 175)-(290, 189), 12
LINE (45, 181)-(31, 195), 12
LINE (270, 181)-(284, 195), 12
LINE (31, 195)-(284, 195), 12
LINE (290, 189)-(284, 195), 12
LINE (275, 176)-(270, 181), 12
PAINT (150, 185), 12
PAINT (282, 184), 4, 12

FOR Y = 30 TO 170 STEP 20
  FOR X = 60 TO 260 STEP 28
    CIRCLE (X, Y), 8, 0
    PAINT (X, Y), 0, 0
    CIRCLE (X, Y), 6, 14, 4.6, .1
  NEXT X
NEXT Y

END SUB

SUB DropChip (X, ChipColor, Valid)

  Col = (X - 60) / 28 + 1        ' Calculates the Column (1-8)

  FOR C = 8 TO 2 STEP -1
    IF Grid(Col, C) = False THEN EXIT FOR
  NEXT C

  IF Grid(Col, C) = False THEN ' Empty Holder, place your chip here
    Grid(Col, C) = ChipColor     ' Make it filled
    Row = ((C - 1) * 20) + 30    ' Calculate the Row
    CIRCLE (X, Row), 8, 8        ' Make Chip border color Dark Grey
    PAINT (X, Row), ChipColor, 8 ' Fill chip color
    Valid = True
    CheckForWin C, Col, ChipColor
  END IF

END SUB

SUB EraseChip (X)
 
  PAINT (X, 7), 0

END SUB

SUB SwitchTurn (X, ChipColor, ChipColor2)

  EraseChip X
  SWAP ChipColor, ChipColor2    ' Swap the two variables
  X = 144                       ' Reset X Coordinates
  DrawChip X, ChipColor

END SUB

SUB WhoWon (ChipColor)

  ' Check who wins
  ' Do whatever you want for the closing screen

  IF ChipColor = User THEN
    IF Player = 1 THEN PRINT "You Win!" ELSE PRINT "Player One Wins!"
  ELSE
    IF Player = 1 THEN PRINT "Computer Wins!" ELSE PRINT "Player Two Wins!"
  END IF

  END

END SUB

