1
// This file is part of hnefatafl-copenhagen.
2
//
3
// hnefatafl-copenhagen is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU Affero General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// hnefatafl-copenhagen is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU Affero General Public License for more details.
12
//
13
// You should have received a copy of the GNU Affero General Public License
14
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15

            
16
#![cfg(test)]
17

            
18
use std::{fmt, str::FromStr, time::Duration};
19

            
20
use crate::{
21
    ai::{AI, AiBanal},
22
    board::BoardSize,
23
    game_tree::Tree,
24
};
25

            
26
use super::*;
27
use board::{Board, STARTING_POSITION_11X11};
28
use game::Game;
29
use play::Vertex;
30
use role::Role;
31
use status::Status;
32

            
33
114
fn assert_error_str<T: fmt::Debug>(result: anyhow::Result<T>, string: &str) {
34
114
    if let Err(error) = result {
35
114
        assert_eq!(error.to_string(), string);
36
    }
37
114
}
38

            
39
#[test]
40
6
fn monte_carlo() {
41
6
    let mut tree = Tree::new(Game::new_game(BoardSize::_11, None));
42
6
    let depth = 80;
43
6
    let (loops, _plays) = tree.monte_carlo_tree_search(Duration::from_secs(1), depth);
44
6
    println!("{loops}");
45
6
}
46

            
47
#[ignore = "takes too long"]
48
#[test]
49
fn monte_carlo_long() {
50
    let mut tree = Tree::new(Game::new_game(BoardSize::_11, None));
51
    let depth = 40;
52
    let (loops, _plays) = tree.monte_carlo_tree_search(Duration::from_secs(10), depth);
53
    println!("{loops}");
54
}
55

            
56
#[test]
57
6
fn flood_fill_1() -> anyhow::Result<()> {
58
6
    let board_1 = [
59
6
        "...........",
60
6
        ".........X.",
61
6
        "...........",
62
6
        "...........",
63
6
        "...........",
64
6
        "...........",
65
6
        "...........",
66
6
        ".....O.....",
67
6
        "....O.O....",
68
6
        "....O.O....",
69
6
        "....OKO....",
70
6
    ];
71

            
72
6
    let game = game::Game {
73
6
        board: board_1.try_into()?,
74
6
        turn: Role::Defender,
75
6
        ..Default::default()
76
    };
77

            
78
6
    let vertex = Vertex::from_str("f1")?;
79
6
    assert!(game.board.flood_fill_defender_wins(&vertex));
80

            
81
6
    Ok(())
82
6
}
83

            
84
#[test]
85
6
fn flood_fill_2() -> anyhow::Result<()> {
86
6
    let board_1 = [
87
6
        "...........",
88
6
        ".........X.",
89
6
        "...........",
90
6
        "...........",
91
6
        "...........",
92
6
        "...........",
93
6
        "...........",
94
6
        "....OO.....",
95
6
        "....O......",
96
6
        "....O.O....",
97
6
        "....OKO....",
98
6
    ];
99

            
100
6
    let game = game::Game {
101
6
        board: board_1.try_into()?,
102
6
        turn: Role::Defender,
103
6
        ..Default::default()
104
    };
105

            
106
6
    let vertex = Vertex::from_str("f1")?;
107
6
    assert!(!game.board.flood_fill_defender_wins(&vertex));
108

            
109
6
    Ok(())
110
6
}
111

            
112
// One
113

            
114
#[test]
115
6
fn starting_position() -> anyhow::Result<()> {
116
6
    let game = Game::default();
117
6
    assert_eq!(game.board, STARTING_POSITION_11X11.try_into()?);
118

            
119
6
    Ok(())
120
6
}
121

            
122
// Two
123

            
124
#[test]
125
6
fn first_turn() {
126
6
    let game = Game::default();
127
6
    assert_eq!(game.turn, Role::Attacker);
128
6
}
129

            
130
// Three
131

            
132
#[test]
133
6
fn move_orthogonally_1() -> anyhow::Result<()> {
134
6
    let board = [
135
6
        "...X.......",
136
6
        "...........",
137
6
        "...........",
138
6
        "...........",
139
6
        "...........",
140
6
        "...........",
141
6
        "...........",
142
6
        "X..O......X",
143
6
        "...........",
144
6
        "...........",
145
6
        "...X.......",
146
6
    ];
147

            
148
6
    let mut game = game::Game {
149
6
        board: board.try_into()?,
150
6
        turn: Role::Defender,
151
6
        ..Default::default()
152
    };
153

            
154
6
    let mut result = game.read_line("play defender d4 d1");
155
6
    assert!(result.is_err());
156
6
    assert_error_str(result, "play: you have to play through empty locations");
157

            
158
6
    result = game.read_line("play defender d4 d11");
159
6
    assert!(result.is_err());
160
6
    assert_error_str(result, "play: you have to play through empty locations");
161

            
162
6
    result = game.read_line("play defender d4 a4");
163
6
    assert!(result.is_err());
164
6
    assert_error_str(result, "play: you have to play through empty locations");
165

            
166
6
    result = game.read_line("play defender d4 k4");
167
6
    assert!(result.is_err());
168
6
    assert_error_str(result, "play: you have to play through empty locations");
169

            
170
6
    Ok(())
171
6
}
172

            
173
#[test]
174
6
fn move_orthogonally_2() -> anyhow::Result<()> {
175
6
    let board = [
176
6
        "...........",
177
6
        "...........",
178
6
        "...........",
179
6
        "...........",
180
6
        "...........",
181
6
        "...........",
182
6
        "...........",
183
6
        "...O.......",
184
6
        "...........",
185
6
        "...........",
186
6
        "...........",
187
6
    ];
188

            
189
6
    let mut game = game::Game {
190
6
        board: board.try_into()?,
191
6
        turn: Role::Defender,
192
6
        ..Default::default()
193
    };
194

            
195
    // Play a junk move:
196
6
    let mut result = game.read_line("play defender junk d1");
197
6
    assert!(result.is_err());
198
6
    assert_error_str(result, "invalid digit found in string");
199

            
200
6
    result = game.read_line("play defender d4 junk");
201
6
    assert!(result.is_err());
202
6
    assert_error_str(result, "invalid digit found in string");
203

            
204
    // Diagonal play:
205
6
    result = game.read_line("play defender d4 a3");
206
6
    assert!(result.is_err());
207
6
    assert_error_str(result, "play: you can only play in a straight line");
208

            
209
    // Play out of bounds:
210
6
    result = game.read_line("play defender d4 m4");
211
6
    assert!(result.is_err());
212
6
    assert_error_str(result, "play: the first letter is not a legal char");
213

            
214
6
    result = game.read_line("play defender d4 d12");
215
6
    assert!(result.is_err());
216
6
    assert_error_str(result, "play: invalid coordinate");
217

            
218
6
    result = game.read_line("play defender d4 d0");
219
6
    assert!(result.is_err());
220
6
    assert_error_str(result, "play: invalid coordinate");
221

            
222
    // Don't move:
223
6
    result = game.read_line("play defender d4 d4");
224
6
    assert!(result.is_err());
225
6
    assert_error_str(result, "play: you have to change location");
226

            
227
    // Move all the way to the right:
228
6
    let mut game_1 = game.clone();
229
6
    game_1.read_line("play defender d4 a4")?;
230
    // Move all the way to the left:
231
6
    let mut game_2 = game.clone();
232
6
    game_2.read_line("play defender d4 k4")?;
233
    // Move all the way up:
234
6
    let mut game_3 = game.clone();
235
6
    game_3.read_line("play defender d4 d11")?;
236
    // Move all the way down:
237
6
    let mut game_4 = game.clone();
238
6
    game_4.read_line("play defender d4 d1")?;
239

            
240
6
    Ok(())
241
6
}
242

            
243
// Four
244

            
245
#[test]
246
6
fn sandwich_capture_1() -> anyhow::Result<()> {
247
6
    let board_1 = [
248
6
        "...........",
249
6
        "...........",
250
6
        "...........",
251
6
        "...........",
252
6
        "...........",
253
6
        "...X.......",
254
6
        "...O.......",
255
6
        ".XO.OX.....",
256
6
        "...........",
257
6
        "...X.......",
258
6
        "...........",
259
6
    ];
260

            
261
6
    let board_2 = [
262
6
        "...........",
263
6
        "...........",
264
6
        "...........",
265
6
        "...........",
266
6
        "...........",
267
6
        "...X.......",
268
6
        "...........",
269
6
        ".X.X.X.....",
270
6
        "...........",
271
6
        "...........",
272
6
        "...........",
273
6
    ];
274

            
275
6
    let mut game = game::Game {
276
6
        board: board_1.try_into()?,
277
6
        ..Default::default()
278
    };
279

            
280
6
    game.read_line("play attacker d2 d4")?;
281
6
    assert_eq!(game.board, board_2.try_into()?);
282

            
283
6
    Ok(())
284
6
}
285

            
286
#[test]
287
6
fn sandwich_capture_2() -> anyhow::Result<()> {
288
6
    let board_1 = [
289
6
        "...........",
290
6
        "...........",
291
6
        "...........",
292
6
        "...........",
293
6
        "...........",
294
6
        "...X.......",
295
6
        "...K.......",
296
6
        ".XO.OX.....",
297
6
        "...........",
298
6
        "...X.......",
299
6
        "...........",
300
6
    ];
301

            
302
6
    let board_2 = [
303
6
        "...........",
304
6
        "...........",
305
6
        "...........",
306
6
        "...........",
307
6
        "...........",
308
6
        "...X.......",
309
6
        "...K.......",
310
6
        ".X.X.X.....",
311
6
        "...........",
312
6
        "...........",
313
6
        "...........",
314
6
    ];
315

            
316
6
    let mut game = game::Game {
317
6
        board: board_1.try_into()?,
318
6
        ..Default::default()
319
    };
320

            
321
6
    game.read_line("play attacker d2 d4")?;
322
6
    assert_eq!(game.board, board_2.try_into()?);
323

            
324
6
    Ok(())
325
6
}
326

            
327
#[test]
328
6
fn sandwich_capture_3() -> anyhow::Result<()> {
329
6
    let board_1 = [
330
6
        "...........",
331
6
        "...........",
332
6
        "...........",
333
6
        "...........",
334
6
        "...........",
335
6
        "...........",
336
6
        ".....O.....",
337
6
        ".X.........",
338
6
        "...........",
339
6
        "...........",
340
6
        "...........",
341
6
    ];
342

            
343
6
    let board_2 = [
344
6
        "...........",
345
6
        "...........",
346
6
        "...........",
347
6
        "...........",
348
6
        "...........",
349
6
        "...........",
350
6
        "...........",
351
6
        ".....X.....",
352
6
        "...........",
353
6
        "...........",
354
6
        "...........",
355
6
    ];
356

            
357
6
    let mut game = game::Game {
358
6
        board: board_1.try_into()?,
359
6
        ..Default::default()
360
    };
361

            
362
6
    game.read_line("play attacker b4 f4")?;
363
6
    assert_eq!(game.board, board_2.try_into()?);
364

            
365
6
    Ok(())
366
6
}
367

            
368
#[test]
369
6
fn sandwich_capture_4() -> anyhow::Result<()> {
370
6
    let board_1 = [
371
6
        "...........",
372
6
        "...........",
373
6
        "...........",
374
6
        "...........",
375
6
        "...........",
376
6
        "..K........",
377
6
        "...........",
378
6
        "...........",
379
6
        "..X........",
380
6
        "..O........",
381
6
        "...........",
382
6
    ];
383

            
384
6
    let board_2 = [
385
6
        "...........",
386
6
        "...........",
387
6
        "...........",
388
6
        "...........",
389
6
        "...........",
390
6
        "...........",
391
6
        "...........",
392
6
        "..K........",
393
6
        "...........",
394
6
        "..O........",
395
6
        "...........",
396
6
    ];
397

            
398
6
    let mut game = game::Game {
399
6
        board: board_1.try_into()?,
400
6
        turn: Role::Defender,
401
6
        ..Default::default()
402
    };
403

            
404
6
    game.read_line("play defender c6 c4")?;
405
6
    assert_eq!(game.board, board_2.try_into()?);
406

            
407
6
    Ok(())
408
6
}
409

            
410
#[test]
411
6
fn sandwich_capture_5() -> anyhow::Result<()> {
412
6
    let board_1 = [
413
6
        "...........",
414
6
        "...........",
415
6
        "...........",
416
6
        "...........",
417
6
        "...........",
418
6
        ".....K.....",
419
6
        ".....X.....",
420
6
        ".O.........",
421
6
        "...........",
422
6
        "...........",
423
6
        "...........",
424
6
    ];
425

            
426
6
    let board_2 = [
427
6
        "...........",
428
6
        "...........",
429
6
        "...........",
430
6
        "...........",
431
6
        "...........",
432
6
        ".....K.....",
433
6
        "...........",
434
6
        ".....O.....",
435
6
        "...........",
436
6
        "...........",
437
6
        "...........",
438
6
    ];
439

            
440
6
    let mut game = game::Game {
441
6
        board: board_1.try_into()?,
442
6
        turn: Role::Defender,
443
6
        ..Default::default()
444
    };
445

            
446
6
    game.read_line("play defender b4 f4")?;
447
6
    assert_eq!(game.board, board_2.try_into()?);
448

            
449
6
    Ok(())
450
6
}
451

            
452
#[test]
453
6
fn sandwich_capture_6() -> anyhow::Result<()> {
454
6
    let board_1 = [
455
6
        ".O.........",
456
6
        "...........",
457
6
        "..X........",
458
6
        "...........",
459
6
        "...........",
460
6
        "...........",
461
6
        "...........",
462
6
        "...........",
463
6
        "...........",
464
6
        "...........",
465
6
        "...........",
466
6
    ];
467

            
468
6
    let board_2 = [
469
6
        "..X........",
470
6
        "...........",
471
6
        "...........",
472
6
        "...........",
473
6
        "...........",
474
6
        "...........",
475
6
        "...........",
476
6
        "...........",
477
6
        "...........",
478
6
        "...........",
479
6
        "...........",
480
6
    ];
481

            
482
6
    let mut game = game::Game {
483
6
        board: board_1.try_into()?,
484
6
        ..Default::default()
485
    };
486

            
487
6
    game.read_line("play attacker c9 c11")?;
488
6
    assert_eq!(game.board, board_2.try_into()?);
489

            
490
6
    Ok(())
491
6
}
492

            
493
#[test]
494
6
fn sandwich_capture_7() -> anyhow::Result<()> {
495
6
    let board_1 = [
496
6
        "...........",
497
6
        "...........",
498
6
        "...........",
499
6
        "...........",
500
6
        "...........",
501
6
        ".....K.....",
502
6
        ".....O.....",
503
6
        ".X.........",
504
6
        "...........",
505
6
        "...........",
506
6
        "...........",
507
6
    ];
508

            
509
6
    let board_2 = [
510
6
        "...........",
511
6
        "...........",
512
6
        "...........",
513
6
        "...........",
514
6
        "...........",
515
6
        ".....K.....",
516
6
        ".....O.....",
517
6
        ".....X.....",
518
6
        "...........",
519
6
        "...........",
520
6
        "...........",
521
6
    ];
522

            
523
6
    let mut game = game::Game {
524
6
        board: board_1.try_into()?,
525
6
        ..Default::default()
526
    };
527

            
528
6
    game.read_line("play attacker b4 f4")?;
529
6
    assert_eq!(game.board, board_2.try_into()?);
530

            
531
6
    Ok(())
532
6
}
533

            
534
#[test]
535
6
fn sandwich_capture_8() -> anyhow::Result<()> {
536
6
    let board_1 = [
537
6
        "...........",
538
6
        "...........",
539
6
        "...........",
540
6
        "...........",
541
6
        "...........",
542
6
        "...........",
543
6
        ".O.O.......",
544
6
        "...........",
545
6
        "..X........",
546
6
        "...........",
547
6
        "...........",
548
6
    ];
549

            
550
6
    let board_2 = [
551
6
        "...........",
552
6
        "...........",
553
6
        "...........",
554
6
        "...........",
555
6
        "...........",
556
6
        "...........",
557
6
        ".OXO.......",
558
6
        "...........",
559
6
        "...........",
560
6
        "...........",
561
6
        "...........",
562
6
    ];
563

            
564
6
    let mut game = game::Game {
565
6
        board: board_1.try_into()?,
566
6
        ..Default::default()
567
    };
568

            
569
6
    game.read_line("play attacker c3 c5")?;
570
6
    assert_eq!(game.board, board_2.try_into()?);
571

            
572
6
    Ok(())
573
6
}
574

            
575
#[test]
576
6
fn shield_wall_1() -> anyhow::Result<()> {
577
6
    let board_1 = [
578
6
        "...........",
579
6
        "...........",
580
6
        "...........",
581
6
        "...........",
582
6
        "...........",
583
6
        "...........",
584
6
        "...........",
585
6
        "...........",
586
6
        "..O........",
587
6
        "...OOO.....",
588
6
        "...XXXO....",
589
6
    ];
590

            
591
6
    let board_2 = [
592
6
        "...........",
593
6
        "...........",
594
6
        "...........",
595
6
        "...........",
596
6
        "...........",
597
6
        "...........",
598
6
        "...........",
599
6
        "...........",
600
6
        "...........",
601
6
        "...OOO.....",
602
6
        "..O...O....",
603
6
    ];
604

            
605
6
    let mut game_1 = game::Game {
606
6
        board: board_1.try_into()?,
607
6
        turn: Role::Defender,
608
6
        ..Default::default()
609
    };
610

            
611
6
    game_1.read_line("play defender c3 c1")?;
612
6
    assert_eq!(game_1.board, board_2.try_into()?);
613

            
614
6
    let board_3 = [
615
6
        "...XXXO....",
616
6
        "...OOO.....",
617
6
        "..O........",
618
6
        "...........",
619
6
        "...........",
620
6
        "...........",
621
6
        "...........",
622
6
        "...........",
623
6
        "...........",
624
6
        "...........",
625
6
        "...........",
626
6
    ];
627

            
628
6
    let board_4 = [
629
6
        "..O...O....",
630
6
        "...OOO.....",
631
6
        "...........",
632
6
        "...........",
633
6
        "...........",
634
6
        "...........",
635
6
        "...........",
636
6
        "...........",
637
6
        "...........",
638
6
        "...........",
639
6
        "...........",
640
6
    ];
641

            
642
6
    let mut game_2 = game::Game {
643
6
        board: board_3.try_into()?,
644
6
        turn: Role::Defender,
645
6
        ..Default::default()
646
    };
647

            
648
6
    game_2.read_line("play defender c9 c11")?;
649
6
    assert_eq!(game_2.board, board_4.try_into()?);
650

            
651
6
    Ok(())
652
6
}
653

            
654
#[test]
655
6
fn shield_wall_1_13() -> anyhow::Result<()> {
656
6
    let board_1 = [
657
6
        "...XXXO......",
658
6
        "...OOO.......",
659
6
        "..O..........",
660
6
        ".............",
661
6
        ".............",
662
6
        ".............",
663
6
        ".............",
664
6
        ".............",
665
6
        ".............",
666
6
        ".............",
667
6
        ".............",
668
6
        ".............",
669
6
        ".............",
670
6
    ];
671

            
672
6
    let board_2 = [
673
6
        "..O...O......",
674
6
        "...OOO.......",
675
6
        ".............",
676
6
        ".............",
677
6
        ".............",
678
6
        ".............",
679
6
        ".............",
680
6
        ".............",
681
6
        ".............",
682
6
        ".............",
683
6
        ".............",
684
6
        ".............",
685
6
        ".............",
686
6
    ];
687

            
688
6
    let mut game_1 = game::Game {
689
6
        board: board_1.try_into()?,
690
6
        turn: Role::Defender,
691
6
        ..Default::default()
692
    };
693

            
694
6
    game_1.read_line("play defender C11 C13")?;
695
6
    assert_eq!(game_1.board, board_2.try_into()?);
696

            
697
6
    Ok(())
698
6
}
699

            
700
#[test]
701
6
fn shield_wall_2() -> anyhow::Result<()> {
702
6
    let board_1 = [
703
6
        "...........",
704
6
        "...........",
705
6
        "...........",
706
6
        "...........",
707
6
        "..O........",
708
6
        "XO.........",
709
6
        "XO.........",
710
6
        "XO.........",
711
6
        "O..........",
712
6
        "...........",
713
6
        "...........",
714
6
    ];
715

            
716
6
    let board_2 = [
717
6
        "...........",
718
6
        "...........",
719
6
        "...........",
720
6
        "...........",
721
6
        "O..........",
722
6
        ".O.........",
723
6
        ".O.........",
724
6
        ".O.........",
725
6
        "O..........",
726
6
        "...........",
727
6
        "...........",
728
6
    ];
729

            
730
6
    let mut game_1 = game::Game {
731
6
        board: board_1.try_into()?,
732
6
        turn: Role::Defender,
733
6
        ..Default::default()
734
    };
735

            
736
6
    game_1.read_line("play defender c7 a7")?;
737
6
    assert_eq!(game_1.board, board_2.try_into()?);
738

            
739
6
    let board_3 = [
740
6
        "...........",
741
6
        "...........",
742
6
        "...........",
743
6
        "...........",
744
6
        "........O..",
745
6
        ".........OX",
746
6
        ".........OX",
747
6
        ".........OX",
748
6
        "..........O",
749
6
        "...........",
750
6
        "...........",
751
6
    ];
752

            
753
6
    let board_4 = [
754
6
        "...........",
755
6
        "...........",
756
6
        "...........",
757
6
        "...........",
758
6
        "..........O",
759
6
        ".........O.",
760
6
        ".........O.",
761
6
        ".........O.",
762
6
        "..........O",
763
6
        "...........",
764
6
        "...........",
765
6
    ];
766

            
767
6
    let mut game_2 = game::Game {
768
6
        board: board_3.try_into()?,
769
6
        turn: Role::Defender,
770
6
        ..Default::default()
771
    };
772

            
773
6
    game_2.read_line("play defender i7 k7")?;
774
6
    assert_eq!(game_2.board, board_4.try_into()?);
775

            
776
6
    Ok(())
777
6
}
778

            
779
#[test]
780
6
fn shield_wall_3() -> anyhow::Result<()> {
781
6
    let board_1 = [
782
6
        "...........",
783
6
        "...........",
784
6
        "...........",
785
6
        "...........",
786
6
        "...........",
787
6
        "...........",
788
6
        "...........",
789
6
        "...........",
790
6
        "...........",
791
6
        "........XX.",
792
6
        ".....X..OK.",
793
6
    ];
794

            
795
6
    let board_2 = [
796
6
        "...........",
797
6
        "...........",
798
6
        "...........",
799
6
        "...........",
800
6
        "...........",
801
6
        "...........",
802
6
        "...........",
803
6
        "...........",
804
6
        "...........",
805
6
        "........XX.",
806
6
        ".......X.K.",
807
6
    ];
808

            
809
6
    let mut game_1 = game::Game {
810
6
        board: board_1.try_into()?,
811
6
        ..Default::default()
812
    };
813

            
814
6
    game_1.read_line("play attacker f1 h1")?;
815
6
    assert_eq!(game_1.board, board_2.try_into()?);
816

            
817
6
    let board_3 = [
818
6
        "...........",
819
6
        "...........",
820
6
        "...........",
821
6
        "...........",
822
6
        "...........",
823
6
        "...........",
824
6
        "...........",
825
6
        "...........",
826
6
        "...........",
827
6
        ".XX........",
828
6
        ".KO..X.....",
829
6
    ];
830

            
831
6
    let board_4 = [
832
6
        "...........",
833
6
        "...........",
834
6
        "...........",
835
6
        "...........",
836
6
        "...........",
837
6
        "...........",
838
6
        "...........",
839
6
        "...........",
840
6
        "...........",
841
6
        ".XX........",
842
6
        ".K.X.......",
843
6
    ];
844

            
845
6
    let mut game_2 = game::Game {
846
6
        board: board_3.try_into()?,
847
6
        ..Default::default()
848
    };
849

            
850
6
    game_2.read_line("play attacker f1 d1")?;
851
6
    assert_eq!(game_2.board, board_4.try_into()?);
852

            
853
6
    Ok(())
854
6
}
855

            
856
#[test]
857
6
fn shield_wall_4() -> anyhow::Result<()> {
858
6
    let board_1 = [
859
6
        ".....X..OK.",
860
6
        "........XX.",
861
6
        "...........",
862
6
        "...........",
863
6
        "...........",
864
6
        "...........",
865
6
        "...........",
866
6
        "...........",
867
6
        "...........",
868
6
        "...........",
869
6
        "...........",
870
6
    ];
871

            
872
6
    let board_2 = [
873
6
        ".......X.K.",
874
6
        "........XX.",
875
6
        "...........",
876
6
        "...........",
877
6
        "...........",
878
6
        "...........",
879
6
        "...........",
880
6
        "...........",
881
6
        "...........",
882
6
        "...........",
883
6
        "...........",
884
6
    ];
885

            
886
6
    let mut game_1 = game::Game {
887
6
        board: board_1.try_into()?,
888
6
        ..Default::default()
889
    };
890

            
891
6
    game_1.read_line("play attacker f11 h11")?;
892
6
    assert_eq!(game_1.board, board_2.try_into()?);
893

            
894
6
    let board_3 = [
895
6
        ".KO..X.....",
896
6
        ".XX........",
897
6
        "...........",
898
6
        "...........",
899
6
        "...........",
900
6
        "...........",
901
6
        "...........",
902
6
        "...........",
903
6
        "...........",
904
6
        "...........",
905
6
        "...........",
906
6
    ];
907

            
908
6
    let board_4 = [
909
6
        ".K.X.......",
910
6
        ".XX........",
911
6
        "...........",
912
6
        "...........",
913
6
        "...........",
914
6
        "...........",
915
6
        "...........",
916
6
        "...........",
917
6
        "...........",
918
6
        "...........",
919
6
        "...........",
920
6
    ];
921

            
922
6
    let mut game_2 = game::Game {
923
6
        board: board_3.try_into()?,
924
6
        ..Default::default()
925
    };
926

            
927
6
    game_2.read_line("play attacker f11 d11")?;
928
6
    assert_eq!(game_2.board, board_4.try_into()?);
929

            
930
6
    Ok(())
931
6
}
932

            
933
#[test]
934
6
fn shield_wall_5() -> anyhow::Result<()> {
935
6
    let board_1 = [
936
6
        "...........",
937
6
        "...........",
938
6
        "...........",
939
6
        "...........",
940
6
        "...........",
941
6
        "X..........",
942
6
        "...........",
943
6
        "...........",
944
6
        "OX.........",
945
6
        "KX.........",
946
6
        "...........",
947
6
    ];
948

            
949
6
    let board_2 = [
950
6
        "...........",
951
6
        "...........",
952
6
        "...........",
953
6
        "...........",
954
6
        "...........",
955
6
        "...........",
956
6
        "...........",
957
6
        "X..........",
958
6
        ".X.........",
959
6
        "KX.........",
960
6
        "...........",
961
6
    ];
962

            
963
6
    let mut game_1 = game::Game {
964
6
        board: board_1.try_into()?,
965
6
        ..Default::default()
966
    };
967

            
968
6
    game_1.read_line("play attacker a6 a4")?;
969
6
    assert_eq!(game_1.board, board_2.try_into()?);
970

            
971
6
    let board_3 = [
972
6
        "...........",
973
6
        "KX.........",
974
6
        "OX.........",
975
6
        "...........",
976
6
        "...........",
977
6
        "X..........",
978
6
        "...........",
979
6
        "...........",
980
6
        "...........",
981
6
        "...........",
982
6
        "...........",
983
6
    ];
984

            
985
6
    let board_4 = [
986
6
        "...........",
987
6
        "KX.........",
988
6
        ".X.........",
989
6
        "X..........",
990
6
        "...........",
991
6
        "...........",
992
6
        "...........",
993
6
        "...........",
994
6
        "...........",
995
6
        "...........",
996
6
        "...........",
997
6
    ];
998

            
999
6
    let mut game_2 = game::Game {
6
        board: board_3.try_into()?,
6
        ..Default::default()
    };
6
    game_2.read_line("play attacker a6 a8")?;
6
    assert_eq!(game_2.board, board_4.try_into()?);
6
    Ok(())
6
}
#[test]
6
fn shield_wall_6() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        ".........XO",
6
        ".........XK",
