Lab 3 - Number guessing game

 Lab 3 - Number guessing game

In this lab, I will make a game where you can guess a number between 1 to 100. Each guess will narrow the number range until the player guesses the correct number.

First, I make a character interface to welcome the player and prompt to start the game.
  define SCINIT		   $ff81 ; initialize/clear screen
  define CHRIN       $ffcf ; input character from keyboard  
  define CHROUT	  	 $ffd2 ; output character to screen

  define STRPTR      $00   ; String pointer - low byte
  define STRPTRH     $01   ; String pointer - high byte
  
MAIN:
  ; Move string pointer points to welcome string
  JSR SCINIT
  LDA #<STR_WELCOME
  STA STRPTR
  LDA #>STR_WELCOME
  STA STRPTRH
  JSR PRINT_STR   ; Print string
  
  ; Print next line character
  LDA #$0D
  JSR CHROUT  
  
  ; Move string pointer points to start game prompt string
  LDA #<STR_START
  STA STRPTR
  LDA #>STR_START
  STA STRPTRH
  JSR PRINT_STR  ; Print string

START:
  LDA $FF
  CMP #$0D       ; Detect if user entered 'Enter' key
  BNE START      ; 


MAIN_GAME:
  RTS

; Print the line of string to the character display
PRINT_STR:
  LDY #$00
PRINT_LOOP:
  LDA (STRPTR), Y  ; Get the character
  BEQ RETURN       ; Return if the string reach the null character
  JSR CHROUT       ; Output character to screen
  INY              ; Next character
  BNE PRINT_LOOP   ; Loop
  
RETURN:
  RTS

; Strings
STR_WELCOME:
  DCB "*","*","*","W","e","l","c","o","m","e",$20,"t","o",$20,"n","u","m","b","e","r",$20,"g","u","e","s","s","i","n","g",$20,"g","a","m","e","*","*","*",$0D,0
STR_START:
  DCB "P","l","e","a","s","e",$20,"p","r","e","s","s",$20,"e","n","t","e","r",$20,"t","o",$20,"s","t","a","r","t",$0D,0

To start the game, I need to define the range and set a random number between 1 to 100 as the secret number. I used a one-byte pseudo-random number generator to get a random number. However, the number will generate between 0 to 255. So, I created a loop to get a random number again if the number is 0 or greater than 100.
MAIN_GAME:
  ; Initial the guess range
  LDA #$01
  STA MIN
  LDA #$64
  STA MAX
  ; Set a random number between 1 - 100
SET_TARGET:
  LDA $FE
  CMP #$01
  BCC SET_TARGET        ; Get a random number again if the number is less than 1
  BEQ SET_TARGET        ; Get a random number again if the number is equal to 1
  CMP #$64
  BCS SET_TARGET        ; Get a random number again if the number is greater than or equal to 100
  STA TARGET_NUM        ; Store the random number as the target number
To use the Bitmap, I will print a cover on the screen. When the guessing number is revealed, it will print the number on the Bitmap.
  define MAX_WIDTH   $50
  define MAX_HEIGHT  $51
; Print covering box
  LDA #$0B
  STA MAX_WIDTH
  LDA #$07
  STA MAX_HEIGHT

  LDA #<BOX
  STA IMGPTR
  LDA #>BOX
  STA IMGPTRH

  LDA #$8B
  STA SCRPTR
  LDA #$03
  STA SCRPTRH

  JSR PRINT_SCREEN
PRINT_SCREEN:
  LDY #$00
  LDX #$00
PRINT_IMG:
  LDA (IMGPTR), Y
  STA (SCRPTR), Y
  INY
  CPY MAX_WIDTH
  BNE PRINT_IMG
  
  INX
  CPX MAX_HEIGHT
  BEQ RETURN_NEAR
  
  LDA IMGPTR
  CLC
  ADC MAX_WIDTH
  STA IMGPTR
  LDA IMGPTRH
  ADC #$00
  STA IMGPTRH
  
  LDA SCRPTR
  CLC
  ADC #$20
  STA SCRPTR
  LDA SCRPTRH
  ADC #$00
  STA SCRPTRH

  LDY #$00
  JMP PRINT_IMG
