/** * Adds a leaf node (training constsruction) */ public void addLeaf(ActionNode child) { ActionNode current = this; while (current.children.Count != 0) { current = current.children[0]; } current.addChild(child); }
public CompanionController(PlayerController p) { // nch, should only be called by CharacterController.construct player = p; isLearning = false; learnedPlan = new ActionNode(ActionNode.EMPTY); currentGoal = null; currentGoalID = -1; walking = false; distance = 0; walk_dir = 0; walk_target = -1; interacting = false; invalids = new List<int>(); is_init = false; //last_walk_target = -1; ///debug //learnedPlan.addLeaf(new ActionNode(new Brew(Brew.COLOR_RED, 0))); }
/** * Adds a child node */ public void addChild(ActionNode child) { children.Add(child); child.parents.Add(this); }
/** * Merge a training session with this *@param training the training to merge */ public void merge(ActionNode training) { ActionNode current = this; List<int> visited = new List<int>(); // somehow... merge for (ActionNode i = training; i != null;) { ActionNode next = findNode(i, visited); if (next == null) // add i as child of current, update current to..??? { next = i.copy(); } bool hasChild = false; for (int j = 0; j < current.children.Count; j++) { if (next.equals(current.children[j])) { hasChild = true; break; } } if (!hasChild) { current.addChild(next); } current = next; // populate visited list (magically) List<ActionNode> ancestors = new List<ActionNode>(); ancestors.Add(current); for (int j = 0; j < ancestors.Count; j++) { if (!visited.Contains(ancestors[j].id)) { //Console.WriteLine("adding " + ancestors[j].id + " to visited"); visited.Add(ancestors[j].id); for (int k = 0; k < ancestors[j].parents.Count; k++) { //Console.WriteLine("adding " + ancestors[j].parents[k].id + " to ancestors"); ancestors.Add(ancestors[j].parents[k]); } } } if (i.children.Count != 0) { i = i.children[0]; } else { i = null; } } debugPrint(); }
/** * Finds a node that is yet to be visited and returns it *@param node the node to find *@param visited nodes that have already been visited *@return null if the node doesn't exist, or the node */ public ActionNode findNode(ActionNode node, List<int> visited) { List<ActionNode> next = new List<ActionNode>(); next.Add(this); for (int i = 0; i < next.Count; i++) { if (!visited.Contains(next[i].id) && node.equals(next[i])) { return next[i]; } for (int j = 0; j < next[i].children.Count; j++) { next.Add(next[i].children[j]); } } return null; }
/** * Finda a node and returns it *@param node the node to find *@return null if node doesn't exist, or the node */ public ActionNode findNode(ActionNode node) { List<ActionNode> next = new List<ActionNode>(); for (int j = 0; j < children.Count; j++) { next.Add(children[j]); } for (int i = 0; i < next.Count; i++) { if (node.equals(next[i])) { return next[i]; } for (int j = 0; j < next[i].children.Count; j++) { next.Add(next[i].children[j]); } } return null; }
/** * Checks if 2 nodes equal each other *@param node the node to compare with this *@return true if they are equal, otherwise false */ public bool equals(ActionNode node) { return(node.data.equals(data)); }
/// <summary> /// Factory method to create CharacterControllers /// </summary> /// <param name="ci">Information about character apperance and stats</param> /// <param name="startpos">Where in the Area the character should be placed</param> /// <param name="playerControlled">True if the character should be a PC, false if NPC</param> /// <returns>Constructed CharacterController</returns> public static CharacterController construct(CharacterInfo ci, Vector2 startpos, Constants.CharType typeOfChar, PlayerController p) { CharacterController cc; cc = new CharacterController(); cc.m_doodadIndex = 0; ColliderType type; if (typeOfChar == Constants.CharType.PLAYERCHAR) { cc = new PlayerController(); type = ColliderType.PC; cc.m_doodadIndex = Constants.PLAYER; cc.bouncer = null; cc.brew = new Brew(0, 0); currPlan = null;// new ActionNode(ActionNode.EMPTY); } else if (typeOfChar == Constants.CharType.NPCHAR) { type = ColliderType.NPC; cc.bouncer = null; cc.brew = null; } else { cc = new CompanionController(p); type = ColliderType.PC; cc.m_doodadIndex = Constants.COMPANION; cc.bouncer = null; cc.brew = new Brew(0, 0); } cc.m_position = startpos; cc.AnimationController = new AnimationController(ci.animationDataPath, ci.animationTexturePath); cc.AnimationController.ActionTriggered += new ActionTriggeredEventHandler(cc.handleAction); cc.AnimationController.Scale = ci.scale; Rectangle bounds = ci.collisionBox; bounds.Offset((int)cc.m_position.X, (int)cc.m_position.Y); cc.m_collider = new Collider(cc, bounds, type); cc.m_speed = ci.speed; //if(PCControllerInput. cc.m_previousAngle = (float)Math.PI / 2; cc.victim = -1; cc.social_game = null; cc.walking = false; cc.walk_target = -1; cc.walk_dir = -1; cc.distance = 0; return cc; }
public void clearPlan() { currPlan = null; //currPlan = new ActionNode(ActionNode.EMPTY); }
public void addTaskToPlan(PuzzleObject po) { if (currPlan == null) { currPlan = new ActionNode(po); } else { currPlan.addLeaf(new ActionNode(po)); } currPlan.debugPrint(); }
private bool executePlan() { if (!is_init) { width = (int)m_collider.Bounds.Width; height = (int)m_collider.Bounds.Height; boundsX = (int)m_collider.Bounds.X; boundsY = (int)m_collider.Bounds.Y; is_init = true; } if (Quest.talkedToCompanion) { //go to first node's location if (currentGoal == null) { // query the world to find out if there are any interactable objects List<PuzzleObject> objs = GameplayManager.ActiveArea.getPuzzleObjects((int)m_collider.Bounds.Center().X / Area.TILE_WIDTH, (int)m_collider.Bounds.Center().Y / Area.TILE_HEIGHT, (int)m_collider.Bounds.Width, (int)m_collider.Bounds.Height, brew); int priority = 0; // choose highest priority object to interact with for (int i = 0; i < objs.Count; i++) { if (!invalids.Contains(objs[i].id)) { int p = learnedPlan.findNodeDepth(objs[i]); if (p != -1 && (currentGoal == null || p < priority)) { currentGoal = learnedPlan.findNode(new ActionNode(objs[i])); currentGoalID = objs[i].id; priority = p; } } } if (currentGoal != null) { currentGoal.value++; //invalids.Clear(); invalids.Add(currentGoalID); Console.WriteLine("doing: " + currentGoal.id); interacting = true; walk_target = -1; } } if (currentGoal != null) { if (interacting) { if (!walking) { // check if adjacent to goal int x = (int)m_collider.Bounds.Center().X / Area.TILE_WIDTH; int y = (int)m_collider.Bounds.Center().Y / Area.TILE_HEIGHT; if (walk_target == -1) { walk_target = GameplayManager.ActiveArea.getObjectLocation(currentGoalID); Console.WriteLine("walk to: " + (walk_target) % Area.WIDTH_IN_TILES + "x" + (walk_target / Area.WIDTH_IN_TILES)); } int gx = walk_target % Area.WIDTH_IN_TILES; int gy = walk_target / Area.WIDTH_IN_TILES; if (x+y*Area.WIDTH_IN_TILES == walk_target)//(gx - x) * (gx - x) + (gy - y) * (gy - y) <= 1) { // adjacent // interact! GameplayManager.ActiveArea.interact(this, currentGoalID); interacting = false; walk_target = -1; } else { // need to walk to walk_dir = GameplayManager.ActiveArea.startPath(x + y * Area.WIDTH_IN_TILES, walk_target, currentGoal.getData().type, currentGoalID, width, height); //Console.WriteLine("path: " + walk_dir); if (walk_dir == -2) { // bad, but, at location GameplayManager.ActiveArea.interact(this, currentGoalID); interacting = false; walk_target = -1; } else if (walk_dir != -1) { walking = true; // reset to center of square //m_collider.m_bounds.X = x * Area.TILE_WIDTH + (Area.TILE_WIDTH - width) / 2; //m_collider.m_bounds.Y = y * Area.TILE_HEIGHT + (Area.TILE_HEIGHT - height) / 2; //Console.WriteLine(m_collider.m_bounds.X + "x" + m_collider.m_bounds.Y); //Console.WriteLine((x * Area.TILE_WIDTH + (Area.TILE_WIDTH - width) / 2) + "x" + (3+y * Area.TILE_HEIGHT + (Area.TILE_HEIGHT - height) / 2)); m_collider.handleMovement(new Vector2(-(float)m_collider.m_bounds.X + x * Area.TILE_WIDTH + (Area.TILE_WIDTH - width) / 2, 11 - (float)m_collider.m_bounds.Y + y * Area.TILE_HEIGHT + (Area.TILE_HEIGHT - height) / 2)); } else { // need to pick another action / can't reach this one Console.WriteLine(walk_target + " is impossible to reach"); currentGoal = null; return false; } } } else { // walk torwards this thingy int travel = m_speed; int size = walk_dir < WALK_UP ? Area.TILE_WIDTH : Area.TILE_HEIGHT; int reservation = size; if (distance + travel > size) { travel = (walk_dir < WALK_UP ? Area.TILE_WIDTH : Area.TILE_HEIGHT) - distance; distance = 0; walking = false; reservation = 0; boundsX = (int)m_collider.Bounds.X; boundsY = (int)m_collider.Bounds.Y; } else { distance += travel; reservation -= distance; } // reserve space /*switch (walk_dir) { case WALK_LEFT: if (reservation != 0) { m_collider.m_bounds.X = boundsX - Area.TILE_WIDTH - travel; } m_collider.m_bounds.Width = width + reservation; break; case WALK_RIGHT: m_collider.m_bounds.Width = width + reservation; break; case WALK_UP: if (reservation != 0) { m_collider.m_bounds.Y = boundsY - Area.TILE_HEIGHT - travel; } m_collider.m_bounds.Height = height + reservation; break; case WALK_DOWN: m_collider.m_bounds.Height = height + reservation; break; }*/ m_collider.handleMovement(new Vector2(walk_dir == WALK_LEFT ? -travel : walk_dir == WALK_RIGHT ? travel : 0, walk_dir == WALK_UP ? -travel : walk_dir == WALK_DOWN ? travel : 0)); AnimationController.requestAnimation(walk_dir == WALK_LEFT ? "left" : walk_dir == WALK_RIGHT ? "right" : walk_dir == WALK_UP ? "up" : "down", AnimationController.AnimationCommand.Play); AnimationController.update(); } } if (!interacting) { // find new goal ActionNode next = null; List<PuzzleObject> objs = GameplayManager.ActiveArea.getPuzzleObjects((int)m_collider.Bounds.Center().X / Area.TILE_WIDTH, (int)m_collider.Bounds.Center().Y / Area.TILE_HEIGHT, (int)m_collider.Bounds.Width, (int)m_collider.Bounds.Height, brew); int priority = 0; int nextID = -1; // choose highest priority object to interact with for (int i = 0; i < objs.Count; i++) { if (!invalids.Contains(objs[i].id)) { int p = currentGoal.findNodeDepth(objs[i]); if (p != -1 && (next == null || p < priority)) { next = currentGoal.findNode(new ActionNode(objs[i])); nextID = objs[i].id; priority = p; } } } /*int next_walk_target = -1; if (nextID != -1) { next_walk_target = GameplayManager.ActiveArea.getObjectLocation(nextID); }*/ if (next != null)// && last_walk_target != next_walk_target) { currentGoal = next; currentGoal.value++; Console.WriteLine("doing: " + currentGoal.id); currentGoalID = nextID; walk_target = -1; interacting = true; invalids.Add(currentGoalID); //last_walk_target = next_walk_target; } else { // check if this is another step series we can do /*for (int i = 0; i < objs.Count; i++) { int p = learnedPlan.findNodeDepth(objs[i], doneGoals); if (p != -1 && (next == null || p < priority)) { currentGoal = learnedPlan.findNode(new ActionNode(objs[i])); nextID = objs[i].id; priority = p; } } if (next != null) { currentGoal = next; Console.WriteLine("re-doing: " + currentGoal.id); doneGoals.Add(currentGoal.id); currentGoalID = nextID; walk_target = -1; interacting = true; }*/ currentGoal = null; currentGoalID = -1; } } } } return (currentGoal != null); }
/* public void toggleLearning() { isLearning = !isLearning; } */ public void learnNewInfo(ActionNode newInfo) { if (newInfo != null) { learnedPlan.merge(newInfo); } currentGoal = null; invalids.Clear(); walk_target = -1; }