6
        "...........",
6
    ];
6
    let board_2 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "..........X",
6
        ".........X.",
6
        ".........XK",
6
        "...........",
6
    ];
6
    let mut game_1 = game::Game {
6
        board: board_1.try_into()?,
6
        ..Default::default()
    };
6
    game_1.read_line("play attacker k6 k4")?;
6
    assert_eq!(game_1.board, board_2.try_into()?);
6
    let board_3 = [
6
        "...........",
6
        ".........XK",
6
        ".........XO",
6
        "...........",
6
        "...........",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let board_4 = [
6
        "...........",
6
        ".........XK",
6
        ".........X.",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game_2 = game::Game {
6
        board: board_3.try_into()?,
6
        ..Default::default()
    };
6
    game_2.read_line("play attacker k6 k8")?;
6
    assert_eq!(game_2.board, board_4.try_into()?);
6
    Ok(())
6
}
#[test]
6
fn shield_wall_7() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "...........",
6
        "........X.O",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let board_2 = [
6
        "...........",
6
        ".........XO",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board_1.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker i10 j10")?;
6
    assert_eq!(game.board, board_2.try_into()?);
6
    let board_3 = [
6
        "...........",
6
        "..........X",
6
        "........X.O",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let board_4 = [
6
        "...........",
6
        "..........X",
6
        ".........XO",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board_3.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker i9 j9")?;
6
    assert_eq!(game.board, board_4.try_into()?);
6
    Ok(())
6
}
#[test]
6
fn shield_wall_nope() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "...........",
6
        "........X.O",
6
        ".........XO",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let board_2 = [
6
        "...........",
6
        ".........XO",
6
        ".........XO",
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board_1.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker i10 j10")?;
6
    assert_eq!(game.board, board_2.try_into()?);
6
    Ok(())
6
}
// Five
#[test]
6
fn kings_1() {
6
    let board = [
6
        "KK.........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let result: anyhow::Result<Board> = board.try_into();
6
    assert!(result.is_err());
6
    assert_error_str(result, "You can only have one king!");
6
}
#[test]
6
fn kings_2() -> anyhow::Result<()> {
6
    let board = [
6
        ".X.........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    let result = game.read_line("play attacker b11 a11");
6
    assert!(result.is_err());
6
    assert_error_str(
6
        result,
6
        "play: only the king may move to a restricted square",
    );
6
    Ok(())
6
}
#[test]
6
fn kings_3() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "K..........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let _board: Board = board_1.try_into()?;
6
    let board_2 = [
6
        "X..........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let result: anyhow::Result<Board> = board_2.try_into();
6
    assert!(result.is_err());
6
    assert_error_str(result, "Only the king is allowed on restricted squares!");
6
    Ok(())
6
}
#[test]
6
fn kings_4() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "..........K",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let _board: Board = board_1.try_into()?;
6
    let board_2 = [
6
        "..........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let result: anyhow::Result<Board> = board_2.try_into();
6
    assert!(result.is_err());
6
    assert_error_str(result, "Only the king is allowed on restricted squares!");
6
    Ok(())
6
}
#[test]
6
fn kings_5() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....K.....",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let _board: Board = board_1.try_into()?;
6
    let board_2 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....X.....",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let result: anyhow::Result<Board> = board_2.try_into();
6
    assert!(result.is_err());
6
    assert_error_str(result, "Only the king is allowed on restricted squares!");
6
    Ok(())
6
}
#[test]
6
fn kings_6() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "K..........",
6
    ];
6
    let _board: Board = board_1.try_into()?;
6
    let board_2 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "X..........",
6
    ];
6
    let result: anyhow::Result<Board> = board_2.try_into();
6
    assert!(result.is_err());
6
    assert_error_str(result, "Only the king is allowed on restricted squares!");
6
    Ok(())
6
}
#[test]
6
fn kings_7() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "..........K",
6
    ];
