/// <summary>
        /// Load DAT file and output with multiline comments
        /// </summary>
        /// <param name="pFile"></param>
        public static void SaveAsCommentedDat(string pFile)
        {
            string outputFileName = Path.GetFileNameWithoutExtension(pFile) + "_commented" + Path.GetExtension(pFile);


            using (StreamWriter sw = new StreamWriter(outputFileName))
            {
                DATToChunks.Load(pFile);

                var header = new GameHeader(DATToChunks.GetTokensAsInt(12));

                sw.WriteLine("{0} /*Unknown*/", header.Unknown);
                sw.WriteLine("{0} /*Number of items*/", header.NumItems - 1);
                sw.WriteLine("{0} /*Number of actions*/", header.NumActions - 1);
                sw.WriteLine("{0} /*Number of Noun Verbs*/", header.NumNounVerbs - 1);
                sw.WriteLine("{0} /*Number of Rooms*/", header.NumRooms - 1);
                sw.WriteLine("{0} /*Maximum carry*/", header.MaxCarry);
                sw.WriteLine("{0} /*Start room*/", header.StartRoom);
                sw.WriteLine("{0} /*Total treasures*/", header.TotalTreasures);
                sw.WriteLine("{0} /*Word length*/", header.WordLength);
                sw.WriteLine("{0} /*Light duration*/", header.LightDuration);
                sw.WriteLine("{0} /*Number of messages*/", header.NumMessages - 1);
                sw.WriteLine("{0} /*Treasure room*/", header.TreasureRoom);

                //produces an array of arrays
                var labels = new string[] { "/*NounVerb*/", "/*Condition1*/", "/*Condition2*/", "/*Condition3*/", "/*Condition4*/", "/*Condition5*/", "/*Actions 1 and 2*/", "/*Actions 3 and 4*/" };
                int ctr    = 1;
                foreach (var action in
                         Enumerable.Range(0, header.NumActions).Select(n => DATToChunks.getTokens(8).ToArray()).ToArray())
                {
                    sw.WriteLine("{0}\t\t\t/*Action index {1} - NounVerb*/", action.First(), ctr++);
                    for (int a = 1; a < 8; a++)
                    {
                        sw.WriteLine("{0}\t\t\t{1}", action[a], labels[a]);
                    }
                }

                int vb = 0, nn = 0, j = 0;
                foreach (var w in DATToChunks.getTokens(header.NumNounVerbs * 2))
                {
                    if (j == 0) //verb
                    {
                        if (!w.StartsWith("*"))
                        {
                            vb++;
                        }

                        sw.WriteLine("\"{0}\"\t\t{1}"
                                     , w
                                     , !w.StartsWith("*") ? string.Format("/*Verb index {0}*/", vb)
                                                 : string.Format("/*synonym of verb index {0}*/", vb)
                                     );
                    }
                    else if (j == 1)   //noun
                    {
                        if (!w.StartsWith("*"))
                        {
                            nn++;
                        }

                        sw.WriteLine("\"{0}\"\t\t{1}"
                                     , w
                                     , !w.StartsWith("*") ? string.Format("/*Noun index {0}*/", nn)
                                                 : string.Format("/*synonym of noun index {0}*/", nn)
                                     );
                    }

                    j++;
                    if (j > 1)
                    {
                        j = 0;
                    }
                }

                ctr = 0;
                string[] dire = { "/*North ", "/*South ", "/*East ", "/*West ", "/*Up ", "/*Down " };
                foreach (var room in Enumerable.Range(0, header.NumRooms).Select(n => DATToChunks.getTokens(7).ToArray()))
                {
                    for (int q = 0; q < 6; q++)
                    {
                        sw.WriteLine("{0}\t{1}{2}*/", room[q], dire[q], room[q] == "0" ? " - not used" : " - links to room " + room[q]);
                    }

                    sw.WriteLine("\"{0}\" /*Room {1} Description*/", room.Last(), ctr++);
                }

                ctr = 0;

                foreach (var message in DATToChunks.getTokens(header.NumMessages))
                {
                    sw.WriteLine("\"{0}\" /*Message {1}*/", message, ctr++);
                }


                ctr = 0;
                foreach (var item in Enumerable.Range(0, header.NumItems).Select(n => DATToChunks.getTokens(2).ToArray()))
                {
                    sw.WriteLine("\"{0}\" /*Item {1} Description*/ {2} /*Location*/", item.First(), ctr++, item.Last());
                }

                ctr = 0;
                foreach (var actionMessage in DATToChunks.getTokens(header.NumActions))
                {
                    sw.WriteLine("\"{0}\" /*Action {1} description*/", actionMessage, ctr++);
                }

                var footer = new GameFooter(DATToChunks.GetTokensAsInt(3));

                sw.WriteLine("{0} /*Version number*/", footer.Version);
                sw.WriteLine("{0} /*Adventure number*/", footer.AdventureNumber);
                sw.WriteLine("{0} /*Unknown*/", footer.Unknown);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Load the adventure game from the provided dat file
        /// </summary>
        /// <param name="pFile"></param>
        /// <returns>Game data class</returns>
        public static GameData Load(string pFile)
        {
            string[] directionsLong = { "North", "South", "East", "West", "Up", "Down" };
            int      VERB_TAKE      = 10;
            int      VERB_DROP      = 18;

            GameData gd = new GameData();

            DATToChunks.Load(pFile);

            int[] header = DATToChunks.GetTokensAsInt(12);

            gd.Header      = new GameHeader(header);
            gd.Verbs       = new string[gd.Header.NumNounVerbs];
            gd.Nouns       = new string[gd.Header.NumNounVerbs];
            gd.Rooms       = new Room[gd.Header.NumRooms];
            gd.Messages    = new string[gd.Header.NumMessages];
            gd.Items       = new Item[gd.Header.NumItems];
            gd.GameName    = pFile;
            gd.CurrentRoom = gd.Header.StartRoom;
            gd.LampLife    = gd.Header.LightDuration;

            int ctr = 0;

            List <Action> Actions = new List <Action>();

            #region Actions

            for (ctr = 0; ctr < gd.Header.NumActions; ctr++)
            {
                Actions.Add(new Action(DATToChunks.GetTokensAsInt(8)));
            }

            #endregion

            #region Words

            /*
             * An interleaved list of verb/noun that begins
             * with the entries "AUT" and "ANY" that we skip
             *
             * An entry beginning with a star is a synonym of the first
             * preceeding word that doesn't begin with a star
             */

            int      v    = 0;
            int      n    = 0;
            string[] word = DATToChunks.getTokens(gd.Header.NumNounVerbs * 2);

            for (ctr = 0 /*SKIP*/; ctr < word.Count(); ctr++)
            {
                if (ctr % 2 == 0)
                {
                    gd.Verbs[v] = word[ctr];

                    if (gd.Verbs[v].StartsWith("*") & gd.Verbs[v].Length > (gd.Header.WordLength + 1))
                    {
                        gd.Verbs[v] = gd.Verbs[v].Substring(0, gd.Header.WordLength + 1);
                    }
                    else if (!gd.Verbs[v].StartsWith("*") & gd.Verbs[v].StartsWith("*") && word[ctr].Length > gd.Header.WordLength)
                    {
                        gd.Verbs[v] = gd.Verbs[v].Substring(0, gd.Header.WordLength);
                    }

                    v++;
                }
                else
                {
                    gd.Nouns[n] = word[ctr];

                    if (gd.Nouns[n].StartsWith("*") & gd.Nouns[n].Length > (gd.Header.WordLength + 1))
                    {
                        gd.Nouns[n] = gd.Nouns[n].Substring(0, gd.Header.WordLength + 1);
                    }
                    else if (!gd.Nouns[n].StartsWith("*") & word[ctr].Length > gd.Header.WordLength)
                    {
                        gd.Nouns[n] = gd.Nouns[n].Substring(0, gd.Header.WordLength);
                    }

                    n++;
                }
            }

            #endregion

            #region Rooms

            for (ctr = 0; ctr < gd.Rooms.Length; ctr++)
            {
                gd.Rooms[ctr] = new Room(DATToChunks.GetTokensAsInt(6), DATToChunks.getTokens(1).First());


                gd.Rooms[ctr].Description += Environment.NewLine + Environment.NewLine + _ObviousExits;

                if (gd.Rooms[ctr].Exits.Count(e => e > 0) > 0)
                {
                    gd.Rooms[ctr].Description +=
                        gd.Rooms[ctr].Exits
                        .Select((val, ind) => new { val, ind })
                        .Where(i => i.val > 0)
                        .Select(i => directionsLong[i.ind])
                        .Aggregate((current, next) => current + ", " + next);
                }
                else
                {
                    gd.Rooms[ctr].Description += _None; //none
                }
            }

            #endregion

            #region Build Game Messages

            gd.Messages = DATToChunks.getTokens(gd.Messages.Length);

            #endregion

            #region Items

            for (ctr = 0; ctr < gd.Items.Length; ctr++)
            {
                gd.Items[ctr] = new Item(DATToChunks.getTokens(1).First(), DATToChunks.GetTokensAsInt(1).First());
            }

            #endregion

            #region Add any comments to actions

            for (ctr = 0; ctr < gd.Header.NumActions; ctr++)
            {
                Actions[ctr].Comment = DATToChunks.getTokens(1).First();
            }

            #endregion

            #region Generate get/drop actions for items that can be carried

            for (int itemCtr = 0; itemCtr < gd.Items.Count(); itemCtr++)
            {
                if (gd.Items[itemCtr].Word != null)
                {
                    Actions.Add
                    (
                        new Action()
                    {
                        Comment = "Autotake for " + gd.Items[itemCtr].Description
                        ,
                        Verb = VERB_TAKE
                        ,
                        Noun = gd.Nouns.TakeWhile(nn => nn != gd.Items[itemCtr].Word).Count()
                        ,
                        Conditions = new int[][] { new int[] { 2, itemCtr } }
                        ,
                        Effects = new int[][] { new int[] { 52, itemCtr, 0 } }
                    }
                    );

                    Actions.Add
                    (
                        new Action()
                    {
                        Comment = "Autodrop for " + gd.Items[itemCtr].Description
                        ,
                        Verb = VERB_DROP
                        ,
                        Noun = gd.Nouns.TakeWhile(nn => nn != gd.Items[itemCtr].Word).Count()
                        ,
                        Conditions = new int[][] { new int[] { 1, itemCtr } }
                        ,
                        Effects = new int[][] { new int[] { 53, itemCtr, 0 } }
                    }
                    );
                }
            }

            #endregion

            //      Child action processing

            //      All actions that follow an action with a component 73 are noun == 0 && verb == 0
            //      and are the children of that action. This method moves them into a array of
            //      their parent
            //      e.g 157 in Adv01.dat
            List <Action> childs = null;
            for (int i = Actions.Count() - 1; i >= 0; i--)
            {
                if (Actions[i].Effects.Count(act => act[0] == 73) > 0)
                {
                    int j = i + 1;
                    childs = new List <Action>();
                    while (Actions[j].Verb == 0 && Actions[j].Noun == 0)
                    {
                        childs.Add(Actions[j]);
                        j++;
                    }

                    Actions[i].Children = childs.ToArray();
                    Actions.RemoveRange(i + 1, childs.Count());
                }
            }

            /*
             * Claymorgue castle fix
             *
             * Action 148 has no conditions and a noun and a verb of 0,
             * and follows a user tiggered action. This particular set of
             * conditions only occurs in Claymorgue and none of the other 13
             * adventures. I think that when this set of conditions occurs,
             * the latter action should be treated as a child of the former,
             *  and would require some special treatment when the DAT file is loaded.
             */
            Action ac;
            for (var i = 1; i < Actions.Count(); i++)
            {
                ac = Actions[i];

                if (
                    Actions[i].Conditions.Length == 0 &&
                    Actions[i].Effects.Length > 0 &&
                    Actions[i].Verb == 0 &&
                    Actions[i].Noun == 0 &&
                    Actions[i - 1].Verb > 0
                    )
                {
                    Actions[i - 1].Children =
                        new Action[] { Actions[i] };

                    Actions[i] = null;
                }
            }

            //If words aren't present for SAV GAM add them
            //for adv06, 07, 09, 10, 11, 12, 13, 14a
            #region Add save game

            if (!gd.Nouns.Contains("GAM") && !gd.Verbs.Contains("SAV"))
            {
                Array.Resize(ref gd.Nouns, gd.Nouns.Length + 1);
                gd.Nouns[gd.Nouns.Length - 1] = "GAM";

                Array.Resize(ref gd.Verbs, gd.Verbs.Length + 1);
                gd.Verbs[gd.Verbs.Length - 1] = "SAV";

                Actions.Add(
                    new Action(
                        new int[]
                {
                    (gd.Verbs.Length - 1) * 150 //verb
                    + (gd.Nouns.Length - 1)     //noun
                    , 0                         //condition 1
                    , 0                         //condition 2
                    , 0                         //condition 3
                    , 0                         //condition 4
                    , 0                         //condition 5
                    , 71 * 150
                    , 0
                }
                        )
                    );
            }

            #endregion

            gd.Actions = Actions.Where(a => a != null).ToArray();

            gd.Footer = new GameFooter(DATToChunks.GetTokensAsInt(3));


            return(gd);
        }