INCLUDE Irvine32.
inc
.DATA
; Title   Screen Lines
T1 BYTE   4, 4, 4, 4, 4, 32, 4, 32, 4, 4, 4, 4, 32, 32, 32, 4
   BYTE   4, 4, 4, 4, 4, 32, 32, 4, 4, 32, 32, 4, 4, 4, 4, 32
   BYTE   32, 32, 4, 4, 4, 4, 4, 32, 32, 4, 4, 32, 32, 4, 4, 4
   BYTE   4, 0
T2 BYTE   32,   32, 4, 32,   32,   32, 4, 32, 4, 32, 32, 32, 32, 32, 32, 32
   BYTE   32,   4, 32, 32,   32,   4, 32, 32, 4, 32, 4, 32, 32, 32, 32, 32
   BYTE   32,   32, 32, 4,   32,   32, 32, 4, 32, 32, 4, 32, 4, 0
T3 BYTE   32,   32, 4, 32,   32,   32, 4, 32, 4, 32, 32, 32, 32, 32, 32, 32
   BYTE   32,   4, 32, 32,   32,   4, 4, 4, 4, 32, 4, 32, 32, 32, 32, 32
   BYTE   32,   32, 32, 4,   32,   32, 32, 4, 32, 32, 4, 32, 4, 4, 4, 4
   BYTE   0
T4 BYTE   32, 32, 4, 32, 32, 32, 4, 32, 4, 4, 4, 4, 32, 4, 32, 32
   BYTE   32, 4, 32, 32, 32, 4, 32, 32, 4, 32, 4, 4, 4, 4, 32, 4
   BYTE   32, 32, 32, 4, 32, 32, 32, 32, 4, 4, 32, 32, 4, 4, 4, 4
   BYTE   0
TAGLINE BYTE "Developed by Tanvir Ahmed Sojal", 0
PAK BYTE "Press any key to continue...",0
; Game Rules
R BYTE "Game Rules:", 0
R1 BYTE "1. Players will take turns.", 0
R2 BYTE "2. Player 1 will start the game.", 0
R3 BYTE "3. Player 1 will set 'X' and Player 2 will set 'O'.", 0
R4 BYTE "4. The board is marked with cell numbers.", 0
R5 BYTE "5. Enter CELL NUMBER to place your mark.", 0
R6 BYTE "6. Set 3 of your marks horizontally, vertically or diagonally to win.", 0
R7 BYTE "Good Luck!", 0
; Cell Marks
PC1 BYTE " (X)", 0
PC2 BYTE " (O)", 0
; Board   Lines
L1 BYTE   "   |    |  ", 0
L2 BYTE   "-----------", 0
N1 BYTE   " | ", 0
; Cell Numbers
C1 BYTE "1", 0
C2 BYTE "2", 0
C3 BYTE "3", 0
C4 BYTE "4", 0
C5 BYTE "5", 0
C6 BYTE "6", 0
C7 BYTE "7", 0
C8 BYTE "8", 0
C9 BYTE "9", 0
; Player Info
PLAYER BYTE "Player: ", 0
MOVES DWORD 0
DONE DWORD 0
DR DWORD 0
; Prompts
INP BYTE ":: Enter cell no. : ", 0
TKN BYTE "This cell is taken! Press any key...", 0
CUR BYTE "X", 0
W1 BYTE "Player ", 0
W2 BYTE " won the game!", 0
DRW BYTE "The game is draw!", 0
TRA BYTE "Want to play again? (y/n): ", 0
WI BYTE "Wrong input! Press any key...", 0
EMP BYTE "                                         ", 0
DEBUG_MSG BYTE "Debugging Here!", 0
.CODE
MAIN PROC
       lea edx, DEBUG_MSG
    call WriteString ; Display debug message
; Subroutine to display the title screen
DisplayTitleScreen PROC
    ; Display logo lines
    mov edx, OFFSET T1
    call WriteString
    mov edx, OFFSET T2
    call WriteString
    mov edx, OFFSET T3
    call WriteString
    mov edx, OFFSET T4
    call WriteString
    ; Move cursor and display developer tagline
    call SetCursorPos
    mov edx, OFFSET TAGLINE
    call WriteString
    ; Display "Press any key to continue..."
    mov edx, OFFSET PAK
    call WriteString
    ; Wait for key press
    call WaitMsgKey
    ; Clear the screen
    call Clrscr
    ret
DisplayTitleScreen ENDP
; Subroutine to set the cursor position (simulates INT 10H with DL, DH values)
SetCursorPos PROC
    ; Cursor for tagline
    mov ecx, 12
    call GotoXY
    ret
