package game import ( "errors" "fmt" "strings" ) type TileType int const ( neutral TileType = iota + 1 tower gate wall house farm street spawn docks store ) func (t TileType) String() string { switch t { case neutral: return "neutral" case tower: return "tower" case wall: return "wall" case gate: return "gate" case house: return "house" case farm: return "farm" case street: return "street" case spawn: return "spawn" case docks: return "docks" case store: return "store" } return "" } func (t TileType) IsFortification() bool { return t == TileTypes.Wall || t == TileTypes.Gate || t == TileTypes.Tower } var TileTypes = struct { Neutral TileType Tower TileType Wall TileType Gate TileType House TileType Farm TileType Street TileType Spawn TileType Docks TileType Store TileType }{ Neutral: neutral, Tower: tower, Wall: wall, Gate: gate, House: house, Farm: farm, Street: street, Spawn: spawn, Docks: docks, Store: store, } var TileNames = map[string]TileType{ "neutral": neutral, "tower": tower, "wall": wall, "gate": gate, "house": house, "farm": farm, "street": street, "spawn": spawn, "docks": docks, "store": store, } var farmEffect areaEffect = newGrantFullActionEffect("misc/farmer", func(a Action) ActionResolveFunc { u := a.Source().(*Unit) return func(s *LocalState) { controller := u.Controller() controller.gainResource(3) } }, "gain 3 resource", "farmAction") var towerEffect areaEffect = newDynamicAreaEffect( func(p Permanent) { var u *Unit var ok bool if u, ok = p.(*Unit); !ok { return } if u.Attack.MaxRange() < 2 { return } u.Attack.Extend(1) }, func(p Permanent) { var u *Unit var ok bool if u, ok = p.(*Unit); !ok { return } if u.Attack.MaxRange() < 3 { return } u.Attack.Shorten(1) }, ) type Tile struct { Position Position Permanent Permanent Type TileType Water bool Raw string effects []areaEffect } func (t *Tile) String() string { return fmt.Sprintf("%v", t.Position) } func INVALID_TILE() Tile { return Tile{Position: INVALID_POSITION()} } var ErrInvalidTileName = errors.New("unknown tile name") func NewTileFromString(raw string, pos Position) (Tile, error) { tile := strings.ToLower(raw) tokens := strings.Split(tile, " ") tileType, found := TileNames[tokens[0]] if !found { if strings.Contains(tile, "spawn") { tileType = spawn } } water := strings.Contains(tile, "water") t := Tile{Position: pos, Type: tileType, Water: water, Raw: raw} switch tileType { case TileTypes.Farm: t.effects = append(t.effects, farmEffect) case TileTypes.Tower: t.effects = append(t.effects, towerEffect) } return t, nil } func (t *Tile) IsFree() bool { return t.Permanent == nil } func (t *Tile) IsSuitableForCard(card *Card) bool { if t.Water && !card.hasPlacementConstrain("swimming") { return false } if !t.Water && card.hasPlacementConstrain("swimming") { return false } if t.Type == TileTypes.Wall { return false } return true } func (t *Tile) IsAvailableForCard(card *Card) bool { if t.IsFree() { return t.IsSuitableForCard(card) } x, err := t.Permanent.Card().getXEffect("crew") if err != nil { return false } if len(t.Permanent.Pile()) == x.x { return false } return true } func (t *Tile) OnDiagonal(other *Tile) bool { p1, p2 := t.Position, other.Position return p1.X == p2.X-1 && p1.Y == p2.Y-1 || p1.X == p2.X+1 && p1.Y == p2.Y-1 || p1.X == p2.X+1 && p1.Y == p2.Y+1 || p1.X == p2.X-1 && p1.Y == p2.Y+1 } func (t *Tile) entering(p Permanent) { t.Permanent = p if t.Type == TileTypes.Store { p.Controller().addKnownStore(t.Position) } for _, effect := range t.effects { effect.onEntering(p) } } func (t *Tile) leaving(p Permanent) { t.Permanent = nil for _, effect := range t.effects { effect.onLeaving(p) } } func (t *Tile) addEffect(effect areaEffect) { t.effects = append(t.effects, effect) // Apply effect to the current Permanent if t.Permanent != nil { effect.onEntering(t.Permanent) } } func (t *Tile) removeEffect(effect areaEffect) { for i, e := range t.effects { if e == effect { t.effects[i] = t.effects[len(t.effects)-1] t.effects = t.effects[:len(t.effects)-1] break } } // Remove effect from the current Permanent if t.Permanent != nil { effect.onLeaving(t.Permanent) } } func (t *Tile) Neutralize() { if t.Type == TileTypes.Farm { t.removeEffect(farmEffect) } t.Type = TileTypes.Neutral t.Water = false }