Exemple #1
0
        // Very similar to the above, but takes in a point and searches all derps
        // We return a pointer to the poor soul or null if none are in range
        public Derp SearchForDerp(int x, int y, double range)
        {
            // return null if there is no collision
            Derp   ret     = null;
            double mindist = range * range;

            // check against all other enemy derps
            foreach (Derp o in homeDerps)
            {
                myVector toOther = new myVector(o.x - x, o.y - y);

                if (toOther.mag2() < mindist)
                {
                    mindist = toOther.mag2();
                    ret     = o;
                }
            }

            foreach (Derp o in awayDerps)
            {
                myVector toOther = new myVector(o.x - x, o.y - y);

                if (toOther.mag2() < mindist)
                {
                    mindist = toOther.mag2();
                    ret     = o;
                }
            }

            // the unlucky nearest visible enemy
            return(ret);
        }
Exemple #2
0
        public static int SampleInput(myVector sampleInput, Network N)
        {
            float sum;
            float Error     = 0;
            int   foundID   = -35;
            int   correctID = 25;
            int   Counter   = 0;

            ClearInputs(N);
            //float NormalizationCoef = 1 / sampleInput.GetVector().Count;
            float NormalizationCoef = 1.0f / 50.0f;
            var   WordsList         = sampleInput.GetVector();
            var   InputLayer        = N.getNetwork().Where(o => o.type == 0).ToList();


            var HiddenLayer = N.getNetwork().Where(o => o.type == 1).ToList();
            var OutputLayer = N.getNetwork().Where(o => o.type == 2).ToList();


            //while (foundID != correctID && Counter < 20)
            //{
            //    sum = 0;
            //    N = ClearInputs(N);

            // Pierwsza iteracja
            for (int i = 0; i < sampleInput.GetVector().Count; i++)
            {
                InputLayer[i].Input = (float)WordsList[i];
            }

            // Druga iteracja
            CalculateInput(InputLayer);
            SigmoidFunction(HiddenLayer, NormalizationCoef);

            // Trzecia iteracja
            CalculateInput(HiddenLayer);
            SigmoidFunction(OutputLayer, NormalizationCoef);

            // Liczenie wyniku
            foundID = -OutputLayer.OrderBy(o => o.Input).Reverse().FirstOrDefault().ID - 1;
            //     correctID = -CorrectId(sampleInput, OutputLayer) - 1;
            //
            //    // Dopasowywanie wag
            //    sum = SumInputs(OutputLayer, sum);
            //    Error = (OutputLayer[correctID].Input - OutputLayer[foundID].Input) / sum;
            //    if (foundID != correctID)
            //    {
            //        AdjustWeights(HiddenLayer, Error);
            //        AdjustWeights(InputLayer, Error);
            //    }
            //    Counter++;
            //}



            return(foundID);
        }
Exemple #3
0
 public void InitializeNetwork()
 {
     classes = DataClass.CreateDataClasses(bow);
     classes = TestFunctions.CreateFullSet(classes, bow);
     myVector x = new myVector();
     {
         x = bow.GetVectorsList()[0];
         WithoutHiddenLayerNetwork = NeuralConstruction.CreateDefaultNetwork(x.GetVector().Count, classes);
         NeuralConstruction.SampleWeight(WithoutHiddenLayerNetwork, bow.GetVectorsList(), classes);
         NeuralNetwork = NeuralConstruction.CreateNewDefaultNetwork(x.GetVector().Count, classes, 5);
     }
 }
