.data
guessBuffer: .space 100
guessList: .space 200	
hintArray:.asciiz "     "
checkArray: .asciiz "     "
newGame: .asciiz "\nWelcome to MIPS wordle!\n6 guesses. Letters must be in UPPERCASE.\n'*' means that letter is in the word.\n'!' means that letter is in the correct spot.\n"
guessPrompt: .asciiz "\nEnter guess number "
error: .asciiz "Guess must be 5 uppercase letters! Try again: "
congratulation: .asciiz "\nCongratulations, you guessed the word! The word was: "
gameLost: .asciiz "\nYou ran out of guesses. The correct word was: "
replayPrompt: .asciiz "\nWould you like to play again? (y/n): "
wordBank: .asciiz "WHICH\0THERE\0THEIR\0ABOUT\0WOULD\0THESE\0OTHER\0WORDS\0COULD\0WRITE\0FIRST\0WATER\0AFTER\0WHERE\0RIGHT\0THINK\0THREE\0YEARS\0PLACE\0SOUND\0GREAT\0AGAIN\0STILL\0EVERY\0SMALL\0FOUND\0THOSE\0NEVER\0UNDER\0MIGHT\0WHILE\0HOUSE\0WORLD\0BELOW\0ASKED\0GOING\0LARGE\0UNTIL\0ALONG\0SHALL\0BEING\0OFTEN\0EARTH\0BEGAN\0SINCE\0STUDY\0NIGHT\0LIGHT\0ABOVE\0PAPER\0PARTS\0YOUNG\0STORY\0POINT\0TIMES\0HEARD\0WHOLE\0WHITE\0GIVEN\0MEANS\0MUSIC\0MILES\0THING\0TODAY\0LATER\0USING\0MONEY\0LINES\0ORDER\0GROUP\0AMONG\0LEARN\0KNOWN\0SPACE\0TABLE\0EARLY\0TREES\0SHORT\0HANDS\0STATE\0BLACK\0SHOWN\0STOOD\0FRONT\0VOICE\0KINDS\0MAKES\0COMES\0CLOSE\0POWER\0LIVED\0VOWEL\0TAKEN\0BUILT\0HEART\0READY\0QUITE\0CLASS\0BRING\0ROUND\0HORSE\0SHOWS\0PIECE\0GREEN\0STAND\0BIRDS\0START\0RIVER\0TRIED\0LEAST\0FIELD\0WHOSE\0GIRLS\0LEAVE\0ADDED\0COLOR\0THIRD\0HOURS\0MOVED\0PLANT\0DOING\0NAMES\0FORMS\0HEAVY\0IDEAS\0CRIED\0CHECK\0FLOOR\0BEGIN\0WOMAN\0ALONE\0PLANE\0SPELL\0WATCH\0CARRY\0WROTE\0CLEAR\0NAMED\0BOOKS\0CHILD\0GLASS\0HUMAN\0TAKES\0PARTY\0BUILD\0SEEMS\0BLOOD\0SIDES\0SEVEN\0MOUTH\0SOLVE\0NORTH\0VALUE\0DEATH\0MAYBE\0HAPPY\0TELLS\0GIVES\0LOOKS\0SHAPE\0LIVES\0STEPS\0AREAS\0SENSE\0SPEAK\0FORCE\0OCEAN\0SPEED\0WOMEN\0METAL\0SOUTH\0GRASS\0SCALE\0CELLS\0LOWER\0SLEEP\0WRONG\0PAGES\0SHIPS\0NEEDS\0ROCKS\0EIGHT\0MAJOR\0LEVEL\0TOTAL\0AHEAD\0REACH\0STARS\0STORE\0SIGHT\0TERMS\0CATCH\0WORKS\0BOARD\0COVER\0SONGS\0EQUAL\0STONE\0WAVES\0GUESS\0DANCE\0SPOKE\0BREAK\0CAUSE\0RADIO\0WEEKS\0LANDS\0BASIC\0LIKED\0TRADE\0FRESH\0FINAL\0FIGHT\0MEANT\0DRIVE\0SPENT\0LOCAL\0WAXES\0KNOWS\0TRAIN\0BREAD\0HOMES\0TEETH\0COAST\0THICK\0BROWN\0CLEAN\0QUIET\0SUGAR\0FACTS\0STEEL\0FORTH\0RULES\0NOTES\0UNITS\0PEACE\0MONTH\0VERBS\0SEEDS\0HELPS\0SHARP\0VISIT\0WOODS\0CHIEF\0WALLS\0CROSS\0WINGS\0GROWN\0CASES\0FOODS\0CROPS\0FRUIT\0STICK\0WANTS\0STAGE\0SHEEP\0NOUNS\0PLAIN\0DRINK\0BONES\0APART\0TURNS\0MOVES\0TOUCH\0ANGLE\0BASED\0RANGE\0MARKS\0TIRED\0OLDER\0FARMS\0SPEND\0SHOES\0GOODS\0CHAIR\0TWICE\0CENTS\0EMPTY\0ALIKE\0STYLE\0BROKE\0PAIRS\0COUNT\0ENJOY\0SCORE\0SHORE\0ROOTS\0PAINT\0HEADS\0SHOOK\0SERVE\0ANGRY\0CROWD\0WHEEL\0QUICK\0DRESS\0SHARE\0ALIVE\0NOISE\0SOLID\0CLOTH\0SIGNS\0HILLS\0TYPES\0DRAWN\0WORTH\0TRUCK\0PIANO\0UPPER\0LOVED\0USUAL\0FACES\0DROVE\0CABIN\0BOATS\0TOWNS\0PROUD\0COURT\0MODEL\0PRIME\0FIFTY\0PLANS\0YARDS\0PROVE\0TOOLS\0PRICE\0SHEET\0SMELL\0BOXES\0RAISE\0MATCH\0TRUTH\0ROADS\0THREW\0ENEMY\0LUNCH\0CHART\0SCENE\0GRAPH\0DOUBT\0GUIDE\0WINDS\0BLOCK\0GRAIN\0SMOKE\0MIXED\0GAMES\0WAGON\0SWEET\0TOPIC\0EXTRA\0PLATE\0TITLE\0KNIFE\0FENCE\0FALLS\0CLOUD\0WHEAT\0PLAYS\0ENTER\0BROAD\0STEAM\0ATOMS\0PRESS\0LYING\0BASIS\0CLOCK\0TASTE\0GROWS\0THANK\0STORM\0AGREE\0BRAIN\0TRACK\0SMILE\0FUNNY\0BEACH\0STOCK\0HURRY\0SAVED\0SORRY\0GIANT\0TRAIL\0OFFER\0OUGHT\0ROUGH\0DAILY\0AVOID\0KEEPS\0THROW\0ALLOW\0CREAM\0LAUGH\0EDGES\0TEACH\0FRAME\0BELLS\0DREAM\0MAGIC\0OCCUR\0ENDED\0CHORD\0FALSE\0SKILL\0HOLES\0DOZEN\0BRAVE\0APPLE\0CLIMB\0OUTER\0PITCH\0RULER\0HOLDS\0FIXED\0COSTS\0CALLS\0BLANK\0STAFF\0LABOR\0EATEN\0YOUTH\0TONES\0HONOR\0GLOBE\0GASES\0DOORS\0POLES\0LOOSE\0APPLY\0TEARS\0EXACT\0BRUSH\0CHEST\0LAYER\0WHALE\0MINOR\0FAITH\0TESTS\0JUDGE\0ITEMS\0WORRY\0WASTE\0HOPED\0STRIP\0BEGUN\0ASIDE\0LAKES\0BOUND\0DEPTH\0CANDY\0EVENT\0WORSE\0AWARE\0SHELL\0ROOMS\0RANCH\0IMAGE\0SNAKE\0ALOUD\0DRIED\0LIKES\0MOTOR\0POUND\0KNEES\0REFER\0FULLY\0CHAIN\0SHIRT\0FLOUR\0DROPS\0SPITE\0ORBIT\0BANKS\0SHOOT\0CURVE\0TRIBE\0TIGHT\0BLIND\0SLEPT\0SHADE\0CLAIM\0FLIES\0THEME\0QUEEN\0FIFTH\0UNION\0HENCE\0STRAW\0ENTRY\0ISSUE\0BIRTH\0FEELS\0ANGER\0BRIEF\0RHYME\0GLORY\0GUARD\0FLOWS\0FLESH\0OWNED\0"

