Task

Write a program where the program chooses a number between   1   and   10.

A player is then prompted to enter a guess.   If the player guesses wrong,   then the prompt appears again until the guess is correct.

When the player has made a successful guess the computer will issue a   "Well guessed!"   message,   and the program exits.

A   conditional loop   may be used to repeat the guessing until the user is correct.



Related tasks

   Bulls and cows
   Bulls and cows/Player
   Guess the number/With Feedback
   Mastermind


(module
  (import "wasi_unstable" "fd_read" 
    (func $fd_read (param i32 i32 i32 i32) (result i32)))
  (import "wasi_unstable" "fd_write" 
    (func $fd_write (param i32 i32 i32 i32) (result i32)))
  (import "wasi_unstable" "random_get" 
    (func $random_get (param i32 i32) (result i32)))
 
  (memory 1) (export "memory" (memory 0))
  ;; memory usage:
  ;; 0-7: temp IO Vector used with WASI functions
  ;; 8-24: temp buffer used for reading numbers
  ;; 100-: string data
 
  ;; string constants
  (data (i32.const 100) "Guess a number between 1 and 10.\n")
  (data (i32.const 200) "Well guessed!\n")  
 
  ;; function to print a null-terminated string at the given address
  ;; (assumes use of an IOVector at address 0)
  (func $print_cstr (param $strAddr i32)
	(local $charPos i32)
 
	;; store the data address into our IO vector (address 0)
	i32.const 0  local.get $strAddr  i32.store
 
	;; find the null terminator at the end of the string
	local.get $strAddr  local.set $charPos
	block $loop_break 
	  loop $LOOP
		;; get the character at charPos
		local.get $charPos  i32.load
		;; if it is equal to zero, break out of the loop
		i32.eqz if br $loop_break end
		;; otherwise, increment and loop
		local.get $charPos  i32.const 1  i32.add  local.set $charPos
		br $LOOP
	  end
	end
 
	;; from that, compute the length of the string for our IOVector
	i32.const 4  ;; (address of string length in the IOVector)
	local.get $charPos  local.get $strAddr  i32.sub
	i32.store
 
	;; now call $fd_write to actually write to stdout
	i32.const 1  ;; 1 for stdout
	i32.const 0  i32.const 1   ;; 1 IOVector at address 0
	i32.const 0  ;; where to stuff the number of bytes written
	call $fd_write
	drop  ;; (drop the result value)
  )
 
  ;; function to read a number
  ;; (assumes use of an IOVector at address 0, 
  ;; and 16-character buffer at address 8)
  (func $input_i32 (result i32)
	(local $ptr i32)
	(local $n i32)
	(local $result i32)
 
	;; prepare our IOVector to point to the buffer
	i32.const 0  i32.const 8  i32.store    ;; (address of buffer)
	i32.const 4  i32.const 16  i32.store   ;; (size of buffer)
 
	i32.const 0  ;; 0 for stdin
	i32.const 0  i32.const 1  ;; 1 IOVector at address 0
	i32.const 4  ;; where to stuff the number of bytes read
	call $fd_read  drop
 
	;; Convert that to a number!
	;; loop over characters in the string until we hit something < '0'.
	i32.const 8  local.set $ptr
	block $LOOP_BREAK
	  loop $LOOP
		;; get value of current digit
		;; (we assume all positive integers for this task)
		local.get $ptr  i32.load8_u
		i32.const 48  i32.sub     ;; (subtract 48, ASCII value of '0')
		local.tee $n
 
		;; bail out if < 0
		i32.const 0  i32.lt_s  br_if $LOOP_BREAK
 
		;; multiply current number by 10, and add new number
		local.get $result  i32.const 10  i32.mul
		local.get $n  i32.add
		local.set $result
 
		;; increment and loop
		local.get $ptr  i32.const 1  i32.add  local.set $ptr
		br $LOOP
	  end
	end
 
	local.get $result
  )
 
  ;; function to get a random i32
  ;; (assumes use of temporary space at address 0)
  (func $random_i32 (result i32)
	i32.const 0  i32.const 4  call $random_get  drop
	i32.const 0  i32.load
  )
 
  (func $main (export "_start")
	(local $trueNumber i32)
 
	;; get a random integer, then take that (unsigned) mod 10
	call $random_i32  i32.const 10  i32.rem_u
	local.set $trueNumber
 
	loop $LOOP
	    ;; print prompt
	    i32.const 100  call $print_cstr
 
	    ;; input a guess
	    call $input_i32
 
	    ;; if correct, print message and we're done
	    local.get $trueNumber i32.eq  if
		i32.const 200  call $print_cstr
		return
	    end
	    br $LOOP
	end
  )
)