예제 #1
0
        public override void Think()
        {
            // TODO: algorithm is not optimal because when returning from child to parent, child nodes will be listed again (not so big problem, but it something to improve)

            // timing
            double currentTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
            double mspa        = 1000 / aiSpeed;

            if (!IgnoreSpeed)
            {
                if ((currentTime - lastActionTime) < mspa)
                {
                    return;
                }
            }

            Map.Map map = Position.ParentMap;

            // if the stack is empty AI may be in dead end
            // put its current position to the stack and run the DFS again
            if (blockStack.Count == 0)
            {
                blockStack.Push(new VisitedBlock(Position));
            }

            // get current node and his neighbours
            VisitedBlock currVisitedBlock = blockStack.Peek();

            currVisitedBlock.state = BlockState.OPEN;
            visitedBlocks.Add(currVisitedBlock);
            MapBlock        curr       = map.Grid[currVisitedBlock.x, currVisitedBlock.y];
            List <MapBlock> neighbours = curr.AccessibleNeighbours();

            // choose the next neighbour to go to
            // those neighbours must not be in CLOSED state and should not contain monster
            MapBlock nextBlock = null;

            foreach (MapBlock neighbour in neighbours)
            {
                // check if the neighbour wasn't already visited and is not occupied
                // visited block hash code is calculated only by its coordinates so this can be used
                VisitedBlock neighbourVb = new VisitedBlock(neighbour);
                if (!visitedBlocks.Contains(neighbourVb) && !neighbour.Occupied)
                {
                    // get the last not-visited, unoccupied neighbour
                    // add it to the stack later
                    nextBlock = neighbour;
                }
            }


            // if some neighbours were found, create move action to the last block on the stack
            if (nextBlock != null)
            {
                blockStack.Push(new VisitedBlock(nextBlock));
                Direction nextDirection = DirectionMethods.GetDirection(Position, nextBlock);
                NextAction = new Move()
                {
                    Actor = this, Direction = nextDirection
                };
            }
            else
            {
                // no possible neighbours were found
                // this opens up two possibilities
                // 1. assume current block is a dead end
                // 2. check if there are monster to fight in neighbour blocks and try to fight them
                // for now lets just pick the first one

                // mark current block as closed and pop it from the stack
                currVisitedBlock.state = BlockState.CLOSED;
                blockStack.Pop();

                // move one step back
                if (blockStack.Count > 0)
                {
                    VisitedBlock prevBlock = blockStack.Peek();
                    nextBlock  = map.Grid[prevBlock.x, prevBlock.y];
                    NextAction = new Move()
                    {
                        Actor = this, Direction = DirectionMethods.GetDirection(Position, nextBlock)
                    };
                }
            }

            lastActionTime = currentTime;
        }