.text
main:
	li $s2, 5				# Initializes a global variable with the number of letters in the keyword.
	
	li $v0, 4				# Prints an introduction with a set of rules.
	la $a0, newGame   
	syscall 
	
	replay:
	addi $sp, $sp, -16			# Creates a stack frame.
	sw $ra, 0($sp)				# Stores the return address to the stack.
	
	jal findRandomWord			# Finds a random word and stores its address into $s1.
	
	li $t0, 1				# Initializes a guess counter.
	
	mainLoop:
	li $t2, 7				# Max guesses (plus 1).
	beq $t0, $t2, mainFinal		# Branches if all guesses have been used.
	
	li $v0, 4				# Promps for input.
	la $a0, guessPrompt   
	syscall 
	li $v0, 1
	add $a0, $t0, $zero			# Prints the guess number.
	syscall
	li $v0, 11
	addi $a0, $zero, 58			# Prints a colon.
	syscall
	li $v0, 11
	addi $a0, $zero, 32			# Prints a space.
	syscall
	
	sw $t0, 4($sp)				# Stores the guess counter to the stack.
	
	jal guessValidator			# Takes correctly formatted guess as input and stores in the guessBuffer.
	jal checkGuess				# Checks that guess for matches with the keyword. Stores a list of hints to
						# hintArray.
	
	lw $t0, 4($sp)				# Loads the guess counter from the stack.
	add $a0, $t0, $zero			# Uses our index as an argument for guessFormatter.
	jal guessFormatter			# Formats that guess with hints from hintArray and appends to guessList.
	
	li $v0, 4				# Prints the guessList.
	la $a0, guessList   
	syscall 
	
	lw $t0, 4($sp)				# Loads the guess counter from the stack.
	addi $t0, $t0, 1			# Increments the guess counter by 1.
	
	j mainLoop
	
	mainFinal:				# If the program has reached this point, the player is out of guesses.
	lw $ra, 0($sp)				# Stores the return address to the stack.
	addi $sp, $sp, 16			# Removes the stack frame created for 'main'.
	j outOfGuesses
	
	mainReplay:			
	la $a0, guessList			# Clears all the arrays for replayability.
	jal clearArray
	la $a0, hintArray
	jal clearArray
	
	li $v0, 4				# Prompts if the player would like to play again.
	la $a0, replayPrompt   
	syscall 
	li $v0, 12				# Reads a character.
	syscall 
	li $t0, 121				# ASCII code for 'y'.
	beq $t0, $v0, replay			# Replays if we get a 'y'.
					
	li $v0, 10          			# If the player entered any other character, the program will exit.
      	syscall         
	
