diff --git a/SpriteCompiler.Test/HeuristicTests.cs b/SpriteCompiler.Test/HeuristicTests.cs index e1e2d83..df177b0 100644 --- a/SpriteCompiler.Test/HeuristicTests.cs +++ b/SpriteCompiler.Test/HeuristicTests.cs @@ -22,12 +22,10 @@ namespace SpriteCompiler.Test // STA 3,s // PHA = 7 cycles - var state = new SpriteGeneratorState(new[] { new SpriteByte(0x11, 0), new SpriteByte(0x11, 3)}) - { - A = Register.Constant(0x0011), - S = Register.INITIAL_OFFSET, - P = SpriteGeneratorState.LONG_I - }; + var state = SpriteGeneratorState.Init(new[] { new SpriteByte(0x11, 0), new SpriteByte(0x11, 3)}); + state.A = Register.Constant(0x0011); + state.S = Register.INITIAL_OFFSET; + state.P = SpriteGeneratorState.LONG_I; var h = heuristic.Eval(state); diff --git a/SpriteCompiler.Test/MarioTests.cs b/SpriteCompiler.Test/MarioTests.cs index d59ab88..c7df24b 100644 --- a/SpriteCompiler.Test/MarioTests.cs +++ b/SpriteCompiler.Test/MarioTests.cs @@ -28,7 +28,7 @@ namespace SpriteCompiler.Test }; // Act : solve the problem - var solution = search.Search(problem, new SpriteGeneratorState(sprite)); + var solution = search.Search(problem, SpriteGeneratorState.Init(sprite)); // Assert : The initial state IS the goal state WriteOutSolution(solution); @@ -53,7 +53,7 @@ namespace SpriteCompiler.Test }; // Act : solve the problem - var solution = search.Search(problem, new SpriteGeneratorState(sprite)); + var solution = search.Search(problem, SpriteGeneratorState.Init(sprite)); // Assert : The initial state IS the goal state WriteOutSolution(solution); @@ -84,7 +84,7 @@ namespace SpriteCompiler.Test }; // Act : solve the problem - var solution = search.Search(problem, new SpriteGeneratorState(sprite)); + var solution = search.Search(problem, SpriteGeneratorState.Init(sprite)); // Assert : The initial state IS the goal state WriteOutSolution(solution); diff --git a/SpriteCompiler.Test/Tests.cs b/SpriteCompiler.Test/Tests.cs index 80b3eaf..f7feb96 100644 --- a/SpriteCompiler.Test/Tests.cs +++ b/SpriteCompiler.Test/Tests.cs @@ -35,7 +35,7 @@ namespace SpriteCompiler.Test var search = SpriteGeneratorSearchProblem.Create(); // Act : solve the problem - var solution = search.Search(problem, new SpriteGeneratorState(new byte[] { 0xAA })); + var solution = search.Search(problem, SpriteGeneratorState.Init(new byte[] { 0xAA })); // Assert // @@ -62,7 +62,7 @@ namespace SpriteCompiler.Test var search = SpriteGeneratorSearchProblem.Create(); // Act : solve the problem - var solution = search.Search(problem, new SpriteGeneratorState(new byte[] { 0xAA, 0x55 })); + var solution = search.Search(problem, SpriteGeneratorState.Init(new byte[] { 0xAA, 0x55 })); // Assert // @@ -87,7 +87,7 @@ namespace SpriteCompiler.Test var search = SpriteGeneratorSearchProblem.Create(); // Act : solve the problem - var solution = search.Search(problem, new SpriteGeneratorState(new byte[] { 0x11, 0x22, 0x22 })); + var solution = search.Search(problem, SpriteGeneratorState.Init(new byte[] { 0x11, 0x22, 0x22 })); // Assert // @@ -113,7 +113,7 @@ namespace SpriteCompiler.Test var search = SpriteGeneratorSearchProblem.Create(); // Act : solve the problem - var solution = search.Search(problem, new SpriteGeneratorState(new byte[] { 0xAA, 0x55, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 })); + var solution = search.Search(problem, SpriteGeneratorState.Init(new byte[] { 0xAA, 0x55, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 })); // Assert // diff --git a/SpriteCompiler/Problem/SpriteGeneratorState.cs b/SpriteCompiler/Problem/SpriteGeneratorState.cs index f184b68..caf4eb8 100644 --- a/SpriteCompiler/Problem/SpriteGeneratorState.cs +++ b/SpriteCompiler/Problem/SpriteGeneratorState.cs @@ -8,6 +8,20 @@ { // Single static reference to the original data set public static List DATASET = null; + public static IDictionary DATASET_BY_OFFSET = null; + + public static SpriteGeneratorState Init(IEnumerable bytes) + { + DATASET = bytes.ToList(); + DATASET_BY_OFFSET = DATASET.ToDictionary(x => (int)x.Offset, x => x); + + return new SpriteGeneratorState(); + } + + public static SpriteGeneratorState Init(IEnumerable bytes) + { + return Init(bytes.Select((x, i) => new SpriteByte(x, (ushort)i))); + } public SpriteGeneratorState() { diff --git a/SpriteCompiler/Problem/SpriteGeneratorSuccessorFunction.cs b/SpriteCompiler/Problem/SpriteGeneratorSuccessorFunction.cs index 892f515..eeb26d5 100644 --- a/SpriteCompiler/Problem/SpriteGeneratorSuccessorFunction.cs +++ b/SpriteCompiler/Problem/SpriteGeneratorSuccessorFunction.cs @@ -65,8 +65,9 @@ // // We always try to return actions that write data since that moves us toward the goal state - // Make it more convenient to get data by offset (this will probably be the representation of the state, eventually) - var bytes = state.Bytes.ToDictionary(x => x.Offset, x => x); + // Get the list of remaining bytes by removing the closed list from the global sprite + var open = SpriteGeneratorState.DATASET.Where(x => !state.Closed.Contains(x.Offset)).ToList(); + var bytes = open.ToDictionary(x => x.Offset, x => x); // Get the current byte and current word that exist at the current stack location var topByte = state.TryGetStackByte(bytes); @@ -112,23 +113,23 @@ // move to the first or last byte of each span. So , take the first byte and then look for any if (state.A.IsScreenOffset && !state.S.IsScreenOffset && state.LongA) { - for (var i = 0; i < state.Bytes.Count; i++) + for (var i = 0; i < open.Count; i++) { if (i == 0) { - yield return state.Apply(new MOVE_STACK(state.Bytes[i].Offset - state.A.Value)); + yield return state.Apply(new MOVE_STACK(open[i].Offset - state.A.Value)); continue; } - if (i == state.Bytes.Count - 1) + if (i == open.Count - 1) { - yield return state.Apply(new MOVE_STACK(state.Bytes[i].Offset - state.A.Value)); + yield return state.Apply(new MOVE_STACK(open[i].Offset - state.A.Value)); continue; } - if ((state.Bytes[i].Offset - state.Bytes[i-1].Offset) > 1) + if ((open[i].Offset - open[i - 1].Offset) > 1) { - yield return state.Apply(new MOVE_STACK(state.Bytes[i].Offset - state.A.Value)); + yield return state.Apply(new MOVE_STACK(open[i].Offset - state.A.Value)); } } } @@ -143,12 +144,11 @@ { var addr = state.S.Value; - // Look for consecutive bytes - var local = state.Bytes.Where(WithinRangeOf(addr, 257)).ToList(); // 16-bit value can extend to the 256th byte + // Look for consecutive bytes. The second byte can come from the DATASET + var local = open.Where(WithinRangeOf(addr, 256)).ToList(); var words = local - .Skip(1) - .Select((x, i) => new { High = x, Low = local[i] }) - .Where(p => p.Low.Offset == (p.High.Offset - 1)) + .Where(x => SpriteGeneratorState.DATASET_BY_OFFSET.ContainsKey(x.Offset + 1)) + .Select(x => new { Low = x, High = SpriteGeneratorState.DATASET_BY_OFFSET[x.Offset + 1] }) .ToList(); foreach (var word in words) @@ -177,7 +177,7 @@ var addr = state.S.Value; // We can LDA #$XX / STA X,s for any values within 256 bytes of the current address - foreach (var datum in state.Bytes.Where(WithinRangeOf(addr, 256))) + foreach (var datum in open.Where(WithinRangeOf(addr, 256))) { var offset = datum.Offset - addr; yield return state.Apply(new STACK_REL_8_BIT_IMMEDIATE_STORE(datum.Data, (byte)offset)); @@ -190,7 +190,7 @@ if (state.A.IsScreenOffset && state.S.IsScreenOffset && state.LongA) { var addr = state.S.Value; - foreach (var datum in state.Bytes.Where(x => (x.Offset - addr) > 255 || (x.Offset - addr) < 0)) + foreach (var datum in open.Where(x => (x.Offset - addr) > 255 || (x.Offset - addr) < 0)) { yield return state.Apply(new MOVE_STACK(datum.Offset - state.A.Value)); } diff --git a/SpriteCompiler/Program.cs b/SpriteCompiler/Program.cs index 020cfc7..cd9baf5 100644 --- a/SpriteCompiler/Program.cs +++ b/SpriteCompiler/Program.cs @@ -152,10 +152,11 @@ } } + // Set the global state var problem = SpriteGeneratorSearchProblem.CreateSearchProblem(); var search = SpriteGeneratorSearchProblem.Create(); - var solution = search.Search(problem, new SpriteGeneratorState(sprite)); + var solution = search.Search(problem, SpriteGeneratorState.Init(data)); WriteOutSolution(solution); }