Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Toupie

Pages: 1 [2] 3 4 5
16
Troubleshooting & Bug Reports / Re: The v1.22 beta bug report thread!
« on: October 25, 2013, 07:59:40 pm »
User Texture Engine (voxelinfo_75.txt) does not have a MiningType.
This makes it so you can't pick up the User Texture Engine that you get when you start with the constructor/destructor tool you have when you start.

17
Suggestions / Windows 64 bit or Large Address Aware
« on: October 25, 2013, 07:01:15 pm »
Could we please have a 64 bit windows exe, or at least a Large Address Aware Windows 32 bit exe. I would like to experiment with larger loaded world size.

That there is a 64 bit Ubuntu version doesn't help me since my machine running Ubuntu only has 2G of memory :(

18
General Discussion / Re: Saving variables
« on: October 25, 2013, 06:57:01 pm »
Answer: You simply use GetQuantity(32768) to get the name of the save file before each save/load. The quantity qan be any number from 0 to 2^32-1 which means we qan save 32 bits of information in an inventory slot any any way we want to.

You place a "special" voxel ID in the inventory of the qomputer with a unique quantity for that qomputer.
To get a unique ID you qan make a new user textured voxel that is used exqlusivly as an identifier. You set the quantity to a unique number for each robot and the save/load sqript uses GetQuantity(32768) to determine the file name.

32768 is the id of user textured voxel 1.
Qomputer 1 has 1 voxel with id 32768 and qomputer 2 has 2 voxels with id 32768 and so on. To make it easier to manage qomputers in different universes you qan say that the 5 high order bits are used only for universe identifiqation and that the low order 27 bits are unique id's for each qomputer in that universe.
So the number of voxels stored in a qomputer should be
Code: [Select]
ID = (U << 27) | N //ID = U*pow(2,27) + Nwhere U is the universe number-1 you are in and N is a unique (in that world) identifying number that is at most 2^27-1 (more than you need, you qan have a qube of size 512x512x512 of just qomputers in each universe).
and you name each file ID.save or something.

But doesn't that mean the user will have to manually add those blocks to the robot every time it is placed in the world? So it's up to the user to make sure the id is unique? Does not sound very appealing to me.

If I just get access to the universe number I can save it as Universe_PosX_PosY_PosZ, that will make it unique since there can only be one robot at one place in the same universe. Or alternatively, get the path to the current universe save directory, the PosX_PosY_PosZ will be unique in that path.

19
General Discussion / Re: Saving variables
« on: October 25, 2013, 12:15:00 am »
If you qan live with 1 less storage space then you have 32 bits to identify your qomputers with.
Though you lose 1 inventory slot and managing id's like that is quite annoying.


Would you care to elaborate on this? How would I be able to use an inventory slot to store an id for the robot?

20
General Discussion / Re: Saving variables
« on: October 25, 2013, 12:13:21 am »
This is an expanded save/load routine I have come up with. It will save and load an global table. So all variables you want to have saved needs to be in that table. In my example it's called Setting, but you can name it what you want. Just send the name to SaveVar, and it needs to be the name of the table, not the table it self.

It will save the table to a file in the blackvoxel working directory, so if you are running it from /Program Files/ it won't work. And it does not distinguish between different universes.

Main program.
Code: [Select]
// Test of Loading and Saving variables

NeedLoad <- 0;
Pos <- [0,0,0];

// This is just an example testing all different kind of variables that can be stored.
Setting <- {
  Len = 1,
  Dir = 0,
  Moves = 0
  List = [1,2,3,4,"Hello World!"],
  Ind = { A=[0,1,2], B={A=1,b=2}, [0]="Anka"},
  Hello = "World!",
};

function Dump(var)
{
    local i,v;
    local s="";
    if (typeof var=="integer") {
      s = var+"";
    } else if (typeof var=="string") {
      s = "\""+var+"\"";
    } else if (typeof var=="array") {
      s = "[";
      foreach (v in var) {
        s += Dump(v)+",";
      }
      s += "]";
    } else if (typeof var=="table") {
      s = "{";
      foreach (i,v in var) {
        if (typeof i=="integer") {
          s += "["+i+"]="+Dump(v)+",";
        } else {
          s += i+"="+Dump(v)+",";
        }
      }
      s += "}";
    }
    return s;
}

function SaveVar(varname)
{
  local c,s,filename;
  s="";
  filename  = format("%d_%d_%d.save",Pos[0],Pos[1],Pos[2]);
  if (varname in getroottable() && typeof varname="string") {
    if (typeof (getroottable()[varname])=="table") {
      foreach (i,v in getroottable()[varname]) {
        if (typeof i=="integer") {
          s += "::"+varname+"["+i+"]<-"+Dump(v)+";\n";
        } else {
          s += "::"+varname+"."+i+"<-"+Dump(v)+";\n";
        }
      }
    } else {
      s = "::"+varname+"<-"+Dump(getroottable()[varname])+";\n";
    }

    c = compilestring(s);
    writeclosuretofile(filename,c);
  }
}