guessValidator:					# Validates the input for a guess. Ensures that we have exactly
						# 5 characters that are all uppercase English letters.
						
	la $a0, guessBuffer			# Reads an input string and stores it to guessBuffer.
	addi $a1, $s2, 100			
	li $v0, 8				
	syscall 
	
	li $t0, -1				# Initializes the index for guessValidatorLoop.
	la $t3, guessBuffer			# Loads in the address of the guessBuffer
	
	guessValidatorLoop: 			# Iterates through each character of the input
	addi $t0, $t0, 1			# Increments the guessValidatorLoop index by 1.
	
	add $t8, $t0, $t3			# Loads in the value of guessBuffer at the current offset.
	lb $t1, 0($t8)
	
	li $t9, 10				# ASCII code for a newline, signals the end of the input.
	beq $t1, $t9, guessValidatorFoundNewline	
	
	slti $t2, $t1, 65			# Checks if the ASCII value of the guessBuffer letter is in the range
						# of 65 to 90, the range of uppercase letter ASCII codes.
	bne $t2, $zero, guessValidatorError
	slti $t2, $t1, 91
	beq $t2, $zero, guessValidatorError
	bne $t1, $zero, guessValidatorLoop	# Loops back if the loaded value from guessBuffer passed all the tests.
	
	guessValidatorError:			# Prints an error prompt, and restarts the procedure to receive new input.
	li $v0, 4			
	la $a0, error
	syscall 
	j guessValidator
	
	guessValidatorFoundNewline:		
	li $t1, 5
	bne $t0, 5, guessValidatorError	# Branches if the length is not 5.
	sb $zero, 0($t8)			# Replaces the newline character with a null byte.
	jr $ra					
	
	