Then, I will ask the player to input a number. Since the number entered will use ASCII code to store in the Accumulator, I need to convert the ASCII code into a number. I will subtract 10 each time and increase Y to count the ten digits, and the number left over would be the unit digit.
CONVERT_STR_NUM:
  ; Read unit
  CPX #$00
  BEQ GETINPUT
  DEX
  LDA STR_NUM, X
  CMP #$00
  BEQ CONVERT_STR_NUM
  SBC #$30
  STA USER_NUM
  
  ; Read ten
  CPX #$00
  BEQ GAME_LOGIC
  DEX
  LDA STR_NUM, X
  SBC #$30
  ASL ; x2
  STA TEMP_NUM
  ASL ; x4
  ASL ; x8
  CLC
  ADC TEMP_NUM
  ADC USER_NUM
  STA USER_NUM
Each time the player guesses a number, the number range will be narrowed down.
GAME_LOGIC:
  ; Check if the user input number same as the target number
  CMP TARGET_NUM
  BEQ WIN
  BCS CHANGE_MAX
  BCC CHANGE_MIN
  
CHANGE_MAX:
  CMP MAX
  BCS CLEAR_INPUT
  STA MAX
  JMP GAME_LOOP

CHANGE_MIN:
  CMP MIN
  BEQ CLEAR_INPUT
  BCC CLEAR_INPUT
  STA MIN
  JMP GAME_LOOP
The full code and the working game are below:
  define SCINIT		   $ff81 ; initialize/clear screen
  define CHRIN       $ffcf ; input character from keyboard  
  define CHROUT	  	 $ffd2 ; output character to screen

  define STRPTR      $00   ; String pointer - low byte
  define STRPTRH     $01   ; String pointer - high byte
  define TARGET_NUM  $02   ; Target number for guessing
  define MIN         $03   ; Minimum of the range
  define MAX         $04   ; Maximin of the range
  
  define TEN         $10
  define UNIT        $11

  define STR_NUM     $20   ; The place to store the number character
  define USER_NUM    $22
  define TEMP_NUM    $23

  define MAX_WIDTH   $50
  define MAX_HEIGHT  $51
  define IMGPTR      $60
  define IMGPTRH     $61
  define SCRPTR      $62
  define SCRPTRH     $63
  
MAIN:
  ; Move string pointer points to welcome string
  JSR SCINIT
  LDA #<STR_WELCOME
  STA STRPTR
  LDA #>STR_WELCOME
  STA STRPTRH
  JSR PRINT_STR   ; Print string
  
  ; Print next line character
  LDA #$0D
  JSR CHROUT  
  
  ; Move string pointer points to start game prompt string
  LDA #<STR_START
  STA STRPTR
  LDA #>STR_START
  STA STRPTRH
  JSR PRINT_STR  ; Print string

START:
  LDA $FF
  CMP #$0D       ; Detect if user entered 'Enter' key
  BNE START      ; 

; *************************************************************************************
MAIN_GAME:
  ; Initial the guess range
  LDA #$01
  STA MIN
  LDA #$64
  STA MAX

  ; Set a random number between 1 - 100
SET_TARGET:
  LDA $FE
  CMP #$01
  BCC SET_TARGET        ; Get a random number again if the number is less than 1
  BEQ SET_TARGET        ; Get a random number again if the number is equal to 1
  CMP #$64
  BCS SET_TARGET        ; Get a random number again if the number is greater than or equal to 100
  STA TARGET_NUM        ; Store the random number as the target number

  ; Print covering box
  LDA #$0B
  STA MAX_WIDTH
  LDA #$07
  STA MAX_HEIGHT

  LDA #<BOX
  STA IMGPTR
  LDA #>BOX
  STA IMGPTRH

  LDA #$8B
  STA SCRPTR
  LDA #$03
  STA SCRPTRH

  JSR PRINT_SCREEN