6
    let _board: Board = board_1.try_into()?;
6
    let board_2 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "..........X",
6
    ];
6
    let result: anyhow::Result<Board> = board_2.try_into();
6
    assert!(result.is_err());
6
    assert_error_str(result, "Only the king is allowed on restricted squares!");
6
    Ok(())
6
}
// Six
#[test]
6
fn defender_wins_exit() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....K.....",
6
    ];
6
    let mut game_1 = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    let mut game_2 = game_1.clone();
6
    game_1.read_line("play defender f1 k1")?;
6
    assert_eq!(game_1.status, Status::DefenderWins);
6
    game_2.read_line("play defender f1 a1")?;
6
    assert_eq!(game_2.status, Status::DefenderWins);
6
    let board = [
6
        ".....K.....",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game_1 = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    let mut game_2 = game_1.clone();
6
    game_1.read_line("play defender f11 k11")?;
6
    assert_eq!(game_1.status, Status::DefenderWins);
6
    game_2.read_line("play defender f11 a11")?;
6
    assert_eq!(game_2.status, Status::DefenderWins);
6
    Ok(())
6
}
#[test]
6
fn defender_wins_escape_fort_1() -> anyhow::Result<()> {
6
    let board = [
6
        "....O.O....",
6
        "....OKO....",
6
        "....OO.....",
6
        "....XX.....",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender f10 f11")?;
6
    assert_eq!(game.status, Status::DefenderWins);
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "....XX.....",
6
        "....OO.....",
6
        "....OKO....",
6
        "....O.O....",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender f2 f1")?;
6
    assert_eq!(game.status, Status::DefenderWins);
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "OOOX.......",
6
        ".KOX.......",
6
        "OO.........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender b6 a6")?;
6
    assert_eq!(game.status, Status::DefenderWins);
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".......XOOO",
6
        ".......XOK.",
6
        ".........OO",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender j6 k6")?;
6
    assert_eq!(game.status, Status::DefenderWins);
6
    Ok(())
6
}
#[test]
6
fn defender_wins_escape_fort_1_13() -> anyhow::Result<()> {
6
    let board = [
6
        "....OKO......",
6
        "....O........",
6
        "....OOO......",
6
        "....XX.......",
6
        ".............",
6
        ".............",
6
        ".............",
6
        ".............",
6
        ".............",
6
        ".............",
6
        ".............",
6
        ".............",
6
        ".............",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender G11 G12")?;
6
    assert_eq!(game.status, Status::DefenderWins);
6
    Ok(())
6
}
#[test]
6
fn defender_wins_escape_fort_2() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "........XOO",
6
        "........OK.",
6
        ".......X.OO",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender j6 k6")?;
6
    assert_eq!(game.status, Status::Ongoing);
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "........XOO",
6
        "........OK.",
6
        ".........OO",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender j6 k6")?;
6
    assert_eq!(game.status, Status::DefenderWins);
6
    Ok(())
6
}
#[test]
6
fn defender_wins_escape_fort_3() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "........X.O",
6
        ".........O.",