function LoadVar()
{
  local s;
  s = format("%d_%d_%d.save",GetX(),GetY(),GetZ());
  try {
    dofile(s);
    remove(s);
  } catch(e) {}
  NeedLoad = 0;
}

function SavePos()
{
  Pos[0]=GetX();
  Pos[1]=GetY();
  Pos[2]=GetZ();
}

function Voxel_Load()
{
  NeedLoad = 1;
}

function Voxel_Unload()
{
  SaveVar("Setting");
}

function Voxel_Step()
{
  local i,j,v,done;

  if (NeedLoad)
    LoadVar();

  // Do stuff

  SavePos();
}

If you place a programmable robot in the same spot that one was Unloaded before it would load it's variables. So to prevent that you need to have a script named 0.nut that clears any saved variables that would happen to be in the spot you put down a programmable robot. (It's not a good idea to have 0.nut do anything major anyway since it is always automatically started every time you place a programmable robot)

0.nut
Code: [Select]
NeedLoad <- 1;

function Voxel_Step()
{
  local s;
  if (NeedLoad) {
    s = format("%d_%d_%d.save",GetX(),GetY(),GetZ());
    try {
      remove(s);
    } catch(e) {}
    NeedLoad = 0;
  }
}

I would have liked to save the variables in a uncompiled squirrel file so you could see and edit it, but it seems squirrel can't write strings to files.
I'm still at a loss to why squirrel is used instead of lua. The trouble the author of squirrel had with lua garbage collection is long since fixed in lua.

21
General Discussion / Saving variables
« on: October 24, 2013, 01:46:09 pm »
Now it's possible to save variables between game save/load with the following code.

Code: [Select]
Len <- 1;
Dir <- 0;
Moves <- 0;

function Voxel_Load()
{
try {
dofile("save.nut");
remove("save.nut");
} catch(e) {}
}

function Voxel_Unload()
{
local s;
s = compilestring(format("::Moves<-%d;\n::Dir<-%d;\n::Len<-%d;\n",Moves,Dir,Len));
writeclosuretofile("save.nut",s);
}

But there is not enough information available to the script to distinguish different robots apart or different universes.

I was thinking I could save the variables for a script in it's Voxel_Unload function. I need to have a way to separated several programmable robots that all run the same script apart. So I thought their x,y,z position should do. But those are not available in the Voxel_Load and Voxel_Unload.
I also need to separate the saved variables from different universes, but there is no way of knowing what universe we are in.
There should probably also be a way for a script to read it's program number. (In case you have copied or renamed it)

I also have trouble identifying if Voxel_Load was called because the robot was placed in the world, loaded, or had it's program changed. I really only want to load stored variables when the robot is loaded into the world, not when it is first placed, or had it's program changed.

All in all, it would probably be better if there was a specific blackvoxel function that handled the saving and loading of variables that a script could use.

22
General Discussion / Re: The tips & tricks thread.
« on: October 24, 2013, 01:30:21 pm »
  • F1  Show Mouse Cursor
  • F2  Hide Mouse Cursor
  • F5  Save (but don't exit)
  • F6  Toggle Crosshair
  • F12 Show FPS

23
Gallery / Re: Qons gallery
« on: October 23, 2013, 09:09:18 pm »
Very nice !!!

For the player coordinates and view direction, you'll be happy... that's in the package  :)

You can get these infos with the var GetInfo(int InfoNum) function.

Depending on the InfoNum parameter, you'll get :

0: (int) Max for InfoNum parameter.
1: (float) Player Location (x)
2: (float) Player Location (y)
3: (float) Player Location (z)
4: (int) Player Location (x) in Voxel Units
5: (int) Player Location (y) in Voxel Units
6: (int) Player Location (z) in Voxel Units
7: (float) Player Viewing direction (yaw)
8: (float) Player Viewing direction (pitch)
9: (float) Player Viewing direction (roll)
11: (float) Player Head Location (x)
12: (float) Player Head Location (y)
13: (float) Player Head Location (z)
14: (int) Player Head Location (x) in Voxel Units
15: (int) Player Head Location (y) in Voxel Units
16: (int) Player Head Location (z) in Voxel Units

The Blackvoxel Team

Thank you.
I was just wondering what that function did.

24
Troubleshooting & Bug Reports / Re: The v1.22 beta bug report thread!
« on: October 23, 2013, 09:06:24 pm »
PushVoxelTo() still don't remove the the voxel type when quantity reaches zero. (PlaceVoxel works.)

If you pick up a single voxel from the inventory with the mouse, it is possible to place it with a right click but still having it on the mouse.  So when you let go off the left mouse button it will place the voxel as zero quantity. It is also possible to pick up this zero quantity voxel and move it somewhere. There is no visual differance between a single voxel and a zero quantity voxel in the inventory since neither of them show a quantity number.


