Sortron-driven automatic processing

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
Code:
1  CONSTANT paintWhite     
2  CONSTANT paintOrange    
3  CONSTANT paintMagenta   
4  CONSTANT paintLightBlue 
5  CONSTANT paintYellow    
6  CONSTANT paintLime      
7  CONSTANT paintPink      
8  CONSTANT paintGray      
9  CONSTANT paintLightGray 
10 CONSTANT paintCyan      
11 CONSTANT paintPurple    
12 CONSTANT paintBlue      
13 CONSTANT paintBrown     
14 CONSTANT paintGreen     
15 CONSTANT paintRed       
16 CONSTANT paintBlack     

1     CONSTANT wireWhite    
2     CONSTANT wireOrange   
4     CONSTANT wireMagenta  
8     CONSTANT wireLightBlue
16    CONSTANT wireYellow   
32    CONSTANT wireLime     
64    CONSTANT wirePink     
128   CONSTANT wireGray     
256   CONSTANT wireLightGray
512   CONSTANT wireCyan     
1024  CONSTANT wirePurple   
2048  CONSTANT wireBlue     
4096  CONSTANT wireBrown    
8192  CONSTANT wireGreen    
16384 CONSTANT wireRed      
32768 CONSTANT wireBlack    

wireRed    CONSTANT signalProcMacerate 
wireOrange CONSTANT signalProcFurnace  
wireYellow CONSTANT signalProcRecycle  
wirePink   CONSTANT signalProcSort     
wireBlack  CONSTANT signalProcStop     

wireRed    CONSTANT signalFlush1Over   
wireOrange CONSTANT signalFlushEndOver 
wireYellow CONSTANT signalFlushEndProc 
wireBlack  CONSTANT signalFlushStop    

wireBlack  CONSTANT signalBufferStop   

paintRed    CONSTANT tubeProcMacerate
paintOrange CONSTANT tubeProcFurnace 
paintYellow CONSTANT tubeProcRecycle 
paintPink   CONSTANT tubeProcSort    
paintRed    CONSTANT tubeFlushOver   
paintOrange CONSTANT tubeFlushProc   

\ DOUBLE WORD (32 BIT) EQUALITY - USEFUL FOR SORTRON ITEM IDENTIFIERS.
\ D D -- F
: M= ROT = -ROT = AND ;
 
\ DOUBLE WORD (32 BIT) NON-EQUALITY
\ D D -- F
: M<> M= 0= ;

: pullAll
SORTSLOTS 0 ?DO
I SORTSLOT@
DUP 0<> IF I SORTPULL THEN
DROP 2DROP
LOOP
;

VARIABLE item1
VARIABLE item2
: pullAllMatch
0 SORTSLOT@
0<> IF
 item2 ! item1 !
 SORTSLOTS 0 ?DO
  I SORTSLOT@
  0<> IF
   item1 @ item2 @ M= IF 255 I SORTPULL DROP THEN
  ELSE
   2DROP
  THEN
 LOOP
ELSE
 2DROP
THEN
;

: pull1stack
0 SORTSLOT@
DUP 0<> IF 0 SORTPULL THEN
DROP 2DROP
;

: pullEnd
0 SORTSLOTS 1 - ?DO
I SORTSLOT@
DUP
0= IF DROP 2DROP LEAVE THEN
I SORTPULL
DROP 2DROP
-1 +LOOP
;

: signalQuiesce
BEGIN
IOX@
0= UNTIL ;

: signalFlush
0
BEGIN
1
IOX@ signalFlush1Over   = IF tubeFlushOver    SORTCOLOR! pull1stack signalQuiesce THEN
IOX@ signalFlushEndOver = IF tubeFlushOver    SORTCOLOR! pullEnd    signalQuiesce THEN
IOX@ signalFlushEndProc = IF tubeFlushProc    SORTCOLOR! pullEnd    signalQuiesce THEN
IOX@ signalFlushStop    = IF 0 SORTCOLOR! DROP ." Stopping"  THEN
TICK
0= UNTIL ;

: signalProc
0
BEGIN
1
IOX@ signalProcMacerate = IF tubeProcMacerate SORTCOLOR! pullAllMatch signalQuiesce THEN
IOX@ signalProcFurnace  = IF tubeProcFurnace  SORTCOLOR! pullAllMatch signalQuiesce THEN
IOX@ signalProcRecycle  = IF tubeProcRecycle  SORTCOLOR! pullAllMatch signalQuiesce THEN
IOX@ signalProcSort     = IF tubeProcSort     SORTCOLOR! pullAllMatch signalQuiesce THEN
IOX@ signalProcStop     = IF 0 SORTCOLOR! DROP ." Stopping"  THEN
TICK
0= UNTIL ;

