Example #1
0
        /// <summary>Runs the thread.</summary>
        private void run()
        {
            List<WorldEvent> evnts = new List<WorldEvent>();
            while (true)
            {
                evnts.Clear();
                Waiting = true;
                while (Waiting)
                {
                    if (Stop)
                        break;

                    if (SyncFinished)
                    {
                        lock (Events)
                        {
                            evnts.AddRange(Events);
                            Events.Clear();
                        }

                        lock (waiting)
                        {
                            lock (syncFinished)
                            {
                                waiting = false;
                                syncFinished = false;
                            }
                        }
                    }
                }

                if (Stop)
                    break;

                Grid.startNewUpdate(CurTime);

                #region Sync
                {
                    List<Node> newNodes = new List<Node>();
                    List<Segment> newSegs = new List<Segment>();
                    List<Node> updateNodes = new List<Node>();
                    List<List<Segment>> updateNodeSegs = new List<List<Segment>>();
                    SegmentSkel tempSeg = null;
                    NodeSkel tempNode = null;
                    foreach (WorldEvent evnt in evnts)
                    {
                        switch (evnt.WEvent)
                        {
                            // add segment
                            case WorldEvent.EventType.AddSeg:
                                if ((bool)evnt.Arguments[0]) // if owned by this player
                                {
                                    tempSeg = (Segment)evnt.Arguments[1];
                                    Segments.Add((Segment)tempSeg);
                                    newSegs.Add((Segment)tempSeg);
                                    Path.intersect(tempSeg.EndLoc[0], tempSeg.EndLoc[1], 1);
                                    tempSeg.Visible = true;
                                }
                                else
                                {
                                    tempSeg = new SegmentSkel();
                                    tempSeg.ID = (string)evnt.Arguments[1];
                                    tempSeg.EndLoc[0] = (VectorF)evnt.Arguments[2];
                                    tempSeg.State[0] = (SegmentSkel.SegState)evnt.Arguments[3];
                                    tempSeg.EndLoc[1] = (VectorF)evnt.Arguments[4];
                                    tempSeg.State[1] = (SegmentSkel.SegState)evnt.Arguments[5];
                                    lock (Owner.Fog) { tempSeg.Visible = Owner.Fog.isVisible(tempSeg); }
                                }

                                SegByID.Add(tempSeg.ID, tempSeg);
                                Grid.Line(tempSeg.EndLoc[0], tempSeg.EndLoc[1], tempSeg, gridAddSegment);
                                break;

                            // remove segment
                            case WorldEvent.EventType.RemSeg:
                                tempSeg = SegByID[(string)evnt.Arguments[0]];
                                if (tempSeg.Owner == Owner)
                                {
                                    Segments.Remove((Segment)tempSeg);
                                    Path.intersect(tempSeg.EndLoc[0], tempSeg.EndLoc[1], -1);
                                }
                                SegByID.Remove(tempSeg.ID);
                                Grid.Line(tempSeg.EndLoc[0], tempSeg.EndLoc[1], tempSeg, gridRemoveSegment);
                                break;

                            // change segment state
                            case WorldEvent.EventType.SegChangeState:
                                tempSeg = SegByID[(string)evnt.Arguments[0]];
                                Grid.Line(tempSeg.EndLoc[0], tempSeg.EndLoc[1], tempSeg, gridRemoveSegment);

                                if (tempSeg.Owner == Owner)
                                {
                                    Segment s = (Segment)tempSeg;
                                    FInt l0 = (FInt)evnt.Arguments[1];
                                    FInt l1 = (FInt)evnt.Arguments[3];

                                    bool reAdd = false;
                                    if (s.EndLength[0] != l0 || s.EndLength[1] != l1)
                                    {
                                        Path.intersect(s.EndLoc[0], s.EndLoc[1], -1);
                                        reAdd = true;
                                    }

                                    s.EndLength[0] = l0;
                                    s.State[0] = (SegmentSkel.SegState)evnt.Arguments[2];
                                    s.EndLength[1] = l1;
                                    s.State[1] = (SegmentSkel.SegState)evnt.Arguments[4];
                                    s.refreshEndLocs();

                                    if (reAdd)
                                        Path.intersect(s.EndLoc[0], s.EndLoc[1], 1);
                                }
                                else
                                {
                                    tempSeg.EndLoc[0] = (VectorF)evnt.Arguments[1];
                                    tempSeg.State[0] = (SegmentSkel.SegState)evnt.Arguments[2];
                                    tempSeg.EndLoc[1] = (VectorF)evnt.Arguments[3];
                                    tempSeg.State[1] = (SegmentSkel.SegState)evnt.Arguments[4];
                                    lock (Owner.Fog) { tempSeg.Visible = Owner.Fog.isVisible(tempSeg); }
                                }
                                Grid.Line(tempSeg.EndLoc[0], tempSeg.EndLoc[1], tempSeg, gridAddSegment);
                                break;

                            // add node
                            case WorldEvent.EventType.AddNode:
                                if ((bool)evnt.Arguments[0]) // if owned by this player
                                {
                                    tempNode = (Node)evnt.Arguments[1];
                                    tempNode.Visible = true;
                                    Nodes.Add((Node)tempNode);
                                    newNodes.Add((Node)tempNode);
                                }
                                else
                                {
                                    tempNode = new NodeSkel();
                                    tempNode.ID = (string)evnt.Arguments[1];
                                    tempNode.IsParent = (bool)evnt.Arguments[2];
                                    tempNode.Pos = (VectorF)evnt.Arguments[3];
                                    tempNode.Radius = (FInt)evnt.Arguments[4];
                                    lock (Owner.Fog) { tempNode.Visible = Owner.Fog.isVisible(tempNode); }
                                }

                                NodeByID.Add(tempNode.ID, tempNode);
                                Grid.Point(tempNode.Pos, tempNode, gridAddNode);

                                //if ((bool)evnt.Arguments[0] || tempNode.Active)
                                //	Path.intersect(tempNode.Pos, tempNode.Radius, 1);

                                if ((bool)evnt.Arguments[0] && tempNode.Active) // if owned by this player
                                    refreshVisibility(new VectorF(tempNode.X - tempNode.SightDistance, tempNode.Y - tempNode.SightDistance), new VectorF(tempNode.X + tempNode.SightDistance, tempNode.Y + tempNode.SightDistance));

                                break;

                            // change node state
                            case WorldEvent.EventType.NodeChangeState:
                                tempNode = NodeByID[(string)evnt.Arguments[0]];

                                if (tempNode.Owner == Owner) // if owned by this player
                                {
                                    Node realNode = (Node)tempNode;
                                    bool applyVisibility = !realNode.Active && (bool)evnt.Arguments[1];
                                    realNode.Active = (bool)evnt.Arguments[1];
                                    List<Segment> segs = (List<Segment>)evnt.Arguments[2];

                                    updateNodes.Add(realNode);
                                    updateNodeSegs.Add(segs);

                                    if (applyVisibility)
                                    {
                                        lock (Owner.Fog) { Owner.Fog.applyVisibility(realNode); }
                                        refreshVisibility(new VectorF(tempNode.X - tempNode.SightDistance, tempNode.Y - tempNode.SightDistance), new VectorF(tempNode.X + tempNode.SightDistance, tempNode.Y + tempNode.SightDistance));
                                    }
                                }
                                else
                                {
                                    /*if ((bool)evnt.Arguments[1] && !tempNode.Active)
                                        Path.intersect(tempNode.Pos, tempNode.Radius, 1);
                                    else if (!(bool)evnt.Arguments[1] && tempNode.Active)
                                        Path.intersect(tempNode.Pos, tempNode.Radius, -1);*/

                                    tempNode.Active = (bool)evnt.Arguments[1];
                                }
                                break;

                            // remove node
                            case WorldEvent.EventType.RemNode:
                                tempNode = NodeByID[(string)evnt.Arguments[0]];

                                // prepare to invalidate fog of war
                                VectorF upperLeft = VectorF.Zero;
                                VectorF lowerRight = VectorF.Zero;

                                if (tempNode.Active && tempNode.Owner == Owner)
                                {
                                    upperLeft = new VectorF(tempNode.X - tempNode.SightDistance, tempNode.Y - tempNode.SightDistance);
                                    lowerRight = new VectorF(tempNode.X + tempNode.SightDistance, tempNode.Y + tempNode.SightDistance);
                                }

                                if (tempNode.Owner == Owner)
                                    Nodes.Remove((Node)tempNode);
                                NodeByID.Remove(tempNode.ID);
                                Grid.Point(tempNode.Pos, tempNode, gridRemoveNode);

                                //if (tempNode.Owner == Owner || tempNode.Active)
                                //	Path.intersect(tempNode.Pos, tempNode.Radius, -1);

                                // invalidate fog of war
                                if (upperLeft != lowerRight)
                                {
                                    lock (Owner.Fog) { Owner.Fog.invalidate(upperLeft, lowerRight); }
                                    refreshVisibility(upperLeft, lowerRight);
                                }
                                break;
                            default:
                                throw new Exception("Unrecognized event: " + evnt.ToString());
                        }
                    }
                    evnts.Clear();

                    // link new nodes to their connected segments and parents
                    foreach (Node newNode in newNodes)
                    {
                        // segments
                        for (int i = 0; i < newNode.Segments.Length; i++)
                        {
                            if (newNode.Segments[i] != null)
                            {
                                SegmentSkel reassignSeg = null;
                                if (SegByID.TryGetValue(newNode.Segments[i].ID, out reassignSeg))
                                    newNode.Segments[i] = (Segment)reassignSeg;
            #if DEBUG
                                else
                                    throw new Exception("Segment id " + newNode.Segments[i].ID + " not found.");
            #endif
                            }
                        }

                        // parents
                        for (int i = 0; i < newNode.Parents.Count; i++)
                        {
                            NodeSkel reassignNode = null;
                            if (NodeByID.TryGetValue(newNode.Parents[i].ID, out reassignNode))
                                newNode.Parents[i] = (Node)reassignNode;
                        }
                    }

                    // link new segments to their connected nodes
                    foreach (Segment newSeg in newSegs)
                    {
                        for (int i = 0; i < 2; i++)
                        {
                            NodeSkel reassignNode = null;
                            if (NodeByID.TryGetValue(newSeg.Nodes[i].ID, out reassignNode))
                                newSeg.Nodes[i] = (Node)reassignNode;
                            else
                                newSeg.Nodes[i] = new Node(newSeg.Nodes[i]);
                        }
                    }

                    // link updated nodes to their connected segments
                    for (int i = 0; i < updateNodes.Count; i++)
                    {
                        Node node = updateNodes[i];
                        List<Segment> segs = updateNodeSegs[i];

                        updateNodes[i].NumSegments = 0;

                        for (int j = 0; j < segs.Count; j++)
                        {
                            if (segs[j] != null)
                                updateNodes[i].NumSegments++;

                            if (segs[j] == null && node.Segments[j] != null) // if removing a segment
                            {
                                node.Segments[j] = null;
                            }
                            else if (segs[j] != null && node.Segments[j] == null) // if adding a segment
                            {
                                node.Segments[j] = (Segment)SegByID[segs[j].ID];
                            }
                            else if (segs[j] != null && node.Segments[j] != null && segs[j].ID != node.Segments[j].ID) // if switching out a segment with another
                            {
                                node.Segments[j] = (Segment)SegByID[segs[j].ID];
                            }
                        }
                    }
                }
                #endregion Sync

                #region Update Destination

                if (destUpdateDue)
                {
                    // TODO: make this work

                    destUpdateDue = false;
                }

                #endregion Update Destination

                #region Decision-Making

                /*{ // Pattern AI
                Node top = null;
                Node bottom = null;
                Node right = null;
                Node left = null;

                foreach (Node n in Nodes)
                {
                    if (top == null || n.Pos.Y < top.Y)
                        top = n;

                    if (bottom == null || n.Pos.Y > bottom.Y)
                        bottom = n;

                    if (right == null || n.Pos.X > right.X)
                        right = n;

                    if (left == null || n.Pos.X < left.X)
                        left = n;
                }

                foreach (Node fromNode in Nodes)
                {
                    if (!fromNode.Active || fromNode.NumSegments > 1)
                        continue;

                    VectorF dest = VectorF.Zero;

                    if (fromNode.IsParent)
                    {
                        FInt x = (fromNode.Pos.X + fromNode.Segments[0].getOppNode(fromNode).Pos.X) / FInt.F2;
                        if (left == fromNode)
                            dest = new VectorF(x, fromNode.Pos.Y + (FInt)200);
                        else
                            dest = new VectorF(x, fromNode.Pos.Y - (FInt)200);
                    }
                    else
                    {
                        if (bottom == fromNode)
                            dest = new VectorF(right.Pos.X + (FInt)200, right.Pos.Y);
                        else if (top == fromNode)
                            dest = new VectorF(left.Pos.X - (FInt)200, left.Pos.Y);
                        else if (right == fromNode)
                            dest = new VectorF(top.Pos.X, top.Pos.Y - (FInt)200);
                        else // left
                            dest = new VectorF(bottom.Pos.X, bottom.Pos.Y + (FInt)200);
                    }

                    Actions.Add(new PlayerAction(Owner, PlayerAction.ActionType.BuildSeg, fromNode.ID, false, dest));
                }

                if (Actions.Count == 0)
                    for (int i = 0; i < 9999999; i++) { } // give the main loop a break
            }*/

                #endregion Decision-Making

                #region Decision-Making
                /*{ // Real thinking AI
                    Node bestNode = null;
                    PathNode bestPathNode = null;
                    FInt bestWorth = FInt.F0;
                    Node worstNode = null;
                    PathNode worstPathNode = null;
                    FInt worstWorth = FInt.F0;
                    bool stillBuilding = false;
                    FInt maxDist = (FInt)400;
                    foreach (Node fromNode in Nodes)
                    {
                        if (!fromNode.Active)
                            stillBuilding = true;

                        if (!fromNode.Active || fromNode.NumSegments == fromNode.Segments.Length)
                            continue;

                        VectorF fromPos = fromNode.Pos;

                        VectorF nSpacing = (VectorF)Path.NodeSpacing;
                        VectorF nde = new VectorF(fromPos.X - maxDist, fromPos.Y - maxDist) / nSpacing;
                        nde.X = (FInt)Math.Round((double)nde.X);
                        nde.Y = (FInt)Math.Round((double)nde.Y);
                        int left = Math.Max(0, (int)nde.X);
                        int top = Math.Max(0, (int)nde.Y);
                        nde = new VectorF(fromPos.X + maxDist, fromPos.Y + maxDist) / nSpacing;
                        nde.X = (FInt)Math.Round((double)nde.X);
                        nde.Y = (FInt)Math.Round((double)nde.Y);
                        int right = Math.Min(Path.NumCols - 1, (int)nde.X);
                        int bottom = Math.Min(Path.NumRows - 1, (int)nde.Y);
                        FInt[,] worth = new FInt[bottom - top + 1, right - left + 1];

                        nde = (Grid.Squares[0, 0].Nodes[0].Pos + Grid.Squares[0, 0].Nodes[1].Pos) / FInt.F2 / nSpacing;
                        nde.X = (FInt)Math.Round((double)nde.X);
                        nde.Y = (FInt)Math.Round((double)nde.Y);
                        VectorF toPos = (VectorF)Path.Grid[(int)nde.Y, (int)nde.X].Position;
                        FInt totDist = VectorF.Distance(fromPos, toPos);

                        for (int row = top; row <= bottom; row++)
                        {
                            for (int col = left; col <= right; col++)
                            {
                                PathNode pn = Path.Grid[row, col];
                                VectorF pnPos = (VectorF)pn.Position;

                                // distance from source node
                                FInt srcDist = VectorF.Distance(fromPos, pnPos);
                                FInt srcDistWorth = FInt.F0;

                                if (srcDist > maxDist || srcDist < (FInt)100)
                                    srcDistWorth = FInt.F1 / FInt.F2;
                                else
                                    srcDistWorth = FInt.F1;

                                // distance from destination node
                                FInt destDist = VectorF.Distance(toPos, pnPos);
                                FInt destDistWorth = FInt.F1 - (destDist / (maxDist * FInt.F2));

                                // collisions
                                List<NodeSkel> ignoreNode = new List<NodeSkel>(1) { fromNode };
                                List<SegmentSkel> ignoreSeg = new List<SegmentSkel>(fromNode.NumSegments);
                                foreach (Segment seg in fromNode.Segments)
                                {
                                    if (seg != null)
                                        ignoreSeg.Add(seg);
                                }

                                FInt collWorth = FInt.F0;
                                List<SegmentSkel> collSeg;
                                List<NodeSkel> collNode;
                                List<GeoSkel> collGeo;
                                if (Collision.segCollision(fromPos, pnPos, ignoreSeg, ignoreNode, out collSeg, out collNode, out collGeo, true, Owner))
                                {
                                    if (collGeo.Count > 0)
                                    {
                                        collWorth = FInt.F0;
                                    }
                                    else if (collNode.Count > 0)
                                    {
                                        collWorth = FInt.F0;
                                    }
                                    else
                                    {
                                        SegmentSkel closestSeg = null;
                                        VectorF closestInt = VectorF.Zero;
                                        FInt closestDist = FInt.F0;

                                        for (int i = 0; i < collSeg.Count; i++)
                                        {
                                            VectorF nextInt = Calc.LineIntersect(fromPos, pnPos, collSeg[i].EndLoc[0], collSeg[i].EndLoc[1]);

                                            if (collSeg[i].Owner == Owner)
                                            {
                                                VectorF end0 = (collSeg[i].State[1] == SegmentSkel.SegState.Retracting)
                                                    ? collSeg[i].EndLoc[0]
                                                    : ((Segment)collSeg[i]).Nodes[0].Pos;

                                                VectorF end1 = (collSeg[i].State[0] == SegmentSkel.SegState.Retracting)
                                                    ? collSeg[i].EndLoc[1]
                                                    : ((Segment)collSeg[i]).Nodes[1].Pos;

                                                nextInt = Calc.LineIntersect(fromPos, pnPos, end0, end1);
                                            }
                                            else
                                            {
                                                nextInt = Calc.LineIntersect(fromPos, pnPos, collSeg[i].EndLoc[0], collSeg[i].EndLoc[1]);
                                            }

                                            FInt nextDist = VectorF.Distance(fromPos, nextInt);

                                            if (closestSeg == null || nextDist < closestDist)
                                            {
                                                closestSeg = collSeg[i];
                                                closestInt = nextInt;
                                                closestDist = nextDist;
                                            }
                                        }

                                        if (closestSeg.Owner == Owner)
                                            collWorth = FInt.F0;
                                        else
                                            collWorth = FInt.F1;
                                    }
                                }
                                else
                                {
                                    NodeType nType = Owner.InWorld.getNodeType(srcDist);

                                    if (pnPos.X - nType.Radius < 0
                                        || pnPos.Y - nType.Radius < 0
                                        || pnPos.X + nType.Radius >= Owner.InWorld.Width
                                        || pnPos.Y + nType.Radius >= Owner.InWorld.Height
                                        || Collision.nodeCollision(pnPos, nType.Radius, new List<SegmentSkel>(0), new List<NodeSkel>(0), true, Owner)
                                        || Collision.nodeCollNodeSpacing(pnPos, nType.Radius, nType.Spacing, Owner, new List<NodeSkel>(0), true))
                                    {
                                        collWorth = FInt.F0;
                                    }
                                    else
                                        collWorth = FInt.F1 / FInt.F2;
                                }

                                // calculate worth
                                worth[row - top, col - left] = (collWorth * FInt.F5) + (srcDistWorth * FInt.F2) + destDistWorth;

                                if (worth[row - top, col - left] > bestWorth || (worth[row - top, col - left] == bestWorth && new Random().Next(2) == 1))
                                {
                                    bestNode = fromNode;
                                    bestPathNode = pn;
                                    bestWorth = worth[row - top, col - left];
                                }
                                else if (fromNode.NumSegments == 1 && worth[row - top, col - left] < worstWorth || (worth[row - top, col - left] == worstWorth && new Random().Next(2) == 1))
                                {
                                    worstNode = fromNode;
                                    worstPathNode = pn;
                                    worstWorth = worth[row - top, col - left];
                                }
                            }
                        }
                    }

                    PlayerAction action = null;

                    if (bestPathNode != null && bestNode != null && (!stillBuilding || bestWorth > (FInt)3.5)) // if worth isn't high enough, don't do anything
                        action = new PlayerAction(Owner, PlayerAction.ActionType.BuildSeg, bestNode.ID, false, (VectorF)bestPathNode.Position);
                    else if (worstPathNode != null && worstNode != null)
                        action = new PlayerAction(Owner, PlayerAction.ActionType.DestroyNode, worstNode.ID);

                    if (action != null)
                    {
                        lock (Actions)
                            Actions.Add(action);
                    }

                }*/
                #endregion Decision-Making

                #region Decision-Making
                if (false)
                {
                    VectorF nSpacing = (VectorF)Path.NodeSpacing;

                    VectorF dest = (Grid.Squares[0, 0].Nodes[0].Pos + Grid.Squares[0, 0].Nodes[1].Pos) / FInt.F2 / nSpacing;
                    PathNode destNode = Path.Grid[(int)dest.Y, (int)dest.X];
                    dest = (VectorF)destNode.Position;
                    Node uselessNode = null;
                    List<NodeDistPath> openNodes = new List<NodeDistPath>();

                    // collect list of nodes with an open branch
                    foreach (Node n in Nodes)
                    {
                        if (n.Active && n.NumSegments < n.Segments.Length)
                            openNodes.Add(new NodeDistPath(n, VectorF.Distance(n.Pos, dest), null));
                    }

                    //
                    // FIND CLOSEST NODE TO DESTINATION
                    //

                    // sort nodes by distance from destination
                    NodeDistPath swap;
                    for (int i = 1, j; i < openNodes.Count; i++)
                    {
                        for (j = i; j > 0 && openNodes[j] < openNodes[j - 1]; j--)
                        {
                            swap = openNodes[j];
                            openNodes[j] = openNodes[j - 1];
                            openNodes[j - 1] = swap;
                        }
                    }

                    // find the node with the shortest path to the destination
                    while (openNodes.Count > 0 && openNodes[0].Path == null)
                    {
                        // get a starting path node
                        PathNode srcNode = Path.Grid[(int)((double)openNodes[0].Node.Pos.Y / Path.NodeSpacing.Y), (int)((double)openNodes[0].Node.Pos.X / Path.NodeSpacing.X)];
                        while (srcNode.isOrphaned())
                        {
                            srcNode = Path.Nodes[srcNode.Index - Path.NumCols];
                        }

                        // get shortest path
                        openNodes[0].Path = Path.gridToList(Path.search(srcNode, destNode), srcNode, destNode);

                        // if path doesn't exist
                        if (openNodes[0].Path == null)
                        {
                            openNodes.RemoveAt(0);
                            continue;
                        }

                        double dist = 0d;
                        foreach (PathEdge edge in openNodes[0].Path)
                        {
                            dist += edge.Distance;
                        }
                        openNodes[0].Dist = (FInt)dist;

                        // update order in list
                        for (int i = 0; i < openNodes.Count - 1 && openNodes[i] > openNodes[i + 1]; i++)
                        {
                            swap = openNodes[i];
                            openNodes[i] = openNodes[i + 1];
                            openNodes[i + 1] = swap;
                        }
                    }

                    if (openNodes.Count > 0)
                    {

                        // find furthest reachable path node
                        FInt maxDist = (FInt)400; // TODO: get rid of magic number (400)
                        int magnetEdge = -1;
                        for (int i = openNodes[0].Path.Count - 1; i >= 0; i--)
                        {
                            if (VectorF.Distance(openNodes[0].Node.Pos, (VectorF)Path.Nodes[openNodes[0].Path[i].NodeDest].Position) < maxDist)
                            {
                                magnetEdge = i;
                                break;
                            }
                        }

                        // find furthest node with no collisions
                        List<NodeSkel> ignoreNode = new List<NodeSkel>(1) { openNodes[0].Node };
                        List<SegmentSkel> ignoreSeg = new List<SegmentSkel>(openNodes[0].Node.NumSegments);
                        foreach (Segment seg in openNodes[0].Node.Segments)
                        {
                            if (seg != null)
                                ignoreSeg.Add(seg);
                        }
                        List<SegmentSkel> collSeg;
                        List<NodeSkel> collNode;
                        List<GeoSkel> collGeo;
                        VectorF magnetPoint = VectorF.Zero;

                        for (int i = magnetEdge; i >= 0; i--)
                        {
                            bool collision = false;
                            if (Collision.segCollision(openNodes[0].Node.Pos, (VectorF)Path.Nodes[openNodes[0].Path[i].NodeDest].Position, ignoreSeg, ignoreNode, out collSeg, out collNode, out collGeo, true, Owner))
                            {
                                if (collNode.Count > 0 || collGeo.Count > 0)
                                {
                                    collision = true;
                                }
                                else
                                {
                                    foreach (SegmentSkel s in collSeg)
                                    {
                                        if (s.Owner == Owner)
                                        {
                                            collision = true;
                                            break;
                                        }
                                    }
                                }
                            }

                            if (!collision)
                            {
                                magnetPoint = (VectorF)Path.Nodes[openNodes[0].Path[i].NodeDest].Position;
                                break;
                            }
                        }

                        // find best path node towards destination

                        VectorF nde = new VectorF(openNodes[0].Node.X - maxDist, openNodes[0].Node.Y - maxDist) / nSpacing;
                        nde.X = (FInt)Math.Round((double)nde.X);
                        nde.Y = (FInt)Math.Round((double)nde.Y);
                        int left = Math.Max(0, (int)nde.X);
                        int top = Math.Max(0, (int)nde.Y);
                        nde = new VectorF(openNodes[0].Node.X + maxDist, openNodes[0].Node.Y + maxDist) / nSpacing;
                        nde.X = (FInt)Math.Round((double)nde.X);
                        nde.Y = (FInt)Math.Round((double)nde.Y);
                        int right = Math.Min(Path.NumCols - 1, (int)nde.X);
                        int bottom = Math.Min(Path.NumRows - 1, (int)nde.Y);

                        Node bestNode = null;
                        PathNode bestPNode = null;
                        FInt bestWorth = FInt.F0;
                        for (int row = top; row <= bottom; row++)
                        {
                            for (int col = left; col <= right; col++)
                            {
                                PathNode pn = Path.Grid[row, col];
                                VectorF pnPos = (VectorF)pn.Position;

                                FInt collWorth = FInt.F0;

                                if (Collision.segCollision(openNodes[0].Node.Pos, pnPos, ignoreSeg, ignoreNode, out collSeg, out collNode, out collGeo, true, Owner))
                                {
                                    if (collGeo.Count > 0 || collNode.Count > 0)
                                    {
                                        collWorth = FInt.FN1;
                                    }
                                    else
                                    {
                                        SegmentSkel closestSeg = null;
                                        VectorF closestInt = VectorF.Zero;
                                        FInt closestDist = FInt.F0;

                                        for (int i = 0; i < collSeg.Count; i++)
                                        {
                                            VectorF nextInt = Calc.LineIntersect(openNodes[0].Node.Pos, pnPos, collSeg[i].EndLoc[0], collSeg[i].EndLoc[1]);

                                            if (collSeg[i].Owner == Owner)
                                            {
                                                VectorF end0 = (collSeg[i].State[1] == SegmentSkel.SegState.Retracting)
                                                    ? collSeg[i].EndLoc[0]
                                                    : ((Segment)collSeg[i]).Nodes[0].Pos;

                                                VectorF end1 = (collSeg[i].State[0] == SegmentSkel.SegState.Retracting)
                                                    ? collSeg[i].EndLoc[1]
                                                    : ((Segment)collSeg[i]).Nodes[1].Pos;

                                                nextInt = Calc.LineIntersect(openNodes[0].Node.Pos, pnPos, end0, end1);
                                            }
                                            else
                                            {
                                                nextInt = Calc.LineIntersect(openNodes[0].Node.Pos, pnPos, collSeg[i].EndLoc[0], collSeg[i].EndLoc[1]);
                                            }

                                            FInt nextDist = VectorF.Distance(openNodes[0].Node.Pos, nextInt);

                                            if (closestSeg == null || nextDist < closestDist)
                                            {
                                                closestSeg = collSeg[i];
                                                closestInt = nextInt;
                                                closestDist = nextDist;
                                            }
                                        }

                                        if (closestSeg.Owner == Owner)
                                            collWorth = FInt.FN1;
                                        else
                                            collWorth = FInt.F1;
                                    }
                                }
                                else
                                {
                                    NodeType nType = Owner.InWorld.getNodeType(VectorF.Distance(openNodes[0].Node.Pos, pnPos));

                                    if (pnPos.X - nType.Radius < 0
                                        || pnPos.Y - nType.Radius < 0
                                        || pnPos.X + nType.Radius >= Owner.InWorld.Width
                                        || pnPos.Y + nType.Radius >= Owner.InWorld.Height
                                        || Collision.nodeCollision(pnPos, nType.Radius, new List<SegmentSkel>(0), new List<NodeSkel>(0), true, Owner)
                                        || Collision.nodeCollNodeSpacing(pnPos, nType.Radius, nType.Spacing, Owner, new List<NodeSkel>(0), true))
                                    {
                                        collWorth = FInt.FN1;
                                    }
                                }

                                if (collWorth != FInt.FN1)
                                {
                                    // distance from destination node
                                    FInt destDist = VectorF.Distance(magnetPoint, pnPos);
                                    FInt worth = maxDist - destDist + collWorth;

                                    if (bestPNode == null || worth > bestWorth || (worth == bestWorth && new Random().Next(2) == 1))
                                    {
                                        bestPNode = pn;
                                        bestWorth = worth;
                                    }
                                }
                            }
                        }

                        if (bestPNode != null)
                            bestNode = openNodes[0].Node;

                        //
                        // FIND MOST USELESS NODE
                        //

                        for (int i = openNodes.Count - 1; i >= 0; i--)
                        {
                            if (!openNodes[i].Node.IsParent && openNodes[i].Node.NumSegments == 1)
                            {
                                uselessNode = openNodes[i].Node;
                                break;
                            }
                        }

                        //
                        // FIND INTERSECTIONS
                        //

                        foreach (NodeDistPath fromNode in openNodes)
                        {
                            VectorF fromPos = fromNode.Node.Pos;

                            nde = new VectorF(fromPos.X - maxDist, fromPos.Y - maxDist) / nSpacing;
                            nde.X = (FInt)Math.Round((double)nde.X);
                            nde.Y = (FInt)Math.Round((double)nde.Y);
                            left = Math.Max(0, (int)nde.X);
                            top = Math.Max(0, (int)nde.Y);
                            nde = new VectorF(fromPos.X + maxDist, fromPos.Y + maxDist) / nSpacing;
                            nde.X = (FInt)Math.Round((double)nde.X);
                            nde.Y = (FInt)Math.Round((double)nde.Y);
                            right = Math.Min(Path.NumCols - 1, (int)nde.X);
                            bottom = Math.Min(Path.NumRows - 1, (int)nde.Y);

                            nde = (Grid.Squares[0, 0].Nodes[0].Pos + Grid.Squares[0, 0].Nodes[1].Pos) / FInt.F2 / nSpacing;
                            nde.X = (FInt)Math.Round((double)nde.X);
                            nde.Y = (FInt)Math.Round((double)nde.Y);

                            for (int row = top; row <= bottom; row++)
                            {
                                for (int col = left; col <= right; col++)
                                {
                                    PathNode pn = Path.Grid[row, col];
                                    VectorF pnPos = (VectorF)pn.Position;

                                    // distance from source node
                                    FInt srcDist = VectorF.Distance(fromPos, pnPos);

                                    // collisions
                                    ignoreNode = new List<NodeSkel>(1) { fromNode.Node };
                                    ignoreSeg = new List<SegmentSkel>(fromNode.Node.NumSegments);
                                    foreach (Segment seg in fromNode.Node.Segments)
                                    {
                                        if (seg != null)
                                            ignoreSeg.Add(seg);
                                    }

                                    FInt collWorth = FInt.F0;
                                    if (Collision.segCollision(fromPos, pnPos, ignoreSeg, ignoreNode, out collSeg, out collNode, out collGeo, true, Owner) && collGeo.Count == 0 && collNode.Count == 0)
                                    {
                                        SegmentSkel closestSeg = null;
                                        VectorF closestInt = VectorF.Zero;
                                        FInt closestDist = FInt.F0;

                                        for (int i = 0; i < collSeg.Count; i++)
                                        {
                                            VectorF nextInt = Calc.LineIntersect(fromPos, pnPos, collSeg[i].EndLoc[0], collSeg[i].EndLoc[1]);

                                            if (collSeg[i].Owner == Owner)
                                            {
                                                VectorF end0 = (collSeg[i].State[1] == SegmentSkel.SegState.Retracting)
                                                    ? collSeg[i].EndLoc[0]
                                                    : ((Segment)collSeg[i]).Nodes[0].Pos;

                                                VectorF end1 = (collSeg[i].State[0] == SegmentSkel.SegState.Retracting)
                                                    ? collSeg[i].EndLoc[1]
                                                    : ((Segment)collSeg[i]).Nodes[1].Pos;

                                                nextInt = Calc.LineIntersect(fromPos, pnPos, end0, end1);
                                            }
                                            else
                                            {
                                                nextInt = Calc.LineIntersect(fromPos, pnPos, collSeg[i].EndLoc[0], collSeg[i].EndLoc[1]);
                                            }

                                            FInt nextDist = VectorF.Distance(fromPos, nextInt);

                                            if (closestSeg == null || nextDist < closestDist)
                                            {
                                                closestSeg = collSeg[i];
                                                closestInt = nextInt;
                                                closestDist = nextDist;
                                            }
                                        }

                                        if (closestSeg.Owner == Owner)
                                            collWorth = FInt.F0;
                                        else
                                            collWorth = FInt.F1;

                                        // calculate worth

                                        FInt worth = collWorth * (maxDist - closestDist) * 2;

                                        if (bestPNode == null || worth > bestWorth || (worth == bestWorth && new Random().Next(2) == 1))
                                        {
                                            bestNode = fromNode.Node;
                                            bestPNode = pn;
                                            bestWorth = worth;
                                        }
                                    }
                                }
                            }
                        }

                        //
                        // MAKE DECISION
                        //

                        PlayerAction action = null;

                        if (bestPNode != null && bestNode != null && (bestWorth > (FInt)3.5)) // if worth isn't high enough, don't do anything
                            action = new PlayerAction(Owner, PlayerAction.ActionType.BuildSeg, bestNode.ID, false, (VectorF)bestPNode.Position);
                        else if (uselessNode != null)
                            action = new PlayerAction(Owner, PlayerAction.ActionType.DestroyNode, uselessNode.ID);

                        if (action != null)
                        {
                            lock (Actions)
                                Actions.Add(action);
                        }
                    }
                }

                #endregion Decision-Making

                #region Decision-Making

                if (false)
                {
                    // Real thinking AI
                    Node bestNode = null;
                    PathNode bestPathNode = null;
                    FInt bestWorth = FInt.F0;
                    Node worstNode = null;
                    PathNode worstPathNode = null;
                    FInt worstWorth = FInt.F0;
                    bool stillBuilding = false;
                    FInt maxDist = (FInt)400;
                    foreach (Node fromNode in Nodes)
                    {
                        if (!fromNode.Active)
                            stillBuilding = true;

                        if (!fromNode.Active || fromNode.NumSegments == fromNode.Segments.Length)
                            continue;

                        VectorF fromPos = fromNode.Pos;

                        VectorF nSpacing = (VectorF)Path.NodeSpacing;
                        VectorF nde = new VectorF(fromPos.X - maxDist, fromPos.Y - maxDist) / nSpacing;
                        nde.X = (FInt)Math.Round((double)nde.X);
                        nde.Y = (FInt)Math.Round((double)nde.Y);
                        int left = Math.Max(0, (int)nde.X);
                        int top = Math.Max(0, (int)nde.Y);
                        nde = new VectorF(fromPos.X + maxDist, fromPos.Y + maxDist) / nSpacing;
                        nde.X = (FInt)Math.Round((double)nde.X);
                        nde.Y = (FInt)Math.Round((double)nde.Y);
                        int right = Math.Min(Path.NumCols - 1, (int)nde.X);
                        int bottom = Math.Min(Path.NumRows - 1, (int)nde.Y);
                        FInt[,] worth = new FInt[bottom - top + 1, right - left + 1];

                        nde = (Grid.Squares[0, 0].Nodes[0].Pos + Grid.Squares[0, 0].Nodes[1].Pos) / FInt.F2 / nSpacing;
                        nde.X = (FInt)Math.Round((double)nde.X);
                        nde.Y = (FInt)Math.Round((double)nde.Y);
                        VectorF toPos = (VectorF)Path.Grid[(int)nde.Y, (int)nde.X].Position;
                        FInt totDist = VectorF.Distance(fromPos, toPos);

                        for (int row = top; row <= bottom; row++)
                        {
                            for (int col = left; col <= right; col++)
                            {
                                PathNode pn = Path.Grid[row, col];
                                VectorF pnPos = (VectorF)pn.Position;

                                // distance from source node
                                FInt srcDist = VectorF.Distance(fromPos, pnPos);
                                FInt srcDistWorth = FInt.F0;

                                if (srcDist > maxDist || srcDist < (FInt)100)
                                    srcDistWorth = FInt.F1 / FInt.F2;
                                else
                                    srcDistWorth = FInt.F1;

                                // distance from destination node
                                FInt destDist = VectorF.Distance(toPos, pnPos);
                                FInt destDistWorth = FInt.F1 - (destDist / (maxDist * FInt.F2));

                                // collisions
                                List<NodeSkel> ignoreNode = new List<NodeSkel>(1) { fromNode };
                                List<SegmentSkel> ignoreSeg = new List<SegmentSkel>(fromNode.NumSegments);
                                foreach (Segment seg in fromNode.Segments)
                                {
                                    if (seg != null)
                                        ignoreSeg.Add(seg);
                                }

                                FInt collWorth = FInt.F0;
                                List<SegmentSkel> collSeg;
                                List<NodeSkel> collNode;
                                List<GeoSkel> collGeo;
                                if (Collision.segCollision(fromPos, pnPos, ignoreSeg, ignoreNode, out collSeg, out collNode, out collGeo, true, Owner))
                                {
                                    if (collGeo.Count > 0 || collNode.Count > 0)
                                    {
                                        collWorth = FInt.F0;
                                    }
                                    else
                                    {
                                        SegmentSkel closestSeg = null;
                                        VectorF closestInt = VectorF.Zero;
                                        FInt closestDist = FInt.F0;

                                        for (int i = 0; i < collSeg.Count; i++)
                                        {
                                            VectorF nextInt = Calc.LineIntersect(fromPos, pnPos, collSeg[i].EndLoc[0], collSeg[i].EndLoc[1]);

                                            if (collSeg[i].Owner == Owner)
                                            {
                                                VectorF end0 = (collSeg[i].State[1] == SegmentSkel.SegState.Retracting)
                                                    ? collSeg[i].EndLoc[0]
                                                    : ((Segment)collSeg[i]).Nodes[0].Pos;

                                                VectorF end1 = (collSeg[i].State[0] == SegmentSkel.SegState.Retracting)
                                                    ? collSeg[i].EndLoc[1]
                                                    : ((Segment)collSeg[i]).Nodes[1].Pos;

                                                nextInt = Calc.LineIntersect(fromPos, pnPos, end0, end1);
                                            }
                                            else
                                            {
                                                nextInt = Calc.LineIntersect(fromPos, pnPos, collSeg[i].EndLoc[0], collSeg[i].EndLoc[1]);
                                            }

                                            FInt nextDist = VectorF.Distance(fromPos, nextInt);

                                            if (closestSeg == null || nextDist < closestDist)
                                            {
                                                closestSeg = collSeg[i];
                                                closestInt = nextInt;
                                                closestDist = nextDist;
                                            }
                                        }

                                        if (closestSeg.Owner == Owner)
                                            collWorth = FInt.F0;
                                        else
                                            collWorth = FInt.F1;
                                    }
                                }
                                else
                                {
                                    NodeType nType = Owner.InWorld.getNodeType(srcDist);

                                    if (pnPos.X - nType.Radius < 0
                                        || pnPos.Y - nType.Radius < 0
                                        || pnPos.X + nType.Radius >= Owner.InWorld.Width
                                        || pnPos.Y + nType.Radius >= Owner.InWorld.Height
                                        || Collision.nodeCollision(pnPos, nType.Radius, new List<SegmentSkel>(0), new List<NodeSkel>(0), true, Owner)
                                        || Collision.nodeCollNodeSpacing(pnPos, nType.Radius, nType.Spacing, Owner, new List<NodeSkel>(0), true))
                                    {
                                        collWorth = FInt.F0;
                                    }
                                    else
                                        collWorth = FInt.F1 / FInt.F2;
                                }

                                // calculate worth
                                worth[row - top, col - left] = (collWorth * FInt.F5) + (srcDistWorth * FInt.F2) + destDistWorth;

                                if (worth[row - top, col - left] > bestWorth || (worth[row - top, col - left] == bestWorth && new Random().Next(2) == 1))
                                {
                                    bestNode = fromNode;
                                    bestPathNode = pn;
                                    bestWorth = worth[row - top, col - left];
                                }
                                else if (fromNode.NumSegments == 1 && worth[row - top, col - left] < worstWorth || (worth[row - top, col - left] == worstWorth && new Random().Next(2) == 1))
                                {
                                    worstNode = fromNode;
                                    worstPathNode = pn;
                                    worstWorth = worth[row - top, col - left];
                                }
                            }
                        }
                    }

                    PlayerAction action = null;

                    if (bestPathNode != null && bestNode != null && (!stillBuilding || bestWorth > (FInt)3.5)) // if worth isn't high enough, don't do anything
                        action = new PlayerAction(Owner, PlayerAction.ActionType.BuildSeg, bestNode.ID, false, (VectorF)bestPathNode.Position);
                    else if (worstPathNode != null && worstNode != null)
                        action = new PlayerAction(Owner, PlayerAction.ActionType.DestroyNode, worstNode.ID);

                    if (action != null)
                    {
                        lock (Actions)
                            Actions.Add(action);
                    }

                }
                #endregion Decision-Making
            }

            Waiting = false;
        }
