Server Help Forum Index Server Help
Community forums for Subgame, ASSS, and bots
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   StatisticsStatistics   RegisterRegister 
 ProfileProfile   Login to check your private messagesLogin to check your private messages   LoginLogin (SSL) 

Server Help | ASSS Wiki (0) | Shanky.com
Loading a formula from an INI file

 
Post new topic   Reply to topic Printable version
 View previous topic  Flag Neuter Post :: Post C help  View next topic  
Author Message
50% Packetloss
Server Help Squatter


Age:39
Gender:Gender:Male
Joined: Sep 09 2003
Posts: 561
Location: Santa Clarita, California
Offline

PostPosted: Tue Jul 27, 2004 11:06 pm    Post subject: Loading a formula from an INI file Reply to topic Reply with quote

k, here is the deal. Im making a duel bot for a specific zone's league. Now they arent quite certain if the formula they created for ranking players in the league will work out ok, so they want the ability to change it from a file. This involves loading the string and then using that string to do math, ex: "5 * 2 - 3 + (55 - 2) / 4", I dont care about any truncations that happen with division.

I have done all this but was looking to see if anyone has code that does it better or has a better plan. Currently what i am doing is searching the string for operators ( * / + - () ) and numbers. It builds a linklist backwards, starting from the tail ( end of the string) and building to the head so that by the end i have an array of numbers and operators in the correct order (no need to worry about error checking, i can do that way before i start using the formula). Then once the linklist is built, a function to calculate the math will be called. This function uses recursion, this is done because stuff that is inside () parenesis must be completed first. So the function searches for a open parenthesis (, if it is found then it will call itself and send a pointer the next position in the linklist. In the case that no parenthesis is found, it will fall out of the loop and then begin doing the math until it finds a NULL or a close parenthesis ). It handles 2 operators at a time * and / or + and - (order of operations). If one of these operators are found then it will perform the operation between the number that is ->last in the linklist and the number that is ->next. Deletes those numbers and stores the result in the position that the operator was in. Depending on if its handling numbers inside parenthesis, it will delete any parenthesis and return a pointer to the linklist ( the function that was called first will return a pointer to the head of the linklist, that way its not lost in all the deletes that happen). I need to clean up the code a bit and then i can post it if anyone would like to see it, it isnt that impressive but it works. I plan on adding code that will replace macros in the formula with variables.
Back to top
View users profile Send private message Add User to Ignore List Send email AIM Address
CypherJF
I gargle nitroglycerin


Gender:Gender:Male
Joined: Aug 14 2003
Posts: 2582
Location: USA
Offline

PostPosted: Tue Jul 27, 2004 11:28 pm    Post subject: Reply to topic Reply with quote

Cool cool; I had to do something similar for a regular expression to RPN (?) # # OPSIGN etc etc.. instead of # OP #... and it would evaluate using queue's and stack's..

I'd still post it..
_________________
Performance is often the art of cheating carefully. - James Gosling
Back to top
View users profile Send private message Add User to Ignore List
Mr Ekted
Movie Geek


Gender:Gender:Male
Joined: Feb 09 2004
Posts: 1379
Offline

PostPosted: Wed Jul 28, 2004 2:32 am    Post subject: Reply to topic Reply with quote

Unary negate and powers (squared at least) would be nice too. Pretty soon your bots will be reading perl or python scripts. icon_smile.gif
_________________
4,691 irradiated haggis!
Back to top
View users profile Send private message Add User to Ignore List
50% Packetloss
Server Help Squatter


Age:39
Gender:Gender:Male
Joined: Sep 09 2003
Posts: 561
Location: Santa Clarita, California
Offline

PostPosted: Wed Jul 28, 2004 3:58 am    Post subject: Reply to topic Reply with quote

yah i figure (0-7) would negate a number, powers are only multiplication but could easily be added as an operator
Back to top
View users profile Send private message Add User to Ignore List Send email AIM Address
50% Packetloss
Server Help Squatter


Age:39
Gender:Gender:Male
Joined: Sep 09 2003
Posts: 561
Location: Santa Clarita, California
Offline

PostPosted: Wed Jul 28, 2004 5:13 am    Post subject: Reply to topic Reply with quote

This is what i am done with so far. It seems to work.
Code: Show/Hide

typedef unsigned char    Uint8;
typedef unsigned short    Uint16;
typedef unsigned long    Uint32;
typedef signed char      Sint8;
typedef signed short    Sint16;
typedef signed long      Sint32;