SetCursorPos ENDP
; Subroutine to simulate "Press any key" wait
WaitMsgKey PROC
    call ReadKey     ; Reads a keypress without echoing it
    ret
WaitMsgKey ENDP
; Subroutine to display the game rules
DisplayRules PROC
    mov edx, OFFSET R
    call WriteString
    mov edx, OFFSET R1
    call WriteString
    mov edx, OFFSET R2
    call WriteString
    mov edx, OFFSET R3
    call WriteString
    mov edx, OFFSET R4
    call WriteString
    mov edx, OFFSET R5
    call WriteString
    mov edx, OFFSET R6
    call WriteString
    mov edx, OFFSET R7
    call WriteString
    ret
DisplayRules ENDP
; ---------- INITIALIZE ---------------------
INIT:
    ; INITIALIZING ALL VARIABLES
    MOV PLAYER, 49     ; Initializing Player variable
    MOV MOVES, 0
    MOV DONE, 0
    MOV DR, 0
    MOV   C1,   49
    MOV   C2,   50
    MOV   C3,   51
    MOV   C4,   52
    MOV   C5,   53
    MOV   C6,   54
    MOV   C7,   55
    MOV   C8,   56
    MOV   C9,   57
    JMP PLRCHANGE
; ---------- INITIALIZATION ENDS --------------
; ------------ VICTORY ------------------------
VICTORY:
    ; Print victory message
    lea edx, W1
    call WriteString
    lea edx, PLAYER
    call WriteString
    lea edx, W2
    call WriteString
    ; Set Cursor
    call SetCursorPos
    lea edx, PAK ; PRESS ANY KEY
    call WriteString
    ; Wait for key press
    call WaitMsgKey
    ; Retry
    JMP TRYAGAIN
; ------------ DRAW ------------
DRAW:
    lea edx, DRW
    call WriteString
    ; Set Cursor for retry
    call SetCursorPos
    lea edx, PAK ; PRESS ANY KEY
    call WriteString
    ; Wait for key press
    call WaitMsgKey
    JMP TRYAGAIN
; ------------ CHECK IF WINNING CONDITION IS MET -----------
CHECK:   ; THERE ARE 8 POSSIBLE WINNING COMBINATIONS
    CHECK1: ; CHECKING 1, 2, 3
        MOV AL, C1
        MOV BL, C2
        MOV CL, C3
        CMP AL, BL
        JNZ CHECK2
        CMP BL, CL
        JNZ CHECK2
        MOV DONE, 1
        JMP BOARD
    CHECK2:    ; CHECKING 4, 5, 6
        MOV   AL, C4
        MOV   BL, C5
        MOV   CL, C6
        CMP   AL, BL
        JNZ   CHECK3
        CMP   BL, CL
        JNZ   CHECK3
        MOV   DONE, 1
        JMP   BOARD
    CHECK3: ; CHECKING 7, 8, 9
    MOV AL, C7
    MOV BL, C8
    MOV CL, C9
    CMP AL, BL
    JNZ CHECK4
    CMP BL, CL
    JNZ CHECK4
    MOV DONE, 1
    JMP BOARD
   CHECK4:     ; CHECKING 1, 4, 7
       MOV   AL, C1
       MOV   BL, C4
       MOV   CL, C7
       CMP   AL, BL
       JNZ   CHECK5
       CMP   BL, CL
       JNZ   CHECK5
       MOV   DONE, 1
       JMP   BOARD
   CHECK5:     ; CHECKING 2, 5, 8
       MOV   AL, C2
       MOV   BL, C5
       MOV   CL, C8
       CMP   AL, BL
       JNZ   CHECK6
       CMP   BL, CL
       JNZ   CHECK6
       MOV   DONE, 1
       JMP   BOARD
   CHECK6:     ; CHECKING 3, 6, 9
       MOV   AL, C3
       MOV   BL, C6
       MOV   CL, C9
       CMP   AL, BL
       JNZ   CHECK7
       CMP   BL, CL
       JNZ   CHECK7
       MOV   DONE, 1
       JMP   BOARD
   CHECK7:     ; CHECKING 1, 5, 9
       MOV   AL, C1
       MOV   BL, C5
       MOV   CL, C9
       CMP   AL, BL
       JNZ   CHECK8
       CMP   BL, CL
       JNZ   CHECK8
       MOV   DONE, 1
       JMP   BOARD
   CHECK8:     ; CHECKING 3, 5, 7
       MOV   AL, C3
       MOV   BL, C5
       MOV   CL, C7
       CMP   AL, BL
       JNZ   DRAWCHECK
       CMP   BL, CL
       JNZ   DRAWCHECK
       MOV   DONE, 1
       JMP   BOARD
DRAWCHECK:
    CMP DONE, 1