findRandomWord:					# Generates a random number using a PRNG, and uses that number
						# as an index to our word bank. 
						
	li $v0, 42				# Generates a random number in range 0-499 inclusive.
	li $a1, 499				
	li $a0, 0		
	syscall
	
	sll $t2, $a0, 2				# Multiplies by 6 (the length of our keyword plus 1 for the null byte).
	add $t2, $a0, $t2
	add $t2, $a0, $t2		
	
	la $s1, wordBank
	add $s1, $s1, $t2			# Adds the index to the wordbank address and stores this offset in $s1.
	jr $ra

clearArray:					# Fills an array with spaces. Stores zeros to memory until
						# a null byte is reached.
						# $a0 is the address of the array to clear.
	addi $t0, $zero, -1			# Initializes an index for clearArrayLoop.
	addi $t1, $zero, 32			# ASCII code for a space.
	
	clearArrayLoop:				# Loops through each element of the array.
	addi $t0, $t0, 1			# Increments the clearArrayLoop index by 1.
	
	add $t2, $a0, $t0			# Checks if we have reached a null byte in the array.
	lb $t3, 0($t2)				
	beq $t3, $zero, clearArrayFinal	# Branches on a null byte.
	
	sb $t1, 0($t2)				# Stores a space to the array offset.
	j clearArrayLoop
	
	clearArrayFinal:
	jr $ra


correctAnswerFound:				# Outputs that the player has won.
	li $v0, 4			
	la $a0, congratulation   
	syscall 
	add $a0, $zero, $s1   
	syscall 
	j mainReplay


outOfGuesses:					# Outputs that the player has lost.
	li $v0, 4		
	la $a0, gameLost   
	syscall 
	li $v0, 4			
	add $a0, $s1, $zero
	syscall 
	j mainReplay


letterInSpotFinder:				# Iterates through the guess and keyword and finds any exact letter
						# matches between the two. At the index where letters match, an
						# exclamation point is stored to hintArray.
	addi $t0, $zero	, 33			# ASCII code for an exclamation point.
	addi $t1, $zero, -1			# Initializes an index for letterInSpotFinderLoop.
	add $t9, $zero, $zero			# Counter of exclamation points. Starts at zero. Used to determine
						# if the game has been won.
	
	letterInSpotFinderLoop:
	addi $t1, $t1, 1			# Increments the index by 1.
	beq $t1, $s2, letterInSpotFinderFinal	# Branches if we have checked every letter ($s2 = 5).

	add $t3, $s1, $t1			# Adds the letterInSpotFinderLoop index to the keyword address in $s1.
	lb $t5, 0($t3)				# Loads in the keyword letter at that offset.
	la $t7, guessBuffer		
	add $t3, $t7, $t1			# Adds the letterInSpotFinderLoop index to the guessBuffer address.
	lb $t6, 0($t3)				# Loads in the guessBuffer letter at that offset.

	bne $t5, $t6, letterInSpotFinderLoop	# Branches when the keyword letter is not equal to the guess letter,
						# and moves on to the next set of letters.
						
	la $t2, hintArray			# If we reach this point, the letter in the guess and keyword match.
	add $t8, $t2, $t1			# Adds the letterInSpotFinderLoop index to the hintArray address.
	sb $t0, 0($t8)				# Stores an exclamation point to the hintArray.
	addi $t9, $t9, 1			# Increments the exclamation point counter by 1. 
	j letterInSpotFinderLoop
	
	letterInSpotFinderFinal:
	beq $t9, $s2, correctAnswerFound	# If the exclamation pointer count is 5, the game is won.
	jr $ra