struct Math
{
   bool IsNum;
   int var;
   Math *next;
   Math *last;
};

void Del(Math *ptr)
{
   if(ptr->last != NULL)
   {ptr->last->next= ptr->next;}
         
   if(ptr->next != NULL)
   {ptr->next->last= ptr->last;}

   delete ptr;
}

char Operator[5]={'*', '/', '+', '-'};
Math* Calculate(Math *list)
{
   Math* var1= NULL;//var1 is used for doing math operations and for deleteing ')' nodes
   Math* var2= NULL;//used only for math
   Math *parse=list;//used for cycling through the linklist
   Uint16 i;//used for looping through the order of operations

   while( parse != NULL)//cycle through the linklist
   {
      if(!parse->IsNum)//if its an operator
      {
         if(parse->var == '(')//if the operator is an open parenthesis
         {
            var1= Calculate(parse->next);//solve everything within the parenthesis, function should return a pointer to the close parenthesis ')'

            if(parse == list)//dont lose the pointer that marks our place
            {list= parse->next;}
            
            Del(parse);//delete the '('

            if(var1 != NULL)//delete the ')'
            {Del(var1);}

            break;//get outta the loop
         }
      }
      parse = parse->next;
   }

   for(i=0; i < 4; i+=2)//cycle through the Operators, 2 at a time
   {
      parse= list;
      while( parse != NULL)//go through the linklist
      {
         if(!parse->IsNum)//if its an operator
         {
            if(parse->var == Operator[i] || parse->var == Operator[i+1])//if its one of the ones wanted
            {
               var1= parse->last;//get the 2 numbers between the operator
               var2= parse->next;

               if(var1 != NULL && var2 != NULL && var1->IsNum && var2->IsNum)//make sure everything is ok
               {
                  parse->IsNum=true;//this operator is going to turn into a number
                  switch(parse->var)
                  {
                  case '/':
                     parse->var= var1->var / var2->var;
                     break;
                  case '*':
                     parse->var= var1->var * var2->var;
                     break;
                  case '+':
                     parse->var= var1->var + var2->var;
                     break;
                  case '-':
                     parse->var= var1->var - var2->var;
                     break;
                  }

                  if(var1 == list)//make sure we dont lose our place in the array
                  {list= parse;}

                  Del(var1);//delete the 2 variables
                  Del(var2);
               }
            }
            else if(parse->var == ')')//if a ')' closed-parenthesis is found, get out of the loop
            {
               break;
            }
         }
         parse= parse->next;
      }
   }

   if(parse != NULL)//if parse != NULL then that means that a ')' closed-parenthesis was found so return a pointer to it
   {list= parse;}

   return list;
}

int main ()
{
   #define LEN 256 //length of the formula buffer, it will be loaded from INI file sooner or later
   char formula[LEN]="(500 + 600) * 8 + 6 - (2 + (7 - 3))+2";//the problem we want to solve
   int i,j;//used for loops
   Uint16 Multiplier;//used to convert strings into integers
   Math *list=NULL;//the linklist
   Math *parse=NULL;//used to make and parse through the linklist

   j=0;
   for(i=0; (i < LEN) && (formula[i] != NULL) ; i++)
   {//make sure that only characters we want are in the string (this will probably be done once after the formula is loaded from the INI file)
      if(formula[i] >= '(' && formula[i] <= '9' && formula[i] != ',' && formula[i] != '.')//Numbers: 0-9 Operators: ( ) * + - /
      {
         formula[j++]=formula[i];
      }
   }
   formula[j]=0;


   for(i=j-1;i >=0;i--)//start from the end of the string and move forward
   {
      parse= new Math;//make a new Math and make it the head of the linklist
      if(list != NULL)
      {list->last= parse;}//list's last is equal to new head
      parse->next= list;//next is equal to the old head
      list= parse;//list is equal to the head of the linklist

      if(formula[i] >= '0' && formula[i] <= '9')//if its a number
      {
         Multiplier=1;

         parse->var= 0;
         parse->IsNum=true;

         while(i>=0 && formula[i] >= '0' && formula[i] <= '9')
         {
            parse->var += (formula[i] ^ 0x30) * Multiplier;
            Multiplier *= 10;
            i--;
         }
         i++;
      }
      else //its not a number, so its an operator
      {
         parse->var= formula[i];
         parse->IsNum=false;
      }
   }
   list->last= NULL;//the head's ->last pointer points to NULL

   list = Calculate(list);//calculate the number down to 1 node
   if(list != NULL)//if everything went well
   {
      //printf("%i",list->var);
      delete list;//delete the last node
      list=NULL;
   }
   return 0;
}




