/// <summary> /// Tests whether the direction entity wants to move in is free and if so, /// sests its direction and sets variable for saving direction to default value. /// </summary> /// <param name="newDirection">Variable with stored target direction (set to default in case of success).</param> /// <param name="entity">The observed entity.</param> private void SetToMove (ref Direction.nType newDirection, ref Tuple <int, int, PictureBox, Direction.nType, DefaultAI> entity) { // Direction dir = new Direction(); Tuple <int, int> delta = dir.DirectionToTuple(newDirection); if (IsDirectionFree(delta.Item1, delta.Item2, entity)) { entity = new Tuple <int, int, PictureBox, Direction.nType, DefaultAI> (entity.Item1, entity.Item2, entity.Item3, newDirection, entity.Item5); newDirection = Direction.nType.DIRECTION; } }
/// <summary> /// Checks whether the direction player intends to move in is free and nulls assosiated timer /// in such case, continues in countdown otherwise. /// </summary> /// <param name="direction">Direction player intends to move in.</param> /// <param name="keyCountdown">Number of tries left.</param> private void KeyCountAndDir(ref Direction.nType direction, ref int keyCountdown) { if (direction == Direction.nType.DIRECTION && keyCountdown != 0) { keyCountdown = 0; } else if (direction != Direction.nType.DIRECTION && keyCountdown > 1) { keyCountdown--; } else if (direction != Direction.nType.DIRECTION && keyCountdown == 1) { direction = Direction.nType.DIRECTION; keyCountdown = 0; } }
/// <summary> /// Function that chooses entity's next position based on set AI algorithms and entity's current state. /// </summary> /// <param name="position">The entity's position.</param> /// <param name="target">Target tile.</param> /// <param name="direction">The entity's curent direction.</param> /// <returns>Returns chosen direction for the entity.</returns> public Direction.nType NextStep (Tuple <int, int> position, Tuple <int, int> target, Direction.nType direction, Tile[][] map) { //Calls function to return AI's next direction if (State == nType.HOSTILERETREAT) { return(HostileRetreat(position, target, direction, map)); } else if (State == nType.EATEN) { return(Eaten(position, target, direction, map)); } else if (State == nType.CANBEEATEN) { return(CanBeEaten(position, target, direction, map)); } else { return(HostileAttack(position, target, direction, map)); } }
/// <summary> /// AI Algorithm choosing next position for hostille entities during their retreat phase. /// </summary> /// <param name="position">The entity's position.</param> /// <param name="target">Target tile (Usually some corner tile).</param> /// <param name="direction">The entity's curent direction.</param> /// <returns>Returns chosen direction for the entity.</returns> virtual public Direction.nType HostileRetreat(Tuple <int, int> position, Tuple <int, int> target, Direction.nType direction, Tile[][] map) { return(RandomAI(position, direction, map)); }
/// <summary> /// Random AI algorithm that decides new direction randomly at each crossroad. /// if there is no other way, AI chooses direction it came from or stops. /// </summary> /// <param name="position">The entity's position.</param> /// <param name="direction">The entity's curent direction.</param> /// <returns>Returns chosen direction for the entity.</returns> public Direction.nType RandomAI(Tuple <int, int> position, Direction.nType direction, Tile[][] map) { Random rnmd = new Random(); List <Tuple <int, int> > possibilities = new List <Tuple <int, int> >(); Direction dir = new Direction(); Tuple <int, int> back = dir.DirectionToTuple(direction); back = new Tuple <int, int>(back.Item1 * -1, back.Item2 * -1); for (int j = 0; j < 2; j++) { for (int i = -1; i < 2; i += 2) { int deltaX = (j == 0 ? i : 0); int deltaY = (j == 1 ? i : 0); if (position.Item1 + deltaY < 0) { if (direction == Direction.nType.LEFT) { possibilities.Add(new Tuple <int, int>(deltaX, deltaY)); } } else if (position.Item1 + deltaY >= fieldSizeInColumns) { if (direction == Direction.nType.RIGHT) { possibilities.Add(new Tuple <int, int>(deltaX, deltaY)); } } else if (position.Item2 + deltaX < 0) { if (direction == Direction.nType.UP) { possibilities.Add(new Tuple <int, int>(deltaX, deltaY)); } } else if (position.Item2 + deltaX >= fieldSizeInRows) { if (direction == Direction.nType.DOWN) { possibilities.Add(new Tuple <int, int>(deltaX, deltaY)); } } else if (CanAdd(map[position.Item2 + deltaX][position.Item1 + deltaY]) && (deltaX != back.Item1 || deltaY != back.Item2)) { possibilities.Add(new Tuple <int, int>(deltaX, deltaY)); } } } if (possibilities.Count() > 0) { return(dir.TupleToDirection(possibilities[rnmd.Next(possibilities.Count())])); } else if (direction != Direction.nType.DIRECTION) { return(dir.TupleToDirection(back)); } else { return(Direction.nType.DIRECTION); } }
/// <summary> /// AI Algorithm choosing next position for vulnerable entities. /// </summary> /// <param name="position">The entity's position.</param> /// <param name="target">Target tile.</param> /// <param name="direction">The entity's curent direction.</param> /// <returns>Returns chosen direction for the entity.</returns> virtual public Direction.nType CanBeEaten(Tuple <int, int> position, Tuple <int, int> target, Direction.nType direction, Tile[][] map) { return(RandomAI(position, direction, map)); }
/// <summary> /// Function handling key pressing during gameplay. /// </summary> /// <param name="e">Identifies pressed key.</param> private void GameKeyDownHandler(KeyEventArgs e) { //Two booleans keyPressed1 and 2 to notice which of the players during VS play has pushed the key if (Player2) { if (e.KeyCode == Keys.A || e.KeyCode == Keys.W || e.KeyCode == Keys.D || e.KeyCode == Keys.S) { keyPressed1 = true; } else { keyPressed2 = true; } } else { keyPressed1 = true; } //NewDirection1 and 2 to save desired direction of both players if (e.KeyCode == Keys.A || !Player2 && e.KeyCode == Keys.Left) { NewDirection1 = Direction.nType.LEFT; } else if (e.KeyCode == Keys.W || !Player2 && e.KeyCode == Keys.Up) { NewDirection1 = Direction.nType.UP; } else if (e.KeyCode == Keys.D || !Player2 && e.KeyCode == Keys.Right) { NewDirection1 = Direction.nType.RIGHT; } else if (e.KeyCode == Keys.S || !Player2 && e.KeyCode == Keys.Down) { NewDirection1 = Direction.nType.DOWN; } else if (Player2 && e.KeyCode == Keys.Left) { NewDirection2 = Direction.nType.LEFT; } else if (Player2 && e.KeyCode == Keys.Up) { NewDirection2 = Direction.nType.UP; } else if (Player2 && e.KeyCode == Keys.Right) { NewDirection2 = Direction.nType.RIGHT; } else if (Player2 && e.KeyCode == Keys.Down) { NewDirection2 = Direction.nType.DOWN; } else if (e.KeyCode == Keys.Escape) { EndGame(); } //In case the statment has reached this part the pushed key is invalid so disable the booleans else if (Player2) { keyPressed1 = false; keyPressed2 = false; } else { keyPressed1 = false; } }