SPO600 Lab 3 - Math and Strings - Guessing Numbers.
Published: 2022-09-28 04:54:22

In my previous blog I started developing a number guessing game. The game. The game has some milestones:

- Accept number from the player.
- Compare two numbers.
- Generate a random number and store it.
- Compare the number accepted by the user with the random number.

In my previous blog we have completed the first 2 parts. Now lets start with the next part. 

## Generate a random number and store it.
So the program generates and stores the random number (answer) before starting to get the input number ('start:' part) since it needs to keep getting the input until the user inputs the correct answer but the answer in one game (round) must not be changed.

```
; variables
define        answer    $16
;-------------------------------------------------------
lda $fe        ; generate random number
and #$99       ; mask out low two bits (=numbers 0-99)
sta answer    ; store the answer

start:        jsr PRINT

dcb $0d,$0d,"E","n","t","e","r",32,"a",32,"n","u","m","b","e","r"
```
After generating the random number we will compare the input by the player with the random number. 

Here is the final code:

```
; A number guessing game

; ROM routine entry points
define        SCINIT        $ff81 ; initialize/clear screen
define        CHRIN        $ffcf ; input character from keyboard
define        CHROUT        $ffd2 ; output character to screen
define        SCREEN        $ffed ; get screen size
define        PLOT        $fff0 ; get/set cursor coordinates

; zeropage variables
define        PRINT_PTR    $10
define        PRINT_PTR_H    $11
define        value_h        $15
define        answer    $16

; absolute variables
define        GETNUM_1    $0080
define        GETNUM_2    $0081

; constants

; --------------------------------------------------------

        jsr SCINIT
        jsr CHRIN

        jsr PRINT

dcb "A",32,"n","u","m","b","e","r",32
dcb "g","u","e","s","s","i","n","g",32,"g","a","m","e",00

        lda $fe        ; generate random number
        and #$99       ; mask out low two bits (=numbers 0-99)
        sta answer     ; store the answer

start:        jsr PRINT

dcb $0d,$0d,"E","n","t","e","r",32,"a",32,"n","u","m","b","e","r"
dcb "(","0","-","9","9",")",":"
dcb 32,32,32,32,32,32,32,32,00

        lda #$00
        sta value_h

        jsr GETNUM

        sed        ; set decimal
        cmp answer ; compare user input to the answer
        cld        ; clear decimal flag (switches into binary math mode)

        bcc toolow    ; if input value is less than the answer, go to toolow
        beq identical    ; if input value is same as answer, go to identical

        ; otherwise (if input value is greater than the answer), go to toohigh
toohigh:    pha        ; push the accumulator
        jsr PRINT

dcb "T","o","o",32,"h","i","g","h",32
dcb 32,32,32,32,32,32,32
dcb 32,32,32,32,32,32,32
dcb 32,32,32,32,32,32,32
dcb 00

        jsr start

toolow:        pha        ; push the accumulator
        jsr PRINT

dcb "T","o","o",32,"l","o","w",32
dcb 32,32,32,32,32,32,32
dcb 32,32,32,32,32,32,32
dcb 32,32,32,32,32,32,32
dcb 00
        jsr start

identical:    pha        ; push the accumulator
        jsr PRINT

dcb "C","o","r","r","e","c","t",".",32
dcb "T","h","e",32,"a","n","s","w","e","r",32,"w","a","s",":"
dcb 32,32,32,32,32
dcb 00

        lda value_h
        beq low_digits
        lda #$31
        jsr CHROUT
        jmp draw_100s

low_digits:    lda answer
        and #$f0
        beq ones_digit

draw_100s:    lda answer
        lsr
        lsr
        lsr
        lsr
        ora #$30
        jsr CHROUT

ones_digit:    lda answer
        and #$0f
        ora #$30
        jsr CHROUT

        brk        ; if correct, break the program

; --------------------------------------------------------
; Print a message
; 
; Prints the message in memory immediately after the 
; JSR PRINT. The message must be null-terminated and
; 255 characters maximum in length.

PRINT:        pla    ; pull the accumulator
        clc    ; clear carry flag (C) - required before using ADC
        adc #$01    ; add with carry
        sta PRINT_PTR
        pla
        sta PRINT_PTR_H

        tya    ; transfer Y to A
        pha    ; push the accumulator

        ldy #$00
print_next:    lda (PRINT_PTR),y
        beq print_done

        jsr CHROUT
        iny
        jmp print_next

print_done:    tya
        clc
        adc PRINT_PTR
        sta PRINT_PTR

        lda PRINT_PTR_H
        adc #$00
        sta PRINT_PTR_H

        pla
        tay

        lda PRINT_PTR_H
        pha
        lda PRINT_PTR
        pha

        rts

; ---------------------------------------------------
; GETNUM - get a 2-digit decimal number
;
; Returns A containing 2-digit BCD value

GETNUM:        txa        ; transfer X to accumulator
        pha        ; push the accumulator
        tya        ; transfer Y to A
        pha

        ldx #$00    ; count of digits received
        stx GETNUM_1    ; store the X register
        stx GETNUM_2


getnum_cursor:    lda #$a0    ; black square
        jsr CHROUT
        lda #$83    ; left cursor
        jsr CHROUT

getnum_key:    jsr CHRIN
        cmp #$00
        beq getnum_key

        cmp #$08    ; BACKSPACE
        beq getnum_bs

        cmp #$0d    ; ENTER
        beq getnum_enter

        cmp #$30    ; "0"
        bmi getnum_key

        cmp #$3a    ; "9" + 1
        bmi getnum_digit

        jmp getnum_key

getnum_enter:    cpx #$00
        beq getnum_key

        lda #$20
        jsr CHROUT
        lda #$0d
        jsr CHROUT

        lda GETNUM_1

        cpx #$01
        beq getnum_done

        asl
        asl
        asl
        asl
        ora GETNUM_2

getnum_done:    sta GETNUM_1
        pla
        tay
        pla
        tax
        lda GETNUM_1

        rts

getnum_digit:    cpx #$02
        bpl getnum_key
        pha
        jsr CHROUT
        pla
        and #$0f
        sta GETNUM_1,x
        inx
        jmp getnum_cursor

getnum_bs:    cpx #$00
        beq getnum_key
        lda #$20
        jsr CHROUT
        lda #$83
        jsr CHROUT
        jsr CHROUT
        lda #$20
        jsr CHROUT
        lda #$83
        jsr CHROUT
        dex
        lda #$00
        sta GETNUM_1,x
        jmp getnum_cursor
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p01cfmxe6k0isywrkujh.png)

I have used Chris Tyler's code from the repository of Wiki page.