From d2f5211cce16a86828b4cc3386e4bf95ec25293e Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Sun, 24 Jun 2018 09:01:25 +0200 Subject: [PATCH] Added terraformer, train scripts. --- libs/ir_train_control/ir_train_control.lua | 31 +++ .../train_speed_checkpoint.lua | 81 +++++++ scripts/ir_train_speed_checkpoint | 84 +++++++ scripts/terraformer/terraformer.lua | 212 ++++++++++++++++++ 4 files changed, 408 insertions(+) create mode 100644 libs/ir_train_control/ir_train_control.lua create mode 100644 scripts/ir_speed_checkpoint/train_speed_checkpoint.lua create mode 100644 scripts/ir_train_speed_checkpoint create mode 100644 scripts/terraformer/terraformer.lua diff --git a/libs/ir_train_control/ir_train_control.lua b/libs/ir_train_control/ir_train_control.lua new file mode 100644 index 0000000..fcbf247 --- /dev/null +++ b/libs/ir_train_control/ir_train_control.lua @@ -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. diff --git a/scripts/ir_speed_checkpoint/train_speed_checkpoint.lua b/scripts/ir_speed_checkpoint/train_speed_checkpoint.lua new file mode 100644 index 0000000..eda8e2d --- /dev/null +++ b/scripts/ir_speed_checkpoint/train_speed_checkpoint.lua @@ -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 \ No newline at end of file diff --git a/scripts/ir_train_speed_checkpoint b/scripts/ir_train_speed_checkpoint new file mode 100644 index 0000000..2dad273 --- /dev/null +++ b/scripts/ir_train_speed_checkpoint @@ -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 \ No newline at end of file diff --git a/scripts/terraformer/terraformer.lua b/scripts/terraformer/terraformer.lua new file mode 100644 index 0000000..b5315ef --- /dev/null +++ b/scripts/terraformer/terraformer.lua @@ -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() \ No newline at end of file