• Labs icon Lab
  • Core Tech
Labs

Guided: Build a Text-Based Adventure Game in Rust

This hands-on lab is designed to help you practice your understanding of core Rust concepts. A series of guided steps will give you a walkthrough on how to apply your knowledge of these fundamental Rust concepts in a development setting. By the end of the lab, you will have demonstrated your ability to build a functioning multi-modular Rust application using these concepts.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 2h 14m
Published
Clock icon Jun 13, 2023

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    In this lab, you have been given a text-based adventure game application in Rust. However, the major components have not been fully completed. As such, it will be your responsibility to finish each of their implementations within this lab.

    The application can be run at any time by executing the cargo run command in the terminal or clicking the Run button in the terminal.

    Note: You may notice that when completing tasks for earlier modules(ie. modules 1 and 2) the test output may still output warnings. This is normal as these warnings are just referencing the later modules you have not yet completed and will gradually disappear as you progress.

  2. Challenge

    Step 1: Implementing the Player

    The first incomplete component is the Player. The Player module is located within player.rs, which has a Player struct already defined. There are also multiple spawning functions for each class, each with their own distinct values. The get_class_input() method is a predefined auxiliary function for reading your input when selecting a class.

    You will need to complete the Player module by implementing pick_class() for selecting your class at the start of the game, level_up() for strengthening your character on each level up, rest_health() for healing between dungeon rooms, and player_attack() to simulate combat.

    Instructions
    let player; 
    	
    if selected_class is warrior(value of 1)
    	set player to spawn_warrior()
    	print warrior class selection
    
    else if selected class is wizard(value of 2)
    	set player to spawn_wizard()
    	print wizard class selection
    else
    	set player to spawn_ranger()
    	print ranger class selection
    
    player.expect("No player class was selected.")
    
    Hint #1

    Use the Option enum in Rust with Some() when assigning the player variable. This is done using player = Some(input) which extracts the value of input and assigns it to the player if it exists, or None if it doesn't.

    Hint #2

    The functions to spawn a class are defined for you at the top of the Player module. Functions of a module can be called in Rust with the syntax Module::function(). For example, Player::spawn_warrior().

    Instructions
    let mut enough_xp = true;
    	
    while enough_xp is true
    	define req_exp for level up
    	
    	if self.exp >= req_exp
    		increment self.level
    		subract req_exp from self.exp
    	
    		increase player stat values based off self.class
    		print level up message
    	else
    		set enough_xp to false
    	
    
    Hint #1

    When increasing stat values, use a match statement. match works similar to switch statements from other languages . The default case of the match statement should be to do nothing in the format

    _  => {}
    
    Instructions
    if self.rests >= 1
    	calculate half_hp(self.max_health/2)
    	if self.current_health <= half_hp, self.current_health += half_hp
    	else self.current_health = self.max_health
    	decrement self.rests by 1
    	
    	print current health
    	print remaining rests
    else
     print no more rests message
    	
    
    Hint #1

    You can use a ternary statement when setting self.current_health.

    Instructions
    let mut base_dmg = rng.gen_range(self.min_damage to self.max_damage)
    let total_damage
    	
    check if attack is a critical hit, if it is then double base_dmg
    
    check if dmg_ismagic
    	if it is, set total_damage to base_damage - mob.resistance or 1 if the value is less than 1
    
    if dmg_ismagic is false
    	set total_damage to base_damage - mob.armor or 1 if the value is less than 1
    
    subtract total_damage from mob.current_health
    
    if attack is critical hit, print critical hit message. Else print normal damage message.
    
    Hint #1

    To calculate if an attack is a critical hit, use rng.gen_range() to generate a value between 1 and 100, inclusive. If this value is less than or equal to self.crit_chance, then the attack is a critical.

    After completing all the aforementioned tasks, the `Player` module is now complete. Now the player is able to successfully pick their class at the start of the app, level up when reaching the correct amount of exp to grow stronger, rest to recover health, and simulate an attack against enemies. Next, we will move on the to `Mob` module.
  3. Challenge

    Step 2: Implementing the Mobs

    The Mob module contains all the data regarding the monsters you will encounter in this game. It is very similar to the Player module as it has a Mob struct with multiple spawning functions for mobs with their own distinct values.

    The only function that you will need to complete is the mob_attack() function to simulate combat against the player.

    Instructions
    check if player dodge rolled successfully
    
    if player didnt dodge
    	calculate base damage similar to the previous task
    	let mut total_damage = 1 #Minimum damage a mob does to a player is 1
    	
    	if self.dmg_ismagic
    		calculate total damage as base damage - player.resistance or 1
    	else
    		calculate total damage as base damage - player.armor or 1
    	
    	subtract total damage from player.health
    	
    	print damage done to player
    
    else
    	print dodge message #no damage should have been done to player
    
    Hint #1

    Since total_damage should be initialized as one, it should only be changed if the calculated damage done to the player is >= 1.

    After completing the aforementioned task, the `Mob` module is complete. Now, both the `Player` and `Mob` can engage in combat by attacking each other.
  4. Challenge

    Step 3: Dungeon Generation

    Now we will need to populate the dungeon with the completed Mob creatures. It would be a good idea to familiarize yourself with all the mob spawning functions that were already predefined for you in the Mob module as they'll be used extensively here.

    Hint #1

    Since the functions to spawn the mobs are in the separate Mob module, you will need to spawn them with the Module::function() syntax. Since room_mobs is just a vector, you can simply push() the spawned mob into room_mobs.

  5. Challenge

    Step 4: Game State

    The last module to complete is the GameState which stores data on the current progression of the game. player_victory() and proceed_room() are the two functions that you will need to implement here.

    Instructions
    print statements
    
    add curr_mob.exp to player.exp
    call player.level_up() #use player parameter, not Player module
    increment mob_index #Dereference pointer
    set self to GameState::AwaitingInput #Dereference pointer
    
    Hint #1

    When working with variables that are references, you need to dereference them to directly modify the value they point to. This is done by prefixing a * to the variable name such as *example -=5

    Instructions
    increment room_number #Derefence pointer
    increment player.rests #No need to dereference
    set mob_index to 0 #Dereference pointer
    set self to GameState::AwaitingInput #Dereference pointer
    
    With these tasks completed, the app should be fully functional. Great job!

George is a Pluralsight Author working on content for Hands-On Experiences. He is experienced in the Python, JavaScript, Java, and most recently Rust domains.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.