GAME_LOOP:
  JSR SCINIT            ; Initialize character display
  ; Move string pointer points to range prompt
  LDA #<STR_RANGE_PROMPT
  STA STRPTR
  LDA #>STR_RANGE_PROMPT
  STA STRPTRH
  JSR PRINT_STR         ; Print string
  
  LDA MIN
  JSR CAL_TENS_UNITS
  JSR PRINT_NUM

  LDA #<STR_TO
  STA STRPTR
  LDA #>STR_TO
  STA STRPTRH
  JSR PRINT_STR

  LDA MAX
  JSR CAL_TENS_UNITS
  JSR PRINT_NUM
  LDA #$3A             ; Print :
  JSR CHROUT
  LDA #$0D             ; Next line
  JSR CHROUT
  
GETINPUT:
  LDX #$00
CHECK:
  LDA $FF
  CMP #$08
  BEQ DELETE_CH
  CMP #$0D
  BEQ CONVERT_STR_NUM
  CMP #$00
  BEQ CHECK

STORE_CH:
  CPX #$02
  BEQ CHECK
  STA STR_NUM, X
  INX
  JSR CHROUT
  LDA #$00
  STA $FF
  JMP CHECK

DELETE_CH:
  CPX #$00
  BEQ CHECK
  JSR CHROUT
  LDA #$00
  DEX
  STA STR_NUM, X
  STA $FF
  JMP CHECK

CONVERT_STR_NUM:
  ; Read unit
  CPX #$00
  BEQ GETINPUT
  DEX
  LDA STR_NUM, X
  CMP #$00
  BEQ CONVERT_STR_NUM
  SBC #$30
  STA USER_NUM
  
  ; Read ten
  CPX #$00
  BEQ GAME_LOGIC
  DEX
  LDA STR_NUM, X
  SBC #$30
  ASL ; x2
  STA TEMP_NUM
  ASL ; x4
  ASL ; x8
  CLC
  ADC TEMP_NUM
  ADC USER_NUM
  STA USER_NUM

GAME_LOGIC:
  ; Check if the user input number same as the target number
  CMP TARGET_NUM
  BEQ WIN
  BCS CHANGE_MAX
  BCC CHANGE_MIN
  
CHANGE_MAX:
  CMP MAX
  BCS CLEAR_INPUT
  STA MAX
  JMP GAME_LOOP

CHANGE_MIN:
  CMP MIN
  BEQ CLEAR_INPUT
  BCC CLEAR_INPUT
  STA MIN
  JMP GAME_LOOP

CLEAR_INPUT:
  LDA #$08
  JSR CHROUT
  JSR CHROUT
  JMP GETINPUT

WIN:
  JSR SCINIT
  LDA #<STR_WIN
  STA STRPTR
  LDA #>STR_WIN
  STA STRPTRH
  JSR PRINT_STR

  ; Remove box

  LDA #<BLANK_BOX
  STA IMGPTR
  LDA #>BLANK_BOX
  STA IMGPTRH

  LDA #$8B
  STA SCRPTR
  LDA #$03
  STA SCRPTRH

  JSR PRINT_SCREEN

  ; Print the target number to bitmap
  LDA #$05
  STA MAX_WIDTH
  LDA #$07
  STA MAX_HEIGHT

  LDA #$8B
  STA SCRPTR
  LDA #$03
  STA SCRPTRH

  LDA TARGET_NUM
  JSR CAL_TENS_UNITS
  LDA TEN
  JSR GET_NUM_IMG
  JSR PRINT_SCREEN

  LDA #$91
  STA SCRPTR
  LDA #$03
  STA SCRPTRH

  LDA UNIT
  JSR GET_NUM_IMG
  JSR PRINT_SCREEN

  RTS
PRINT_SCREEN:
  LDY #$00
  LDX #$00