JZ VICTORY ; Jump to victory handling
CMP DR, 1
JZ DRAW ; Jump to draw handling
; Check if player wants to restart
LEA DX, TRA
CALL WriteString
CALL ReadChar
; Handle user input (y/n for restart or exit)
; ------------ PLAYER ----------
PLRCHANGE:
    CMP PLAYER, 49
    JZ P2
    CMP PLAYER, 50
    JZ P1
P1:
      MOV PLAYER, 49
      MOV CUR, 88
      JMP BOARD
P2:
      MOV PLAYER, 50
      MOV CUR, 79
      JMP BOARD
; ------------- BOARD ----------
BOARD:
    ; CLEAR SCREEN
    CALL ClrScr    ; Clears the screen using Irvine32
      ; SET CURSOR to row 6, column 30
      MOV DH, 6
      MOV DL, 30
      CALL SetCursorPos
      LEA DX, L1
      CALL WriteString   ; Display L1 string
      ; SET CURSOR to row 7, column 30
      MOV DH, 7
      MOV DL, 30
      CALL SetCursorPos
    MOV AH, 2
    MOV DL, 32
    INT 21H ; This line should be replaced with Irvine32 equivalent if you want to
use WriteChar
    ; Write ' ' character here for spacing, Irvine32 provides WriteChar to display
a character
; --------------------------------
; CELL 1
    LEA DX, C1
    CALL WriteString
      LEA DX, N1
    CALL WriteString
; CELL 2
    LEA DX, C2
    CALL WriteString
    LEA DX, N1
    CALL WriteString
; CELL 3
    LEA DX, C3
    CALL WriteString
; ---------------------------------
    ; SET CURSOR to row 8, column 30
    MOV DH, 8
    MOV DL, 30
    CALL SetCursorPos
    LEA DX, L2
    CALL WriteString
    ; SET CURSOR to row 9, column 30
    MOV DH, 9
    MOV DL, 30
    CALL SetCursorPos
    LEA DX, L1
    CALL WriteString
    ; SET CURSOR to row 10, column 30
    MOV DH, 10
    MOV DL, 30
    CALL SetCursorPos
    MOV AH, 2
    MOV DL, 32
    INT 21H
; --------------------------------
; CELL 4
    LEA DX, C4
    CALL WriteString
    LEA DX, N1
    CALL WriteString
; CELL 5
    LEA DX, C5
    CALL WriteString
    LEA DX, N1
    CALL WriteString
; CELL 6
    LEA DX, C6
    CALL WriteString
; ---------------------------------
    ; SET CURSOR to row 11, column 30
    MOV DH, 11
    MOV DL, 30
    CALL SetCursorPos
    LEA DX, L1
    CALL WriteString
    ; SET CURSOR to row 12, column 30
    MOV DH, 12
    MOV DL, 30
    CALL SetCursorPos
    LEA DX, L2
    CALL WriteString
    ; SET CURSOR to row 13, column 30
    MOV DH, 13
    MOV DL, 30
    CALL SetCursorPos
    LEA DX, L1
    CALL WriteString
    ; SET CURSOR to row 14, column 30
    MOV DH, 14
    MOV DL, 30
    CALL SetCursorPos
    MOV AH, 2
    MOV DL, 32
    INT 21H
; --------------------------------
; CELL 7
    LEA DX, C7
    CALL WriteString
    LEA DX, N1
    CALL WriteString
; CELL 8
    LEA DX, C8
    CALL WriteString
    LEA DX, N1
    CALL WriteString
; CELL 9
    LEA DX, C9
    CALL WriteString
; ---------------------------------
    ; SET CURSOR to row 15, column 30
    MOV DH, 15
    MOV DL, 30
    CALL SetCursorPos
    LEA DX, L1
    CALL WriteString
    ; SET CURSOR to row 16, column 20
    MOV DH, 16
    MOV DL, 20
    CALL SetCursorPos
    CMP DONE, 1
    JZ VICTORY
    CMP DR, 1
    JZ DRAW
; ------------ END OF BOARD -------
; ------------ INPUT --------------
INPUT:
    LEA DX, W1
    CALL WriteString   ; Display W1 string
    CALL WriteChar     ; Display the PLAYER character
    CMP PLAYER, 49
    JZ PL1
    LEA DX, PC2
    CALL WriteString
    JMP TAKEINPUT
PL1:
    LEA DX, PC1
    CALL WriteString