Exemple #4
0
        private void _Start_Copy_Click(object sender, RoutedEventArgs e)
        {
            myVector        x              = bow.GetVectorsList()[0];
            TestClass       T              = TestFunctions.CreateTest2(classes);
            List <myVector> vectors        = test.GetTestVectors();
            List <int>      kNNResultsIds  = new List <int>();
            List <int>      NNResultsIds   = new List <int>();
            List <int>      WHNNResultsIds = new List <int>();

            // Liczymy
            foreach (myVector V in vectors)
            {
                int id = 0;
                id = kNN.CalculateKNN(V, classes, 3);
                kNNResultsIds.Add(id);
                id = NeuralConstruction.OldSampleInput(V, WithoutHiddenLayerNetwork);
                WHNNResultsIds.Add(id);
                id = NeuralConstruction.SampleInput(V, NeuralNetwork);
                NNResultsIds.Add(id);
            }

            // Dodajemy wyniki dla KNN
            for (int i = 0; i < kNNResultsIds.Count; i++)
            {
                TestResult testresult = new TestResult("kNNAlgorithm");
                testresult.filltestData(T.GetTrainingClasses(), kNNResultsIds[i], vectors[i]);
                kNNResults.Add(testresult);
            }
            // Dodajemy wyniki dla sieci neuronowej
            for (int i = 0; i < NNResultsIds.Count; i++)
            {
                TestResult testresult = new TestResult("NNAlgorithm");
                testresult.filltestData(classes, NNResultsIds[i], vectors[i]);
                NNResults.Add(testresult);
            }
            // Dodajemy wyniki dla sieci neuronowej bez warstwy ukrytej
            for (int i = 0; i < WHNNResultsIds.Count; i++)
            {
                TestResult testresult = new TestResult("WHNNAlgorithm");
                testresult.filltestData(classes, WHNNResultsIds[i], vectors[i]);
                WHNNResults.Add(testresult);
            }
            ListView1.ItemsSource = kNNResults;
            ListView2.ItemsSource = NNResults;
            ListView3.ItemsSource = WHNNResults;

            kNNResults  = new List <TestResult>();
            NNResults   = new List <TestResult>();
            WHNNResults = new List <TestResult>();
            test        = new TestClass();
            test        = TestFunctions.CreateVectorTest(bow);
        }
Exemple #5
0
        private void UczenieSieci_Click(object sender, RoutedEventArgs e)
        {
            myVector x = bow.GetVectorsList()[0];

            BackPropagation.UczenieSieci(200, test.GetTrainingtVectors(), NeuralNetwork, classes);
            Console.Beep();

            foreach (myVector testvector in test.GetTestVectors())
            {
                int id     = NeuralConstruction.SampleInput(testvector, NeuralNetwork);
                var output = NeuralNetwork.getNetwork().Where(o => o.type == 2).ToList();
            }
            UczenieSieci.IsEnabled = false;
        }
Exemple #6
0
        public static int OldSampleInput(myVector sampleInput, Network N)
        {
            var vector = sampleInput.GetVector();
            int id     = 0;

            // Zerujemy inputy
            foreach (var neuron in N.getNetwork())
            {
                neuron.Input = 0;
            }


            // Pierwsza iteracja
            for (int i = 0; i < vector.Count; i++)
            {
                // int index = vector[i];
                var neuron = N.getNetwork().ElementAt(i);
                neuron.Input = (float)vector[i];
            }

            // Druga iteracja
            for (int i = 0; i < vector.Count; i++)
            {
                // int index = vector[i];
                var neuron           = N.getNetwork().ElementAt(i);
                var ConnectionVector = neuron.GetConnectionsOld();

                for (int j = vector.Count, k = 0; k < ConnectionVector.Count; j++, k++)
                {
                    N.getNetwork().ElementAt(j).Input += neuron.Input * neuron.GetWeights()[k];
                }
            }
            int connectionCount = N.getNetwork()[0].GetConnectionsOld().Count();

            double max = 0;

            for (int i = vector.Count; i < vector.Count + connectionCount; i++)
            {
                var neuron = N.getNetwork().ElementAt(i);
                if (neuron.Input > max)
                {
                    max = neuron.Input;
                    id  = (-neuron.ID) - 1;
                }
            }



            return(id);
        }
