SOLVED: integer value at 0.0025, not possible?

Started by johanvepa, Thu 09/05/2013 23:23:46

Previous topic - Next topic

johanvepa

I would like to have an integer with a value of 0.0025 (zero point zero zero two five).

I declare the integer VARIABLE in the global script, and I only need it in the global script.

Near the top of globalscript.asc, i Have this:
Code: AGS

int VARIABLE;


At game_start, I set the integer value like this
Code: AGS

function game_start()
{   
VARIABLE = 0.0025;

//lots of other stuff and integer values declared

}


I get this error message: Error (line 1140): Type mismatch: cannot convert 'float' to 'int'.

What am I trying to do here that causes error?

The int VARIABLE is not going to change at all, it will stay at this value the entire game, but I need to call it numerous times, and if I want to change the value for testing purposes, it is nice to have it declared as an integer.

Can I declare it as (1 / 400) instead?

I found that I can use (1 / 400) at places in the code where the variable should have been, but I'm not sure I get the same result that way.



Calin Leafshade

int means integer which means a whole number

you need to declare a float

Code: ags

float variable = 0.0025

johanvepa

#2
I still get the same error message, only now it's the other way around: Cannot convert 'int' to 'float'..

The code I'm scribbling together looks like this:


Code: AGS


int LUCK; //may have a value of 1 to 100

bool LuckSuccess;

float VARIABLE = 0.0025;

function TryYourLuck(int difficulty)
if 
  ((((LUCK * LUCK * VARIABLE)+5) * (100/difficulty)) >= Random(100)) 
    {
    LuckSuccess = true;
    }


So, according to how much LUCK cEgo has, and how much of a difficulty he's up against, he has an increasing chance of success.
Chance = VARIABLE*(Luck2) +5
Chance is then weighed upon difficulty and a random.


This works if I put (1 / 400) instead of VARIABLE in the code, but I would like to have it as a global variable.

Crimson Wizard

AGS don't automatically convert between integer and float variables. You should use functions FloatToInt and IntToFloat to make them work together.

http://www.adventuregamestudio.co.uk/wiki/Maths_functions_and_properties#FloatToInt

johanvepa

But if I convert the float at a value of 0.0025 into an integer, wont the integer have the value of either 0 or 1, then? I would like to make the calculation at decimal level, otherwise the meaning is kinda lost.

Slasher

Ints only show full numbers: 1,2,3 etc

IntToFloat not FloatToInt i believe

Phemar

#6
That's correct, integers don't store decimal places which means it'll always be rounded down to 0.

If you want to work with decimal places you'll need to use floats throughout your calculations.

Eg
Code: ags
int x = (7 / 15) * 40;


Will always give 0, since 7/15 < 1, and 0 * 40 = 40.

Edit, try this:
Code: ags
int LUCK = 1; //may have a value of 1 to 100

bool LuckSuccess;

float VARIABLE = 0.0025;

function TryYourLuck (int difficulty) {

  if ((((IntToFloat(LUCK) * IntToFloat(LUCK) * VARIABLE) + 5.0)
      * (100.0/IntToFloat(difficulty))) >= IntToFloat(Random(100)))
    LuckSuccess = true;
    
}


Edit again. For simplicity's sake you could just have the function return a boolean value. Eg:
Code: ags
int LUCK = 1; //may have a value of 1 to 100

float VARIABLE = 0.0025;

bool TryYourLuck (int difficulty) {

  if ((((IntToFloat(LUCK * LUCK) * VARIABLE) + 5.0)
      * (100.0/IntToFloat(difficulty))) >= IntToFloat(Random(100)))
    return true;
    
}


Then just call the function like:
Code: ags
if (TryYourLuck(10)) { // If the player won
  //code here
}
else { // If the player lost
  //code here
}

Ryan Timothy B

