JanetRossini.github.io

Lua, LSL, Blender, Python in Second Life


Project maintained by JanetRossini

Simpler Shunting Idea

May 12, 2025 • [designluaobjectsshunting]


I have a sort of half an idea for making the testing of plans easier. Let me explain.

The basic operations that the Locomotive can do seem to me to come down to just a few: it can move to its home location, it can move to the head of one of the sidings, it can pull 1, 2, or 3 cars out of a siding, or it can push 1, 2, or 3 cars into a siding. (All these are subject to there being room to push and cars to pull, of course.)

So why can’t a plan of action be just a sequence of two-character commands, like this: “m1 p2 mh m2 d1 mh m3 d1”, meaning, I hope it’s clear, “move to siding 1, pull 2 cars out, move home, move to siding 2, drop 1 car, move home, move to siding 3, drop 1 car”?

And instead of setting up sidings like this:

   siding.set_cars("2", "1", "3" "4"."5")

Why not like this:

   siding.set_cars("21345")

And when we ask for the cars currently on a siding or being pulled, a similar string would be returned so if we said siding.cars() we’d get "21345" back. We can debate whether to reverse the order of the pulled cars so that it is easier to see which way the ends are going. The point is, we can make the plan and the result easy to type and easy to check, and let the methods in the Siding and Locomotive help us out with a bit of formatting, while keeping their internal data in whatever form they need.

I think I’ll just log into aditi right now and try it. I rewrite my last test like this:

function Tests:test_pull_one_car()
   siding5 = Siding(5, "21345")
   siding31 = Siding(3)
   siding32 = Siding(3)
   loco = Locomotive(siding5, siding31, siding32)
   plan = loco:fetch(2, 1)
   assert_equals(plan, "m2 p1 mh", "check plan")

Now I just have to make it work. Note that I now define the Siding including its contents. I propose that that will be optional, for now, because it will keep other tests running. Also I write this new test:

function Tests:test_new_siding_init()
   siding = Siding(5, "54321")
   car1 = siding.cars[1]
   assert_equals(car1.id, "5", "check one car id")
   assert_equals(siding:car_string(), "54321", "check all cars 54321")
end

And based on that:

local Siding = class()
function Siding:init(length, cars)
   self.length = length
   self.cars = {}
   if cars then for i = 1, cars:len() do
      local c = cars:sub(i, i)
      table.insert(self.cars, Car(c))
   end end
end

function Siding:car_string()
   local result = ""
   for i, car in self.cars do
      result ..= car.id
   end
   return result
end

That test runs and then to make the first one run:

function Locomotive:fetch(siding, count)
   return `m{siding} p{count} mh`
end

That returns the correct result. Note that I am putting siding in as a number 1, 2, 3 now, not as a siding, as before. This seems simpler.

Summing Up

My tests work, and I have a more compact notation for setting up the situation, and for the “plan”. That should let me write tests in a more compact and easy form, which will encourage me to test, which will keep the code working better as I push forward.

I find that things often work out as they did today. I have a session where I kind of fumble around and try things, and then I think about it and maybe chat with friends, and then next time I’m able to clean things up and make some progress. That’s why I don’t bash myself when things don’t go well: I know that’s part of my learning process.

Next time … I don’t know what we’ll do. A bit more on plans, probably. I can’t wait to find out.

Safe paths!