Exemple #7
0
        // Add an attack Animation here
        // TODO: maybe put the thing that actually applies the damage here, just to consolodate logical code
        public void AddAttack(Derp from, Derp to)
        {
            // This must be located two radius distance from the derp, in the direction of the delivering attacker
            myVector u = new myVector(from.x - to.x, from.y - to.y);

            u.toUnit();

            // opposite direction for nearest cardinal dir calculation
            myVector u2 = new myVector(-u.x, -u.y);

            DerpAttack attack = new DerpAttack(to.x + (u.x * to.stats.radius * 2), to.y + (u.y * to.stats.radius * 2), Geometry.GetNearestCardinalDir(u2));

            derpAttacks.Add(attack.key, attack);
        }
Exemple #8
0
        private static int CorrectId(myVector sample, List <Neuron> outputlayer)
        {
            int    correctID        = 0;
            string correctclassName = sample.GetVectorName();

            correctclassName = correctclassName.Remove(correctclassName.Length - 2);
            foreach (Neuron n in outputlayer)
            {
                if (n.Category == correctclassName)
                {
                    correctID = n.ID;
                }
            }
            return(correctID);
        }
Exemple #9
0
        // Set a derp to move out of the way of another derp. Also returns the slow derp. (even if it actually isn't slower?)
        // The fastDerp has run into the slow derp, it must tell it to move out of the way. Give the other derp the unit vector to move along
        public Derp SetToMoveOutOfWay(int slowDerpID, Derp fastDerp)
        {
            List <Derp> checkList = (fastDerp.team == TEAM.HOME ? homeDerps : awayDerps);
            Derp        slowDerp  = checkList[slowDerpID];

            // only actually do this if the slow derp is slower or equal
            if (slowDerp.stats.spd > fastDerp.stats.spd)
            {
                return(slowDerp);
            }

            // The Move Vector should be directly away from the fast derp
            myVector awayVector = new myVector(slowDerp.x - fastDerp.x, slowDerp.y - fastDerp.y);

            awayVector.toUnit();

            // Tell 'em to move
            slowDerp.moveOutOfWay       = true;
            slowDerp.moveOutOfWayVector = awayVector;

            return(slowDerp);
        }
Exemple #10
0
        // Search for enemy derps within our radar range
        // We return a pointer to the poor soul or null if none are in range
        public Derp SearchForEnemy(Derp d, double range)
        {
            // return null if there is no collision
            Derp ret = null;

            // For collision we are checking only against our enemies
            List <Derp> checkingList;

            if (d.team == TEAM.HOME)
            {
                checkingList = awayDerps;
            }
            else
            {
                checkingList = homeDerps;
            }

            double mindist = range * range;

            // check against all other enemy derps
            double        throwaway1;
            myLineSegment throwaway2;

            foreach (Derp o in checkingList)
            {
                myVector toOther = new myVector(o.x - d.x, o.y - d.y);

                if (toOther.mag2() < mindist && !Field.field.CheckFieldCollision(d, toOther, out throwaway1, out throwaway2))
                {
                    mindist = toOther.mag2();
                    ret     = o;
                }
            }

            // the unlucky nearest visible enemy
            return(ret);
        }
