Skip to content

Instantly share code, notes, and snippets.

@BryanHaley
Last active July 13, 2021 06:36
Show Gist options
  • Save BryanHaley/1d2d9f3fca18607cf4dd80480eb63780 to your computer and use it in GitHub Desktop.
Save BryanHaley/1d2d9f3fca18607cf4dd80480eb63780 to your computer and use it in GitHub Desktop.
COMPUTERCRAFT: Point of sale machine for potato vending machine
-- Globals
STATES = {}
CURRENT_STATE = nil
NUM_SLOTS = 16
PRICES = {
["minecraft:coal"] = 1,
["minecraft:iron_ingot"] = 6,
["minecraft:diamond"] = 45,
["minecraft:netherite_ingot"] = 100,
["minecraft:bone_meal"] = 2,
["minecraft:arrow"] = 4
}
-- Utils
function succ()
for i = 1, NUM_SLOTS, 1 do
turtle.suck()
end
end
function empty_inventory()
for i = 1, NUM_SLOTS, 1 do
turtle.select(i)
turtle.drop()
end
end
-- State machine
function sm_switch_states(new_state, args)
if (CURRENT_STATE ~= nil) then
CURRENT_STATE:exit()
end
CURRENT_STATE = new_state
CURRENT_STATE:enter(args)
end
-- States
-- Idle: Waits for someone to throw it items
IDLE_STATE = {}
function IDLE_STATE:enter(args)
empty_inventory()
end
function IDLE_STATE:execute()
-- Succ then check inventory for changes. Can't use event because it is blocking.
succ()
for i = 1, NUM_SLOTS, 1 do
local x = turtle.getItemDetail(i)
if (x ~= nil) then
sm_switch_states(STATES['exchange'], nil);
return
end
end
os.sleep(0.25)
end
function IDLE_STATE:exit()
-- Do nothing
end
-- Exchange: Calculates the value of items in inventory and drops them into store chest
EXCHANGE_STATE = {}
function EXCHANGE_STATE:enter(args)
-- Do nothing
end
function EXCHANGE_STATE:execute()
-- Go through inventory and calculate value
local value = 0
for i = 1, NUM_SLOTS, 1 do
x = turtle.getItemDetail(i)
if (x ~= nil) then
if PRICES[x["name"]] ~= nil then
value = value + (x['count'] * PRICES[x["name"]])
turtle.dropDown()
else
turtle.drop()
end
end
end
if (value > 0) then
sm_switch_states(STATES['dispense'], value)
return
else
sm_switch_states(STATES['idle'], nil)
return
end
end
function EXCHANGE_STATE:exit()
-- Make sure inventory is empty
empty_inventory()
end
-- Dispense: Grab potatoes from the chest and dispense them
DISPENSE_STATE = { num_potatoes = 0 }
function DISPENSE_STATE:enter(args)
if (args == 0 or not args) then
sm_switch_states(STATES['idle'], nil)
return
end
DISPENSE_STATE.num_potatoes = args
end
function DISPENSE_STATE:execute()
while (DISPENSE_STATE.num_potatoes > 0) do
local num_thrown = DISPENSE_STATE:grab_and_throw(DISPENSE_STATE.num_potatoes)
DISPENSE_STATE.num_potatoes = DISPENSE_STATE.num_potatoes - num_thrown
end
sm_switch_states(STATES['idle'], nil)
return
end
function DISPENSE_STATE:grab_and_throw(num_to_grab)
turtle.turnRight()
turtle.turnRight()
for i = 1, math.floor(num_to_grab/64), 1 do
success = turtle.suck(64)
if not success then break end
end
turtle.suck(num_to_grab%64)
-- Check how many potatoes we're actually going to throw
local num_thrown = 0
for i = 1, NUM_SLOTS, 1 do
x = turtle.getItemCount(i)
num_thrown = num_thrown + x
end
turtle.turnLeft()
turtle.turnLeft()
empty_inventory()
return num_thrown
end
function DISPENSE_STATE:exit()
-- Make sure inventory is empty
empty_inventory()
end
-- Main thread
STATES['idle'] = IDLE_STATE
STATES['exchange'] = EXCHANGE_STATE
STATES['dispense'] = DISPENSE_STATE
sm_switch_states(STATES['idle'], nil)
while (true) do
CURRENT_STATE:execute()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment