I don't know what features you plan to add in the future, but in the current version, it is quite easy to write an algorithm which decides whether the level is winnable or not. You could implement this algorithm and run it after creating each level; if the level is unwinnable, throw it away and create a new one. Then, you would get a quite interesting roguelike, which one can lose only as their own fault.

The algorithm goes as follows: create a graph of all states, i.e. (player position, guard position, have card or not), and the level is winnable iff there is a path from the initial state to a final state, which you can check with any standard algorithm, for example BFS, which as a side result will also give you the smallest number of moves possible, so the final score could be based on how your number of moves compares to the best. Also it can be used for scoring lost games: after each time you could check whether the game is still winnable. And if from a position winnable in 20 steps you manage in 8 steps to get to a position winnable in 15 steps, but then you make an error and you can no longer win, you get a 5 out of 32 score on that level (5/8 * 5/20; 5/20 is the percentage of level completed and 5/8 is your effectiveness).