25
Troubleshooting & Bug Reports / Re: The v1.21 bug report thread
« on: October 21, 2013, 03:46:43 pm »
Infinite death loop.

If you dig a deep hole at location x:0 z:0 you will end up in an infinite death loop if you die since you always respawn at x:0 y:0 z:0.

Either put a voxel below the player spawn point on respawn or scan for a safe place to respawn the player. (The later is probably prefered, or you could be stranded on a single voxel without anything in your inventory to build your way out.)

26
Suggestions / Extended voxel interface
« on: October 21, 2013, 03:41:58 pm »
How about an extended voxel interface between the programmable robot and the atomic compressor that lets the programmable robot query the compressors storage to see how many and what voxel types it has. And also the ability to get a specific voxel type.

This could be limited to higher tier robots and compressors.

27
Troubleshooting & Bug Reports / Re: The v1.21 bug report thread
« on: October 21, 2013, 03:38:10 pm »

PullVoxelFrom() will fail if the programmable robot does not have any internal storage slots without an voxel type, even if some of the slots have zero quantity. This combined with the bug that leaves the voxel type in the slots when you empty them makes for a game breaking bug. Once the programmable robot has filled all it's slots it can't ever pick up anything more until you manually fix those left over zero quantity voxels.

A workaround is to make sure you always have at least one slot that is completely empty, no quantity and no voxel type. But that reduces the programmable robots internal storage to 19 instead of 20.

28
Gallery / Re: Pictures of my work area
« on: October 17, 2013, 07:19:09 pm »
Made an semi automatic "Atomic Materializer" factory. I used as much "cheating" as I could. There is no supply chain, but instead the materials needed are stored in the Sequencers.

The Atmoic Materializer is just one one the components to the essential Voxel Materializer. And the Voxelduct is just as complex to build. So now I need to build two a more almost identical factories. One for the Voxelduct and one for the Disintegrator for the "Voxel Dematerializer" and the XR-2 robots.

I can't even imagine building a complete factory the those XR-2 Robots. It would be HUGE.
I'm starting to think that using a Programmable Robot to automate production is an easier way.

I have one picture of the factory without any material in to so it's visible how its built, and another with in work. I just put one X-Material on the "In" voxel and in a couple of seconds out comes an "Atomic Materializer".

29
Programming with Blackvoxel / Re: Complex Mining Robot Restarter
« on: October 17, 2013, 01:45:52 pm »
Oops!

It was walking the wrong way when searching for the master compressor. Was supposed to walk up, but went down.

Since you had loaded the game when the computer was waiting on the first compressor it didn't know where the nearest master is located, so it has to search for it. No way of telling where you started mining. I was first assuming that it started at the surface, but figured that was a bad assumption. So implemented this "search" instead, but somehow it never gotten tested.

To fix it change line 492 to
Code: [Select]
                        MasterLevel = GetY()+1;and line 495 to
Code: [Select]
                        destY = GetY()+1;
Or download this updated script.
Code: [Select]
// Complex Mining Robot Restarter
//
// Define the size of how many compressor/robots for it to manage.
// Place the Computer where you want it to start placing the first compressor/robots.
// Load it with the exact amount of Robots it needs (SizeX *  SizeZ * 4)
// Load it with at least the number of Atomic Compressors it need. If you are using "Master" compressors
//   you need to give it at least one more then the number compressor/robots to manage, and more if you want
//   it to place new "master" compressors along the way to speed things up and make it able to go deeper then -192 from the start.
// Start the script. (I recommend that you leave script 0.nut empty and give this script a higher number so you can load it with
//   with compressors and robots before starting it.)
// Stand somewhere inside the area being mined to follow it down to prevent the robots to move outside of the loaded area.
//
// Set BuildStarts <- 1 to have it automaticaly build a staircase right next to the "Master" compressors for easy access
//  to the "master" compressors and going up and down.
//
// For now the only time it can handle a load is when it is standing on top of the first compressor waiting for the robots to finish.
// This will be fixed when I will be able to save and restore variables.

Debug <- 2;           // Output debug info. 0=Only errors to stderr.txt 1=Errors to Display and to stderr.txt 2=Info and error to display and stderr.txt
SizeX <- 1;           // Number of compressor/robot sets to manage in X axis (8 is max practical value)
SizeZ <- 2;           // Number of compressor/robot sets to manage in Z axis (8 is max practical value)
UseMasterCompressor <- 1;  // Use one "master" Atomic Compressor to empty the computer to after every iteration. (Strongly recomended)
NewMasterAfter <- 192;// How often to place a new "Master" Atomic Compressor (Need to be <= 192. Make it an even 16 please, and anything less the 64 is a waste.)
BuildStairs <- 0;     // 0=Do not build stair, 1=Build Stair outside mining area, 2=Build stair inside mining area. (Only works if UseMasterCompressor is on)
MaxLevel <- -575;     // Don't place robots deeper then this. (Going below -1340 is dangerous)
Robot <- 153;         // The VoxelType of our robots. 153=XR-1(8*16*8) 154=XR-2(8*32*8) 155=XR-3(8*32*8) 156=XR-4(8*64*8) 157=XR-5(16*64*16) 158=XR-Z(16*64*16)
Compressor <- 49;     // The VoxelType of the Atomic Compressor (Should be 49 unless the game is changed)