Example #2
0
        /// <summary>Builds the dictionaries of all nodes and segments.</summary>
        public void buildDictionaries(NodeSkel[] nodes, SegmentSkel[] segs)
        {
            foreach (NodeSkel node in nodes)
            {
                NodeByID.Add(node.ID, node);
            }

            foreach (SegmentSkel seg in segs)
            {
                SegByID.Add(seg.ID, seg);
            }
        }
Example #3
0
 /// <summary>Determines whether or not the provided segment is visible.</summary>
 /// <param name="seg">The segment to test.</param>
 /// <returns>Whether or not the provided segment is visible.</returns>
 public bool isVisible(SegmentSkel seg)
 {
     return isVisible(seg.EndLoc[0], seg.EndLoc[1]);
 }
Example #4
0
        /// <summary>Gets a skeleton version of this segment.</summary>
        /// <returns>A skeleton version of this segment.</returns>
        public SegmentSkel getSkeleton()
        {
            SegmentSkel skeleton = new SegmentSkel();

            skeleton.owner = this.Owner;
            skeleton.ID = this.ID;
            skeleton.EndLoc = (VectorF[])this.EndLoc.Clone();
            skeleton.CurLength = this.CurLength;
            skeleton.State = (SegState[])this.State.Clone();

            return skeleton;
        }
