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":
|
case "g":
|
||||||
m.s.Input("get")
|
m.s.Input("get")
|
||||||
case "p":
|
case "p":
|
||||||
var res []string
|
var res []sim.ItemEntry
|
||||||
for k := range m.s.Player.Resources {
|
for _, k := range sim.GlobalItemList {
|
||||||
res = append(res, strconv.Itoa(k))
|
if m.s.Player.Resources[k] != 0 {
|
||||||
|
res = append(res, sim.Lookup(k))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return newPlaceModel(res, nil), nil
|
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 {
|
func (m model) View() string {
|
||||||
var render 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()))
|
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
|
return render
|
||||||
}
|
}
|
||||||
|
22
place.go
22
place.go
@ -1,16 +1,21 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
sim "git.saintnet.tech/stryan/spacetea/simulator"
|
||||||
"github.com/charmbracelet/bubbles/list"
|
"github.com/charmbracelet/bubbles/list"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var docStyle = lipgloss.NewStyle().Margin(1, 2)
|
||||||
|
|
||||||
type item struct {
|
type item struct {
|
||||||
title, desc string
|
title, desc, id string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i item) Title() string { return i.title }
|
func (i item) Title() string { return i.title }
|
||||||
func (i item) Description() string { return i.desc }
|
func (i item) Description() string { return i.desc }
|
||||||
|
func (i item) ID() string { return i.id }
|
||||||
func (i item) FilterValue() string { return i.title }
|
func (i item) FilterValue() string { return i.title }
|
||||||
|
|
||||||
type placeModel struct {
|
type placeModel struct {
|
||||||
@ -21,17 +26,17 @@ type placeMsg string
|
|||||||
|
|
||||||
func (p placeModel) buildPlaceMsg() tea.Msg {
|
func (p placeModel) buildPlaceMsg() tea.Msg {
|
||||||
i := p.list.SelectedItem().(item)
|
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
|
var p placeModel
|
||||||
items := []list.Item{}
|
items := []list.Item{}
|
||||||
for _, v := range entries {
|
for _, v := range entries {
|
||||||
items = append(items, item{v, v})
|
items = append(items, item{v.Name(), "no description", v.ID()})
|
||||||
}
|
}
|
||||||
//w,h
|
//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.Title = "What do you want to place?"
|
||||||
p.list.DisableQuitKeybindings()
|
p.list.DisableQuitKeybindings()
|
||||||
return p
|
return p
|
||||||
@ -48,16 +53,17 @@ func (p placeModel) Init() tea.Cmd {
|
|||||||
func (p placeModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (p placeModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.WindowSizeMsg:
|
case tea.WindowSizeMsg:
|
||||||
p.list.SetWidth(msg.Width)
|
h, v := docStyle.GetFrameSize()
|
||||||
|
p.list.SetSize(msg.Width-h, msg.Height-v)
|
||||||
return p, nil
|
return p, nil
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
switch keypress := msg.String(); keypress {
|
switch keypress := msg.String(); keypress {
|
||||||
case "ctrl-c":
|
case "ctrl-c":
|
||||||
return p, tea.Quit
|
return p, tea.Quit
|
||||||
case "esc":
|
case "esc":
|
||||||
return initMainscreen(), nil
|
return initMainscreen(), heartbeat()
|
||||||
case "enter":
|
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
|
//Factory is a game object that can hold resources and produce something
|
||||||
type Factory struct {
|
type Factory struct {
|
||||||
Resources map[int]int
|
Resources map[int]int
|
||||||
|
value int
|
||||||
|
outputType int
|
||||||
Description string
|
Description string
|
||||||
Formula string
|
formula string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Tick a beat
|
||||||
func (f *Factory) Tick() {
|
func (f *Factory) Tick() {
|
||||||
panic("not implemented") // TODO: Implement
|
panic("not implemented") // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Get produce
|
||||||
func (f *Factory) Get() Produce {
|
func (f *Factory) Get() Produce {
|
||||||
panic("not implemented") // TODO: Implement
|
panic("not implemented") // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//String
|
||||||
func (f *Factory) String() string {
|
func (f *Factory) String() string {
|
||||||
panic("not implemented") // TODO: Implement
|
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
|
//Plant is a plant that grows per tick
|
||||||
type Plant struct {
|
type Plant struct {
|
||||||
kind int
|
kind itemType
|
||||||
value int
|
value int
|
||||||
growth 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{
|
return &Plant{
|
||||||
kind: k,
|
kind: k,
|
||||||
value: 0,
|
value: 0,
|
||||||
growth: 0,
|
growth: 0,
|
||||||
|
rate: getPlant(k).rate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Tick one iteration
|
//Tick one iteration
|
||||||
func (p *Plant) Tick() {
|
func (p *Plant) Tick() {
|
||||||
p.growth++
|
p.growth++
|
||||||
if p.growth > 10 {
|
if p.growth > p.rate {
|
||||||
p.value++
|
p.value++
|
||||||
p.growth = 0
|
p.growth = 0
|
||||||
}
|
}
|
||||||
@ -39,10 +45,33 @@ func (p *Plant) Get() Produce {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Plant) String() string {
|
func (p *Plant) String() string {
|
||||||
return strconv.Itoa(p.kind)
|
return Lookup(p.kind).Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
//Describe returns a human useful string
|
//Describe returns a human useful string
|
||||||
func (p *Plant) Describe() 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
|
//Player is a player controlled mob
|
||||||
type Player struct {
|
type Player struct {
|
||||||
Resources map[int]int
|
Resources map[itemType]int
|
||||||
CurrentTile *Tile
|
CurrentTile *Tile
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewPlayer initializes a player
|
//NewPlayer initializes a player
|
||||||
func NewPlayer() *Player {
|
func NewPlayer() *Player {
|
||||||
return &Player{Resources: make(map[int]int)}
|
return &Player{Resources: make(map[itemType]int)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) String() string {
|
func (p *Player) String() string {
|
||||||
var res string
|
var res string
|
||||||
res += "Resources: \n"
|
res += "Resources: \n"
|
||||||
for i := range p.Resources {
|
for _, i := range GlobalItemList {
|
||||||
res += fmt.Sprintf("%v: %v", i, p.Resources[i])
|
if p.Resources[i] != 0 {
|
||||||
|
res += fmt.Sprintf("%v: %v\n", Lookup(i).Name(), p.Resources[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res += "\nLocation: \n"
|
res += "\nLocation: \n"
|
||||||
if p.CurrentTile != nil {
|
if p.CurrentTile != nil {
|
||||||
|
@ -15,17 +15,17 @@ func newPod() *Pod {
|
|||||||
func (p *Pod) Tick() {
|
func (p *Pod) Tick() {
|
||||||
for i := range p.Tiles {
|
for i := range p.Tiles {
|
||||||
for _, v := range p.Tiles[i] {
|
for _, v := range p.Tiles[i] {
|
||||||
if v.Maker != nil {
|
if v.Building != nil {
|
||||||
v.Maker.Tick()
|
v.Building.Tick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Place an item on a tile
|
//Place an item on a tile
|
||||||
func (p *Pod) Place(item Producer, x, y int) bool {
|
func (p *Pod) Place(item Object, x, y int) bool {
|
||||||
if p.Tiles[x][y].Maker == nil {
|
if p.Tiles[x][y].Building == nil {
|
||||||
p.Tiles[x][y].Maker = item
|
p.Tiles[x][y].Building = item
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -52,8 +52,8 @@ func (p *Pod) String() string {
|
|||||||
for _, v := range p.Tiles[i] {
|
for _, v := range p.Tiles[i] {
|
||||||
if v.User != nil {
|
if v.User != nil {
|
||||||
res += "@"
|
res += "@"
|
||||||
} else if v.Maker != nil {
|
} else if v.Building != nil {
|
||||||
res += v.Maker.String()
|
res += v.Building.String()
|
||||||
} else {
|
} else {
|
||||||
res += "."
|
res += "."
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package simulator
|
|||||||
|
|
||||||
//Producer is a game object that producers a material
|
//Producer is a game object that producers a material
|
||||||
type Producer interface {
|
type Producer interface {
|
||||||
|
Object
|
||||||
Tick()
|
Tick()
|
||||||
Get() Produce
|
Get() Produce
|
||||||
String() string
|
String() string
|
||||||
@ -10,6 +11,6 @@ type Producer interface {
|
|||||||
|
|
||||||
//Produce is the result of a producer
|
//Produce is the result of a producer
|
||||||
type Produce struct {
|
type Produce struct {
|
||||||
Kind int
|
Kind itemType
|
||||||
Value int
|
Value int
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package simulator
|
package simulator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -19,9 +18,10 @@ type Simulator struct {
|
|||||||
func NewSimulator() *Simulator {
|
func NewSimulator() *Simulator {
|
||||||
pod := newPod()
|
pod := newPod()
|
||||||
player := NewPlayer()
|
player := NewPlayer()
|
||||||
pod.Place(newPlant(1), 4, 4)
|
pod.Place(newPlant(itemPlantTea), 4, 4)
|
||||||
pod.Tiles[0][0].User = player
|
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
|
//Start begins the simulation, non blocking
|
||||||
@ -40,21 +40,29 @@ func (s *Simulator) Input(cmd string) {
|
|||||||
cmdS := strings.Split(cmd, " ")
|
cmdS := strings.Split(cmd, " ")
|
||||||
switch cmdS[0] {
|
switch cmdS[0] {
|
||||||
case "get":
|
case "get":
|
||||||
if cur.Maker != nil {
|
if cur.Building != nil {
|
||||||
prod := cur.Maker.Get()
|
if cur.Building.Type() == producerObject {
|
||||||
|
build := cur.Building.(Producer)
|
||||||
|
prod := build.Get()
|
||||||
if prod.Kind != 0 && prod.Value > 0 {
|
if prod.Kind != 0 && prod.Value > 0 {
|
||||||
s.Player.Resources[prod.Kind] = s.Player.Resources[prod.Kind] + prod.Value
|
s.Player.Resources[prod.Kind] = s.Player.Resources[prod.Kind] + prod.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case "place":
|
case "place":
|
||||||
if len(cmdS) < 2 {
|
if len(cmdS) < 2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
item := cmdS[1]
|
item := cmdS[1]
|
||||||
if item == strconv.Itoa(1) {
|
if item == itemPlantTea.String() {
|
||||||
res := s.Place.Place(newPlant(1), s.Px, s.Py)
|
res := s.Place.Place(newPlant(itemPlantTea), s.Px, s.Py)
|
||||||
if res {
|
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
|
//Tile is a tile
|
||||||
type Tile struct {
|
type Tile struct {
|
||||||
Maker Producer
|
Building Object
|
||||||
User *Player
|
User *Player
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tile) String() string {
|
func (t *Tile) String() string {
|
||||||
var res string
|
var res string
|
||||||
if t.Maker != nil {
|
if t.Building != nil {
|
||||||
res += fmt.Sprintf("There is a %v here\n", t.Maker.Describe())
|
res += fmt.Sprintf("There is a %v here\n", t.Building.Describe())
|
||||||
} else {
|
} else {
|
||||||
res += "Nothing here"
|
res += "Nothing here"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user