add converters

This commit is contained in:
stryan 2022-05-19 17:09:46 -04:00
parent ab12a9b26a
commit 7e8e241164
13 changed files with 231 additions and 44 deletions

View File

@ -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
}

View File

@ -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())
}
}

7
simulator/consumer.go Normal file
View File

@ -0,0 +1,7 @@
package simulator
//Consumer is a game object that consumes resources
type Consumer interface {
Object
Tick()
}

71
simulator/converter.go Normal file
View File

@ -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()
}

View File

@ -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
}

39
simulator/item_table.go Normal file
View File

@ -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
}

17
simulator/object.go Normal file
View File

@ -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
)

View File

@ -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()
}

View File

@ -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 {

View File

@ -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 += "."
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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"
}