Another problem with another new mp scenario

Discussion of all aspects of multiplayer development: unit balancing, map development, server development, and so forth.

Moderator: Forum Moderators

Post Reply
Hieronymus
Posts: 41
Joined: February 24th, 2005, 2:10 pm

Another problem with another new mp scenario

Post by Hieronymus »

Ok, since my first mp scenario is still not working and nobody seems to be able to tell me what's wrong (see http://www.wesnoth.org/forum/viewtopic.php?t=5037), I have decided to try making another scenario, a bit more simple. It is called "Domination" and the idea behind it is: there are 9 so called "domination villages" on the map. The player which controls 6 of them, wins.

Here is the code:

Code: Select all

[multiplayer] 
   	id=domination4p
   	name="Domination4p 0.1" 
   	map_data="{maps/multiplayer/Domination4p}" 
   	description="Domination4p 0.1"
	turns=20

   	{DAWN} 
   	{MORNING} 
   	{AFTERNOON} 
   	{DUSK} 
   	{FIRST_WATCH} 
   	{SECOND_WATCH} 

#####MACROS#####

#define ADD_SIDE SIDE
	[side] 
   		side={SIDE} 
   		team_name={SIDE} 
   		canrecruit=1 
   		controller=human 
   	[/side]
#enddef

#define SET_VILLAGE_CAPTURE_LISTENER X Y VILLAGENR
	# sets a capture event for this village, which stores the side which has captured it
	[message]
		message="Debug: SET_VILLAGE_CAPTURE_LISTENER village {VILLAGENR}"
	[/message]
	[event]
		name=capture
		first_time_only=no
		[filter]
			x={X}
			y={Y}
		[/filter]
		[message]
   			message="Debug: Village nr. {VILLAGENR} (pos {X},{Y}), captured by $primary_unit.side"
   		[/message]
		
		[set_variable]
			name=playerScores.score[$primary_unit.side]
			add=1
		[/set_variable]
		
		[if]
			[variable]
				name=playerScores.score[$primary_unit.side]
				equals=$nrVillagesToWin
			[/variable]
			[then]
				[message]
					message="Player $primary_unit.side has won!" #i will change that later
				[/message]
			[/then]
		[/if]

		[set_variable]
			name=playerScores.score[$villages.village[{VILLAGENR}].owner]
			add=-1
		[/set_variable]		
	
		[set_variable]
   			name=villages.village[{VILLAGENR}].owner
   			value=$primary_unit.side
   		[/set_variable]
		{DEBUGMSG {VILLAGENR}}
		{DEBUGMSGSCORES}
	[/event]
#enddef

#define DEBUGMSGSCORES
	[message]
		message="Scores = 0: $playerScores.score[0], 1: $playerScores.score[1], 2: $playerScores.score[2], 3: $playerScores.score[3]"
	[/message]
#enddef

#define DEBUGMSGVILLAGE VILLAGE
	[message]
		message="Village {VILLAGE} = x: $villages.village[{VILLAGE}].xPos, y: $villages.village[{VILLAGE}].yPos, owner: $villages.village[{VILLAGE}].owner"
	[/message]
#enddef

#define DEBUGMSGSTART
	[event]
		name=start
		{DEBUGMSGVILLAGE 0}
		{DEBUGMSGVILLAGE 1}
		{DEBUGMSGSCORES}		
	[/event]
#enddef

#define INIT
	[event]
		name=prestart
		[variables]
			[villages]
				[village]
					xPos=13
					yPos=4
					owner=0
				[/village]
				[village]
					xPos=8
					yPos=8
					owner=0
				[/village]
			[/villages]
			# left out the other domination villages for readability
			
			nrVillagesToWin=6
			
			[playerScores]
				score=-1 # there is no side 0!
				score=0
				score=0
				score=0
				score=0
			[/playerScores]
		[/variables]
	      {FOREACH villages villageNr}
			{SET_VILLAGE_CAPTURE_LISTENER $villages.village[$villageNr].xPos $villages.village[$villageNr].yPos $villageNr}
		{NEXT villageNr}									
	[/event]
#enddef

#####END MACROS#####

	{INIT}

	{ADD_SIDE 1}
	{ADD_SIDE 2}
	{ADD_SIDE 3}
	{ADD_SIDE 4}

	{DEBUGMSGSTART}

[/multiplayer]
The problem now is that it doesn't ta ... riablesWML.

Please help me and tell me what I am doing wrong... Thanks.
User avatar
Tomsik
Posts: 1401
Joined: February 7th, 2005, 7:04 am
Location: Poland

Post by Tomsik »

i dont see where you initialized "VillageNr", its standard macro?
Rhuvaen
Inactive Developer
Posts: 1272
Joined: August 27th, 2004, 8:05 am
Location: Berlin, Germany

Re: Another problem with another new mp scenario

Post by Rhuvaen »

Scary, I'm trying to do the exact same thing, except with 10 villages and you need to capture 8 :shock: ... (note that the examples posted here are from my tunnels code, I've done the village thing without arrays first)

What I find is that assigning from or to array variables requires an exact syntax, and not all of the possibilities listed in the wiki seem to work at all! I find that no matter what I try, the arrays never get read correctly in the messages.

