Lab 3 - Another Trial (Word Guessing Game)
Introduction
This project is an attempt to build a word guessing game in 6502 Assembly. Unlike the previous completed version, this iteration is somewhat unfinished and does not fully adhere to the intended game mechanics. However, the process led to some interesting findings, and I believe the results are still worth sharing.
Overview
This project is a simple word guessing game written in 6502 Assembly, inspired by classic word games like Hangman. The player is given a fixed word to guess and has eight attempts to correctly guess the letters. If the player completes the word before running out of attempts, they win. Otherwise, they lose, and the correct word is revealed.
**Building a Simple Word Guessing Game in 6502 Assembly**
How It Works
- The game starts by displaying a short introduction and setting up the word to guess ("seneca").
- The guessed word is initially displayed as underscores (e.g., `_ e _ e _ a`).
- The player inputs a lowercase letter, which is checked against the word.
- If the letter is in the word, it is revealed in the correct position(s).
- If the letter is incorrect, the number of remaining attempts decreases.
- The game continues until the word is fully guessed or the player runs out of attempts.
- Upon completion, a win or loss message is displayed.
Code
; ROM routine entry points
define SCINIT $ff81 ; Clear screen
define CHRIN $ffcf ; Get character input
define CHROUT $ffd2 ; Print character to screen
; Game Variables
define word_to_guess $0082 ; Word "seneca" storage
define guessed_letters $0088 ; Stores guessed letters (_ e _ e _ a)
define remaining_attempts $0081 ; Number of attempts left
define user_guess $23 ; Stores user's input
define WORD_LENGTH 6 ; Length of word
define PRINT_PTR $00 ; Print function variables
define PRINT_PTR_H $01
; Game Title
jsr PRINT
dcb "W","o","r","d",32,"G","u","e","s","s","i","n","g",32,"G","a","m","e",$0d,00
jsr PRINT
dcb "G","u","e","s","s",32,"t","h","e",32,"s","e","c","r","e","t",32,"w","o","r","d","!",$0d,00
jsr PRINT
dcb "Y","o","u",32,"h","a","v","e",32,"e","i","g","h","t",32,"c","h","a","n","c","e","s",$0d,00
START:
LDX #0
INIT_WORD:
LDA word_data, X
STA word_to_guess, X
INX
CPX #WORD_LENGTH
BNE INIT_WORD
LDX #0
INIT_GUESS:
LDA #$5F ; '_'
STA guessed_letters, X
INX
CPX #WORD_LENGTH
BNE INIT_GUESS
LDA #$08 ; Set initial attempts
STA remaining_attempts
GAME_LOOP:
jsr PRINT
dcb $0d,"W","o","r","d",32,":",32,00
LDX #0
SHOW_PROGRESS:
LDA guessed_letters, X
JSR CHROUT
LDA #32
JSR CHROUT
INX
CPX #WORD_LENGTH
BNE SHOW_PROGRESS
jsr PRINT
dcb $0d,"G","u","e","s","s",32,"a",32,"l","o","w","e","r","c","a","s","e",32,"l","e","t","t","e","r",32,"(" ,"a","-","z",")",":",32,00
GET_CHAR:
JSR CHRIN
JSR CHROUT
CMP #$61 ; 'a'
BCC GET_CHAR
CMP #$7A ; 'z'
BCS GET_CHAR
STA user_guess
LDX #0
LDA #0
STA $00 ; Match flag
CHECK_LETTER:
LDA word_to_guess, X
CMP user_guess
BNE NEXT_LETTER
STA guessed_letters, X
LDA #1
STA $00 ; Match found
NEXT_LETTER:
INX
CPX #WORD_LENGTH
BNE CHECK_LETTER
LDA $00
BNE CHECK_COMPLETE
DEC remaining_attempts
BEQ END_GAME
jsr PRINT
dcb $0d,"W","r","o","n","g","!",32,"T","r","y",32,"a","g","a","i","n",".",$0d,00
JMP GAME_LOOP
CHECK_COMPLETE:
LDX #0
CHECK_LOOP:
LDA guessed_letters, X
CMP #$5F
BEQ SHORT_JUMP
INX
CPX #WORD_LENGTH
BNE CHECK_LOOP
JMP CORRECT
SHORT_JUMP:
JMP GAME_LOOP
CORRECT:
jsr PRINT
dcb $0d,"C","o","n","g","r","a","t","s","!",32,"Y","o","u",32,"g","u","e","s","s","e","d",32,"t","h","e",32,"w","o","r","d","!",$0d,00
JMP EXIT_GAME
END_GAME:
jsr PRINT
dcb $0d,"G","a","m","e",32,"O","v","e","r",".",32,"T","h","e",32,"w","o","r","d",32,"w","a","s",32,00
LDX #0
PRINT_ANSWER:
LDA word_to_guess, X
JSR CHROUT
INX
CPX #WORD_LENGTH
BNE PRINT_ANSWER
jsr PRINT
dcb $0d,00
EXIT_GAME:
RTS
word_data:
dcb $73, $65, $6E, $65, $63, $61 ; "seneca"
PRINT:
pla
clc
adc #$01
sta PRINT_PTR
pla
sta PRINT_PTR_H
tya
pha
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
Things That Could Be Improved
While the game works as expected, there are some areas that could be improved:
1. Fixed Word Instead of Random Generation
Currently, the word to guess is hardcoded as "seneca". A better approach would be to implement random word selection from a predefined list.
2. No Hangman-Style Graphics
A true Hangman game includes a visual representation of a hanging figure that progresses with each incorrect guess. Unfortunately, implementing graphics in 6502 Assembly is quite challenging, so this feature was left out.
3. Unnecessary Blank Output
The program sometimes outputs unnecessary blank lines, especially when the player does not immediately input a letter. This is likely due to how text output is handled in the game loop. It doesn’t break the game, but it makes the output look messy.
4. Only Handles Lowercase Input
Currently, the game only accepts lowercase letters as input. Adding support for uppercase input and properly handling case conversion would improve usability and make the game more user-friendly.
Future Improvements
If I get more time, I’d like to revisit this project and:
- Implement a simple way to randomly select words.
- Improve the text rendering to prevent unwanted blank outputs.
- Attempt a basic Hangman graphic using ASCII characters or simple screen effects.
- Add support for uppercase input to enhance user experience.
Overall, this was a fun and educational project that helped me get more comfortable with 6502 Assembly.
Comments
Post a Comment