Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2002:
[Freeciv-Dev] Re: normalize_map_pos and invalid map positions

[Freeciv-Dev] Re: normalize_map_pos and invalid map positions

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: "Per I. Mathisen" <per@xxxxxxxxxxx>
Cc: "Ross W. Wetmore" <rwetmore@xxxxxxxxxxxx>, Mike Kaufman <kaufman@xxxxxxxxxxxxxxxxxxxxxx>, <freeciv-dev@xxxxxxxxxxx>
Subject: [Freeciv-Dev] Re: normalize_map_pos and invalid map positions
From: "Ross W. Wetmore" <rwetmore@xxxxxxxxxxxx>
Date: Thu, 22 Aug 2002 01:54:18 -0400

At 01:15 PM 02/08/15 +0000, Per I. Mathisen wrote:
>On Tue, 13 Aug 2002, Ross W. Wetmore wrote:
>> Normalize_map_pos() is the swiss army knife for coordinate testing.
>> It returns false if the coordinate is unreal - generally terminal error.
>> It returns true and a valid normalized coordinate pair otherwise. This
>> may involve normalizing the coordinates in the process but that is always
>> possible if they are real.
>> This should be used at all portal points, i.e. places where you should
>> check for unreal coordinates. This includes source creation, network
>> input points or any place where one might want to check for corruption
>> of any sort, or even just a change in the definition of "normalized".
>> In some cases it is better to use unnormalized or differently normalized
>> coordinates for a given operation. In this case one would normalize before
>> handing off such coordinates to more picky code outside of this module,
>> or do it on input to any module that might receive such coordinates.
>> This should always be the case. It doesn't hurt to fix things up and
>> continue in any situation, and a few judiciously placed checks like
>> this will be useful to catch the unreal cases which are terminal.
>> So even the big reason for normalizing everywhere is not really that
>> sensible with truly generalized topologies.
>So what you are suggesting is that normalize_map_pos() is used at the
>lowest level where coordinates are generated, changed or received from the
>client, and that the the higher level functions receive properly
>normalized map positions which are checked with is_normal_map_pos().

I'm juggling lower/higher but I think I know what you mean.

Almost correct, or rather correct as a gross generalization with
some minor derivative fixes for the fully refined case.

Normalize_map_pos() should be used to validate any (new) coordinate 
before it is used as it is the only function that checks for realness
which is all that really counts. Only unreal coordinates are hard 
errors. As a bonus, it will normalize the values during this process.

There are two main cases. 1) when you first generate new coordinates
as with map_step() from an existing one, and 2) whenever there is any
reason to suspect that coordinates might be invalid.

Case 2 should be done whenever you pass coordinates into a new module
or code component (using the terms generally) that demands normalized
values. For example, when coordinates are passed into the server from 
a client they should be checked. A check for realness is sufficient, 
as this will also handle any normalization that might be required.

Within defined module boundaries, you can insist that coordinates be 
passed as normalized values. Thus there is no need to check at the 
entry to each functional routine except as a sanity check. Some code 
should do sanity checking as an ongoing general error detection policy.

Some modules might be more efficient if they use unnormalized values.
There shouldn't be any problem with them doing this. But if they call 
any interface with the normalized constraint, they need to make sure 
they obey the rules and pass in only normalized values. Any routine
that accepts unnormalized values need to call normalize_map_pos() 
before it uses the coordinates in most cases and typically will do 
it once at the start of the routine.

Note doing a normalize_map_map() is cheap if the coordinates are
already normalized and never more expensive than an is_normal() test. 

>Obviously we should not use normalize_map_pos() in high level code that
>should receive normalized coordinates, since it could receive real,
>non-normalized but completely wrong coordinates, and passing
>normalize_map_pos() over them would make them even more wrong by
>normalizing them, and it would return TRUE, suggesting that coordinates
>are okay.

Any real coordinates are fine. They are always fine as they can always
be normalized on the fly with comnplete safety in all cases. They are
never wrong, and can never be made more wrong. Any other interpretation
is pure religious hogwash used to justify an unnecessary constraint.

Only unreal coordinates are untouchable. There is no valid operation
you can do on unreal coordinates to make them usable. This was the
void tile problem - it didn't understand realness is the one universal
condition that matters and tried to "fix" things by making them pseudo 

>> >example: a unit at (0,0) is ordered to move "northwest" by:
>> >a) the server (by proxy of the ai)
>> >b) a remote client.
>> >
>> >What should ideally happen in a general topological framework?
>> If you normalize the position before handing it off and it comes back
>> something other than (-1,-1) you don't need to worry. Since you can
>> choose the soft condition of normalization in any way you like, this
>> should almost always work - I can't think of a case where it wouldn't.
>Uhm, shouldn't the dir function that returns the coordinate for northwest
>from (0, 0) return a _normalized_ map position? Then both coordinates
>should be >= 0, no?

Since you can always deal with any real coordinate, then in the case
where there are multiple values for some position, you can pass an
alternate one to avoid a special case. It helps a lot if you define
your normalized set to *not* include the special value, then you just
handoff normalized coordinates and everybody is happy. But as long as 
you can pass real values safely without violating the recipient's
interface conditions, there should never be any serious issue.

In cases like vconn_notify() or whatever, accepting real coordinates
will allow you to easily handle such things without vconn_notify()
having to understand all the possible special conditions.

>> If your topology wants to define the value (-1,-1) as both real and
>> normal
>Now you lost me again. I thought a normalized map position by definition
>would be "unwrapped" and always refer to a square map (x1 >= 0, y1 >= 0)
>to (x2 > x1, y2 > y1) in size.
>But a negative map value can be normal?

Most topologies do not map well to a square rectangular map, and for
sure their normal sets are not rectangular squares in freeciv internal
coordinates that you are likely thinking of here.

Normalization is a defined condition, not something intrinsic or fixed.
Certainly you *can* define a normal set to include (-1,-1), but most
of the time this doesn't make sense. 

You want might do this for a polar coordinate map, rather than building 
in an origin shift to keep all values (transformed to rectangular 
coordinates) positive. Its normal set will usually be chosen as a circle, 

Playing a Solar system based game is easy to handle with a shift, because
there is a defined limit to the radius. But an infinite polar map, or 
just one with fuzzy radial extents could be tricky.

The "normal" set for an isometric rectangular map is a rectangular grid
with all even or all odd points missing. But when you transform this
into standard freeciv internal coordinates it is a dense packed rhomboid 
shape, and usually offset so only two corners touch the X and Y axes. 
But if you just did the rotation, it would have negative standard 
coordinates. This is easily handled by the current core algorithms with
only storage issues (but map_index() converting accesses to linear
offsets of a vector avoids these trivially) and of course the (-1,-1) 
special case. 



[Prev in Thread] Current Thread [Next in Thread]