package game import ( "strings" "testing" "muhq.space/muhqs-game/go/utils" ) func TestPioneerFullAction(t *testing.T) { mapDef := `map: |1- HST H H FW symbols: T: tower H: house F: farm S: street W: deep water ` s := NewLocalState() m, _ := readMap(strings.NewReader(mapDef)) s.SetMap(m) player := s.AddNewPlayer("p", NewDeck()) p := s.addNewUnit(NewCard("base/pioneer"), Position{1, 1}, player) sword := s.addNewEquipment(NewCard("base/sword"), Position{0, 1}, player) palisade := s.addNewArtifact(NewCard("base/palisade"), Position{0, 0}, player) a := p.FullActions[0] opts := a.Target().Options() if len(opts) != 11 { t.Fatal("expexted 11 targets to neutralize") } if !utils.InterfaceSliceContains(opts, sword) { t.Fatal("sword is missing") } if !utils.InterfaceSliceContains(opts, palisade) { t.Fatal("palisade is missing") } _ = a.Target().AddSelection(m.TileAt(Position{0, 1})) s.ResolveAction(a) if m.TileAt(Position{0, 1}).Type != TileTypes.Neutral { t.Fatal("tile not neutralized") } a = p.FullActions[0] if len(a.Target().Selection()) != 0 { t.Fatal("full action still has target selection") } _ = a.Target().AddSelection(palisade) s.ResolveAction(a) if m.TileAt(Position{0, 0}).Permanent != nil { t.Fatal("palisade not destroyed") } } func TestPikemanRange(t *testing.T) { mapDef := `map: |1- SSS SSS SHS symbols: S: street H: house ` s := NewLocalState() m, _ := readMap(strings.NewReader(mapDef)) s.SetMap(m) player := s.AddNewPlayer("p", NewDeck()) opo := s.AddNewPlayer("o", NewDeck()) p := s.addNewUnit(NewCard("base/pikeman"), Position{0, 0}, player) c := s.addNewUnit(NewCard("base/cavalry"), Position{0, 2}, opo) prot := s.addNewUnit(NewCard("base/cavalry_archer"), Position{1, 2}, opo) ca := s.addNewUnit(NewCard("base/cavalry_archer"), Position{2, 1}, opo) k := s.addNewUnit(NewCard("base/knight"), Position{2, 0}, opo) attackable := utils.TypedSliceToInterfaceSlice(p.AttackableEnemyPermanents()) if !utils.InterfaceSliceContains(attackable, c) { t.Fatal("cavalry not attackable") } if !utils.InterfaceSliceContains(attackable, ca) { t.Fatal("cavalry archer not attackable") } if utils.InterfaceSliceContains(attackable, k) { t.Fatal("knight is attackable") } if utils.InterfaceSliceContains(attackable, prot) { t.Fatal("cavalry is protected") } a := NewAttackAction(p) err := a.Target().AddSelection(c) if err != nil { t.Fatal("invalid target:", err) } s.ResolveAction(a) if !c.IsDestroyed() { t.Fatal("cavalry not destroyed") } a.Target().ClearSelection() err = a.Target().AddSelection(ca) if err != nil { t.Fatal("invalid target:", err) } s.ResolveAction(a) if !c.IsDestroyed() { t.Fatal("cavalry archer not destroyed") } if p.Damage() != 1 { t.Fatal("pikeman not damaged") } a.Target().ClearSelection() err = a.Target().AddSelection(k) if err == nil { t.Fatal("unexpected valid target") } } func TestMissionary(t *testing.T) { mapDef := `map: |1- SSS SSS SHS symbols: S: street H: house ` s := NewLocalState() m, _ := readMap(strings.NewReader(mapDef)) s.SetMap(m) player := s.AddNewPlayer("p", NewDeck()) opo := s.AddNewPlayer("o", NewDeck()) mis := s.addNewUnit(NewCard("base/missionary"), Position{0, 0}, player) king := s.addNewUnit(NewCard("misc/king"), Position{0, 2}, opo) k := s.addNewUnit(NewCard("base/knight"), Position{2, 0}, opo) r := s.addNewUnit(NewCard("base/recruit"), Position{2, 1}, opo) a := mis.FullActions[0] err := a.Target().AddSelection(king) if err != nil { t.Fatal("invalid target:", err) } for range 20 { a.resolve(s) if king.controller != king.owner { t.Fatal("king not controlled by its owner") } } a.Target().ClearSelection() _ = a.Target().AddSelection(k) a.resolve(s) if k.controller != k.owner { t.Fatal("knight not controlled by its owner") } s.ResolveAction(a) if k.controller != player { t.Fatal("knight not controlled by player") } // recruit a.Target().ClearSelection() _ = a.Target().AddSelection(r) s.ResolveAction(a) if r.controller != player { t.Fatal("recruit not controlled by player") } // TODO: test return to owner } func TestMace(t *testing.T) { s := NewLocalState() m := newEmpty2x2Map() s.SetMap(m) player := s.AddNewPlayer("p", NewDeck()) ctrl := newMockPlayerControl(player) ctrl.actionToSend = NewPassPriority(player) player.Ctrl = ctrl opo := s.AddNewPlayer("o", NewDeck()) ctrl = newMockPlayerControl(opo) ctrl.actionToSend = NewPassPriority(opo) opo.Ctrl = ctrl k := s.addNewUnit(NewCard("base/knight"), Position{0, 0}, player) p := s.addNewUnit(NewCard("base/pioneer"), Position{0, 1}, opo) mace := newEquipment(NewCard("equipments/mace"), k, player) s.addPermanent(mace) if len(s.triggers) == 0 { t.Fatal("mace trigger not registered") } s.fight(k, p) s.stateBasedActions() if len(s.stack.Actions) == 0 { t.Fatal("mace not triggered") } s.stack.resolve() if p.Marks(UnitStates.Paralysis) != 1 { t.Fatal("pioneer not paralysed") } s.destroyPermanent(mace) if len(s.triggers) != 0 { t.Fatal("mace trigger not removed") } } func TestArmor(t *testing.T) { s := NewLocalState() m := newEmpty2x2Map() s.SetMap(m) player := s.AddNewPlayer("p", NewDeck()) opo := s.AddNewPlayer("o", NewDeck()) a := s.addNewUnit(NewCard("base/archer"), Position{0, 0}, player) p := s.addNewUnit(NewCard("base/pioneer"), Position{0, 1}, opo) armor := newEquipment(NewCard("equipments/armor"), p, opo) s.addPermanent(armor) if armor, err := p.XEffect("armor"); armor != 1 { t.Fatal("pioneer not armored", armor, err) } s.fight(a, p) if p.Damage() != 0 { t.Fatal("pioneer received damage") } }