Jump to content
Gen. MERICA

Loop not stopping, hint giving error

Recommended Posts

Trying to sort which towns (Markers) are the closest and have not been captured.

I can get it to sort which towns are the closest however when checking the value for whether or not it is captured in the loop throws an error?

 

To help give you the run down,

ClosestTowns = [All the towns positions]

ClosestTownsState = [The state of the town, 0 for civ, 1 for blu, 2 for op and 3 for ind]

 

ClosestTowns = Towns;
ClosestTownsState = TownsState;

for[{_t = 0},{_t != count ClosestTowns},{_t = _t + 1}] do {
	for[{_t2 = _t},{_t2 != count ClosestTowns},{_t2 = _t2 + 1}] do {
		if(((ClosestTowns select _t) distance2D player) > ((ClosestTowns select _t2) distance2D player)) then {
			_placeotest = ClosestTowns select _t;
			_placeoval = ClosestTownsState select _t;
			_placetest = ClosestTowns select _t2;
			_placeval = ClosestTownsState select _t2;
			
			ClosestTowns set [_t, _placetest];
			ClosestTowns set [_t2, _placeotest];
			ClosestTownsState set [_t, _placeval];
			ClosestTownsState set [_t2, _placeoval];
			
		};
	};
	
};

The sort above works correctly but I wanted to put it there just in case it ends up being the problem (its just a bubble sort for two arrays).

Both of these do return the correct values when doing

hint format ["%1" ClosestTowns select _x];

hint format ["%1" ClosestTownsState select _x];

 

They do return the correct values and locations.

 

However, when I have the same script check for if the town state isnt 1, it works on the first run

so this means the town is closest, stop the loop. Only it doesnt stop, it turns back around and gives an error.

for[{_t = 0},{_t != count Towns},{_t = _t + 1}] do {
	hint format["%1", ClosestTownsState select _t];
	if((ClosestTownsState select _t) != 1) then {
	player setPos (ClosestTowns select _t);
	_t = count Towns;
	};
	sleep 5;
};

I get this error, not sure why the loop goes around again.

If I set it to a number, it loops around again?

for[{_t = 0},{_t != 10},{_t = _t + 1}] do {
hint format["%1", ClosestTownsState select _t];
	if((ClosestTownsState select _t) != 1) then {
	player setPos (ClosestTowns select _t);
	_t = 10;
	};
	sleep 5;
};

http://imgur.com/8QKqzoe

It gives this error, although it does what it is supposed to the loop never stops.

Share this post


Link to post
Share on other sites

I'm guessing the issue is with

_t != count Towns

That makes it possible for _t to be bigger that count Towns and cause infinite loop. It should be 

_t < count Towns

Also, using _t = count Towns to break the loop condition is not the best way to stop it.

 

You can use exitWith to stop the loop and execute some code, it's more clear. Example:

for[{_t = 0},{_t < count Towns},{_t = _t + 1}] do {
	hint format["%1", ClosestTownsState select _t];
	
    	// This is same as normal if, but it will stop the loop if the condition is satisfied
   	if((ClosestTownsState select _t) != 1) exitWith {
		player setPos (ClosestTowns select _t);
	};
    
	sleep 5;
};

You can also use breakTo / breakOut, but it's a bit more complicated

Share this post


Link to post
Share on other sites

You don't need to loop this, do you only need to return the closest non captured town?

 

Cheers

Share this post


Link to post
Share on other sites
2 hours ago, SkaceKachna said:

I'm guessing the issue is with


_t != count Towns

That makes it possible for _t to be bigger that count Towns and cause infinite loop. It should be 


_t < count Towns

Also, using _t = count Towns to break the loop condition is not the best way to stop it.

 

You can use exitWith to stop the loop and execute some code, it's more clear. Example:


for[{_t = 0},{_t < count Towns},{_t = _t + 1}] do {
	hint format["%1", ClosestTownsState select _t];
	
    	// This is same as normal if, but it will stop the loop if the condition is satisfied
   	if((ClosestTownsState select _t) != 1) exitWith {
		player setPos (ClosestTowns select _t);
	};
    
	sleep 5;
};

You can also use breakTo / breakOut, but it's a bit more complicated

Works perfectly!

Dont know how I didnt think of it becoming greater than, but I dont see how it could've done that it the first place but ill just leave it arma.

Interesting solution though, never had to use an exitWith yet.

 

And to answer Grumpy Old Mans question for giggles, I Ideally need it to return 3 of the closest towns to capture, so I would need a loop to cycle through towns that are already captured.

Share this post


Link to post
Share on other sites
3 hours ago, Gen. MERICA said:

And to answer Grumpy Old Mans question for giggles, I Ideally need it to return 3 of the closest towns to capture, so I would need a loop to cycle through towns that are already captured.

 

Piece of cake, still no foreach or for _i from loop needed.

At first I need some data to work with, so we generate 30 random positions and populate an occupation array, giving a random value between 0 and 3 for every random position.

I also generate markers for visualization.

testTowns = [];
testOccupations = [];
testOccupants = ["Civ","Blufor","Opfor","Indfor"];
_mrkColor = ["ColorCIV","ColorWEST","ColorEAST","ColorGUER"];
{deletemarker _x} foreach allMapMarkers;
for "_i" from 1 to 30 do {

	_rndpos =(player getrelpos [500 + (random 2000),random 360]);
	_rndOcc =(selectRandom [0,1,2,3]);
	_descOcc = testOccupants select _rndOcc;
	_marker = createmarker [str random 100000,_rndpos];
	_marker setmarkertype "hd_dot";
	_marker setmarkercolor (_mrkColor select _rndocc);
	_marker setmarkertext format ["Marker %1: %2",_i,_descOcc];
	testTowns pushback _rndpos;
	testOccupations pushback _rndOcc;

};

You obviously don't have to do that, since you already have a position and occupation array.

Now to find the closest position that is not occupied by blufor (at least that's what I think you want) we filter through the lists:

_notBlue = testTowns select {_index = testTowns find _x;_occupation = testOccupations select _index;_occupation != 1};
_findclosest = _notBlue apply {[_x distance2d player,_x]};
_findclosest sort true;
if (count _findclosest >= 3) then {_findclosest resize 3};
_result = _findclosest apply {_x select 1};

That's it, might be even done with less than 5 lines, but I'm lazy today, running for roughly 0.16ms, so not bad for an occasional check. :yay:

Now to again visualize if the findings are correct markers come out to play again:

{

	_marker = createmarker [str random 100000,_x];
	_marker setmarkertype "hd_warning";
	_marker setmarkercolor "ColorRed";
	_marker setmarkertext format ["!!!Result %1!!!",_foreachindex];

} foreach _result;

621mfvL.jpg

 

 

Cheers

Share this post


Link to post
Share on other sites
2 hours ago, Grumpy Old Man said:

 


_notBlue = testTowns select {_index = testTowns find _x;_occupation = testOccupations select _index;_occupation != 1};
_findclosest = _notBlue apply {[_x distance2d player,_x]};
_findclosest sort true;
if (count _findclosest >= 3) then {_findclosest resize 3};
_result = _findclosest apply {_x select 1};

 

 

Very interesting response, never knew the select {code here} could be extended like that.

I will have to play with the select syntax's more but thanks for the beautiful response,

The way I was doing it was much less... organized to say the least.

  • Like 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×