PRINT_IMG:
  LDA (IMGPTR), Y
  STA (SCRPTR), Y
  INY
  CPY MAX_WIDTH
  BNE PRINT_IMG
  
  INX
  CPX MAX_HEIGHT
  BEQ RETURN_NEAR
  
  LDA IMGPTR
  CLC
  ADC MAX_WIDTH
  STA IMGPTR
  LDA IMGPTRH
  ADC #$00
  STA IMGPTRH
  
  LDA SCRPTR
  CLC
  ADC #$20
  STA SCRPTR
  LDA SCRPTRH
  ADC #$00
  STA SCRPTRH

  LDY #$00
  JMP PRINT_IMG

RETURN_NEAR:
  RTS

GET_NUM_IMG:
  CMP #$00
  BEQ GET_NUM_0
  CMP #$01
  BEQ GET_NUM_1
  CMP #$02
  BEQ GET_NUM_2
  CMP #$03
  BEQ GET_NUM_3
  CMP #$04
  BEQ GET_NUM_4
  CMP #$05
  BEQ GET_NUM_5
  CMP #$06
  BEQ GET_NUM_6
  CMP #$07
  BEQ GET_NUM_7
  CMP #$08
  BEQ GET_NUM_8
  CMP #$09
  BEQ GET_NUM_9

GET_NUM_0:
  LDA #<NUM_0
  STA IMGPTR
  LDA #>NUM_0
  STA IMGPTRH
  RTS
GET_NUM_1:
  LDA #<NUM_1
  STA IMGPTR
  LDA #>NUM_1
  STA IMGPTRH
  RTS
GET_NUM_2:
  LDA #<NUM_2
  STA IMGPTR
  LDA #>NUM_2
  STA IMGPTRH
  RTS
GET_NUM_3:
  LDA #<NUM_3
  STA IMGPTR
  LDA #>NUM_3
  STA IMGPTRH
  RTS
GET_NUM_4:
  LDA #<NUM_4
  STA IMGPTR
  LDA #>NUM_4
  STA IMGPTRH
  RTS
GET_NUM_5:
  LDA #<NUM_5
  STA IMGPTR
  LDA #>NUM_5
  STA IMGPTRH
  RTS
GET_NUM_6:
  LDA #<NUM_6
  STA IMGPTR
  LDA #>NUM_6
  STA IMGPTRH
  RTS
GET_NUM_7:
  LDA #<NUM_7
  STA IMGPTR
  LDA #>NUM_7
  STA IMGPTRH
  RTS
GET_NUM_8:
  LDA #<NUM_8
  STA IMGPTR
  LDA #>NUM_8
  STA IMGPTRH
  RTS
GET_NUM_9:
  LDA #<NUM_9
  STA IMGPTR
  LDA #>NUM_9
  STA IMGPTRH
  RTS
; *************************************************************************************
CAL_TENS_UNITS:
  LDY #$00
  SEC
CAL_TENS:
  SBC #$0A
  BMI CAL_UNITS
  INY
  BPL CAL_TENS

CAL_UNITS:
  ADC #$0A
  STA UNIT
  STY TEN
  RTS
; *************************************************************************************
PRINT_NUM:
  LDA TEN
  BEQ P_UNIT
  CMP #$0A
  BEQ P_100
  CLC
  ADC #$30
  JSR CHROUT
P_UNIT:
  LDA UNIT
  CLC
  ADC #$30
  JSR CHROUT
  LDA #$20
  JSR CHROUT
  RTS

P_100:
  ; Move string pointer points to String 100
  LDA #<STR_100
  STA STRPTR
  LDA #>STR_100
  STA STRPTRH
  JSR PRINT_STR   ; Print string
  RTS
; *************************************************************************************

; *************************************************************************************
; Print the line of string to the character display
PRINT_STR:
  LDY #$00
PRINT_LOOP:
  LDA (STRPTR), Y  ; Get the character
  BEQ RETURN       ; Return if the string reach the null character
  JSR CHROUT       ; Output character to screen
  INY              ; Next character
  BNE PRINT_LOOP   ; Loop
; *************************************************************************************
RETURN:
  RTS
