Added terraformer, train scripts.

This commit is contained in:
Andrew Lalis 2018-06-24 09:01:25 +02:00
parent 137b8ff572
commit d2f5211cce
4 changed files with 408 additions and 0 deletions

View File

@ -0,0 +1,31 @@
--[[
Author: Andrew Lalis
File: ir_train_control.lua
Version: 1.0
Last Modified: 12-06-2018
Description:
Library which simplifies functions that are often used with immersive railroads
trains and their track augments.
--]]
local ir_train_control = {}
--Require statements and component definitions.
local component = require("component")
local detector = component.ir_augment_detector
local controller = component.ir_augment_control
--[[
Pulls the ir_train_overhead event, and passes the results to a function defined
elsewhere.
func - function(net_address, augment_type, stock_uuid): Function to handle
pulled events.
--]]
local function ir_train_control.pullTrainEvent(func)
local event_name, net_address, augment_type, stock_uuid = event.pull("ir_train_overhead")
func(net_address, augment_type, stock_uuid)
end
local function ir_train_control.

View File

@ -0,0 +1,81 @@
--[[
Author: Andrew Lalis
File: train_speed_checkpoint.lua
Version: 1.0
Last Modified: 16-06-2018
Script used for helping to control the speed of a train. Use many
computers running this script to calibrate trains to run at a certain speed.
--]]
--Require statements and component definitions.
local component = require("component")
local event = require("event")
local computer = require("computer")
local term = require("term")
local detector = component.ir_augment_detector
local controller = component.ir_augment_control
-- Optimal Speed.
local DESIRED_SPEED = 20
--[[
Shortcut for pulling only train events.
func - function(net_address, augment_type, stock_uuid): function to handle the
train event, with augment type being either DETECTOR or LOCO_CONTROL.
--]]
local function pullTrainEvent(func)
local event_name, net_address, augment_type, stock_uuid = event.pull("ir_train_overhead")
func(net_address, augment_type, stock_uuid)
end
--[[
Determines if a string starts with a given substring.
return - boolean: true if str starts with start, false otherwise.
--]]
local function strStarts(str, start)
return string.sub(str, 1, string.len(start)) == start
end
--[[
Determines if a stock car over the detector is a locomotive by reading info.id
from the detector's info() method. If it begins with rolling_stock/loc, then
it is a locomotive.
--]]
local function isStockLocomotive(id)
return strStarts(id, "rolling_stock/loc")
end
local function balanceSpeed(info, target_speed)
local diff = target_speed - info.speed
local percent_diff = info.speed / target_speed
if diff > 0 then -- We are too slow.
controller.setBrake(0)
controller.setThrottle(info.throttle + percent_diff)
else -- We are too fast.
controller.setThrottle(0)
controller.setBrake(percent_diff)
end
end
local function handleTrainEvent(net_address, augment_type, stock_uuid)
local info = detector.info()
local data = detector.consist()
if not (data and info and isStockLocomotive(info.id)) then
return
end
if (augment_type == "DETECTOR") then
term.clear()
term.setCursor(1, 1)
term.write(" Speed: "..data.speed_km.." Km/h")
term.write(" Dir: "..data.direction)
term.write(" Weight: "..data.weight_kg.." Kg")
end
if (augment_type == "LOCO_CONTROL") then
balanceSpeed(info, DESIRED_SPEED)
end
end
while true do
pullTrainEvent(handleTrainEvent)
end

View File

