andybalaam / rabbit-escape

Android and PC game inspired by Lemmings and Pingus
http://artificialworlds.net/rabbit-escape
GNU General Public License v2.0
75 stars 42 forks source link

Solution syntax #120

Closed andybalaam closed 9 years ago

andybalaam commented 9 years ago

We plan to support specifying solutions and non-solutions inside levels.

The first use of this will be automated tests that check that all levels are soluble even when we change levels or the rules of the world. Other uses might include ensuring that easy "cheat" solutions are not possible, reporting bugs, demo mode, and unit tests.

Requirements:

Proposal: something like:

solution.1=20;dig;(2,3);5;bash&(4,5);(5,6);10;
solution_author.1=Andy Balaam
solution_url.1=blah

Translation:

Wait 20 time steps, then in the next time step select the dig ability, then in the next time step place the selected ability at co-ordinates 2,3.

Wait 5 time steps, then next time step do 2 things simultaneously: select the bash ability and place it at 4,5. In the next time step place another at 5,6.

Wait 10 time steps.

Syntax:

; - separates time steps
& - separates actions that both happen in the same time step (almost never use this!)
(x,y) - place the selected ability at co-ordinates x,y.
name_of_ability - select the named ability (same name as in the ability lines at the top of the level)
number - act as if the following semi-colon is actually as many semi-colons as number.
andybalaam commented 9 years ago

Related: #40

tttppp commented 9 years ago

Great idea! A few extra thoughts I had on this.

  1. I like the idea of supporting multiple solutions per file, but I'm not keen on the pseudo-structure created by linking the keys via the 1 (particularly in the author key). Perhaps a solution line could optionally contain the author and URL? Alternatively perhaps something like:

    solution.1=blah
    solution_author.1=blah
    solution_url.1=blah
  2. What does a non-solution look like? It needs to specify when the solution doesn't happen, otherwise I think you hit the halting problem! While it would be useful to include a solution to the halting problem in RabbitEscape, a first draft where we specify a maximum runtime might be useful.
  3. Rot13-ification: It would be annoying to see the published answer before getting to attempt a level. Another bonus of obfuscation of solutions is that it allows publishing levels containing a proof that they're possible, without giving away the solution. This would greatly encourage me to keep trying a level like #113, where I've become convinced that there's a typo in it.
colonelfazackerley commented 9 years ago

Good idea. I agree that seeing the solution would be a shame. Not sure rot13 would work to hide this. The ;(),0123456789 would not change.

Maybe put them in a separate file. File with the same name, but .res (rabbit escape solution) extension?

tttppp commented 9 years ago

Good point about the digits and punctuation. Maybe base64 encoded then? (Although I think Andy is fluent, so this might not be suitable.) Base64 encoded text is longer than unencoded, but this is a simple readily available encoding that obfuscates a large character set, so I think the extra few bytes isn't a big issue.

Further thought about non-solutions. The obvious format is to use the same as a solution - i.e. just specify some number of steps at the end to wait, and assert the level is not won at that point.

andybalaam commented 9 years ago

Updated to use : to separate simultaneous actions within the same time step. Disambiguates from the use of , to separate co-ordinates.

andybalaam commented 9 years ago

Added a note that the brackets around (x,y) could be optional.

andybalaam commented 9 years ago

@tttppp re 1 I share your distaste at linking in this way but don't want to over-engineer. I like the idea of the solution author and url in the same entry, except this will make very long lines, and URLs can contain lots of weird characters making parsing error-prone.

Given all this I'd go for your suggestion, unless we come up with something better:

solution.1=
solution_author.1=
solution_url.1=

Then we leave ourselves open to some kind of automatic-array-building based on numeric suffixes later, but for now we can treat these as opaque keys.

[If we did automatic array building later, it would be nice to upgrade the hints to use the same scheme. I now regret my "back to basics" approach of not including the dot in those.]

andybalaam commented 9 years ago

@tttppp re 2 a non-solution is a sequence of actions that results in a world state that is not solved. In theory we could try to provide more assertions e.g. "all rabbits are dead", but I think in practice this will normally be enough. For specific other cases we might just want to write unit tests.

