When Simon and I discussed how to fully integrate the city creator, code named “Map Invoker”, the idea of it working like a Wizard surfaced. 

With a wizard like interface, each layer of objects (Waterways, Roads, Walls, etc.) would each be generated by a different page on the wizard.  A “generate” button would draw the objects directly in CC3.  If the results were not what the user wanted, the user could press the “generate” button again and the old objects would be removed and the new ones drawn.  Once the user liked the output, the “next” button would take the user to the next wizard page.

Now this sounded like a great design to me.  But …. I had some technical issues to overcome and some design work to make life a little easier.

The main technical issue was that the built-in dialog system was not made to ever run custom code and call XP functions while the dialog was still visible.  This was solved by using C# to write the Dialog code and communicating with CC3 via a simple callback class and a delegate.  I will go into this solution in depth in a later post.  Right now I want to go over the design work I did to make life easier passing data back and forth between C++ & C#.

Here is the diagram of my classes thus far.  They are simple value classes, with no behavior.  In a previous experiment, I created a REAL object (data & behavior) but because of the fact that a real class crosses native and managed code, it worked great in a all C++/cli environment, but I could not use it in C#.  So I decided to split data and behavior into two separate dlls.  The cc3objects.dll, a C# set of value classes and cc3actions.dll, the C++/cli dll that implements the behavior.

diagram

Now, what this does is let me create an entire object, or set of objects that can be directly converted to native CC3 objects.  So, I actually build my objects in C# then pass them to my C++/cli XP dll.  Plus, once I get done with this project everyone will be able to use these dlls.

As I sit here in this cozy little room talking quietly with my wife’s family, as her mother lies sleeping in her medical bed, I began to think about the broader meaning of family and community. I’ve always realized in a cursory way, that the Campaign Cartographer community was in many ways a family. But, until recently I had not fully grasped the true meaning of that fact.

Let us back up about a year. I had recently approached Mark and Simon about producing a city generator for them. We had determined that an April/May timeframe for completion would be just about right and I happily went about the task of creation.

Then my wife’s mother’s cancer returned in March. At first we didn’t realize it was the cancer but all of a sudden, my wife was busy taking care of her mother. Off to the doctors, taking over her bills and doing all of the household chores her mother used to do for herself but could no longer do them. I, of course, being the good husband, started doing all the little things that she no longer had time to do.

That seriously cut into my evening coding, especially in the middle of spring lambing season!

Well as you can guess, the month of May flew by and I felt embarrassed that I had missed my deadline. “I had given my word!” I never forgot my obligation, it was just that every day I would tell myself after getting all the chores done, maybe after driving back from the city where I picked up my wife from her mother’s house and took her out to dinner, that I could rest today and tomorrow would not be so hectic and I could get back to programming. And, since I was going to get it done, there was no need to tell Mark or Simon about my difficulties.

Here is my point about family and community. Unlike the rest of the world, you pull family and community closer to you in times of trouble. To the wide world your troubles are your own and since everyone has troubles, you just keep them to yourself. But, for family and community – to keep them in the dark on your troubles is not fair to them. They need to know so they can help.

So I screwed up my courage and finally contacted Simon explaining why I had not only missed the deadline but feared that I would not be finishing the program anytime soon. Now, you have to understand that ProFantasy is a business. It lives and dies by the products it makes and the reputation it has with its user base. They had announced that I would be creating such a tool for them and since then I had failed to finish it. In my mind, I had done them some amount of harm.

I should not have been worried. Simon not only told me not to worry about it, but asked if there was anything they could do.

Family, I should have known.

So that is why I am writing this to you now. After a second failed round of Chemotherapy/Radiation and now hospice, I wanted to tell the greater Campaign Cartographer community that I’ve not forgotten my promise to you. I may not get back to it soon, my wife will need a lot of help cleaning up and organizing the estate, but I promise I’ll finish when I can.

And I know that you will understand. Like I said, Family.

First a warning – The .FCW file format is BINARY!  If you do not feel comfortable playing with bits and bytes, this may not be for you.  But if you do enjoy this type of challenge, the .FCW file format is one of the best ways to output to CC3.
Imagine you have a random maze generator and you want to output it to CC3.  You could export a script.  It would redraw your maze one line at a time.  
But there are also some problems with scripts:

  • You have to run them.  This may sound obvious but consider that you have to either know the text command to open and run a script file, or you need to know where in the menu system it is. 
  • Scripts are slow.  CC3 will have to take your script and run it line-by-line.  Its as if you had set down and typed in the commands directly into CC3.
  • Scripts are not exactly fragile, but they are not very robust either.  And, if your script fails, your users are the ones that are going to get frustrated.

