Another Array problem (from an old code)...

The place to post your WML questions and answers.

Moderator: Forum Moderators

Forum rules
  • Please use [code] BBCode tags in your posts for embedding WML snippets.
  • To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
Post Reply
Dret
Posts: 79
Joined: June 13th, 2007, 11:06 pm
Contact:

Another Array problem (from an old code)...

Post by Dret »

Hi to all... in according with Sapient'suggest... I open a new topic to don't clutt the Array Tutorial one.

This problem is related a code exposed in another post (here)... For an easy consultation I put all code inside an attachment.

The problem is:

I'm realizing wml a code to give possibility to "place fires" on battle field (as barriers against enemy and to light-up an area, to prevent assaults of "nightstalk" units).

The code works in this way:

1 Take a Straw Bale and move it on a specific hex
2 Leave the Bale upon the hex
3 Burn the Bale
4 After 2 turns, the fire stop burning

The code works perfectly... until step 4...

The function to "turn off" the fire... have a problem...

The structure of code include:

A [set_menu] item to "Burn the strow bale" that create an array (with [store_location]) to store all fire locations. I have also added a variable $array[$index].turn to control when the fire have to be "turned off".
(the FIRE_LIST macro)

Then I prepared a FOREACH + NEXT code to check each arrays's element to control the variable $array[$index].turn.
(the CONTROL_FIRE macro)

All work fine... but only if I place a single fire on battel ground...
If i set more than 1 fire... the "time limit" of the burning fire don't work for all array's elements but only for the first.

The problem could be located in two different place:
- Definition of $array[$index].turn variable.
- The control of the same variable.

Someone can help me?

Thanks Bye!
Attachments
attach.cfg
(1.1 KiB) Downloaded 193 times
AI
Developer
Posts: 2396
Joined: January 31st, 2008, 8:38 pm

Re: Another Array problem (from an old code)...

Post by AI »

Well, you're using the non-existant macro VARIABILE_OPER instead of VARIABLE_OP.

Also, you're using it in a place where you want to use the [variable] tag (which checks variables) rather than [set_variable]. (which changes them and is what VARIABLE and VARIABLE_OP shorten)
Dret
Posts: 79
Joined: June 13th, 2007, 11:06 pm
Contact:

Re: Another Array problem (from an old code)...

Post by Dret »

Excuse me, is not an error: that MACRO was previously defined by myself in this way:

#define VARIABILE_OPER NOM_VAR OP VALO
[variable]
name={NOM_VAR}
{OP}={VALO}
[/variable]
#enddef

I forgot to insert it in attachment...
I have used it in other scenarios and works perfectly.

Is maybe uncorrect to use it here?
User avatar
governor
Posts: 267
Joined: December 8th, 2006, 12:32 am

Re: Another Array problem (from an old code)...

Post by governor »

Meant to be one line?

Code: Select all

#HERE A MACRO TO REMOVE THE FIRE LOCATION FROM "FIRELIST" ARRAY		{REMOVE_FIRELIST}
also you will need a FOREACH to iterate over this, otherwise you arent accomplishing what you are trying to accomplish

Code: Select all

        [set_variable]
	name=index
	add=-1
	[/set_variable]	
	
	[set_variable]
	name=firelist[$index].turn
	value=2
	[/set_variable]	
Dret
Posts: 79
Joined: June 13th, 2007, 11:06 pm
Contact:

Re: Another Array problem (from an old code)...

Post by Dret »

Please can you explain me with an example... I'm a little bit confused...! :hmm:

I used the coded previously quoted (the second one) to iterate only over the last submitted element of array: to set time limit for each "fire".

I belived that a FOREACH macro iterate over all elements of array...
How can I restrict to the last element?

Thanks... bye...
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Another Array problem (from an old code)...

Post by Sapient »

removing elements from an array is currently not very easy (unless it is simply an array of locations or units on the game map with no additional information).

When you use [store_locations] to overwrite the variable, it is losing all the turn information. Thus, REMOVE_FIRELIST does not work.

I suggest instead to set an array.active="false" when you want to disable an item.

And to check for array.active not_equals="false" before taking action on an item.

I used this strategy here to answer Blueblaze's question: http://www.wesnoth.org/forum/viewtopic. ... 01#p291701
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Dret
Posts: 79
Joined: June 13th, 2007, 11:06 pm
Contact:

Re: Another Array problem (from an old code)...

Post by Dret »

I tried but the problem still remain...

Here the new code:

Code: Select all

#define CONTROL_FIRE

[event]
name=new turn
first_time_only=no

{FOREACH firelist count}

		[if]
		
				{VARIABILE_OPER firelist[$count].active not_equals false}		
				{VARIABILE_OPER firelist[$count].turn numerical_equals 0}
		[then]		
	
				
#HERE A CODE TO REMOVE IMAGE FIRE
					{REMOVE_IMAGE}
				
		{VARIABLE firelist[$count].active false}
			
		[/then]
				[else]
				
							[set_variable]
							name=firelist[$count].turn
							add=-1
							[/set_variable]
				[/else]
		[/if]

{NEXT count}
[/event]

#enddef	
On a single fire... works fine... but all the others are "turned off" after first turn... :annoyed:
User avatar
governor
Posts: 267
Joined: December 8th, 2006, 12:32 am

Re: Another Array problem (from an old code)...

Post by governor »

I did not immediately realize that you were intentionally appending a variable to the last firelist item to use as a counter.

How does REMOVE_IMAGE know which fire to remove?
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Another Array problem (from an old code)...

Post by Sapient »

the code you posted looks fine, but I suspect you are still using the FIRE_LIST macro?
as I said, [store_locations] will cause you to overwrite the variable and thus you will lose the turn / active information.

Instead, you should append to the end of the array directly, like I did in the link to Blueblaze thread.

Code: Select all

    [store_locations]
       x=$x1
       y=$y1
       [or]
            find_in=firelist
       [/or]
			variable=firelist
  
	[/store_locations]
^^^^^^^^^^^^ this won't work

Code: Select all

{VARIABLE index $firelist.length}
{VARIABLE firelist[$index].x $x1}
{VARIABLE firelist[$index].y $y1}
{VARIABLE firelist[$index].turn 2}
^^^^^^^^^^^ this will work


In the Development 1.5 version, there is an easier way:

Code: Select all

[set_variables]
  name=firelist
  mode=append
  [value]
   x,y=$x1,$y1
   turn=2
  [/value]
[/set_variables]
And finally, one more approach. If you want to store a simple array of locations, then you can use the find_in= approach to easily add and remove elements, and you could store the turn count serperately.

Code: Select all

  {VARIABLE turn_count_var "turn_$firelist[$count].x|_$firelist[$count].y"}
  [set_variable]
   name=$turn_count_var
   add=1
  [/set_variable]
  [if]
   [variable]
    name=$turn_count_var
    numerical_equals=2
   [/variable]
   [then]
# do stuff here *******************

# now get rid of that location from the list
     {CLEAR_VARIABLE $turn_count_var}
     [store_locations]
       find_in=firelist
       [not]
        x,y=$firelist[$count].x,$firelist[$count].y
       [/not]
       variable=firelist
     [/store_locations]
   
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Dret
Posts: 79
Joined: June 13th, 2007, 11:06 pm
Contact:

Re: Another Array problem (from an old code)...

Post by Dret »

You are right... i belived that the problem with [store_location] was only during the "removing" event...

But the problem is still not solved, i explain:

The First solution is good but create other problems:

The fires are not "erased" form the array, they are only checked by another variable (false or true). That situation don't prevent units to be affected by the features of this particular location (the image fire disappear but the effect on Nightstalk ability and the damage for moving into these locations are still present).

The Second solution is great... because leave the possibility to use [store_location] to add and remove locations (with all their effects on units)... adding a separeted counter for turns...

But it dosen't work fine... if a units place more then a fire in the same turn... some disappear at the right moment but others dont't...!! :shock:

This is the code i used:

Code: Select all

#define CONTROL_FIRE

[event]
name=new turn
first_time_only=no

{FOREACH firelist count}
{VARIABLE turn_count_var "turn_firelist[$count].x|_firelist[$count].y"}
  [set_variable]
   name=$turn_count_var
   add=1
  [/set_variable]
		[if]
		