; ----------- INPUT HANDLING -----------
; Checking if player input corresponds to a valid cell
TAKEINPUT:
    LEA DX, INP
    CALL WriteString ; Display INP string
    CALL ReadChar      ; Read character from input (no echo)
    INC MOVES          ; Increment MOVES counter by 1
    MOV BL, AL
    SUB BL, 48         ; Convert character to numeric value (1-9)
    MOV CL, CUR        ; Store current position
    ; Checking valid input (1-9)
    CMP   BL, 1
    JZ    UPDATE_C1
    CMP   BL, 2
    JZ    UPDATE_C2
    CMP   BL, 3
    JZ    UPDATE_C3
    CMP   BL, 4
    JZ    UPDATE_C4
    CMP   BL, 5
    JZ    UPDATE_C5
    CMP   BL, 6
    JZ    UPDATE_C6
    CMP   BL, 7
    JZ    UPDATE_C7
    CMP   BL, 8
    JZ    UPDATE_C8
    CMP   BL, 9
    JZ    UPDATE_C9
    ; If input is invalid, decrease moves and prompt again
    DEC MOVES
    LEA DX, WI
    CALL WriteString
    CALL ReadChar
    JMP TAKEINPUT
; ----------- CELL UPDATES -----------
UPDATE_C1:    ; Update C1 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C1
    MOV BYTE PTR C1, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C1:
    MOV BYTE PTR C1, 88   ; 'X' for Player 1
    JMP BOARD
UPDATE_C2:    ; Update C2 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C2
    MOV BYTE PTR C2, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C2:
    MOV BYTE PTR C2, 88   ; 'X' for Player 1
    JMP BOARD
UPDATE_C3:    ; Update C3 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C3
    MOV BYTE PTR C3, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C3:
    MOV BYTE PTR C3, 88   ; 'X' for Player 1
    JMP BOARD
UPDATE_C4:    ; Update C4 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C4
    MOV BYTE PTR C4, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C4:
    MOV BYTE PTR C4, 88   ; 'X' for Player 1
    JMP BOARD
UPDATE_C5:    ; Update C5 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C5
    MOV BYTE PTR C5, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C5:
    MOV BYTE PTR C5, 88   ; 'X' for Player 1
    JMP BOARD
UPDATE_C6:    ; Update C6 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C6
    MOV BYTE PTR C6, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C6:
    MOV BYTE PTR C6, 88   ; 'X' for Player 1
    JMP BOARD
UPDATE_C7:    ; Update C7 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C7
    MOV BYTE PTR C7, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C7:
    MOV BYTE PTR C7, 88   ; 'X' for Player 1
    JMP BOARD
UPDATE_C8:    ; Update C8 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C8
    MOV BYTE PTR C8, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C8:
    MOV BYTE PTR C8, 88   ; 'X' for Player 1
    JMP BOARD
UPDATE_C9:    ; Update C9 with current player's mark (X or O)
    CMP PLAYER, 49
    JZ PLAYER_X_C9
    MOV BYTE PTR C9, 79 ; 'O' for Player 2
    JMP BOARD
PLAYER_X_C9:
    MOV BYTE PTR C9, 88 ; 'X' for Player 1
    JMP BOARD
; ----------- TRY AGAIN -----------
TRYAGAIN:
    ; Clear   screen
    MOV AX,   0600H
    MOV BH,   07H
    MOV CX,   0000H
    MOV DX,   184FH
    INT 10H
    ; Set cursor
    MOV AH, 2
    MOV BH, 0
    MOV DH, 10
    MOV DL, 24
    INT 10H
    LEA DX, TRA        ; "TRY AGAIN" prompt
    CALL WriteString
    CALL ReadChar      ; Read input (y/n)
    CMP AL, 121        ; Check if input is 'y'
    JZ INIT
    CMP AL, 89         ; Check if input is 'Y'
    JZ INIT
    ; If input is 'Y'/'y', then repeat the game
   CMP AL, 110       ; Check if input is 'n'
   JZ EXIT_PROGRAM
   CMP AL, 78        ; Check if input is 'N'
   JZ EXIT_PROGRAM            ; If input is 'N'/'n' then exit the game
    MOV AH, 2               ; Invalid input handling
    MOV BH, 0
    MOV DH, 10
    MOV DL, 24
    INT 10H
    LEA DX, WI         ; "WRONG INPUT" message
    CALL WriteString
    CALL ReadChar      ; Input without echo
    ; Set cursor again to clear the line
    MOV AH, 2
    MOV BH, 0
    MOV DH, 10
    MOV DL, 24
    INT 10H
    LEA DX, EMP        ; Empty line to overwrite the wrong input
    CALL WriteString
    ; Repeat Try Again prompt
    JMP TRYAGAIN
; ----------- END OF INPUT --------
EXIT_PROGRAM:
    MOV AH, 4Ch        ; Function to terminate the program
    INT 21h            ; DOS interrupt to terminate the program
MAIN ENDP
END MAIN