6
        ".......X.OK",
6
        "..........O",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender k5 k6")?;
6
    assert_eq!(game.status, Status::DefenderWins);
6
    Ok(())
6
}
// Seven
#[test]
6
fn kings_not_captured() -> anyhow::Result<()> {
6
    let board_1 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....X.....",
6
        "...........",
6
        ".....KX....",
6
        ".....X.....",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let board_2 = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....X.....",
6
        ".....KX....",
6
        ".....X.....",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ]
6
    .try_into()?;
6
    let mut game = game::Game {
6
        board: board_1.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker f8 f7")?;
6
    assert_eq!(game.board, board_2);
6
    Ok(())
6
}
#[test]
6
fn kings_captured_1() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....X.....",
6
        "...........",
6
        "....XKX....",
6
        ".....X.....",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker f8 f7")?;
6
    assert_eq!(game.status, Status::AttackerWins);
6
    Ok(())
6
}
#[test]
6
fn kings_captured_2() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "....XKX....",
6
        "...........",
6
        ".....X.....",
6
        "...........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker f3 f4")?;
6
    assert_eq!(game.status, Status::AttackerWins);
6
    Ok(())
6
}
#[test]
6
fn kings_captured_3() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "....X......",
6
        "...XKX.....",
6
        "...........",
