I actually implemented this over a week ago, but I think it's interesting enough to warrant a post. So lets go...
Map generationI didn't think much about this beforehand and just created a grid of random characters, but it soon became apparent that this wasn't enough.
Character SelectionIt's a bad idea to start with all available characters, so I decided to restrict the characters to the home position for now. For German keyboards this means I have to choose one of these "asdfjklö" for every cell of the grid. Eventually the game will support multiple keyboard layouts (probably the big three English, French and German), until then you will see a lot of umlauts.
The code looks something like this:
for(var i=0; i<map.length; i++) {
var availableChars = 'asdfjklö';
var character = randomElement(availableChars);
[add character to map]
}
This approach is not very flexible, but good enough for now. When I will introduce additional characters or other keyboard layouts I will have to change it. I will probably store the characters and the probability they should appear in some kind of map.
Preventing duplicatesWhile testing often had the case that the same characters appeared multiple times in the cursor. Like this:
What should happen when the player presses 's', should the cursor move to the right or to the left? I planned to solve this problem by using some clever interface where the player would have to press the key multiple times to select the right one and then confirm using the space or enter key.
After thinking some more about it I decided to prevent this ambiguity from happening in the first place. At first I thought it would be really complicated and fantasized about backtracking and genetic algorithms, I also had a fever at the time which didn't really help...
Turns out the solution is pretty easy. I use the same algorithm as above but remove all characters from
availableChars that would lead to ambiguities. Here is the source:
for(var i=0; i<map.length; i++) {
var availableChars = 'asdfjklö';
// 1. get the illegal characters
var illegalChars = [
map.at(i).up().left().get('character'),
map.at(i).up().right().get('character'),
map.at(i).left().left().get('character'),
map.at(i).up().up().get('character')
];
// 2. remove them from the available characters
availableChars = _.difference(availableChars, illegalChars);
// 3. pick a random character
var character = randomElement(availableChars);
[add character to map]
}
I'm especially proud of implementing chaining for the direction operations, it makes the code so much easier to understand.
Here is an image which visualizes the four illegal cases:
That's it for this time.
Next: Implementing goals and a scoring system.