guessFormatter:					# Takes the hint values from hintArray and concatenates them with the guess.
						# Stores this string to the array of previous guesses (guessList).
						# $a0 is the total guess count (used to find the offset of guessList).
	
	addi $sp, $sp, -16			# Creates a stack frame.
	sw $ra, 0($sp)				# Stores the return address to the stack.
	
	addi $t0, $zero	, 33			# ASCII code for an exclamation point.
	addi $t9, $zero	, 32			# ASCII code for a space.
	addi $t1, $zero, -1			# Initializes an index for guessFormatterLoop.
	
	sll $t7, $a0, 4				# Multiplies $a0 by 16 to find the offset for guessList.
	addi $t6, $t7, -18			# -18 = (-3 + 1(newline) + $a0(index))
	
	la $t8, guessList			# Loads in the address of guessList and computes the offset.
	add $t8, $t8, $t6
	addi $t8, $t8, 2
	li $t7, 10				# ASCII code for a newline.
	sb $t7, 0($t8)				# Stores a newline to the offset so that our guesses format nicely.
	
	guessFormatterLoop:
	addi $t1, $t1, 1			# Increments the guessFormatterLoop index by 1.
	addi $t6, $t6, 3			# Increments the guessList offset by 3. Each letter uses three charactesr
						# in guessList.
	
	beq $t1, $s2, guessFormatterLoopFinal	# Checks if we have checked every letter ($s2 = 5).
	
	la $t7, guessList	
	add $t4, $t7, $t6			# Adds guessList's offset to its address.
	
	la $t7, guessBuffer	
	add $t3, $t7, $t1			# Adds the guessFormatterLoop index to the guessBuffer address.
	lb $t5, 0($t3)				# Loads in the letter at that address.
	sb $t5, 0($t4)				# Stores that letter to the guessList string.
	
	la $t7, hintArray	
	add $t7, $t7, $t1			# Adds the guessFormatterLoop index to the hintArray address.
	lb $t8, 0($t7)				# Loads in the value of hintArray at guessFormatterLoop's index.
	sb $t8, 1($t4)				# Stores that value to the guessList string.
	sb $t9, 2($t4)				# Stores a space to the guessList string.
	j guessFormatterLoop
	
	guessFormatterLoopFinal:	
	lw $ra, 0($sp)				# Retrieves the return address
	addi $sp, $sp, 16			# Removes a stack frame		
	jr $ra


