From 7e8e2411644639a4db1a738cc4656fd355b463dd Mon Sep 17 00:00:00 2001 From: Steve Date: Thu, 19 May 2022 17:09:46 -0400 Subject: [PATCH] add converters --- mainscreen.go | 10 +++--- place.go | 22 ++++++++----- simulator/consumer.go | 7 ++++ simulator/converter.go | 71 +++++++++++++++++++++++++++++++++++++++++ simulator/factory.go | 7 +++- simulator/item_table.go | 39 ++++++++++++++++++++++ simulator/object.go | 17 ++++++++++ simulator/plant.go | 39 +++++++++++++++++++--- simulator/player.go | 10 +++--- simulator/pod.go | 14 ++++---- simulator/producer.go | 3 +- simulator/simulator.go | 28 ++++++++++------ simulator/tile.go | 8 ++--- 13 files changed, 231 insertions(+), 44 deletions(-) create mode 100644 simulator/consumer.go create mode 100644 simulator/converter.go create mode 100644 simulator/item_table.go create mode 100644 simulator/object.go diff --git a/mainscreen.go b/mainscreen.go index 762ad27..2bbefdc 100644 --- a/mainscreen.go +++ b/mainscreen.go @@ -99,9 +99,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "g": m.s.Input("get") case "p": - var res []string - for k := range m.s.Player.Resources { - res = append(res, strconv.Itoa(k)) + var res []sim.ItemEntry + for _, k := range sim.GlobalItemList { + if m.s.Player.Resources[k] != 0 { + res = append(res, sim.Lookup(k)) + } } return newPlaceModel(res, nil), nil } @@ -116,7 +118,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m model) View() string { var render string - display := lipgloss.JoinHorizontal(0, style.Render(m.s.Place.String()), style.Render(fmt.Sprintf("Player\n%v", m.s.Player.String()))) + display := lipgloss.JoinHorizontal(0, style.Render(m.s.Place.String()), style.Render(fmt.Sprintf("%v", m.s.Player.String()))) render = fmt.Sprintf("%v\n%v\n%v\n", style.Render(fmt.Sprintf("Current Time: %v", strconv.Itoa(m.s.Time))), display, style.Render(m.input.View())) return render } diff --git a/place.go b/place.go index 61a6757..ee0f0be 100644 --- a/place.go +++ b/place.go @@ -1,16 +1,21 @@ package main import ( + sim "git.saintnet.tech/stryan/spacetea/simulator" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" ) +var docStyle = lipgloss.NewStyle().Margin(1, 2) + type item struct { - title, desc string + title, desc, id string } func (i item) Title() string { return i.title } func (i item) Description() string { return i.desc } +func (i item) ID() string { return i.id } func (i item) FilterValue() string { return i.title } type placeModel struct { @@ -21,17 +26,17 @@ type placeMsg string func (p placeModel) buildPlaceMsg() tea.Msg { i := p.list.SelectedItem().(item) - return placeMsg(i.Title()) + return placeMsg(i.ID()) } -func newPlaceModel(entries []string, m tea.Model) placeModel { +func newPlaceModel(entries []sim.ItemEntry, m tea.Model) placeModel { var p placeModel items := []list.Item{} for _, v := range entries { - items = append(items, item{v, v}) + items = append(items, item{v.Name(), "no description", v.ID()}) } //w,h - p.list = list.New(items, list.NewDefaultDelegate(), 0, 0) + p.list = list.New(items, list.NewDefaultDelegate(), 32, 32) p.list.Title = "What do you want to place?" p.list.DisableQuitKeybindings() return p @@ -48,16 +53,17 @@ func (p placeModel) Init() tea.Cmd { func (p placeModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: - p.list.SetWidth(msg.Width) + h, v := docStyle.GetFrameSize() + p.list.SetSize(msg.Width-h, msg.Height-v) return p, nil case tea.KeyMsg: switch keypress := msg.String(); keypress { case "ctrl-c": return p, tea.Quit case "esc": - return initMainscreen(), nil + return initMainscreen(), heartbeat() case "enter": - return initMainscreen(), p.buildPlaceMsg + return initMainscreen(), tea.Batch(p.buildPlaceMsg, heartbeat()) } } diff --git a/simulator/consumer.go b/simulator/consumer.go new file mode 100644 index 0000000..a9923de --- /dev/null +++ b/simulator/consumer.go @@ -0,0 +1,7 @@ +package simulator + +//Consumer is a game object that consumes resources +type Consumer interface { + Object + Tick() +} diff --git a/simulator/converter.go b/simulator/converter.go new file mode 100644 index 0000000..9d86f0c --- /dev/null +++ b/simulator/converter.go @@ -0,0 +1,71 @@ +package simulator + +import ( + "fmt" +) + +//Converter is a object that converts one item into another per tick +type Converter struct { + kind itemType + rate int + source itemType + output itemType + owner *Player +} + +func newConverter(k itemType, o *Player) *Converter { + return &Converter{ + kind: k, + rate: getConverter(k).rate, + source: getConverter(k).source, + output: getConverter(k).output, + owner: o, + } +} + +//Tick one iteration +func (c *Converter) Tick() { + if c.owner.Resources[c.source] > c.rate { + c.owner.Resources[c.source] = c.owner.Resources[c.source] - c.rate + c.owner.Resources[c.output] = c.owner.Resources[c.output] + 1 + } +} + +func (c *Converter) String() string { + return Lookup(c.kind).Render() +} + +//Describe returns human useful string +func (c *Converter) Describe() string { + output := getConverter(c.kind).output + return fmt.Sprintf("a %v converter that outputs %v", Lookup(c.kind).Name(), Lookup(output).Name()) +} + +//Type returns consumer +func (c *Converter) Type() ObjectType { + return consumerObject +} + +func getConverter(k itemType) converterEntry { + return Lookup(k).(converterEntry) +} + +type converterEntry struct { + id itemType + rate int + name string + source itemType + output itemType +} + +func (c converterEntry) Name() string { + return c.name +} + +func (c converterEntry) Render() string { + return "m" +} + +func (c converterEntry) ID() string { + return c.id.String() +} diff --git a/simulator/factory.go b/simulator/factory.go index b1929bf..8250c79 100644 --- a/simulator/factory.go +++ b/simulator/factory.go @@ -3,18 +3,23 @@ package simulator //Factory is a game object that can hold resources and produce something type Factory struct { Resources map[int]int + value int + outputType int Description string - Formula string + formula string } +//Tick a beat func (f *Factory) Tick() { panic("not implemented") // TODO: Implement } +//Get produce func (f *Factory) Get() Produce { panic("not implemented") // TODO: Implement } +//String func (f *Factory) String() string { panic("not implemented") // TODO: Implement } diff --git a/simulator/item_table.go b/simulator/item_table.go new file mode 100644 index 0000000..5492207 --- /dev/null +++ b/simulator/item_table.go @@ -0,0 +1,39 @@ +package simulator + +import "strconv" + +//ItemEntry is a human/ui friendly item description +type ItemEntry interface { + Name() string + Render() string + ID() string +} + +type itemType int + +func (i itemType) String() string { + return strconv.Itoa(int(i)) +} + +const ( + itemPlantTea itemType = iota + 1 + itemPlantWood + + convertPulper +) + +//GlobalItemList of all items +var GlobalItemList = []itemType{itemPlantTea, itemPlantWood, convertPulper} + +//Lookup returns a human friendly item entry +func Lookup(id itemType) ItemEntry { + switch id { + case itemPlantTea: + return plantEntry{itemPlantTea, 3, "tea"} + case itemPlantWood: + return plantEntry{itemPlantWood, 10, "wood"} + case convertPulper: + return converterEntry{convertPulper, 5, "teaConverter", itemPlantTea, itemPlantWood} + } + return nil +} diff --git a/simulator/object.go b/simulator/object.go new file mode 100644 index 0000000..d1d3a4f --- /dev/null +++ b/simulator/object.go @@ -0,0 +1,17 @@ +package simulator + +//Object is anything that can be placed in a pod +type Object interface { + Type() ObjectType + Tick() + String() string + Describe() string +} + +//ObjectType is what kind of game object it is +type ObjectType int + +const ( + producerObject ObjectType = iota + consumerObject +) diff --git a/simulator/plant.go b/simulator/plant.go index 90bab50..50d7dd8 100644 --- a/simulator/plant.go +++ b/simulator/plant.go @@ -7,23 +7,29 @@ import ( //Plant is a plant that grows per tick type Plant struct { - kind int + kind itemType value int growth int + rate int } -func newPlant(k int) *Plant { +func getPlant(k itemType) plantEntry { + return Lookup(k).(plantEntry) +} + +func newPlant(k itemType) *Plant { return &Plant{ kind: k, value: 0, growth: 0, + rate: getPlant(k).rate, } } //Tick one iteration func (p *Plant) Tick() { p.growth++ - if p.growth > 10 { + if p.growth > p.rate { p.value++ p.growth = 0 } @@ -39,10 +45,33 @@ func (p *Plant) Get() Produce { } func (p *Plant) String() string { - return strconv.Itoa(p.kind) + return Lookup(p.kind).Render() } //Describe returns a human useful string func (p *Plant) Describe() string { - return fmt.Sprintf("A %v plant with %v value", strconv.Itoa(p.kind), strconv.Itoa(p.value)) + return fmt.Sprintf("a %v plant with %v value", Lookup(p.kind).Name(), strconv.Itoa(p.value)) +} + +//Type returns producer +func (p *Plant) Type() ObjectType { + return producerObject +} + +type plantEntry struct { + id itemType + rate int + name string +} + +func (p plantEntry) Render() string { + return "w" +} + +func (p plantEntry) Name() string { + return p.name +} + +func (p plantEntry) ID() string { + return p.id.String() } diff --git a/simulator/player.go b/simulator/player.go index 5a28601..dd30de1 100644 --- a/simulator/player.go +++ b/simulator/player.go @@ -6,20 +6,22 @@ import ( //Player is a player controlled mob type Player struct { - Resources map[int]int + Resources map[itemType]int CurrentTile *Tile } //NewPlayer initializes a player func NewPlayer() *Player { - return &Player{Resources: make(map[int]int)} + return &Player{Resources: make(map[itemType]int)} } func (p *Player) String() string { var res string res += "Resources: \n" - for i := range p.Resources { - res += fmt.Sprintf("%v: %v", i, p.Resources[i]) + for _, i := range GlobalItemList { + if p.Resources[i] != 0 { + res += fmt.Sprintf("%v: %v\n", Lookup(i).Name(), p.Resources[i]) + } } res += "\nLocation: \n" if p.CurrentTile != nil { diff --git a/simulator/pod.go b/simulator/pod.go index f60ca52..7c9c13b 100644 --- a/simulator/pod.go +++ b/simulator/pod.go @@ -15,17 +15,17 @@ func newPod() *Pod { func (p *Pod) Tick() { for i := range p.Tiles { for _, v := range p.Tiles[i] { - if v.Maker != nil { - v.Maker.Tick() + if v.Building != nil { + v.Building.Tick() } } } } //Place an item on a tile -func (p *Pod) Place(item Producer, x, y int) bool { - if p.Tiles[x][y].Maker == nil { - p.Tiles[x][y].Maker = item +func (p *Pod) Place(item Object, x, y int) bool { + if p.Tiles[x][y].Building == nil { + p.Tiles[x][y].Building = item return true } return false @@ -52,8 +52,8 @@ func (p *Pod) String() string { for _, v := range p.Tiles[i] { if v.User != nil { res += "@" - } else if v.Maker != nil { - res += v.Maker.String() + } else if v.Building != nil { + res += v.Building.String() } else { res += "." } diff --git a/simulator/producer.go b/simulator/producer.go index 2fb0a7b..cf51fa0 100644 --- a/simulator/producer.go +++ b/simulator/producer.go @@ -2,6 +2,7 @@ package simulator //Producer is a game object that producers a material type Producer interface { + Object Tick() Get() Produce String() string @@ -10,6 +11,6 @@ type Producer interface { //Produce is the result of a producer type Produce struct { - Kind int + Kind itemType Value int } diff --git a/simulator/simulator.go b/simulator/simulator.go index 2aa93c5..a114ad9 100644 --- a/simulator/simulator.go +++ b/simulator/simulator.go @@ -1,7 +1,6 @@ package simulator import ( - "strconv" "strings" "time" ) @@ -19,9 +18,10 @@ type Simulator struct { func NewSimulator() *Simulator { pod := newPod() player := NewPlayer() - pod.Place(newPlant(1), 4, 4) + pod.Place(newPlant(itemPlantTea), 4, 4) pod.Tiles[0][0].User = player - return &Simulator{pod, NewPlayer(), 0, 0, 0, make(chan bool)} + player.Resources[convertPulper] = 1 + return &Simulator{pod, player, 0, 0, 0, make(chan bool)} } //Start begins the simulation, non blocking @@ -40,10 +40,13 @@ func (s *Simulator) Input(cmd string) { cmdS := strings.Split(cmd, " ") switch cmdS[0] { case "get": - if cur.Maker != nil { - prod := cur.Maker.Get() - if prod.Kind != 0 && prod.Value > 0 { - s.Player.Resources[prod.Kind] = s.Player.Resources[prod.Kind] + prod.Value + if cur.Building != nil { + if cur.Building.Type() == producerObject { + build := cur.Building.(Producer) + prod := build.Get() + if prod.Kind != 0 && prod.Value > 0 { + s.Player.Resources[prod.Kind] = s.Player.Resources[prod.Kind] + prod.Value + } } } case "place": @@ -51,10 +54,15 @@ func (s *Simulator) Input(cmd string) { return } item := cmdS[1] - if item == strconv.Itoa(1) { - res := s.Place.Place(newPlant(1), s.Px, s.Py) + if item == itemPlantTea.String() { + res := s.Place.Place(newPlant(itemPlantTea), s.Px, s.Py) if res { - s.Player.Resources[1] = s.Player.Resources[1] - 1 + s.Player.Resources[itemPlantTea] = s.Player.Resources[itemPlantTea] - 1 + } + } else if item == convertPulper.String() { + res := s.Place.Place(newConverter(convertPulper, s.Player), s.Px, s.Py) + if res { + s.Player.Resources[convertPulper] = s.Player.Resources[convertPulper] - 1 } } diff --git a/simulator/tile.go b/simulator/tile.go index 21a912a..a5b75d2 100644 --- a/simulator/tile.go +++ b/simulator/tile.go @@ -6,14 +6,14 @@ import ( //Tile is a tile type Tile struct { - Maker Producer - User *Player + Building Object + User *Player } func (t *Tile) String() string { var res string - if t.Maker != nil { - res += fmt.Sprintf("There is a %v here\n", t.Maker.Describe()) + if t.Building != nil { + res += fmt.Sprintf("There is a %v here\n", t.Building.Describe()) } else { res += "Nothing here" }