Exemple #11
0
        // This is the function that tries to make a step, it can recurse once.
        public void attemptStep(myVector v, bool recurse)
        {
            // Optimistic no collision
            double   t    = 1.0;
            myVector newV = null;

            // Check for team derp collisions
            double   derpT;
            myVector derpV = null;

            int colID = manager.CheckDerpCollision(this, v, out derpT, enemyDetected); // note: this returns -1 if either there is no collision, or if we are colliding with the other team

            isColliding = (colID != -1);

            // We have collided with another derp
            // Tell the other to move out of the way, and have us try to move perpendicular to them
            if (isColliding && !recurse)
            {
                Derp slowDerp = manager.SetToMoveOutOfWay(colID, this);

                if (slowDerp != null)
                {
                    // Get the Unit Vector towards the slow Derp
                    myVector u = new myVector(slowDerp.x - x, slowDerp.y - y);
                    u.toUnit();

                    // Make sure that the slow derp is actually in front of where you want to go
                    if (u.dot(v) > 0.0)
                    {
                        // Get a perpendicular unit vector to follow
                        myVector uPerp = new myVector(-u.y, u.x);

                        // Make sure it is the correct way
                        double dir = uPerp.dot(v);

                        // Wrong way
                        if (dir < -1e-3)
                        {
                            uPerp.x *= -1;
                            uPerp.y *= -1;
                        }
                        // Special Zero case, pick a random direction
                        // this should... almost never happen
                        // I'm concerned this could mess up random synch in multiplayer. Just pick a constant direction.
                        else if (dir < 1e-3)
                        {
                            /*
                             * if (MyRandom.Next(team, 2) % 2 == 0)
                             * {
                             *  uPerp.x *= -1;
                             *  uPerp.y *= -1;
                             * }
                             */
                        }

                        // Try moving along the new path
                        double remainingT = (1.0 - derpT);
                        derpV = new myVector(uPerp.x * remainingT * v.mag(), uPerp.y * remainingT * v.mag());
                    }
                }
            }

            // Check for field collisions
            double        fieldT;
            myVector      fieldV = null;
            myLineSegment collisionVect;

            if (Field.field.CheckFieldCollision(this, v, out fieldT, out collisionVect) && !recurse)
            {
                // try to move parallel to the wall with the extra t
                collisionVect.v.toUnit();

                // make sure this unit vector is in the right direction
                double dir = collisionVect.v.dot(v);

                // Wrong way
                if (dir < -1e-3)
                {
                    collisionVect.v.x *= -1;
                    collisionVect.v.y *= -1;
                }

                // ignore zero case
                if (Math.Abs(dir) > 1e-3)
                {
                    // Try moving along the new path
                    double remainingT = (1.0 - fieldT);
                    fieldV = new myVector(collisionVect.v.x * remainingT * v.mag(), collisionVect.v.y * remainingT * v.mag());
                }
            }

            // See if we have a collision
            // If either of the recalculated V values are not null, we hit something along the way
            if (derpT < 1.0 - 1e-6 || fieldT < 1.0 - 1e-6)
            {
                if (fieldT < derpT)
                {
                    t    = fieldT;
                    newV = fieldV;
                }
                else
                {
                    t    = derpT;
                    newV = derpV;
                }
            }

            // Only step as far as we can
            x += v.x * t;
            y += v.y * t;

            if (newV != null)
            {
                attemptStep(newV, true);
            }
        }
