示例#1
0
        private static void PartOne()
        {
            var gridSize    = 347991;
            var grid        = new Dictionary <string, int>();
            var moveOutcome = new MoveOutcome
            {
                X         = 0,
                Y         = 0,
                Direction = Move.First
            };

            for (int i = 1; i <= gridSize; i++)
            {
                moveOutcome = GetNextCoordinates(moveOutcome, grid);
                grid.Add(GetCoordinate(moveOutcome.X, moveOutcome.Y), i);
            }
            var locationOfTarget = grid.FirstOrDefault(v => v.Value == gridSize).Key;
            var locationOfStart  = grid.FirstOrDefault(v => v.Value == 1).Key;

            Console.WriteLine($"Location Of Target: {locationOfTarget}");
            Console.WriteLine($"Location Of Start: {locationOfStart}");
            var targetX     = int.Parse(locationOfTarget.Split(",")[0]);
            var targetY     = int.Parse(locationOfTarget.Split(",")[1]);
            var startX      = int.Parse(locationOfStart.Split(",")[0]);
            var startY      = int.Parse(locationOfStart.Split(",")[1]);
            var stepsAcross = Math.Abs(targetX - startX);
            var stepsUpDown = Math.Abs(targetY - startY);

            Console.WriteLine($"Steps Across: {stepsAcross}");
            Console.WriteLine($"Steps Up/Down: {stepsUpDown}");
            Console.WriteLine($"Total Steps: {(stepsAcross + stepsUpDown)}");
        }
    // Attempts to move player avatar to a new location and returns the outcome of the movement - potential location will be updated with the location the player avatar is trying to move to
    public CommandOutcome MovePlayer(MovementWord command)
    {
        // Start with potential location being the same as the current location
        PotentialLocation = CurrentLocation;

        // Keep track of where player avatar is moving from
        UpdateOldLocations();

        // See if the command is valid for movement from this location
        MoveOutcome outcome = locationController.TryMovement(command);

        string moveMsg;

        if (outcome.locationID != null && outcome.locationID != "")
        {
            // The command attempts to move player avatar to a new location
            PotentialLocation = outcome.locationID;
            return(CommandOutcome.FULL);
        }
        else if (outcome.messageID != null && outcome.messageID != "")
        {
            // The command triggers a message for the player instead of a movement
            moveMsg = outcome.messageID;
        }
        else
        {
            // The command doesn't do anything at this location, so show a default message for that command
            moveMsg = command.DefaultMessageID;
        }

        textDisplayController.AddTextToLog(playerMessageController.GetMessage(moveMsg));
        return(CommandOutcome.MESSAGE);
    }
