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_SCREENPRINT_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_LOOPThe 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
Post a Comment