VARIABLE slots
VARIABLE slot
: signalBuffer
SORTSLOTS slots !
0 slot !
0
BEGIN
1
slot @ SORTSLOT@
DUP 0<> IF slot @ SORTPULL THEN
DROP 2DROP
IOX@ signalBufferStop     = IF 0 SORTCOLOR! DROP ." Stopping"  THEN
20 TICKS
slot @ 1 + slot !
slot @ slots @ = IF 0 slot ! THEN
0= UNTIL ;
This code defines two processes, both of which monitor incoming signals in bundled cables. signalFlush is for flushing items out of my main input Enderchest to one of two destinations - an overflow chest, and a processing Enderchest. signalProc sends all the items in my processing Enderchest into my processing machines. I have a signal for Macerate, one for Furnace, and one for Recycle. I haven't actually hooked up the outputs to the machines yet, but the programs work, they send all the items to the correct coloured tube. The new set of machines that I am about to hook up will return their processed outputs into the processing chest.

signalFlush has three operations: pull the first stack from the Enderchest into overflow; pull all the contiguous stacks at the end of the Enderchest into the overflow; and pull all the contiguous stacks at the and of the Enderchest into the processing Enderchest. You probably won't want this, it's a peculiarity of my sorting system that my input chest has no default route.

signalProc is the main event. It takes four signals, and sends the entire contents of my processing Enderchest to one of three destinations, the fourth signal terminates the program. After each signal is detected, it does what it needs to do and then waits for no signals to be detected on the input. That's what signalQuiesce is, it waits for all signals to stop. *Updated*: It now only sends items that match the item in the first slot. So if I've got a mixture of cobblestone and sand in the pouch, and sand is in the first slot, then only sand gets sent to be processed.

Here's my comms room:
2013-03-07_21.09.29.jpg
and here are the two Sortrons connected to the chests:
2013-03-07_21.10.03.jpg
This is my Wireless Remote interface:
2013-03-07_21.14.21.jpg

Update: I've hooked up a Macerator, Electric Furnace, and Recycler and it's working like a charm. I also added a new signal to flush the processing Enderchest into the sorting Enderchest, so if I'm building something and I run out of refined iron then I can dump some iron in, click "Proc Furnace", and then send the refined iron to be sorted into my metals chest, all without having to visit my machine room. I'm a little bit paranoid about accidentally clicking "Recycle" with a bunch of valuable things in the chest...
 
  • Like
Reactions: Guswut

Guswut

New Member
Jul 29, 2019
2,152
0
0
I'm a little bit paranoid about accidentally clicking "Recycle" with a bunch of valuable things in the chest...

As you should be. I'd suggest setting up the recycling subsystem to store things in a chest await recycling, which you then manually start, so you can confirm you didn't accidentally start recycling on something you don't want to recycle. Perhaps a bypass for automated recycling of things such as cobblestone/dirt/etc.
 

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
I might introduce a new signal "Remove Safeguard" that has to be sent after any Recycle signal, so that I can't accidentally leave the remote set to Recycle and activate it on some valuable loot.

Another feature that I'm thinking of adding is a series of chests that I can rotate the contents of, so I can have tools in one, building blocks in another, consumables, ingots & gems, machines, etc. and click a button to rotate the contents of all the chests by one step so I can access several additional inventories on the go. Alternatively I could just throw a bunch of canvas bags and enderpouches into an enderpouch, but where's the fun in that? I can't see myself using my remote processing system much either, but building it was fun, and it seems to be a "never been done before" build which is rare nowadays.
 

ratchet freak

Well-Known Member
Nov 11, 2012
1,198
243
79
you do know that

Code:
1 CONSTANT paintWhite

if equivalent to

Code:
: paintWhite 1 ;

and IMO more readable
 

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
Yes I've recently rewritten that section as constants, it's probably more efficient that way too, I'm not sure if calling a word has an overhead over a constant. I'm just starting to learn Forth really.
 

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
I'm trying to work out how arrays work, so I can store a list of item codes, stack sizes, and colours. e.g. "Cobblestone 16 Red", or literally, 10332 -9668 16 15. I have Aeronica's code to look at but it's a bit baffling as there's some syntax that I'm not familiar with. Hopefully you're reading this, Aero, and can help me out!

For example, the very first line:
Code:
: STRUCT 0 ;
That appears, to me, to define a word called STRUCT that just pushes 0 onto the stack!

I think I understand the STRUCT stuff later on, but the initial definition of the word is baffling me. In Forth Lesson 18 there is a "struct" word described, but I assume that's something different.
 

Aeronica

New Member
Jul 29, 2019
27
0
0
Hello Phil, The tutorial hides the definition of STRUCT in the text of the article. The author also uses lowercase so it was somewhat hard to find.

