mirror of
https://github.com/mvvasilev/last_light.git
synced 2025-04-18 20:29:52 +03:00
146 lines
3 KiB
Go
146 lines
3 KiB
Go
package model
|
|
|
|
import (
|
|
"mvvasilev/last_light/engine"
|
|
)
|
|
|
|
type Inventory interface {
|
|
Items() []Item
|
|
Shape() engine.Size
|
|
Push(item Item) bool
|
|
Drop(x, y int) Item
|
|
ItemAt(x, y int) Item
|
|
}
|
|
|
|
type BasicInventory struct {
|
|
contents []Item
|
|
shape engine.Size
|
|
}
|
|
|
|
func CreateInventory(shape engine.Size) *BasicInventory {
|
|
inv := new(BasicInventory)
|
|
|
|
inv.contents = make([]Item, 0, shape.Height()*shape.Width())
|
|
inv.shape = shape
|
|
|
|
return inv
|
|
}
|
|
|
|
func (i *BasicInventory) Items() (items []Item) {
|
|
return i.contents
|
|
}
|
|
|
|
func (i *BasicInventory) Shape() engine.Size {
|
|
return i.shape
|
|
}
|
|
|
|
func (inv *BasicInventory) Push(i Item) (success bool) {
|
|
if len(inv.contents) == inv.shape.Area() {
|
|
return false
|
|
}
|
|
|
|
itemType := i.Type()
|
|
|
|
// Try to first find a matching item with capacity
|
|
for index, existingItem := range inv.contents {
|
|
if existingItem == nil {
|
|
continue
|
|
}
|
|
|
|
itemsAreSame := existingItem.Type() == itemType
|
|
bothItemsAreQuantifiable := existingItem.Quantifiable() != nil && i.Quantifiable() != nil
|
|
|
|
if itemsAreSame && bothItemsAreQuantifiable {
|
|
existingCurrent := existingItem.Quantifiable().CurrentQuantity
|
|
incomingCurrent := i.Quantifiable().CurrentQuantity
|
|
existingMax := existingItem.Quantifiable().MaxQuantity
|
|
|
|
// Cannot add even a single more item to this stack, skip it
|
|
if existingItem.Quantifiable().CurrentQuantity+1 > existingItem.Quantifiable().MaxQuantity {
|
|
continue
|
|
}
|
|
|
|
total := existingCurrent + incomingCurrent
|
|
leftOver := engine.AbsInt(existingMax - total)
|
|
|
|
// Existing item is filled, and remained is turned into new stack
|
|
if leftOver > 0 {
|
|
// If we have don't have enough free slots, just say we can't push it
|
|
if index+1 >= inv.shape.Area() {
|
|
return false
|
|
}
|
|
|
|
existingItem.Quantifiable().CurrentQuantity = existingMax
|
|
|
|
i.Quantifiable().CurrentQuantity = leftOver
|
|
|
|
inv.contents[index+1] = i
|
|
|
|
return true
|
|
}
|
|
|
|
// Otherwise, just set the existing item quantity to the total
|
|
existingItem.Quantifiable().CurrentQuantity = total
|
|
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Next, try to find an intermediate empty slot to fit this item into
|
|
for index, existingItem := range inv.contents {
|
|
if existingItem == nil {
|
|
inv.contents[index] = i
|
|
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Finally, just append the new item at the end
|
|
inv.contents = append(inv.contents, i)
|
|
|
|
return true
|
|
}
|
|
|
|
func (i *BasicInventory) Drop(x, y int) Item {
|
|
index := y*i.shape.Width() + x
|
|
|
|
if index > len(i.contents)-1 {
|
|
return nil
|
|
}
|
|
|
|
item := i.contents[index]
|
|
|
|
i.contents[index] = nil
|
|
|
|
return item
|
|
}
|
|
|
|
func (i *BasicInventory) ReduceQuantityAt(x, y int, amount int) {
|
|
it := i.ItemAt(x, y)
|
|
|
|
if it == nil {
|
|
return
|
|
}
|
|
|
|
quantityData := it.Quantifiable()
|
|
|
|
if quantityData != nil {
|
|
if quantityData.CurrentQuantity-amount <= 0 {
|
|
i.Drop(x, y)
|
|
} else {
|
|
quantityData.CurrentQuantity = quantityData.CurrentQuantity - amount
|
|
}
|
|
} else {
|
|
i.Drop(x, y)
|
|
}
|
|
}
|
|
|
|
func (i *BasicInventory) ItemAt(x, y int) (item Item) {
|
|
index := y*i.shape.Width() + x
|
|
|
|
if index > len(i.contents)-1 {
|
|
return nil
|
|
}
|
|
|
|
return i.contents[index]
|
|
}
|