In my code, assigning to arrays you always need to use the to_variable key in set_variables, not the value key, when you're assigning to another variable. Such as:

Code: Select all

        [set_variable]
          name=tunneler[$unit].x
          to_variable=tunnels[$tunnel_number].to_x
        [/set_variable]
Don't use the $ sign in front of the array variable name, and don't forget to use it on the array index. Similarly I think arrays don't get interpreted correctly in value keys, or when used as array indices - and as we've both seen in messages. In such cases, I'd use an intermediate variable. Here's an example from your code:

Code: Select all

      [set_variable]
         name=playerScores.score[$villages.village[{VILLAGENR}].owner]
         add=-1
      [/set_variable]
The above isn't going to work according to my experience. Just do this instead:

Code: Select all

      [set_variable]
         name=index
         to_variable=villages.village[{VILLAGENR}].owner
      [/set_variable]
      [set_variable]
         name=temp_score
         to_variable=playerScores.score[$index]
      [/set_variable]
      [set_variable]
         name=temp_score
         add=-1
      [/set_variable]
      [set_variable]
         name=playerScores.score[$index]
         to_variable=temp_score
      [/set_variable]
That should work instead (although I'm not sure if the macro argument will work as an array index in the first tag here - if not, use an intermediate variable again!). Of course, such array operations could be fashioned into a set of macros!

When I'm trying to assign a specific value to an array element, I can use macro arguments, such as:

Code: Select all

[set_variable]
  name=tunnels[$tunnel_counter].y
  value={Y1}
[/set_variable]
Seems to work for me.

Try to do simple things first, maybe we can come up with a couple of array utility macros together :wink: !
Rhuvaen
Inactive Developer
Posts: 1272
Joined: August 27th, 2004, 8:05 am
Location: Berlin, Germany

Post by Rhuvaen »

tomsik wrote:i dont see where you initialized "VillageNr", its standard macro?
No, it's the index of the FOREACH macro. It will get initialised there. FOREACH is really useful when working with arrays, it's a good idea to familiarise yourself with it!
Hieronymus
Posts: 41
Joined: February 24th, 2005, 2:10 pm

Post by Hieronymus »

Well, I've had it with these arrays in WML, and I have now made a version without arrays, using a macro workaround for arrays. It works better, but there is still one bug in it. Code:

Code: Select all

[multiplayer] 
   	id=domination4p
   	name="Domination4p 0.1" 
   	map_data="{maps/multiplayer/Domination4p}" 
   	description="Domination4p 0.1"
	turns=20

   	{DAWN} 
   	{MORNING} 
   	{AFTERNOON} 
   	{DUSK} 
   	{FIRST_WATCH} 
   	{SECOND_WATCH} 

#####MACROS#####

#define ADD_SIDE SIDE
	[event]
		name=start
		[side] 
   			side={SIDE} 
   			team_name={SIDE} 
   			canrecruit=1 
   			controller=human 
   		[/side]
		[set_variable]
			name=player{SIDE}Score
			value=0
		[/set_variable]
		[set_variable]
			name=nrSides
			add=1
		[/set_variable]
	[/event]
#enddef

#define TURN_COUNTER
	[event]
		name=side turn
		first_time_only=no
		# set turnOfSide variable to next side
		[if]   
			[variable]
            		name=turnOfSide
            		numerical_equals=$nrSides
			[/variable]
			[then]
 				[set_variable]
      				name=turnOfSide
      				value=1
 				[/set_variable]
			[/then]
			[else]
 				[set_variable]
      				name=turnOfSide
      				add=1
 				[/set_variable]
			[/else]
		[/if]
	[/event]
#enddef
	

#define SET_VILLAGE_CAPTURE_LISTENER X Y VILLAGENR
	[event]
		name=capture
		first_time_only=no
		[filter]
			x={X}
			y={Y}
		[/filter]
		
		[set_variable]
			name=player$turnOfSide|Score
			add=1
		[/set_variable]

		{SET_VILLAGE_MESSAGE {X} {Y} $turnOfSide}	

		[if]
			[variable]
				name=player$turnOfSide|Score
				numerical_equals=$nrVillagesToWin
			[/variable]
			[then]
  				{SET_MESSAGE ("Player $turnOfSide has won!")}
				[endlevel]
  					result=victory
  				[/endlevel]
			[/then]	
		[/if]

		[set_variable]
			name=player$village{VILLAGENR}Owner|Score
			add=-1
		[/set_variable]		
	
		[set_variable]
   			name=village{VILLAGENR}Owner
   			value=$turnOfSide
   		[/set_variable]
		# {DEBUGMSG {VILLAGENR}}
		{DEBUGMSGSCORES}
	[/event]
#enddef

#define SET_MESSAGE MSG
	[message]
		speaker=narrator
		message={MSG}
	[/message]
#enddef

#define CHECK_VICTORY SIDE

#enddef
#define SET_VILLAGE_MESSAGE X Y SIDE
	{SET_MESSAGE ("Village at {X},{Y} captured by player {SIDE}, who now has $player{SIDE}Score")}
#enddef

#define ADD_DOMINATION_VILLAGE X Y NR
	[event]
		name=prestart
		[set_variable]
			name=village{NR}Owner
			value=0
		[/set_variable]
		{SET_VILLAGE_CAPTURE_LISTENER {X} {Y} {NR}}
	[/event]
#enddef

#define DEBUGMSGSCORES
	{SET_MESSAGE ("Scores = 1: $player1Score, 2: $player2Score, 3: $player3Score, 4: $player4Score")}
#enddef

#define DEBUGMSGVILLAGE VILLAGE
	{SET_MESSAGE ("Village {VILLAGE} owner: $village{VILLAGE}Owner")}
#enddef

#define DEBUGMSGSTART
	[event]
		name=start
		{DEBUGMSGVILLAGE 1}
		{DEBUGMSGVILLAGE 2}
		{DEBUGMSGSCORES}
		{SET_MESSAGE ("nrVillages to win: $nrVillagesToWin")}		
	[/event]
#enddef

#define INIT
	[event]
		name=prestart
		[set_variable]
			name=nrSides
			value=0
		[/set_variable]
		[set_variable]
			name=turnOfSide
			value=1
		[/set_variable]
		[set_variable]
			name=nrVillagesToWin
			value=2
		[/set_variable]								
	[/event]
#enddef

#####END MACROS#####

	{INIT}

	objectives= _ "Victory:
@ Own 6 of the special villages"

	{ADD_SIDE 1}
	{ADD_SIDE 2}
	{ADD_SIDE 3}
	{ADD_SIDE 4}

	{ADD_DOMINATION_VILLAGE 13 4 1}
	{ADD_DOMINATION_VILLAGE 8 8 2}
	{ADD_DOMINATION_VILLAGE 18 8 3}
	{ADD_DOMINATION_VILLAGE 3 14 4}
	{ADD_DOMINATION_VILLAGE 13 14 5}
	{ADD_DOMINATION_VILLAGE 23 14 6}
	{ADD_DOMINATION_VILLAGE 8 19 7}
	{ADD_DOMINATION_VILLAGE 18 19 8}
	{ADD_DOMINATION_VILLAGE 13 24 9}
	
	{TURN_COUNTER}

	# {DEBUGMSGSTART}

[/multiplayer]
In the former version in the capture event, $primary_unit.side had no value... So I was forced to make my own variable which keeps track of who's turn it is. My own seems to be working fine (but why does $primary_unit.side not work?).

The error left is in SET_VILLAGE_CAPTURE_LISTENER. In this macro the lines

Code: Select all

[set_variable]
	name=player$turnOfSide|Score
	add=1
[/set_variable]
are working fine, the variable is increased. But in the next lines, in which I want to check the same variable and see if it equals another, it cannot find it:

Code: Select all

[if]
	[variable]
		name=player$turnOfSide|Score
		numerical_equals=$nrVillagesToWin
	[/variable]
Why does it recognize that variable player$turnOfSide|Score in [set_variable], but not in [variable]?
Rhuvaen
Inactive Developer
Posts: 1272
Joined: August 27th, 2004, 8:05 am
Location: Berlin, Germany

Post by Rhuvaen »

Hieronymus wrote:In the former version in the capture event, $primary_unit.side had no value... So I was forced to make my own variable which keeps track of who's turn it is. My own seems to be working fine (but why does $primary_unit.side not work?).
It's a location filter, not a unit filter! I did it by storing the unit at that location, it might be simpler than working it out by the turn:

Code: Select all

#define SET_VILLAGE_CAPTURE_LISTENER X Y VILLAGENR
   [event]
      name=capture
      first_time_only=no
      [filter]
         x={X}
         y={Y}
      [/filter]
      [store_unit]
         variable=captor
         kill=no
         [filter]
           x={X}
           y={Y}
         [/filter]
      [/store_unit]
      [set_variable]
         name=player$captor.side|Score
         add=1
      [/set_variable]
      ...
Hieronymus wrote:The error left is in SET_VILLAGE_CAPTURE_LISTENER. In this macro the lines

Code: Select all

[set_variable]
	name=player$turnOfSide|Score
	add=1
[/set_variable]
are working fine, the variable is increased. But in the next lines, in which I want to check the same variable and see if it equals another, it cannot find it:

Code: Select all

[if]
	[variable]
		name=player$turnOfSide|Score
		numerical_equals=$nrVillagesToWin
	[/variable]
Why does it recognize that variable player$turnOfSide|Score in [set_variable], but not in [variable]?
I don't know the answer, all I can say is that I had LOTS of problems with this kind of array-workaround when these variables cropped up in different macros or 'scopes' (tags). Or maybe the [variable] tag doesn't support '$' interpretation? Try to use an intermediate variable, and see what happens:

Code: Select all

[set_variable]
     name=player_score
     to_variable=player$turnOfSide|Score
[/set_variable]
[if]
	[variable]
		name=player_score
		numerical_equals=$nrVillagesToWin
	[/variable]
....
As with arrays, I've found to_variable to interpret the array variable fairly well, unlike the value key, which doesn't do a lot. Maybe it's similar with this workaround.
Post Reply