public int CountOfEntries(GameMemory zorkFile)
 {
     ByteAddress startOfDictionary = ptrToDictionary(zorkFile);
     int countSepCharacters = CountOfSeparatorCharacters(zorkFile);
     WordAddress ptrToEntryCount = new WordAddress(startOfDictionary.Value + 1 + countSepCharacters + 2);
     return zorkFile.ReadWord(ptrToEntryCount).Value;
 }
        public Word[] GetContentsOfNthEntry(int n, GameMemory zorkFile)
        {
            int entrySize =  GetEntrySizeInBytes(n, zorkFile);

            // I have been assuming that the above call will return 4, since that
            // is how many bytes are in a word entry. But it think this size
            // allows there to be arbitrary entries after all the words, and they might
            // be of up to this size.

            // Two questions:

            // 1. How do I know that we are in the size-regulated, has words-in-order
            // part of the dictionary?

            // 2. How do I know the size of the entries that are after the words,
            // in the arbitrary-sized part of the table?

            int entrySizeInWords = entrySize / 2;

            Word[] retval = new Word[entrySizeInWords];
            WordAddress ptrStartOfEntry = GetOffSetOfNthEntry(n, zorkFile);

            for(int i = 0; i < entrySizeInWords; i++)
            {
                WordAddress here = new WordAddress(ptrStartOfEntry.Value + (i * 2));
                retval[i] = zorkFile.ReadWord(here);
            }

            return retval;
        }
        public Word ReadWord(WordAddress address)
        {
            ByteAddress highByteAddress = Bits.AddressOfHighByte(address);
            ByteAddress lowByteAddress = Bits.AddressOfLowByte(address);
            byte high = ReadByte(highByteAddress);
            byte low = ReadByte(lowByteAddress);

            return new Word((256 * high) + low);
        }
 public static WordAddress AddressOfAbbreviationByNumber(AbbreviationNumber number, GameMemory memory)
 {
     AbbreviationTableBase basePtr = new AbbreviationTableBase(memory);
     WordAddress addressOfPtrToAbbrTable = new WordAddress(24);
     WordAddress ptrToAbbrevTable = new WordAddress(memory.ReadWord(addressOfPtrToAbbrTable).Value);
     WordAddress ptrToChosenAbbrv = ptrToAbbrevTable + (number.Value);
     WordAddress decompressedAbbrvPtr = new WordAddress(memory.ReadWord(ptrToChosenAbbrv).Value * 2);
     return decompressedAbbrvPtr;
 }
        static void Main(string[] args)
        {
            string pathToMiniZork = @"..\..\..\minizork.z3";
            GameMemory minizork = GameMemory.OpenFile(pathToMiniZork);

            //ReadDictionaryTillBreak(minizork);

            DictionaryHelper dictionary = new DictionaryHelper();

            Console.WriteLine($"Dictionary is expected to have {dictionary.CountOfEntries(minizork)} entries");
            string expectedFirst10EntriesString = "$ve . , #comm #rand #reco #unre \" a about";
            string[] expectedFirst10Entries = expectedFirst10EntriesString.Split(' ');

            List<string> nEntries = new List<string>();
            int n = 10;
            for(int i = 0; i < n; i++ )
            {
                string entry = dictionary.ReadNthEntry(i, minizork).Print;
                Console.WriteLine($"Expected: {expectedFirst10Entries[i]} but Found: {entry}");
            }

            WordAddress testText = new WordAddress(0xb106);
            IEnumerable<Zchar> story = Zchar.ReadWordsTillBreak(testText, minizork);
            char[] toPrint = Zchar.DecodeFromZString(story, minizork).ToArray();
            string printMe = new string(toPrint);
            Console.Write(printMe);

            TestMemoryBase();
            TestReadingAndWritingGameState();
            TestReadVersionNumberFromFile(pathToMiniZork);

            //TestBitTwiddling();

            //19 t 0d h 0a e 00 _ 05 ? 05 ?
            //1e y 14 o 1a u 17 r 00 _ 05 ?
            ReadFromAbbrTable(pathToMiniZork);

            Console.WriteLine("Now reading every abbreviation in order");

            for(int i = 0; i < 96; i++)
            {
                AbbreviationNumber num = new AbbreviationNumber(i);
                var zchars = Zchar.ReadAbbrevTillBreak(num, minizork);
                var normalChars = Zchar.DecodeFromZString(zchars, minizork, false)
                    .ToArray();
                Console.WriteLine($"Abbrev number {i} : {new string(normalChars)}");
            }

            Console.ReadKey();
        }
 public static List<Zchar> ReadStringFromAddress(WordAddress address, GameMemory memory)
 {
     throw new System.NotImplementedException();
     List<Zchar> retval = new List<Zchar>();
     Word word = memory.ReadWord(address);
     while(!word.IsTerminal())
     {
         //Zchar char1 = new Zchar(new AbbreviationNumber(Bits.FetchBits(BitNumber.Bit14, BitSize.Size5, word)));
         //Zchar char2 = new Zchar(new AbbreviationNumber(Bits.FetchBits(BitNumber.Bit9, BitSize.Size5, word)));
         //Zchar char3 = new Zchar(new AbbreviationNumber(Bits.FetchBits(BitNumber.Bit4, BitSize.Size5, word)));
         //retval.Add(char1);
         //retval.Add(char2);
         //retval.Add(char3);
         address = address + 1;
         word = memory.ReadWord(address);
     }
     return retval;
 }
 public DictionaryEntry(string print, WordAddress offset, int ix)
 {
     this.Print = print;
     this.OffsetIntoFile = offset;
     this.IndexIntoDictionary = ix;
 }
 public void WriteWord(WordAddress wordAddress, Word toWrite)
 {
     short bytes = toWrite.Value;
     byte high = (byte)((bytes >> 8) & 0xFF);
     byte low = (byte)(bytes & 0xFF);
     this.WriteByte(Bits.AddressOfHighByte(wordAddress), high);
     this.WriteByte(Bits.AddressOfLowByte(wordAddress), low);
 }
 public AbbreviationTableBase(GameMemory memory)
 {
     WordAddress addrOfTableBasePtr = new WordAddress(24);
     WordAddress addressOfTableBase = new WordAddress(memory.ReadWord(addrOfTableBasePtr).Value);
     this.value = addressOfTableBase.Value;
 }
 public static IEnumerable<char> YieldAbbreviationFromAbbreviationNumber(AbbreviationNumber number, GameMemory memory)
 {
     WordAddress addressOfPtrToAbbrTable = new WordAddress(24);
     WordAddress ptrToAbbrevTable = new WordAddress(memory.ReadWord(addressOfPtrToAbbrTable).Value);
     WordAddress address = AbbreviationTableBase.AddressOfAbbreviationByNumber(number, memory);
     Word word = memory.ReadWord(address);
     while (true)
     {
         char[] firstThree = Zchar.PrintWordAsZchars(word).ToCharArray();
         foreach (char ch in firstThree)
         {
             yield return ch;
         }
         if (word.IsTerminal())
         {
             yield break;
         }
         address = address + 1;
         word = memory.ReadWord(address);
     }
 }
 public static ByteAddress AddressOfLowByte(WordAddress address)
 {
     return new ByteAddress(address.Value + 1);
 }
 public static IEnumerable<Zchar> ReadAbbrevTillBreak(AbbreviationNumber num, GameMemory memory)
 {
     WordAddress addressOfPtrToAbbrTable = new WordAddress(24);
     WordAddress ptrToAbbrevTable = new WordAddress(memory.ReadWord(addressOfPtrToAbbrTable).Value);
     WordAddress ptrChosenAbbrev = AbbreviationTableBase.AddressOfAbbreviationByNumber(num, memory);
     return ReadWordsTillBreak(ptrChosenAbbrev, memory);
 }
        private static void ReadDictionaryTillBreak(GameMemory zorkFile)
        {
            DictionaryHelper dictionary = new DictionaryHelper();

            WordAddress startOfEntries = dictionary.GetOffSetOfNthEntry(0, zorkFile);
            WordAddress ptrFirstEntry = new WordAddress(startOfEntries.Value);

            var test = Zchar.ReadWordsTillBreak(ptrFirstEntry, zorkFile);
            char[] result = Zchar.DecodeFromZString(test, zorkFile, permitRecurse: false)
                .ToArray();

            Console.Write(new string(result));
        }
        private static void TestReadingAndWritingGameState()
        {
            string storyState = "Listen to a story 'bout a guy named Al";
            string interpreterState = "Who lived in the sewer with his hamster pal";
            int expectedImmutableSize = Encoding.UTF8.GetByteCount(storyState);
            byte[] immutablePart = Encoding.UTF8.GetBytes(storyState);
            int expectedDynamicSize = Encoding.UTF8.GetByteCount(interpreterState);
            byte[] dynamicPart = Encoding.UTF8.GetBytes(interpreterState);
            ImmutableByteWrapper changingPart = new ImmutableByteWrapper(dynamicPart);
            GameMemory gameState = new GameMemory(immutablePart, changingPart);

            WordAddress zeroPointer = new WordAddress(0);
            List<WordAddress> firstFivePointers = Enumerable.Range(0, 5)
                .Select(el => zeroPointer + el)
                .ToList();

            IEnumerable<ByteAddress> firstTenByteAddress = Enumerable.Range(0, 10)
                .Select(el => new ByteAddress(el));

            byte[] firstTenBytes = firstTenByteAddress
                .Select(p => gameState.ReadByte(p))
                .ToArray();

            byte[] firstFiveWords = firstFivePointers
                 .Select(p => gameState.ReadWord(p))
                 .SelectMany(word => new byte[] { (byte)(word.Value & 0xFF), (byte)((word.Value >> 8) & 0xFF) })
                 .ToArray();

            string firstFive = new string(Encoding.UTF8.GetChars(firstFiveWords));

            byte[] firstFiveTransposed = firstFivePointers
                .Select(p => gameState.ReadWord(p))
                .SelectMany(word => new byte[] { (byte)((word.Value >> 8) & 0xFF), (byte)(word.Value & 0xFF) })
                .ToArray();

            string firstFiveTransposedRead = new string(Encoding.UTF8.GetChars(firstFiveTransposed));

            string whatIRead = new String(Encoding.UTF8.GetChars(firstTenBytes));

            //test writing to game state:
            //replace "Who lived " with
            //        "zzCheese2 "
            byte[] toWrite = Encoding.UTF8.GetBytes("zzCheese2 ");
            System.Diagnostics.Debug.Assert(toWrite.Length == firstTenBytes.Length);

            Enumerable.Range(0, 10)
                .Select(el => new { address = new ByteAddress(el), val = toWrite[el] })
                .ToList()
                .ForEach(item => gameState.WriteByte(item.address, item.val));

            byte[] firstTenBytesAgain = firstTenByteAddress
                .Select(p => gameState.ReadByte(p))
                .ToArray();

            string mutated = new string(Encoding.UTF8.GetChars(firstTenBytesAgain));

            //test writing Words instead of bytes to game state:
            byte[] toWriteWordWise = Encoding.UTF8.GetBytes("aaZZeess33");
            WordAddress zero = new WordAddress(0);
            for(int i = 0; i < toWriteWordWise.Length - 1; i += 2)
            {
                int val = (toWriteWordWise[i] * 256 + toWriteWordWise[i + 1]);
                WordAddress address = zero + i / 2;
                gameState.WriteWord(address, new Word(val));
            }

            byte[] firstTenBytesAgain2 = firstTenByteAddress
                .Select(p => gameState.ReadByte(p))
                .ToArray();

            string mutated2 = new string(Encoding.UTF8.GetChars(firstTenBytesAgain2));

            Console.WriteLine($"{whatIRead} became {mutated} and then {mutated2}");
        }
        private static void ReadFromAbbrTable(string pathToMiniZork)
        {
            GameMemory minizork = GameMemory.OpenFile(pathToMiniZork);
            WordAddress addressOfPtrToAbbrTable = new WordAddress(24);
            WordAddress ptrToAbbrevTable = new WordAddress(minizork.ReadWord(addressOfPtrToAbbrTable).Value);
            WordAddress decompressedAddressOfFirstAbbreviation = new WordAddress(minizork.ReadWord(ptrToAbbrevTable).Value * 2);

            Word word = minizork.ReadWord(decompressedAddressOfFirstAbbreviation);
            int abbreviationLenght = 0;
            while (!word.IsTerminal())
            {
                abbreviationLenght++;
                Console.Write(Zchar.PrintWordAsZchars(word));
                word = minizork.ReadWord(decompressedAddressOfFirstAbbreviation + abbreviationLenght);
            }
            WordAddress secondAbbrev = AbbreviationTableBase.AddressOfAbbreviationByNumber(new AbbreviationNumber(1), minizork);
            List<Zchar> wholeSecondAbbrev = Zchar.ReadAbbrevTillBreak(new AbbreviationNumber(2), minizork).ToList();
            Console.WriteLine();
            word = minizork.ReadWord(secondAbbrev);
            int len = 0;
            string accumulator = "";
            accumulator += Zchar.PrintWordAsZchars(word);
            while (true)
            {
                len++;
                word = minizork.ReadWord(secondAbbrev + len);
                accumulator += Zchar.PrintWordAsZchars(word);
                if (word.IsTerminal()) break;
            }
            Console.WriteLine(accumulator);
        }
 public static IEnumerable<Zchar> ReadWordsTillBreak(WordAddress address, GameMemory memory, ISet<char> breakers = null)
 {
     while (true)
     {
         Word word = memory.ReadWord(address);
         Zchar low = new Zchar(Bits.FetchBits(BitNumber.Bit14, BitSize.Size5, word));
         Zchar mid = new Zchar(Bits.FetchBits(BitNumber.Bit9, BitSize.Size5, word));
         Zchar high = new Zchar(Bits.FetchBits(BitNumber.Bit4, BitSize.Size5, word));
         yield return low;
         yield return mid;
         yield return high;
         if (word.IsTerminal(breakers))
         {
             yield break;
         }
         address = address + 1;
     }
 }
 public static ByteAddress AddressOfHighByte(WordAddress address)
 {
     return new ByteAddress(address.Value);
 }