Exemple #12
0
        public void Update()
        {
            // CHECK FOR ATTACKS
            // use the derp radar to search for visible enemies in range
            Derp enemy = manager.SearchForEnemy(this, 100.0);

            enemyDetected = (enemy != null);

            // see if we can attack this enemy
            myVector toEnemy = null;

            if (enemyDetected)
            {
                toEnemy     = new myVector(enemy.x - x, enemy.y - y);
                isAttacking = (toEnemy.mag() < stats.radius + enemy.stats.radius + stats.rng);
                debugDist   = toEnemy.mag();

                if (isAttacking && (DateTime.Now.Subtract(lastAttack).TotalMilliseconds > (2000 - 15 * stats.aspd)))
                {
                    lastAttack = DateTime.Now;

                    enemy.takeHit(stats.atk);
                    manager.AddAttack(this, enemy);
                }
            }
            else
            {
                isAttacking = false;
            }

            // FOLLOW THE TRAIL
            // Find the vector between the derp and its current node destination
            double dx  = path[pathID].x - x;
            double dy  = path[pathID].y - y;
            double mag = Math.Sqrt(dx * dx + dy * dy);

            double        t = 1.0;
            myLineSegment throwaway;
            int           nextPathID = pathID + (team == TEAM.HOME ? 1 : -1);

            // Check if we can move to the next path node
            if (mag < (stats.spd * SPEED_CONST))
            {
                pathID = nextPathID;

                // Recalculate for the next node
                dx  = path[pathID].x - x;
                dy  = path[pathID].y - y;
                mag = Math.Sqrt(dx * dx + dy * dy);
            }
            // Sometimes we can abort the current node for the next-next node
            else if (nextPathID >= 0 && nextPathID < path.Count)
            {
                // if the next node is behind us (meaning we passed it accidentily) then just keep going
                // we use a manual dot product for this
                double ndx = path[nextPathID].x - x;
                double ndy = path[nextPathID].y - y;
                if (dx * ndx + dy * ndy < 0.0 && !Field.field.CheckFieldCollision(this, new myVector(path[nextPathID].x - x, path[nextPathID].y - y), out t, out throwaway))
                {
                    pathID = nextPathID;

                    // Recalculate for the next node
                    dx  = path[pathID].x - x;
                    dy  = path[pathID].y - y;
                    mag = Math.Sqrt(dx * dx + dy * dy);
                }
                // we can give a more liberal option to move forward to the next node
                // if we are colliding or seeking an enemy derp, and we can see the next node
                else if (isColliding && mag < GENERIOUS_THRESHHOLD &&
                         !Field.field.CheckFieldCollision(this, new myVector(path[nextPathID].x - x, path[nextPathID].y - y), out t, out throwaway))
                {
                    pathID = nextPathID;

                    // Recalculate for the next node
                    dx  = path[pathID].x - x;
                    dy  = path[pathID].y - y;
                    mag = Math.Sqrt(dx * dx + dy * dy);
                }
            }

            // DETERMINE MOVE
            if (!isAttacking)
            {
                // Calculate velocity and try to make the step
                double   velocity = stats.spd * SPEED_CONST;
                myVector v;
                if (enemyDetected && toEnemy != null)
                {
                    toEnemy.toUnit();
                    v = new myVector(toEnemy.x * velocity, toEnemy.y * velocity);
                }
                else if (moveOutOfWay)
                {
                    // Move out of the way!
                    v = new myVector(moveOutOfWayVector.x * velocity, moveOutOfWayVector.y * velocity);
                }
                else
                {
                    // Move Towards next Node
                    v = new myVector((dx / mag) * velocity, (dy / mag) * velocity);
                }

                // DEBUG: error catching
                double oldx = x;
                double oldy = y;

                if (isStuck)
                {
                    isStuck = false;
                }

                // Try to Step
                attemptStep(v, false);

                // DEBUG: error catching
                if (Math.Abs(x - oldx) < 1e-3)
                {
                    isStuck = true;
                }

                // Update our current instantaneous velocity
                vel.x = x - oldx; vel.y = y - oldy;

                // WE SHOULD NEVER MOVE THIS FAST. FIND MATH ERRORS.
                if (Math.Abs(vel.x) > 50 || Math.Abs(vel.y) > 50)
                {
                    x = oldx;
                    y = oldy;
                }
            }

            // Reset our MoveOUtOfWay variable, it will be set again next round if we need to keep moving out of the way
            moveOutOfWay = false;

            // This will be the game end condition eventually
            if ((team == TEAM.HOME && x > (Field.field.Width - 1) * Field.BLOCK_WIDTH) || (team == TEAM.AWAY && x < Field.BLOCK_WIDTH) || stats.hp <= 0)
            {
                Kill();
            }
        }