// ============= DON'T CHANGE ANYTHING BELOW THIS (unless you know what you are doing) ===========

Path <- {
  // Stair 2 Wide 4 High 16 Down. Size 7x7. Builds floor and railings if in empty space
  [0] = [ 9, 12, 12, 8, 13, 13, 13, 21, 16, 10, 21, 18,
          9, 12, 12, 8, 13, 13, 13, 21, 16, 10, 21, 18,
          9, 12, 12, 8, 13, 13, 13, 21, 16, 10, 21, 18,
          9, 12, 12, 8, 13, 13, 13, 21, 16, 10, 21,
          9, 12, 12, 12, 8, 13, 13, 13, 21, 16, 17, 10, 21, 17, 18,
          11 ],
  // Doorway 2 Wide 3 High. Ends in the same location it started
  [1] = [ 9, 9, 12, 12, 8, 13, 5, 10, 13, 11, 11 ],

  // Stair 2 Wide 4 High 16 Down. Size 7x7. Builds floor and railings if in empty space
  [2] = [ 21, 8, 21, 11, 21, 10, 21,
          11, 13, 21, 18, 8, 21, 16,
          11, 13, 21, 16, 10, 21, 18,
          11, 13, 21, 18, 8, 21, 16,
          11, 13, 21, 10, 21, 18,
          11, 21, 18, 19, 8, 21, 19,
          10 ]
};
PathNo <- 0;

// StartX             // The X pos we started at
// StartZ             // The Z pos we started at
// CurrentC           // What compressor are we working with
// State              // What are we currently doing
// MiningSize         // How wide the Robot mines.
// MiningLevel        // The level where the latest compressors where placed from
// MasterLevel        // The Y pos of the latest master
// StairsLevel        // Stairs are built to this level
// Step <- 0;         // Current step in the path
// Rotation <- 0;     // Current rotation adjustment

Time <- 0;
LastState <- 0;
UnknownReturn <- 256000;
NextC <- 0;
NumC <- 0;
PullC <- 0;

/*
Logic:
Place all compressor/robots
Place Master Compressor if not already placed.
Empty Computer into Master Compressor
Empty all compressors
Dig staircase down to mining level.
Go to the compressors and wait for there robots to finish.
Pick up all the mined material, robots and the compressors.
Go down to the bottom of the mine shaft.
Restart
*/

function Voxel_Load()
{
  Time = GetGameTime() - 2000;
  if ("State" in getroottable()) {
    log_file("Starting at State "+State);
  } else {
    ::State <- 0;
  }
  if ("CurrentC" in getroottable()) {
    log_file("Working on Compressor "+CurrentC);
  } else {
    ::CurrentC <- 0;
  }
  if ("MasterLevel" in getroottable()) {
    log_file("Using old MasterLevel of "+MasterLevel);
  } else {
    ::MasterLevel <- 1;
  }
  if ("StartX" in getroottable()) {
    log_file("Using old StartX of "+StartX);
  } else {
    ::StartX <- GetX();
  }
  if ("StartZ" in getroottable()) {
    log_file("Using old StartZ of "+StartZ);
  } else {
    ::StartZ <- GetZ();
  }
  if ("MiningLevel" in getroottable()) {
    log_file("Using old MiningLevel of "+MiningLevel);
  } else {
    ::MiningLevel <- 1;
  }
  if ("Step" in getroottable()) {
    log_file("Using old Step of "+Step);
  } else {
    ::Step <- 0;
  }
  if ("Rotation" in getroottable()) {
    log_file("Using old Rotation of "+Rotation);
  } else {
    ::Rotation <- 0;
  }
  if ("StairsLevel" in getroottable()) {
    log_file("Using old StairsLevel of "+StairsLevel);
  } else {
    ::StairsLevel <- 0;
  }
  if (Robot<153)
    Robot = 153;
  else if (Robot>158)
    Robot = 158;
  if (Robot>=157) {
    ::MiningSize <- 16;
  } else {
    ::MiningSize <- 8;
  }

  if ("NumR" in getroottable()) {
    log_file("Using old NumR of "+NumR);
  } else {
    ::NumR <- GetQuantity(Robot);
  }

  if (NewMasterAfter > 192)
    NewMasterAfter = 192;
  if (NewMasterAfter < 16)
    NewMasterAfter = 16;
  NewMasterAfter = (NewMasterAfter / 16) * 16
  if (BuildStairs == 2)
    PathNo = 2;
}

