// Process an item word
    private CommandOutcome ProcessItem(Command itemCommand)
    {
        // Select the command to use
        ItemWord command = (ItemWord)itemCommand;

        OldItem = command.AssociatedItem;

        // Get the other word entered, if any
        string[] otherWord       = parserState.GetOtherWordText();
        string   otherWordActive = otherWord != null ? otherWord[0].ToUpper() : null;

        // Check for use of certain item words as verbs
        if ((command.CommandID == "1021Water" || command.CommandID == "1022Oil") && (otherWordActive == "PLANT" || otherWordActive == "DOOR"))
        {
            // Player is trying to water/oil the plant/door, so construct a POUR command with this item as the subject and execute that instead
            CommandWord pourCommand    = new CommandWord("POUR", null);
            CommandWord newItemCommand = new CommandWord(parserState.Words[0], parserState.Words[1]);
            parserState.ResetParserState(new CommandWord[2] {
                pourCommand, newItemCommand
            });
            return(ProcessCommand());
        }
        else if (command.CommandID == "1004Cage" && otherWordActive == "BIRD" && playerController.ItemIsPresent("4Cage") && playerController.ItemIsPresent("8Bird"))
        {
            // Player is trying to cage the bird, so construct a CATCH command with the bird as the subject and execute that instead
            CommandWord catchCommand   = new CommandWord("CATCH", null);
            CommandWord newItemCommand = new CommandWord(otherWord[0], otherWord[1]);
            parserState.ResetParserState(new CommandWord[2] {
                catchCommand, newItemCommand
            });
            return(ProcessCommand());
        }

        // Get the matching item
        string item = command.AssociatedItem;

        bool continueProcessing = true;

        // Check if item is present
        if (!playerController.ItemIsPresent(item))
        {
            // Item is not present so check for special cases
            string loc = playerController.CurrentLocation; // Make short ref to current location
            continueProcessing = false;                    // Assume we won't continue processing

            switch (command.CommandID)
            {
            case "1003Grate":

                // If GRATE used on its own, treat it like a movement word, if in an appropriate location
                if (parserState.GetOtherWordText() == null)
                {
                    if (playerController.PlayerCanBeFoundAt(new List <string> {
                        "1Road", "4Valley", "7SlitInStreambed"
                    }))
                    {
                        parserState.SubstituteCommand("63Depression");
                        continueProcessing = true;
                    }
                    else if (playerController.PlayerCanBeFoundAt(new List <string> {
                        "10CobbleCrawl", "11DebrisRoom", "12AwkwardCanyon", "13BirdChamber", "14TopOfPit"
                    }))
                    {
                        parserState.SubstituteCommand("64Entrance");
                        continueProcessing = true;
                    }
                }

                break;

            case "1017Dwarf":

                // If dwarf has been referenced, check that there is actually a dwarf here
                if (dwarfController.FirstDwarfAt(loc) != -1)
                {
                    // There is, so process next command
                    parserState.Subject             = item;
                    parserState.CurrentCommandState = CommandState.SUBJECT_IDENTIFIED;
                    continueProcessing = true;
                }

                break;

            case "1021Water":
            case "1022Oil":
                // Check to see if the bottle is present with the correct liquid, or the correct liquid is present at this location
                //Item bottle = itemController.GetItemWithID("20Bottle");
                bool       bottleHere          = playerController.ItemIsPresent("20Bottle");
                int        requiredBottleState = command.CommandID == "1021Water" ? 0 : 2;
                LiquidType requiredLiquidType  = command.CommandID == "1021Water" ? LiquidType.WATER : LiquidType.OIL;

                if ((bottleHere && itemController.GetItemState("20Bottle") == requiredBottleState) || locationController.LiquidAtLocation(loc) == requiredLiquidType)
                {
                    // There is, so process next command
                    parserState.Subject             = item;
                    parserState.CurrentCommandState = CommandState.SUBJECT_IDENTIFIED;
                    continueProcessing = true;
                }
                else
                {
                    // Otherwise check to see if the player is trying to manipulate oil and the urn is here and contains oil
                    if (command.CommandID == "1022Oil" && itemController.ItemIsAt("42Urn", loc) && itemController.GetItemState("42Urn") != 0)
                    {
                        // If so, set the subject to be the urn and continue processing
                        parserState.Subject             = "42Urn";
                        parserState.CurrentCommandState = CommandState.SUBJECT_IDENTIFIED;
                        continueProcessing = true;
                    }
                }

                break;

            case "1024Plant":
                // Check if player is trying to manipulate the plant, but is actually at a location where the phony plant is present
                if (itemController.ItemIsAt("25PhonyPlant", loc) && itemController.GetItemState("25PhonyPlant") != 0)
                {
                    // If so, set the subject to be the phony plant and continue processing
                    parserState.Subject             = "25PhonyPlant";
                    parserState.CurrentCommandState = CommandState.SUBJECT_IDENTIFIED;
                    continueProcessing = true;
                }

                break;

            case "1005Rod":
                // If the player is trying to do something with the rod, check if they are at the phony rod location
                if (playerController.ItemIsPresent("6BlackRod"))
                {
                    // If so, set the subject to be the phony rod and continue processing
                    parserState.Subject             = "6BlackRod";
                    parserState.CurrentCommandState = CommandState.SUBJECT_IDENTIFIED;
                    continueProcessing = true;
                }
                break;
            }

            // If we have a verb and it's FIND or INVENT, then it's OK that the subject is not present
            if (!continueProcessing && (parserState.VerbIs("2019Find") || parserState.VerbIs("2020Inventory")))
            {
                parserState.Subject             = item;
                parserState.CurrentCommandState = CommandState.SUBJECT_IDENTIFIED;
                continueProcessing = true;
            }

            if (!continueProcessing)
            {
                // Mark this as discarded...
                parserState.CurrentCommandState = CommandState.DISCARDED;

                // ... but check if there's still more commands to be processed
                if (parserState.ContainsState(CommandState.NOT_PROCESSED))
                {
                    // ... if so, mark this as pending and process other command
                    parserState.CurrentCommandState = CommandState.PENDING;
                    continueProcessing = true;
                }
                else
                {
                    // Object not present and isn't a special case so let player know that object is not here
                    textDisplayController.AddTextToLog(playerMessageController.GetMessage("256ISeeNo", parserState.Words));
                    return(CommandOutcome.MESSAGE);
                }
            }
        }
        else
        {
            // Special case for knife
            if (item == "18Knife")
            {
                dwarfController.KnifeMessageShown();
                textDisplayController.AddTextToLog(playerMessageController.GetMessage("116KnivesVanish"));
                parserState.CommandComplete();
                return(CommandOutcome.MESSAGE);
            }

            // The item is here, so set it as the subject
            parserState.Subject             = item;
            parserState.CurrentCommandState = CommandState.SUBJECT_IDENTIFIED;
        }

        // Now check to see if we have a verb or an unprocessed command, or a carried over verb, and if so, go back to processing
        if (parserState.ContainsState(CommandState.VERB_IDENTIFIED) || parserState.ContainsState(CommandState.NOT_PROCESSED) || parserState.SetCarriedOverCommand(false))
        {
            return(ProcessCommand());
        }

        // If we get here, the player has just given us the name of the item, so ask them what they want to do with it
        parserState.CarryOverSubject();
        textDisplayController.AddTextToLog(playerMessageController.GetMessage("255WantToDo", parserState.Words));
        return(CommandOutcome.MESSAGE);
    }