feature updates
This commit is contained in:
751
tests/unit/test_effect_resolver.gd
Normal file
751
tests/unit/test_effect_resolver.gd
Normal file
@@ -0,0 +1,751 @@
|
||||
extends GutTest
|
||||
|
||||
## Tests for EffectResolver effect execution
|
||||
## Covers core effects: DAMAGE, POWER_MOD, DULL, ACTIVATE, DRAW, BREAK, RETURN
|
||||
|
||||
|
||||
var resolver: EffectResolver
|
||||
|
||||
|
||||
func before_each() -> void:
|
||||
resolver = EffectResolver.new()
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# DAMAGE EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_damage_basic() -> void:
|
||||
var card = _create_mock_forward(7000)
|
||||
var game_state = _create_mock_game_state_with_forward(card, 0)
|
||||
var effect = {"type": "DAMAGE", "amount": 3000}
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_eq(card.damage_received, 3000, "Card should have received 3000 damage")
|
||||
|
||||
|
||||
func test_resolve_damage_breaks_forward() -> void:
|
||||
var card = _create_mock_forward(5000)
|
||||
var game_state = _create_mock_game_state_with_forward(card, 0)
|
||||
var effect = {"type": "DAMAGE", "amount": 5000}
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_true(game_state.players[0].break_zone.has_card(card), "Forward should be in break zone")
|
||||
assert_false(game_state.players[0].field_forwards.has_card(card), "Forward should not be on field")
|
||||
|
||||
|
||||
func test_resolve_damage_exact_power_breaks() -> void:
|
||||
var card = _create_mock_forward(6000)
|
||||
var game_state = _create_mock_game_state_with_forward(card, 0)
|
||||
var effect = {"type": "DAMAGE", "amount": 6000}
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_true(game_state.players[0].break_zone.has_card(card), "Forward should break when damage equals power")
|
||||
|
||||
|
||||
func test_resolve_damage_multiple_targets() -> void:
|
||||
var card1 = _create_mock_forward(8000)
|
||||
var card2 = _create_mock_forward(5000)
|
||||
var game_state = _create_mock_game_state()
|
||||
game_state.players[0].field_forwards.add_card(card1)
|
||||
game_state.players[0].field_forwards.add_card(card2)
|
||||
card1.controller_index = 0
|
||||
card2.controller_index = 0
|
||||
|
||||
var effect = {"type": "DAMAGE", "amount": 3000}
|
||||
|
||||
resolver.resolve(effect, null, [card1, card2], game_state)
|
||||
|
||||
assert_eq(card1.damage_received, 3000, "First card should have 3000 damage")
|
||||
assert_eq(card2.damage_received, 3000, "Second card should have 3000 damage")
|
||||
|
||||
|
||||
func test_resolve_damage_ignores_non_forwards() -> void:
|
||||
var backup = _create_mock_backup()
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "DAMAGE", "amount": 5000}
|
||||
|
||||
resolver.resolve(effect, null, [backup], game_state)
|
||||
|
||||
assert_eq(backup.damage_received, 0, "Backup should not receive damage")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# POWER_MOD EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_power_mod_positive() -> void:
|
||||
var card = _create_mock_forward(5000)
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "POWER_MOD", "amount": 2000}
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_eq(card.power_modifiers.size(), 1, "Should have one power modifier")
|
||||
assert_eq(card.power_modifiers[0], 2000, "Power modifier should be +2000")
|
||||
|
||||
|
||||
func test_resolve_power_mod_negative() -> void:
|
||||
var card = _create_mock_forward(7000)
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "POWER_MOD", "amount": -3000}
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_eq(card.power_modifiers[0], -3000, "Power modifier should be -3000")
|
||||
|
||||
|
||||
func test_resolve_power_mod_multiple_targets() -> void:
|
||||
var card1 = _create_mock_forward(5000)
|
||||
var card2 = _create_mock_forward(6000)
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "POWER_MOD", "amount": 1000}
|
||||
|
||||
resolver.resolve(effect, null, [card1, card2], game_state)
|
||||
|
||||
assert_eq(card1.power_modifiers[0], 1000, "First card should have +1000")
|
||||
assert_eq(card2.power_modifiers[0], 1000, "Second card should have +1000")
|
||||
|
||||
|
||||
func test_resolve_power_mod_applies_to_source_if_no_targets() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "POWER_MOD", "amount": 3000}
|
||||
|
||||
resolver.resolve(effect, source, [], game_state)
|
||||
|
||||
assert_eq(source.power_modifiers[0], 3000, "Source should get modifier when no targets")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# DULL EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_dull_single_target() -> void:
|
||||
var card = _create_mock_forward(5000)
|
||||
card.activate() # Ensure card starts active
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "DULL"}
|
||||
|
||||
assert_true(card.is_active(), "Card should start active")
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_true(card.is_dull(), "Card should be dulled")
|
||||
|
||||
|
||||
func test_resolve_dull_multiple_targets() -> void:
|
||||
var card1 = _create_mock_forward(5000)
|
||||
var card2 = _create_mock_forward(6000)
|
||||
card1.activate()
|
||||
card2.activate()
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "DULL"}
|
||||
|
||||
resolver.resolve(effect, null, [card1, card2], game_state)
|
||||
|
||||
assert_true(card1.is_dull(), "First card should be dulled")
|
||||
assert_true(card2.is_dull(), "Second card should be dulled")
|
||||
|
||||
|
||||
func test_resolve_dull_already_dull_card() -> void:
|
||||
var card = _create_mock_forward(5000)
|
||||
card.dull() # Already dull
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "DULL"}
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_true(card.is_dull(), "Card should remain dulled")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# ACTIVATE EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_activate_single_target() -> void:
|
||||
var card = _create_mock_forward(5000)
|
||||
card.dull() # Start dull
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "ACTIVATE"}
|
||||
|
||||
assert_true(card.is_dull(), "Card should start dull")
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_true(card.is_active(), "Card should be activated")
|
||||
|
||||
|
||||
func test_resolve_activate_multiple_targets() -> void:
|
||||
var card1 = _create_mock_forward(5000)
|
||||
var card2 = _create_mock_forward(6000)
|
||||
card1.dull()
|
||||
card2.dull()
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "ACTIVATE"}
|
||||
|
||||
resolver.resolve(effect, null, [card1, card2], game_state)
|
||||
|
||||
assert_true(card1.is_active(), "First card should be active")
|
||||
assert_true(card2.is_active(), "Second card should be active")
|
||||
|
||||
|
||||
func test_resolve_activate_already_active_card() -> void:
|
||||
var card = _create_mock_forward(5000)
|
||||
card.activate() # Already active
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "ACTIVATE"}
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_true(card.is_active(), "Card should remain active")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# DRAW EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_draw_single_card() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var game_state = _create_mock_game_state_with_deck(5)
|
||||
var effect = {"type": "DRAW", "amount": 1}
|
||||
|
||||
var initial_deck_size = game_state.players[0].deck.get_count()
|
||||
var initial_hand_size = game_state.players[0].hand.get_count()
|
||||
|
||||
resolver.resolve(effect, source, [], game_state)
|
||||
|
||||
assert_eq(game_state.players[0].deck.get_count(), initial_deck_size - 1, "Deck should have 1 less card")
|
||||
assert_eq(game_state.players[0].hand.get_count(), initial_hand_size + 1, "Hand should have 1 more card")
|
||||
|
||||
|
||||
func test_resolve_draw_multiple_cards() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var game_state = _create_mock_game_state_with_deck(10)
|
||||
var effect = {"type": "DRAW", "amount": 3}
|
||||
|
||||
var initial_deck_size = game_state.players[0].deck.get_count()
|
||||
|
||||
resolver.resolve(effect, source, [], game_state)
|
||||
|
||||
assert_eq(game_state.players[0].deck.get_count(), initial_deck_size - 3, "Deck should have 3 fewer cards")
|
||||
|
||||
|
||||
func test_resolve_draw_opponent() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var game_state = _create_mock_game_state_with_deck(5)
|
||||
# Add cards to opponent's deck too
|
||||
for i in range(5):
|
||||
var deck_card = _create_mock_forward(1000)
|
||||
game_state.players[1].deck.add_card(deck_card)
|
||||
|
||||
var effect = {"type": "DRAW", "amount": 1, "target": {"type": "OPPONENT"}}
|
||||
|
||||
var initial_opp_deck = game_state.players[1].deck.get_count()
|
||||
var initial_opp_hand = game_state.players[1].hand.get_count()
|
||||
|
||||
resolver.resolve(effect, source, [], game_state)
|
||||
|
||||
assert_eq(game_state.players[1].deck.get_count(), initial_opp_deck - 1, "Opponent deck should have 1 less card")
|
||||
assert_eq(game_state.players[1].hand.get_count(), initial_opp_hand + 1, "Opponent hand should have 1 more card")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# BREAK EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_break_single_target() -> void:
|
||||
var card = _create_mock_forward(7000)
|
||||
var game_state = _create_mock_game_state_with_forward(card, 0)
|
||||
var effect = {"type": "BREAK"}
|
||||
|
||||
assert_true(game_state.players[0].field_forwards.has_card(card), "Card should start on field")
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_false(game_state.players[0].field_forwards.has_card(card), "Card should not be on field")
|
||||
assert_true(game_state.players[0].break_zone.has_card(card), "Card should be in break zone")
|
||||
|
||||
|
||||
func test_resolve_break_multiple_targets() -> void:
|
||||
var card1 = _create_mock_forward(5000)
|
||||
var card2 = _create_mock_forward(6000)
|
||||
var game_state = _create_mock_game_state()
|
||||
game_state.players[0].field_forwards.add_card(card1)
|
||||
game_state.players[0].field_forwards.add_card(card2)
|
||||
card1.controller_index = 0
|
||||
card2.controller_index = 0
|
||||
|
||||
var effect = {"type": "BREAK"}
|
||||
|
||||
resolver.resolve(effect, null, [card1, card2], game_state)
|
||||
|
||||
assert_true(game_state.players[0].break_zone.has_card(card1), "First card should be in break zone")
|
||||
assert_true(game_state.players[0].break_zone.has_card(card2), "Second card should be in break zone")
|
||||
|
||||
|
||||
func test_resolve_break_backup() -> void:
|
||||
var backup = _create_mock_backup()
|
||||
var game_state = _create_mock_game_state()
|
||||
game_state.players[0].field_backups.add_card(backup)
|
||||
backup.controller_index = 0
|
||||
|
||||
var effect = {"type": "BREAK"}
|
||||
|
||||
resolver.resolve(effect, null, [backup], game_state)
|
||||
|
||||
assert_true(game_state.players[0].break_zone.has_card(backup), "Backup should be in break zone")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# RETURN EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_return_forward_to_hand() -> void:
|
||||
var card = _create_mock_forward(5000)
|
||||
var game_state = _create_mock_game_state_with_forward(card, 0)
|
||||
var effect = {"type": "RETURN"}
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_false(game_state.players[0].field_forwards.has_card(card), "Card should not be on field")
|
||||
assert_true(game_state.players[0].hand.has_card(card), "Card should be in hand")
|
||||
|
||||
|
||||
func test_resolve_return_backup_to_hand() -> void:
|
||||
var backup = _create_mock_backup()
|
||||
var game_state = _create_mock_game_state()
|
||||
game_state.players[0].field_backups.add_card(backup)
|
||||
backup.controller_index = 0
|
||||
backup.owner_index = 0
|
||||
|
||||
var effect = {"type": "RETURN"}
|
||||
|
||||
resolver.resolve(effect, null, [backup], game_state)
|
||||
|
||||
assert_false(game_state.players[0].field_backups.has_card(backup), "Backup should not be on field")
|
||||
assert_true(game_state.players[0].hand.has_card(backup), "Backup should be in hand")
|
||||
|
||||
|
||||
func test_resolve_return_multiple_targets() -> void:
|
||||
var card1 = _create_mock_forward(5000)
|
||||
var card2 = _create_mock_forward(6000)
|
||||
var game_state = _create_mock_game_state()
|
||||
game_state.players[0].field_forwards.add_card(card1)
|
||||
game_state.players[0].field_forwards.add_card(card2)
|
||||
card1.controller_index = 0
|
||||
card1.owner_index = 0
|
||||
card2.controller_index = 0
|
||||
card2.owner_index = 0
|
||||
|
||||
var effect = {"type": "RETURN"}
|
||||
|
||||
resolver.resolve(effect, null, [card1, card2], game_state)
|
||||
|
||||
assert_true(game_state.players[0].hand.has_card(card1), "First card should be in hand")
|
||||
assert_true(game_state.players[0].hand.has_card(card2), "Second card should be in hand")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# SCALING_EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_scaling_effect_by_forwards() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var target = _create_mock_forward(10000)
|
||||
target.controller_index = 1
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
# Add 3 forwards to controller's field
|
||||
for i in range(3):
|
||||
var forward = _create_mock_forward(4000)
|
||||
forward.controller_index = 0
|
||||
game_state.players[0].field_forwards.add_card(forward)
|
||||
# Add target to opponent's field
|
||||
game_state.players[1].field_forwards.add_card(target)
|
||||
|
||||
var effect = {
|
||||
"type": "SCALING_EFFECT",
|
||||
"base_effect": {"type": "DAMAGE"},
|
||||
"scale_by": "FORWARDS_CONTROLLED",
|
||||
"multiplier": 1000,
|
||||
"scale_filter": {}
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [target], game_state)
|
||||
|
||||
assert_eq(target.damage_received, 3000, "Should deal 3000 damage (3 forwards * 1000)")
|
||||
|
||||
|
||||
func test_resolve_scaling_effect_by_backups() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var target = _create_mock_forward(10000)
|
||||
target.controller_index = 1
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
# Add 4 backups to controller's field
|
||||
for i in range(4):
|
||||
var backup = _create_mock_backup()
|
||||
backup.controller_index = 0
|
||||
game_state.players[0].field_backups.add_card(backup)
|
||||
game_state.players[1].field_forwards.add_card(target)
|
||||
|
||||
var effect = {
|
||||
"type": "SCALING_EFFECT",
|
||||
"base_effect": {"type": "DAMAGE"},
|
||||
"scale_by": "BACKUPS_CONTROLLED",
|
||||
"multiplier": 500,
|
||||
"scale_filter": {}
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [target], game_state)
|
||||
|
||||
assert_eq(target.damage_received, 2000, "Should deal 2000 damage (4 backups * 500)")
|
||||
|
||||
|
||||
func test_resolve_scaling_effect_with_filter() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var target = _create_mock_forward(10000)
|
||||
target.controller_index = 1
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
# Add 2 Fire forwards and 2 Ice forwards
|
||||
for i in range(2):
|
||||
var fire_forward = _create_mock_forward_with_element(Enums.Element.FIRE)
|
||||
fire_forward.controller_index = 0
|
||||
game_state.players[0].field_forwards.add_card(fire_forward)
|
||||
for i in range(2):
|
||||
var ice_forward = _create_mock_forward_with_element(Enums.Element.ICE)
|
||||
ice_forward.controller_index = 0
|
||||
game_state.players[0].field_forwards.add_card(ice_forward)
|
||||
game_state.players[1].field_forwards.add_card(target)
|
||||
|
||||
var effect = {
|
||||
"type": "SCALING_EFFECT",
|
||||
"base_effect": {"type": "DAMAGE"},
|
||||
"scale_by": "FORWARDS_CONTROLLED",
|
||||
"multiplier": 2000,
|
||||
"scale_filter": {"element": "FIRE"} # Only count Fire forwards
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [target], game_state)
|
||||
|
||||
assert_eq(target.damage_received, 4000, "Should deal 4000 damage (2 Fire forwards * 2000)")
|
||||
|
||||
|
||||
func test_resolve_scaling_effect_zero_count() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var target = _create_mock_forward(10000)
|
||||
target.controller_index = 1
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
# No forwards on controller's field
|
||||
game_state.players[1].field_forwards.add_card(target)
|
||||
|
||||
var effect = {
|
||||
"type": "SCALING_EFFECT",
|
||||
"base_effect": {"type": "DAMAGE"},
|
||||
"scale_by": "FORWARDS_CONTROLLED",
|
||||
"multiplier": 1000,
|
||||
"scale_filter": {}
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [target], game_state)
|
||||
|
||||
assert_eq(target.damage_received, 0, "Should deal 0 damage (0 forwards * 1000)")
|
||||
|
||||
|
||||
func test_resolve_scaling_effect_power_mod() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
# Add 2 backups
|
||||
for i in range(2):
|
||||
var backup = _create_mock_backup()
|
||||
backup.controller_index = 0
|
||||
game_state.players[0].field_backups.add_card(backup)
|
||||
|
||||
var effect = {
|
||||
"type": "SCALING_EFFECT",
|
||||
"base_effect": {"type": "POWER_MOD"},
|
||||
"scale_by": "BACKUPS_CONTROLLED",
|
||||
"multiplier": 1000,
|
||||
"scale_filter": {}
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [source], game_state)
|
||||
|
||||
assert_eq(source.power_modifiers[0], 2000, "Should get +2000 power (2 backups * 1000)")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# CONDITIONAL EFFECT TESTS
|
||||
# =============================================================================
|
||||
|
||||
func test_resolve_conditional_then_branch() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var target = _create_mock_forward(7000)
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
game_state.players[0].damage = 5 # 5 damage points
|
||||
|
||||
# Setup ConditionChecker mock
|
||||
resolver.condition_checker = MockConditionChecker.new(true)
|
||||
|
||||
var effect = {
|
||||
"type": "CONDITIONAL",
|
||||
"condition": {"type": "DAMAGE_RECEIVED", "comparison": "GTE", "value": 3},
|
||||
"then_effects": [{"type": "DAMAGE", "amount": 5000}],
|
||||
"else_effects": []
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [target], game_state)
|
||||
|
||||
assert_eq(target.damage_received, 5000, "Should execute then_effects branch")
|
||||
|
||||
|
||||
func test_resolve_conditional_else_branch() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var target = _create_mock_forward(7000)
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
game_state.players[0].damage = 1 # Only 1 damage
|
||||
|
||||
# Setup ConditionChecker mock that returns false
|
||||
resolver.condition_checker = MockConditionChecker.new(false)
|
||||
|
||||
var effect = {
|
||||
"type": "CONDITIONAL",
|
||||
"condition": {"type": "DAMAGE_RECEIVED", "comparison": "GTE", "value": 5},
|
||||
"then_effects": [{"type": "DAMAGE", "amount": 5000}],
|
||||
"else_effects": [{"type": "DAMAGE", "amount": 1000}]
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [target], game_state)
|
||||
|
||||
assert_eq(target.damage_received, 1000, "Should execute else_effects branch")
|
||||
|
||||
|
||||
func test_resolve_conditional_no_else_branch() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var target = _create_mock_forward(7000)
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
|
||||
# Setup ConditionChecker mock that returns false
|
||||
resolver.condition_checker = MockConditionChecker.new(false)
|
||||
|
||||
var effect = {
|
||||
"type": "CONDITIONAL",
|
||||
"condition": {"type": "SOME_CONDITION"},
|
||||
"then_effects": [{"type": "DAMAGE", "amount": 5000}],
|
||||
"else_effects": [] # No else branch
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [target], game_state)
|
||||
|
||||
assert_eq(target.damage_received, 0, "Should do nothing when condition false and no else")
|
||||
|
||||
|
||||
func test_resolve_conditional_multiple_then_effects() -> void:
|
||||
var source = _create_mock_forward(5000)
|
||||
source.controller_index = 0
|
||||
var target = _create_mock_forward(7000)
|
||||
|
||||
var game_state = _create_mock_game_state()
|
||||
|
||||
resolver.condition_checker = MockConditionChecker.new(true)
|
||||
|
||||
var effect = {
|
||||
"type": "CONDITIONAL",
|
||||
"condition": {"type": "ALWAYS_TRUE"},
|
||||
"then_effects": [
|
||||
{"type": "DAMAGE", "amount": 2000},
|
||||
{"type": "POWER_MOD", "amount": -1000}
|
||||
],
|
||||
"else_effects": []
|
||||
}
|
||||
|
||||
resolver.resolve(effect, source, [target], game_state)
|
||||
|
||||
assert_eq(target.damage_received, 2000, "Should apply damage")
|
||||
assert_eq(target.power_modifiers[0], -1000, "Should apply power mod")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# EFFECT_COMPLETED SIGNAL TEST
|
||||
# =============================================================================
|
||||
|
||||
func test_effect_completed_signal_emitted() -> void:
|
||||
var card = _create_mock_forward(5000)
|
||||
var game_state = _create_mock_game_state()
|
||||
var effect = {"type": "DULL"}
|
||||
var signal_received = false
|
||||
var received_effect = {}
|
||||
var received_targets = []
|
||||
|
||||
resolver.effect_completed.connect(func(e, t):
|
||||
signal_received = true
|
||||
received_effect = e
|
||||
received_targets = t
|
||||
)
|
||||
|
||||
resolver.resolve(effect, null, [card], game_state)
|
||||
|
||||
assert_true(signal_received, "effect_completed signal should be emitted")
|
||||
assert_eq(received_effect.type, "DULL", "Signal should contain effect")
|
||||
assert_eq(received_targets.size(), 1, "Signal should contain targets")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# COMBINED DAMAGE AND BREAK TEST
|
||||
# =============================================================================
|
||||
|
||||
func test_damage_accumulates_before_break() -> void:
|
||||
var card = _create_mock_forward(10000)
|
||||
var game_state = _create_mock_game_state_with_forward(card, 0)
|
||||
|
||||
# Apply 4000 damage (shouldn't break)
|
||||
resolver.resolve({"type": "DAMAGE", "amount": 4000}, null, [card], game_state)
|
||||
assert_eq(card.damage_received, 4000, "Should have 4000 damage")
|
||||
assert_true(game_state.players[0].field_forwards.has_card(card), "Should still be on field")
|
||||
|
||||
# Apply 6000 more (total 10000, should break)
|
||||
resolver.resolve({"type": "DAMAGE", "amount": 6000}, null, [card], game_state)
|
||||
assert_true(game_state.players[0].break_zone.has_card(card), "Should be broken with 10000 total damage")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# =============================================================================
|
||||
|
||||
func _create_mock_forward(power: int) -> CardInstance:
|
||||
var card = CardInstance.new()
|
||||
var data = CardDatabase.CardData.new()
|
||||
data.type = Enums.CardType.FORWARD
|
||||
data.power = power
|
||||
data.cost = 3
|
||||
data.name = "Test Forward"
|
||||
data.elements = [Enums.Element.FIRE]
|
||||
card.card_data = data
|
||||
card.current_power = power
|
||||
return card
|
||||
|
||||
|
||||
func _create_mock_backup() -> CardInstance:
|
||||
var card = CardInstance.new()
|
||||
var data = CardDatabase.CardData.new()
|
||||
data.type = Enums.CardType.BACKUP
|
||||
data.cost = 2
|
||||
data.name = "Test Backup"
|
||||
data.elements = [Enums.Element.WATER]
|
||||
card.card_data = data
|
||||
return card
|
||||
|
||||
|
||||
func _create_mock_forward_with_element(element: Enums.Element) -> CardInstance:
|
||||
var card = _create_mock_forward(5000)
|
||||
card.card_data.elements = [element]
|
||||
return card
|
||||
|
||||
|
||||
func _create_mock_game_state() -> MockGameState:
|
||||
return MockGameState.new()
|
||||
|
||||
|
||||
func _create_mock_game_state_with_forward(card: CardInstance, player_index: int) -> MockGameState:
|
||||
var gs = MockGameState.new()
|
||||
gs.players[player_index].field_forwards.add_card(card)
|
||||
card.controller_index = player_index
|
||||
card.owner_index = player_index
|
||||
return gs
|
||||
|
||||
|
||||
func _create_mock_game_state_with_deck(card_count: int) -> MockGameState:
|
||||
var gs = MockGameState.new()
|
||||
for i in range(card_count):
|
||||
var deck_card = _create_mock_forward(1000 + i * 1000)
|
||||
gs.players[0].deck.add_card(deck_card)
|
||||
return gs
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# MOCK CLASSES
|
||||
# =============================================================================
|
||||
|
||||
class MockGameState:
|
||||
var players: Array
|
||||
|
||||
func _init():
|
||||
players = [MockPlayer.new(0), MockPlayer.new(1)]
|
||||
|
||||
func get_player(index: int):
|
||||
if index >= 0 and index < players.size():
|
||||
return players[index]
|
||||
return null
|
||||
|
||||
|
||||
class MockPlayer:
|
||||
var player_index: int
|
||||
var damage: int = 0
|
||||
var deck: Zone
|
||||
var hand: Zone
|
||||
var field_forwards: Zone
|
||||
var field_backups: Zone
|
||||
var break_zone: Zone
|
||||
|
||||
func _init(index: int = 0):
|
||||
player_index = index
|
||||
deck = Zone.new(Enums.ZoneType.DECK, index)
|
||||
hand = Zone.new(Enums.ZoneType.HAND, index)
|
||||
field_forwards = Zone.new(Enums.ZoneType.FIELD, index)
|
||||
field_backups = Zone.new(Enums.ZoneType.FIELD, index)
|
||||
break_zone = Zone.new(Enums.ZoneType.BREAK_ZONE, index)
|
||||
|
||||
func draw_cards(count: int) -> Array:
|
||||
var drawn: Array = []
|
||||
for i in range(count):
|
||||
var card = deck.pop_top_card()
|
||||
if card:
|
||||
hand.add_card(card)
|
||||
drawn.append(card)
|
||||
return drawn
|
||||
|
||||
func break_card(card: CardInstance) -> bool:
|
||||
var removed = false
|
||||
|
||||
if field_forwards.has_card(card):
|
||||
field_forwards.remove_card(card)
|
||||
removed = true
|
||||
elif field_backups.has_card(card):
|
||||
field_backups.remove_card(card)
|
||||
removed = true
|
||||
|
||||
if removed:
|
||||
break_zone.add_card(card)
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
class MockConditionChecker:
|
||||
var _return_value: bool
|
||||
|
||||
func _init(return_value: bool = true):
|
||||
_return_value = return_value
|
||||
|
||||
func evaluate(_condition: Dictionary, _context: Dictionary) -> bool:
|
||||
return _return_value
|
||||
Reference in New Issue
Block a user