function Voxel_Unload()
{
}

function Voxel_Step()
{
    local i,j,v,q,b;

    if ( (GetGameTime() - Time) > 1 )  // To run the script in slow-motion set time to wait to 1000 or higher
    {
       Time = GetGameTime();
    } else {
       return;
    }

    if (LastState != State) { // Only log on State change
        log_file("State="+State+" CurrentC="+CurrentC);
        LastState = State;
    }

    switch (State)
    {
        case 0: // Start up State. Try to figure out what to do
            if (Look(5) == Compressor) {
                // If we start ontop of a Compressor we just assume this is compressor set 0. (Since this is where we spend most of our time.)
                // This is the best we can do until there is a way to save variables
                StartX = GetX();
                StartZ = GetZ();
                MasterLevel = UnknownReturn;
                MiningLevel = GetY();
                StairsLevel = GetY() -1;
                CurrentC = 0;
                State = 5;
                log_info("Starting at compressor 0 X:"+StartX+" Y:"+MasterLevel+" Z:"+StartZ+" CurrentC:"+CurrentC);
                break;
            }
            if (GetQuantity(Robot)>=(SizeX*SizeZ*4)) { // We have all our robots.
                if (GetQuantity(Compressor)>=(SizeX*SizeZ+UseMasterCompressor)) { // and our compressor.
                  // Start from scratch.
                  StartX = GetX();
                  StartZ = GetZ();
                  MiningLevel = GetY() + 1;
                  MasterLevel = GetY() + 1;
                  StairsLevel = GetY();
                  CurrentC = 0;
                  log_info("Starting from scratch X:"+StartX+" Y:"+MasterLevel+" Z:"+StartZ+" CurrentC:"+CurrentC);
                  State = 40;
                  break;
                } else {
                  log_err("Wrong amount of Atomic Compressors. Have "+GetQuantity(Compressor)+" but need "+(SizeX*SizeZ+UseMasterCompressor) );
                }
            } else {
              log_err("Wrong amount of Robots. Have "+GetQuantity(Robot)+" but need "+(SizeX*SizeZ*4) );
            }
            Time = Time + 5000;
            break;

        case 5: // Move down until we find a Compressor
          v = Look(5);
          if (v!=Compressor) {
              if (!Move(5)) {
                  log_err("Could not move down to my compressor "+CurrentC);
              }
          } else {
              log_info("Waiting for Robots for set "+CurrentC);
              NumR = GetQuantity(Robot);
              PullC = 0;
              State = 10;
          }
          break;

        case 10:  // Waiting on top of a compressor for all the robots to finish there work.
            if (Look(5)==Compressor) {
                j = 5000; // Limit the amount of voxels to pull every step (It will still only take us 4 seconds to empty the compressor)
                while(PullVoxelFrom(5) && j>0) { // Pull voxels from the atomic compressor
                    j--;
                }
                if (j>0) { // We didn't reach our pull limit so check if the robots done
                    if (GetQuantity(Robot)>=(NumR+4)) { // If all mining robots are picked up then we can move on as soon as the compressor is empty
                        State = 11;
                    } else {
                        // Check for storage full
                        if (UseMasterCompressor && IsStorageFull()) {
                            State = 15; // Handle storage full
                        } else {
                            // Robots not yet ready, so we can take a rest (This is to prevent the script from using unnessesary cpu time while just waiting)
                            Time = Time + 1000;
                        }
                    }
                }
            } else {
                // Something is wrong.
                log_err( "No Atomic compressor found a set "+CurrentC+". Moving on!" );
                CurrentC++;
                State = 20;
            }
            break;
        case 11: // Just because we have our robots doesn't mean the compressor is empty. But one last pull should be enough
            if (Look(5) == Compressor) {
                if(!PullVoxelFrom(5) && PullC>0) {
                    // Check that we didn't fail to Pull voxels because our storage is full.
                    if (IsStorageFull()) {
                      State = 15;
                    } else {
                      NumC = GetQuantity(Compressor);
                      State = 12;
                    }
                } else {
                    PullC++;
                    State = 10;
                }
            } else {
                State = 10;
            }
            break;
        case 12: // Pick up Atomic Compressor
            if (Look(5) == Compressor) {
                log_info("Picking up Compressor for set "+CurrentC);
                PickVoxel(5);
                if (GetQuantity(Compressor)>NumC) { // Make sure the atomic compressor is on board
                    State = 20;
                    CurrentC++;
                } else {
                    // Computer storage is probably full.
                    log_err("Can't pick up the Atomic Compressor for set "+CurrentC+". Is my storage full?");
                    if (IsStorageFull())
                        State == 15;
                }
            } else {
                State = 10;
            }
            break;

        case 15: // My storage is full
            if (UseMasterCompressor) {
                log_info("My storage is full. Moving to master to empty my self.");
                NextC = CurrentC; // Save this compressor to process it next
                CurrentC = SizeX * SizeZ;
                State = 50; // Go empty me
            } else {
                State = 16;
            }
            break;
        case 16: // Signal that I need to be manually emptied
            if (IsStorageFull()) {
                log_err("My storage is full! PLEASE EMPTY ME!");
                Time = Time + 15000;
            } else {
                State = 10;
            }
            break;

        case 20: // Move to the next Compressor to pick up
            if (MoveToNextCompressor(0)) {
                if (CurrentC==0) { // Are we back to the first Compressor?
                  State = 30;
                } else {
                  State = 5;
                }
            }
            break;

        case 30: // The compressors and all mining bots are in storage so its safe to dig down.
            if (GetY() < MaxLevel) {
              log_info("Hit max level. Just going to empty my storage then I stop my work.");
              State = 100;
              break;
            }
            // Check if we have hit bottom
            i = 0;
            for (j=0; j<4; j++) { // Count the number of solid voxels on our sides
                v = Look(j);
                b = GetVoxelProp(v,0)
                if (!b) {
                    i++;
                }
            }
            if (i>2) { // We have hit bottom
                State = 35;
            } else {
              SafeMove(5);
            }
            break;
        case 35: // Move up one so we are above the bottom
            if (SafeMove(4)) {
                State = 40;
            }
            break;

        case 40: // We are now in position to place the mining robots
            log_info("Placing Robots for set "+CurrentC);
            for (i=0; i<4; i++) {
                if (SafePickVoxel(i))
                    PlaceVoxel(i, Robot);
            }
            State = 41;
            break;
       case 41:
            if (SafeMove(4))
                State = 42;
            break;
        case 42: // Place the atomic compressor between the mining bots
            log_info("Placing Compressor for set "+CurrentC);
            PlaceVoxel(5, Compressor);
            if (CurrentC==0)
                MiningLevel = GetY();
            CurrentC++;
            State = 43;
            break;
        case 43: // Make sure the compressor is in place. Do we need to do this?
            if (Look(5)==Compressor) {
                State = 50;
            }
            break;

        case 50: // Move to place the next Compressor/Robot Set
            if (MoveToNextCompressor(UseMasterCompressor)) {
                State = 51;
            }
            break;
        case 51: // We are at the location of our next Compressor.
            if (CurrentC == 0) {
                State = 5;
            } else {
                if (CurrentC < SizeX*SizeZ) {
                    if (SafeMove(5))
                        State = 40; // Place next robot/compressor set
                } else {
                    log_info("Pushing Voxels to Master Compressor");
                    State = 60; // Place Master or Empty into Master
                }
            }
            break;

       case 60: // Empty my self into the master
            if (PushMaster()) {
                if (BuildStairs && NextC==0)
                    State = 70;
                else
                    State = 80;
            }
            break;

        case 70: // Make stairs down next to the Master Compressor
            if (MiningLevel < StairsLevel) { // Only build stairs if we are mining below the already built stairs level
                log_info("Building Stair");
                if (SafeMove(0)) // Move away from the Master Compressor
                    State = 71;
            } else {
                State = 80;
            }
            break;
        case 71: // Move to the start of the stair
            if (MoveToStair())
                State = 72;
            break;
        case 72: // Build stair down to MiningLevel
            if (BuildStair()) {
                State = 80;
            }
            break;

        case 80: // Move to the first compressor
            CurrentC = NextC;
            NextC = 0;
            if (MoveToNextCompressor(0)) {
                State = 5;
            }
            break;

        case 100: // Done mining. Just some stuff to finish up.
            CurrentC = SizeX * SizeZ;
            MiningLevel = GetY();
            if (UseMasterCompressor)
                State = 101;
            else
                State = 105;
            break;
        case 101: // Return to the nearest "master"
            if (MoveToNextCompressor(1)) {
                log_info("Pushing Voxels to Master Compressor");
                State = 102;
                break;
            }
            break;
        case 102: // Empty me
            if (PushMaster()) {
                if (BuildStairs) {
                    log_info("Building Stair");
                    if (SafeMove(0)) // Move away from the Master Compressor
                        State = 103;
                } else {
                    State = 105;
                }
            }
            break;
        case 103: // Move to the start of the stair
            if (MoveToStair())
                State = 104;
            break;
        case 104: // Build at least one full rotation of the stair
            if (BuildStair()) {
                State = 105;
            }
            break;
        case 105: // Inform that we are done
            log_info("ALL WORK DONE!");
            State = 999;
            break;
        case 999: // Do nothing
            Time = Time + 60000;
            break;
    }
}

