I had vague ideas about how to implement such an algorithm, but they were really vague and all involved starting with a blank sheet and then placing pairs of tiles until the 3D turtle shape was built up of the stacked tiles. So I set Charlie to the task of thinking about how to solve the problem of finding a solution. Next morning he presents me with the idea that it would be better to play the game forwards rather than backwards. That is to say, start with the turtle populated somehow, have the computer play the game by removing sets of tiles randomly until none were left, then using that configuration. He had a simple method worked out for mutating the values of the positions of tiles to map their "openness" or "closedness." You can only remove a tile if it is free on one side, left or right, and not covered by a tile above.
1=open left and right2=open left or right3=not open left and right, but open above4=not open left or right and above5=not open left and right and above
Then whenever you remove a tile you subtract one from the positions left or right and 2 from the position below to adjust their values. Then just solve the puzzle forward using blank tiles. You randomly select two free tiles (<3 tiles) and assign them a pair of tiles (1-36), then "remove" as per above. Repeat until you get to 0. If it runs into a block (which is relatively rare) where it can't find a final pair-- Restart. See lines 20-74 and 2000-2045: https://github.com/jggames/trs80mc10/blob/master/quicktype/Puzzle/Mahjong/NEWMAHJ12.TXT
I had done some research of my own and had come across a similar tip originally from the Stack Overflow coding site. Basically the author, Merlyn Morgan-Graham, suggested the same idea as Charlie, but he made it clear that what you do is start with a blank set of tiles in the turtle shape. He also provided insight into the problems you will face with this method, as occasionally you can end up with an odd number of tiles that are free (i.e. 1) and you will have to restart. His estimates for how often this happened were very helpful and encouraging.
Long story short, we got the algorithm to work and the initial version timed to just under 2 minutes for program setup and algorithm completion. Obviously, it took a little longer if the algorithm hit an uneven completion and had to restart. Just running the algorithm (not including program initialization) timed to just over a minute, but in subsequent re-writes I think I have got this down to just under a minute.
Lots of data had to be stored, including a 3 dimensional array (15 X 9 X 5) to store all the initial position data and openness data. Other info was also required such as top tile, and the current height of each stack. We made use of many 144 element long 2-dimensional arrays to store pointers to the x, y and z of the valid positions and the current tile type in those positions. 144 represents the total number of tiles (i.e. 4 of the 36 types of tile, or two sets of every tile type). Processing these 2-dimensional arrays was great for speed, but we did have some difficulties moving back and forth between references to these lists and the 3-dimensional space with the info about each tiles' openness.
So I had to really streamline and pare down my initial routines for generating the unique low res tile set I had worked out for the original game. I was able to store all the tile info in strings and then just use MID$ to get to any particular tile I needed. This was much better than my old version which stored tile detail in data statements and then constructed the strings in string memory.
So I had to really streamline and pare down my initial routines for generating the unique low res tile set I had worked out for the original game. I was able to store all the tile info in strings and then just use MID$ to get to any particular tile I needed. This was much better than my old version which stored tile detail in data statements and then constructed the strings in string memory.
I also added an undo feature that was lacking from the original, and since everything was pretty much stored in arrays already, a game save feature using the MC-10's CSAVE* command which allows you to easily save arrays to tape. Charlie's system of coding the open tile info also really sped up the searches for possible moves for the HELP/GAME OVER feature. In my old version every search required determining whether a tile was free by consulting its neighbours, instead of just storing this info permanently (and "mutate" the array every time you remove a tile as per Charlie's method). The help feature simply presents the open tile pairs a set at a time. If no such tiles exist, it presents the game over prompt.
So here's a video of me playing the new version:
As I mentioned, the algorithm has been speed up even further from this initial release. Here is a video of a speed test that indicates that even with initial program initialization you can be playing in just over a minute and a half:
Enjoy! The game can be played here. Choose the "Play Our Original Micro Color Basic Games" option, then select "MAHJONG" from the Cassette menu and type RUN:
No comments:
Post a Comment