Note: The following full answer expands on the previous partial answer, which has been retained below.
Full answer
To analyze all the possible states, the algorithm Ken Thompson described in his 1986 paper Retrograde Analysis of Certain Endgames, which was used to develop some of the earliest chess endgame tablebases, was adapted for this question. His method starts at known winning positions and moves backward in time ("unmoves") to predecessor positions. Those positions are analyzed and the ones that always lead to defeat are added to the list of losing positions. Then new predecessor positions of the losing positions are analyzed. This continues until there are no new predecessors.
At the end of the analysis, either all possible positions have been added to the list of losing positions and a win is guaranteed with optimal play, or there is a subset of non-losing positions that can be leveraged to defend against a win.
Analysis of Lions and Zebras on a Chess Board leads to the conclusion that...
In the jungle, the mighty jungle, the lion eats tonight...
An optimal lion wins from every possible game position. Against optimal zebras each, the lion slightly improves with each move until his opponents run out of defenses. This takes 16 moves at most.
Lion eats in 16
This is a typical best-case setup for the zebras. They are arrayed in the corners and the lion lacks any immediate threatening moves. But even if the zebras could dictate the lion's first move, it would offer them no advantage. All the lion's initial moves lead to a captured zebra in 16 moves.
Since the state space is too large to present a full analysis for the tens of billions of positions, the following analysis has been limited to this position. Further, it only looks at lines where the lion chooses Nd1 as his first move. It produces a number interesting lines that demonstrate the strategies without having an unmanageable number of variations.
Interestingly, in responding to Nd1, despite a plethora of options, the zebras only have two optimal replies: Bab8 and Bab1. Anything else results in earlier capture.
Analysis of the lines starting at this position are given in PGN format. Given the non-standard rules of the game, not all PGN viewers can handle them. But, as of this writing, the PGN viewer on chess.com works. (Choose Load PGN and paste in the PGN.). Zebra moves are annotated for only optimal move: '!'; suboptimal move: '?'; or highly suboptimal move: '??'.
1... Nd1 2. Bab8
In moves 3 to 11, the zebras maintain their defensive posture by occupying the corners. But they only have one optimal move at each turn. On move 12, the zebras finally two options Bab6 or Bab2, but either one forces the abandoment of the corners. Either way, the lion continues with b4, then c2, and on move 14 the a1 zebra then has four choices: b2, c3, e5, or f6. The lion continues to e3 and then no matter which of the eight combinations of moves the zebras chose on 12 and 14, the lion forks them on move 15.
[FEN "B6B/B6B/8/8/8/8/Bn5B/B6B b - - 0 1"]
[SetUp "1"] 1... Nd1 2. Bab8 Nf2 3. Bhg2! Ng4 4. Bg1! Nf6 5. Bhb1! Nd5 6. Bh7! Nb6 7. Bab7! Nd7 8. Bba7! Nf8 9. Bhg8! Ng6 10. Bhg7! Ne7 11. Bh7! Nc6 12. Bab6 Nb4 13. Bf7 Nc2 14. Bab2 Ne3 15. Bh1 Nc4 16. Ba1 Nxb6
1... Nd1 2. Bab1
The lion leaves the zebras with only a single optimal choice on moves 3 to 10. Unlike the Bab8 line, this line requires early abandonment of the corners. The zebras are finally afforded a choice on move 11, either Bc8 or Be8. But the table is already set and Nf7 forces Bhb2. The lion then threatens one zebra after another until he finally captures the a1 zebra trapped on move 12.
The amazing thing about this line is that if the zebras play optimally the lion could play blind. In optimal play, the lion can use these same moves starting at move 2 and he will always capture the zebra on a1 on move 16.
[FEN "B6B/B6B/8/8/8/8/Bn5B/B6B b - - 0 1"]
[SetUp "1"] 1... Nd1 2. Bab1 Nc3 3. Bbc2! Ne4 4. Bb1! Nf6 5. Bhf5! Ng4 6. Bhg1! Nf2 7. Bhg2! Nh3 8. Bh2! Ng5 9. Bd7! Nf3 10. Bg3! Ne5 11. Bc8 Nf7 12. Bhb2! Nd6 13. Bch3! Nb5 14. Bg1 Na3 15. Ba2 Nc2 16. Bh8 Nxa1
Other variations
The following lines show the optimal lion strategy to reach a win in five moves. The starting position is after 1... Nd1. Reviewing with a PGN viewer is recommended since there are many subvariations, and many of those deeply nested lines.
Bab8
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bab8 Nf2 3. Bhg2! (3. Bhf3?? Ng4 4. Bg1! (4. Bhg3? Nf6) 4... Nf6 5. Bf5! (5. Bc2? Nd7) 5... Nd5 6. Bh7! Nc3) (3. Bhc6?? Ng4 4. Bg1! Nf6) 3... Ng4 4. Bg1! (4. Bhg3?? Nf6 5. Bc2 {or Bf5} Nd7 6. Ba7! Nb6) 4... Nf6 5. Bhb1! (5. Bc2? {or Bd3?} Nd7 6. Bba7! Ne5 7. Bh7! Nc6 8. Bac5 (8. Bab6 Nb4 9. Bab1 {or Bb3} Nc2) 8... Nb4 9. Bab1 {or Bb3/Bag8} Nc2) (5. Bg6? Nd7 6. Bba7! Ne5 7. Bh7! (7. Be8? Nc6) 7... Nc6 8. Bac5 (8. Bab6 Nb4 9. Bab1 {or Bb3} Nc2) 8... Nb4 9. Bab1 {or Bb3/Bag8} Nc2) (5. Bf5?? Nd7 6. Bba7! Nb6) 5... Nd5 6. Bh7! (6. Bb3?? Nb6) 6... Nb6 7. Bab7! (7. Bac6?? Nd7 8. Bba7! Nf6) 7... Nd7 8. Bba7! (8. Bd6?? Nf6) 8... Nf8 9. Bhg8! (9. Bc2? Ng6 10. Bhg7! Nf4) 9... Ng6 10. Bhg7! (10. Bhf6? Nf4) 10... Ne7 11. Bh7! Nc6
Bab1
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bab1 Nc3 3. Bbc2! (3. Bbg6?? Ne4 4. Bg8! Ng3 5. Bhf3! Nf5 6. Bgh5! Ne3 7. Ba2! Nc2) (3. Bbd3?? Nb5 4. Bab8! (4. Bag1? {or Be3?} Nd4) (4. Bf2? {or Bb6?} Nc7) 4... Nc7 5. Baf3! Na6 6. Ba7! Nc5) (3. Bbf5?? Ne4 4. Bc8! Nf2 5. Bhg2 {or Bhf3} (5. Bhc6 Ne4 6. Ba6! Ng5) 5... Ng4 6. Bhg1 (6. Bg3 Ne3) 6... Nf6) 3... Ne4 4. Bb1! (4. Bb3? Ng5 5. Bhg8! (5. Bg6?? Nf7) 5... Nf7 6. Bhg7! (6. Bhc3? Ne5 7. Ba2! Nf3) 6... Nh6 7. Bh7! Ng4 8. Bhg1 (8. Bhb8 Nf6 9. Bb1 (9. Bg6 Nd5) 9... Ne4) 8... Nf2 9. Bhg2! Nh3) (4. Ba4?? Nd6 5. Bd1 (5. Bac2 Nf7 6. Bhf6! Ng5 7. Bg8! (7. Bhg6? Nf3) 7... Nf3 8. Bg3! Nd4) (5. Bf2 Nf7 6. Bhg7! Ng5 7. Bg8! (7. Bg6? Nf3) 7... Ne4 8. Bfg1 (8. Ba7 Ng3) 8... Nf2) (5. Bb8 Nf7 6. Bhg7! (6. Bhc3? Ne5) 6... Ng5 7. Bb1! (7. Bg8? Nf3) 7... Ne6 8. Bh8! Nc7) (5. Bb3? Nf7 6. Bhf6! Ng5 7. Bg6 {or Bhg8} Nf3) (5. B8c6?? {or B4c6??} Nf7) 5... Nc8 6. Bag1! (6. Bf2? {or Be3?/B7d4?/Bc5?/Bab8?} Nb6) 6... Nb6 7. Bab7! Nd7 8. Bc7! Nc5) (4. Bhg1?? Nf2 5. Bhg2! (5. Bhd5? {or Bhb7?} Nh3 6. Bh2! Ng5) (5. Bhc6? Nh3) 5... Nh3 6. Bgc5! (6. Bgb6? Ng5) 6... Nf4 7. Bh1! Ng6) (4. Bb7?? Ng5 5. Bg8! (5. Bhg6? Nf7) 5... Nf7 6. Bhg7! Nd6 7. Ba8! Nc8) (4. Bg8?? Nf2 5. Bhf3 (5. Bhc6 Ng4 6. Bhg1! Nf6) 5... Ng4 6. Bhg1! Nh6) (4. Bab8?? Nf2 5. Bhf3! Ng4 6. Bg1 {or Bhg3} Nf6) (4. Bf4?? Nf2 5. Bhb7! Ne4) (4. Bc7?? Ng3 5. Bhg2! Nf5) (4. Bhb8?? Ng5 5. Bg8! Nf7) (4. Bb6?? {or Bg6??/Bab2??} Nf2) 4... Nf6 5. Bhf5! (5. Bhg6? Ng4 6. Bhg1! (6. Bg3?? Nf2 7. Bhg2! Ne4) (6. Bc7?? Ne5 7. Bh5 (7. Bh7 Nf7) 7... Ng6) 6... Nf2 7. Bhf3! (7. Bhc6? Ne4 8. Bh5 (8. Bc2 Nd2 9. Bh1! Nb3) (8. Bh7? {or Ba2?} Nc3) 8... Nd2 9. Ba2! Nb3) (7. Bhb7? Nh3 8. Bh2! Nf4 9. Bh7! Ng6) 7... Ne4 8. Bh1! (8. Bc2? Nd2 9. Bh1! Nb3) (8. Ba2? Nc3) 8... Ng3 9. Bhf3! Ne2 10. Bgf2 {or Bh2} Nc3) (5. Bhc2?? Ne4 6. Ba2! Nf2) 5... Ng4 6. Bhg1! (6. Bhb8? Ne5 7. Bg1! (7. Bf2? Nd7 8. Bh2 (8. Bba7 {or Bc7} Nb6) 8... Ne5) 7... Nf3 8. Bb6! Nd2 9. Ba2! Nb3) (6. Bg3?? Nf2 7. Bhg2! Ne4) (6. Bf4?? Ne5 7. Bg3! Ng6) 6... Nf2 7. Bhg2! (7. Bhf3?? Nh3 8. Bh2! Ng1) (7. Bhd5?? Nd1 8. Bg8! Nc3) (7. Bhc6?? Ne4 8. Bh3 {or Bh7} Nc3) 7... Nh3 8. Bh2! (8. Bgc5? Nf4 9. Bh1! Ne2) (8. Bge3?? Ng5) 8... Ng5 9. Bd7! (9. Bc8? Nf7 10. Bhf6 {or Bhg7} Nd6) (9. Bg3? Ne4) (9. Bhb8? Nf7) 9... Nf3 10. Bg3! Ne5 11. Bc8 {or Be8} Nf7
Bag1?
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bag1? Nf2 3. Bhg2! (3. Bhc6?? Ng4 4. Bb8! Nf6) 3... Nh3 4. Ba7! (4. Bc5? Ng5 5. Bhg8! Nf3 6. Bg3! Nd4 7. Ba7! Nc6) (4. Bb6?? Ng5 5. Bhb1 (5. Bhg8 Nf7 6. Bhg7! Nh6) 5... Nf3 6. Bg3 (6. Bb8 Ne5) 6... Ne1) 4... Ng5 5. Bhg8! (5. Bhb1? Nf3 6. Bg3! Nh4 7. Bf1 {or Bh1} Ng6 8. Bhg7! Nf4) 5... Nf3 6. Bg3 (6. Bc7 Nd4 7. Bh2! (7. Bg3? Nc6) 7... Nc6 8. Bc5 {or Bb6} Nb4 9. Bb1 {or Bab3} Nc2) 6... Nh4 7. Bh1! (7. Bf1? Ng6 8. Bhc3 {or Bhf6} Ne7) (7. Bh3? {or Bge4?} Ng6) 7... Ng6 8. Bhc3 (8. Bhf6 Ne7 9. Bh7! Nc8) 8... Ne7 9. Bh7! Nc6
Bhg1?
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bhg1? Nf2 3. Bhg2! (3. Bhd5?? Ne4 4. Bdc4! (4. Bdc6? Nf6) 4... Ng5 5. Bhg8! Nf3 6. Bgf2! Nd2) (3. Bhc6?? Ne4 4. Bb1 {or Bg6/Bhg7/Bhg8} (4. Bb8 {or Bh2} Nf6) 4... Nc3) (3. Bhb7?? Ne4 4. Bc6 {or Bc8} Nf6) 3... Nh3 4. Bh2! (4. Bgb6? Ng5 5. Bhg8! Nf7 6. Bhg7! (6. Bhf6? Nh6) 6... Nh6 7. Bh7! Nf5) (4. Bge3?? Ng5 5. Bhg8! (5. Bhb1? Ne4) 5... Nf7 6. Bhc3! Nh6) (4. Bgd4?? Ng5 5. Bhg8! Nf7) (4. Bgc5?? Nf4 5. Bf1 {or Bh1} Ng6) 4... Ng5 5. Bhg8! (5. Bhb1? Nf3 6. Bg3! Nh4 7. Bf1 {or Bh1} Ng6 8. Bhg7! Nf4) 5... Nf3 6. Bg3 (6. Bc7 Nd4 7. Bh2! (7. Bg3? Nc6) 7... Nc6 8. Bc5 {or Bb6} Nb4 9. Bb1 {or Bab3} Nc2) 6... Nh4 7. Bh1! (7. Bf1? Ng6 8. Bhc3 {or Bhf6} Ne7) (7. Bh3? {or Bge4?} Ng6) 7... Ng6 8. Bhc3 (8. Bhf6 Ne7 9. Bh7! Nc8) 8... Ne7 9. Bh7! Nc6
Bab7?
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bab7? Nf2 3. Bhg2! (3. Bhf3? Ng4 4. Bhg1! (4. Bg3?? Nf6) 4... Nf6 5. Bg6! (5. Bc2? Nd5 6. Bh7! Nc3) 5... Ne4 6. Bh1! (6. Bgh5? {or Ba8?} Nc3) (6. Ba6? Nd2) 6... Ng3 7. Bhf3! Ne2 8. Bh2! Nc1) (3. Bhc6?? Ne4 4. Ba8! Nf6) 3... Ng4 4. Bhg1! (4. Bg3?? Nf6) 4... Ne3 5. Bh1! (5. Bh3?? Nc2 6. Baf6! Na3) (5. Bgf3?? {or Bge4??} Nc2) 5... Nc2 6. Bac3! (6. Bab2? Nb4 7. Bab1 {or Bag8} Nc6) (6. Baf6? Nb4 7. Bab1! Nc6) 6... Nb4 7. Bab1! Nc6 8. Bab6! Na5 9. Ba6 {or Ba8} Nc4
Bhg8?
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bhg8? Nc3 3. Bac4! (3. Bab3? Nb5 4. Bab8! (4. Bf2?? Nd4 5. Ba2 {or Ba4} Nc2) (4. Bb6?? Nc7 5. Bab7! Nd5) 4... Nc7 5. Bac6! (5. Bag2? Nd5 6. Bf7! Nf4 7. Ba8! Ng6) (5. Baf3? Nd5 6. Bf7 (6. Ba4 Ne7 7. Bh7! Ng6) (6. Ba2? {or Bh7?} Nf6) 6... Ne7 7. Ba8! Ng6) 5... Nd5 6. Ba8! (6. Bf7? Ne7 7. Ba8! Ng6) (6. Bh7? Nf6) 6... Nb6 7. Bac6! Nd7 8. Ba7 {or Bbc7} Nf6) (3. Baf7?? Nd5 4. Bh7! Nc7) 3... Nb5 4. Bab8! (4. Bag1? Nd4 5. Bb8! (5. Bc7? Ne2 6. Bf2 {or Bgh2} (6. Ba7 Nd4) 6... Ng3) 5... Nc6 6. Bg3! Ne7 7. Bh7! Ng6) (4. Bc5?? Nd4 5. Bb6! Nc2) (4. Bb6?? Nc7 5. Bab7! Nd5) 4... Nc7 5. Bab7! (5. Baf3?? Nd5 6. Ba2 {or Ba6} Nf6) (5. Bae4?? Nd5 6. Bb1! Nf6) (5. Bac6?? Nd5 6. B6b5! Nf6) 5... Na6 6. Ba7! (6. Bbf4? Nc5 7. Ba8! Nb3) (6. Bbd6?? Nb4) 6... Nb4 7. Be2! (7. Bf1? Nc2 8. Bab2 {or Bac3} Ne3) (7. Bag1? {or Bb6?} Nc2) 7... Nc6 8. Bb6! Nd4 9. Bd1 {or Bf1} Nc2
Bb3?
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bb3? Nf2 3. Bhg2! (3. Bhf3? Ng4 4. Bhg1! Nf6 5. Bg6! (5. Bd3? Ne4 6. Bg8! Ng5) 5... Ne4 6. Bg8! (6. Bc2? Nd2 7. Bh1! Nb3) (6. Bfd1? {or Ba2?} Nc3) (6. Bh1? {or Be2?/Bfh5?} Ng3) 6... Nd6 7. Bb1! (7. Bgh5? Nc8) 7... Nc8 8. Bb8! Nb6) (3. Bhc6?? Ng4 4. Bhg1 {or Bg3} Nf6) (3. Bhb7?? Ng4 4. Bhg1! Nf6) 3... Ne4 4. Bh1 (4. Ba2 Ng5 5. Bhg8! (5. Bhb1? Nf3 6. Bg3! Nh4 7. Bf1 {or Bh1} Ng6 8. Bhg7! Nf4) 5... Nf3 6. Bg3 (6. Bc7 Nd4 7. Bh2! (7. Bg3? Nc6) 7... Nc6 8. Bc5 {or Bb6} Nb4 9. Bb1 {or Bab3} Nc2) 6... Nh4 7. Bh1! (7. Bf1? Ng6 8. Bhc3 {or Bhf6} Ne7) (7. Bh3? {or Bge4?} Ng6) 7... Ng6 8. Bhc3 (8. Bhf6 Ne7 9. Bh7! Nc8) 8... Ne7 9. Bh7! Nc6) (4. Bhg1? Ng5 5. Bhg8! Nf3 6. Bgf2! Nd4 7. Ba2 {or Ba4} Nc2) (4. Bhg8? Nf6 5. Bgf7! Ng4 6. Bhg1 (6. Bg3 Ne5 7. Be8 {or Bg8} Nc6) 6... Ne3 7. Bh1! Nc2) (4. Bab8? Nf6 5. Bg6! (5. Bb1? Nd7 6. Ba7 {or Bbc7} Nb6) 5... Nd7 6. Ba7! Nb6 7. Bab7! Nc8) (4. Ba4?? Ng5 5. Bb1 (5. Bg8 Nf3 6. Bg3 {or Bc7} Nh4) 5... Nf3 6. Bg3! Nd4) (4. Bf4?? Nf6 5. Bb1! Nd5) (4. Bhb8?? Ng5 5. Bb1 (5. Bhg8 Nf7) 5... Nf3) (4. Bab2?? Nf6 5. Bg6! Ng4) (4. Bb6?? {or Bc7??} Nf6) 4... Ng5 5. Bhg8! (5. Bg6?? Nf7) 5... Nf7 6. Bhg7! (6. Bhc3? Ne5 7. Ba2! Nf3) 6... Nh6 7. Bh7! Ng4 8. Bhg1 (8. Bhb8 Nf6 9. Bb1 (9. Bg6 Nd5) 9... Ne4) 8... Nf2 9. Bhg2! Nh3
Bhg2?
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bhg2? Nc3 3. Bag8! (3. Bb3? Nb5 4. Bab8! (4. Bb6?? Nd4 5. Ba2! Nc2) 4... Nc7 5. Bac6! (5. Baf3? Nd5 6. Bh1 (6. Ba4 Nc3) (6. Bh3 Ne3) 6... Nf6) 5... Nd5 6. Ba8! (6. Bh1? {or Bba4?} Nf6) (6. Bh3? Ne3) 6... Nb6 7. Bac6! Nd7 8. Ba7! Nf6) (3. Bc4? Nb5 4. Bab8! Nc7 5. Bab7! Na6 6. Ba7! (6. Bbd6? Nb4) 6... Nb4 7. Be2! Nc2 8. Bab2! Ne3) (3. Bf7?? Nb5 4. Bab8! (4. Bf2? {or Bb6?} Nc7) 4... Nc7 5. Bac6! Ne6 6. Bfe8! Nd4) 3... Nd5 4. Bb1! (4. Bf7?? Nc7) 4... Nc7 5. Bab7! (5. Bac6?? Nb5 6. Bab8! Na3) 5... Nb5 6. Bab8! (6. Bc5?? Nc3) 6... Na3 7. Bba2! (7. Bg6? Nc2 8. Bab2! Ne3) 7... Nc2 8. Bab2! (8. Bac3? Ne3) 8... Nb4 9. Bb1! Nc6
Bhb8??, Bg3??
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bhb8?? (2. Bg3?? Nc3 3. Bb3! (3. Bc4?? Ne4 4. Be1 {or Bh4} (4. Bh2 Nf2) 4... Ng3) 3... Nb5 4. Bab8! (4. Bb6? Nc7 5. Bac6! Nd5 6. Ba7 (6. Bd8 Nc3) 6... Nf6) (4. Baf2?? Nc7) 4... Nc7 5. Bac6! Na6 6. Ba7! Nc5 7. Ba2! Ne4 8. Bh2! Nf2) 2... Nc3 3. Bb3! (3. Bf7? Nb5 4. Bg1! (4. Bf2? Nc7 5. Bac6! Na6 6. Bba7! Nc5) (4. Be3?? {or Bb6??} Nc7) 4... Nc7 5. Bac6! Ne6 6. Bfe8! Nc5 7. Bb1! Nb3) (3. Bc4?? Nd5 4. Bf1 (4. Be2 Nf6 5. Bc2 {or Bhd3/Bg6} Ne4) (4. Bb3? Nb6) 4... Ne3 5. Bh3! Nc2) (3. Bag8?? Nd5 4. Bf7! Nb6) 3... Nb5 4. Bg1! (4. Bf2?? {or Bb6??} Nc7) 4... Nc7 5. Bac6! (5. Baf3? Nd5 6. Bfd1 (6. Ba2 {or Ba4} Nc3) (6. Bbc2 {or Bba7/Bgh2/Bab2} Nf6) (6. Be2 Nf4) 6... Ne3) 5... Nd5 6. Bba7 (6. Ba8 Nb6 7. Baf3 (7. Bac6 Nd7 8. Bba7! Nf8) 7... Nd7 8. Bba7! Nf6) (6. Bd1? {or Bb5?/Bf2?/Bgh2?/Bab2?} Nf6) 6... Nf6 7. Bb1 (7. Bg6 Ne4 8. Ba8 {or Bce8} Ng3) 7... Ne4 8. Bg8! Ng3
Bg6??, Be6??
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bg6?? (2. Be6?? Nf2 3. Bhg2! Ng4 4. Bhg1! Ne5 5. Ba2 (5. Bb3 Nc6 6. Bab6! Nd4 7. Ba2! Nc2) (5. Bc8? Nc6) (5. Beg8? Ng6) 5... Nc6 6. Bac5 (6. Bab6 Nb4 7. Bab1 {or Bb3} Nc2) 6... Nb4 7. Bab1 {or Bb3/Bag8} Nc2) 2... Nf2 3. Bhg2! (3. Bhb7? Ne4 4. Bc8! (4. Bc6? Nc3) 4... Nc3 5. Bb3! Nb5) 3... Ng4 4. Bhg1! (4. Bg3? Ne5 5. Bh7 (5. Be8 Nc6) 5... Ng6) (4. Bc7? Ne5 5. Bh7! Ng6) 4... Ne3 5. Bh1! (5. Bh3? {or B2e4?} Nc2) 5... Nc2 6. Bac3! Nb4 7. Bab1! Nc6
Bf7??, Bc5??, Bf5??
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bf7?? (2. Bc5?? Nf2 3. Bhg2! Ng4 4. Bhg1! Nf6 5. Bc2 {or Bf5} Nd5) (2. Bf5?? Nf2 3. Bhf3! Ng4 4. Bhg1! (4. Bg3? Nh2) 4... Ne3 5. Bh3 {or Bh7} Nc2)2... Nf2 3. Bhg2! Ng4 4. Bhg1! (4. Bg3? Ne5 5. Ba2 (5. Bb3 Nc6) 5... Ng6) (4. Bc7? Ne5 5. Ba2 {or Bb3} Ng6) 4... Ne5 5. Ba2 (5. Bb3 Nc6 6. Bab6! Nd4 7. Ba2! Nc2) (5. Be8? {or Bfg8?} Ng6) 5... Nc6 6. Bac5 (6. Bab6 Nb4 7. Bab1 {or Bb3} Nc2) 6... Nb4 7. Bab1 {or Bb3/Bag8} Nc2
The rest
[FEN "B6B/B6B/8/8/8/8/B6B/B2n3B w - - 0 2"]
[SetUp "1"] 2. Bb6?? (2. Baf3?? {or Bhf3??} Nc3) (2. Bc2?? {or B7d4??/Bac6??/Bc4??} Nf2) (2. Bag7?? Nf2 3. Bhg2! Ng4) (2. Bhc6?? Nc3 3. Bc4! Nb5 4. Bab8! Nc7) (2. B2e5?? Nc3 3. Bb3! Nb5 4. Bf2! Nd4) (2. Bf4?? Nc3 3. Bb3! Nb5 4. Bf2 {or Bab8} Nc7) (2. Bhg7?? Nc3 3. Bb3 {or Bc4} Nb5 4. Bb6 {or Bab8} Nc7) 2... Nf2 3. Bhf3! Ng4 4. Bhg1 {or Bg3} Nf6
Conclusion
The preceding variations demonstrate the tactics adopted by the lion versus various zebra defenses. It's not possible to present the full analysis, but the final result is the lion always wins.
Partial answer
Note: This was the first cut at the game analysis prior to the full analysis done above.
If we limit the zebras to execute the four-corners strategy suggested in other answers, the problem is more manageable. An analyzing every state where the zebras restrict themselves to the four squares in each corner shows that this strategy is unsustainable. Sooner or later, the zebras have to abandon those squares.
To demonstrate this, I implemented a Python program to with an optimal lion. (It should work in both Python 2.7 and Python 3.x, but let me know if it not.) The user takes the role of the zebras. To reduce the state space, I limited the zebras to having four on white and four on black with two zebras on each long diagonal. This is the optimal organization for the zebras when playing the four corners.
Once the program is started, you receive a command prompt.
To create an initial position, use the start
command followed by {l}:{z1}{z2}...{z8}
where {l}
is the lion's square and {zn}
is each zebra's square. For instance, to use the position shown in Prem's answer use:
start d5:a1a2a7a8h1h2h7h8
The lion will move and the next position shown. To move just enter a move for a zebra, which must be to one of the corner squares. For example:
a2b1
The zebra move will be shown, along with the optimal reply from the lion.
To take back the last move:
undo
And to leave the program:
quit
Optimal Lion vs. Four-Corner Zebras Demo
from cmd import Cmd
from itertools import product, combinations, starmap, chain
from functools import reduce
from zlib import decompress
from base64 import b64decode
import sys
import re
LMOVES_COMPRESSED = [
'eJztkMEKwDAIQ0/B///jla2dmmjPPTQD6RTDi2ZXV4cI+otXYTrr6I0PvEsO5Ad/TV90slh9IfUD'
'W8Es5ImSpkg12nl/c6kQkUgl13c74xy5r7mM/IRiLdTT5dBQFyl+IGFi8iZjk35/NDwguyEr',
'eJzNktsOgCAMQ0OWpv//x+puDEUfF0vAMWqyMxijT9KoRqwh/CyFPmIXK8t/xYOICRYfTc1ca4V7'
'Li65nUdeHN4LnKOTC0xhfgBfTZqFH2KeWvxUzRdHP5e+msJFrS1LSnTBbMKdvRD9hEt05nsqMfye'
'bJ/OjSe4rv4EnXDh5QHHmA45',
'eJzdk1EKwDAIQykSdv8br5Zt1mGq3ef8CuMlmsJa0znGtL9p3Bp9Lt2VfZ8ZouG8cabjiXcYjEfA'
'wO96tIDs8pmM2dS013Qb3RXe772ko07QV7XkTO4l7/zmI0ZTMkYg8Z2LXpXuWZfK/bxXnuN6we6s'
'eb9rls/+F2wyLP8ESRYaZQ==',
'eJylU1sKwDAIQ0rvf+VRRBpfqTA/irg0JtOKiKwl5NTMIuf/MVbRjnirxvBA/ayXIfjpXXD9sb43'
'4+k8IlIZsvJeVf7K/8O0MvHe4Tn/cel9zuaF2xJvzL3PZnr0dRMxD3U96omv4L2HyNxtFGK6Paz0'
'1PiXrzsvr7/OsWPOs6rYyW8Hf/+dl8hShWI+eSgNYQ==',
'eJztU9sOxSAIezC0///H41JwZtn7yckaB1pRRixr/T0ILBS4DBvULmBMF6YIn9cuc+pjgDFE7ZoH'
'msXXQJhar9rNvBEUq5znOh3ECMyTfm2kCO9hk71Kmgqs/lq0+KqFHZR3BnHj8++hC/kCewW3rQzK'
'o1NdL4bvI+EfWR7Uh5+HWitawM2KV/ZnRCnCtvBCE1KbtMfjuTvmoLjFf4vZwtt+zh7inF7rZjxi'
'KBXmsE4oXLETHMk=',
'eJy1UkkOxCAMa4Qc///HkwVoeiodgQ+RD5YdB67rHbIJC1FL2JUlQpA2xaeKOif7BBTKoENDdZIa'
'psbAbb3Cs2WiZesjdz1LAMHsApktzGc25d10pBzrFW4o/vFE9Ft+6dUc/T6gTt7sUg6/WGrQNe48'
'NPt7jX1s+A7OW/Dc4d9ec9sWjYC719CwaE728onkbJ+z0oHl3Z87Ry/eON0L5R+i+Nf5A3ZIC6U=',
'eJyVVNESxDAEZHac///jSyRKEu31PHSMWcsiJQr7mGV/GE8TFpkRCNyfESIArKIXJvnDMC1yxazA'
'pFwUPJ0h597z9E9kuZ9VLDyHrlG95a796NmPfSd/Q5Q8knVh1zVbeTXDrAu1LoSutrtyhlmLNk9v'
'dDm/dbfzmC7ETqt9idV6wND7O+wXxK40/BkhYlbuXTmGdkxU8njzbjCy1MKCGevKsz3n/Ieu/r6u'
'Wns/pkvsHhyjta6c21Kk1KURx1Fr7Ivz/SDevmPg711zpJjP4z2PS/j137BnkeJ6wyOPmMFjOMmR'
'jPkC9XEYPw==',
'eJzdk8EKwDAIQ+tMzP//8XSFbbAdS6F9hyC5PdTW5nEMgm8CBn2ZqDXayz0kxpOeDdf3YjlQPdVn'
'buDlbpabQgA9/WqW9xLSwuq/UHMmsYPXfYt/nFyICAc=',
'eJzdU0EOwzAIgwDz/388EpVANKp113GykDEYEqIZrxX0R1hWXHlTUw1sGx8cApElBm44X3pZ4Zij'
'Q4ezds8zsTU6Aola15R+Hi06iU/Og/088LVGLhwEZ2LuOJqcoiNSdot+z2PFJz72MwZw7c0Mo9OZ'
'KPJsvsNOx/Nxl6VzYV6xa8cIrB7czQPevTjxr77mxFtHFa0vFI6ooJlHxIu3F9fpfAGi6QudL+ek'
'rzLb0cv/V9zCxa2bx98wynu+87XfAxOsv2nm/V6tDpf/wne9Di+J3xBnFgw=',
'eJzdktuSxCAIROWSzv//8WqDDsbJy9Y+LZliLHMEm47q/wy7esBEXGEuDmblToPdPZBMD75V5dp6'
'FrcHAzKaDLjzYMCftNbGAnHkwQhvEhkAJnkyeef7In8tRnq86/IeY83rpZa21sr7O0lJvaO/yaZr'
'dRfOITc11tTFx1vUGd0bVatuukYdRB12YfeYkmobHXnKbTBL+110Ua9fh1/Loze/ogsmAyp9Mqnd'
'lwtfPI23xS/+/cavYLzMFrtfmFqw6+rzMc7Q5p0lGawcM4w5x5O6ok74VZnjO7TDr3nu42bttbR7'
'8ctnzS9+HXlnUBS9MX9Zp36lhfkBhUATYg==',
]
VALID_SQUARES = tuple(product(range(8), repeat=2))
ZSQUARE_GROUPS = (((0,0),(1,1),(6,6),(7,7)), ((0,1),(1,0),(6,7),(7,6)),
((0,7),(1,6),(6,1),(7,0)), ((0,6),(1,7),(6,0),(7,1)))
ALL_CORNERS = reduce(frozenset.union, ZSQUARE_GROUPS, frozenset())
def comb2(iterable): return combinations(iterable, 2)
Z_STATES = list(map(frozenset, starmap(chain, product(*map(comb2, ZSQUARE_GROUPS)))))
LNORM_POS = ((0,0),(2,0),(4,0),(6,0),(1,1),(3,1),(5,1),(2,2),(4,2),(3,3))
pos_combos = [[i in c for i in range(4)] for c in combinations(range(4), 2)]
LMOVE_DELTAS = ((-2,-1),(-2,1),(-1,-2),(-1,2),(1,-2),(1,2),(2,-1),(2,1))
def map_lmoves(l_pos, move_data):
return (l_pos, dict(zip(Z_STATES, bytearray(decompress(b64decode(move_data))))))
LMOVE_LU = dict(map(map_lmoves, LNORM_POS, LMOVES_COMPRESSED))
def str2id(s): return (ord(s[0])-ord('a'), ord(s[1])-ord('1'))
def id2str(id): return chr(ord('a')+id[0])+chr(ord('1')+id[1])
def move2str(move): return "%s%s" % (id2str(move[0]), id2str(move[1]))
def str2move(s): return (str2id(s[:2]), str2id(s[2:]))
def refl_a1h8(id): return (id[1],id[0])
def refl_a8h1(id): return (7-id[1],7-id[0])
def refl_lr(id): return (7-id[0],id[1])
def get_l_move(l_sq, z_sqs):
norm_fs = []
if l_sq[1]>7-l_sq[0]: norm_fs.append(refl_a8h1)
if l_sq[1]>l_sq[0]: norm_fs.append(refl_a1h8)
if 1&(l_sq[0]^l_sq[1]): norm_fs.append(refl_lr)
l_norm_sq, z_norm_sqs = l_sq, z_sqs
for f in norm_fs:
l_norm_sq, z_norm_sqs = f(l_norm_sq), map(f, z_norm_sqs)
d_f, d_r = LMOVE_DELTAS[LMOVE_LU[l_norm_sq][frozenset(z_norm_sqs)]]
l_next_sq = (l_norm_sq[0]+d_f, l_norm_sq[1]+d_r)
for f in norm_fs[::-1]: l_next_sq = f(l_next_sq)
return l_next_sq
def get_z_cands(l_sq, z_sqs):
cands = []
for z_sq in z_sqs:
for d_f, d_r in product((-1,1), repeat=2):
z_next = (z_sq[0]+d_f, z_sq[1]+d_r)
while z_next in VALID_SQUARES:
if z_next == l_sq or z_next in z_sqs:
break
if z_next in ALL_CORNERS:
cands.append((z_sq, z_next))
z_next = (z_next[0]+d_f, z_next[1]+d_r)
return cands
def print_board(l_sq, z_sqs):
def square_c(i, j): return ' Lz'[(i,j)==l_sq or ((i,j) in z_sqs and 2)]
sys.stdout.write('+-+-+-+-+-+-+-+-+\n')
for r in range(7,-1,-1):
line = '|%s| %d' % ('|'.join([square_c(f,r) for f in range(8)]), r+1)
sys.stdout.write('%s\n+-+-+-+-+-+-+-+-+\n' % line)
sys.stdout.write(' a b c d e f g h\n')
class ZLCmd(Cmd):
def __init__(self):
Cmd.__init__(self)
self.phases = []
def init_game(self, sstr):
match = re.match(r"([a-h][1-8]):(([abgh][1278]){8})$", sstr)
if match is None:
raise RuntimeError('Invalid position definition string')
l_str, z_str, _ = match.groups()
l_sq = str2id(l_str)
z_sqs = frozenset(str2id(z_str[2*i:2*i+2]) for i in range(8))
if l_sq in z_sqs:
raise RuntimeError('Lion position overlaps zebras')
if not all([2==len(z_sqs.intersection(group)) for group in ZSQUARE_GROUPS]):
raise RuntimeError('Invalid zebra positions')
self.phases = []
self.l_move(None, l_sq, z_sqs)
def print_last_phase(self):
if len(self.phases) > 0:
phase = self.phases[-1]
l0, l1 = phase['l_move']
z_sqs = phase['z_sqs']
print_board(l0, z_sqs)
sys.stdout.write('\nL move: %s\n\n' % move2str((l0,l1)))
print_board(l1, z_sqs)
if len(phase['z_cands']) == 0:
sys.stdout.write('\nGame over\n')
else:
sys.stdout.write('**No active game**\n')
sys.stdout.write('\n')
def l_move(self, z_move, l_sq, z_sqs):
l_next_sq = get_l_move(l_sq, z_sqs)
if l_next_sq in z_sqs:
# z_sqs = z_sqs.difference((l_next_sq,))
z_cands = []
else:
z_cands = get_z_cands(l_next_sq, z_sqs)
z_cands = dict((move2str(z_cand), z_cand) for z_cand in z_cands)
self.phases.append({'z_move': z_move, 'z_sqs': z_sqs,
'l_move': (l_sq, l_next_sq), 'z_cands': z_cands})
self.print_last_phase()
def z_move(self, move):
phase = self.phases[-1]
l_sq, z_sqs = phase['l_move'][1], phase['z_sqs']
self.l_move(move, l_sq, z_sqs.symmetric_difference(move))
def do_quit(self, line):
"""Quit the program."""
return True
def do_undo(self, line):
"""Undo last move."""
if len(self.phases) > 1:
self.phases.pop()
self.print_last_phase()
else:
sys.stdout.write('Cannot undo\n')
def do_start(self, line):
"""Start at a new position.
Example: start b1:a1a2a7a8h1h2h7h8
"""
try:
if len(line.split()) != 1:
raise RuntimeError('Invalid number of arguments')
self.init_game(line)
except RuntimeError as e:
sys.stdout.write('Error: %s\n' % str(e))
def default(self, line):
if re.match(r"([abcdefgh][12345678]){2}$", line):
if len(self.phases) > 0 and line in self.phases[-1]['z_cands']:
self.z_move(self.phases[-1]['z_cands'][line])
else:
sys.stdout.write('Error: Invalid move, %s\n' % line)
else:
Cmd.default(self, line)
if __name__=='__main__':
try:
ZLCmd().cmdloop()
except Exception as e:
sys.stderr.write('Fatal error: %s\n' % str(e))
sys.exit(1)