letterCheck:					# Checks if a letter is in the keyword. Uses two arrays, hintArray
						# and checkArray, to see if a letter has already been discovered to 
						# to prevent double accounting for it. hintArray stores the hint 
						# found for the letter submitted in $a0.
						# $a0 is the letter being checked for in the keyword.
						# $a1 is the index of that letter.
	addi $sp, $sp, -16			# Creates a stack frame
	sw $ra, 0($sp)				# Stores the return address

	addi $t0, $zero, -1			# Initializes an index for letterCheckLoop.
	letterCheckLoop:
	addi $t0, $t0, 1			# Increments the index by 1.
	beq $t0, $s2 letterCheckFinal		# Branches if we have checked all letters ($s2 is 5).
	
	add $t1, $s1, $zero			# Loads in the keyword address at $s1.
	add $t1, $t1, $t0			# Adds the loop's index to the keyword's address to compute the offset.
	lb $t1, 0($t1)				# Loads in the letter of the keyword at that offset.
	beq $t1, $a0, letterCheckFound		# Branches if the loaded keyword letter matches $a0.
	j letterCheckLoop			# Loops if the loaded keyword letter does not match.
	
	letterCheckFound:			# Performs a series of checks to ensure this letter
						# has not been accounted for. If it has not been accounted for,
						# an asterisk is stored to hintArray and checkArray.
						
	# CHECK 1
	la $t1, checkArray			# Loads in the value at letterCheckLoop's index of checkArray.
	add $t1, $t1, $t0		
	lb $t1, 0($t1)
	li $t2, 42				
	beq $t1, $t2, letterCheckLoop		# Checks if that value is an asterisk. If it is, we have already
						# accounted for this letter and we disregard it by branching back
						# to the loop.
	
	# CHECK 2
	la $t1, hintArray			# Loads in the value at letterCheckLoop's index of hintArray.
	add $t1, $t1, $t0
	lb $t1, 0($t1)
	li $t2, 33				
	beq $t1, $t2, letterCheckLoop		# Checks if that value is an exclamation point. If it is, we have 
						# already accounted for this letter and we disregard it by branching 
						# back to the loop.
	
	# CHECK 3
	la $t1, hintArray			# Loads in the value of hintArray at offset $a1. 
	add $t1, $t1, $a1
	lb $t1, 0($t1)
	li $t2, 33				
	beq $t1, $t2, letterCheckLoop		# Checks if that value is an exclamation point. If it is, we have 
						# already accounted for this letter and we disregard it by branching 
						# back to the loop.
	
						# If we have reached this point, all checks were passed, and we have
						# found a new matching letter.
	la $t1, checkArray			# Stores an asterisk to checkArray at letterCheckLoop's index.
	add $t1, $t1, $t0	
	li $t2, 42
	sb $t2, 0($t1)
	
	la $t1, hintArray			# Stores an asterisk to hintArray at offset $a1.
	add $t1, $t1, $a1
	sb $t2, 0($t1)

	letterCheckFinal:
	lw $ra, 0($sp)				# Loads the return address from the stack.
	addi $sp, $sp, 16			# Deletes the stack frame.
	jr $ra


checkGuess:					# Checks the guess in the guess buffer.
	addi $sp, $sp, -16			# Creates a stack frame.
	sw $ra, 0($sp)				# Stores the return address.
	
	la $a0, hintArray			# Clears hintArray and checkArray. We will use these with letterCheck.
	jal clearArray
	la $a0, checkArray
	jal clearArray			
	
	jal letterInSpotFinder			# Finds where letters in the keyword match with the letters in the guess.
	
	li $t0, 0				# Initializes an index for checkGuessLoop.
	
	checkGuessLoop:				# Iterates through each letter of the guess and checks them against 
						# every letter of the keyword for matches.
					
	beq $t0, $s2, endCheckGuessLoop	# Branches if we have checked every letter ($s2 is 5).
	la $t1, guessBuffer 			# Loads the address of guessBuffer.
	add $t2, $t1, $t0			# Adds the loop's index to guessBuffer's address to compute the offset.
	
	lb $a0, 0($t2)				# Loads the letter at that offset into the 0th argument.
	add $a1, $zero, $t0			# Loads index of that letter into the 1st argument.
	sw $t0, 4($sp)				# Stores our index to the stack.
	jal letterCheck				# Calls a procedure that compares the letter to each letter in the keyword.
	lw $t0, 4($sp)				# Loads the index from the stack.
	addi $t0, $t0, 1			# Increments the index by 1.
	j checkGuessLoop
	
	endCheckGuessLoop:
	lw $ra, 0($sp)				# Loads the return address from the stack
	addi $sp, $sp, 16			# Deletes the stack frame
	jr $ra