You are correct "STRUCT" pushes 0 on the stack and that becomes a counter used in the definition of a structure. "field" creates new words in the forth dictionary that essentially add the field size to the item on TOS. It is used as an index. The purpose is to create dictionary words that can be use to reference fields in a block of memory. It just a fancy way to create named indexes.

I tossed this to together pretty quickly but hopefully you get the idea. Type it in and play with it.

\ http://wiki.laptop.org/go/Forth_Lesson_18
: STRUCT 0 ;
: FIELD CREATE OVER , + DOES> @ + ;

STRUCT \ pushes 0 onto the stack as counter. Later stored in the constant /FOO which is the total size of the defined structure.


2 FIELD >W \ this defines a new dictionary word >W which simply adds 0 to the TOS (value at top of stack)
4 FIELD >L \ this defines another new word >L which adds 2 to the TOS
1 FIELD >B \ this defines the last new word >B which adds 6 to the TOS
CONSTANT /FOO \ at this point the constant /FOO will be created with the value of 7 which is the total size of this structure.

0 >W . 0
0 >L . 2
0 >bB . 6
/FOO . 7

\ Let's make an array to hold 5 of these structures. Each is /FOO or 7 memory locations in length.
5 CONSTANT MAXFOOS

CREATE FOOARRAY /FOO MAXFOOS * ALLOT

\ FOOARRAY now contains the base address of the array.

\ We can access the 0th FOO on this array quite simply using the base address itself.

1 FOOARRAY >W ! \ Initialize the 1st location in FOOARRAY >W to 1
2 FOOARRAY >L ! \ Initialize the 1st location in FOOARRAY >L to 2
3 FOOARRAY >B ! \ Initialize the 1st location in FOOARRAY >B to 3


\ But of course we allocated space for 5 of these FOOS.

\ Lets make a better way to deal with this structure.

: PFOO ( index -- addr )
0 MAX MAXFOOS MIN /FOO * ; \ Calculates the index into the FOOARRAY with bounds checking and leaves the address of next position on the stack


\ now let's try it out and read the values we stuck the 0th postion before

0 PFOO >W @ . 1 \ The value we set earlier
0 PFOO >L @ . 2
0 PFOO >B @ . 3

\ how about the next index into our array
10 1 PFOO >W ! \ FOOARRAY(1) = 10
1 PFOO >W @ . 10 \ Read the value we just set.
0 PFOO >W @ . 1 \ and we did not overwrite the 0th >W
 
  • Like
Reactions: PhilHibbs

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
Phew I'm not going mad! Big thanks, I have an Easter project now!

Click! I get it now! You're telling the compiler (or interpreter or whatnot) to tally up the cumulative offsets of the structure elements, and to dynamically create words for them! That's really cool. I love that "click" feeling. Suddenly I'm not as stupid as I thought.

*Edit* I updated my code, the only change is that I use constants instead of words for the cable and pipe definitions.
 

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
Hm. Not good. I posted a new version of the code without testing it and it doesn't work. The theory is, I define the wire and tube colours as CONSTANTs rather than defining them as words, but there's a problem that I don't understand. Here's the first part of the code:

Code:
: paints
1  CONSTANT paintWhite
2  CONSTANT paintOrange
3  CONSTANT paintMagenta
4  CONSTANT paintLightBlue
5  CONSTANT paintYellow
6  CONSTANT paintLime
7  CONSTANT paintPink
8  CONSTANT paintGray
9  CONSTANT paintLightGray
10 CONSTANT paintCyan
11 CONSTANT paintPurple
12 CONSTANT paintBlue
13 CONSTANT paintBrown
14 CONSTANT paintGreen
15 CONSTANT paintRed
16 CONSTANT paintBlack
;
 
: wires
1    CONSTANT wireWhite
2    CONSTANT wireOrange
4    CONSTANT wireMagenta
8    CONSTANT wireLightBlue
16    CONSTANT wireYellow
32    CONSTANT wireLime
64    CONSTANT wirePink
128  CONSTANT wireGray
256  CONSTANT wireLightGray
512  CONSTANT wireCyan
1024  CONSTANT wirePurple
2048  CONSTANT wireBlue
4096  CONSTANT wireBrown
8192  CONSTANT wireGreen
16384 CONSTANT wireRed
32768 CONSTANT wireBlack
;
 