andybalaam commented 9 years ago

@tttppp re 3 very strong point about providing a proof without giving away the solution. On the other hand, in the real level files we ship I'd like it to be as clear as possible, so probably we should support 2 formats.

How about:

solution.1=base64:MjA7ZGlnOygyLDMpOzU7YmFzaDooNCw1KTsoNSw2KTsxMDs=

Perhaps all level properties should support this optionally.

Bear in mind that my allergy to dependencies might mean we have to implement our own Base64 encoder, until we use Java 8: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html

andybalaam commented 9 years ago

Updated to use @tttppp's .1 format.

andybalaam commented 9 years ago

btw, in my mind everything everywhere is utf-8, and that includes the text that we encode to base 64.

Also btw, I am not fluent in base64, yet. I imagine after a few weeks of reading solutions we might be.

colonelfazackerley commented 9 years ago

https://en.wikipedia.org/wiki/Base64#Sample_Implementation_in_Java

should be simple to change to

:hint.1= 

I would prefer something like '_' to ':'. ':' is similar to ';' which makes it hard to read.

solution.1=20;dig;(2,3);5;bash_(4,5);(5,6);10;

I think brackets should be mandatory. This is hard to read becuase ';' is like ','

solution.1=20;dig;2,3;5;bash_4,5;5,6;10;
andybalaam commented 9 years ago

Good point about being hard to read. In the text UI I may make brackets optional, but in the solution format they can be mandatory.

How about | to separate 2 things that happen at the same instant? _ feels wrong somehow.

colonelfazackerley commented 9 years ago
solution.1=20;dig;(2,3);5;bash|(4,5);(5,6);10;
solution.1=20;dig;(2,3);5;bash&(4,5);(5,6);10;

Pipe is good. Another idea: ampersand. It reads nicely: equip bash and drop at (4,5).

andybalaam commented 9 years ago

Yes @GamingInky and I arrived at & independently over lunch today. I think it's Right.

BenjaminBalaam commented 9 years ago

yes @andybalaam thought because he doesn't like the & symbol he should make it that to show you shouldn't really use it normally.

andybalaam commented 9 years ago

Updated to use & and to make brackets non-optional.

tttppp commented 9 years ago

I have this mainly working, but it's a bit rough still. Sample solution lines are at the bottom of this unit test file: https://github.com/tttppp/rabbit-escape/blob/ecfce38ad70e0727d4d2f9be65201d234ca50f4d/rabbit-escape-engine/test/rabbitescape/engine/TestTextWorldManip.java

It currently only supports one solution per level, and doesn't allow for credits, but might be of use for checking the levels now we have the fixes that @colonelfazackerley has been making.

andybalaam commented 9 years ago

Silly me didn't mention we were working on it too. Anyway you're way ahead of us. I'll have a look but from the examples it looks perfect.

tttppp commented 9 years ago

I've started adding multiple solution support, but I'm accidentally reusing all the Collections that get passed into the world (I initially thought that creating a new world to test a solution against would be separation enough).

The solution syntax is going to be really hard to use without the solution recording feature. Maybe you could have a look how that can be done? (Particularly how should we output a recording to the player?)

If you wanted to work on the same bit though we could come up with a list of issues with the current implementation and work through them on a branch?

tttppp commented 9 years ago

Ok, I think the sandbox game is now actually sandboxed. Still need to test selecting and adding tokens that the user doesn't have any of, and generally find out how rabbit-escape exception handling works! Click recording is still a huge outstanding feature.

tttppp commented 9 years ago

Also it would be good for someone trying a level to know that at least one of the solutions is a victory solution. For example the following level has one non-solution, but no solution. If the solution is obfuscated then the player may be tricked into playing for a long time.

:num_rabbits=1
:bash=1
:solution.4=bash;(1,1);9;LOST
Q      
  # # O
#######
andybalaam commented 9 years ago

Ah, I was expecting non-solutions to look like:

:nonsolution.1=foo;bar

but I see your syntax elegantly allows us to avoid another key type.

For the reason you give, I wonder whether nonsolution key name is better. We could also just make Rabbit Escape be verbose enough when testing levels that you can see what is a solution or a non-solution.