function MoveToNextCompressor(includeMaster)
{
    local x,y,z,v,d,destX,destY,destZ;
    if (CurrentC >= (SizeX * SizeZ + includeMaster))
        CurrentC = 0;
    if (CurrentC < SizeX*SizeZ) {
        x = CurrentC%SizeX;
        z = CurrentC/SizeX;
        if (z%2 > 0)
            x = (SizeX-1)-x;
        destZ = StartZ + z * MiningSize * 2 + x; // Offset every row of compressors by one for efficency
        destX = StartX + x * MiningSize * 2 - z;
        destY = MiningLevel;
    } else {
        if (UseMasterCompressor == 1) {
            destZ = StartZ - MiningSize;
            if (MasterLevel == UnknownReturn) {  // Search for nearest Master
                destX = StartX;
                if (destX == GetX() && destZ == GetZ()) {
                    if (Look(1) == Compressor) {
                        MasterLevel = GetY()+1;
                        destY = MasterLevel;
                        log_info("Master found at level "+MasterLevel);
                    } else {
                        destY = GetY()+1;
                        if (destY > 4) {
                            log_err("Failed to find any master!");
                            return 1;  // Failed to find a master compressor
                        } else {
                            log_file("Searching for Master");
                        }
                    }
                } else
                    destY = GetY();
            } else {
                if (((MasterLevel-NewMasterAfter) >= MiningLevel) && GetQuantity(Compressor) > 0) {
                    // If it is more then the set number of blocks up to the master and we still have Compressors in inventory place a new master.
                    MasterLevel = MiningLevel;
                    log_info("Setting new MasterLevel to "+MasterLevel);
                }
                destX = StartX + 1;
                destY = MasterLevel;
            }
        } else {
            log_err("Unexpected CurrentC "+CurrentC);
            return 0;
        }
    }
    if (destY>GetY()) {
        d = 4;  // Always move up first
    } else if (destX>GetX()) {
        d = 1;
    } else if (destX<GetX()) {
        d = 3;
    } else if (destZ>GetZ()) {
        d = 0;
    } else if (destZ<GetZ()) {
        d = 2;
    } else if (destY<GetY()) {
        d = 5; // and always down last
    } else {
        return 1;
    }
    log_file("Moving to Compressor "+CurrentC+" X:"+destX+" Y:"+destY+" Z:"+destZ+" Dir:"+d);
    if (!SafeMove(d)) {
        log_err("Could not move in direction "+d+". Area is probably not loaded.");
        Time = Time + 10000;
    }
    return 0;
}