: signals
wires
wireRed    CONSTANT signalProcMacerate
wireOrange CONSTANT signalProcFurnace
wireYellow CONSTANT signalProcRecycle
wirePink  CONSTANT signalProcSort
wireBlack  CONSTANT signalProcStop
wireRed    CONSTANT signalFlush1Over
wireOrange CONSTANT signalFlushEndOver
wireYellow CONSTANT signalFlushEndProc
wireBlack  CONSTANT signalFlushStop
;
When it gets to "wirePink CONSTANT signalProcSort" it fails with "Unknown Token: signalProcSort", which makes no sense since that's the name of the constant that I'm trying to define! Any ideas? For now I am reverting the code back to how it was with words instead of constants. Maybe it just doesn't like defining a constant in terms of another constant, but I'm baffled why the first three signals seem ok.

Also I've appended a new program, procBuffer, which empties a buffer chest into my sorting chest one slot per second. But it also doesn't work. The initial VARIABLE definition fails, "Unknown Token: slots". Is it that you can't define a variable within a word? That's... ok, maybe that makes sense... kind of.
 

Aeronica

New Member
Jul 29, 2019
27
0
0
I'm no expert on Forth, but I'm not sure it's a good idea to define constants inside a word definition in that manner. It's as though you are attempting to define local constants. When I try I get the same error on the first constant I attempt to define. What may be happening for you is that your paints and wire may be referencing constants that were previously defined and you are simply re-defining them and thus get no error. Type WORDS to see all the define words constants and variables. I suspect the wirePink is either not defined or is mis-spelled or a letter or two are the wrong case: upper vs lower. But I would take all those constant definitions out of the : ; word definitions. Use a comment instead

Code:
\ Paints
1 CONSTANT paintWhite
2 CONSTANT paintOrange
3 CONSTANT paintMagenta
4 CONSTANT paintLightBlue
5 CONSTANT paintYellow
6 CONSTANT paintLime
7 CONSTANT paintPink
8 CONSTANT paintGray
9 CONSTANT paintLightGray
10 CONSTANT paintCyan
11 CONSTANT paintPurple
12 CONSTANT paintBlue
13 CONSTANT paintBrown
14 CONSTANT paintGreen
15 CONSTANT paintRed
16 CONSTANT paintBlack
 
\ Wires
1 CONSTANT wireWhite
2 CONSTANT wireOrange
4 CONSTANT wireMagenta
8 CONSTANT wireLightBlue
16 CONSTANT wireYellow
32 CONSTANT wireLime
64 CONSTANT wirePink
128 CONSTANT wireGray
256 CONSTANT wireLightGray
512 CONSTANT wireCyan
1024 CONSTANT wirePurple
2048 CONSTANT wireBlue
4096 CONSTANT wireBrown
8192 CONSTANT wireGreen
16384 CONSTANT wireRed
32768 CONSTANT wireBlack
 
\ Signals
wireRed CONSTANT signalProcMacerate
wireOrange CONSTANT signalProcFurnace
wireYellow CONSTANT signalProcRecycle
wirePink CONSTANT signalProcSort
wireBlack CONSTANT signalProcStop
wireRed CONSTANT signalFlush1Over
wireOrange CONSTANT signalFlushEndOver
wireYellow CONSTANT signalFlushEndProc
wireBlack CONSTANT signalFlushStop

Constants and variable in this version of Forth are all global as far as I know. There are versions of Forth that allow local variables. Perhaps someone with more experience can elaborate.
 

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
Ah I think I get it. It's not that they are all global that was confusing me, I knew they were global, its the persistence that was confusing me. I kind of assumed that they would cease to exist when there was no Forth program running, and therefore should be defined at the start of a program. Thanks again both!

I got my signal program to run but it just sits there and does nothing. The code above is missing a couple of lines to increment slot and loop around to zero. I'll debug it tonight.
 

Aeronica

New Member
Jul 29, 2019
27
0
0
Forth is an interactive environment. Every constant, variable and word you define becomes part of the system. Allocated and stored the moment it's compiled at the command prompt. When you SAVE" filename", your Forth system is written to disk and the ENTIRE memory image is saved. That means all the constants, variables and words you defined are saved too. So when you boot off that disk it all gets reloaded.
 

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
OK I've fixed and updated my signalBuffer prorgam. The two mistakes I made were: my variable retrieval references had to have @ after them, and... I forgot to power my Sortron with some blutricity.

The signalBuffer just sits between my quarry output enderchest and my sorting input enderchest, and every second it pulls a slot from one into the other and moves on to the next slot. So it gets 27 seconds worth of buffering. Usually this will pull a stack of cobble, then half a stack, then a couple of pieces of gravel or dirt, and then nothing for 24 seconds. Works for me.
 

PhilHibbs

Forum Addict
Trusted User
Jan 15, 2013
3,174
1,128
183
Birmingham, United Kingdom
Updated code: the automatic processing now uses a word called pullAllMatch instead of pullAll, which pulls all the items that match the item in the first slot. pullAll is no longer used but I haven't removed it. Maybe the "procSort" command should pull everything into the sorting system, I'm not sure.