Thread: Creating a map

  1. #1
    Registered User
    Join Date
    Jun 2003
    Posts
    129

    Creating a map

    I'm not sure if this should really go in game programming, general programming or whatever, so forgive me, but seeing as I am doing this in C#, might as well post it here.

    I'm currently writing a text based game (just tidied up and put on windows forms) and I'm having a mental block on trying to write the game map portion. The map is (or part of) a galaxy, with stars based on a 25x21 grid. I can currently create the placement, randomly, of the stars. The next step is to basically 'link' the stars with hyperspace links. A possible example on a 3x3 grid is here:

    Code:
    100Y--101B--102C
     oo \/ooo \/ o  
     |  /\ |  /\ |
    103H--104S--105G
     |  \/oooo\/ |
     |  /\ |  /\ |
    106R--107Y--108p
    The number itself is just a system code, the letter is just it's type (Y= Yellow Dwarf). The lines are fairly explanatory. These are the 'links' between systems via hyperspace. The example above only shows what is possible. Not all the systems shown could really be there (or even in that number order, lots of lovely but controlled randomness). The hard part is deciding whether to have a link between two existing systems, and then how to show it easily. It's not even one grid space length only, it could be up to three (horizontal or vertical only though).

    The following is the part of placing the stars:

    Code:
    void PlaceSystems()
    		{
    			Random randomNumber = new Random();
    
    			for (int y = 0; y < 21; y++)
    			{
    				for (int x = 0; x < 25; x++)
    				{
    
    					int max = 70;
    					List<int> vert1 = new List<int>();
    					vert1.AddRange(new int[] { 0, 4, 5, 9, 10, 14, 15, 19, 20, 24 });
    					List<int> Hori1 = new List<int>();
    					Hori1.AddRange(new int[] { 0, 6, 7, 13, 20 });
    					if (Hori1.Contains(y))
    					{
    						max -= 15;
    					}
    					if (vert1.Contains(x))
    					{
    						max -= 15;
    					}
    
    					int xminus2 = x - 2 < 0 ? 0 : x - 2;
    					int xminus1 = x - 1 < 0 ? 0 : x - 1;
    					int yminus2 = y - 2 < 0 ? 0 : y - 2;
    					int yminus1 = y - 1 < 0 ? 0 : y - 1;
    					int xplus2 = x + 2 > 24 ? 24 : x + 2;
    					int xplus1 = x + 1 > 24 ? 24 : x + 1;
    					int yplus2 = y + 2 > 20 ? 20 : y + 2;
    					int yplus1 = y + 1 > 20 ? 20 : y + 1;
    
    					if ((this[xminus2, y].Exists && this[xminus1, y].Exists) || this[x, yminus2].Exists && this[x, yminus1].Exists)
    					{
    						max -= 10;
    					}
    					if ((this[xminus1, yminus1].Exists && this[xminus2, yminus2].Exists) || (this[xplus1, yminus1].Exists && this[xplus2, yminus2].Exists))
    					{
    						max -= 10;
    					}
    
    					if (randomNumber.Next(0, max) > 35)
    					{
    						StarTypes newStarType = StarTypes.Error;
    						int systemNumber = GenerateSystemNumber();
    						SystemStar newSystem = new SystemStar(systemNumber, newStarType.GenerateStarTypeFromNumber(randomNumber.Next(1, 26)));
    						SystemsList.Add(newSystem);
    						this[x, y] = new MapBase(systemNumber, x, y);
    					}
    				}
    			}
    		}
    That is contained within the map class itself and is the first stage of generating the map.

    Next it looks at where links can be possibly placed...

    Code:
    void FindLinkableSystems()
    		{
    			for (int y = 0; y < 21; y++)
    			{
    				for (int x = 0; x < 25; x++)
    				{
    					if (this[x, y].Exists)
    					{
    						bool foundRight = false;
    						bool foundLeft = false;
    						bool foundUp = false;
    						bool foundDown = false;
    						for (int i = 1; i < 4; i++)
    						{
    							if (!foundRight)
    							{
    								if (i + x > 24)
    								{
    									break;
    								}
    								if (this[x + i, y].Exists)
    								{
    									this[x, y].LinkableSystems.Add(new LinkDetails(this[x + i, y].StarNumber, Direction.Right, i));
    									foundRight = true;
    								}
    							}
    						}
    						for (int i = 1; i < 4; i++)
    						{
    							if (!foundLeft)
    							{
    								if (x - i < 0)
    								{
    									break;
    								}
    								if (this[x - i, y].Exists)
    								{
    									this[x, y].LinkableSystems.Add(new LinkDetails(this[x - i, y].StarNumber, Direction.Left, i));
    									foundLeft = true;
    								}
    							}
    						}
    						for (int i = 1; i < 4; i++)
    						{
    							if (!foundDown)
    							{
    								if (y + i > 20)
    								{
    									break;
    								}
    								if (this[x, y + i].Exists)
    								{
    									this[x, y].LinkableSystems.Add(new LinkDetails(this[x, y + i].StarNumber, Direction.Down, i));
    									foundDown = true;
    								}
    							}
    						}
    						for (int i = 1; i < 4; i++)
    						{
    							if (!foundUp)
    							{
    								if (y - i < 0)
    								{
    									break;
    								}
    								if (this[x, y - i].Exists)
    								{
    									this[x, y].LinkableSystems.Add(new LinkDetails(this[x, y - i].StarNumber, Direction.Up, i));
    									foundUp = true;
    								}
    							}
    						}
    
    						if (!(y - 1 < 0 || x - 1 < 0) && this[x - 1, y - 1].Exists)
    						{
    							this[x, y].LinkableSystems.Add(new LinkDetails(this[x - 1, y - 1].StarNumber, Direction.UpLeft, 1));
    						}
    						if (!(y + 1 > 20 || x + 1 > 24) && this[x + 1, y + 1].Exists)
    						{
    							this[x, y].LinkableSystems.Add(new LinkDetails(this[x + 1, y + 1].StarNumber, Direction.DownRight, 1));
    						}
    						if (!(y + 1 > 20 || x - 1 < 0) && this[x - 1, y + 1].Exists)
    						{
    							this[x, y].LinkableSystems.Add(new LinkDetails(this[x - 1, y + 1].StarNumber, Direction.DownLeft, 1));
    						}
    						if (!(y - 1 < 0 || x + 1 > 24) && this[x + 1, y - 1].Exists)
    						{
    							this[x, y].LinkableSystems.Add(new LinkDetails(this[x + 1, y - 1].StarNumber, Direction.UpRight, 1));
    						}
    					}
    				}
    			}
    		}
    Yeah yeah, I could probably massively shorten that one...!

    Anyways, the next step actually creates the links, but it's a little hard to actually verify it works truly correctly, which is later...

    Code:
    void CreateLinks()
    		{
    			for (int y = 0; y < 21; y++)
    			{
    				for (int x = 0; x < 25; x++)
    				{
    					if (this[x, y].Exists)
    					{
    						int LinkableCount = this[x, y].LinkableSystems.Count;
    						int subSystemsCount = SystemsList[this[x, y].StarNumber].AdjacentSystems.Count;
    						int availableLinksAmount = 7 - subSystemsCount;
    						if (LinkableCount == 1)
    						{
    							int currentSystemNumber = this[x, y].StarNumber;
    							int linkableSystemNumber = this[x, y].LinkableSystems[0].StarNumber;
    
    							SystemsList[currentSystemNumber].AdjacentSystems.Add(linkableSystemNumber);
    							SystemsList[linkableSystemNumber].AdjacentSystems.Add(currentSystemNumber);
    
    							switch (this[x, y].LinkableSystems[0].Direction)
    							{
    								case Direction.Up:
    									this[x, y].Uplink = true;
    									this[linkableSystemNumber].Downlink = true;
    									break;
    								case Direction.Down:
    									this[x, y].Downlink = true;
    									this[linkableSystemNumber].Uplink = true;
    									break;
    								case Direction.Left:
    									this[x, y].LeftLink = true;
    									this[linkableSystemNumber].Rightlink = true;
    									break;
    								case Direction.Right:
    									this[x, y].Rightlink = true;
    									this[linkableSystemNumber].LeftLink = true;
    									break;
    								case Direction.UpRight:
    									this[x, y].UpRightLink = true;
    									this[linkableSystemNumber].DownLeftLink = true;
    									break;
    								case Direction.DownRight:
    									this[x, y].DownRightLink = true;
    									this[linkableSystemNumber].UpLeftLink = true;
    									break;
    								case Direction.DownLeft:
    									this[x, y].DownLeftLink = true;
    									this[linkableSystemNumber].UpRightLink = true;
    									break;
    								case Direction.UpLeft:
    									this[x, y].UpLeftLink = true;
    									this[linkableSystemNumber].DownRightLink = true;
    									break;
    								default:
    									break;
    							}
    						}
    						int hold = 0;
    					}
    				}
    			}
    		}
    Sorry for breaking the forums. Anyways, that appears to work (I don't get errors anymore and have since removed the try/catch stuff I had to place in. There are still a few holes so to speak, such as I should also be assigning the destination system in that last switch statement for the link to be placed as true in the opposite direction for the destination system back to the system it's doing at the moment. That's lots of little if's etc making sure I don't error out of range.

    The hard part is actually drawing this out to a text file or control. You see, there are so many conditions it has to operate under that I just cannot think of how to do this! You see, in a system grid square, if there's not a system there it could be passed through by a hyperlink from a system one side to another the other side. It could even have links crossing over it!

    It's not so much the actual code, but help on actually designing how I should go about this. If you're confused, feel free to ask more.

    Thanks for your time and I hope you didn't fall asleep!
    He who asks is a fool for five minutes, but he who does not ask remains a fool forever.

    The fool wonders, the wise man asks. - Benjamin Disraeli

    There are no foolish questions and no man becomes a fool until he has stopped asking questions. Charles Steinmetz

  2. #2
    Tha 1 Sick RAT
    Join Date
    Dec 2003
    Posts
    271
    Confused o_0? Let's see....
    Ok, 1st of all, I gather it's a logical problem so there's no need for the massive amounts of lines of code.
    2nd,
    The example above only shows what is possible. Not all the systems shown could really be there (or even in that number order, lots of lovely but controlled randomness). The hard part is deciding whether to have a link between two existing systems, and then how to show it easily. It's not even one grid space length only, it could be up to three (horizontal or vertical only though).
    please explain that part more clearly. e.g. what is the case for any 2+ systems being linked?
    A hundred Elephants can knock down the walls of a fortress... One diseased rat can kill everyone inside

  3. #3
    Registered User
    Join Date
    Jun 2003
    Posts
    129
    The large amount of code is just setting it up. Using it and working on it turns out should be a doddle after I've done this part.

    A system may be linked to another system on the map so that ships/fleets can travel from one system to another. There will be a method of moving from system to system without the links, but this is highly expensive (think that FTL travel hasn't been invented or ever will be and the links are like wormholes). Thing is, it's all random, structured yes, but random and almost sparse with the links.
    He who asks is a fool for five minutes, but he who does not ask remains a fool forever.

    The fool wonders, the wise man asks. - Benjamin Disraeli

    There are no foolish questions and no man becomes a fool until he has stopped asking questions. Charles Steinmetz

  4. #4
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Quote Originally Posted by DanFraser View Post
    The large amount of code is just setting it up. Using it and working on it turns out should be a doddle after I've done this part.

    A system may be linked to another system on the map so that ships/fleets can travel from one system to another. There will be a method of moving from system to system without the links, but this is highly expensive (think that FTL travel hasn't been invented or ever will be and the links are like wormholes). Thing is, it's all random, structured yes, but random and almost sparse with the links.
    I don't have time to read all the code through, but how are you drawing the stars right now?

    You might be doing this already, but have you considered just creating a custom control and then drawing the stars as small circles(Colors can even be done easily, yellow for yellow dwarfs and so on). This way, drawing the lines won't be a problem, since as far as I can see, you're trying to do this with ASCII art.

    Excuse me if I misunderstood, but I wasn't able to see how you are drawing this to your form.
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

  5. #5
    Registered User
    Join Date
    Jun 2003
    Posts
    129
    Oh it's all just text based, not even as far as ASCII art. It is just just like this:

    Code:
    100Y--101B--102C
     oo \/ooo \/ o  
     |  /\ |  /\ |
    103H--104S--105G
     |  \/oooo\/ |
     |  /\ |  /\ |
    106R--107Y--108p
    But just in a 25x21 grid, and not all the links will exist for each and every 'star' that is there, and also, each grid space will not have a star, it works out at about 30% have a star.

    The base layout is pretty much four characters in line 1 for the systems' number and it's corresponding code. Very easy to get. In line 2, the first four characters either represent the planets the system has, if present, or if a link goes down to another star that if one exists. The next line below only shows a link going down if one exists, otherwise it'll just be 4 blank spaces. Characters 5 and 6 on line 1 will either show "--" if the system has a link to the right to another system, if not, it's " ". Characters 5 on line 2 and 6 on line 3 will show "\" if the system has a link going down and right to another system, if not, blank. The characters 6 on line 2 and 5 on line 3 will show "/" under similar circumstances.

    It looks simple when you do this:

    Code:
    if(grid[x,y].exists) // there is a way to check if there is a system in this grid
    {
      Line1 += SystemsList[grid[x,y].StarNumber].GetMapCode();
    }
    else
    {
      Line1+="    ";
    }
    if(grid[x,y].HasRightLink)
    {
      Line1+="--";
    }
    else
    {
      Line1+="  ";
    }
    if(SystemsList[grid[x,y].StarNumber].SubSystems > 0)
    {
      Line2+=SystemsList[grid[x,y].StarNumber].GetSubsMapCode();
    }
    else
    {
      Line2+="    ";
    }
    And so on... But here's the kicker, what if that grid square is blank, and the systems either side are connected? But, also, what if one of those systems, you couldn't see!? Visibility is a large factor too!
    Last edited by DanFraser; 01-21-2009 at 11:14 AM.
    He who asks is a fool for five minutes, but he who does not ask remains a fool forever.

    The fool wonders, the wise man asks. - Benjamin Disraeli

    There are no foolish questions and no man becomes a fool until he has stopped asking questions. Charles Steinmetz

  6. #6
    Tha 1 Sick RAT
    Join Date
    Dec 2003
    Posts
    271
    Ok let me get this straight. (Just so that I follow your thinking) even though the size of your Galaxy is dimensionally constrained,the accessibility of stars within this galaxy is arbitrary and you want to write a method to implement this?
    so for example:
    Code:
    100Y--101B--102C
     oo \/ooo \/ o  
     |  /\ |  /\ |
    103H--104S--105G
     |  \/oooo\/ |
     |  /\ |  /\ |
    106R--107Y--108p
    is the possible types of connection but you would like it to appear more arbitral?
    Like say:
    Code:
    100Y--101B--102C
     oo  /ooo \/ o  
     |  /  |  /\ |
    103H--104S--105G
        \/oooo / |
        /\ |  /  |
    106R--107Y--108p
    A hundred Elephants can knock down the walls of a fortress... One diseased rat can kill everyone inside

  7. #7
    Registered User
    Join Date
    Jun 2003
    Posts
    129
    Yep, but more like this:

    Code:
    100Y  101B--102C
     oo   ooo    o  
     |     |  
    103H--104S--105G
        \/oooo / 
        /\ |  /  
    106R  107Y--108p
    He who asks is a fool for five minutes, but he who does not ask remains a fool forever.

    The fool wonders, the wise man asks. - Benjamin Disraeli

    There are no foolish questions and no man becomes a fool until he has stopped asking questions. Charles Steinmetz

  8. #8
    Tha 1 Sick RAT
    Join Date
    Dec 2003
    Posts
    271
    I think I now understand the problem.
    It's down to your game design. Think of it this way, you are trying to create some form of chaos out of a logical tool, or at least make it appear chaotic/non uniform. In this case the way to do it would be to imbue each object, say solar system for instance, with properties that govern whether or not is reachable from current destination.
    In this case let's make it a simple one like say distance being the constraining variable that governs whether a link is established between systems. Your method would then follow a logical path like (in abstract code):
    Code:
     foreach(system solarsystem in galaxy)
    {
    	do
    	{
    	  if distance(this.solarsystem.location, next.solarsystem.location) <  maxdistance;
    	      createlink(this.solarsystem.location, next.solarsystem.location); 
                    
    	}while (++galaxy);
    }
    Last edited by WDT; 01-23-2009 at 06:26 AM.
    A hundred Elephants can knock down the walls of a fortress... One diseased rat can kill everyone inside

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Creating a map with a new object type
    By blacknail in forum C++ Programming
    Replies: 6
    Last Post: 11-24-2008, 10:16 AM
  2. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 08:32 AM
  3. Profiler Valgrind
    By afflictedd2 in forum C++ Programming
    Replies: 4
    Last Post: 07-18-2008, 09:38 AM
  4. Creating a map of objects with variable width and height
    By MrSparky in forum C++ Programming
    Replies: 6
    Last Post: 07-30-2007, 03:06 PM
  5. Creating a map engine.
    By suzakugaiden in forum Game Programming
    Replies: 11
    Last Post: 06-21-2005, 05:06 AM