示例#3
0
        private static MoveOutcome GetNextCoordinates(MoveOutcome lastMove, Dictionary <string, int> grid)
        {
            var currentX = lastMove.X;
            var currentY = lastMove.Y;

            switch (lastMove.Direction)
            {
            case Move.First:     //Special case for first move.
                return(new MoveOutcome
                {
                    Direction = Move.Right,
                });

            case Move.Right:
                while (true)
                {
                    return(new MoveOutcome
                    {
                        Direction = GetNextDirection(currentX + 1, currentY, lastMove.Direction, grid),
                        X = currentX + 1,
                        Y = currentY
                    });
                }

            case Move.Up:
                while (true)
                {
                    return(new MoveOutcome
                    {
                        Direction = GetNextDirection(currentX, currentY + 1, lastMove.Direction, grid),
                        X = currentX,
                        Y = currentY + 1
                    });
                }

            case Move.Left:
                while (true)
                {
                    return(new MoveOutcome
                    {
                        Direction = GetNextDirection(currentX - 1, currentY, lastMove.Direction, grid),
                        X = currentX - 1,
                        Y = currentY
                    });
                }

            case Move.Down:
                while (true)
                {
                    return(new MoveOutcome
                    {
                        Direction = GetNextDirection(currentX, currentY - 1, lastMove.Direction, grid),
                        X = currentX,
                        Y = currentY - 1
                    });
                }
            }
            throw new Exception("Invalid Input");
        }
    private MoveOutcome FreshOutcome()
    {
        MoveOutcome outcome = new MoveOutcome();

        outcome.locationID      = null;
        outcome.messageID       = null;
        outcome.failedCondition = false;
        return(outcome);
    }
    // Check to see if it is possible to move from this location using the given command and returns the outcome of the movement
    public MoveOutcome TryMovement(Command command, LocationController controller)
    {
        MoveOutcome outcome = new MoveOutcome();

        outcome.locationID = null;
        outcome.messageID  = null;

        // If travel is forced, set command to null, which will find the first option that is unconditional, or where the condition is met
        if (travelIsForced)
        {
            command = null;
        }

        bool failedCondition = false;

        // Find and return the first option matching the given command
        for (int i = 0; i < travelOptions.Length; i++)
        {
            outcome = travelOptions[i].TryMovement(command, controller);

            // Check if a computed location needs to be translated to final location
            if (!outcome.failedCondition && outcome.locationID != null && controller.IsComputedLocation(outcome.locationID))
            {
                outcome.locationID = controller.GetComputedLocation(outcome.locationID);

                // If the new location is null, it means we need to get the next location from the movement table
                if (outcome.locationID == null)
                {
                    outcome.failedCondition = true;
                }
            }

            if (outcome.failedCondition)
            {
                // The current option matched but failed a condition, so indicate we should match the next item with a condition that passes or which is unconditional
                command         = null;
                failedCondition = true;
            }
            else if (outcome.locationID != null || outcome.messageID != null)
            {
                failedCondition = false;
                break;
            }
        }

        // If we get here with failedCondition set then there's been an error as no unconditional alternative was found for one or more conditional entries
        if (failedCondition)
        {
            Debug.LogErrorFormat("Location \"{0}\" has at least one conditional travel option without an unconditional alternative", ShortDescription);
        }

        return(outcome);
    }
示例#6
0
        private static int GetSumOfNeighbours(MoveOutcome moveOutcome, Dictionary <string, int> grid)
        {
            //Check everything around (if there).
            var sum = 0;

            if (moveOutcome.X == 0 && moveOutcome.Y == 0)
            {
                //First move, return 1
                return(1);
            }
            if (grid.ContainsKey(GetCoordinate(moveOutcome.X + 1, moveOutcome.Y)))
            {
                sum += grid[GetCoordinate(moveOutcome.X + 1, moveOutcome.Y)];
            }
            if (grid.ContainsKey(GetCoordinate(moveOutcome.X + 1, moveOutcome.Y + 1)))
            {
                sum += grid[GetCoordinate(moveOutcome.X + 1, moveOutcome.Y + 1)];
            }
            if (grid.ContainsKey(GetCoordinate(moveOutcome.X, moveOutcome.Y + 1)))
            {
                sum += grid[GetCoordinate(moveOutcome.X, moveOutcome.Y + 1)];
            }
            if (grid.ContainsKey(GetCoordinate(moveOutcome.X - 1, moveOutcome.Y + 1)))
            {
                sum += grid[GetCoordinate(moveOutcome.X - 1, moveOutcome.Y + 1)];
            }
            if (grid.ContainsKey(GetCoordinate(moveOutcome.X - 1, moveOutcome.Y)))
            {
                sum += grid[GetCoordinate(moveOutcome.X - 1, moveOutcome.Y)];
            }
            if (grid.ContainsKey(GetCoordinate(moveOutcome.X - 1, moveOutcome.Y - 1)))
            {
                sum += grid[GetCoordinate(moveOutcome.X - 1, moveOutcome.Y - 1)];
            }
            if (grid.ContainsKey(GetCoordinate(moveOutcome.X, moveOutcome.Y - 1)))
            {
                sum += grid[GetCoordinate(moveOutcome.X, moveOutcome.Y - 1)];
            }
            if (grid.ContainsKey(GetCoordinate(moveOutcome.X + 1, moveOutcome.Y - 1)))
            {
                sum += grid[GetCoordinate(moveOutcome.X + 1, moveOutcome.Y - 1)];
            }
            return(sum);
        }
示例#7
0
        private int applyOutcome(CCharacter attacker, CCharacter target, MoveOutcome outcome, int damage)
        {
            switch (outcome)
            {
            case (MoveOutcome.Hit):
                break;

            case (MoveOutcome.Crit):
                damage += (int)attacker.Stats.GetStat(new CriticalDamage());
                break;

            case (MoveOutcome.Dodge):
                damage = 0;
                break;

            case (MoveOutcome.BlockCrit):
                damage += (int)(attacker.Stats.GetStat(new CriticalDamage()) * 1.15f);     //extra damage for critting through block
                break;

            case (MoveOutcome.Block):
                damage = 0;
                break;
            }

            var moveLog = new ExchangeProfile()
            {
                objectId    = attacker.ObjectId,
                outcome     = outcome,
                damage      = damage,
                totalDamage = fight.updateTotalDamage(attacker, damage)                     //bonus damage is accrued before potential overkill clamp
            };

            resultForClient.Add(moveLog.objectId, moveLog);

            //All time stats: damage++, crit++, critdamage++, hit++, dodge++, blockcrit++, block++
            attacker.Effects.OnDamageGiven(damage, attacker);

            //target.Effects.OnDamageReceived is called inside Stats.ApplyDamage
            return(target.Stats.ApplyDamage(damage, attacker)); //clamps to actual damage dealt on overkill then inflicts and returns its value
        }
示例#8
0
        private static void PartTwo()
        {
            var gridSize    = 347991;
            var grid        = new Dictionary <string, int>();
            var moveOutcome = new MoveOutcome
            {
                X         = 0,
                Y         = 0,
                Direction = Move.First
            };

            for (var i = 1; i <= gridSize; i++)
            {
                moveOutcome = GetNextCoordinates(moveOutcome, grid);
                var sum = GetSumOfNeighbours(moveOutcome, grid);
                if (sum > gridSize)
                {
                    Console.WriteLine(sum);
                    break;
                }
                grid.Add(GetCoordinate(moveOutcome.X, moveOutcome.Y), sum);
            }
        }
示例#9
0
        public int ProcessOutcome(SpellEnvironment env, MoveOutcome outcome)
        {
            const string METHODNAME = "ProcessOutcome";
            var          attacker   = env.Character;
            var          target     = env.Target;

            var attackerStats = attacker.Stats;
            var damage        = (int)attackerStats.GetStat(new Damage(), target); //calculates rng damage (minDmg <= dmg <= maxDmg) and applies target negation

            switch (outcome)
            {
            case (MoveOutcome.Hit):
                //HIT CHANCE VS TARGET'S DODGE CHANCE
                if (attackerStats.GetStat(new HitChance(), target) > RngUtil.hundredRoll())
                {
                    //CRIT CHANCE VS TARGET'S ANTI-CRIT CHANCE, if fails then HIT
                    damage = attackerStats.GetStat(
                        new CriticalHitChance(), target) > RngUtil.hundredRoll()    ? applyOutcome(attacker, target, MoveOutcome.Crit, damage)
                                                                                        : applyOutcome(attacker, target, MoveOutcome.Hit, damage);
                }
                else
                {
                    //IF HIT 'MISSES' ITS A DODGE
                    damage = applyOutcome(attacker, target, MoveOutcome.Dodge, damage);
                }
                break;

            case (MoveOutcome.Block):
                damage = applyOutcome(attacker, target,
                                      attacker.Stats.GetStat(new CriticalHitChance(), target) * 0.2f > RngUtil.hundredRoll()  ? MoveOutcome.BlockCrit
                                                                                                                : MoveOutcome.Block,
                                      damage);
                break;
            }

            return(damage);
        }
