' Othello Game, incomplete, to be worked on later...

$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"

$RESOURCE GRID_BMP AS "GRID.BMP"
$RESOURCE OTHELLO_ICO AS "OTHELLO.ICO"

DECLARE SUB NewGame
DECLARE SUB HintClick
DECLARE SUB ExitItemClick
DECLARE SUB BoardMouseMove (X AS INTEGER, Y AS INTEGER, Shift AS INTEGER)
DECLARE SUB BoardClick
DECLARE SUB InitGrid
DECLARE SUB UpdateHintGrid

DIM P1Color AS INTEGER
    P1Color = clRed
DIM P2Color AS INTEGER
    P2Color = clBlue
DIM CurrentChip AS INTEGER
DIM GameChips AS INTEGER

DIM Grid(0 TO 11, 0 TO 11) AS INTEGER
DIM HintGrid(1 TO 10, 1 TO 10) AS INTEGER

DIM Font AS QFont
    Font.Name = "Arial"
    Font.Size = 12


'-- Create GUI
CREATE Form AS QForm
  Width = 450
  Height = 315
  ICOHandle = OTHELLO_ICO
  Caption = "Othello/Reversi Game"
  Center
  CREATE Menu AS QMainMenu
    CREATE FileMenu AS QMenuItem
      Caption = "&File"
      CREATE NewItem AS QMenuItem
        Caption = "&New Game"
        OnClick = NewGame
      END CREATE
      CREATE Break AS QMenuItem
        Caption = "-"
      END CREATE
      CREATE ExitItem AS QMenuItem
        Caption = "E&xit"
        OnClick = ExitItemClick
      END CREATE
    END CREATE
    CREATE HelpMenu AS QMenuItem
      Caption = "&Help"
      CREATE HintItem AS QMenuItem
        Caption = "&Hint"
        OnClick = HintClick
      END CREATE
    END CREATE
  END CREATE
  CREATE Board AS QImage
    AutoSize = True
    Transparent = True
    BMPHandle = GRID_BMP
    Cursor = crHandPoint
    OnMouseMove = BoardMouseMove
    OnClick = BoardClick
  END CREATE
  CREATE Panel AS QPanel
    Width = 120
    Align = alRight
    CREATE TitleLabel AS QLabel
      Caption = "Othello"
      Left = 10
      Top = 10
      Font = Font
    END CREATE
  END CREATE
  CREATE StatusBar AS QStatusBar
    AddPanels "", ""
    Panel(0).Width = 90
    Panel(0).Alignment = taCenter
    Panel(1).Caption = "Othello for Rapid-Q created by William Yu"
  END CREATE
END CREATE


Font.Name = "Courier"
Font.Size = 10

CREATE HintForm AS QForm
  Center
  Width = 200
  Height = 200
  Caption = "Hint Grid"
  BorderStyle = bsToolWindow
  CREATE RichEdit AS QRichEdit
    Align = alClient
    PlainText = True
    ReadOnly = True
    Font = Font
  END CREATE
END CREATE

'-- Initialization
NewGame
Form.ShowModal


SUB DrawChip (X AS INTEGER, Y AS INTEGER, Colour AS INTEGER)
  Board.Circle(9+(X-1)*29,6+(Y-1)*24,(X-1)*29+29,(Y-1)*24+26,clBlack,Colour)
END SUB

FUNCTION HorizontalMatches (GridX AS INTEGER, GridY AS INTEGER, Colour AS INTEGER) AS INTEGER
  DIM X AS INTEGER
  DIM NotColor AS INTEGER, Matches AS INTEGER, SumMatches AS INTEGER

  IF Colour = P1Color THEN
    NotColor = P2Color
  ELSE
    NotColor = P1Color
  END IF

  Matches = 0

  '-- Check left side
  FOR X = GridX-1 TO 0 STEP -1
    IF Grid(X, GridY) = NotColor THEN
      Matches++
    ELSEIF Grid(X, GridY) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
  NEXT X

  SumMatches = Matches

  Matches = 0

  '-- Check right side
  FOR X = GridX+1 TO 11
    IF Grid(X, GridY) = NotColor THEN
      Matches++
    ELSEIF Grid(X, GridY) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
  NEXT X

  SumMatches += Matches

  HorizontalMatches = SumMatches