Exemple #13
0
        public int CheckDerpCollision(Derp casting, myVector v, out double t, bool checkBothTeams)
        {
            // t is initialized optimistically to the full distance
            t = 1.0;

            // the id of the derp is -1 if there is no collision
            int ret = -1;

            // For collision we are checking only against our teammates (because we will always attack (and stop moving) before we collide with enemies) <- at least that's the plan
            List <Derp> checkingList;

            if (casting.team == TEAM.HOME)
            {
                checkingList = homeDerps;
            }
            else
            {
                checkingList = awayDerps;
            }

            // I'm making the optimistic assumption that these lists will be sorted because they are sorted every Draw Step
            int myID = checkingList.IndexOf(casting);

            // check derps above me
            for (int i = myID - 1; i >= 0; --i)
            {
                // only check derps near me on the y axis
                if (casting.y - checkingList[i].y > distThreshholdY)
                {
                    break;
                }

                double check_t = Geometry.DerpCircleCast(casting, checkingList[i], v);
                if (check_t < t)
                {
                    t   = check_t;
                    ret = i;
                }
            }

            // check derps below me
            for (int i = myID + 1; i < checkingList.Count; ++i)
            {
                // only check derps near me on the y axis
                if (casting.y - checkingList[i].y > distThreshholdY)
                {
                    break;
                }

                double check_t = Geometry.DerpCircleCast(casting, checkingList[i], v);
                if (check_t < t)
                {
                    t   = check_t;
                    ret = i;
                }
            }

            // If we need to check the enemy team, then we can't do it quite as fast, but just check against them all
            if (checkBothTeams)
            {
                checkingList = (casting.team == TEAM.HOME ? awayDerps : homeDerps);
                foreach (Derp o in checkingList)
                {
                    double check_t = Geometry.DerpCircleCast(casting, o, v);
                    if (check_t < t)
                    {
                        t   = check_t;
                        ret = -1;
                    }
                }
            }

            // the id of the colliding derp
            return(ret);
        }