Example #5
0
        /// <summary>Gets a skeleton version of this grid manager.</summary>
        /// <param name="forPlayer">The player that will use it.  His nodes and segments are full instead of skeletons.</param>
        /// <param name="playerNodes">A list of all of the player's nodes.</param>
        /// <param name="playerSegs">A list of all of the player's segments.</param>
        /// <param name="allSegs">A list of all segments.</param>
        /// <param name="allNodes">A list of all nodes.</param>
        /// <returns>A skeleton version of this grid manager.</returns>
        public GridManager getSkeleton(Player forPlayer, out Node[] playerNodes, out Segment[] playerSegs, out NodeSkel[] allNodes, out SegmentSkel[] allSegs)
        {
            playerNodes = new Node[forPlayer.Nodes.Count];
            playerSegs = new Segment[forPlayer.Segments.Count];
            allNodes = new NodeSkel[InWorld.Nodes.Count];
            allSegs = new SegmentSkel[InWorld.Segments.Count];
            int nextPlyrNode = 0;
            int nextPlyrSeg = 0;
            int nextAllNode = 0;
            int nextAllSeg = 0;

            GridManager skeleton = new GridManager(NumCols, NumRows, InWorld, false);
            Dictionary<string, NodeSkel> nodes = new Dictionary<string, NodeSkel>(InWorld.Nodes.Count);
            Dictionary<string, SegmentSkel> segments = new Dictionary<string, SegmentSkel>(InWorld.Segments.Count);
            Dictionary<string, GeoSkel> geos = new Dictionary<string, GeoSkel>(InWorld.Geos.Count);

            // add nodes, segments, and geos to dictionary

            foreach (Node node in InWorld.Nodes)
            {
                if (node.Owner == forPlayer)
                {
                    Node clone = new Node(node);
                    nodes.Add(clone.ID, clone);
                    playerNodes[nextPlyrNode] = clone;
                    nextPlyrNode++;
                    allNodes[nextAllNode] = clone;
                }
                else if (!node.Destroyed)
                {
                    NodeSkel skel = node.getSkeleton();
                    nodes.Add(node.ID, skel);
                    allNodes[nextAllNode] = skel;
                }

                nextAllNode++;
            }

            foreach (Segment seg in InWorld.Segments)
            {
                if (seg.Owner == forPlayer)
                {
                    Segment clone = new Segment(seg);
                    segments.Add(clone.ID, clone);
                    playerSegs[nextPlyrSeg] = clone;
                    nextPlyrSeg++;
                    allSegs[nextAllSeg] = clone;
                    nextAllSeg++;
                }
                else if (!seg.Destroyed)
                {
                    SegmentSkel skel = seg.getSkeleton();
                    segments.Add(seg.ID, skel);
                    allSegs[nextAllSeg] = skel;
                    nextAllSeg++;
                }
            }

            foreach (Geo geo in InWorld.Geos)
            {
                geos.Add(geo.ID, geo.getSkeleton());
            }

            // connect cloned nodes and segments to each other

            foreach (Node node in playerNodes)
            {
                for (int i = 0; i < node.Segments.Length; i++)
                {
                    Segment seg = node.Segments[i];
                    if (seg != null)
                        node.Segments[i] = (Segment)segments[seg.ID];
                }

                for (int i = 0; i < node.Parents.Count; i++)
                {
                    Node n = node.Parents[i];
                    node.Parents[i] = (Node)nodes[n.ID];
                }
            }

            foreach (Segment seg in playerSegs)
            {
                for (int i = 0; i < seg.Nodes.Length; i++)
                {
                    Node node = seg.Nodes[i];

                    if (!node.Destroyed)
                        seg.Nodes[i] = (Node)nodes[node.ID];
                    else
                        seg.Nodes[i] = new Node(node);
                }
            }

            // build grid

            skeleton.SqrSize = this.SqrSize;

            for (int row = 0; row < NumRows; row++)
            {
                for (int col = 0; col < NumRows; col++)
                {
                    GridSqr sqr = Squares[row, col];
                    skeleton.Squares[row, col] = new GridSqr(new List<NodeSkel>(sqr.Nodes.Count), new List<SegmentSkel>(sqr.Segments.Count), new List<GeoSkel>(sqr.Geos.Count), new List<Hotspot>(sqr.Hotspots.Count), false);

                    foreach (NodeSkel node in sqr.Nodes)
                    {
                        if (((Node)node).Active && !((Node)node).Destroyed)
                            skeleton.Squares[row, col].Nodes.Add(nodes[node.ID]);
                    }

                    foreach (SegmentSkel seg in sqr.Segments)
                    {
                        if (!((Segment)seg).Destroyed)
                            skeleton.Squares[row, col].Segments.Add(segments[seg.ID]);
                    }

                    foreach (GeoSkel geo in sqr.Geos)
                    {
                        skeleton.Squares[row, col].Geos.Add(geos[geo.ID]);
                    }
                }
            }

            return skeleton;
        }
