In search of better metrics!
- cycles to first item
- cycles to 6 items
- long-term production schedule (average speed, batch size & pattern if applicable)
- default cost model
- default area model
- tech level (number of unique commands used)
- code volume (total number of bytecodes)
Hardware cost and Software tech level are related, because both penalize the introduction and use of the more sophisticated tools (pistons and then tracks). Hardware area and code volume and related, because both represent how "tightly wrapped" or self contained your project is.
Adding the software metrics generates interesting gameplay. Players are encouraged to create components with similar behavior, so that they can share code between components. Players are encourage to find patterns, to allow refactoring. There is a two-way feedback loop between tweaking the physical layout, and tweaking the software layout. Stuff shows up like "hey, if I made this area more symmetric I could reuse this piston code."
If the first bit is 0, the byte represents an object. If the first bit is 1, then the byte represents a function.
0 111-1111
int-!cmd
1 1-111111
?-fncode
All items have both an int and a command. The command is repeated int times. For example (item 6 +turn) will run 6 times.
The int is simply the first three bits as a binary number, between 0 and 5.
A value of 0 indicates that the command will be run 0 times, i.e. skipped entirely without wasting a cycle.
When adding and subtracting these ints, all values rollover at 6. This means that adding three twice wraps you around to your original starting value, as does adding two thrice. This should make it easier to work with spinner arms.
Commands are indicated by the last four bits. The fourth to last bit indicates the parity of the command; all commands have both negative and positive versions. The "tech level" metric measures how many unqiue commands your project uses. Parities (except on wait and null) count seperately, and so the maximum tech level is 14.
| last three bits | command | positive | negative |
|---|---|---|---|
001 |
twist | Q | E |
010 |
turn | A | D |
011 |
reach | W | S |
100 |
slide | G | T |
101 |
hold | F | R |
110 |
PARAM | regular | negated |
111 |
wait | forward | backward |
000 |
null | forward | backward |
can refer to commands as
+turnforA(left turn)-turnforD(right turn)+holdforF(fetch)-holdforR(release)
param is for use in functions
null is the standard blank tile, and does nothing. Nulls must be manually included, you can have offset buffering or even no buffering. Extra nulls at the beggining perform the same role as they currently do - "wait through this, then start your loop".
A negative null at the beggining pushes back all other programs. For all other purposes, the parity of null has no effect. As this is purely a conveniance feature, null parity has no effect on tech level.
Waits are similar to nulls, except they skip an entire round (e.g. wait for all machines to read through their buffers). This can help cordinate startup with spinny hexagons, and hopefully allow some new creative solutions. Negative waits push back all other threads, ie let the current thread get setup first.
The first bit decides whether ("call" or "define"), the remaining 6 bits are the identifier. This means you get 64 functions per project, though some pre-built functions are included.
Refering to (item _ param) in a function definition means that when called, that item will be replaced by the parameter. The number field is the number of times the param should be substitutued. The param is substituted with its int field intact.
Here is an example of a user defined macro for multiplication
(define repeat_five) (item 5 +param)
then
(call repeat_five) (item 5 +null)
expands inline to
(item 5 +null) (item 5 +null) (item 5 +null) (item 5 +null) (item 5 +null)
and stalls for 25 whole cycles.
So for example a setup with four simple transfer arms
BEFORE (18 code volume, tech level 5)
(item 1 +hold) (item 1 +turn) (item 1 -hold) (item 1 -turn)
(item 2 +null) (item 1 +hold) (item 1 -turn) (item 1 -hold) (item 1 +turn)
(item 1 +hold) (item 1 +turn) (item 1 -hold) (item 1 -turn)
(item 2 +null) (item 1 +hold) (item 1 -turn) (item 1 -hold) (item 1 +turn)
AFTER (15 code volume, tech level 7)
(define transfer) (item 1 +hold) (item 1 +param) (item 1 -hold) (item 1 -param)
(call transfer) (item 1 +turn)
(item 2 +null) (call transfer) (item 1 -turn)
(call transfer) (item 1 +turn)
(item 2 +null) (call transfer) (item 1 -turn)
There is functionality that cannot be implemented with the base system, such as int arithmetic and functions with multiple parameters. As I study different scenarios, I hope to identify clean implementations for necesarry building blocks.
These functions will be mapped on some subset of availible function codes. They will be called with (call fname) and can be ovewritten if a user specifies their binary address outside of the normal auto-increment order (define 000010:myFunc) ....
The number in the item code should indicate which param it is, not the number of repeats.