andybalaam commented 9 years ago

Merged into a branch called solutionChecker, which I have pushed to github here: https://github.com/andybalaam/rabbit-escape/tree/solutionChecker

I see no reason not to merge this in and work on it in master, but will wait until @tttppp is happy.

andybalaam commented 9 years ago

I will add comments for changes I make here.

andybalaam commented 9 years ago

Somehow the line endings got messed up 81e576ec238245f9985a1b07b3127556855494da

andybalaam commented 9 years ago

Even thought I hate it, I needed to be able to compare Solutions and various kinds of Instruction: 3ccd6b0392e5275d1aa2f08a65e02936e1b9820a and 3eba6313e4e753c9d2effa2497e5a78bf692f28e

andybalaam commented 9 years ago

Unit tests for SolutionFactory ff582193fef6d6a93b1d78d4faea4f55969f2929

andybalaam commented 9 years ago

Simpler regular expression a2360fdd83a6b49af5ab1586cec6851ebba68734

andybalaam commented 9 years ago

Simpler regex for wait instructions, technically allowing waiting zero, but I think that's probably ok 4f83e637049c497946897cd60773333f0c02e3cc

andybalaam commented 9 years ago

Break out some of the horrible hoops Java requires you to make to check whether something is in an array into a Util method 19e42e00c18ab235ea60922b95f79a5bbad80b45

andybalaam commented 9 years ago

Use regex groups to find the place token co-ordinates 57b0a02f4644b7c38590b9156dddb2c98c6f887e

andybalaam commented 9 years ago

Test some error cases c3ea4b8b636844d7c1832d9458ae7f579629201f

andybalaam commented 9 years ago

Make the command line interface mostly work 5e10b4391e4551ecdc0e1e9d467335c1cf07fd41 c486debf751074c707b22080925930dd8dc17ed2 3a9cf7c38d99eb463a2d6c4468a0f980237d8bdd

andybalaam commented 9 years ago

Very primitive solution printing 203bbaf708220d1b2077052295a7089ed484f098

andybalaam commented 9 years ago

So we now have a way of authoring solutions: make runmenu, then solve the level. The solution is printed out above the "You won!" message.

tttppp commented 9 years ago

@andybalaam Happy to merge this to master now. I wanted to ensure that solutions could be added to the existing levels without breaking anything. I've just demonstrated this in a pull request (hopefully!)

Looking great with the ASCII interface and all your commits from last night. Did you get any sleep?! As well as printing steps above "You won!", I think we should print steps above "You lost!" for non-solutions.

I agree that by default the solution checking should be turned off (for built in levels), but I think it might be good to have it on for github/file level loading. If you agree then let's create a new enhancement ticket for it.

Also it would be good to add solution checking to the "round trip" test.

I think the only things left from this ticket are solution author and solution url.

andybalaam commented 9 years ago

Did you get any sleep?

I slept about 4.30 to 7.30

andybalaam commented 9 years ago

Happy to merge this to master now

Cool, I will do that as soon as I get a chance. Much better to be working on a single stream whenever possible.

andybalaam commented 9 years ago

I agree that by default the solution checking should be turned off (for built in levels), but I think it might be good to have it on for github/file level loading. If you agree then let's create a new enhancement ticket for it.

I agree.

andybalaam commented 9 years ago

Also it would be good to add solution checking to the "round trip" test.

Yes, I am working on that.

andybalaam commented 9 years ago

I think the only things left from this ticket are solution author and solution url.

This issue is massive - shall we break them into another one?

andybalaam commented 9 years ago

As well as printing steps above "You won!", I think we should print steps above "You lost!" for non-solutions.

It actually does - I just didn't describe it very well.

andybalaam commented 9 years ago

Checking all levels have solutions is #140

andybalaam commented 9 years ago

I managed to break the build with 1e7e87845818b60cd6b8b8aae20447a989025059 somehow - it needed a make clean test to see it for some reason. Sorry about that. I fixed it and merged into master.

andybalaam commented 9 years ago

Solution checking for external levels is #141

andybalaam commented 9 years ago

Closing since the remaining work has other issues (I think - correct me if I'm wrong).