Where as if you exported a .FCW file, simply the action of opening the file is all that is needed.
So … if you are still with me, here we go!

One last twist – the .FCW file could be compressed.

The .FCW file format is made up of many different “Blocks” of data.  The first 4 bytes of each block (except for the first block) contains the number of bytes that the following block contains.  It starts with the FileID block.  The FileID block is the only block that is guaranteed to be uncompressed.  This 128 byte block contains quite a bit of general info on the file.  It identifies what type of file it is to other programs, and the version and sub-version number of the file format is was built with.  Last, but not least, it informs the reader that bytes after byte 128 are compressed or not.  (To save an uncompressed file, after you have clicked “Save As …”, you will be presented with the save file dialog.  If you click on the options button, you will be presented with a small dialog box.  Uncheck the “File Compression” option)

For this first blog post on the .FCW file format, I will show you how to read a binary file into a byte array and how to display it, byte-by-byte in a textbox similar to all the binary editors display it.  Being able to look inside a binary file will come in very handy in the future.  Last but not least I will show you FILEID object.

Code Snippet – How to read an entire file into a byte array
  1. public byte[] ConvertFileToByteArray(string fileName)
  2. {
  3.     byte[] buffer;
  4.  
  5.     using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
  6.     {
  7.         using (var binaryReader = new BinaryReader(fileStream))
  8.         {
  9.             buffer = binaryReader.ReadBytes((int)new FileInfo(fileName).Length);
  10.  
  11.             binaryReader.Close();
  12.         }
  13.  
  14.         fileStream.Close();
  15.     }
  16.  
  17.     return buffer;
  18. }

Once the file is read into a byte array, I pull the first 128 bytes out of the file byte array, using an extension method to Arrays to create sub-arrays.

Code Snippet – SubArray extension method
  1. public static class Extensions
  2. {
  3.     public static T[] SubArray<T>(this T[] data, int index, int length)
  4.     {
  5.         var result = new T[length];
  6.  
  7.         Array.Copy(data, index, result, 0, length);
  8.  
  9.         return result;
  10.     }
  11. }

Then I feed the sub-array to my FILEID object.  This object converts the bytes into the fields of the FILEID object.  We can then check the Compressed property.  If the file is compressed, the rest of the data is meaningless, so if the file is compressed, I set the background color of the textbox to a Rose color.

Code Snippet
  1. using System;
  2. using System.Text;
  3.  
  4. namespace DisplayBinaryFile
  5. {
  6.     public class FILEID
  7.     {
  8.         #region Fields
  9.         public char[] ProgId = new char[26];
  10.         public char[] VerText = new char[4];
  11.         public char[] VerTextS = new char[14];
  12.         public byte[] DosChars = new byte[3];
  13.         public byte DBVer;
  14.         public bool Compressed;
  15.         public byte[] Filler = new byte[78];
  16.         public byte EndFileID;
  17.         #endregion
  18.  
  19.         public int Length { get; set; }
  20.  
  21.         public FILEID(byte[] buffer)
  22.         {
  23.             ProgId = Encoding.ASCII.GetChars(buffer.SubArray(0, 26));
  24.             VerText = Encoding.ASCII.GetChars(buffer.SubArray(26, 4));
  25.             VerTextS = Encoding.ASCII.GetChars(buffer.SubArray(30, 14));
  26.             DosChars = buffer.SubArray(44, 3);
  27.             DBVer = buffer.SubArray(47, 1)[0];
  28.             Compressed = BitConverter.ToBoolean(buffer.SubArray(48, 1), 0);
  29.             Filler = buffer.SubArray(49, 78);
  30.             EndFileID = buffer.SubArray(127, 1)[0];
  31.  
  32.             Length = 128;
  33.         }
  34.  
  35.         public byte[] GetBytes()
  36.         {
  37.             var returnValue = new byte[Length];
  38.  
  39.             Array.Copy(Encoding.ASCII.GetBytes(ProgId), 0, returnValue, 0, 26);
  40.             Array.Copy(Encoding.ASCII.GetBytes(VerText), 0, returnValue, 26, 4);
  41.             Array.Copy(Encoding.ASCII.GetBytes(VerTextS), 0, returnValue, 30, 14);
  42.             Array.Copy(DosChars, 0, returnValue, 44, 3);
  43.             Array.Copy(BitConverter.GetBytes(DBVer), 0, returnValue, 47, 1);
  44.             Array.Copy(BitConverter.GetBytes(Compressed), 0, returnValue, 48, 1);
  45.             Array.Copy(Filler, 0, returnValue, 49, 78);
  46.             Array.Copy(BitConverter.GetBytes(EndFileID), 0, returnValue, 127, 1);
  47.  
  48.             return returnValue;
  49.         }
  50.     }
  51. }

