Planet value calculation made easy! |
Sun, 20 March 2005 18:45 |
|
m.a@stars | | Commander | Messages: 2765
Registered: October 2004 Location: Third star to the left | |
|
Hi,
I finally managed to understand how the planet habitability works (it took some zen!). In the process I rewrote the algorithm to make it easier on the eye (and perhaps on the compiler) as well as closer to the spirit of things. This code has already calculated 26000+ planets (belonging to 28 different planet reports) accurately.
A note for testers: Complications may arise due to integer math implicit conversions. Two of them are marked as such. The third is ugly enough that alternate code is provided.
Comments, suggestions, welcome!
#define BYTE char
#define WORD short
#define IMMUNE(a) ((a)==-1)
//simplified for this. Initialized somewhere else
struct playerDataStruct
{
BYTE lowerHab[3]; // from 0 to 100 "clicks", -1 for immunity
BYTE upperHab[3];
} player;
//in: an array of 3 bytes from 0 to 100
//out: a signed integer between -45 and 100
//hey, it was the Jeffs idea!
signed long planetValueCalc(BYTE* planetHabData)
{
signed long planetValuePoints=0,redValue=0,ideality=10000; //in fact, they are never < 0
WORD planetHab,habUpper,habLower,habCenter;
WORD Excentr,habRadius,margin,Negativ,dist2Center;
for (WORD i=0; i<3; i++) {
habUpper = player.upperHab[i];
if (IMMUNE(habUpper)) { //perfect hab
planetValuePoints += 10000;
}
else { //the messy part
habLower = player.lowerHab[i];
habCenter = (habUpper+habLower)/2; //no need to precalc
planetHab = planetHabData[i];
/*
note: this version makes the basic assumption that habitability is
symmetrical around the center, that is, the ideal center is located
in the middle of the lower and upper boundaries, and both halves
have the same value. The original algorithm seems able to cope with
weirder definitions, i.e: bottom is 20, top is 80, center is 65,
and hab value stretches proportionally to the different length of
both "halves"...
*/
dist2Center = abs(planetHab-habCenter);
habRadius = habCenter-habLower;
if (dist2Center<=habRadius) { /* green planet */
Excentr = 100*dist2Center/habRadius; //note: implicit conversion to integer
Excentr = 100 - Excentr; //kind of reverse excentricity
planetValuePoints += Excentr*Excentr;
margin = dist2Center*2 - habRadius;
if (margin>0) { //hab in the "external quarters". dist2Center > 0.5*habRadius
ideality *= (double)(3/2 - dist2Center/habRadius); //decrease ideality up to ~50%
/*
ideality *= habRadius*2 - margin; //better suited for integer math
ideality /= habRadius*2;
*/
}
} else { /* red planet */
Negativ = dist2Center-habRadius;
if (Negativ>15) Negativ=15;
redValue += Negativ;
}
}
}
if (redValue!=0) return -redValue;
planetValuePoints = sqrt((double)planetValuePoints/3)+0.9; //rounding a la Jeffs
planetValuePoints = planetValuePoints * ideality/10000; //note: implicit conversion to integer
return planetValuePoints; //Thanks ConstB for starting this
}
{related topics: http://starsautohost.org/sahforum/index.php?t=msg&th=227 1&start=0&rid=625&S=425579ce978e6d33b2db2f095c4a 3dee
added some comments, mainly for version developers
}
[Updated on: Sun, 27 March 2005 16:10]
So many Stars, so few Missiles!
In space no one can hear you scheme! Report message to a moderator
|
|
|
Re: Planet value calculation made easy! |
Wed, 23 March 2005 12:56 |
|
sirgwain | | Senior Chief Petty Officer | Messages: 86
Registered: March 2004 Location: Tucson | |
|
Very nice! I have a question on how you validated the data. You got planet dumps with gravity, temp, and radiation information. How did you convert from the gravity value to the number of clicks? A lookup table feels error prone because in the race UI there are multiple clicks that give you the same gravity. For example these are the first 11 clicks:
.12f, .12f, .13f, .13f, .14f, .14f, .15f, .15f, .16f, .17f, .17f
How did you get around this?
-SirGwain
[Edit]
Ahhh I see, I just read your posts on the freestars forum. You can convert from clicks to grav completely accurately but not back again.
[Updated on: Wed, 23 March 2005 13:11] Report message to a moderator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Re: Planet value calculation made easy! |
Sat, 09 April 2005 15:25 |
|
|
Hmmm,
Seems to me someone isn't remembering the history of this game very well. i.e.
Quote: | The makers said they did bitpack stuff to get the game files size down and so e-mail size down.
Actually i suspect they bitpacked everything since they just loved to do it. Why to squeeze planets x, y and name_id into 4 bytes in xy file? Why not to use logical 6 bytes? Its e-mailed only once so why to save these 2 kilobytes? Very minor effect
|
So, here is the condensed version:
Stars! was created BEFORE Windows 95 - back in the days of Windows 3.1 and the early internet explosion. Size WAS important. Hard disks rarely capped 250 megs back then and home broadband didn't exist. All compiling would have been done with the compiler options selected for 'minimize code size' and 'optimize code'. The original game (versions 1.0 and 1.1) fit onto a 1.44 meg floppy - and that was with the documentation and help file.
Back in these days (which isn't so long ago in the history of the computer and that I have lived and worked through) - we CARED about code size and efficiency. You could easily play Stars! on any PC that would run Windows 3.1
So folks - there you have it in a nutshell.
Ptolemy
Emperor of a Thousand Suns
Though we often ask how and why, we must also do to get the answers to the questions.Report message to a moderator
|
|
|
|
|
|
|
|
|
Re: Planet value calculation made easy! |
Tue, 02 October 2007 17:36 |
|
yartrebo | | Petty Officer 3rd Class | Messages: 43
Registered: July 2006 Location: North America | |
|
Quote: | It's true that bitpacking code increases EXE size. However, compressed strings also decrease the size.
|
You can reduce both string size and EXE size by using generic compression such as bz2 or zip. Most compression algorithms handle extra 0s very easily and the bitpacking will do little to increase compression.
The compression will slow down the opening of the file a bit, but it will neither bloat the codebase nor impose tight constraints the way bitpacking does.
I am using some bitpacking the stars! clone I'm writing, but it is limited to places where it will not impose restrictions such as storing all LRTs in a 32-bit dword, where performance will be equal to or faster than using separate variables, and where the code bloat will be marginal. For the LRT examples, it's faster than using a bunch of 8-bit bytes since 8-bit operations are very slow, doesn't need as much RAM (speeding up cache performance), and can be tested in two machine operations (and bitfield, mask[IFE]; jnz), which is as fast as if I spent a whole 32-bits for each trait (xor lrt[IFE], 0x0; jnz).
[Updated on: Tue, 02 October 2007 17:38] Report message to a moderator
|
|
|