; *************************************************************************************
; Strings
STR_WELCOME:
  DCB "*","*","*","W","e","l","c","o","m","e",$20,"t","o",$20,"n","u","m","b","e","r",$20,"g","u","e","s","s","i","n","g",$20,"g","a","m","e","*","*","*",$0D,0
STR_START:
  DCB "P","l","e","a","s","e",$20,"p","r","e","s","s",$20,"e","n","t","e","r",$20,"t","o",$20,"s","t","a","r","t",$0D,0
STR_RANGE_PROMPT:
  DCB "P","l","e","a","s","e",$20,"e","n","t","e","r",$20,"a",$20,"n","u","m","b","e","r",$20,"b","e","t","w","e","e","n",$20,0
STR_TO:
  DCB "t","o",$20,0
STR_100:
  DCB "1","0","0",0
STR_WIN:
  DCB "Y","o","u",$20,"W","I","N","!",0
; *************************************************************************************
; Graph
NUM_0:
  DCB $01,$01,$01,$01,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
NUM_1:
  DCB $00,$00,$01,$00,$00
  DCB $00,$01,$01,$00,$00
  DCB $01,$00,$01,$00,$00
  DCB $00,$00,$01,$00,$00
  DCB $00,$00,$01,$00,$00
  DCB $00,$00,$01,$00,$00
  DCB $01,$01,$01,$01,$01
NUM_2:
  DCB $01,$01,$01,$01,$01
  DCB $00,$00,$00,$00,$01
  DCB $00,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
  DCB $01,$00,$00,$00,$00
  DCB $01,$00,$00,$00,$00
  DCB $01,$01,$01,$01,$01
NUM_3:
  DCB $01,$01,$01,$01,$01
  DCB $00,$00,$00,$00,$01
  DCB $00,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
  DCB $00,$00,$00,$00,$01
  DCB $00,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
NUM_4:
  DCB $01,$00,$01,$00,$00
  DCB $01,$00,$01,$00,$00
  DCB $01,$00,$01,$00,$00
  DCB $01,$01,$01,$01,$01
  DCB $00,$00,$01,$00,$00
  DCB $00,$00,$01,$00,$00
  DCB $00,$00,$01,$00,$00
NUM_5:
  DCB $01,$01,$01,$01,$01
  DCB $01,$00,$00,$00,$00
  DCB $01,$00,$00,$00,$00
  DCB $01,$01,$01,$01,$01
  DCB $00,$00,$00,$00,$01
  DCB $00,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
NUM_6:
  DCB $01,$01,$01,$01,$01
  DCB $01,$00,$00,$00,$00
  DCB $01,$00,$00,$00,$00
  DCB $01,$01,$01,$01,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
NUM_7:
  DCB $01,$01,$01,$01,$01
  DCB $00,$00,$00,$00,$01
  DCB $00,$00,$00,$01,$00
  DCB $00,$00,$00,$01,$00
  DCB $00,$00,$01,$00,$00
  DCB $00,$00,$01,$00,$00
  DCB $00,$00,$01,$00,$00
NUM_8:
  DCB $01,$01,$01,$01,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
NUM_9:
  DCB $01,$01,$01,$01,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
  DCB $00,$00,$00,$00,$01
  DCB $00,$00,$00,$00,$01
  DCB $01,$01,$01,$01,$01
BOX:
  DCB $01,$01,$00,$01,$01,$01,$01,$00,$01,$01,$01
  DCB $01,$00,$01,$00,$01,$01,$00,$01,$00,$01,$01
  DCB $01,$01,$01,$00,$01,$01,$01,$01,$00,$01,$01
  DCB $01,$01,$00,$01,$01,$01,$01,$00,$01,$01,$01
  DCB $01,$01,$00,$01,$01,$01,$01,$00,$01,$01,$01
  DCB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01
  DCB $01,$01,$00,$01,$01,$01,$01,$00,$01,$01,$01
BLANK_BOX:
  DCB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00





Comments

Popular posts from this blog

Project - Stage 1: Create a Basic GCC Pass

Lab 4 - GCC Build