Recorded Video Session: Text Adventure Game Part 2

Tutorial

·

Beginner

·

+0XP

·

90 mins

·

(280)

Unity Technologies

Recorded Video Session: Text Adventure Game Part 2

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this session we will see the finished project and introduce what we aim to learn in this series of sessions.

Languages available:

1. Introduction and Goals

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this session we will see the finished project and introduce what we aim to learn in this series of sessions.

Creating a Text Based Adventure Part 2 - Introduction and Goals [1/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

2. Project Architecture and Review

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will review what we did in the first half of our session and look at an overview of the architecture we will create in part two.

Creating a Text Based Adventure Part 2 - Project Architecture and Review [2/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

3. Displaying Item Descriptions

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will learn how to to display the descriptions of all the items in a room when we enter it.

Creating a Text Based Adventure Part 2 - Displaying Item Descriptions [3/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

4. Examining Items

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will add the ability for the player to examine items and see a second more detailed description of them.

Creating a Text Based Adventure Part 2 - Examining Items [4/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

5. Taking Items

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will add the ability for the player to take items and add them to their inventory.

Creating a Text Based Adventure Part 2 - Taking Items [5/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

6. Displaying Inventory

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will add the ability for the player to display the items they have taken into their inventory.

Creating a Text Based Adventure Part 2 - Displaying Inventory [6/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

7. Action Responses

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will add ActionResponses which we will use to execute functions when the player chooses the Use action with an item.

Creating a Text Based Adventure Part 2 - Action Responses [7/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

8. Preparing The Use Item Dictionary

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will add Action Responses to our system in order to create pluggable functions that will be executed when the player chooses to Use an item.

Creating a Text Based Adventure Part 2 - Preparing The Use Item Dictionary [8/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

9. Creating The Use Action

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will finish adding the capacity for players to change the state of the game based on using an item in the correct room using Action Responses by creating the 'Use' Input Action.

Creating a Text Based Adventure Part 2 - Creating The Use Action [9/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

10. Questions and Answers

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will finish the session by taking questions and answers.

Creating a Text Based Adventure Part 2 - Displaying Inventory [10/10] Live 2017/3/29

InteractableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);    
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> ();    
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction    interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

Complete this tutorial