Navigation

    forum

    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Users
    • Groups
    1. Home
    2. Toolmaker
    3. Posts
    • Flag Profile
    • block_user
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Groups
    • Blog

    Posts made by Toolmaker

    • Tombstones and new reaction cooldowns not in Steam server

      The latest changes to the game, the tombstones and new reaction cooldowns, aren't available in the Steam dedicated server like they are available on the production environment.

      I used the dedicated Steam server for development and testing. It runs at a pace I can control, allows me to 'cheat' by editing the database from the CLI and in general have full control over it. However, with the dedicated Steam server and the production environment running on different server version my codebase has to either compensate for the change(ie, have a special getCooldownForReaction(resource) method containing a switch and I cannot use the tombstones.

      I am aware there is the PTR, but even then it would make my code unable to run on the Steam server and thus severely hamper my ability to develop and debug.

      Is there any update on when the Steam version will be updated?

      posted in Private servers
      Toolmaker
    • RE: Draft: room event log

      Great idea, however, since accessing the eventLog incurs costs, would it be possible to apply filtering before accessing the eventlog? For instance, let's assume I do not care about my harvest effeciency but only care for attack events, would it be possible to call setEventLogFilter() on the room and only supply EVENT_ATTACK as a filter?

      By default, no filtering is applied, but after calling this method, all other events are ommitted from the log(and thus also save cpu cycles server side when serializing it).

      posted in General Discussion
      Toolmaker
    • RE: Extension Building impossible to finish

      I've had this occur in my SIM room as well. Creep.build() returns 0, no actual building is done(carry[ENERGY] won't decrease either) and the whole thing locks up. I noticed that if I build a container it places 2 construction sites. The count goes down by 2 and IF the container finishes I can still see the second construction site. I restarted several times, tried 2 different browsers(and the Steam client) and the lock ups happen at different moments, sometimes it finishes other times it won't.

      posted in Technical Issues and Bugs
      Toolmaker
    • RE: Incorrect handling of available extension count when placing them manually

      This bug is still present in the simulation room. Whenever I zoom in on a container it will show a construction site underneath. Changing to a different room is impossible because it will reset the sim room. It also happened that containers were never finished, even though the creep.build() returned 0.

      posted in Technical Issues and Bugs
      Toolmaker
    • RE: More than one room in simulation mode?

      Thank you for the reply Artem, I shall use the PTR for implementing my multi-room related code.

      I'm aware that in software development there are always more possible features to implement than there is time available. Having the PTR is a great alternative to the simulation but it lacks one important aspect in regard to the simulation: total control. In the simulation mode I can create a room layout to my liking and if necessary increase the RCL, add structures so I don't need to wait for them to be built and but more importantly: increase the game speed to 500% without any limitations on the amount of CPU cycles. Features that making testing incredibly efficient and productive.

      Please don't feel hard pressed, I rather have you guys spend your time on implementing World mode related features but if you at some point do have a little time to spare it would be absolutely wonderful if the simulation room could be made multi-roomed, even if it would only be 2 rooms without any fancy bells and whistles.

      I understand that your time is very limited and don't believe this should be a high-priority feature.

      posted in Feature Requests
      Toolmaker
    • More than one room in simulation mode?

      I'm currently getting my AI ready to start playing in World mode. However, it is impossible to test out my AI behaves when it has to colonize another room, attack another player or in fact just discovering a new room for the first time. Attacking Player 2 in the same room has limited opportunity to test my scripts in all scenarios and I rather not fiddle around in production later on to implement these things.

      Can the simulation be expanded with at least 1 additional room? Having a total of 5 rooms would be most perfect(a center room with connecting rooms in the north/east/west/south) but I'm not too picky and would totally settle for just one additional room.

      posted in Feature Requests
      Toolmaker
    • RE: List creeps and filter

      I've ran into this exact same problem today, with this code:

      var drops = _(this.memory).filter(function(node) {
      return node.amount - node.capacity > 0;
      }).map(function (node) {
      return Game.getObjectById(node.id);
      });

      If you're chaining lodash method calls, they will get wrapped in a lodash object and you need to call value() as the last method in the chain to execute it and unwrap the result. The proper block looks like this:

      var drops = _(this.memory).filter(function(node) {
      return node.amount - node.capacity > 0;
      }).map(function (node) {
      return Game.getObjectById(node.id);
      }).value();

      You can read more about this here.

       

      In other words, you last method call should look like this:

      _(Game.creeps).filter({ memory: { role: 'Harvester' }}).value();
      posted in Help
      Toolmaker
    • RE: require occasionally takes up a lot of CPU

      I have noticed this behavior as well and I think it is because of the javascript files being compiled, as I detailed in my answer in this post

      posted in Technical Issues and Bugs
      Toolmaker
    • RE: Source keeper...what is that?

      You can find more information on the Source Keepers in this post.

      In short: Source Keepers guard sources in maps. Every room has up to TWO unprotected sources which are freely accessible by your creeps without being hindered. If your room has more than 2 sources the remaining sources will have a Keeper Lair within 5 tiles which will spawn Keepers. The keepers follow the same lifecycle as your creeps(they live only 30 minutes) and have a mission to keep you from accessing the source's energy. In order to get to the source you will have to kill the keeper and kill it after it respawns after 300 ticks.

      It is lazy so it won't stray far from its source and will not bother to follow your creeps but it will attack any creeps that is near the source. Once killed it will drop energy which you can pickup. If you intend to mine those sources(which is advisable) you should build protective ramparts around the source to protect your miners and trucks.

      posted in Help
      Toolmaker
    • RE: Extending String.prototype for easier string formatting

      And they just updated to a version of iojs that supports ec6. So I'll be using template strings from now on.

      posted in General Discussion
      Toolmaker
    • RE: Extending String.prototype for easier string formatting

      I agree, string concats are faster than using this method. But especially when I'm debugging stuff I don't really care about the speed but more about convenience and readability. Once a module is complete I strip it of any log messages anyway.

      posted in General Discussion
      Toolmaker
    • RE: Keepers are breaking free

      Thanks for fixing this up. It was unexpected to see keepers break free all the sudden and ruin one of my mining operations but at least now one has to keep constructing soldiers in order to keep them in check. Seems like I have my work cutout for me today.

      posted in General Discussion
      Toolmaker
    • Extending String.prototype for easier string formatting

      I see a lot of code snippets passing by where a lot of string concatenation is done using the + operator, like console.log("Creep " + creep.name + " is located on (" + creep.pos.x + ", " + creep.pos.y + ").");. I personally find such statements difficult to write due to the excessive amounts of " and + signs and even more difficult to read.

      So I liberated the following snippet from Microsoft's Ajax library and modified it slightly for my own purposes. It is based on the .NET implementation of String.Format(), allowing you to write your statements as console.log("Creep {0} is located near ({1}, {2})".format(creep.name, creep.pos.x, creep.pos.y);

      Thought I'd share this one.

      var _ = require("lodash");
      
      module.exports = function() {
          String.prototype.format = function(format, args) {
              /// <summary>Replaces the format items in a specified String with the text equivalents of the values of   corresponding object instances. The invariant culture will be used to format dates and numbers.</summary>
              /// <param name="format" type="String">A format string.</param>
              /// <param name="args" parameterArray="true" mayBeNull="true">The objects to format.</param>
              /// <returns type="String">A copy of format in which the format items have been replaced by the   string equivalent of the corresponding instances of object arguments.</returns>
              return String.prototype._toFormattedString(this, _.values(arguments));
          };
      
          String.prototype._toFormattedString = function(format, args) {
              var result = '';
      
              for (var i = 0; ; ) {
                  // Find the next opening or closing brace
                  var open = format.indexOf('{', i);
                  var close = format.indexOf('}', i);
                  if ((open < 0) && (close < 0)) {
                      // Not found: copy the end of the string and break
                      result += format.slice(i);
                      break;
                  }
                  if ((close > 0) && ((close < open) || (open < 0))) {
      
                      if (format.charAt(close + 1) !== '}') {
                          throw new Error('format stringFormatBraceMismatch');
                      }
      
                      result += format.slice(i, close + 1);
                      i = close + 2;
                      continue;
                  }
      
                  // Copy the string before the brace
                  result += format.slice(i, open);
                  i = open + 1;
      
                  // Check for double braces (which display as one and are not arguments)
                  if (format.charAt(i) === '{') {
                      result += '{';
                      i++;
                      continue;
                  }
      
                  if (close < 0) throw new Error('format stringFormatBraceMismatch');
      
                  // Get the string between the braces, and split it around the ':' (if any)
                  var brace = format.substring(i, close);
                  var colonIndex = brace.indexOf(':');
                  var argNumber = parseInt((colonIndex < 0) ? brace : brace.substring(0, colonIndex), 10);
      
                  if (isNaN(argNumber)) throw new Error('format stringFormatInvalid');
      
                  var argFormat = (colonIndex < 0) ? '' : brace.substring(colonIndex + 1);
      
                  var arg = args[argNumber];
                  if (typeof (arg) === "undefined") {
                      arg = '[undefined]';
                  } else if (arg === null) {
                      arg = '[null]';
                  }
      
                  // If it has a toFormattedString method, call it.  Otherwise, call toString()
                  if (arg.format) {
                      result += arg.format(argFormat);
                  }
                  else
                      result += arg.toString();
      
                  i = close + 1;
              }
      
              return result;
          };
      };
      
      posted in General Discussion
      Toolmaker
    • RE: Map getting a bit cramped

      A map getting a bit cramped might finally mean people will have to start combating for rooms, which isn't a bad thing in my opinion.

      posted in General Discussion
      Toolmaker
    • RE: New terrain type request

      What would be the added benefit of having this terrain type? Adding something just for the sole purpose of being 'cool' wouldn't add much to the game. It might in fact degrade the experience.

      Why would I want a mountain, why would I want to construct a road on it and why would I then decide to 'climb' up the mountain?

      posted in Feature Requests
      Toolmaker
    • RE: How much CPU does cycle eats.

      It really depends on what you're doing and how you're doing it and without seeing any code it is really difficult to determine if your code is using up a lot of CPU or not. I wrote a cpu module for this purpose, of which I've attached the code below. Put this in a file named cpu.js and in the top of your main put global.cpu = require("cpu"); immediately followed by a cpu.init();

      "use strict";
      
      var _ = require("lodash");
      
      function init() {
          Memory.cpu = {};
      }
      
      function begin(key) {
          if (Memory.cpu[key] === undefined) {
              Memory.cpu[key] = {
                  total: 0
              };
          }
      
          if (Memory.cpu[key].start === undefined)
              Memory.cpu[key].start = Game.getUsedCpu();
      }
      
      function end(key) {
          if (Memory.cpu[key] === undefined) {
              console.log("[WARN] Ending logging for '{0}' without begin()".format(key));
      
              if (Memory.cpu[key] === undefined) {
                  Memory.cpu[key] = {
                      total: 0,
                      start: 0
                  };
              }
          }
      
          Memory.cpu[key].total += Game.getUsedCpu() - Memory.cpu[key].start;
          delete Memory.cpu[key].start;
      }
      
      function track(key, fn) {
          if (key === undefined)
              throw new Error("cpu.track(key, function) was called without a key and function.");
          if (!_.isFunction(fn))
              throw new Error("cpu.track(key, function) was called without a function.");
      
          if (Memory.cpu === undefined)
              Memory.cpu = {};
      
          var begin = Game.getUsedCpu();
          fn();
          var total = Game.getUsedCpu() - begin;
      
          if (Memory.cpu[key] === undefined) {
              Memory.cpu[key] = {
                  total: total
              };
          } else {
              Memory.cpu[key].total += total;
          }
      }
      
      function show(keys) {
          if (Memory.cpu === undefined)
              return;
      
          var text = "CPU usage:\n";
      
          if (Memory.cpu === undefined)
              return;
      
          _.each(Memory.cpu, function(value, key) {
              if (keys === undefined || _.contains(keys, key))
                  text += "{0}: {1}\n".format(key, value.total);
          });
          text += "Total CPU used: {0}".format(Game.getUsedCpu());
          console.log(text);
      }
      
      module.exports = {
          init: init,
          begin: begin,
          end: end,
          track: track,
          show: show
      };
      

      There are two ways in which you can use this module: You can either call cpu.begin("nameToTrack"); execute your code and then call cpu.end("nameToTrack");. Or you can wrap whatever your wish to time into a parameterless function and call the track(key, fn) function like so:

      cpu.track("someName", function() {
          var totalEnergy = _.reduce(Game.structures, function(total, s){
               return total + s.energy;
          },0);
      });
      

      To display the timing results you can use cpu.show(); or cpu.show(["keyOne", "keyTwo"]);. The second version will only display the keys passed into the array. I have a version of my cpu module that tracks averages over several ticks but I'm sure you can figure that out yourself.

      posted in Help
      Toolmaker
    • RE: Walling In Source Keeper Spawns

      Probably. I should debug it a bit soon, after I finished writing code to expand into a new room and construct roads.

      posted in General Discussion
      Toolmaker
    • RE: Significant cpu is used before my script is run

      I'm having this problem too and I think I managed to track it down. I started by putting a Game.getUsedCpu() at the top of my main.js and it almost always had a value less than 2, so the reported cpu is actually going into the execution of your scripts.

      I have a cpu object in the global scope to keep track of cpu usage and a lot of time goes into the require() function it seems. I do most of my require'ing in a module called init, looking like this:

          cpu.track("init", function() {
              var modules = [
                  "string", // *must* be first or catch-block will fail
                  "global",
                  "math",
                  "protoGame",
                  "protoGame",
                  "protoSpawn",
                  "protoCreep",
                  "protoRoom",
                  "protoSource",
                  "protoStructure",
                  "protoRoomPosition"
              ];
      
              _.each(modules, function(module) {
                  try {
                      cpu.begin(module);
                      require(module)();
                      cpu.end(module);
                  }
                  catch (ex) {
                      console.log("Exception caught: {0}.Stack: {1}".format(ex, ex.stack));
                  }
              });
      
              _.mixin(Room.prototype, brainRoom, { "chain": false });
      
              if (_.isUndefined(Memory.index)) {
                  Memory.index = {};
              }
          });
      

      The output of that looks like this (I stripped away the items that were <2):
      ```
      protoCreep: 10.955753000000001
      protoRoom: 6.102737000000001
      protoRoom.require: 4.112070000000003
      init: 27.029208

      protoCreep: 7.1586099999999995
      protoRoom: 12.721302000000001
      protoRoom.require: 9.670390999999999
      init: 28.924640999999998
      ```

      Most of these files modify the prototypes of various game objects(hence the proto prefix) but I also timed the require calls and as you can see they take up most of the time.

      To add some more detailed output I decided to time the execution of the modules that are actually being required by adding a begin()/end() call at the top/bottom of the those to time how long it took the VM to evaluate the actual files. The results were as follows:

      protoRoom: 5.566376000000002
      EnergyMap: 0.04861100000000107
      B-Q: 0.0905040000000028
      C-Q: 0.08399100000000104
      Statistics: 0.04209700000000183
      protoRoom.require: 3.4115080000000013
      init: 22.651317

      It would be really nice if all the source files were actually pre-included before our main functions were executed so that the amount of time spent in require() calls would be reduced to a minimum. Any script file that throws a compile error is ignored. And of course, the scripts shouldn't be executed, just precompiled.

      posted in Technical Issues and Bugs
      Toolmaker
    • RE: Walling In Source Keeper Spawns

      See this post for more discussion on the subject.

      And no, the keepers will spawn even if they can't leave their spawn. I have one of the keepers in my room (W13S11, bottom left of the map) sealed it and it will still spawn, just can't leave its lair. You can only attack the keeper with ranged attack when he's on the lair, I tried with short range attack and that had no effects.

      posted in General Discussion
      Toolmaker
    • RE: Are sources under Source Keeper worth fighting for?

      You can protect your workers by building ramparts on their work positions and the locations carriers await their pickup turn(or have them wait outside the attack range of the keeper). If you wall in the keeper into its lair you can in certain cases(but not all since walls/ramparts will not prevent ranged attacks from passing over them) avoid fighting it completely. So you only have to murder it to death while constructing/repairing the walls.

      In the other cases it is advisable to have plenty of ramparts around it in which guards can stand to fight it. They won't get hit as long as they're within a rampart and like Chris said, if you kill it on a tile other than its lair you can collect the energy the keeper drops too.

      posted in General Discussion
      Toolmaker