6
        "....X......",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker e1 e2")?;
6
    assert_eq!(game.status, Status::AttackerWins);
6
    Ok(())
6
}
#[test]
6
fn kings_captured_4() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        ".O.........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "X..........",
6
        "K.X........",
6
        "X..........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker c3 b3")?;
6
    assert_eq!(game.status, Status::Ongoing);
6
    Ok(())
6
}
#[test]
6
fn kings_captured_5() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "X..........",
6
        "K.X........",
6
        "...........",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker c2 b2")?;
6
    assert_eq!(game.status, Status::Ongoing);
6
    Ok(())
6
}
#[test]
6
fn kings_captured_surround_1() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        ".....XXX...",
6
        "....X...XX.",
6
        ".X...O....X",
6
        "..X.......X",
6
        ".X.O...O..X",
6
        ".X..OK...X.",
6
        "..X...O.X..",
6
        "...XXX.X...",
6
        "......X....",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker b7 c7")?;
6
    assert_eq!(game.status, Status::Ongoing);
6
    game.read_line("play defender f7 g7")?;
6
    assert_eq!(game.status, Status::Ongoing);
6
    game.read_line("play attacker c7 d7")?;
6
    assert_eq!(game.status, Status::AttackerWins);
6
    Ok(())
6
}
#[test]
6
fn kings_captured_surround_2() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...O.......",
6
        ".....XXX...",