示例#10
0
        public void Run()
        {
            Console.WriteLine();

            while (true)
            {
                board.Print();
                Move        currentMove = GetUserInput();
                MoveOutcome result      = TryPerformMove(currentMove);

                switch (result)
                {
                case MoveOutcome.BlackWins:
                    Console.WriteLine("Black wins");
                    return;

                case MoveOutcome.WhiteWins:
                    Console.WriteLine("White wins");
                    return;

                case MoveOutcome.Illegal:
                    Console.Clear();
                    Console.WriteLine("This move is not legal");
                    break;

                case MoveOutcome.Success:
                    board.ChangeTurns();
                    Console.Clear();
                    Console.WriteLine();
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
        }
示例#11
0
    public MoveOutcome ExecuteMove(Move move)
    {
        MoveOutcome outcome  = MoveOutcome.OK;
        List <Cell> newCells = new List <Cell>();
        List <Cell> oldCells = new List <Cell>();

        //  Update history with activeCells
        List <Cell> historyStep = new List <Cell>(activeCells);

        history.Add(historyStep);

        // playerCameraControl = false;

        Cell.RootDirection direction = Cell.RootDirection.Up;

        switch (move)
        {
        case Move.UP: direction = Cell.RootDirection.Up; break;

        case Move.DOWN: direction = Cell.RootDirection.Down; break;

        case Move.RIGHT: direction = Cell.RootDirection.Right; break;

        case Move.LEFT: direction = Cell.RootDirection.Left; break;
        }

        activeCells.ForEach(cell =>
        {
            int newX = Mathf.RoundToInt(cell.transform.position.x); // TODO store X/Y in cell
            int newY = Mathf.RoundToInt(cell.transform.position.y); // TODO store X/Y in cell
            Cell.RootDirection previousPosition = Cell.RootDirection.Up;
            var cellDirection = direction;
            var cellMove      = move;

            if (cell.IsInverted)
            {
                switch (direction)
                {
                case Cell.RootDirection.Left: cellDirection = Cell.RootDirection.Right; break;

                case Cell.RootDirection.Right: cellDirection = Cell.RootDirection.Left; break;
                }

                switch (move)
                {
                case Move.LEFT: cellMove = Move.RIGHT; break;

                case Move.RIGHT: cellMove = Move.LEFT; break;
                }
            }

            if (cell.Status != Cell.RootStatus.WATER && cell.Status != Cell.RootStatus.POISON)
            {
                switch (cellMove)
                {
                case Move.UP: newY++; break;

                case Move.DOWN: newY--; break;

                case Move.RIGHT: newX++; break;

                case Move.LEFT: newX--; break;
                }
            }



            if (newY < cell.transform.position.y)
            {
                previousPosition = Cell.RootDirection.Up;
            }
            if (newY > cell.transform.position.y)
            {
                previousPosition = Cell.RootDirection.Down;
            }
            if (newX < cell.transform.position.x)
            {
                previousPosition = Cell.RootDirection.Right;
            }
            if (newX > cell.transform.position.x)
            {
                previousPosition = Cell.RootDirection.Left;
            }

            var cellOutcome = CheckCell(newX, newY);

            switch (cellOutcome)
            {
            case MoveOutcome.NONE:
                oldCells.Add(cell);
                AddFx(fxRock, new Vector3(cell.transform.position.x, cell.transform.position.y, -2));
                break;

            case MoveOutcome.DEATH:
                ProcessRoot(cells[newX, newY], cell, previousPosition, cellDirection);
                outcome = MoveOutcome.DEATH;
                soundLose.Play();
                cells[newX, newY].Fx = AddFx(fxDeath, new Vector3(newX, newY, -1), true);
                newCells.Add(cells[newX, newY]);
                cells[newX, newY].Status = Cell.RootStatus.POISON;
                break;

            case MoveOutcome.OK:
            case MoveOutcome.OK_INVERT:
                AddFx(fxEarth, new Vector3(newX, newY, -2));
                soundDig.Play();
                if (cellOutcome == MoveOutcome.OK_INVERT)
                {
                    soundInvert.Play();
                }
                if (cellOutcome == MoveOutcome.OK_INVERT)
                {
                    cells[newX, newY].IsInverted = !cell.IsInverted;
                }
                else
                {
                    cells[newX, newY].IsInverted = cell.IsInverted;
                }
                newCells.Add(cells[newX, newY]);
                ProcessRoot(cells[newX, newY], cell, previousPosition, cellDirection);
                break;

            case MoveOutcome.WATER:
                ProcessRoot(cells[newX, newY], cell, previousPosition, cellDirection);
                cells[newX, newY].Fx = AddFx(fxWater, new Vector3(newX, newY + 0.7f, -2), true);
                soundWater.Play();
                newCells.Add(cells[newX, newY]);
                cells[newX, newY].Status = Cell.RootStatus.WATER;
                waterCount--;
                break;
            }
        });

        activeCells = oldCells;
        newCells.ForEach(cell => activeCells.Add(cell));

        if (outcome == MoveOutcome.DEATH)
        {
            // StartCoroutine(LoseSequence());
            isDead = true;
            return(MoveOutcome.DEATH);
        }



        // ProcessRoot(newCells, direction);

        if (waterCount <= 0)
        {
            StartCoroutine(WinSequence());
            gameOver = true;
            return(MoveOutcome.WIN);
        }

        return(outcome);
    }
    }                                                             // We need to query the options destination when calculating possible routes

    // Check to see if the given command is valid for this movement option and return null if it isn't or a move outcome with Location or MessageID if it is
    public MoveOutcome TryMovement(Command command, LocationController controller)
    {
        MoveOutcome outcome = FreshOutcome();

        // If commands are null or the given command is null, this is a forced movement entry, so just get the destination / message ID
        if (commands == null || command == null)
        {
            outcome.locationID = destination;
            outcome.messageID  = messageID;
        }
        else
        {
            // Otherwise, search for a the first entry that matches the given command
            for (int i = 0; i < commands.Length; i++)
            {
                if (command == commands[i])
                {
                    outcome.locationID = destination;
                    outcome.messageID  = messageID;
                    break;
                }
            }
        }

        // If a match was found, check for conditions
        if (outcome.locationID != null || outcome.messageID != null)
        {
            ItemController   itemController   = controller.IC;
            PlayerController playerController = controller.PC;

            bool conditionMet = false;
            switch (conditionType)
            {
            case ConditionType.NONE:
                conditionMet = true;
                break;

            case ConditionType.PROBABILITY:             // There's a % chance of the movement happening
                if (Random.Range(0, 100) + 1 <= percentage)
                {
                    conditionMet = true;
                }
                break;

            case ConditionType.PRESENT:                 // The required item must be in location or carried
                if (itemController.ItemsAt(playerController.CurrentLocation).Contains(requiredItem))
                {
                    conditionMet = true;
                    break;
                }
                goto case ConditionType.CARRYING;       // Note: falls through to CARRYING check if condition not met

            case ConditionType.CARRYING:                // The required item must be carried
                if (playerController.HasItem(requiredItem))
                {
                    conditionMet = true;
                }
                break;

            case ConditionType.ITEMSTATE:
                if (itemController.GetItemState(requiredItem) != forbiddenItemState)
                {
                    conditionMet = true;
                }
                break;

            default:
                Debug.LogErrorFormat("Unknown travel condition: {0}", conditionType);
                break;
            }

            // If the condition was not met, clear the outcome but indicate a condition was failed
            if (!conditionMet)
            {
                outcome = FreshOutcome();
                outcome.failedCondition = true;
            }
        }

        return(outcome);
    }