Here is a link to the entire Visual Studio 2010 project

In the last post, I introduced Intercom with an old example I wrote using VB6.  This post will be a much more modern example using C#.
I’ve also included a “Round Trip” example where the command is initiated via CC3.  By adding this small macro, you now have a command that draws a diamond on the screen.

Code Snippet
  1. MACRO DIAMOND
  2. GP TEMP ^DCenter:
  3. SENDM 2 TEMP
  4. ENDM

What this does is as the user to get a point (GP) and then send it via Intercom to the c# application.
Once it gets to the c# code, it takes the string from CC3 (all data sent from CC3 via Intercom is in strings), splits it on the comma and converts the two substrings into doubles.  Then it creates a command string and passes it back to CC3.

Code Snippet
  1. var strNumbers = System.Text.Encoding.ASCII.GetString(bytMsg).Split(‘,’);
  2. var x = double.Parse(strNumbers[0]);
  3. var y = double.Parse(strNumbers[1]);
  4. var strDiamond = “LINE \n” +
  5.                     (x – 100) + “,” + y + ” \n” +
  6.                     x + “,” + (y – 100) + ” \n” +
  7.                     (x + 100) + “,” + y + ” \n” +
  8.                     x + “,” + (y + 100) + ” \n” +
  9.                     (x – 100) + “,” + y + ” \n\n” +
  10.                     “ENDM”;
  11. icSendMsg(20, strDiamond);

Here is a link to the C# portion

As many of you know I’ve been heads down working on “Map Invoker”, a map auto generator, for awhile. In its first (hopefully of many) incarnation it generates random towns/cities.

One of the first hurdles was to somehow create an algorithm to create a realistic shape for a city and its walls. Well, the resulting algorithm created three circles. One fixed in the center of the map and two that had their centers randomly placed within the first circle.

Fine, I check marked that as done and went on to the next challenge.

Well, now I’m in parameterizing mode where I am pulling out all the hard coded numbers and placing them at the disposal of the user, and that lead me back to the Wall algorithm. Why just limit it to two circles? Why not five, or eight? Why not start with a square or turn the additional circles into squares – or a random mix of both?

With the right settings, all these parameters can create so cities that look amazingly natural. With the wrong settings you can create a city that … just looks weird. But, that is the purpose of allowing the users to tweak these parameters, is it not? Nobody wants a cookie-cutter city generator. If anyone is going to want to use a city generator, they want to be able to create a one-of-a-kind city that is all their own.

Then it’s just a matter of trying to name these parameters so that the user has an inkling of what they control. For the circle/square/mixed parameter – a slider, one side all circles, the other all squares and in the middle a mixture. What to call it? Wall Squareness? Wall Sharpness? Wall Roundness? Hmmm…

Hopefully no matter what the parameters are named, users will be able to deduce its effect.

Well, it looks like I’ve gotten most of the Wall generation parameterized. Here is an image of a large city (2000′ x 1600′ Template) with some of the “interesting” settings.

A large city generated by 'Map Invoker'

Note: This is a cross post.  The original is posted @ The CC3 Developer Blog

Wow, its been a while since I’ve written a post here.  The holidays are always a busy family blur.  Well, here is the latest installment …

The path/poly element is the most used element in CC3.  You really cannot get much done with it.  Try building anything in CC3 without it (Sure you can just use more primitive elements and use multipoly & group for joining and filling, but really you are just re-creating the path/poly element).  So if you want to get something done in an XP, odds are you are going to be working with paths/polys.

Continue reading »

As Simon mentioned in a  previous post here, I am working on an application, which I am developing under the code name “Map Invoker”. It will generate random towns, from small little hamlets to large walled cities. I’ve been concentrating on the algorithm side and am truely quite a ways towards a “feature complete” logic set.

So Simon was correct in stating that “He’s gone beyond proof of concept”. Soon I will be turning from generation to the interface so that all the parameters that I’ve included in the algorithms are exposed to the user so that the user can create an incredable range of different towns.

Once the parameter inputs are down and tested, then we will be looking into adding all the “garnish” that makes programs like this come alive.

So if you have any ideas, practical or “pie in the sky”, I’d love to here them. Either post your idea or email me at: SAUNDERL (at) HOTMAIL (dot) COM.