6
        "....X...XX.",
6
        "..X..O....X",
6
        "..X.......X",
6
        ".X.O...O..X",
6
        ".X..OK...X.",
6
        "..X...O.X..",
6
        "...XXX.X...",
6
        "......X....",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker c7 d7")?;
6
    assert_eq!(game.status, Status::Ongoing);
6
    Ok(())
6
}
// Eight
#[test]
6
fn can_not_repeat_moves() -> anyhow::Result<()> {
6
    let mut game = Game::default();
6
    game.read_line("play attacker f2 f3")?;
6
    game.read_line("play defender f4 g4")?;
6
    game.read_line("play attacker f3 f2")?;
6
    let result = game.read_line("play defender g4 f4");
6
    assert!(result.is_err());
6
    assert_error_str(result, "play: you already reached that position");
6
    Ok(())
6
}
// Nine
#[test]
6
fn attacker_automatically_loses() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....K.....",
6
        ".....X.....",
6
        "...........",
6
        ".....O.....",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    game.read_line("play defender f1 f2")?;
6
    assert_eq!(game.status, Status::DefenderWins);
6
    Ok(())
6
}
#[test]
6
fn defender_automatically_loses_1() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....X.....",
6
        ".X..XKX....",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker b1 b2")?;
6
    assert_eq!(game.status, Status::AttackerWins);
