Example #1
0
        public static void GenMapPoints(CommandEventArgs e)
        {
            try
            {
                e.Mobile.SendMessage("Begin generation.");
                Dolphin  fish = new Dolphin();
                SeaChart tempMap = null;
                double   maxd = 0; double mind = 64; int count = 0; int failedPin = 0;
                int      pinNdx = 0; int pinCollisions = 0; int notInRect = 0; int specialExclusions = 0; int badMap = 0;
                int      wetTileFailure = 0; int badMapBounds = 0; int failMap = 0; int noLand = 0; int minDist = 0;
                SortedList <double, MapNode> list = new SortedList <double, MapNode>();
                for (int ji = 0; ji < Utility.BritWrap.Length; ji++)
                {
                    for (int mx = Utility.BritWrap[ji].Start.X; mx <= (Utility.BritWrap[ji].Start.X + Utility.BritWrap[ji].Width - 1); mx++)
                    {
                        for (int my = Utility.BritWrap[ji].Start.Y; my <= (Utility.BritWrap[ji].Start.Y + Utility.BritWrap[ji].Height - 1); my++)
                        {
                            // are we inside the brit rect?
                            if (Utility.BritWrap[ji].Contains(new Point2D(mx, my)) == false)
                            {                                   // bad point - not in rect
                                notInRect++;
                                continue;
                            }

                            // wet tile rect sanity check - make sure we are surrounded by water (not a puddle)
                            if (PuddleCheck(Utility.BritWrap[ji], new Point2D(mx, my)) == false)
                            {
                                wetTileFailure++;
                                continue;
                            }

                            // exclude special areas (eg. angel island prison, dungeons)
                            if (ValidRegion(mx, my) == false)
                            {
                                specialExclusions++;
                                continue;
                            }

                            // okay, we have what looks like a good map center and first pin
                            // we must have land within 64 tiles
                            Point3D wetLoc = new Point3D(mx, my, Map.Felucca.GetAverageZ(mx, my));
                            Point3D dryLoc = Spawner.GetSpawnPosition(Map.Felucca, wetLoc, 64, false, null);
                            if (wetLoc == dryLoc)
                            {                                   // spawner failed to find a good location
                                noLand++;
                                continue;
                            }

                            // okay, we have a focus point
                            //	now place the remaing N pins with validation

                            // dist2land to old point
                            double dist2land = GetDistance(new Point2D(wetLoc), new Point2D(dryLoc));

                            // level of this map
                            int level = (dist2land < 21) ? 1 : (dist2land < 31) ? 2 : (dist2land < 41) ? 3 : (dist2land < 51) ? 4 : (dist2land < 91) ? 5 : 0;

                            // create a temp map to validate pin locations
                            #region TEMP MAP CREATION & VALIDATION
                            if (tempMap != null)
                            {
                                tempMap.Delete();
                                tempMap = null;
                            }
                            // new level-sized map
                            tempMap = new SeaChart(level, new Point2D(wetLoc));

                            // make sure there is no w/h failure. I think this happens when we are at the map edge
                            if (tempMap.Bounds.Width <= 0 || tempMap.Height <= 0)
                            {
                                badMap++;
                                continue;
                            }
                            // even though our wet-point is in the brit rect, the bounds may not be. Exclude those maps here
                            if (!Utility.BritWrap[ji].Contains(tempMap.Bounds.Start) || !Utility.BritWrap[ji].Contains(tempMap.Bounds.End))
                            {
                                badMapBounds++;
                                continue;
                            }
                            #endregion TEMP MAP CREATION & VALIDATION

                            #region ADD PINS
                            // okay, place the start pin
                            Point2D[] pins = new Point2D[6];
                            pinNdx         = 0;
                            pins[pinNdx++] = new Point2D(wetLoc.X, wetLoc.Y);

                            Point3D newPinLoc;                                          // new pin location
                            Point3D lastPinLoc = wetLoc;                                // last pin location

                            // okay, try to place 6 pins
                            int good = 1;                       // how many pins have we placed?
                            for (int hx = 1; hx < 6; hx++)      // 6 pins
                            {                                   // 100 tries to place a pin
                                for (int retry = 0; retry < 100; retry++)
                                {
                                    // get a new pin location
                                    newPinLoc = Spawner.GetSpawnPosition(Map.Felucca, lastPinLoc, 200, false, false, Spawner.SpawnFlags.SpawnFar, fish);
                                    if (newPinLoc == lastPinLoc)
                                    {
                                        continue;
                                    }

                                    // did we exit the brit rect?
                                    if (Utility.BritWrap[ji].Contains(newPinLoc) == false)
                                    {                                           // bad point - not in rect
                                        notInRect++;
                                        continue;
                                    }

                                    // wet tile rect sanity check - make sure we are surrounded by water (not a puddle)
                                    if (PuddleCheck(Utility.BritWrap[ji], new Point2D(newPinLoc)) == false)
                                    {
                                        wetTileFailure++;
                                        continue;
                                    }

                                    // is this pin in an illegal region?
                                    if (ValidRegion(newPinLoc.X, newPinLoc.Y) == false)
                                    {
                                        specialExclusions++;
                                        continue;
                                    }

                                    // validate that we don't exceed the map bounds
                                    if (ValidBounds(tempMap, newPinLoc.X, newPinLoc.Y) == false)
                                    {
                                        badMap++;
                                        continue;
                                    }

                                    // validate a minmum distance
                                    if (ValidDistance(150, new Point2D(lastPinLoc), new Point2D(newPinLoc)) == false)
                                    {
                                        minDist++;
                                        continue;
                                    }

                                    if (ValidUnique(pins, pinNdx, new Point2D(newPinLoc.X, newPinLoc.Y)) == false)
                                    {
                                        pinCollisions++;
                                        continue;
                                    }

                                    // okay, looks to be a reasonable pin location
                                    pins[pinNdx++] = new Point2D(newPinLoc.X, newPinLoc.Y);
                                    lastPinLoc     = newPinLoc;                                 // make the next pin relative to this pin
                                    good++;
                                    break;
                                }
                            }

                            if (good < 6)
                            {                                   // skip this location as we can't place sufficient pins
                                failedPin++;
                                continue;
                            }
                            #endregion ADD PINS


                            // Create an actual map and run sanity checks on it.
                            //	for some unknown reason, we're still getting like 10% bad maps
                            #region FINAL CHECK
                            for (int rm = 0; rm < pins.Length; rm++)
                            {
                                tempMap.AddWorldPin(pins[rm].X, pins[rm].Y);
                            }
                            bool[] failTest = new bool[10];
                            if (CheckMap(tempMap, failTest) == false)
                            {
                                failMap++;
                                tempMap.ClearPins();
                                continue;
                            }
                            tempMap.ClearPins();
                            #endregion FINAL CHECK

                            // maps processed
                            count++;

                            // give a little feedback since thie process is so slow
                            if (count % 1000 == 0)
                            {
                                Console.Write("{0},", count);
                            }

                            // add to sorted list
                            double key      = Utility.RandomDouble();
                            bool   retrykey = false;
                            while (list.ContainsKey(key))
                            {                                   // feedback for key retries
                                Console.Write(".");
                                key      = Utility.RandomDouble();
                                retrykey = true;
                            }
                            list.Add(key, new MapNode(level, pins));

                            if (retrykey == true)
                            {
                                Console.Write(",");
                            }
                        }
                    }
                }

                // no longer need our test fish
                fish.Delete();

                Console.WriteLine();
                Console.WriteLine("Fill arrays");

                int[] indexes = new int[m_Locations.GetUpperBound(0) + 1]; // column index
                foreach (KeyValuePair <double, MapNode> kvp in list)
                {                                                          // only store the first 500 (m_Locations.GetUpperBound(1)+1) for each level
                    if (indexes[kvp.Value.Level - 1] > m_Locations.GetUpperBound(1))
                    {
                        continue;
                    }

                    m_Locations[kvp.Value.Level - 1, indexes[kvp.Value.Level - 1]] =
                        new Point2D[6] {
                        kvp.Value.Pins[0], kvp.Value.Pins[1], kvp.Value.Pins[2],
                        kvp.Value.Pins[3], kvp.Value.Pins[4], kvp.Value.Pins[5]
                    };

                    indexes[kvp.Value.Level - 1]++;
                }

                Console.WriteLine("Write the data");
                try
                {
                    int    rowx, coly;
                    string filePath = Path.Combine(Core.BaseDirectory, "Data/seatreasure.bin");
                    using (Stream stream = File.Open(filePath, FileMode.Create))
                    {
                        BinaryFormatter bin = new BinaryFormatter();
                        for (rowx = 0; rowx <= m_Locations.GetUpperBound(0); rowx++)
                        {
                            for (coly = 0; coly <= m_Locations.GetUpperBound(1); coly++)
                            {
                                bin.Serialize(stream, m_Locations[rowx, coly]);
                            }
                        }
                    }

                    // read it back
                    using (Stream stream = File.Open(filePath, FileMode.Open))
                    {
                        BinaryFormatter bin = new BinaryFormatter();

                        for (rowx = 0; rowx <= m_Locations.GetUpperBound(0); rowx++)
                        {
                            for (coly = 0; coly <= m_Locations.GetUpperBound(1); coly++)
                            {
                                m_Locations[rowx, coly] = new Point2D[6];
                                m_Locations[rowx, coly] = (Point2D[])bin.Deserialize(stream);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.LogException(ex);
                }

                e.Mobile.SendMessage("Generation complete with {0} maps processed.", count);
                e.Mobile.SendMessage("{0} map locations were skipped for bad pin placement.", failedPin);
                e.Mobile.SendMessage("{0} pin locations were skipped because of pin collisions.", pinCollisions);
                e.Mobile.SendMessage("{0} points were skipped: outside rect.", notInRect);
                e.Mobile.SendMessage("{0} points were skipped: special area.", specialExclusions);
                e.Mobile.SendMessage("{0} maps were skipped: bad width/height.", badMap);
                e.Mobile.SendMessage("{0} pins were skipped: not wet.", wetTileFailure);
                e.Mobile.SendMessage("{0} pins were skipped: min distance.", minDist);
                e.Mobile.SendMessage("{0} maps were skipped: bad map bounds.", badMapBounds);
                e.Mobile.SendMessage("{0} maps were skipped: failed map test.", failMap);
                e.Mobile.SendMessage("{0} maps were skipped: failed dist to land test.", noLand);
                e.Mobile.SendMessage("{0} total maps output.", count - failedPin);
            }
            catch (Exception ex)
            {
                LogHelper.LogException(ex);
            }
        }