@Phemar & Nanuaraq: It doesn't make a *huge* difference, but converting int to float or float to int takes a tiny bit of cpu time (just a tiny tiny bit, barely noticeable - all added together could possibly lower your FPS, but only if you were pushing the boundaries of AGS anyway doing a ton of math and other stuff; a regular adventure game will not do that). BUT, it's a better practice to do this:
Code: ags
IntToFloat(LUCK * LUCK)


Instead of:
Code: ags
IntToFloat(LUCK) * IntToFloat(LUCK)  // bad practice


Try to keep all your int calculations together and then convert. Same goes with float calculations (obviously).

Also instead of converting Random(100) to float, you should instead convert the first half of the condition to int. That way you could round (eRoundDown, eRoundNearest, eRoundUp). A float is a floating point number and does some pretty wacky stuff to store the number. It's not often you'll have a float number that is exactly 5, it'll generally do: 4.999999 or 5.000001 (that's written in the manual about float - and common programming knowledge).

Phemar

Ryan's right of course. Sorry I'm just half asleep.

johanvepa

#9
Hello everyone, thank you very much for your time and your answers.

In the end, I settled for a (to me) simpler solution that required only integers, not floats. I was afraid I'd mess everything up, so I made a messier but simpler code that did the job (self-contradiction detected).

I made do with setting three variables to take effect at LUCK >= 10, LUCK >= 60 and LUCK >= 90, respectively, thus mimicking a second degree polynomial somewhat. The results are satisfactory, and I can still keep track of what I'm doing.

Still, I'll look into the floating business when need arises. I'm sure it does, eventually.

Khris

You can always do something like this btw:

Code: ags
int modifier = 0;  // add 0% by default

  if (Random(99) < (LUCK * (100 + modifier)) / 100)  ...


Say LUCK was 20 so the chance of getting lucky is one in five. With a modifier of for instance 15(%), it would rise to 23% or almost one in four. All without decimals / floats.

Not sure what your LUCK >= 10 etc. business is about, but it sounds kinda bad. You can have smooth curves without ever using floats.

johanvepa

#11
Quote from: Khris on Fri 10/05/2013 20:32:26
You can always do something like this btw:

Code: ags
int modifier = 0;  // add 0% by default

  if (Random(99) < (LUCK * (100 + modifier)) / 100)  ...


Say LUCK was 20 so the chance of getting lucky is one in five. With a modifier of for instance 15(%), it would rise to 23% or almost one in four. All without decimals / floats.

Not sure what your LUCK >= 10 etc. business is about, but it sounds kinda bad. You can have smooth curves without ever using floats.

That's exactly what I'm doing, though I admit you scribe the code much more elegantly than I (so I might just possibly steal it, and thank you). The trick is in setting the modifier. Your abovementioned code is still a straight line. What I would have liked to do was this:

Base chance of something happening by luck alone = 0.0025*LUCK2 + 5

I want LUCK to become a dynamically changing amount. I tried to mimic the effect of a second degree polynomial somewhat, using three straight lines rather than a smoothly accelerating curve, by using three different funcstions at LUCK scores between 10-59, between 60-89 and above 90, but it's messy, as you well notice.

Having given the issue more thought, I think I can gain the effect of a true second degree polynomial by making the modifier depend on the value of LUCK. There's the second degree polynomial I've been looking for.