@ -0,0 +1,84 @@
--[[
Author: Andrew Lalis
File: train_speed_checkpoint.lua
Version: 1.0
Last Modified: 16-06-2018
Script used for helping to control the speed of a train. Use many
computers running this script to calibrate trains to run at a certain speed.
--]]
--Require statements and component definitions.
local component = require("component")
local event = require("event")
local computer = require("computer")
local detector = component.ir_augment_detector
local controller = component.ir_augment_control
local BRAKE_ENABLED = false
--[[
Shortcut for pulling only train events.
func - function(net_address, augment_type, stock_uuid): function to handle the
train event, with augment type being either DETECTOR or LOCO_CONTROL.
--]]
local function pullTrainEvent(func)
local event_name, net_address, augment_type, stock_uuid = event.pull("ir_train_overhead")
func(net_address, augment_type, stock_uuid)
end
--[[
Determines if a string starts with a given substring.
return - boolean: true if str starts with start, false otherwise.
--]]
local function strStarts(str, start)
return string.sub(str, 1, string.len(start)) == start
end
--[[
Determines if a stock car over the detector is a locomotive by reading info.id
from the detector's info() method. If it begins with rolling_stock/loc, then
it is a locomotive.
--]]
local function isStockLocomotive()
local info = detector.info()
return strStarts(info.id, "rolling_stock/loc")
end
--[[
Main function to perform test. Currently configured to determine the distance
needed to stop a train. It does this by waiting for a train to go over the
detector, and then applies full brakes, idle throttle, and the train will slow
to a halt. It also records the current time at which the locomotive was
detected, and some other information that is of use.
net_address - string: the network address of the adapter for the augment.
augment_type - string: either DETECTOR or LOCO_CONTROL.
stock_uuid - string: the unique id of the stock detected.
--]]
local function handleTrainEvent(net_address, augment_type, stock_uuid)
if (augment_type == "DETECTOR") then
local data = detector.consist()
-- Only if there's data, and this is a locomotive, do we continue.
if (data == nil or not isStockLocomotive()) then
return
end
print("Locomotive Data from: "..net_address)
print(" Speed: "..data.speed_km.." Km/h")
print(" Direction: "..data.direction)
print(" Weight: "..data.weight_kg.." Kg")
print(" Tractive Effort: "..data.tractive_effort_N.." N")
print(" Cars: "..data.cars)
print(" TIME: "..os.time())
end
-- In the case that the train is over the control augment, apply changes to locomotive control.
-- Also sound horn.
if (augment_type == "LOCO_CONTROL" and BRAKE_ENABLED) then
controller.setThrottle(0)
controller.setBrake(1)
controller.horn()
end
end
while true do
pullTrainEvent(handleTrainEvent)
end

View File