6
    Ok(())
6
}
#[test]
6
fn defender_automatically_loses_2() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....X.....",
6
        ".X..X.X....",
6
        "....XKX....",
6
    ];
6
    let mut game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    game.read_line("play attacker b2 b1")?;
6
    game.read_line("play defender f1 f2")?;
6
    game.read_line("play attacker b1 b2")?;
6
    game.read_line("play defender f2 f1")?;
6
    game.read_line("play attacker b2 b1")?;
6
    assert_eq!(game.status, Status::AttackerWins);
6
    Ok(())
6
}
#[test]
6
fn exit_one_1() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".X...K...X.",
6
    ];
6
    let game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    assert!(!game.exit_one());
6
    Ok(())
6
}
#[test]
6
fn exit_one_2() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....K.....",
6
    ];
6
    let game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    assert!(game.exit_one());
6
    Ok(())
6
}
#[test]
6
fn exit_one_3() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....K.....",
6
        "...........",
6
    ];
6
    let game = game::Game {
6
        board: board.try_into()?,
6
        turn: Role::Defender,
6
        ..Default::default()
    };
6
    assert!(!game.exit_one());
6
    Ok(())
6
}
#[test]
6
fn exit_one_4() -> anyhow::Result<()> {
6
    let board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        ".....K.....",
6
    ];