function PushMaster()
{
    local i,j,v,b;
    b = 0;
    if (PathNo==2)
      b = GetLastBlackRock(); // If we build stair inside mining area we need to save one BlackRock type
    if (Look(5)==Compressor) {
        i = 0;
        j = 5000; // Limit how many voxels to push every Step.
        while (i<20 && j>0) {
            if (GetSlot_Quantity(i) > 0) {
                v = GetSlot_Type(i);
                if (v!=Compressor && v!=Robot && v!=b) {
                    PushVoxelTo(5,v);
                    j--;
                } else {
                    i++;
                }
            } else {
                i++;
            }
        }
        if (i >= 20) { // All Done
          return 1;
        }
    } else {
        if (GetQuantity(Compressor)>0) {
          log_info("Placeing Master Compressor");
          SafePickVoxel(5);
          PlaceVoxel(5,Compressor);
        } else {
           log_err("No Master Compressor found and no Atomic Compressor in inventory");
           Time = Time + 10000;
        }
    }
    return 0;
}

function IsStorageFull()
{
    local i;
    i = 0;
    while (GetSlot_Quantity(i) > 0 && i<20) {
      i++;
    }
    if (i>=20)
        return 1;
    return 0;
}

function MoveToStair()
{
    local d,destX,destY,destZ;

    if (BuildStairs==1) {
        destX = StartX + 2;
        destZ = StartZ - MiningSize - 2;
    } else {
        destX = StartX - 1;
        destZ = StartZ - MiningSize;
    }
    destY = StairsLevel;

    if (destX>GetX()) {
        d = 1;
    } else if (destX<GetX()) {
        d = 3;
    } else if (destY<GetY()) {
        d = 5;
    } else if (destY>GetY()) {
        d = 4;
    } else if (destZ>GetZ()) {
        d = 0;
    } else if (destZ<GetZ()) {
        d = 2;
    } else {
        if (BuildStairs==1)
          PathNo = 0;
        else
          PathNo = 2;
        Rotation = 0; // Always start from the beginning since we are only building full revolutions
        Step = 0;
        return 1;
    }
    log_file("Moving to start of stairs "+CurrentC+" X:"+destX+" Y:"+destY+" Z:"+destZ+" Dir:"+d);
    if (!SafeMove(d)) {
        log_err("Could not move in direction "+d+". Area is probably not loaded.");
        Time = Time + 10000;
    }
    return 0;
}

