I read a few other questions here about it but I'm just not getting it.
I have some variables that change through the course of execution so I understand that they need to go in memory.
var populationManager = {
init: function(){
Memory.PopulationManager = {};
Memory.PopulationManager.nHarvesters = 0;
Memory.PopulationManager.nUpgraders = 0;
Memory.PopulationManager.nBuilders = 0;
Memory.PopulationManager.harvesterNameNum = 0;
Memory.PopulationManager.upgraderNameNum = 0;
Memory.PopulationManager.builderNameNum = 0;
},
demographics: function(){
if( ! Memory.PopulationManager.nHarvesters )
this.init(); //not initialized yet
But it is telling me it cannot read property nHarvesters of undefined.
How do I make my own screeps Memory objects and use them?
After looking over your code I found that the issue is that you are checking for a property of an object that doesn't exist and want you should be doing is checking if the actual object exists.
Change
if( ! Memory.PopulationManager.nHarvesters )
to
if( ! Memory.PopulationManager )
and that will do what you need it to.
Related
I have a List of the type Model. when I loop all its elements and loop the next one except for the last one, then change the last one manually, the one before changes.
here is a little code to reproduce the problem (also you can run it directly in dartpad from here)
void main() {
List<Model> s = [];
for (int i = 0; i < 5; i++) {
s.add(Model(i));
}
for (int i = 0; i < s.length - 1; i++) {
s[i] = s[i + 1];
}
print(s);
s[s.length-1].x = 100;
print(s);
}
class Model {
int x;
Model(this.x);
#override
String toString() => 'x: ' + this.x.toString();
}
notice that this problem does not happen when you comment out the for loop or the manual change, or instead of changing the last one's property, you reassign a new value to it, like s[s.length - 1] = Model(100);. seems like dart for some reason is re-running the loop.
When you run the second for loop, you assign the i + 1th Model to the ith position in the list:
// initialise list
for (int i = 0; i < s.length; i++) {
s[i] = s[i + 1]
}
If you unwrap the loop, it looks roughly like this:
s[0] = s[1];
s[1] = s[2];
s[2] = s[3];
s[3] = s[4];
Notice that this leaves s[4] unchanged, but also assigns it to s[3].
In Dart, variables contain references to objects. This means that when your list runs s[3] = s[4];, both s[3] and s[4] point to the same object.
Now, if you modify s[4] you, are actually modifying the objects that s[4] refers to, which happens to also be the object that s[3] refers to, so they both appear to change in your list.
I'm using a turn-based match for a board game, and when a turn is complete I call GKTurnBasedMatch.EndTurn and pass the match participants and the new match data as the arguments. I need the game to advance to the unmatched players, but it only does so after some indeterminate time related to the timeout value. Setting the timeout value 0 only prevents the game from ever progressing past player 1. The match data is being updated, so the app is definitely communicating with Game Center servers. What am I missing here?
private void endTurn(double timeout)
{
// Copies list of participants to a mutable array
GKTurnBasedParticipant[] Participants = new GKTurnBasedParticipant[match.Participants.Length];
match.Participants.CopyTo(Participants, 0);
// Advances to the next player
match.EndTurn(Participants, timeout, matchData, (e) =>
{
// If there is an error message, print it to the console
if (e != null)
{
Console.WriteLine(e.LocalizedDescription);
Console.WriteLine(e.LocalizedFailureReason);
}
// Otherwise proceed normally
else
turnOverUpdate();
});
}
Apple's documentation is quite poor for the EndTurn method, but I figured it out. The NextParticipants field should be treated like EndTurnWithNextParticipant, so you have to copy GKTurnBasedMatch.Participants and reorder it so the next player is first and so fourth. The match only gives you the participants in order of joining, not relative to the local player, so you have to sort it. Below is the code I used to accomplish this.
List<GKTurnBasedParticipant> participants = new List<GKTurnBasedParticipant>();
// Gets the index of the local player
int index = 0;
for (int i = 0; i < match.Participants.Length; i++)
{
if (match.Participants[i].Player != null)
{
if (match.Participants[i].Player.PlayerID == GKLocalPlayer.LocalPlayer.PlayerID)
{
index = i;
break;
}
}
}
int offset = match.Participants.Length - index;
for (int i = 1; i < offset; i++)
participants.Add(match.Participants[i + index]);
for (int i = 0; i <= index; i++)
participants.Add(match.Participants[i]);
GKTurnBasedParticipant[] nextParticipants = participants.ToArray();
I would like to write Actionscript loop that involves "getURL". However, from what I can see getURL does not allow concatenation of variable names?
I have variables textholder0, textholder1, textholder2 that have movieclip names as values and link0, link1, link2 that have website addresses as values.
I can use this["textholder" + 0].onRelease but getURL("link"+ 0) gives "undefined"
textholder0.onRelease = function()
{
getURL(link0);
}
textholder1.onRelease = function()
{
getURL(link1);
}
textholder2.onRelease = function()
{
getURL(link2);
}
Any way to do this so I can create a loop for the above?
Here is a test. Unfortunately, it still gives me "undefined/" for the URL. To keep it simple I created three movie clips, with instances textholder0, textholder1, textholder2. Put a loop on the main timeline.
var links:Array = ["http://www.google.ca", "http://www.google.com", "http://www.google.ru"];
for(var i:Number=0; i<links.length; i++){
this["textholder" + i].linkURL = links[i];
this["textholder" + i].onRelease = function() {
getURL(linkURL);
}
}
Here is output from debugger window
Variable _level0.links = [object #1, class 'Array'] [
0:"http://www.google.ca",
1:"http://www.google.com",
2:"http://www.google.ru" ]
Variable _level0.i = 3
Movie Clip: Target="_level0.textholder0"
Variable _level0.textholder0.linkURL = "http://www.google.ca"
Variable _level0.textholder0.onRelease = [function 'onRelease']
Movie Clip: Target="_level0.textholder1"
Variable _level0.textholder1.linkURL = "http://www.google.com"
Variable _level0.textholder1.onRelease = [function 'onRelease']
Movie Clip: Target="_level0.textholder2"
Variable _level0.textholder2.linkURL = "http://www.google.ru"
Variable _level0.textholder2.onRelease = [function 'onRelease']
I am starting to think that you can not use onRelease within a loop at all.
getURL("link"+ 0) will try to go to a URL "link0", since "link"+ 0 will be concatenated to the string "link0", and not get the value of link0. But you can try doing this:
getURL(this["link" + 0]);
The difference, and the mechanism of the bracket notation, is that you can reference a property of an object in two ways - using dot notation, like this.link0, or the bracket notation, this["link0"]. But it has to be expressed as an object property, just saying "link" + 0 anywhere, like in getURL("link"+ 0) won't give a reference to link0.
ok, so I think the problem with the loop here is that it was incrementing "i" variable before any of the buttons were clicked.
http://www.senocular.com/flash/tutorials/faq/#loopfunctions
Senocular.com says "you need to define a new, unique variable to represent that value at the time of function creation and have the function reference that value"
So the loop goes as following
var links:Array = ["http://www.google.ca", "http://www.google.com", "http://www.google.ru"];
var curr_button;
for(var i=0; i<=links.length; i++){
curr_button = this["textholder"+i];
//note creation of an extra variable "num" below to store the temp number
curr_button.num = i;
curr_button.onRelease = function() {
getURL(links[this.num]);
}
}
I've been programming some stuff in ActionScript (Haxe) and arrived this very specific problem.
Here's the code (pseudo :S):
var func:Array = new Array(256);
(A) var i:Int = 0;
for(;i<256;i++) { // OR // for(i in 0...256) {
func[i] = function() { trace(i); }
}
func[0]();
func[127]();
func[256]();
The above code outputs (a):
256
256
256
I want that to be (b):
0
127
256
That doesn't happen, because ActionScript/Haxe is assigning the reference of i to the function, and since i equals 256 at the end of the loop where the functions get evaluated, that's why I get (a).
Does anyone know of a way to avoid that and get the expected results at (b) ?
Thanks to all of you guys and your responses.
I think I've found the answer. If you remove the line marked with (A) it works, if you leave it it doesn't. I'm pretty sure you could all figure out why that happens. Thanks again!
it's not neccessary to use callback, this should work as expected (haxe creates a local var in each loop):
var func = [];
for(i in 0...256)
func[i] = function() trace(i);
func[0]();
func[127]();
The one you show is the expected/desired behavior. To retain the value of "i" you must use "callback":
/* not pseudo code ;) */
var func = [];
for(i in 0...256)
func[i] = callback(function(v) trace(v), i);
func[0]();
func[127]();
func[256]();
I'm an experienced programmer but just starting out with Flash/Actionscript. I'm working on a project that for certain reasons requires me to use Actionscript 2 rather than 3.
When I run the following (I just put it in frame one of a new flash project), the output is a 3 rather than a 1 ? I need it to be a 1.
Why does the scope of the 'ii' variable continue between loops?
var fs:Array = new Array();
for (var i = 0; i < 3; i++){
var ii = i + 1;
fs[i] = function(){
trace(ii);
}
}
fs[0]();
Unfortunately, AS2 is not that kind of language; it doesn't have that kind of closure. Functions aren't exactly first-class citizens in AS2, and one of the results of that is that a function doesn't retain its own scope, it has to be associated with some scope when it's called (usually the same scope where the function itself is defined, unless you use a function's call or apply methods).
Then when the function is executed, the scope of variables inside it is just the scope of wherever it happened to be called - in your case, the scope outside your loop. This is also why you can do things like this:
function foo() {
trace( this.value );
}
objA = { value:"A" };
objB = { value:"B" };
foo.apply( objA ); // A
foo.apply( objB ); // B
objA.foo = foo;
objB.foo = foo;
objA.foo(); // A
objB.foo(); // B
If you're used to true OO languages that looks very strange, and the reason is that AS2 is ultimately a prototyped language. Everything that looks object-oriented is just a coincidence. ;D
Unfortunately Actionscript 2.0 does not have a strong scope... especially on the time line.
var fs:Array = new Array();
for (var i = 0; i < 3; i++){
var ii = i + 1;
fs[i] = function(){
trace(ii);
}
}
fs[0]();
trace("out of scope: " + ii + "... but still works");
I came up with a kind of strage solution to my own problem:
var fs:Array = new Array();
for (var i = 0; i < 3; i++){
var ii = i + 1;
f = function(j){
return function(){
trace(j);
};
};
fs[i] = f(ii);
}
fs[0](); //1
fs[1](); //2
fs[2](); //3