/// <summary>Checks against the guards for the command.</summary> /// <param name="actionInput">The full input specified for executing the command.</param> /// <returns>A string with the error message for the user upon guard failure, else null.</returns> public override string Guards(ActionInput actionInput) { IController sender = actionInput.Controller; string commonFailure = VerifyCommonGuards(actionInput, ActionGuards); if (commonFailure != null) { return(commonFailure); } int itemParam = 0; parent = sender.Thing.Parent; if (actionInput.Tail.ToLower().Contains("from")) { // Find the from keyword in the params. int itemMarker = 0; for (int i = 0; i < actionInput.Params.Length; i++) { if (actionInput.Params[i].ToLower() == "from") { itemMarker = i; } } // Destination container for (int j = itemParam; j < itemMarker; j++) { destinationContainerName += actionInput.Params[j] + ' '; } destinationContainerName = destinationContainerName.Trim(); // Source Container name is everything from the marker to the end. sourceContainerName = string.Empty; for (int i = itemMarker + 1; i < actionInput.Params.Length; i++) { sourceContainerName += actionInput.Params[i] + ' '; } sourceContainerName = sourceContainerName.Trim(); // Rule: Do we have an item matching the one specified in our inventory? // If not then does the room have a container with the name. // TODO: Fix: This Find pattern is probably broken... destinationContainer = sender.Thing.Children.Find(t => t.Name == destinationContainerName.ToLower()); if (destinationContainer == null) { destinationContainer = parent.Children.Find(t => t.Name == destinationContainerName.ToLower()); if (destinationContainer == null) { return("You cannot see " + destinationContainerName); } } // Rule: Is the item specified as a container actually a container? this.containerBehavior = destinationContainer.Behaviors.FindFirst <ContainerBehavior>(); if (this.containerBehavior == null) { return(destinationContainerName + " is not able to hold things."); } else { var holdsLiquidBehavior = destinationContainer.Behaviors.FindFirst <HoldsLiquidBehavior>(); if (holdsLiquidBehavior == null) { return(string.Format( "It does not appear that the {0} will hold liquid.", destinationContainerName)); } } // Rule: Is the item open? var openableBehavior = destinationContainer.Behaviors.FindFirst <OpensClosesBehavior>(); if (openableBehavior != null && !openableBehavior.IsOpen) { return(string.Format("You cannot fill the {0} as it is closed.", destinationContainerName)); } // Rule: Do we have an item matching the one specified in our inventory? // If not then does the room have a container with the name. // TODO: Investigate; This search method is probably broken. sourceContainer = sender.Thing.Children.Find(t => t.Name == sourceContainerName.ToLower()); if (sourceContainer == null) { sourceContainer = parent.Children.Find(t => t.Name == sourceContainerName.ToLower()); if (sourceContainer == null) { return("You cannot see " + sourceContainerName); } } // Rule: Is the item specified as a container actually a container? ContainerBehavior containerBehavior = sourceContainer.Behaviors.FindFirst <ContainerBehavior>(); if (containerBehavior == null) { return(string.Format("The {0} does not hold anything to fill the {1} with.", sourceContainerName, destinationContainerName)); } // TODO: HoldsLiquidBehavior? // Rule: Is the item open? OpensClosesBehavior opensClosesBehavior = sourceContainer.Behaviors.FindFirst <OpensClosesBehavior>(); if (!opensClosesBehavior.IsOpen) { return(string.Format("You cannot fill from the {0} as it is closed.", sourceContainerName)); } } else { return("You must use \"from\" to specify the source, as in, \"fill wine skin from fountain\"."); } return(null); }
/// <summary>Prepare for, and determine if the command's prerequisites have been met.</summary> /// <param name="actionInput">The full input specified for executing the command.</param> /// <returns>A string with the error message for the user upon guard failure, else null.</returns> public override string Guards(ActionInput actionInput) { IController sender = actionInput.Controller; string commonFailure = VerifyCommonGuards(actionInput, ActionGuards); if (commonFailure != null) { return(commonFailure); } // Check to see if the first word is a number. // @@@ Is TryParse meant to be used this way? Character analysis may be better. I worry that // this might be throwing a caught exception upon each fail, which is a typical case here. int.TryParse(actionInput.Params[0], out this.numberToGet); int itemParam = 0; string itemName = string.Empty; // Rule: If we have to get a number of something, shunt up the positions of our other params. if (this.numberToGet > 0) { itemParam = 1; } // Rule: is the player using the command to get something from a container // or to get something from the room? Thing targetParent = sender.Thing.Parent; if (actionInput.Tail.ToLower().Contains("from")) { // Find the from keyword in the params. int itemMarker = 0; for (int i = 0; i < actionInput.Params.Length; i++) { if (actionInput.Params[i].ToLower() == "from") { itemMarker = i; } } // Item name is everything from number (if present) to the from marker. for (int j = itemParam; j < itemMarker; j++) { itemName += actionInput.Params[j] + ' '; } itemName = itemName.Trim(); // Container name is everything from the marker to the end. string targetFromName = string.Empty; for (int i = itemMarker + 1; i < actionInput.Params.Length; i++) { targetFromName += actionInput.Params[i] + ' '; } targetFromName = targetFromName.Trim(); // Rule: Do we have an item matching the one specified in our inventory? // If not then does the room have a container with the name. Thing foundContainer = sender.Thing.FindChild(targetFromName.ToLower()); if (foundContainer == null) { foundContainer = targetParent.FindChild(targetFromName.ToLower()); if (foundContainer == null) { return(string.Format("You cannot see {0}.", targetFromName)); } } // Rule: Is the 'from' thing specified as a container actually a container? ContainerBehavior containerBehavior = foundContainer.Behaviors.FindFirst <ContainerBehavior>(); if (containerBehavior == null) { return(string.Format("{0} is not able to hold {1}.", foundContainer.Name, itemName)); } // @@@ Removed OpensClosesBehavior check here... Test to ensure that 'get' is blocked by the // OpensClosesBehavior receiving and cancelling the relevant events and message is good... targetParent = foundContainer; } else { // From the room. // Item name is everything from number (if present) to the from marker. for (int j = itemParam; j < actionInput.Params.Length; j++) { itemName += actionInput.Params[j] + ' '; } itemName = itemName.Trim(); } // Rule: Do we have an item matching in the container? this.thingToGet = targetParent.FindChild(itemName.ToLower()); if (this.thingToGet == null) { return(string.Format("{0} does not contain {1}.", targetParent.Name, itemName)); } // Rule: The targeted thing must be movable. this.movableBehavior = this.thingToGet.Behaviors.FindFirst <MovableBehavior>(); if (this.movableBehavior == null) { return(this.thingToGet.Name + " does not appear to be movable."); } // @@@ TODO: Rule: Is the thing allowed to be picked up? (CannotPickUpBehavior or needs CarryableBehavior or whatnot? hmm) return(null); }
public static (int X, int Y, Vector Direction) NextPosition(double milliseconds, Rectangle bounds, ContainerBehavior containerBehaviour, Vector direction, int x, int y) { x = (int)Math.Round((double)x + (milliseconds / 10) * direction.X); y = (int)Math.Round((double)y + (milliseconds / 10) * direction.Y); switch (containerBehaviour) { case ContainerBehavior.BOUNCE: if (x < 0 || x > bounds.X) { direction = new Vector(-direction.X, direction.Y); } if (y < 0 || y > bounds.Y) { direction = new Vector(direction.X, -direction.Y); } break; case ContainerBehavior.STICK: direction = new Vector(0, 0); break; case ContainerBehavior.WRAP: if (x < 0) { x = 1000; } if (y > bounds.X) { x = 0; } if (y < 0) { y = 1000; } if (y > bounds.Y) { y = 0; } break; } return(x, y, direction); }
/// <summary>Checks against the guards for the command.</summary> /// <param name="actionInput">The full input specified for executing the command.</param> /// <returns>A string with the error message for the user upon guard failure, else null.</returns> public override string Guards(ActionInput actionInput) { IController sender = actionInput.Controller; string commonFailure = VerifyCommonGuards(actionInput, ActionGuards); if (commonFailure != null) { return(commonFailure); } // Break out the specified parameters into their theoretical meaning. string sourceContainerName = actionInput.Params[0]; string destinationParentName = null; if (actionInput.Params.Length > 1) { // TODO: Maybe action input should have a means of automatically stripping words like this or "the" etc? if (actionInput.Params.Length > 2 && (actionInput.Params[1].Equals("into", StringComparison.CurrentCultureIgnoreCase) || actionInput.Params[1].Equals("onto", StringComparison.CurrentCultureIgnoreCase))) { destinationParentName = actionInput.Params[2]; } else { destinationParentName = actionInput.Params[1]; } } // Rule: The target must be an item in the command sender's inventory. Thing thing = sender.Thing.Children.Find(t => t.Name.Equals(sourceContainerName, StringComparison.CurrentCultureIgnoreCase)); if (thing == null) { return(string.Format("You do not hold {0}.", sourceContainerName)); } // Rule: The targeted thing must be a container of some sort. ContainerBehavior containerBehavior = thing.Behaviors.FindFirst <ContainerBehavior>(); if (containerBehavior == null) { return(string.Format("The {0} is not a container.", thing.Name)); } // Rule: The targeted container must not be empty already. sourceContainer = thing; if (sourceContainer.Children.Count == 0) { return(string.Format("The {0} is already empty.", sourceContainer.Name)); } // TODO: Test; Not possible? If so, default to the current container's parent instead of failing? Debug.Assert(!string.IsNullOrEmpty(destinationParentName)); if (destinationParentName.Equals("ground", StringComparison.CurrentCultureIgnoreCase) || destinationParentName.Equals("out", StringComparison.CurrentCultureIgnoreCase)) { // TODO: Test, this may be broken... destinationParent = sender.Thing.Parent; } else { // TODO: Allow targeting of containers in same place, like chests and whatnot? Thing destinationThing = sender.Thing.Children.Find(t => t.Name == destinationParentName.ToLower()); if (destinationThing == null) { return(string.Format("You do not hold {0}.", destinationParentName)); } containerBehavior = thing.Behaviors.FindFirst <ContainerBehavior>(); if (containerBehavior == null) { return(string.Format("{0} is not a container.", destinationParentName)); } destinationParent = thing.Parent; } return(null); }
/// <summary>Checks against the guards for the command.</summary> /// <param name="actionInput">The full input specified for executing the command.</param> /// <returns>A string with the error message for the user upon guard failure, else null.</returns> public override string Guards(ActionInput actionInput) { var commonFailure = VerifyCommonGuards(actionInput, ActionGuards); if (commonFailure != null) { return(commonFailure); } var itemParam = 0; parent = actionInput.Controller.Thing.Parent; if (actionInput.Tail.ToLower().Contains("from")) { // Find the from keyword in the params. var itemMarker = 0; for (var i = 0; i < actionInput.Params.Length; i++) { if (actionInput.Params[i].ToLower() == "from") { itemMarker = i; } } // Destination container for (var j = itemParam; j < itemMarker; j++) { destinationContainerName += actionInput.Params[j] + ' '; } destinationContainerName = destinationContainerName.Trim(); // Source Container name is everything from the marker to the end. sourceContainerName = string.Empty; for (var i = itemMarker + 1; i < actionInput.Params.Length; i++) { sourceContainerName += actionInput.Params[i] + ' '; } sourceContainerName = sourceContainerName.Trim(); // Rule: Do we have an item matching the one specified in our inventory? // If not then does the room have a container with the name. // TODO: Fix: This Find pattern is probably broken... destinationContainer = actionInput.Controller.Thing.Children.Find(t => t.Name == destinationContainerName.ToLower()); if (destinationContainer == null) { destinationContainer = parent.Children.Find(t => t.Name == destinationContainerName.ToLower()); if (destinationContainer == null) { return($"You cannot see {destinationContainerName}."); } } // Rule: Is the item specified as a container actually a container? this.containerBehavior = destinationContainer.Behaviors.FindFirst <ContainerBehavior>(); if (this.containerBehavior == null) { return($"{destinationContainerName} is not able to hold things."); } var holdsLiquidBehavior = destinationContainer.Behaviors.FindFirst <HoldsLiquidBehavior>(); if (holdsLiquidBehavior == null) { return($"It does not appear that the {destinationContainerName} will hold liquid."); } // Rule: Is the item open? var openableBehavior = destinationContainer.Behaviors.FindFirst <OpensClosesBehavior>(); if (openableBehavior is { IsOpen : false })