Cpp1.cpp - 4.69 KB
File downloaded or viewed 35 time(s)
Back to top
View users profile Send private message Add User to Ignore List Send email AIM Address
myndzi
Guest


Offline

PostPosted: Wed Jul 28, 2004 8:24 pm    Post subject: Reply to topic Reply with quote

Well I actually did tell him RPN would work good, it'd be easier to code and I can write the math that way icon_wink.gif But to be honest this way is more intuitive for me and most people.
Back to top
Tommyhawk
Newbie


Joined: Jul 14 2004
Posts: 14
Offline

PostPosted: Wed Jul 28, 2004 8:34 pm    Post subject: Reply to topic Reply with quote

You could have also used postfix to evaluate a math expression. It uses a stack and has two steps (converting from infix to postfix) but neither are that difficult. It's been a while since I had to do this but I remember it being really simple. Here's a link about it:

http://www.spsu.edu/cs/faculty/bbrown/web_lectures/postfix/
Back to top
View users profile Send private message Add User to Ignore List
CypherJF
I gargle nitroglycerin


Gender:Gender:Male
Joined: Aug 14 2003
Posts: 2582
Location: USA
Offline

PostPosted: Wed Jul 28, 2004 8:41 pm    Post subject: Reply to topic Reply with quote

Yeah; the RPN is nicer but meh who cares it's coded now icon_wink.gif
Back to top
View users profile Send private message Add User to Ignore List
50% Packetloss
Server Help Squatter


Age:39
Gender:Gender:Male
Joined: Sep 09 2003
Posts: 561
Location: Santa Clarita, California
Offline

PostPosted: Wed Jul 28, 2004 9:47 pm    Post subject: Reply to topic Reply with quote

yah, I looked at that RPN stuff and i figured that I wasnt Polish enough to understand it. I cant really expect someone who is setting up the formula to learn a new way of writting math
Back to top
View users profile Send private message Add User to Ignore List Send email AIM Address
50% Packetloss
Server Help Squatter


Age:39
Gender:Gender:Male
Joined: Sep 09 2003
Posts: 561
Location: Santa Clarita, California
Offline

PostPosted: Wed Jul 28, 2004 9:52 pm    Post subject: Reply to topic Reply with quote

that postfix stuff is neet, ill bookmark it
Back to top
View users profile Send private message Add User to Ignore List Send email AIM Address
Guest



Offline

PostPosted: Thu Jul 29, 2004 2:37 am    Post subject: Reply to topic Reply with quote

Oh, I don't know if it's literally Polish. Processing is easy though... you go something like this.

Loop through the input string from left to right
When you encounter a value, push it onto the stack
When you encounter an operator, POP the last two items on the stack and apply the operator; push the result
When you encounter the end hopefully you only have one value left on the stack icon_wink.gif

Speaking of postfix I actually have some experience with that through a friend of mine who implemented it in a script, I may be able to help some if you have questions, provided I can go back and understand the code again ... heh, heh!
Back to top
50% Packetloss
Server Help Squatter


Age:39
Gender:Gender:Male
Joined: Sep 09 2003
Posts: 561
Location: Santa Clarita, California
Offline

PostPosted: Thu Jul 29, 2004 2:41 am    Post subject: Reply to topic Reply with quote

nah, my code seems to work. It requires building a linklist and many loops but i think a bot can handle it. Most important thing is that average newbs are able to setup a formula and no have to learn new math techniques
Back to top
View users profile Send private message Add User to Ignore List Send email AIM Address
Tommyhawk
Newbie


Joined: Jul 14 2004
Posts: 14
Offline

PostPosted: Thu Jul 29, 2004 5:08 pm    Post subject: Reply to topic Reply with quote

You don't have to learn any new math techniques. All you have to do is convert from infix (ie 3 + 9) to postfix (3 9 +) and then process the postfix. The link I gave tells you how to do both. Theres even an animation on converting infix to postfix at the bottom.
Back to top
View users profile Send private message Add User to Ignore List
Display posts from previous:   
Post new topic   Reply to topic    Server Help Forum Index -> ASSS Custom Projects All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum
View online users | View Statistics | View Ignored List


Software by php BB © php BB Group
Server Load: 582 page(s) served in previous 5 minutes.

phpBB Created this page in 0.603796 seconds : 40 queries executed (76.3%): GZIP compression disabled