Example #6
0
        /// <summary>Searches for a collision between the provided line and any node or segment.  Also finds the exact intersection point if segment collision.</summary>
        /// <param name="point1">The first point in the line.</param>
        /// <param name="point2">The second point in the line.</param>
        /// <param name="ignoreSeg">The segments to ignore.</param>
        /// <param name="ignoreNode">The nodes to ignore.</param>
        /// <param name="nodeColl">The node that collided with the provided line.</param>
        /// <param name="segColl">The segment that collided with the provided line.</param>
        /// <param name="geoColl">The geometric object that collided with the provided line.</param>
        /// <param name="intersection">The intersection point if intersecting a segment.</param>
        /// <returns>Whether or not there was a collision between the line and any node or segment.</returns>
        public bool segCollisionIntPoint(VectorF point1, VectorF point2, List<SegmentSkel> ignoreSeg, List<NodeSkel> ignoreNode, out SegmentSkel segColl, out NodeSkel nodeColl, out GeoSkel geoColl, out VectorF? intersection)
        {
            intersection = null;
            segColl = null;
            nodeColl = null;
            geoColl = null;
            object[] array = new object[8];
            array[0] = point1;
            array[1] = point2;
            array[5] = false;
            array[6] = null;

            // look for collisions with segments
            List<SegmentSkel> segColls = new List<SegmentSkel>(1);
            array[2] = ignoreSeg;
            array[3] = segColls;
            array[4] = CollSrchType.GetIntersection;
            Grid.Line(point1, point2, array, gridSegCollSeg);

            if (segColls.Count > 0)
            {
                segColl = segColls[0];
                intersection = (VectorF)array[7];
            #if DEBUG
                if (array[7] == null)
                    throw new Exception(segColls.Count.ToString() + " segment(s) was returned, but no intersections.");
            #endif
            }
            else // look for collisions with nodes and geos
            {
                // look for nodes
                List<NodeSkel> nodeColls = new List<NodeSkel>(1);
                array[2] = ignoreNode;
                array[3] = nodeColls;
                array[4] = CollSrchType.DoesItCollide;
                Grid.LineExpand(point1, point2, array, gridSegCollNode);

                if (nodeColls.Count > 0)
                {
                    nodeColl = nodeColls[0];
                }
                else // look for geos
                {
                    List<GeoSkel> geoColls = new List<GeoSkel>(1);
                    array[2] = null;
                    array[3] = geoColls;
                    array[4] = CollSrchType.DoesItCollide;
                    Grid.LineExpand(point1, point2, array, gridSegCollGeo);

                    if (geoColls.Count > 0)
                        geoColl = geoColls[0];
                }

            }

            return nodeColl != null || segColl != null || geoColl != null;
        }