6
    let game = game::Game {
6
        board: board.try_into()?,
6
        ..Default::default()
    };
6
    assert!(!game.exit_one());
6
    Ok(())
6
}
#[test]
6
fn closed_off_exits() -> anyhow::Result<()> {
6
    let board: Board = [
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "X..........",
6
        ".X.........",
6
        "..X..K.....",
6
    ]
6
    .try_into()?;
6
    assert_eq!(board.closed_off_exits(), 1);
6
    let board: Board = [
6
        "..X....X...",
6
        ".X......X..",
6
        "X........X.",
6
        "X.........X",
6
        "X..........",
6
        "X..........",
6
        "X..........",
6
        "X..........",
6
        "X.........X",
6
        ".X.......X.",
6
        "..X..K..X..",
6
    ]
6
    .try_into()?;
6
    assert_eq!(board.closed_off_exits(), 4);
6
    let board: Board = [
6
        ".XX.....XX.",
6
        "X.........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "X.........X",
6
        ".XX..K..XX.",
6
    ]
6
    .try_into()?;
6
    assert_eq!(board.closed_off_exits(), 0);
6
    let board: Board = [
6
        ".X.......X.",
6
        "X.........X",
6
        "X.........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "X.........X",
6
        "X.........X",
6
        ".X...K...X.",
6
    ]
6
    .try_into()?;
6
    assert_eq!(board.closed_off_exits(), 0);
6
    let board: Board = [
6
        ".XX.....XX.",
6
        "X.........X",
6
        "X.........X",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "...........",
6
        "X.........X",
6
        "X.........X",
6
        ".XX..K..XX.",
6
    ]
6
    .try_into()?;
6
    assert_eq!(board.closed_off_exits(), 4);
6
    Ok(())
6
}
#[test]
6
fn someone_wins() {
6
    let mut game = Game::default();
6
    let mut ai: Box<dyn AI> = Box::new(AiBanal);
    loop {
        // Do nothing but play.
732
        if ai.generate_move(&mut game).is_err() {
6
            break;
726
        }
    }
6
    assert!(game.status == Status::AttackerWins || game.status == Status::DefenderWins);
6
}