[variable]
    name=$turn_count_var
    numerical_equals=2
   [/variable]
							
		[then]		
	
				[removeitem]
					x=$firelist[$count].x
					y=$firelist[$count].y
				[/removeitem]
				
				{SP_OBJ_IMG scenery/rubble.png $firelist[$count].x $firelist[$count].y}
				
				{CLEAR_VARIABLE $turn_count_var}
				
				{REMOVE_FIRELIST}
			
		[/then]

		[/if]

{NEXT count}

[/event]

#enddef	
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Another Array problem (from an old code)...

Post by Sapient »

ha... of course, because you are removing from the array while you are iterating over it, and
that's a problem.

I think my first solution was really the simplest one. But.... maybe the second approach will still work if you add this line right after removing from the list...

Code: Select all

  {VARIABLE_OP count add "-1"}
That's really a "hack" though. :)

If it doesn't work, let me know and I'll post something a bit more elegant for you.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Dret
Posts: 79
Joined: June 13th, 2007, 11:06 pm
Contact:

Re: Another Array problem (from an old code)...

Post by Dret »

In according with your suggestion, I have insered you code after {REMOVE_FIRELIST}

But the situation in still the same. :cry:

I can report to you the strange behavior of the code step by step:

Example:

Turn 1

Side 1 place Fire N°1
Side 1 place Fire N°2

Side 2 place Fire N°3

Turn 2

Fire N°1 (still present, OK)
Fire N°2 (still present, OK)

Fire N°3 (still present, OK)

Turn 3 (in this situation, at the beginning of this turn, the "count" value is 2: so all the fires start to burn in turn N1 have to be deleted... but...)

Fire N°1 (deleted, OK)
Fire N°2 (still present, WRONG)

Fire N°3 (deleted, OK)

The situation change again if I use different solution:

For example Fire 1 start to burn during turn 1 and Fire 2 start on turn 2.....
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Another Array problem (from an old code)...

Post by Sapient »

OK, if you really want to use solution #2 (which, as I said, is the hard one)... then here's a way to do it.

1) before the loop, {CLEAR_VARIABLE to_be_removed}

2) to remove a hex from the list, add the location to the array "to_be_removed"

3) after the loop, remove every location in "to_be_removed" from "firelist" like this:

Code: Select all

[store_locations]
  variable=firelist
  find_in=firelist
  [not]
   find_in="to_be_removed"
  [/not]
[/store_locations]
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Dret
Posts: 79
Joined: June 13th, 2007, 11:06 pm
Contact:

Re: Another Array problem (from an old code)...

Post by Dret »

I have tested this last solution (thanks for all this work Sapient!)...

The situation is better but not solved:

- Work fine if the fires start ti burn in the same turn (example: 3 fires in turn 1)
- The situation remain "confused" when fires start to burn in different turns (example: fire 1 in turn1 - fire 2 in turn2)

The code I used is this:
(I don't used the "hack" {VARIABLE_OP count add "-1"} indicated before, tell me if is correct)

Code: Select all

#define CONTROL_FIRE

[event]
name=new turn
first_time_only=no

{CLEAR_VARIABLE to_be_removed}

{FOREACH firelist count}
{VARIABLE_OP turn_count_var format "turn_firelist[$count].x|_firelist[$count].y"}
  [set_variable]
   name=$turn_count_var
   add=1
  [/set_variable]
		[if]
		
[variable]
    name=$turn_count_var
    numerical_equals=2
   [/variable]
							
		[then]		
	
				[removeitem]
					x=$firelist[$count].x
					y=$firelist[$count].y
				[/removeitem]
				
				{SP_OBJ_IMG scenery/rubble.png $firelist[$count].x $firelist[$count].y}
				{CLEAR_VARIABLE $turn_count_var}

{VARIABLE index $to_be_removed.length}				
{VARIABLE to_be_removed[$index].x $firelist[$count].x}
{VARIABLE to_be_removed[$index].y $firelist[$count].y}

			
		[/then]

		[/if]

{NEXT count}

[store_locations]
  variable=firelist
  find_in=firelist
  [not]
   find_in=to_be_removed
  [/not]
[/store_locations]

[/event]

#enddef	
However, if this solution is not realizable, i'll try to implement the first one (but probably the same problem will be present in another part of code).

... or.... we'll wait for WML 1.5...!!! :wink:
Post Reply