Exemple #14
0
        // Check for a Derp's Circle-Cast across the field
        // This will work like a BFS, starting from the initial position
        // then check all 4 corners around the position to build on the bfs
        public bool CheckFieldCollision(Derp d, myVector v, out double t, out myLineSegment col)
        {
            // initial optimistic setup that there will not be a collision
            bool ret = false;
            t = 1.0;
            col = null;

            // calculate starting point
            int startX = (int)(d.x / BLOCK_WIDTH);
            int startY = (int)(d.y / BLOCK_HEIGHT);

            // Unit Vector in desired direction
            myVector vUnit = new myVector(v.x, v.y);
            vUnit.toUnit();

            // set up the bfs
            Queue<SimpleNode> q = new Queue<SimpleNode>();
            bool[,] vis = new bool[height+1, width+1];

            q.Enqueue(new SimpleNode(startX, startY, 0));
            vis[startY, startX] = true;

            // Create the 4 line segments so we don't have to do quiiite as much object creation in this loop
            myLineSegment[] segs = new myLineSegment[4];
            for (int i = 0; i < 4; ++i)
                segs[i] = new myLineSegment(null, null);

            // BFS
            int[] dx = { 0, 1, 0, -1 };
            int[] dy = { -1, 0, 1, 0 };
            int cur_step = 0;
            while (q.Count > 0)
            {
                SimpleNode cur = q.Dequeue();

                // end early if we had a hit already in a previous step
                if (ret && cur_step != cur.step)
                    break;

                // checking 4 nodes around us
                myPoint p1 = new myPoint(cur.x * BLOCK_WIDTH, cur.y * BLOCK_HEIGHT);
                myPoint p2 = new myPoint((cur.x + 1) * BLOCK_WIDTH, cur.y * BLOCK_HEIGHT);
                myPoint p3 = new myPoint((cur.x + 1) * BLOCK_WIDTH, (cur.y + 1) * BLOCK_HEIGHT);
                myPoint p4 = new myPoint(cur.x * BLOCK_WIDTH, (cur.y + 1) * BLOCK_HEIGHT);
                segs[0].Update(p1, p2);
                segs[1].Update(p2, p3);
                segs[2].Update(p4, p3);
                segs[3].Update(p1, p4);

                for (int i = 0; i < 4; ++i)
                {
                    int nx = cur.x + dx[i];
                    int ny = cur.y + dy[i];

                    if (nx < 0 || nx > width || ny < 0 || ny >= height || vis[ny, nx])
                        continue;

                    double possible_t;
                    if (Geometry.DerpLineSegmentCast(d, v, segs[i], out possible_t))
                    {
                        // We have a hit! If the next zone is safe to move in, then continue the bfs
                        if (gameGrid[ny, nx] != '0')
                        {
                            q.Enqueue(new SimpleNode(nx, ny, cur.step + 1));
                            vis[ny, nx] = true;
                        }
                        // We hit an unnavigable space. Stop the BFS, this is as far as we go
                        else
                        {
                            ret = true;

                            if (Math.Abs(possible_t - t) < 1e-5 && col != null)
                            {
                                // break ties by taking the furthest behind the direction we wish to go
                                // Calculate the center point on the wall, and get the dot product of the vector to that point.
                                // The most negative value is the furthest behind
                                myPoint segMidPoint1 = new myPoint((segs[i].p1.x + segs[i].p2.x) / 2.0, (segs[i].p1.y + segs[i].p2.y) / 2.0);
                                myVector toMidPoint1 = new myVector(segMidPoint1.x - d.x, segMidPoint1.y - d.y);

                                myPoint segMidPoint2 = new myPoint((col.p1.x + col.p2.x) / 2.0, (col.p1.y + col.p2.y) / 2.0);
                                myVector toMidPoint2 = new myVector(segMidPoint2.x - d.x, segMidPoint2.y - d.y);

                                if (vUnit.dot(toMidPoint1) < vUnit.dot(toMidPoint2))
                                {
                                    t = possible_t;
                                    col = new myLineSegment(segs[i].p1.x, segs[i].p1.y, segs[i].p2.x, segs[i].p2.y); // careful... memory bugs
                                }
                            }
                            else if (possible_t < t)
                            {
                                t = possible_t;
                                col = new myLineSegment(segs[i].p1.x, segs[i].p1.y, segs[i].p2.x, segs[i].p2.y); // careful... memory bugs
                            }
                        }
                    }
                }

                // if we are a special diagonal case, then check the cross hit as well
                myLineSegment diag = null;

                char c = gameGrid[cur.y, cur.x];
                if (c == '1' || c == '3')
                    diag = new myLineSegment(p2, p4);

                if (c == '2' || c == '4')
                    diag = new myLineSegment(p1, p3);

                if (diag != null)
                {
                    double possible_t;
                    if (Geometry.DerpLineSegmentCast(d, v, diag, out possible_t))
                    {
                        ret = true;

                        if (Math.Abs(possible_t - t) < 1e-5 && col != null)
                        {
                            // break ties by taking the furthest behind the direction we wish to go
                            // Calculate the center point on the wall, and get the dot product of the vector to that point.
                            // The most negative value is the furthest behind
                            myPoint segMidPoint1 = new myPoint((diag.p1.x + diag.p2.x) / 2.0, (diag.p1.y + diag.p2.y) / 2.0);
                            myVector toMidPoint1 = new myVector(segMidPoint1.x - d.x, segMidPoint1.y - d.y);

                            myPoint segMidPoint2 = new myPoint((col.p1.x + col.p2.x) / 2.0, (col.p1.y + col.p2.y) / 2.0);
                            myVector toMidPoint2 = new myVector(segMidPoint2.x - d.x, segMidPoint2.y - d.y);

                            if (vUnit.dot(toMidPoint1) < vUnit.dot(toMidPoint2))
                            {
                                t = possible_t;
                                col = new myLineSegment(diag.p1.x, diag.p1.y, diag.p2.x, diag.p2.y); // careful... memory bugs
                            }
                        }
                        else if (possible_t < t)
                        {
                            t = possible_t;
                            col = new myLineSegment(diag.p1.x,diag.p1.y, diag.p2.x, diag.p2.y); // careful... memory bugs
                        }
                    }
                }

                cur_step = cur.step;
            }

            return ret;
        }