Brainstorm input request: mapping coordinates

Thoughts, Help, Feature Requests, Bug Reports, Developing code for...

Moderators: dorpond, trevor, Azhrei

Forum rules
PLEASE don't post images of your entire desktop, attach entire campaign files when only a single file is needed, or generally act in some other anti-social behavior. :)
User avatar
Jagged
Great Wyrm
Posts: 1306
Joined: Mon Sep 15, 2008 9:27 am
Location: Bristol, UK

Re: Brainstorm input request: mapping coordinates

Post by Jagged »

Despite all the decorating I've been doing this weekend, I have posted the first version I feel is good enough for the public ;)

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Brainstorm input request: mapping coordinates

Post by wolph42 »

bloody hell, that took me quite a bit longer than expected. I finally can say that I'm done (for now). The editor was still a pain, even though the UI is great (the code behind not so much). And it turned out that there were still many bugs in my roborally version, with double shooting lasers, conveyers pushing bots through a wall etc, pushers not functioning in their active round, etc.

I think I at least now have the obvious ones. After playing with it it actually corresponded as it should. Its got full animation AND an extensive logging feature, so you can read back what happened. The one thing I haven't tested extensively (but did so in the passed) are colliding/pushing bots. Since the code changed A LOT over the last few weeks it might be that that part is not working correctly anymore.

I'm first gonna make a short tutorial tonight and then I'll release it.

And I think you're really gonna like the map editor :D

here a pre-look: https://www.dropbox.com/s/l0job9xb8wjpi ... ally.cmpgn

User avatar
Jagged
Great Wyrm
Posts: 1306
Joined: Mon Sep 15, 2008 9:27 am
Location: Bristol, UK

Re: Brainstorm input request: mapping coordinates

Post by Jagged »

I will take a look at that as soon as I can :)

While playing some games we found another "Edge Case" I hadn't previously considered: What happens when everyone dies before the end of the round?

My code wasn't handling the empty list of Bots very well, and certainly wasn't jumping forward to the start of the next round.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Brainstorm input request: mapping coordinates

Post by wolph42 »

Jagged wrote:I will take a look at that as soon as I can :)

While playing some games we found another "Edge Case" I hadn't previously considered: What happens when everyone dies before the end of the round?

My code wasn't handling the empty list of Bots very well, and certainly wasn't jumping forward to the start of the next round.
They end up on the last checkpoint they've set foot on. My code should not have a problem with that
O and I created a tutorial vid

User avatar
Jagged
Great Wyrm
Posts: 1306
Joined: Mon Sep 15, 2008 9:27 am
Location: Bristol, UK

Re: Brainstorm input request: mapping coordinates

Post by Jagged »

wolph42 wrote: They end up on the last checkpoint they've set foot on.
That wasn't the bit where I had the problem. The problem I had was that everyone died on card 2 and my code still wanted to run through cards 3,4 & 5 :(

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Brainstorm input request: mapping coordinates

Post by wolph42 »

yup as I said, no trouble there. As soon as a bot is destroyed the 'isDead' is flagged and the rest of the cards are negated.

Here's the Robo rally tutorial:
Tutorial Map Editor - Quickly create a map filled with different tokens.

(its also a tutorial for a general map editor, hence the titel)

couple of bugs left to fix before release.


User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Brainstorm input request: mapping coordinates

Post by wolph42 »

So currently working on the other tiles from the expansion. Those are easy enough to do as everything is there (save one which I decided not to do: randomizer)

I did run into some questions once more though: pushing into:

-Water: the first move 'when in water' (so not when moving into) is negated, but what if you're pushed??
--> so moving from F(loor) --> W(ater): takes one move
--> moving W-->W takes 2-move and
--> moving W-->W-->W takes 3-move
hence a 1-move while in water is negated.
Now we have bot A (on Floor) pushing bot B (in water) with a 1-move. Does bot B move or not?

Dito Oil slick. When your drive over oil nothing happens, HOWEVER if you stop on oil, you continue until you hit either an obstacle (wall or bot) or none-oil floor. But what happens when you are pushed onto the oil?

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Brainstorm input request: mapping coordinates

Post by wolph42 »

WOOOOOT

After 3 fn days of debugging and struggling with insanely complex code I've FINALLY managed to get in the water, ramp and oil tiles (and working).

Water: when in water the first move is negated (but when driving into water not, just the NEXT move is negated and all moves after that not). When pushed into water :D again the same rules but these need to be send back to the pusher.