After all this, I would modify Base Chance by a difficulty factor, ranging from 1 to 100 (say, a sheer cliff wall is tougher to climb than most trees, even if you're lucky).

The function would look like this in globalscript:

Code: AGS

int climbingskill;
int difficulty;
bool climbsuccess;

int luckmodifier;
bool lucksuccess;

function pushyourluck();
{
lucksuccess = false;  //default unless success
luckmodifier = (((LUCK * 25) / 100)  //modifier is a value equalling 25% of current LUCK count (LUCK may rise with experience)
  if ((Random(99)+1) <= (((LUCK * (luckmodifier)) / 100) + 5) * (100 / difficulty)
  {
  lucksuccess = true;
  }
}

function Do_Climbing();
{
climbsuccess = false; //default unless success
if climbingskill >= difficulty
  {
  climbsuccess = true;
  }
else if (Random (100) < 100) //because LUCK must never become completely trustworthy
  {
  pushyourluck();
  if (lucksuccess == true);
    {
    climbsuccess = true;
    }
  }
}


in local script, when trying to climb the slippery tree:

Code: AGS

function SlipperyTree_Interact();
Display("You look up at the slippery tree. This will be difficult.");
difficulty = 30;  //setting up difficulty for the next line of code
Do_Climbing();  //testing skill and luck against the above set difficulty
if (climbsuccess == true);
  {
  Display("you climb the tree.");
  //tree climbing happening
  }
else
  {
  Display("You fail and land on the hard ground. Better luck next time");
  //something OUCH happening
  }
}



I can't wait to test this.


Khris

First of all, you can pull all that together:

Code: ags
  // climbing the tree
  if (test(LUCK, 30)) {
    // climb tree
  }
  else Display("You suck.");

I could provide you with code, but I'm still not sure about your formula.
QuoteBase chance of something happening by luck alone = 0.0025*LUCK² + 5
So a LUCK value of 10 means the chances are 5.25, correct? Is that in percent?
A LUCK value of 100 would result in 30, which seems a bit low, if that's in percent.

Also, is it supposed to rise exponentially like that? Using a second degree polynomial is fine, but how do you want to use it?
Is having your LUCK value double supposed to make you roughly four times as good at doing things?

johanvepa

#13
Quote from: Khris on Sat 11/05/2013 13:52:21
First of all, you can pull all that together:
Code: ags
  // climbing the tree
  if (test(LUCK, 30)) {
    // climb tree  }
  else Display("You suck.");


True, I can pull it more together than I did. I also think I can make a more general
Code: AGS
 function Do_Attempt(skill); 

which has an equivalent of the pushyourluck(); funtion built-in. I might then use the Do_Attempt(skill) function for different skills.

I'll get to work on it.


Quote from: Khris on Sat 11/05/2013 13:52:21
QuoteBase chance of something happening by luck alone = 0.0025*LUCK² + 5
So a LUCK value of 10 means the chances are 5.25, correct? Is that in percent?
A LUCK value of 100 would result in 30, which seems a bit low, if that's in percent.

Correct, and it is rather low. The point is, even LUCK should not be a sure-fire way of overcoming obstacles. Rather it is a non-reliable but still considerable factor.

LUCK only comes into play if SKILL isn't high enough. SKILL is tried in absolutes, LUCK in probability.

Quote from: Khris on Sat 11/05/2013 13:52:21
Also, is it supposed to rise exponentially like that? Using a second degree polynomial is fine, but how do you want to use it?
Is having your LUCK value double supposed to make you roughly four times as good at doing things?

No, base probability is 0.0025*LUCK² + 5 (which is the second degree polynimal I mimic), so probability is always at a minimum of 5, with LUCK having an initially very small but exponentially rising effect. With the polynomial at 0.0025x2, and x ranging from between 1 to 100, having LUCK value doubled only makes base probability rise a fraction (in absolute value), unless value is nearing 100.

Also, the probabilities you quote here are the base chances. They wil be modified by the given difficulty factor. An obstacle that take a skill of 100 to overcome should not be easily overcome, even by a very LUCKy person. Still, you just might get lucky, even with a low LUCK factor.

And thank you for your kind offer of coding, but I believe I learn more by trying myself. I'll post it though, if you'd like to comment on the finished code.

Khris

Quote from: Nanuaraq on Sat 11/05/2013 14:51:49No, base probability is 0.0025*LUCK² + 5 (which is the second degree polynimal I mimic), so probability is always at a minimum of 5, with LUCK having an initially very small but exponentially rising effect. With the polynomial at 0.0025x2, and x ranging from between 1 to 100, having LUCK value doubled only makes base probability rise a fraction (in absolute value).
The factor doesn't matter at all; doubling LUCK will quadruple LUCK², no matter what factor you put before it afterwards. You can only offset this relation by adding a value (which you do). But I guess we're talking past each other.

My main point is that you don't have to store a value somewhere, then call a function, then process some result variable.
Functions can take up to 9 parameters and return one (or an array, alternatively).

I'd use an enum for the different skills and an array, like this:
Code: ags
// header

enum SkillType {
  eSkillClimb = 0,
  eSkillSneak = 1,
  eSkillLuck = 2,
}

// script

int skill[20];

bool attempt(SkillType s, int difficulty) {
  if (skill[s] >= difficulty) return true;
  // try luck
  int luck = skill[eSkillLuck];
  return (luck * luck * modifier) / 10000 + 5 > Random(99);
}

johanvepa

#15
Quote
The factor doesn't matter at all; doubling LUCK will quadruple LUCK², no matter what factor you put before it afterwards.

I saw it as soon as I'd written it. I also made an edit, but you beat me to it. The point is of course that the effect of raising LUCK one point is initally very small, but will become significant as we come near LUCK=100.

Quote
My main point is that you don't have to store a value somewhere, then call a function, then process some result variable.
Functions can take up to 9 parameters and return one (or an array, alternatively).
True, I only do it for reasons of self-learning. With my code more "spoken-out", I can see what I'm doing and make changes accordingly.

Quote
I'd use an enum for the different skills and an array, like this:

enum SkillType {
  eSkillClimb = 0,
  eSkillSneak = 1,
  eSkillLuck = 2,
}

and a good idea it is, though I keep the integers named instead of enumerated for reasons of myself being able to keep track of them.

Quote
// script

int skill[20];

bool attempt(SkillType s, int difficulty) {
  if (skill >= difficulty) return true;
  // try luck
  int luck = skill[eSkillLuck];
  return (luck * luck * modifier) / 10000 + 5 > Random(99);


From what I can see of this, with my (admittedly) very limited skills in the scripting business, what you do is a shorter and more neat version of the following:

Code: AGS

int climbingskill;
//and other integers relating to skills
int difficulty; //relevant difficulty for a given task
bool AttemptWasSuccessful; 

function Attempt_SkillUse(skill, difficulty)
{
AttemptWasSuccessful = false; //default unless success
if skill >= difficulty  //first, test SKILL
  {
  AttemptWasSuccessful = true;
  }  //if SKILL fails, test LUCK
else if ((Random (99)+1) < 100) //this check done because LUCK must never become completely trustworthy
  {
  if ((Random(99)+1) <= ((((LUCK * ((LUCK * 25) / 100)) / 100) + 5) * (100 / difficulty))
    {
    AttemptWasSuccessful = true;
    }
  }
}



in local room script:

Code: AGS

function oSlipperyTree_Interact();
  {
  Attempt_SkillUse(climbingskill, 30);
  if (AttemptWasSuccessful == true)
    {
    Display("You climb to the top.");
    //climbing happening
    }
  else
    {
    Display("You fall down and crack your skull");
    //something bad happening
    }
  }



..which is what I had thougth out in the time since my last post.

Khris

Let me just say that spelling out stuff is good as long as you're a beginner, but insisting on using bad coding practices isn't.
The fact that functions return values, which allows you to do something like
Code: ags
  Display(String.Format("The rounded result is %d", FloatToInt(Maths.Sqrt(a + DotProduct(x, y)), eRoundNearest)));

is one of the most elementary things about programming.

Nobody expects you to use as few letters as possible, but cutting down on the number of variables is not only good practice, it also makes the code less error-prone.

johanvepa

#17
Quote
Let me just say that spelling out stuff is good as long as you're a beginner, but insisting on using bad coding practices isn't.

Oh, I agree wholeheartedly. And I'm a beginner.

I also think that the only thing worse than bad coding is a bad coder copy-pasting code he doesn't understand a word of. That's bug-prone.

And thank you. I really mean it.

EDIT: Cleaned up the above-scripted code a little.

SMF spam blocked by CleanTalk