add converters
This commit is contained in:
parent
ab12a9b26a
commit
7e8e241164
@ -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
|
||||
}
|
||||
|
22
place.go
22
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())
|
||||
}
|
||||
}
|
||||
|
||||
|
7
simulator/consumer.go
Normal file
7
simulator/consumer.go
Normal 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
71
simulator/converter.go
Normal 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()
|
||||
}
|
@ -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
39
simulator/item_table.go
Normal 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
17
simulator/object.go
Normal 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
|
||||
)
|
@ -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()
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 += "."
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,21 +40,29 @@ func (s *Simulator) Input(cmd string) {
|
||||
cmdS := strings.Split(cmd, " ")
|
||||
switch cmdS[0] {
|
||||
case "get":
|
||||
if cur.Maker != nil {
|
||||
prod := cur.Maker.Get()
|
||||
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":
|
||||
if len(cmdS) < 2 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,14 @@ import (
|
||||
|
||||
//Tile is a tile
|
||||
type Tile struct {
|
||||
Maker Producer
|
||||
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"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user