function BuildStair()
{
  local i,j,v,done;
  done = 0;
  do {
    // Check for end of path
    if (Step >= Path[PathNo].len())
    {
      Step = 0;
      Rotation = (Rotation+1)%4; // Next execution of path will be rotated one step clockwise.
      if (Rotation==0) { // One rotation done
        if (PathNo==0) {
          PathNo = 1; // Make doorway
          Rotation=3; // Only one rotation
        } else {
          StairsLevel = GetY();
          if (PathNo==1)
              PathNo = 0; // Reset PathNo to Stair
          if (StairsLevel <=  MiningLevel) // Continue until we are below of equal to the mining level
              return 1; // We are done. Let the caller know
        }
      }
    }
    i = Path[PathNo][Step];

    // Get direction part of path
    j = (i%8);
    if (j<4) // Don't rotate up/down
    {
      // Modify move/dig value with rotation
      j = (j+Rotation)%4;
    }

    v = Look(j);
    if ((i & 16)==16) { // Bit 8 set = Place Voxel
      if (GetVoxelProp(v,0)) { // If it is not a solid, place one.
        v = GetFirstBlackRock();
        if (v>0)
          PlaceVoxel(j,v);
      }
    } else {
      if (!GetVoxelProp(v,0)) // If it is a solid, mine it.
        SafePickVoxel(j);
    }
    if ((i & 8)==8) { // Bit 3 set = Move also
      if (!Move(j)) {
        log_err("Could not move while building stair! "+j);
      }
      done = 1;
    }
    Step++;
  } while (done==0)
  return 0; // Need to return but not really done yet
}

function GetFirstBlackRock()
{
  local a;
  for (a=1; a<=10; a++)
  {
      if(GetQuantity(a)>0)
      {
          return a;
      }
  }
  return 0;
}

function GetLastBlackRock()
{
  local a;
  for (a=10; a>=1; a--)
  {
      if(GetQuantity(a)>340)
      {
          return a;
      }
  }
  return 0;
}

function SafePickVoxel(dir)
{
    local v,b;
    v = Look(dir);
    if (v != Compressor && v != Robot) {
        b = GetVoxelProp(v,0)
        if (!b) { // If voxel is solid, pick it.
            return PickVoxel(dir);
        }
    } else {
      log_err("Oops. Almost picked a Compressor or Robot by mistake!");
      return 0;
    }
    return 1;
}

function SafeMove(dir)
{
    local v;
    if (SafePickVoxel(dir)) {
        v = Look(dir);
        if (v != 86 && v != 52) { // Avoid Green Acid and Lava
            return Move(dir);
        } else {
          log_err("Oops. Almost moved into Green Acid or Lava");
        }
    }
    return 0;
}

function log_file(msg)
{
    if (Debug>2) {
       error("Robot at " + GetX() + "," + GetY() + "," + GetZ() + " Info: " + msg+"\n");
    }
}

function log_info(msg)
{
    if (Debug>1) {
        Display( "Robot at " + GetX() + "," + GetY() + "," + GetZ() + " Info: " + msg, 1000, 4, 500);
        error("Robot at " + GetX() + "," + GetY() + "," + GetZ() + " Info: " + msg+"\n");
    }
}

function log_err(msg)
{
    if (Debug>0)
      Display( "ROBOT AT " + GetX() + "," + GetY() + "," + GetZ() + " Err: " + msg, 5000, 4, 2000);
    error("ROBOT AT " + GetX() + "," + GetY() + "," + GetZ() + " Err: " + msg+"\n");
    Time = Time + 2000;
}

30
Gallery / Re: Pictures of my work area
« on: October 17, 2013, 12:53:20 pm »
Finally gotten the Stainless Steel Bar factory working. I think it took me 6 hours to get it to work.

In the pictures the water source is not yet implemented, but it is done now.

I had to build this elaborate maze for the BlackRock Blue that trigger the water, and I still had to make a maze even for the water to give the molten metal time enough to mix properly. I kept having problems with the first block turning into Iron Bar instead of Stainless Steel because the water arrived to fast.
I also needed to use 10 blackrock Blue that each trigger one block of water, or the water flows to fast. It seems that if a molten metal block is moved by the conveyor into a water black it will not be cooled. I also had trouble with Sequencer and Materalizer sending out blocks into water blocks resulting in loosing water. Looks like they still send out stuff when there is a liquid on there output side. I solved it by having the sequencer send out the blackrock blue first, end then the water, otherwise the blackrock blue "eat" the water.

The optical fiber in the picture is just to return the blackrock blue back to the input side. It is the same blackrock blues that circulate around infinite. The water is also feed to the top above the molten metal with a optical fiber, but that was not built yet when I took the pictures.
I really would have wanted it to be "cleaner" but this is what I had to do to make it work stable. Way to many Materializers/Dematerializers where harmed in making this factory.

Pages: 1 [2] 3 4 5