END FUNCTION

FUNCTION VerticalMatches (GridX AS INTEGER, GridY AS INTEGER, Colour AS INTEGER) AS INTEGER
  DIM Y AS INTEGER
  DIM NotColor AS INTEGER, Matches AS INTEGER, SumMatches AS INTEGER

  IF Colour = P1Color THEN
    NotColor = P2Color
  ELSE
    NotColor = P1Color
  END IF

  Matches = 0

  '-- Check above
  FOR Y = GridY-1 TO 0 STEP -1
    IF Grid(GridX, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(GridX, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
  NEXT X

  SumMatches = Matches

  Matches = 0

  '-- Check below
  FOR Y = GridY+1 TO 11
    IF Grid(GridX, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(GridX, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
  NEXT X

  SumMatches += Matches

  VerticalMatches = SumMatches
END FUNCTION

FUNCTION LDiagonalMatches (GridX AS INTEGER, GridY AS INTEGER, Colour AS INTEGER) AS INTEGER
  DIM X AS INTEGER, Y AS INTEGER
  DIM NotColor AS INTEGER, Matches AS INTEGER, SumMatches AS INTEGER

  IF Colour = P1Color THEN
    NotColor = P2Color
  ELSE
    NotColor = P1Color
  END IF

  Matches = 0

  '-- Check left side
  Y = GridY-1
  FOR X = GridX-1 TO 0 STEP -1
    IF Y = 0 THEN
      Matches = 0
      EXIT FOR
    END IF
    IF Grid(X, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(X, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
    Y--
  NEXT X

  SumMatches = Matches

  Matches = 0

  '-- Check right side
  Y = GridY+1
  FOR X = GridX+1 TO 11
    IF Y > 10 THEN
      Matches = 0
      EXIT FOR
    END IF
    IF Grid(X, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(X, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
    Y++
  NEXT X

  SumMatches += Matches

  LDiagonalMatches = SumMatches
END FUNCTION

FUNCTION RDiagonalMatches (GridX AS INTEGER, GridY AS INTEGER, Colour AS INTEGER) AS INTEGER
  DIM X AS INTEGER, Y AS INTEGER
  DIM NotColor AS INTEGER, Matches AS INTEGER, SumMatches AS INTEGER

  IF Colour = P1Color THEN
    NotColor = P2Color
  ELSE
    NotColor = P1Color
  END IF

  Matches = 0

  '-- Check right side
  Y = GridY-1
  FOR X = GridX+1 TO 11
    IF Y = 0 THEN
      Matches = 0
      EXIT FOR
    END IF
    IF Grid(X, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(X, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
    Y--
  NEXT X

  SumMatches = Matches

  Matches = 0

  '-- Check left side
  Y = GridY+1
  FOR X = GridX-1 TO 0 STEP -1
    IF Y > 10 THEN
      Matches = 0
      EXIT FOR
    END IF
    IF Grid(X, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(X, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
    Y++
  NEXT X

  SumMatches += Matches

  RDiagonalMatches = SumMatches
END FUNCTION



FUNCTION CheckHorizontal (GridX AS INTEGER, GridY AS INTEGER, Colour AS INTEGER) AS INTEGER
  DIM X AS INTEGER
  DIM NotColor AS INTEGER, Matches AS INTEGER, SumMatches AS INTEGER

  IF Colour = P1Color THEN
    NotColor = P2Color
  ELSE
    NotColor = P1Color
  END IF

  Matches = 0

  '-- Check left side
  FOR X = GridX-1 TO 0 STEP -1
    IF Grid(X, GridY) = NotColor THEN
      Matches++
    ELSEIF Grid(X, GridY) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
  NEXT X

  IF Matches > 0 THEN
    FOR X = GridX-1 TO 1 STEP -1
      IF Grid(X, GridY) = NotColor THEN
        Grid(X, GridY) = Colour
        DrawChip(X, GridY, Colour)
      ELSE
        EXIT FOR
      END IF
    NEXT
  END IF

  SumMatches = Matches

  Matches = 0

  '-- Check right side
  FOR X = GridX+1 TO 11
    IF Grid(X, GridY) = NotColor THEN
      Matches++
    ELSEIF Grid(X, GridY) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
  NEXT X

  IF Matches > 0 THEN
    FOR X = GridX+1 TO 10
      IF Grid(X, GridY) = NotColor THEN
        Grid(X, GridY) = Colour
        DrawChip(X, GridY, Colour)
      ELSE
        EXIT FOR
      END IF
    NEXT
  END IF

  SumMatches += Matches

  CheckHorizontal = SumMatches
END FUNCTION

FUNCTION CheckVertical (GridX AS INTEGER, GridY AS INTEGER, Colour AS INTEGER) AS INTEGER
  DIM Y AS INTEGER
  DIM NotColor AS INTEGER, Matches AS INTEGER, SumMatches AS INTEGER

  IF Colour = P1Color THEN
    NotColor = P2Color
  ELSE
    NotColor = P1Color
  END IF

  Matches = 0

  '-- Check above
  FOR Y = GridY-1 TO 0 STEP -1
    IF Grid(GridX, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(GridX, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
  NEXT X

  IF Matches > 0 THEN
    FOR Y = GridY-1 TO 1 STEP -1
      IF Grid(GridX, Y) = NotColor THEN
        Grid(GridX, Y) = Colour
        DrawChip(GridX, Y, Colour)
      ELSE
        EXIT FOR
      END IF
    NEXT
  END IF

  SumMatches = Matches

  Matches = 0

  '-- Check below
  FOR Y = GridY+1 TO 11
    IF Grid(GridX, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(GridX, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
  NEXT X

  IF Matches > 0 THEN
    FOR Y = GridY+1 TO 10
      IF Grid(GridX, Y) = NotColor THEN
        Grid(GridX, Y) = Colour
        DrawChip(GridX, Y, Colour)
      ELSE
        EXIT FOR
      END IF
    NEXT
  END IF

  SumMatches += Matches

  CheckVertical = SumMatches
END FUNCTION

FUNCTION CheckLDiagonal (GridX AS INTEGER, GridY AS INTEGER, Colour AS INTEGER) AS INTEGER
  DIM X AS INTEGER, Y AS INTEGER
  DIM NotColor AS INTEGER, Matches AS INTEGER, SumMatches AS INTEGER

  IF Colour = P1Color THEN
    NotColor = P2Color
  ELSE
    NotColor = P1Color
  END IF

  Matches = 0

  '-- Check left side
  Y = GridY-1
  FOR X = GridX-1 TO 0 STEP -1
    IF Y = 0 THEN
      Matches = 0
      EXIT FOR
    END IF
    IF Grid(X, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(X, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
    Y--
  NEXT X

  IF Matches > 0 THEN
    Y = GridY-1
    FOR X = GridX-1 TO 1 STEP -1
      IF Y = 0 THEN
        EXIT FOR
      END IF
      IF Grid(X, Y) = NotColor THEN
        Grid(X, Y) = Colour
        DrawChip(X, Y, Colour)
      ELSE
        EXIT FOR
      END IF
      Y--
    NEXT
  END IF

  SumMatches = Matches

  Matches = 0

  '-- Check right side
  Y = GridY+1
  FOR X = GridX+1 TO 11
    IF Y > 10 THEN
      Matches = 0
      EXIT FOR
    END IF
    IF Grid(X, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(X, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
    Y++
  NEXT X

  IF Matches > 0 THEN
    Y = GridY+1
    FOR X = GridX+1 TO 10
      IF Y > 10 THEN
        EXIT FOR
      END IF
      IF Grid(X, Y) = NotColor THEN
        Grid(X, Y) = Colour
        DrawChip(X, Y, Colour)
      ELSE
        EXIT FOR
      END IF
      Y++
    NEXT
  END IF

  SumMatches += Matches

  CheckLDiagonal = SumMatches
END FUNCTION

FUNCTION CheckRDiagonal (GridX AS INTEGER, GridY AS INTEGER, Colour AS INTEGER) AS INTEGER
  DIM X AS INTEGER, Y AS INTEGER
  DIM NotColor AS INTEGER, Matches AS INTEGER, SumMatches AS INTEGER

  IF Colour = P1Color THEN
    NotColor = P2Color
  ELSE
    NotColor = P1Color
  END IF

  Matches = 0

  '-- Check right side
  Y = GridY-1
  FOR X = GridX+1 TO 11
    IF Y = 0 THEN
      Matches = 0
      EXIT FOR
    END IF
    IF Grid(X, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(X, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
    Y--
  NEXT X

  IF Matches > 0 THEN
    Y = GridY-1
    FOR X = GridX+1 TO 10
      IF Y = 0 THEN
        EXIT FOR
      END IF
      IF Grid(X, Y) = NotColor THEN
        Grid(X, Y) = Colour
        DrawChip(X, Y, Colour)
      ELSE
        EXIT FOR
      END IF
      Y--
    NEXT
  END IF

  SumMatches = Matches

  Matches = 0

  '-- Check left side
  Y = GridY+1
  FOR X = GridX-1 TO 0 STEP -1
    IF Y > 10 THEN
      Matches = 0
      EXIT FOR
    END IF
    IF Grid(X, Y) = NotColor THEN
      Matches++
    ELSEIF Grid(X, Y) = Colour THEN
      EXIT FOR
    ELSE
      Matches = 0
      EXIT FOR
    END IF
    Y++
  NEXT X

  IF Matches > 0 THEN
    Y = GridY+1
    FOR X = GridX-1 TO 1 STEP -1
      IF Y > 10 THEN
        EXIT FOR
      END IF
      IF Grid(X, Y) = NotColor THEN
        Grid(X, Y) = Colour
        DrawChip(X, Y, Colour)
      ELSE
        EXIT FOR
      END IF
      Y++
    NEXT
  END IF

  SumMatches += Matches

  CheckRDiagonal = SumMatches
END FUNCTION

SUB InitGrid
  DIM I AS INTEGER, J AS INTEGER

  FOR I = 0 TO 11
    FOR J = 0 TO 11
      Grid(I,J) = 0
    NEXT
  NEXT
END SUB

SUB ComputerMove
  DIM X AS INTEGER, Y AS INTEGER
  DIM MaxValue AS INTEGER, Matches AS INTEGER
  DIM SX AS INTEGER, SY AS INTEGER

  MaxValue = 0
  FOR Y = 1 TO 10
    FOR X = 1 TO 10
      IF HintGrid(X,Y) > MaxValue THEN
        MaxValue = HintGrid(X,Y)
        SX = X: SY = Y
      END IF
    NEXT
  NEXT

  IF MaxValue <> 0 THEN
    Matches =  CheckHorizontal(SX, SY, CurrentChip) + _
               CheckVertical(SX, SY, CurrentChip) + _
               CheckLDiagonal(SX, SY, CurrentChip) + _
               CheckRDiagonal(SX, SY, CurrentChip)
    IF Matches > 0 THEN
      DrawChip(SX, SY, CurrentChip)
      Grid(SX, SY) = CurrentChip

      GameChips++
      IF GameChips = 100 THEN
        ShowMessage "Game Over"
        EXIT SUB
      END IF
    END IF
  ELSE
    Matches = 0
  END IF

  IF CurrentChip = P1Color THEN
    CurrentChip = P2Color
  ELSE
    CurrentChip = P1Color
  END IF
  UpdateHintGrid

  FOR Y = 1 TO 10
    FOR X = 1 TO 10
      MaxValue += HintGrid(X,Y)
    NEXT
  NEXT

  IF MaxValue = 0 THEN
    '-- No valid moves available
    IF Matches = 0 THEN
      '-- Game over, neither one has valid moves
      ShowMessage "Game Over"
      EXIT SUB
    END IF

    IF CurrentChip = P1Color THEN
      CurrentChip = P2Color
    ELSE
      CurrentChip = P1Color
    END IF
    UpdateHintGrid
    ComputerMove
  END IF
END SUB

SUB BoardClick
  DIM GridX AS INTEGER, GridY AS INTEGER
  DIM Matches AS INTEGER

  SELECT CASE MouseX
    CASE 4 TO 32   : GridX = 1
    CASE 33 TO 61  : GridX = 2
    CASE 62 TO 90  : GridX = 3
    CASE 91 TO 119 : GridX = 4
    CASE 120 TO 148: GridX = 5
    CASE 149 TO 177: GridX = 6
    CASE 178 TO 206: GridX = 7
    CASE 207 TO 235: GridX = 8
    CASE 236 TO 264: GridX = 9
    CASE 265 TO 293: GridX = 10
    CASE ELSE
      EXIT SUB
  END SELECT

  SELECT CASE MouseY
    CASE 5 TO 28   : GridY = 1
    CASE 29 TO 52  : GridY = 2
    CASE 53 TO 76  : GridY = 3
    CASE 77 TO 100 : GridY = 4
    CASE 101 TO 124: GridY = 5
    CASE 125 TO 148: GridY = 6
    CASE 149 TO 172: GridY = 7
    CASE 173 TO 196: GridY = 8
    CASE 197 TO 220: GridY = 9
    CASE 221 TO 244: GridY = 10
    CASE ELSE
      EXIT SUB
  END SELECT

  IF Grid(GridX, GridY) <> 0 THEN
    EXIT SUB
  END IF

  Matches =  CheckHorizontal(GridX, GridY, CurrentChip) + _
             CheckVertical(GridX, GridY, CurrentChip) + _
             CheckLDiagonal(GridX, GridY, CurrentChip) + _
             CheckRDiagonal(GridX, GridY, CurrentChip)

  IF Matches > 0 THEN
    DrawChip(GridX, GridY, CurrentChip)
    Grid(GridX, GridY) = CurrentChip

    GameChips++
    IF GameChips = 100 THEN
      ShowMessage "Game Over"
      EXIT SUB
    END IF

    IF CurrentChip = P1Color THEN
      CurrentChip = P2Color
    ELSE
      CurrentChip = P1Color
    END IF
    UpdateHintGrid
    Board.Repaint
    SLEEP .5
    ComputerMove
  END IF
END SUB

SUB BoardMouseMove (X AS INTEGER, Y AS INTEGER, Shift AS INTEGER)
  StatusBar.Panel(0).Caption = "X:"+STR$(X)+"  Y:"+STR$(Y)
END SUB

SUB ExitItemClick
  Form.Close
END SUB

SUB NewGame
  Board.BMPHandle = GRID_BMP
  Board.Circle(125,102,125+20,102+20,clBlack,P2Color)
  Board.Circle(125,126,125+20,126+20,clBlack,P1Color)
  Board.Circle(154,102,154+20,102+20,clBlack,P1Color)
  Board.Circle(154,126,154+20,126+20,clBlack,P2Color)
  InitGrid
  Grid(5,5) = P2Color
  Grid(6,5) = P1Color
  Grid(5,6) = P1Color
  Grid(6,6) = P2Color
  CurrentChip = P1Color
  GameChips = 4
END SUB

SUB UpdateHintGrid
  DIM X AS INTEGER, Y AS INTEGER
  DIM S AS STRING

  RichEdit.Clear
  FOR Y = 1 TO 10
    S = ""
    FOR X = 1 TO 10
      IF Grid(X,Y) <> 0 THEN
        HintGrid(X,Y) = 0
        S = S + "0 "
      ELSE
        HintGrid(X,Y) = HorizontalMatches(X,Y,CurrentChip) + _
                        VerticalMatches(X,Y,CurrentChip) + _
                        LDiagonalMatches(X,Y,CurrentChip) + _
                        RDiagonalMatches(X,Y,CurrentChip)
        S = S + STR$(HintGrid(X,Y)) + " "
      END IF
    NEXT
    IF HintForm.Visible = True THEN
      RichEdit.AddStrings(S)
    END IF
  NEXT
END SUB

SUB HintClick
  HintForm.Visible = True
  UpdateHintGrid
END SUB