Oil: that REALLY was a pain.
- when driving onto oil nothing happens. When stopping you start sliding until you either hit something or are not on oil anymore
so far 'easy'.
- now the pushing... when you push a bot on oil it starts sliding (and as I use recursive loops to check multiple pushing bots I thus need to check EVERY recurse whether they're sliding or not).
- when you are sliding you cannot push BUT when you start driving on oil (first move negates) and THEN push a bot (also on oil) it does start sliding etc.
a real pain to get it programmed but it WORKS.

For the fun of it here the recursive loop:
urgh

Code: Select all

[h:'<!-- ------------------------ calcMoveBot(currentBot, pDirection, pushBot, nRobots, moveLeft, debugIntern) ------------------------ -->']
[h:debug=1]
<!-- is called by itself and moveBot -->
<!-- returns the amount that the robot can move (and thus 0 == false) -->
<!-- 3 CODE LEVELS -->

<!-- -------------------------------------------------------------------------------------- -->
<!-- --------------------------------INITIALIZATION------------------------------------------- -->
<!-- -------------------------------------------------------------------------------------- -->
[varsFromStrProp(getLibProperty("currentGameBoard","lib:roboRally"))]

[h:currentBot		= arg(0)]
<!-- pDirection is passed on as argument when the robot is pushed in a certain direction (which is not necessarily the same as its facing) -->
[h:pDirection	= arg(1)]
<!-- When a bot is moved by a conveyer it does NOT push another bot. In short then it does not move. -->
[h:pushBot		= arg(2)]
[h:nRobots		= arg(3)]
<!-- When a bot moves onto oil then it DRIVES #moveLeft  and then SLIDES the rest of the oil path. This in case of collision. Driving bots CAN push a bot, Sliding bots not-->
[h:moveLeft		= arg(4)]

[h,if(argCount()>5):debugIntern = arg(5) ; debugIntern = 0]

<!-- get current virtual position and status-->
[h:xBot			= getProperty("xCurrent", currentBot)]
[h:yBot			= getProperty("yCurrent", currentBot)]

[h:onHamper		= getProperty("onHamper", currentBot)]
[h:wasOnHamper	= getProperty("wasOnHamper", currentBot)]
<!--	the tricky part about ramps and water
		if bot was !onwater and isonwater than 1 move is negated
		if bot was onwater and isonwater (or not on water) than nothing happens
		however if it was on a steep ramp (which takes 2 moves) then its once again hampered this move!
		
		The real tricky part is that with water movement is AGAIN hampered on the next card, so wasOnwater needs to be reset in moveBot!!
		This is NOT the case for ramps or steep ramps
-->
[h:hampered		= if(onHamper && !wasOnHamper || onHamper == 2, 1, 0)]
[h:nMove		= !hampered]
[h,if(onHamper == 2):onHamper = 1]
[h:setProperty("wasOnHamper", onHamper, currentBot)]

[h:isDead		= getProperty("isDead", currentBot)]
[h:xMin			= getLibProperty("currentXMin", "lib:roboRally")]
[h:yMin			= getLibProperty("currentYMin", "lib:roboRally")]
[h:xMax			= getLibProperty("currentXMax", "lib:roboRally")]
[h:yMax			= getLibProperty("currentYMax", "lib:roboRally")]
[h:currentRound	= getLibProperty("currentRound", "lib:roboRally")]

<!-- 
a bot pushed on an oil slick keeps travelling forward, which needs to be done for pushed bots as well, hence it must be done here. 
as you want to enter the while loop you initially set it to 1
The start-driving-on-oil hamper is handled in moveBot
 -->
[onOil			= 1]
[while(onOil && nMove), CODE:{
	<!-- 
		the bot starts sliding as soon as it STOPS driving. As I cannot check here how far it drives I have to deduct the total (extra) moved value first from nMove in moveBot.
		Note that roll.count starts at 0 so only if it returns a higher value the deduction needs to be done.
	-->
	[extraMove	= roll.count]
	<!-- -------------------------------------------------------------------------------------- -->
	<!-- --------------------------------CALC NEW POSITION------------------------------------- -->
	<!-- -------------------------------------------------------------------------------------- -->

	<!--  move in what direction results in which coordinate change
	0 x+1
	1 y+1
	2 x-1
	3 y-1
	-->
	<!-- bot cannot move when standing on a wall token facing in the pdirection -->
	[foreach(tile, eval("c"+xBot+"_"+yBot)), if(json.get(tile, "type") == "Wall"): nMove	= if(json.get(tile, "bDirection") == pDirection, 0, nMove)]
	[if(debug):bot_debugInfo("c"+xBot+"_"+yBot+", xBot, yBot, currentBot,pDirection, nMove, onHamper, wasOnHamper, extraMove, moveLeft, currentRound", 1, 0, 0, getMacroName(), getMacroLocation())]

	[if(nMove), CODE:{
		[switch(pDirection):
			case 0: xBot	= xBot + 1;
			case 1: yBot	= yBot + 1;
			case 2: xBot	= xBot - 1;
			case 3: yBot	= yBot - 1;
			default:assert(0,"pDirection: "+pDirection+" unknown in macro calcMoveBot",0);
		]
	''
	};{}]

	<!-- -------------------------------------------------------------------------------------- -->
	<!-- --------------------------------BOUNDARY CHECK------------------------------------------- -->
	<!-- -------------------------------------------------------------------------------------- -->


	<!-- boundary check to prevent errors later on when trying to request undefined variables -->
	<!-- check not to fall of board -->
	[xmBot	= xBot]
	[ymBot	= yBot]
	[if(xBot < xMin || xBot > xMax || yBot < yMin || yBot > yMax), CODE:{
		[xBot	= max(xMin,min(xMax,xBot))]
		[yBot	= max(yMin,min(yMax,yBot))]
		[isDead = 1]
		[broadcast(strformat("<i>...%{currentBot} drives from the board."))]
	''
	};{}]
	[if(debugIntern): pause("xmBot","ymBot","xBot","yBot","nMove","isDead","pDirection","currentBot")]

	<!-- -------------------------------------------------------------------------------------- -->
	<!-- --------------------------------WALL CHECK ------------------------------------------- -->
	<!-- -------------------------------------------------------------------------------------- -->

	<!-- bot cannot move when the activation direction of the wall equals pDirection -->
	<!-- the activation direction is the direction a bot moves when it moves onto the tile. If its true then the tile is activated, which is this case means blocked -->
	[wall	= 0]
	[foreach(tile, eval("c"+xBot+"_"+yBot)), CODE:{
		[type	= json.get(tile, "type")]
		[if(startsWith(type, "Wall")), CODE:{
			[nMove	= if(json.get(tile, "activationDirection") == pDirection, 0, nMove)]
			[if(indexOf(type, "Wall Gate")+1):		teleport(json.get(tile, "name"))]
			[if(indexOf(type, "Wall Spiked")+1):	damageBot(1, "Spike", currentBot)]
			[if(indexOf(type, "Wall Ledge")+1):		damageBot(2, "'Falling Of ledge'", currentBot)]
			[wall	= !nMove]
		''
		}]
	''
	}]
	[if(wall): broadcast(strformat("<i>...%{currentBot} drives into a wall"))]

	<!-- -------------------------------------------------------------------------------------- -->
	<!-- --------------------------------COLLISION CHECK--------------------------------------- -->
	<!-- -------------------------------------------------------------------------------------- -->

	<!-- in case of running into another robot, check if that one can move! -->
	<!-- note that during the board fase tokens can be standing on an active tile. In that case they do NOT collide!!! Instead the bot is blocked!! -->
	[sliding = if(getProperty("onOil", currentBot) && extraMove > moveLeft, 1,0)]
	[count(nRobots), if("Robot "+(roll.count+1) != currentBot), CODE:{
		[collisionBot = "Robot "+(roll.count+1)]
		[if(getProperty("xCurrent", collisionBot) == xBot && getProperty("yCurrent", collisionBot) == yBot && !getProperty("onActiveTile", collisionBot)), CODE:{
			<!-- calcMoveBot returns 0 (cannot move) or !0 (can move) -->
			<!-- when your sliding you cannot push a bot -->
			[if(pushBot && !sliding), CODE:{
				[if(!calcMoveBot(collisionBot, pDirection, pushBot, nRobots, moveLeft)): nMove = 0]
			''
			};{
				<!-- apparently bot CANNOT push in this fase and thus nMove returns 0 -->
				[nMove = 0]
			''
			}]
		''
		}]
	''
	}]

	<!-- -------------------------------------------------------------------------------------- -->
	<!-- ------------------------RAMP, WATER, OIL and DAMAGE CHECK----------------------------- -->
	<!-- -------------------------------------------------------------------------------------- -->
	[onWater	= 0]
	[onHamper	= 0]
	[onOil		= 0]
	[if(nMove && !isDead), CODE:{
		<!-- check where the bot drove onto -->
		[foreach(tile, eval("c"+xBot+"_"+yBot)), CODE:{
			[type	= json.get(tile, "type")]
			
			<!-- check if token drove into a pit -->
			[if(type == "Pit"):		isDead	= 1]

			<!-- check if token drove (or is pushed) onto oil -->
			[if(type == "Oil"):		onOil	= 1]
			<!-- check if bot is hampered by the environment -->
			[if(type == "Water" || type == "Ramp" && json.get(tile, "bDirection") == pDirection): onHamper = 1]
			[if(type == "Steep Ramp" && json.get(tile, "bDirection") == pDirection): onHamper = 2]

			<!-- check if token is on water and existinguish any flames -->
			[if(type == "Puddle" || type == "Water"), CODE:{
				[onWater	= 1] 
				[if(getProperty("onFire", currentBot)==1): broadcast(strformat("<i>...%{currentBot} drives through a puddle which extinguishes the flames."))]
				[setProperty("onFire", 0, currentBot)]
			''
			}]

			<!-- check if token is driving on a damaging element -->
			[if(type == "Damage"), CODE:{
				[name	= json.get(tile, "name")]
				<!-- damage when driving through napalm or flamer and onFire if napalm -->
				[if(name == "Flamer"):	damageBot(1, "'Running into Flame'", currentBot)]
				[if(name == "Napalm"), CODE:{
					[damageBot(1, "'Running into Napalm'", currentBot)]
					[setProperty("onFire", 1, currentBot)]
				''
				}]
			''
			}]
		''
		}]
		[setProperty("onOil", onOil, currentBot)]
		[setProperty("onHamper", onHamper, currentBot)]
		
		<!-- output -->
		[if(isDead):	broadcast(strformat("<i>...%{currentBot} falls in a pit."))]
		[if(onHamper):	broadcast(strformat("<i>...%{currentBot} drives onto a move hampering element (water or ramp)."))]
		[if(onOil):		broadcast(strformat("<i>...%{currentBot} drives onto an oil slick."))]
		[if(onWater), CODE:{
			[if(getProperty("onFire", currentBot)): 
				[broadcast(strformat("<i>...%{currentBot} drives in the water, which extinguishes the flames."))]
			;
				[broadcast(strformat("<i>...%{currentBot} drives in the water."))]
			]
			[setProperty("onFire", 0, currentBot)]
		''
		}]
	''
	};{}]

	<!-- -------------------------------------------------------------------------------------- -->
	<!-- --------------------------------MOVE BOT   ------------------------------------------- -->
	<!-- -------------------------------------------------------------------------------------- -->

	[if(nMove), CODE:{
		<!-- move token, even if its destroyed, cause it may just have been moved off board.-->
		[currentAnimation	= strformat("currentBot=%{currentBot} ; turn=%{currentRound} ; x=%{xmBot} ; y=%{ymBot} ; degrees=0 ; teleport=0")]
		[moveArray			= json.append(getLibProperty("moveArray", "lib:roboRally"), currentAnimation)]
		[setLibProperty("moveArray", moveArray,"lib:roboRally")]
		<!-- movement is now only done in memory. After this function is finished, ALL robots are checked and if start!=current then their movement is animated. -->
		['moveToken(xmBot,ymBot,0,currentBot)']
		[setProperty("xCurrent", xmBot,currentBot)]
		[setProperty("yCurrent", ymBot,currentBot)]

		[if(debug):bot_debugInfo("moveArray, currentAnimation, xmBot, ymBot, currentBot,pDirection, nMove, onHamper, wasOnHamper, onOil, extraMove, moveLeft, sliding, currentRound", 1, 0, 0, getMacroName(), getMacroLocation())]
		[if(!isDead):broadcast(strformat("<i>...%{currentBot} moves one %s.", if(abs(getProperty("bDirection", currentBot)-pDirection)==0, "Forward",if(abs(getProperty("bDirection", currentBot)-pDirection)==2, "Backwards","Sideways"))  ))]
	''
	};{	
		[if(!wall && !hampered):broadcast(strformat("<i>...%{currentBot} collides with another bot."))]
	''
	}]

	[if(isDead):destroyBot(currentBot)]
[propOnOil = getProperty("onOil", currentBot)]
[pause("onOil","propOnOil","extraMove", "sliding", "moveLeft","nMove")]
''
}]


<!-- -------------------------------------------------------------------------------------- -->
<!-- --------------------------------RETURN VALUE------------------------------------------ -->
<!-- -------------------------------------------------------------------------------------- -->

<!-- 
nMove is default 1 
will ONLY be set to 0 under the following conditions:
- running into a wall (this tile or next tile)
- running into an unmoveable robot (either that bot is against a wall or your pushing from a conveyer during the table fase)

isDead is default 0 and will ONLY be set to 1 under the following conditions:
- driving off board
- driving over a pit

the return value (canMove = 0, 1 or higher (in case of oil slick) is used for
- pushing in calcMoveBot only 0 and !0 are used 
- extra move on oil needs to be deducted from the total nMove
 -->
['pause("wall", "nMove")']
[macro.return = if(!wall, nMove + extraMove, 0)]

Post Reply

Return to “MapTool”