Skip to content

Commit 674c149

Browse files
authored
add tests (#136)
1 parent 3a50a28 commit 674c149

9 files changed

+617
-76
lines changed

server/src/combat.rs

+27-25
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ pub fn initiate_combat(
116116
can_retreat: bool,
117117
next_game_state: Option<GameState>,
118118
) {
119-
game.lock_undo();
120119
let initiation = next_game_state.map_or_else(
121120
|| Box::new(mem::replace(&mut game.state, Playing)),
122121
Box::new,
@@ -137,30 +136,33 @@ pub fn initiate_combat(
137136
}
138137

139138
pub(crate) fn start_combat(game: &mut Game, combat: Combat, skip: Option<CombatModifier>) {
140-
if skip != Some(CancelFortressExtraDie) {
141-
if skip != Some(SteelWeaponsDefender) {
142-
if skip != Some(SteelWeaponsAttacker)
143-
&& start_steel_weapons_phase(
144-
game,
145-
combat.clone(),
146-
combat.attacker,
147-
SteelWeaponsAttacker,
148-
)
149-
{
150-
return;
151-
}
152-
if start_steel_weapons_phase(
153-
game,
154-
combat.clone(),
155-
combat.defender,
156-
SteelWeaponsDefender,
157-
) {
158-
return;
159-
}
160-
}
161-
if start_siegecraft_phase(game, combat.clone()) {
162-
return;
163-
}
139+
game.lock_undo();
140+
let evaluate: &[CombatModifier] = match skip {
141+
None => &[
142+
SteelWeaponsAttacker,
143+
SteelWeaponsDefender,
144+
CancelFortressExtraDie,
145+
],
146+
Some(SteelWeaponsAttacker) => &[SteelWeaponsDefender, CancelFortressExtraDie],
147+
Some(SteelWeaponsDefender) => &[CancelFortressExtraDie],
148+
Some(CancelFortressExtraDie) => &[],
149+
_ => panic!("Illegal action"),
150+
};
151+
152+
if evaluate.contains(&SteelWeaponsAttacker)
153+
&& start_steel_weapons_phase(game, combat.clone(), combat.attacker, SteelWeaponsAttacker)
154+
{
155+
return;
156+
}
157+
158+
if evaluate.contains(&SteelWeaponsDefender)
159+
&& start_steel_weapons_phase(game, combat.clone(), combat.defender, SteelWeaponsDefender)
160+
{
161+
return;
162+
}
163+
164+
if evaluate.contains(&CancelFortressExtraDie) && start_siegecraft_phase(game, combat.clone()) {
165+
return;
164166
}
165167

166168
combat_loop(game, combat);

server/tests/game_api_tests.rs

+64-32
Original file line numberDiff line numberDiff line change
@@ -421,12 +421,49 @@ fn game_path(name: &str) -> String {
421421
format!("tests{SEPARATOR}test_games{SEPARATOR}{name}.json")
422422
}
423423

424+
fn test_actions(name: &str, player_index: usize, actions: Vec<Action>) {
425+
for (i, action) in actions.into_iter().enumerate() {
426+
let from = if i == 0 {
427+
name.to_string()
428+
} else {
429+
format!("{name}.outcome{}", i - 1)
430+
};
431+
test_action_internal(
432+
&from,
433+
&format!("{name}.outcome{i}"),
434+
action,
435+
player_index,
436+
false,
437+
false,
438+
);
439+
}
440+
}
441+
424442
fn test_action(
425443
name: &str,
426444
action: Action,
427445
player_index: usize,
428446
undoable: bool,
429447
illegal_action_test: bool,
448+
) {
449+
let outcome = format!("{name}.outcome");
450+
test_action_internal(
451+
name,
452+
&outcome,
453+
action,
454+
player_index,
455+
undoable,
456+
illegal_action_test,
457+
);
458+
}
459+
460+
fn test_action_internal(
461+
name: &str,
462+
outcome: &str,
463+
action: Action,
464+
player_index: usize,
465+
undoable: bool,
466+
illegal_action_test: bool,
430467
) {
431468
let a = serde_json::to_string(&action).expect("action should be serializable");
432469
let a2 = serde_json::from_str(&a).expect("action should be deserializable");
@@ -438,25 +475,24 @@ fn test_action(
438475
);
439476
return;
440477
}
441-
let outcome = format!("{name}.outcome");
442-
let expected_game = read_game_str(&outcome);
478+
let expected_game = read_game_str(outcome);
443479
assert_eq_game_json(
444480
&expected_game,
445481
&to_json(&game),
446482
name,
447-
&outcome,
483+
outcome,
448484
&format!("EXECUTE: the game did not match the expectation after the initial {name} action"),
449485
);
450486
if !undoable {
451-
assert!(!game.can_undo());
487+
assert!(!game.can_undo(), "should not be able to undo");
452488
return;
453489
}
454490
undo_redo(
455491
name,
456492
player_index,
457493
&read_game_str(name),
458494
game,
459-
&outcome,
495+
outcome,
460496
&expected_game,
461497
0,
462498
);
@@ -475,10 +511,10 @@ fn read_game_str(name: &str) -> String {
475511
fn undo_redo(
476512
name: &str,
477513
player_index: usize,
478-
original_game: &String,
514+
original_game: &str,
479515
game: Game,
480-
outcome: &String,
481-
expected_game: &String,
516+
outcome: &str,
517+
expected_game: &str,
482518
cycle: usize,
483519
) {
484520
if cycle == 2 {
@@ -895,9 +931,9 @@ fn test_remove_casualties_defender_and_defender_wins() {
895931
}
896932

897933
#[test]
898-
fn test_direct_capture_city() {
934+
fn test_direct_capture_city_metallurgy() {
899935
test_action(
900-
"direct_capture_city",
936+
"direct_capture_city_metallurgy",
901937
move_action(vec![0, 1, 2, 3], Position::from_offset("C1")),
902938
0,
903939
false,
@@ -939,29 +975,25 @@ fn test_first_combat_round_no_hits_attacker_may_retreat() {
939975
}
940976

941977
#[test]
942-
fn test_ask_for_siegecraft() {
943-
test_action(
944-
"ask_for_siegecraft",
945-
move_action(vec![0, 1, 2, 3, 4, 5], Position::from_offset("C1")),
946-
0,
947-
false,
948-
false,
949-
);
950-
}
951-
952-
#[test]
953-
fn test_attack_with_siegecraft() {
954-
test_action(
955-
"attack_with_siegecraft",
956-
CustomPhase(CustomPhaseAction::SiegecraftPaymentAction(
957-
SiegecraftPayment {
958-
ignore_hit: ResourcePile::ore(2),
959-
extra_die: ResourcePile::empty(),
960-
},
961-
)),
978+
fn test_combat_all_modifiers() {
979+
test_actions(
980+
"combat_all_modifiers",
962981
0,
963-
false,
964-
false,
982+
vec![
983+
move_action(vec![0, 1, 2, 3, 4, 5], Position::from_offset("C1")),
984+
CustomPhase(CustomPhaseAction::SteelWeaponsAttackerAction(
985+
ResourcePile::ore(1),
986+
)),
987+
CustomPhase(CustomPhaseAction::SteelWeaponsDefenderAction(
988+
ResourcePile::ore(1),
989+
)),
990+
CustomPhase(CustomPhaseAction::SiegecraftPaymentAction(
991+
SiegecraftPayment {
992+
ignore_hit: ResourcePile::ore(2),
993+
extra_die: ResourcePile::empty(),
994+
},
995+
)),
996+
],
965997
);
966998
}
967999

server/tests/test_games/ask_for_siegecraft.json server/tests/test_games/combat_all_modifiers.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@
9797
"Farming",
9898
"Mining",
9999
"Siegecraft",
100-
"Tactics"
100+
"Tactics" ,
101+
"Steel Weapons"
101102
],
102103
"unlocked_special_advance": [],
103104
"wonders_build": [],
@@ -186,7 +187,8 @@
186187
"available_leaders": [],
187188
"advances": [
188189
"Farming",
189-
"Mining"
190+
"Mining",
191+
"Steel Weapons"
190192
],
191193
"unlocked_special_advance": [],
192194
"wonders_build": [],

server/tests/test_games/ask_for_siegecraft.outcome.json server/tests/test_games/combat_all_modifiers.outcome0.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"state": {
33
"CustomPhase": {
4-
"SiegecraftPayment": {
4+
"SteelWeaponsAttacker": {
55
"initiation": {
66
"Movement": {
77
"movement_actions_left": 2,
@@ -142,6 +142,7 @@
142142
"Farming",
143143
"Mining",
144144
"Siegecraft",
145+
"Steel Weapons",
145146
"Tactics"
146147
],
147148
"unlocked_special_advance": [],
@@ -231,7 +232,8 @@
231232
"available_leaders": [],
232233
"advances": [
233234
"Farming",
234-
"Mining"
235+
"Mining",
236+
"Steel Weapons"
235237
],
236238
"unlocked_special_advance": [],
237239
"wonders_build": [],

server/tests/test_games/attack_with_siegecraft.json server/tests/test_games/combat_all_modifiers.outcome1.json

+20-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"state": {
33
"CustomPhase": {
4-
"SiegecraftPayment": {
4+
"SteelWeaponsDefender": {
55
"initiation": {
66
"Movement": {
77
"movement_actions_left": 2,
@@ -29,7 +29,10 @@
2929
4,
3030
5
3131
],
32-
"can_retreat": true
32+
"can_retreat": true,
33+
"modifiers": [
34+
"SteelWeaponsAttacker"
35+
]
3336
}
3437
}
3538
},
@@ -40,7 +43,7 @@
4043
"resources": {
4144
"food": 2,
4245
"wood": 7,
43-
"ore": 7,
46+
"ore": 6,
4447
"ideas": 3,
4548
"gold": 7,
4649
"mood_tokens": 7,
@@ -142,6 +145,7 @@
142145
"Farming",
143146
"Mining",
144147
"Siegecraft",
148+
"Steel Weapons",
145149
"Tactics"
146150
],
147151
"unlocked_special_advance": [],
@@ -231,7 +235,8 @@
231235
"available_leaders": [],
232236
"advances": [
233237
"Farming",
234-
"Mining"
238+
"Mining",
239+
"Steel Weapons"
235240
],
236241
"unlocked_special_advance": [],
237242
"wonders_build": [],
@@ -361,9 +366,16 @@
361366
"destination": "C1"
362367
}
363368
}
369+
},
370+
{
371+
"CustomPhase": {
372+
"SteelWeaponsAttackerAction": {
373+
"ore": 1
374+
}
375+
}
364376
}
365377
],
366-
"action_log_index": 6,
378+
"action_log_index": 7,
367379
"log": [
368380
"The game has started",
369381
"Age 1 has started",
@@ -377,9 +389,10 @@
377389
"Player2 ended their turn with 3 actions left",
378390
"It's Player1's turn",
379391
"Round 2/3",
380-
"\tPlayer1 marched 2 settlers, 1 infantry, 1 cavalry, 1 elephant and a leader from C2 to C1"
392+
"\tPlayer1 marched 2 settlers, 1 infantry, 1 cavalry, 1 elephant and a leader from C2 to C1",
393+
"Player1 paid for steel weapons: 1 ore"
381394
],
382-
"undo_limit": 6,
395+
"undo_limit": 7,
383396
"actions_left": 2,
384397
"successful_cultural_influence": false,
385398
"round": 2,

0 commit comments

Comments
 (0)