Arrow Error

BlitzMax Forums/BlitzMax Beginners Area/Arrow Error

dw817(Posted 2016) [#1]
This is not so much an error as what I believe to be an incorrect way of handling an infinite number of objects on any tiled surface.

The problem I have always had is - once I select an object and the script, if it moves from where it is, I must flag it so it is not chosen again when doing a scan.

I'm posting this in the hopes that someone can show me a smaller code example which does not require me to reset the objects each time.




Cocopino(Posted 2016) [#2]
Without reading any of your code and only basing this on this sentence:
The problem I have always had is - once I select an object and the script, if it moves from where it is, I must flag it so it is not chosen again when doing a scan.


This might be a case where you'll need to use a custom Type, giving it a field "flagged". E.g.

SuperStrict

Local ScreenWidth:Int = 1024
Local ScreenHeight:Int = 768

Graphics ScreenWidth, ScreenHeight

Type TTile
	
	Field x:Int
	Field y:Int
	Field color:Int[3]
	Field flagged:Int = 0
	Field size:Int

	Function Create:TTile(x:Int, y:Int, size:Int)
		Local tile:TTile = New TTile
		tile.x = x
		tile.y = y
		tile.size = size
		tile.color = [Rand(0, 255), Rand(0, 255), Rand(0, 255)]

		Return tile
	End Function

	Method Draw()

		If flagged Return 'do not draw a flagged tile!

		SetColor(color[0], color[1], color[2])
		DrawOval(x * size, y * size, size, size)

	End Method

End Type

Local xTiles:Int = ScreenWidth / 22 ' nr of horizontal tiles
Local yTiles:Int = ScreenHeight / 22 ' nr of vertical tiles

Local tiles:TTile[xTiles * yTiles]
Local counter:Int = 0
For Local x:Int = 0 To xTiles - 1
	For Local y:Int = 0 To yTiles - 1
		tiles[counter] = TTile.Create(x, y, 20)
		counter:+1
	Next
Next

counter = 0
While Not KeyDown(KEY_ESCAPE)

	Cls

	counter:+1
	For Local t:TTile = EachIn tiles
		t.Draw()
	Next

	If counter Mod 30 = 0
		tiles[Rand(0, tiles.Length - 1)].flagged = 1
	EndIf
	
	Flip()
	
Wend


I can not look at it too long though - it's pretty trippy :)


dw817(Posted 2016) [#3]
I have updated the code, I call it "Traffic" now, Cocopino.

Yet your code is still using an additional For/Next loop. What I want to do is write this, preferably without TYPE variables, and definitely using only =1= For/Next set.

For I vertical, For J horizontal, and no other loops outside repeating the process.

So no For/Next loop where I have to reset flags. There should be a way to do this all in smaller code.



Despite this, it is STILL possible to have a traffic pileup, can you see how ?


Cocopino(Posted 2016) [#4]
Yet your code is still using an additional For/Next loop


It's only using a single, not nested, draw/update loop. The other loop is just there for initialization. Yours is using 2 nested loops in main, so I'm not sure what you mean there?

I just wanted to show an example of how you could use a custom Type to store information about the object: x value, y value, direction, flagged, whatever. The more information you need to store per object, the harder it becomes to circumvent using a Type.

Running your code, I think you could try having the "cars" wait for each other if moving in the same direction, always leaving at least one open space.


dw817(Posted 2016) [#5]
Hi Cocopino.

Here is a solution to this problem, albeit not an entirely elegant one.

I can look for the inverse of the set. That is, once I find an arrow and it needs to move, mark it with the negative value of what it is. If it's already negative, make the marker positive, if it's already positive, make it negative.

Outside the loop flip the switch to make it look for positive and write for negative and vice-versa.

But I still think there should be an easier way to do this, using only =2= For/Next loops in toto.

Having the cars with one space between them will still not prevent collisions coming from other directions.

If you hadn't solved it, and it was a tricky question, :) it is possible to create a traffic jam by 4 of them going in each of 4-directions colliding into each other at once.

A simple solution would be to see if one or more arrows has not moved for 3- or more turns, and if so, vanish from the map.


Casaber(Posted 2016) [#6]
d1817 I looked at the arrows and had an epiphany, two cars going opposite direction of course has no way to avoid a crash despite how much they wait. But apposite dimensions could coordinate themselves in speed when they see eachother.

The epipany was; if both slows down equally much there would be still a crash (if they where in for a crash with their current speeds).
Avoidance all boils down to just ONE thing - to change their relative speeds. They have to balance those.

It might be good or not continue full speed and then one of them goes full stop and wait just the tile before. But It's hard to predict which one should wait and which one should continue.
I Get this problem all the time even when walking downtown haha.
The best option would be to see predict what they see, and when they see approaching objects they use their speeds as a communication with eachother.
You slowdown (maybe speedup abit even), to coordinate a non-crash.

I like that example. It's a very interesting problem.


Casaber(Posted 2016) [#7]
d1817 I looked at the arrows and had an epiphany, two cars going opposite direction of course has no way to avoid a crash despite how much they wait. But apposite dimensions could coordinate themselves in speed when they see eachother.

The epipany was; if both slows down equally much there would be still a crash (if they where in for a crash with their current speeds).
Avoidance all boils down to just ONE thing - to change their relative speeds. They have to balance those.

It might be good or not to continue full speed and then one of them goes full stop and wait just the tile before. But It's hard to predict which one should wait and which one should continue.
I Get this problem all the time even when walking downtown haha.
The best option would be to predict what they see and when they see approaching objects they should use their speeds as a communication with eachother.
You slowdown (maybe speedup abit even), to coordinate a non-crash.

I like that example. It's a very interesting problem.

EDIT

I guess the hard bit is that it can be more than one collision acoming so it would not be a perfect solution to have that,
it could create a deadlock if too many (or few with in a weird situation).
Also.. as changing their own speed also change all their new potential crashes,
each one should take in their near environment and predict to try minimise the number of upcoming crashes using their speed.

I think consistency is key, you should never jump around with different speeds, that would make everyone else
uneasy as you get very hard to predict. So the responsibility each one would have is to be pretty predictiable and smooth
in every change of their speed.

Doing a full stop one or a few tiles before potential crashes would be the extreme case of it. So it all makes sense.

I´m thinking about how to read the speeds of others programmatically. Perhaps something like redlight flags before a slowdown. That others can see.
I guess it's about showing "Hey I AM ABOUT TO CHANGE me speed here the next second, please adjust yours accordingly".

Those where just a few ideas I had. I havn't tried any of them in code yet I think it should be possible with very few
lines as this solution feels very natural and true to me I would give that a shot.

EDIT2
I guess the problem if you only had two speeds (perfect still and, and.. moving in some direction) Then you have another side of the problem. "Binary traffic".
If you did this then you convert speed into time.(like a switch on / off) Move or no move. And you use redlight flags to tell them if they are moving alot or not as much. So that would bridge into that.

Some kind of communication need to happen within the close area. Using others and your own position and speed and maybe flags that everyone closeby can see.


dw817(Posted 2016) [#8]
Casaber, that's a real brainweave you have there. :)

The point of games like this is that all objects run at the same speed. They work on a tight grid and one update is equivalent to moving one grid square. That's about as old-school as you can get and many MANY games that could handle an infinite number of objects in one screen used this method.

I already set it so head-on collisions are impossible by releasing cars from opposite sides in modulos based on their direction. Same for perpendicular parallels.

No, the easy solution would be the double inverse I was talking about earlier. Here, let me see if I can code that:



Updated 03-09-16 10:26pm

Success ! There is only the main 2-level FOR/NEXT loop being done now. By using the variable NEG and negating it only after the entire area has been updated, I can easily swap out the READ & WRITE state of the map.

BTW, hold down space to speed it up and try to create a 4-level traffic jam.

This will only occur when a North traveling car hits a West traveling car which also hits a South traveling car and it in turn hits an East traveling car, locking all 4-cars down.

This is the only way to create a traffic jam, so it's pretty rare when it happens.

Also changed it so everyone gets equal traffic time. It's no longer random from which direction a car is added.


Casaber(Posted 2016) [#9]
Whow I havn't seen a single deadlock or crash yet in your example even if it has zero communication. That last code had great flow.
Nice solution !!

What kind of game are you doing anyways?


Casaber(Posted 2016) [#10]
Got pile up now, but it's really rare. I honestly thought it was impossible for a long time.


Cocopino(Posted 2016) [#11]
I like this problem :)
Here's my take on it. Sorry dw817 but I have too much trouble not using Types.
I implemented a failedToMove counter and a Cheat() method loosely based on Casabers speed up suggestion:




dw817(Posted 2016) [#12]
Ah - me not wanting types is just a preference. I just don't think it's any faster or smaller than regular coding.

Your program crashes in DEBUG mode, Casaber. Always check your variables.

Unhandled Exception:Attempt to index array element beyond array length. Line 119.

If Map[x, i] = 0 MoveTo(x, i) ;foundNewSpot = 1;Exit;


I can tell you right now what the problem is. You need to create a function like I'm using:
' >> RETRIEVE SCREEN TILE EVEN IF OFF EDGES
Function getscrn(x,y)
Local r=-1
  If x>=0 And y>=0 And x<=30 And y<=22 Then r=scrn[x,y]
  Return r
EndFunction
Also you don't need a trailing semi-color (;) at the end of any line.

Trying out your code otherwise looks pretty good. I see you created a function called CHEAT() to handle stuck elements. I could do that in this, but I'd be curious to know if there is a simple and logical bit of code to avoid a traffic jam altogether, however.


Cocopino(Posted 2016) [#13]
Ah - me not wanting types is just a preference. I just don't think it's any faster or smaller than regular coding.


No, they are indeed not. They are used to create more readable, extensible and reusable code.

Your program crashes in DEBUG mode, Casaber.


Yeah, sorry about that. Made an edit to my post without checking it first. A bit of a rushed job altogether, more like a proof of concept.
I am not Casaber though ;)

I'd be curious to know if there is a simple and logical bit of code to avoid a traffic jam altogether


I think that would be pretty hard to avoid if you're creating a random car on every single update with these kind of "roads". In real life though, there could never be intersections on every single part of the road, plus we invented a traffic light for this specific reason of course.
Even if it's very crowded, a green traffic light would then move (e.g.) 3 east/west moving cars to the next part of the road IN BETWEEN intersections and then turn red. 3 north/south cars now get the green light and they would also move IN BETWEEN intersections.

If you need roads like this, I think it can only be achieved by releasing the cars in set intervals instead of randomly.


dw817(Posted 2016) [#14]
Sorry, getting the two of you mixed up - you both seem equally interested in this puzzle of mine. :)

Here is my solution, if you take too long in traffic, you won't receive a traffic ticket, no, you will be DEREZZED. :D Traffic will then resume flow as normal minus the interfering vehicle.

http://tron.wikia.com/wiki/Derez




dw817(Posted 2016) [#15]
You know, a more elegant solution would be for the offending vehicle to back up one step and let the other guys go. I'll work on this.


dw817(Posted 2016) [#16]
And here it is. Chivalry on the road ! :)



My Dad was really fascinated by this sort of stuff. He developed a method years ago for businesses called GUTS which stood for Grand Unified Theory of Systems.

It could also be applied to a computer program. He wrote one where little dots mizzled around each other but if one couldn't move for a long time because of traffic, he got mad and started pushing the others around.

Then they too would get mad and push others. Eventually the others backed up while those angry worked out their frustration (for all the frustration a pixel could have) :), and then "traffic" resumed normally.

He wrote it in Turbo Pascal and was supposed to simulate crowding situations to see what would happen.