@ -0,0 +1,212 @@
--[[
Author: Andrew Lalis
File: terraformer.lua
Version: 1.0
Last Modified: 16-06-2018
Description:
This script enables a robot to make drastic, albeit slow, changes to the
terrain of an area, through several sub-functions, such as flattening, filling,
and removal of trees.
--]]
--Require statements and componenent definitions.
local robot = require("robot")
local component = require("component")
local ic = component.inventory_controller
--Runtime Constants defined for this robot.
local SAPLING_NAME = "minecraft:sapling"
local SAPLING_DATA = 0
local BONEMEAL_NAME = "minecraft:dye"
local BONEMEAL_DATA = 15
--Global configuration variables.
--[[
Exits the program.
--]]
local function quit()
print("#--------------------------------#")
print("# Program exited. #")
os.exit()
end
--[[
Select an item, given its name and damage value.
item_name - string: The id string for an item.
item_data - number: The damage value, or variation of an item. Defaults to zero.
return - boolean: True if at least one slot contains the item. That slot is now
selected.
--]]
local function selectItemByName(item_name, item_data)
for i=1,16 do
local stack = ic.getStackInInternalSlot(i)
if (stack ~= nil and stack.name == item_name and stack.damage == item_data) then
robot.select(i)
return true
end
end
return false
end
--[[
Select an item, similar to selectItemByName, but if the item cannot be found,
the user will be prompted to add it to the robot's inventory and press enter to
continue.
item_name - string: The id string for an item.
item_data - number: The damage value, or variation of an item. Defaults to zero.
return - nil: If set to be continuous, then if the item cannot be found, then
the program will exit. If not, it will loop until the item is provided by the
user.
--]]
local function selectSafely(item_name, item_data)
local success = selectItemByName(item_name, item_data)
while not success do
print("Cannot find "..item_name.." in inventory. Please add some, and press enter.")
io.read()
success = selectItemByName(item_name, item_data)
end
end
local function repeatUntilSuccess(robot_func)
local success = robot_func()
while not success do
success = robot_func()
end
end
--[[
Uses the robot's axe to chop a tree, and quits if the lumber axe provided has
less than 10% durability.
--]]
local function chopTree()
local durability = robot.durability()
if continuous and (durability == nil or durability < 0.1) then
print("Inadequate tool to chop trees, exiting.")
quit()
end
while (durability == nil) or (durability < 0.1) do
print("Please ensure that a lumber axe with at least 10% durability is equipped in the tool slot, and press enter.")
io.read()
durability = robot.durability()
end
robot.swing()
end
local function ensureToolDurability()
local n1, n2, n3 = robot.durability()
while (n1 == nil and n2 == "no tool equipped") or (n1 < 0.01) do
print("Please enter a valid tool with enough durability, and press enter.")
io.read()
n1, n2, n3 = robot.durability()
end
end
local function safeSwing(func)
ensureToolDurability()
repeatUntilSuccess(func)
end
local function flattenSpot()
-- First try to dig until it can't dig anymore.
local displacement = 0
while robot.detectUp() do
safeSwing(robot.swingUp)
repeatUntilSuccess(robot.up)
displacement = displacement + 1
end
for i=1, displacement do
repeatUntilSuccess(robot.down)
end
-- Then place any floor blocks if needed.
local success, data = robot.detectDown()
if not (success and data == "solid") then
-- Remove any grass or other obstructions below.
if success then
local obstructed = success
while obstructed do
safeSwing(robot.swingDown)
obstructed, data = robot.detectDown()
end
end
selectSafely("minecraft:dirt", 0)
repeatUntilSuccess(robot.placeDown)
end
end
local function flattenArea(length, width)
for row=1, length do
print("Beginning row "..row.." of "..length..".")
if (robot.detect()) then
safeSwing(robot.swing)
end
repeatUntilSuccess(robot.forward)
if (row%2) == 1 then
robot.turnRight()
else
robot.turnLeft()
end
for col=1, width-1 do
flattenSpot()
if robot.detect() then
safeSwing(robot.swing)
end
repeatUntilSuccess(robot.forward)
end
flattenSpot()
if (row%2) == 1 then
robot.turnLeft()
else
robot.turnRight()
end
end
end
local function getNumberInput(str, lower_bound, upper_bound)
print(str)
local choice = tonumber(io.read())
while (choice == nil or choice < lower_bound or choice > upper_bound) do
print("Invalid input! Enter a number n such that "..lower_bound.." <= n <= "..upper_bound)
choice = tonumber(io.read())
end
return choice
end
local function flattenMenu()
length = getNumberInput("Enter the length (distance forward).", 1, 256)
width = getNumberInput("Enter the width (distance to the right).", 1, 256)
print("Flattening a "..length.." x "..width.." area. Total of "..(length*width).." spots to flatten.")
flattenArea(length, width)
end
local function treeRemovalMenu()
quit()-- Implement this!
end
local function mainMenu()
print("# Andrew's Terraformer #")
print("# Copyright 2018 Andrew Lalis #")
print("#--------------------------------#")
print("1. Flatten")
print("2. Remove Trees (Not yet implemented)")
print("Please enter a number corresponding to one of the options above, or -1 to quit.")
local choice = tonumber(io.read())
if choice == 1 then
flattenMenu()
elseif choice == 2 then
treeRemovalMenu()
else
quit()
end
end
--[[
Main function in which the iterations of the cycle are performed.
--]]
local function main()
mainMenu()
quit()
end
main()