Page 2 of 6 FirstFirst
1
2
3
4
... LastLast
  1. #21
    Quote Originally Posted by Requital View Post
    It would probably get a lot of use from experienced people but those with less experience tend to stray from things that first appear complicated or lack a UI. However I would love to see it and try it feel free to PM me if you are interested in spreading it around.
    Same. I can take a look at it myself and see if I can implement the xml reader (shouldn't be too hard).

  2. #22
    I did some research on how to import something (char stats) from the web into a file my program can read and I think the cURL libraries are my best bet. I think I will work on doing that some tomorrow.

    My source code is pretty sloppy, but here it is:

    [sblock]
    Code:
    // WindwalkerReforge.c
    // Version 2.0
    // By Janxspirit AKA Keith C
    // Known bugs - Sometimes uses nonexistent gems (expertise+hit yellows, or haste+crit yellows), but since this hasn't actually happened I haven't fixed it yet (I just know it can in theory happen).
    // To do in future - Make character import from web, output gems used (makes you figure it out yourself ATM), optimize some dumb stuff and make comments
    
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    // The number of different types of sockets you have
    #define RED 2
    #define YELLOW 9
    #define BLUE 6
    
    // The value of your socket bonuses plus the 165 crit leg enchant and the 100 crit shoulder enchant
    #define bcri 60+165+100
    #define bmas 0
    #define bhas 60
    #define bexp 120
    #define bhit 0
    
    // The total number of items/enchants
    // Don't fiddle with this, you'll break the program
    #define GEAR 18
    
    // The number of times to run the optimizer
    #define RUNS 1000000
    
    // Input each row (piece of gear) as {haste,crit,mastery,hit,expertise,0}
    // Any time I get a new piece of gear I have to update the entry for it here in this gear array
    // To change to reforging someone else's character I would have to input all their gear
    // This is a very shitty way to input a character.  Would be better to use simcraft to import from armory and then parse that output file.
    // If a piece of gear does not exist (or if it is a pure agi trink) input -1 in the 6th (last) column
    int gear[GEAR][6] = {
    // Input gear UNREFORGED
    // 0=Head
    {882,0,925,0,0,0},
    // 1=Neck
    {604,0,0,0,536,0},
    // 2=Shoulder
    {732,0,732,0,0,0},
    // 3=Back
    {0,557,581,0,0,0},
    // 4=Chest
    {0,0,893,0,935,0},
    // 5=Wrist
    {569,525,0,0,0,0},
    // 6=Hands
    {0,747,0,0,701,0},
    // 7=Waist
    {598,0,0,0,498,0},
    // 8=Legs
    {973,0,935,0,0,0},
    // 9=Feet
    {610,485,0,0,0,0},
    // 10=Ring 1
    {0,494,629,0,0,0},
    // 11=Ring 2
    {449,506,0,0,0,0},
    // 12=Weapon 1
    {0,405,405,0,0,0},
    // 13=Weapon 2
    {0,405,405,0,0,0},
    // 14=Trinket 1
    {0,0,0,1467,0,0},
    // 15=Trinket 2
    {0,0,0,0,0,-1},
    // Don't change these two enchants even if you are using different ones.  Doing so will break the program.
    // 16=Glove enchant
    {170,0,0,0,0,0},
    // 17=Cloak enchant
    {0,180,0,0,0,0}
    };
    
    int best[GEAR],best2[GEAR],globalflag=0;
    
    double bestval=0.0,bestval2=0.0;
    
    double reforge(void);
    int score(void);
    void results(void);
    
    int main(void){
        long int i,j;
        
        srand(time(NULL));
        
        // The program works by throwing darts at a dart board, where the dart board is the space of possible reforges
        // and the darts are random reforges.  For each dart it then makes any changes that would improve the dart
        // so each dart is a local maximum.  It remembers the dart that is the biggest local maximum and thats the answer
        // 100k darts takes about 25 seconds on my computer to run
        // I recommend 1000k darts
        for(i=0;i<RUNS;i++){
            reforge();
            if(bestval>bestval2){
                bestval2=bestval;
                for(j=0;j<GEAR;j++) best2[j]=best[j];
                printf("NEW HIGH - %lf\n",bestval2);
            }
        }
        printf("END O_O %lf\n",bestval2);
        for(i=0;i<GEAR;i++) gear[i][5]=best2[i];
        results();
        while(1);
    }
    
    // This function does 1 dart throw
    double reforge(void){
        int flag=1,i,j,k,temp;
        // Pick a random starting point
        for(i=0;i<GEAR;i++){
            if(gear[i][5]!=-1) gear[i][5]=rand()%7;
        }
        // Note the score
        bestval=0;
        score();
        // Attempt to find a local maxima... it tries to do this by going through all possible single reforges in a randomish order
        // the random order is not really very random at all, I just did a bit of work to make it not always the same order
        // if it makes an improvement it starts over again until it can't make an improvement any more
        while(flag){
            flag=0;
            k=rand()%GEAR;
            for(i=k;i<k+GEAR;i++){
                for(j=1;j<8;j++){
                    if(gear[i%GEAR][5]!=-1) gear[i%GEAR][5]=(gear[i%GEAR][5]+j)%7;
                    if(score()){
                        j=8;
                        i=k+GEAR;
                        flag=1;
                    }
                }
            }
        }
    }
    
    // This function checks to see how good a reforge is
    int score(void){
        // This is initialization based on enchants and gems... very shoddy needs improving and allowance for gem optimization
        int stats[5]={0,0,0,0,0};
        int i,j,k,source,destination,flag,gemsused=0;
        double pts=0.0;
        // Initialize the gear, before reforges... this can be optimized to run faster since these are constant values
        for(i=0;i<GEAR;i++){
            for(j=0;j<5;j++){
                stats[j]+=gear[i][j];
            }
        }
        // Account for socket bonuses and the leg enchant
        stats[0]+=bhas;
        stats[1]+=bcri;
        stats[2]+=bmas;
        stats[3]+=bhit;
        stats[4]+=bexp;
        // Use at least 160 exp from reds gems and 160 hit from blues
        stats[3]+=BLUE*160;
        stats[4]+=RED*160;
        // Reforge gear (other than trinkets)
        for(i=0;i<14;i++){
            if(gear[i][5]>0){
                // find source
                if(gear[i][5]<4){
                    // first nonzero stat
                    k=0;
                    while(gear[i][k]==0) k++;
                }else{
                    // last nonzero stat
                    k=0;
                    while(gear[i][4-k]==0) k++;
                    k=4-k;
                }
                source = k;
                // find destination
                k=0;
                flag=(gear[i][5]-1)%3+1;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reforge the trinkets
        for(i=14;i<16;i++){
            if(gear[i][5]>0){
                // find source
                k=0;
                while(gear[i][k]==0) k++;
                source = k;
                // find destination
                k=0;
                flag=gear[i][5];
                if(flag>4)flag-=4;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reenchant the gloves
        if(gear[16][5]%3==1){stats[2]+=170;stats[0]-=180;}
        if(gear[16][5]%3==2){stats[4]+=170;stats[0]-=180;}
        // Reenchant the cloak
        if(gear[17][5]%2==1){stats[3]+=180;stats[1]-=180;}
        if(globalflag){
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
        }
        // Use gems! In a windwalkery way
        while(gemsused<RED+BLUE+YELLOW*2){
            //Use a red gem
            if(gemsused<RED){
                if(stats[4]<2470){
                    stats[4]+=160;
                }else{
                    if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                        if(stats[0]>stats[1]) stats[1]+=160;
                        else                  stats[0]+=160;
                    }else{
                        stats[2]+=160;
                    }
                }
            }else{
                // Use a blue gem
                if(gemsused<RED+BLUE){
                    if(stats[3]<2510){
                        stats[3]+=160;
                    }else{
                        if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                            if(stats[0]>stats[1]) stats[1]+=160;
                            else                  stats[0]+=160;
                        }else{
                            stats[2]+=160;
                        }
                    }
                }else{
                    //Use a yellow gem
                    if(stats[3]<2510){
                        stats[3]+=160;
                    }else{
                        if(stats[4]<2470){
                            stats[4]+=160;
                        }else{
                            if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                                if(stats[0]>stats[1]) stats[1]+=160;
                                else                  stats[0]+=160;
                            }else{
                                stats[2]+=160;
                            }
                        }
                    }
                }
            }
            gemsused++;
        }
                    
                
        // determine score
        // if you were going to adapt this program for a different class, you would need to change the following few lines of code
        if(stats[4]<2550) pts-=(2550-stats[4])*2;
        if(stats[4]>2550) pts-=(stats[4]-2550)*2;
        if(stats[3]<2550) pts-=(2550-stats[3])*3;
        if(stats[3]>2550) pts-=(stats[3]-2550)*1;
        pts+=stats[0]*3;
        pts+=stats[1]*3;
        if(stats[0]>=stats[2]||stats[1]>=stats[2]) pts*=-1;
        if(globalflag){
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
        }
        //save score if it is good
        if(pts>bestval){
            bestval=pts;
            for(i=0;i<GEAR;i++) best[i]=gear[i][5];
            return(1);
        }
        return(0);
    }
    
    // This function just prints out the found solution
    void results(void){
        int i,k,flag,source,destination;
        for(i=0;i<16;i++){
            switch(i){
                case 0:
                printf("Head - ");
                break;
                case 1:
                printf("Neck - ");
                break;
                case 2:
                printf("Shoulder - ");
                break;
                case 3:
                printf("Back - ");
                break;
                case 4:
                printf("Chest - ");
                break;
                case 5:
                printf("Wrist - ");
                break;
                case 6:
                printf("Hands - ");
                break;
                case 7:
                printf("Waist - ");
                break;
                case 8:
                printf("Legs - ");
                break;
                case 9:
                printf("Feet - ");
                break;
                case 10:
                printf("Ring1 - ");
                break;
                case 11:
                printf("Ring2 - ");
                break;
                case 12:
                printf("Weapon1 - ");
                break;
                case 13:
                printf("Weapon2 - ");
                break;
                case 14:
                printf("Trinket1 - ");
                break;
                case 15:
                printf("Trinket2 - ");
                break;
            }
            if(best2[i]<1){
                printf("No reforge\n");
            }else{
                if(i<14){
                    // find source
                    if(best2[i]<4){
                        // first nonzero stat
                        k=0;
                        while(gear[i][k]==0) k++;
                    }else{
                        // last nonzero stat
                        k=0;
                        while(gear[i][4-k]==0) k++;
                        k=4-k;
                    }
                    source = k;
                    // find destination
                    k=0;
                    flag=(best2[i]-1)%3+1;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }else{
                    // find source
                    k=0;
                    while(gear[i][k]==0) k++;
                    source = k;
                    // find destination
                    k=0;
                    flag=best2[i];
                    if(flag>4)flag-=4;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }
                printf("Reforge out of ");
                switch(source){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf(" and into ");
                switch(destination){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf("\n");
            }
        }
        printf("Enchant gloves with 170 ");
        if(gear[16][5]%3==0) printf("haste\n");
        if(gear[16][5]%3==1) printf("mastery\n");
        if(gear[16][5]%3==2) printf("expertise\n");
        printf("Enchant cloak with 180 ");
        if(gear[17][5]%2==0) printf("crit\n");
        if(gear[17][5]%2==1) printf("hit\n");
        globalflag=1;
        score();
    }
    [/sblock]

    It's worth noting that the program always follows sockets and uses the following relative stat values:

    Hit = -4 for each point under cap, -1 for each over
    Exp = -2 for each point under cap, -2 for each over
    Crit = 3
    Haste = 3
    Mastery = 0 (Yes, 0. This is a bit silly. The value of mastery comes in by higher mastery letting you have higher crit/haste. It forces mastery to be higher than those 2)
    Agi = 0 (Program does not consider value of agi at the moment)

    I'm also probably going to change it to keep track of your total stats from gear and just figure out how they change from the one reforge you are trying rather than having to sum everything up again all the time.

    edit - I really need to make the penalty for being under the expertise cap more, since right now the program thinks losing 3 expertise in exchange for a mastery+crit+haste is an even trade. I upped it a bit in my most recent offline version of the program. It's no wonder my sample output chose to not be very close to exp cap.
    Last edited by keithioapc; 2013-04-09 at 11:56 PM.
    WW Monk - Janxspirit @ US-Illidan
    [20:14:20.744] Janxspirit Rising Sun Kick Horridon *3,374,517* - MEGADAMAGE

  3. #23
    The Lightbringer Requital's Avatar
    Join Date
    Jul 2007
    Location
    But-hurt much? Appears so!
    Posts
    3,880
    I like the script but it's currently spitting out.

    Haste = 7883
    Crit = 7884
    Mastery = 7885
    Hit = 2549
    Expertise = 2925

    I can't figure out why it's just going excessively high with expertise.
    Quote Originally Posted by Boubouille View Post
    Can you imagine if someone insulted you in a thread, you reported it, and I told you "sorry, wrong thread to be butthurt"?

  4. #24
    Quote Originally Posted by Requital View Post
    I like the script but it's currently spitting out.

    Haste = 7883
    Crit = 7884
    Mastery = 7885
    Hit = 2549
    Expertise = 2925

    I can't figure out why it's just going excessively high with expertise.
    You sure you can actually reforge more expertise away? I'm usually finding myself insanely high on expertise when reforging for WW mainly because my mainspec is brewmaster and my gear generally has a lot of expertise on it. Expecially with rentaki trinket. Between tiers you can often find youself high on undesired stats.
    Keeyler - Antebellum - Nordrassil - EU
    Brewmaster Monk - Armory

  5. #25
    Quote Originally Posted by Requital View Post
    I like the script but it's currently spitting out.

    Haste = 7883
    Crit = 7884
    Mastery = 7885
    Hit = 2549
    Expertise = 2925

    I can't figure out why it's just going excessively high with expertise.
    The version I posted there was a bit dumb in the regard that I never told it to use pure agi gems if it was hopelessly over the exp cap (it was just only using exp gems and never using agi), I just assumed that the user (me) would be bright enough to make the change themself. I have since changed it to not be so dumb ;p. It now appropriately uses agi gems rather than exp gems when hopelessly over exp cap. I also tinkered with the stat weighing to make it penalize being under hit/exp cap a bit more harshly since I really hate being under.

    Also there was a bug with my picking a different glove enchant, that caused it to subtract 180 haste rather than 170 when not using the haste enchant, which essentially always made it choose to use the haste enchant.

    I've been rather lazy trying to get it to update from web. I think the libcurl library will give me the functionality I need but I was too dumb to figure out how to link it with my compiler so I could use it.

    Here is my (only slightly) updated code:

    Code:
    // WindwalkerReforge.c
    // Version 2.0.1
    // By Janxspirit AKA Keith C
    // Known bugs - Sometimes uses nonexistent gems (expertise+hit yellows, or haste+crit yellows), but since this hasn't actually happened I haven't fixed it yet (I just know it can in theory happen).
    // To do in future - Make character import from web, output gems used (makes you figure it out yourself ATM), optimize some dumb stuff and make comments
    
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    // The number of different types of sockets you have
    #define RED 4
    #define YELLOW 7
    #define BLUE 2
    
    // The value of your socket bonuses plus the 165 crit leg enchant and the 100 crit shoulder enchant and the 324p meta
    #define bcri 324+165+100
    #define bmas 120
    #define bhas 60
    #define bexp 0
    #define bhit 0
    
    // The total number of items/enchants
    // Don't fiddle with this, you'll break the program
    #define GEAR 18
    
    // The number of times to run the optimizer
    #define RUNS 500000
    
    // Input each row (piece of gear) as {haste,crit,mastery,hit,expertise,0}
    // Any time I get a new piece of gear I have to update the entry for it here in this gear array
    // To change to reforging someone else's character I would have to input all their gear
    // This is a very shitty way to input a character.  Would be better to use simcraft to import from armory and then parse that output file.
    // If a piece of gear does not exist (or if it is a pure agi trink) input -1 in the 6th (last) column
    int gear[GEAR][6] = {
    // Input gear UNREFORGED
    // 0=Head
    {719,0,741,0,0,0},
    // 1=Neck
    {613,0,0,522,0,0},
    // 2=Shoulder
    {776,0,776,0,0,0},
    // 3=Back
    {0,0,588,0,564,0},
    // 4=Chest
    {0,1161,0,977,0,0},
    // 5=Wrist
    {569,525,0,0,0,0},
    // 6=Hands
    {0,747,0,0,701,0},
    // 7=Waist
    {732,0,0,732,0,0},
    // 8=Legs
    {0,758,0,1077,0,0},
    // 9=Feet
    {0,724,740,0,0,0},
    // 10=Ring 1
    {654,0,654,0,0,0},
    // 11=Ring 2
    {0,494,629,0,0,0},
    // 12=Weapon 1
    {425,372,0,0,0,0},
    // 13=Weapon 2
    {0,479,0,0,333,0},
    // 14=Trinket 1
    {0,0,0,0,1657,0},
    // 15=Trinket 2
    {0,0,0,0,0,-1},
    // Don't change these two enchants even if you are using different ones.  Doing so will break the program.
    // 16=Glove enchant
    {170,0,0,0,0,0},
    // 17=Cloak enchant
    {0,180,0,0,0,0}
    };
    
    int best[GEAR],best2[GEAR],globalflag=0;
    
    double bestval=0.0,bestval2=0.0;
    
    double reforge(void);
    int score(void);
    void results(void);
    
    int main(void){
        long int i,j;
        
        srand(time(NULL));
        
        // The program works by throwing darts at a dart board, where the dart board is the space of possible reforges
        // and the darts are random reforges.  For each dart it then makes any changes that would improve the dart
        // so each dart is a local maximum.  It remembers the dart that is the biggest local maximum and thats the answer
        // 100k darts takes about 25 seconds on my computer to run
        // I recommend 1000k darts
        for(i=0;i<RUNS;i++){
            reforge();
            if(bestval>bestval2){
                bestval2=bestval;
                for(j=0;j<GEAR;j++) best2[j]=best[j];
                printf("NEW HIGH - %lf\n",bestval2);
            }
        }
        printf("END O_O %lf\n",bestval2);
        for(i=0;i<GEAR;i++) gear[i][5]=best2[i];
        results();
        while(1);
    }
    
    // This function does 1 dart throw
    double reforge(void){
        int flag=1,i,j,k,temp;
        // Pick a random starting point
        for(i=0;i<GEAR;i++){
            if(gear[i][5]!=-1) gear[i][5]=rand()%7;
        }
        // Note the score
        bestval=0;
        score();
        // Attempt to find a local maxima... it tries to do this by going through all possible single reforges in a randomish order
        // the random order is not really very random at all, I just did a bit of work to make it not always the same order
        // if it makes an improvement it starts over again until it can't make an improvement any more
        while(flag){
            flag=0;
            k=rand()%GEAR;
            for(i=k;i<k+GEAR;i++){
                for(j=1;j<8;j++){
                    if(gear[i%GEAR][5]!=-1) gear[i%GEAR][5]=(gear[i%GEAR][5]+j)%7;
                    if(score()){
                        j=8;
                        i=k+GEAR;
                        flag=1;
                    }
                }
            }
        }
    }
    
    // This function checks to see how good a reforge is
    int score(void){
        // This is initialization based on enchants and gems... very shoddy needs improving and allowance for gem optimization
        int stats[5]={0,0,0,0,0};
        int i,j,k,source,destination,flag,gemsused=0;
        double pts=0.0;
        // Initialize the gear, before reforges... this can be optimized to run faster since these are constant values
        for(i=0;i<GEAR;i++){
            for(j=0;j<5;j++){
                stats[j]+=gear[i][j];
            }
        }
        // Account for socket bonuses and the leg enchant
        stats[0]+=bhas;
        stats[1]+=bcri;
        stats[2]+=bmas;
        stats[3]+=bhit;
        stats[4]+=bexp;
        // Use at least 160 exp from reds gems and 160 hit from blues
        stats[3]+=BLUE*160;
        stats[4]+=RED*160;
        // Reforge gear (other than trinkets)
        for(i=0;i<14;i++){
            if(gear[i][5]>0){
                // find source
                if(gear[i][5]<4){
                    // first nonzero stat
                    k=0;
                    while(gear[i][k]==0) k++;
                }else{
                    // last nonzero stat
                    k=0;
                    while(gear[i][4-k]==0) k++;
                    k=4-k;
                }
                source = k;
                // find destination
                k=0;
                flag=(gear[i][5]-1)%3+1;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reforge the trinkets
        for(i=14;i<16;i++){
            if(gear[i][5]>0){
                // find source
                k=0;
                while(gear[i][k]==0) k++;
                source = k;
                // find destination
                k=0;
                flag=gear[i][5];
                if(flag>4)flag-=4;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reenchant the gloves
        if(gear[16][5]%3==1){stats[2]+=170;stats[0]-=170;}
        if(gear[16][5]%3==2){stats[4]+=170;stats[0]-=170;}
        // Reenchant the cloak
        if(gear[17][5]%2==1){stats[3]+=180;stats[1]-=180;}
        if(globalflag){
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
        }
        // Use gems! In a windwalkery way
        while(gemsused<RED+BLUE+YELLOW*2){
            //Use a red gem
            if(gemsused<RED){
                if(stats[4]<2470){
                    stats[4]+=160;
                }else{
                    if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                        if(stats[0]>stats[1]) stats[1]+=160;
                        else                  stats[0]+=160;
                    }else{
                        stats[2]+=160;
                    }
                }
            }else{
                // Use a blue gem
                if(gemsused<RED+BLUE){
                    if(stats[3]<2510){
                        stats[3]+=160;
                    }else{
                        if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                            if(stats[0]>stats[1]) stats[1]+=160;
                            else                  stats[0]+=160;
                        }else{
                            stats[2]+=160;
                        }
                    }
                }else{
                    //Use a yellow gem
                    if(stats[3]<2510){
                        stats[3]+=160;
                    }else{
                        if(stats[4]<2470){
                            stats[4]+=160;
                        }else{
                            if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                                if(stats[0]>stats[1]) stats[1]+=160;
                                else                  stats[0]+=160;
                            }else{
                                stats[2]+=160;
                            }
                        }
                    }
                }
            }
            gemsused++;
        }
        gemsused=0;
        while(gemsused<RED&&stats[4]>2630){
            stats[4]-=160;
            pts+=300;
            gemsused++;
        }
        
        // determine score
        // if you were going to adapt this program for a different class, you would need to change the following few lines of code
        if(stats[4]<2550) pts-=(2550-stats[4])*5;
        if(stats[4]>2550) pts-=(stats[4]-2550)*2;
        if(stats[3]<2550) pts-=(2550-stats[3])*7;
        if(stats[3]>2550) pts-=(stats[3]-2550)*1;
        pts+=stats[0]*3;
        pts+=stats[1]*3;
        if(stats[0]>=stats[2]||stats[1]>=stats[2]) pts*=-1;
        if(globalflag){
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
        }
        //save score if it is good
        if(pts>bestval){
            bestval=pts;
            for(i=0;i<GEAR;i++) best[i]=gear[i][5];
            return(1);
        }
        return(0);
    }
    
    // This function just prints out the found solution
    void results(void){
        int i,k,flag,source,destination;
        for(i=0;i<16;i++){
            switch(i){
                case 0:
                printf("Head - ");
                break;
                case 1:
                printf("Neck - ");
                break;
                case 2:
                printf("Shoulder - ");
                break;
                case 3:
                printf("Back - ");
                break;
                case 4:
                printf("Chest - ");
                break;
                case 5:
                printf("Wrist - ");
                break;
                case 6:
                printf("Hands - ");
                break;
                case 7:
                printf("Waist - ");
                break;
                case 8:
                printf("Legs - ");
                break;
                case 9:
                printf("Feet - ");
                break;
                case 10:
                printf("Ring1 - ");
                break;
                case 11:
                printf("Ring2 - ");
                break;
                case 12:
                printf("Weapon1 - ");
                break;
                case 13:
                printf("Weapon2 - ");
                break;
                case 14:
                printf("Trinket1 - ");
                break;
                case 15:
                printf("Trinket2 - ");
                break;
            }
            if(best2[i]<1){
                printf("No reforge\n");
            }else{
                if(i<14){
                    // find source
                    if(best2[i]<4){
                        // first nonzero stat
                        k=0;
                        while(gear[i][k]==0) k++;
                    }else{
                        // last nonzero stat
                        k=0;
                        while(gear[i][4-k]==0) k++;
                        k=4-k;
                    }
                    source = k;
                    // find destination
                    k=0;
                    flag=(best2[i]-1)%3+1;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }else{
                    // find source
                    k=0;
                    while(gear[i][k]==0) k++;
                    source = k;
                    // find destination
                    k=0;
                    flag=best2[i];
                    if(flag>4)flag-=4;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }
                printf("Reforge out of ");
                switch(source){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf(" and into ");
                switch(destination){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf("\n");
            }
        }
        printf("Enchant gloves with 170 ");
        if(gear[16][5]%3==0) printf("haste\n");
        if(gear[16][5]%3==1) printf("mastery\n");
        if(gear[16][5]%3==2) printf("expertise\n");
        printf("Enchant cloak with 180 ");
        if(gear[17][5]%2==0) printf("crit\n");
        if(gear[17][5]%2==1) printf("hit\n");
        globalflag=1;
        score();
    }
    I actually do have the RoRo myself now, and have used the program once on myself, and it worked quite well. I'm at 6760 haste, 6761 crit, 6763 mastery, 2559 hit and 2555 expertise ^^. It had to change my glove enchant to get this solution, which is something that most other reforge solvers just don't do.
    Last edited by keithioapc; 2013-04-23 at 03:43 PM.
    WW Monk - Janxspirit @ US-Illidan
    [20:14:20.744] Janxspirit Rising Sun Kick Horridon *3,374,517* - MEGADAMAGE

  6. #26
    I am the developer of Catus (Feral simulator). Catus has a one-click armory import and 1:1:1 Rune reforger. Currently, Catus has a class restriction on import (only Druids) but I will be relaxing this soon:
    fluiddruid.net/forum/viewtopic.php?f=3&t=4574 (apparently I cannot post links)

  7. #27
    How does your program deal with prismatic sockets ?
    Or more precisely how do i tell him i have 2 prismatic sockets on my weapons ?

  8. #28
    Quote Originally Posted by Porcinet View Post
    How does your program deal with prismatic sockets ?
    Or more precisely how do i tell him i have 2 prismatic sockets on my weapons ?
    Just call them yellow sockets, because yellow sockets are sexy.
    WW Monk - Janxspirit @ US-Illidan
    [20:14:20.744] Janxspirit Rising Sun Kick Horridon *3,374,517* - MEGADAMAGE

  9. #29
    The Lightbringer Requital's Avatar
    Join Date
    Jul 2007
    Location
    But-hurt much? Appears so!
    Posts
    3,880
    Quote Originally Posted by Keeyla View Post
    You sure you can actually reforge more expertise away? I'm usually finding myself insanely high on expertise when reforging for WW mainly because my mainspec is brewmaster and my gear generally has a lot of expertise on it. Expecially with rentaki trinket. Between tiers you can often find youself high on undesired stats.
    Ya i'm actually really close to the Exp cap, After a lot of manual work I came up with.

    Crit - 7809, Exp -2552, Haste - 7786, Hit - 2553, Mastery - 7950

    I think I might be able to get better values with the program but it's confused with Expertise.

    ---------- Post added 2013-04-24 at 06:22 AM ----------

    Quote Originally Posted by keithioapc View Post
    The version I posted there was a bit dumb in the regard that I never told it to use pure agi gems if it was hopelessly over the exp cap (it was just only using exp gems and never using agi), I just assumed that the user (me) would be bright enough to make the change themself. I have since changed it to not be so dumb ;p. It now appropriately uses agi gems rather than exp gems when hopelessly over exp cap. I also tinkered with the stat weighing to make it penalize being under hit/exp cap a bit more harshly since I really hate being under.

    Also there was a bug with my picking a different glove enchant, that caused it to subtract 180 haste rather than 170 when not using the haste enchant, which essentially always made it choose to use the haste enchant.

    I've been rather lazy trying to get it to update from web. I think the libcurl library will give me the functionality I need but I was too dumb to figure out how to link it with my compiler so I could use it.

    Here is my (only slightly) updated code:

    Code:
    // WindwalkerReforge.c
    // Version 2.0.1
    // By Janxspirit AKA Keith C
    // Known bugs - Sometimes uses nonexistent gems (expertise+hit yellows, or haste+crit yellows), but since this hasn't actually happened I haven't fixed it yet (I just know it can in theory happen).
    // To do in future - Make character import from web, output gems used (makes you figure it out yourself ATM), optimize some dumb stuff and make comments
    
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    // The number of different types of sockets you have
    #define RED 4
    #define YELLOW 7
    #define BLUE 2
    
    // The value of your socket bonuses plus the 165 crit leg enchant and the 100 crit shoulder enchant and the 324p meta
    #define bcri 324+165+100
    #define bmas 120
    #define bhas 60
    #define bexp 0
    #define bhit 0
    
    // The total number of items/enchants
    // Don't fiddle with this, you'll break the program
    #define GEAR 18
    
    // The number of times to run the optimizer
    #define RUNS 500000
    
    // Input each row (piece of gear) as {haste,crit,mastery,hit,expertise,0}
    // Any time I get a new piece of gear I have to update the entry for it here in this gear array
    // To change to reforging someone else's character I would have to input all their gear
    // This is a very shitty way to input a character.  Would be better to use simcraft to import from armory and then parse that output file.
    // If a piece of gear does not exist (or if it is a pure agi trink) input -1 in the 6th (last) column
    int gear[GEAR][6] = {
    // Input gear UNREFORGED
    // 0=Head
    {719,0,741,0,0,0},
    // 1=Neck
    {613,0,0,522,0,0},
    // 2=Shoulder
    {776,0,776,0,0,0},
    // 3=Back
    {0,0,588,0,564,0},
    // 4=Chest
    {0,1161,0,977,0,0},
    // 5=Wrist
    {569,525,0,0,0,0},
    // 6=Hands
    {0,747,0,0,701,0},
    // 7=Waist
    {732,0,0,732,0,0},
    // 8=Legs
    {0,758,0,1077,0,0},
    // 9=Feet
    {0,724,740,0,0,0},
    // 10=Ring 1
    {654,0,654,0,0,0},
    // 11=Ring 2
    {0,494,629,0,0,0},
    // 12=Weapon 1
    {425,372,0,0,0,0},
    // 13=Weapon 2
    {0,479,0,0,333,0},
    // 14=Trinket 1
    {0,0,0,0,1657,0},
    // 15=Trinket 2
    {0,0,0,0,0,-1},
    // Don't change these two enchants even if you are using different ones.  Doing so will break the program.
    // 16=Glove enchant
    {170,0,0,0,0,0},
    // 17=Cloak enchant
    {0,180,0,0,0,0}
    };
    
    int best[GEAR],best2[GEAR],globalflag=0;
    
    double bestval=0.0,bestval2=0.0;
    
    double reforge(void);
    int score(void);
    void results(void);
    
    int main(void){
        long int i,j;
        
        srand(time(NULL));
        
        // The program works by throwing darts at a dart board, where the dart board is the space of possible reforges
        // and the darts are random reforges.  For each dart it then makes any changes that would improve the dart
        // so each dart is a local maximum.  It remembers the dart that is the biggest local maximum and thats the answer
        // 100k darts takes about 25 seconds on my computer to run
        // I recommend 1000k darts
        for(i=0;i<RUNS;i++){
            reforge();
            if(bestval>bestval2){
                bestval2=bestval;
                for(j=0;j<GEAR;j++) best2[j]=best[j];
                printf("NEW HIGH - %lf\n",bestval2);
            }
        }
        printf("END O_O %lf\n",bestval2);
        for(i=0;i<GEAR;i++) gear[i][5]=best2[i];
        results();
        while(1);
    }
    
    // This function does 1 dart throw
    double reforge(void){
        int flag=1,i,j,k,temp;
        // Pick a random starting point
        for(i=0;i<GEAR;i++){
            if(gear[i][5]!=-1) gear[i][5]=rand()%7;
        }
        // Note the score
        bestval=0;
        score();
        // Attempt to find a local maxima... it tries to do this by going through all possible single reforges in a randomish order
        // the random order is not really very random at all, I just did a bit of work to make it not always the same order
        // if it makes an improvement it starts over again until it can't make an improvement any more
        while(flag){
            flag=0;
            k=rand()%GEAR;
            for(i=k;i<k+GEAR;i++){
                for(j=1;j<8;j++){
                    if(gear[i%GEAR][5]!=-1) gear[i%GEAR][5]=(gear[i%GEAR][5]+j)%7;
                    if(score()){
                        j=8;
                        i=k+GEAR;
                        flag=1;
                    }
                }
            }
        }
    }
    
    // This function checks to see how good a reforge is
    int score(void){
        // This is initialization based on enchants and gems... very shoddy needs improving and allowance for gem optimization
        int stats[5]={0,0,0,0,0};
        int i,j,k,source,destination,flag,gemsused=0;
        double pts=0.0;
        // Initialize the gear, before reforges... this can be optimized to run faster since these are constant values
        for(i=0;i<GEAR;i++){
            for(j=0;j<5;j++){
                stats[j]+=gear[i][j];
            }
        }
        // Account for socket bonuses and the leg enchant
        stats[0]+=bhas;
        stats[1]+=bcri;
        stats[2]+=bmas;
        stats[3]+=bhit;
        stats[4]+=bexp;
        // Use at least 160 exp from reds gems and 160 hit from blues
        stats[3]+=BLUE*160;
        stats[4]+=RED*160;
        // Reforge gear (other than trinkets)
        for(i=0;i<14;i++){
            if(gear[i][5]>0){
                // find source
                if(gear[i][5]<4){
                    // first nonzero stat
                    k=0;
                    while(gear[i][k]==0) k++;
                }else{
                    // last nonzero stat
                    k=0;
                    while(gear[i][4-k]==0) k++;
                    k=4-k;
                }
                source = k;
                // find destination
                k=0;
                flag=(gear[i][5]-1)%3+1;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reforge the trinkets
        for(i=14;i<16;i++){
            if(gear[i][5]>0){
                // find source
                k=0;
                while(gear[i][k]==0) k++;
                source = k;
                // find destination
                k=0;
                flag=gear[i][5];
                if(flag>4)flag-=4;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reenchant the gloves
        if(gear[16][5]%3==1){stats[2]+=170;stats[0]-=170;}
        if(gear[16][5]%3==2){stats[4]+=170;stats[0]-=170;}
        // Reenchant the cloak
        if(gear[17][5]%2==1){stats[3]+=180;stats[1]-=180;}
        if(globalflag){
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
        }
        // Use gems! In a windwalkery way
        while(gemsused<RED+BLUE+YELLOW*2){
            //Use a red gem
            if(gemsused<RED){
                if(stats[4]<2470){
                    stats[4]+=160;
                }else{
                    if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                        if(stats[0]>stats[1]) stats[1]+=160;
                        else                  stats[0]+=160;
                    }else{
                        stats[2]+=160;
                    }
                }
            }else{
                // Use a blue gem
                if(gemsused<RED+BLUE){
                    if(stats[3]<2510){
                        stats[3]+=160;
                    }else{
                        if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                            if(stats[0]>stats[1]) stats[1]+=160;
                            else                  stats[0]+=160;
                        }else{
                            stats[2]+=160;
                        }
                    }
                }else{
                    //Use a yellow gem
                    if(stats[3]<2510){
                        stats[3]+=160;
                    }else{
                        if(stats[4]<2470){
                            stats[4]+=160;
                        }else{
                            if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                                if(stats[0]>stats[1]) stats[1]+=160;
                                else                  stats[0]+=160;
                            }else{
                                stats[2]+=160;
                            }
                        }
                    }
                }
            }
            gemsused++;
        }
        gemsused=0;
        while(gemsused<RED&&stats[4]>2630){
            stats[4]-=160;
            pts+=300;
            gemsused++;
        }
        
        // determine score
        // if you were going to adapt this program for a different class, you would need to change the following few lines of code
        if(stats[4]<2550) pts-=(2550-stats[4])*5;
        if(stats[4]>2550) pts-=(stats[4]-2550)*2;
        if(stats[3]<2550) pts-=(2550-stats[3])*7;
        if(stats[3]>2550) pts-=(stats[3]-2550)*1;
        pts+=stats[0]*3;
        pts+=stats[1]*3;
        if(stats[0]>=stats[2]||stats[1]>=stats[2]) pts*=-1;
        if(globalflag){
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
        }
        //save score if it is good
        if(pts>bestval){
            bestval=pts;
            for(i=0;i<GEAR;i++) best[i]=gear[i][5];
            return(1);
        }
        return(0);
    }
    
    // This function just prints out the found solution
    void results(void){
        int i,k,flag,source,destination;
        for(i=0;i<16;i++){
            switch(i){
                case 0:
                printf("Head - ");
                break;
                case 1:
                printf("Neck - ");
                break;
                case 2:
                printf("Shoulder - ");
                break;
                case 3:
                printf("Back - ");
                break;
                case 4:
                printf("Chest - ");
                break;
                case 5:
                printf("Wrist - ");
                break;
                case 6:
                printf("Hands - ");
                break;
                case 7:
                printf("Waist - ");
                break;
                case 8:
                printf("Legs - ");
                break;
                case 9:
                printf("Feet - ");
                break;
                case 10:
                printf("Ring1 - ");
                break;
                case 11:
                printf("Ring2 - ");
                break;
                case 12:
                printf("Weapon1 - ");
                break;
                case 13:
                printf("Weapon2 - ");
                break;
                case 14:
                printf("Trinket1 - ");
                break;
                case 15:
                printf("Trinket2 - ");
                break;
            }
            if(best2[i]<1){
                printf("No reforge\n");
            }else{
                if(i<14){
                    // find source
                    if(best2[i]<4){
                        // first nonzero stat
                        k=0;
                        while(gear[i][k]==0) k++;
                    }else{
                        // last nonzero stat
                        k=0;
                        while(gear[i][4-k]==0) k++;
                        k=4-k;
                    }
                    source = k;
                    // find destination
                    k=0;
                    flag=(best2[i]-1)%3+1;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }else{
                    // find source
                    k=0;
                    while(gear[i][k]==0) k++;
                    source = k;
                    // find destination
                    k=0;
                    flag=best2[i];
                    if(flag>4)flag-=4;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }
                printf("Reforge out of ");
                switch(source){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf(" and into ");
                switch(destination){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf("\n");
            }
        }
        printf("Enchant gloves with 170 ");
        if(gear[16][5]%3==0) printf("haste\n");
        if(gear[16][5]%3==1) printf("mastery\n");
        if(gear[16][5]%3==2) printf("expertise\n");
        printf("Enchant cloak with 180 ");
        if(gear[17][5]%2==0) printf("crit\n");
        if(gear[17][5]%2==1) printf("hit\n");
        globalflag=1;
        score();
    }
    I actually do have the RoRo myself now, and have used the program once on myself, and it worked quite well. I'm at 6760 haste, 6761 crit, 6763 mastery, 2559 hit and 2555 expertise ^^. It had to change my glove enchant to get this solution, which is something that most other reforge solvers just don't do.
    Another thing, Clock and glove enchant how does it handle them? Gems what is it using as it wasn't printing out anything about gems.

    I took your updated work and tried it again, I'm wondering if something is failing when it's being run. Here are the results that I see when I run it.

    NEW HIGH - 46404.000000
    NEW HIGH - 46464.000000
    NEW HIGH - 46479.000000
    NEW HIGH - 46488.000000
    NEW HIGH - 46520.000000
    NEW HIGH - 46524.000000
    NEW HIGH - 46527.000000
    NEW HIGH - 46533.000000
    NEW HIGH - 46539.000000
    NEW HIGH - 46542.000000
    NEW HIGH - 46545.000000
    NEW HIGH - 46548.000000
    END O_O 46548.000000
    Head - Reforge out of hit and into mastery
    Neck - Reforge out of hit and into crit
    Shoulder - No reforge
    Back - Reforge out of crit and into haste
    Chest - Reforge out of mastery and into haste
    Wrist - Reforge out of haste and into mastery
    Hands - Reforge out of expertise and into mastery
    Waist - Reforge out of expertise and into crit
    Legs - No reforge
    Feet - Reforge out of crit and into haste
    Ring1 - No reforge
    Ring2 - Reforge out of crit and into mastery
    Weapon1 - Reforge out of expertise and into crit
    Weapon2 - Reforge out of haste and into hit
    Trinket1 - Reforge out of expertise and into haste
    Trinket2 - No reforge
    Enchant gloves with 170 haste
    Enchant cloak with 180 crit
    Haste = 6763
    Crit = 6284
    Mastery = 5965
    Hit = 2229
    Expertise = 2925
    Haste = 7883
    Crit = 7884
    Mastery = 7885
    Hit = 2549
    Expertise = 2925

    That is where it ends, It never goes any further. Should it be?
    Last edited by Requital; 2013-04-24 at 06:52 AM.
    Quote Originally Posted by Boubouille View Post
    Can you imagine if someone insulted you in a thread, you reported it, and I told you "sorry, wrong thread to be butthurt"?

  10. #30
    Well, the algorithm considers the cloak and glove enchants to kind of be the same as a piece of gear that you can reforge. Only, rather than working as a normal reforge, your only options are to reforge 100% of it into one of the other stats that you could possibly have enchanted it with.

    When the output says "enchant cloak with...", that is enchant it decided to use in the end.

    For what gems to use, the program is bad and doesn't really tell you clearly what it did. You notice how at the end it lists two sets of stats, the one is the stats early in the gemming process and the other is the stats after regemming. I look at the two to figure out what gems it used. I think today I will actually improve it to make it easier to figure out the gems since it has been inconvenient for me.

    As for your bad output regards expertise, can you paste the code as you ran it? My suspicion is that the gear array you input simply contains a lot of expertise. Perhaps you didn't edit the trinket 1 slot, which in the version I pasted has 1657 expertise from the 535 renatakis (the trink I use). The only reason I think it would give results with that much expertise is if you simply input too much expertise into it in the first place, but post your version of the code so I can check it out. That's really the #1 big problem from manual input, not the inconvenience but the chance for user error.

    And yes, that is the end of output. I'll put a line saying that. My the program ends in an infinite loop rather than a proper end, just to avoid closing on exit.

    ---------- Post added 2013-04-24 at 02:57 PM ----------

    Here is my latest version that now does a better job of telling you how to change your gems, rather than making you figure out how the program gemmed yourself:

    Code:
    // WindwalkerReforge.c
    // Version 2.0.2
    // By Janxspirit AKA Keith C
    // Known bugs - Sometimes uses nonexistent gems (expertise+hit yellows, or haste+crit yellows), but since this hasn't actually happened I haven't fixed it yet (I just know it can in theory happen).
    // To do in future - Make character import from web, optimize some dumb stuff and make comments
    
    // NEW SECTION ADDED RIGHT HERE!
    // This is an optional section.  You say how much stats you are getting from your gems.
    // It will NOT affect the optimizer, the only thing it changes is it uses these numbers to tell you
    // what the change in your gemming needs to be.
    // Remember if you do not input the stats you have from gems, the reforge solution from the program will still be correct
    // but where it tells you the change in gems WILL BE WRONG
    // Note that this section has NOTHING to do with gem socket bonuses, only the stats from gems you are using
    //
    // USE_GEM_TIPS should be set to 1 if you want the output to tell you the change in how to gem, or 0 if you do not want this feature
    #define USE_GEM_TIPS 1
    // Count every 80 you have from agi gems as 1 for agi, and every 160 for other stats as 1
    // In other words a 160expertise&160crit gem would count as +1 CRIT_FROM_GEMS and +1 EXP_FROM_GEMS, and a +320 haste gem would be +2 haste or a +160 agi gem would be +2 agi
    // I did it this way because I found it easy to count, if you don't BOLLOCKS TO YOU!
    #define AGI_FROM_GEMS 1
    #define EXP_FROM_GEMS 2
    #define HASTE_FROM_GEMS 9
    #define CRIT_FROM_GEMS 5
    #define MAST_FROM_GEMS 7
    #define HIT_FROM_GEMS 2
    // If I ever get around to uploading from armory, the above section needs to be parsed rather than input.
    
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    // The number of different types of sockets you have
    #define RED 3
    #define YELLOW 8
    #define BLUE 2
    
    // The value of your socket bonuses plus the 165 crit leg enchant and the 100 crit shoulder enchant and the 324p meta
    #define bcri 324+165+100
    #define bmas 120
    #define bhas 60
    #define bexp 0
    #define bhit 0
    
    // The total number of items/enchants
    // Don't fiddle with this, you'll break the program
    #define GEAR 18
    
    // The number of times to run the optimizer
    #define RUNS 100000
    
    // Input each row (piece of gear) as {haste,crit,mastery,hit,expertise,0}
    // Any time I get a new piece of gear I have to update the entry for it here in this gear array
    // To change to reforging someone else's character I would have to input all their gear
    // This is a very shitty way to input a character.  Would be better to use simcraft to import from armory and then parse that output file.
    // If a piece of gear does not exist (or if it is a pure agi trink) input -1 in the 6th (last) column
    int gear[GEAR][6] = {
    // Input gear UNREFORGED
    // 0=Head
    {719,0,741,0,0,0},
    // 1=Neck
    {613,0,0,522,0,0},
    // 2=Shoulder
    {776,0,776,0,0,0},
    // 3=Back
    {0,0,588,0,564,0},
    // 4=Chest
    {0,1161,0,977,0,0},
    // 5=Wrist
    {569,525,0,0,0,0},
    // 6=Hands
    {0,747,0,0,701,0},
    // 7=Waist
    {732,0,0,732,0,0},
    // 8=Legs
    {1103,0,1070,0,0,0},
    // 9=Feet
    {0,724,740,0,0,0},
    // 10=Ring 1
    {654,0,654,0,0,0},
    // 11=Ring 2
    {0,494,629,0,0,0},
    // 12=Weapon 1
    {425,372,0,0,0,0},
    // 13=Weapon 2
    {0,479,0,0,333,0},
    // 14=Trinket 1
    {0,0,0,0,1657,0},
    // 15=Trinket 2
    {0,0,0,0,0,-1},
    // Don't change these two enchants even if you are using different ones.  Doing so will break the program.
    // 16=Glove enchant
    {170,0,0,0,0,0},
    // 17=Cloak enchant
    {0,180,0,0,0,0}
    };
    
    int best[GEAR],best2[GEAR],globalflag=0;
    
    double bestval=0.0,bestval2=0.0;
    
    double reforge(void);
    int score(void);
    void results(void);
    
    int main(void){
        long int i,j;
        
        srand(time(NULL));
        
        // The program works by throwing darts at a dart board, where the dart board is the space of possible reforges
        // and the darts are random reforges.  For each dart it then makes any changes that would improve the dart
        // so each dart is a local maximum.  It remembers the dart that is the biggest local maximum and thats the answer
        // 100k darts takes about 25 seconds on my computer to run
        // I recommend 1000k darts
        for(i=0;i<RUNS;i++){
            reforge();
            if(bestval>bestval2){
                bestval2=bestval;
                for(j=0;j<GEAR;j++) best2[j]=best[j];
                printf("NEW HIGH - %lf\n",bestval2);
            }
        }
        printf("END O_O %lf\n",bestval2);
        for(i=0;i<GEAR;i++) gear[i][5]=best2[i];
        results();
        printf("\nThe program has finished running and is now in an infinite loop for your convenience.\n");
        while(1);
    }
    
    // This function does 1 dart throw
    double reforge(void){
        int flag=1,i,j,k,temp;
        // Pick a random starting point
        for(i=0;i<GEAR;i++){
            if(gear[i][5]!=-1) gear[i][5]=rand()%7;
        }
        // Note the score
        bestval=0;
        score();
        // Attempt to find a local maxima... it tries to do this by going through all possible single reforges in a randomish order
        // the random order is not really very random at all, I just did a bit of work to make it not always the same order
        // if it makes an improvement it starts over again until it can't make an improvement any more
        while(flag){
            flag=0;
            k=rand()%GEAR;
            for(i=k;i<k+GEAR;i++){
                for(j=1;j<8;j++){
                    if(gear[i%GEAR][5]!=-1) gear[i%GEAR][5]=(gear[i%GEAR][5]+j)%7;
                    if(score()){
                        j=8;
                        i=k+GEAR;
                        flag=1;
                    }
                }
            }
        }
    }
    
    // This function checks to see how good a reforge is
    int score(void){
        // This is initialization based on enchants and gems... very shoddy needs improving and allowance for gem optimization
        int stats[5]={0,0,0,0,0};
        int gemstats[6]={0,0,0,0,0,0};
        int i,j,k,source,destination,flag,gemsused=0;
        double pts=0.0;
        // Initialize the gear, before reforges... this can be optimized to run faster since these are constant values
        for(i=0;i<GEAR;i++){
            for(j=0;j<5;j++){
                stats[j]+=gear[i][j];
            }
        }
        // Account for socket bonuses and the leg enchant
        stats[0]+=bhas;
        stats[1]+=bcri;
        stats[2]+=bmas;
        stats[3]+=bhit;
        stats[4]+=bexp;
        // Use at least 160 exp from reds gems and 160 hit from blues
        stats[3]+=BLUE*160;
        gemstats[3]+=BLUE*160;
        stats[4]+=RED*160;
        gemstats[4]+=RED*160;
        // Reforge gear (other than trinkets)
        for(i=0;i<14;i++){
            if(gear[i][5]>0){
                // find source
                if(gear[i][5]<4){
                    // first nonzero stat
                    k=0;
                    while(gear[i][k]==0) k++;
                }else{
                    // last nonzero stat
                    k=0;
                    while(gear[i][4-k]==0) k++;
                    k=4-k;
                }
                source = k;
                // find destination
                k=0;
                flag=(gear[i][5]-1)%3+1;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reforge the trinkets
        for(i=14;i<16;i++){
            if(gear[i][5]>0){
                // find source
                k=0;
                while(gear[i][k]==0) k++;
                source = k;
                // find destination
                k=0;
                flag=gear[i][5];
                if(flag>4)flag-=4;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reenchant the gloves
        if(gear[16][5]%3==1){stats[2]+=170;stats[0]-=170;}
        if(gear[16][5]%3==2){stats[4]+=170;stats[0]-=170;}
        // Reenchant the cloak
        if(gear[17][5]%2==1){stats[3]+=180;stats[1]-=180;}
        // Use gems! In a windwalkery way
        while(gemsused<RED+BLUE+YELLOW*2){
            //Use a red gem
            if(gemsused<RED){
                if(stats[4]<2470){
                    stats[4]+=160;
                    gemstats[4]+=160;
                }else{
                    if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                        if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                        else                  {stats[0]+=160;gemstats[0]+=160;}
                    }else{
                        stats[2]+=160;gemstats[2]+=160;
                    }
                }
            }else{
                // Use a blue gem
                if(gemsused<RED+BLUE){
                    if(stats[3]<2510){
                        stats[3]+=160;gemstats[3]+=160;
                    }else{
                        if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                            if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                            else                  {stats[0]+=160;gemstats[0]+=160;}
                        }else{
                            stats[2]+=160;gemstats[2]+=160;
                        }
                    }
                }else{
                    //Use a yellow gem
                    if(stats[3]<2510){
                        stats[3]+=160;gemstats[3]+=160;
                    }else{
                        if(stats[4]<2470){
                            stats[4]+=160;gemstats[4]+=160;
                        }else{
                            if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                                if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                                else                  {stats[0]+=160;gemstats[0]+=160;}
                            }else{
                                stats[2]+=160;gemstats[2]+=160;
                            }
                        }
                    }
                }
            }
            gemsused++;
        }
        gemsused=0;
        while(gemsused<RED&&stats[4]>2630){
            stats[4]-=160;gemstats[4]-=160;gemstats[5]+=80;
            pts+=300;
            gemsused++;
        }
        
        // determine score
        // if you were going to adapt this program for a different class, you would need to change the following few lines of code
        if(stats[4]<2550) pts-=(2550-stats[4])*5;
        if(stats[4]>2550) pts-=(stats[4]-2550)*2;
        if(stats[3]<2550) pts-=(2550-stats[3])*7;
        if(stats[3]>2550) pts-=(stats[3]-2550)*1;
        pts+=stats[0]*3;
        pts+=stats[1]*3;
        if(stats[0]>=stats[2]||stats[1]>=stats[2]) pts*=-1;
        if(globalflag){
            printf("\nFinal stats:\n");
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
            if(USE_GEM_TIPS==1){
                printf("\nChange in gemming:\n");
                if(gemstats[0]!=HASTE_FROM_GEMS*160) printf("%d haste\n",-HASTE_FROM_GEMS*160+gemstats[0]);
                if(gemstats[1]!=CRIT_FROM_GEMS*160) printf("%d crit\n",-CRIT_FROM_GEMS*160+gemstats[1]);
                if(gemstats[2]!=MAST_FROM_GEMS*160) printf("%d mastery\n",-MAST_FROM_GEMS*160+gemstats[2]);
                if(gemstats[3]!=HIT_FROM_GEMS*160) printf("%d hit\n",-HIT_FROM_GEMS*160+gemstats[3]);
                if(gemstats[4]!=EXP_FROM_GEMS*160) printf("%d expertise\n",-EXP_FROM_GEMS*160+gemstats[4]);
                if(gemstats[5]!=AGI_FROM_GEMS*80) printf("%d agility\n",-AGI_FROM_GEMS*80+gemstats[5]);
            }
        }
        //save score if it is good
        if(pts>bestval){
            bestval=pts;
            for(i=0;i<GEAR;i++) best[i]=gear[i][5];
            return(1);
        }
        return(0);
    }
    
    // This function just prints out the found solution
    void results(void){
        int i,k,flag,source,destination;
        for(i=0;i<16;i++){
            switch(i){
                case 0:
                printf("Head - ");
                break;
                case 1:
                printf("Neck - ");
                break;
                case 2:
                printf("Shoulder - ");
                break;
                case 3:
                printf("Back - ");
                break;
                case 4:
                printf("Chest - ");
                break;
                case 5:
                printf("Wrist - ");
                break;
                case 6:
                printf("Hands - ");
                break;
                case 7:
                printf("Waist - ");
                break;
                case 8:
                printf("Legs - ");
                break;
                case 9:
                printf("Feet - ");
                break;
                case 10:
                printf("Ring1 - ");
                break;
                case 11:
                printf("Ring2 - ");
                break;
                case 12:
                printf("Weapon1 - ");
                break;
                case 13:
                printf("Weapon2 - ");
                break;
                case 14:
                printf("Trinket1 - ");
                break;
                case 15:
                printf("Trinket2 - ");
                break;
            }
            if(best2[i]<1){
                printf("No reforge\n");
            }else{
                if(i<14){
                    // find source
                    if(best2[i]<4){
                        // first nonzero stat
                        k=0;
                        while(gear[i][k]==0) k++;
                    }else{
                        // last nonzero stat
                        k=0;
                        while(gear[i][4-k]==0) k++;
                        k=4-k;
                    }
                    source = k;
                    // find destination
                    k=0;
                    flag=(best2[i]-1)%3+1;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }else{
                    // find source
                    k=0;
                    while(gear[i][k]==0) k++;
                    source = k;
                    // find destination
                    k=0;
                    flag=best2[i];
                    if(flag>4)flag-=4;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }
                printf("Reforge out of ");
                switch(source){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf(" and into ");
                switch(destination){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf("\n");
            }
        }
        printf("Enchant gloves with 170 ");
        if(gear[16][5]%3==0) printf("haste\n");
        if(gear[16][5]%3==1) printf("mastery\n");
        if(gear[16][5]%3==2) printf("expertise\n");
        printf("Enchant cloak with 180 ");
        if(gear[17][5]%2==0) printf("crit\n");
        if(gear[17][5]%2==1) printf("hit\n");
        globalflag=1;
        score();
    }
    Here is a sample of what the gem output looks like:
    "Change in gemming:
    -640 haste
    320 crit
    160 mastery
    160 hit"
    WW Monk - Janxspirit @ US-Illidan
    [20:14:20.744] Janxspirit Rising Sun Kick Horridon *3,374,517* - MEGADAMAGE

  11. #31
    Quote Originally Posted by raffy View Post
    I am the developer of Catus (Feral simulator). Catus has a one-click armory import and 1:1:1 Rune reforger. Currently, Catus has a class restriction on import (only Druids) but I will be relaxing this soon:
    fluiddruid.net/forum/viewtopic.php?f=3&t=4574 (apparently I cannot post links)
    This would be great.

  12. #32
    The Lightbringer Requital's Avatar
    Join Date
    Jul 2007
    Location
    But-hurt much? Appears so!
    Posts
    3,880
    Quote Originally Posted by keithioapc View Post
    Well, the algorithm considers the cloak and glove enchants to kind of be the same as a piece of gear that you can reforge. Only, rather than working as a normal reforge, your only options are to reforge 100% of it into one of the other stats that you could possibly have enchanted it with.

    When the output says "enchant cloak with...", that is enchant it decided to use in the end.

    For what gems to use, the program is bad and doesn't really tell you clearly what it did. You notice how at the end it lists two sets of stats, the one is the stats early in the gemming process and the other is the stats after regemming. I look at the two to figure out what gems it used. I think today I will actually improve it to make it easier to figure out the gems since it has been inconvenient for me.

    As for your bad output regards expertise, can you paste the code as you ran it? My suspicion is that the gear array you input simply contains a lot of expertise. Perhaps you didn't edit the trinket 1 slot, which in the version I pasted has 1657 expertise from the 535 renatakis (the trink I use). The only reason I think it would give results with that much expertise is if you simply input too much expertise into it in the first place, but post your version of the code so I can check it out. That's really the #1 big problem from manual input, not the inconvenience but the chance for user error.

    And yes, that is the end of output. I'll put a line saying that. My the program ends in an infinite loop rather than a proper end, just to avoid closing on exit.

    ---------- Post added 2013-04-24 at 02:57 PM ----------

    Here is my latest version that now does a better job of telling you how to change your gems, rather than making you figure out how the program gemmed yourself:

    Code:
    // WindwalkerReforge.c
    // Version 2.0.2
    // By Janxspirit AKA Keith C
    // Known bugs - Sometimes uses nonexistent gems (expertise+hit yellows, or haste+crit yellows), but since this hasn't actually happened I haven't fixed it yet (I just know it can in theory happen).
    // To do in future - Make character import from web, optimize some dumb stuff and make comments
    
    // NEW SECTION ADDED RIGHT HERE!
    // This is an optional section.  You say how much stats you are getting from your gems.
    // It will NOT affect the optimizer, the only thing it changes is it uses these numbers to tell you
    // what the change in your gemming needs to be.
    // Remember if you do not input the stats you have from gems, the reforge solution from the program will still be correct
    // but where it tells you the change in gems WILL BE WRONG
    // Note that this section has NOTHING to do with gem socket bonuses, only the stats from gems you are using
    //
    // USE_GEM_TIPS should be set to 1 if you want the output to tell you the change in how to gem, or 0 if you do not want this feature
    #define USE_GEM_TIPS 1
    // Count every 80 you have from agi gems as 1 for agi, and every 160 for other stats as 1
    // In other words a 160expertise&160crit gem would count as +1 CRIT_FROM_GEMS and +1 EXP_FROM_GEMS, and a +320 haste gem would be +2 haste or a +160 agi gem would be +2 agi
    // I did it this way because I found it easy to count, if you don't BOLLOCKS TO YOU!
    #define AGI_FROM_GEMS 1
    #define EXP_FROM_GEMS 2
    #define HASTE_FROM_GEMS 9
    #define CRIT_FROM_GEMS 5
    #define MAST_FROM_GEMS 7
    #define HIT_FROM_GEMS 2
    // If I ever get around to uploading from armory, the above section needs to be parsed rather than input.
    
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    // The number of different types of sockets you have
    #define RED 3
    #define YELLOW 8
    #define BLUE 2
    
    // The value of your socket bonuses plus the 165 crit leg enchant and the 100 crit shoulder enchant and the 324p meta
    #define bcri 324+165+100
    #define bmas 120
    #define bhas 60
    #define bexp 0
    #define bhit 0
    
    // The total number of items/enchants
    // Don't fiddle with this, you'll break the program
    #define GEAR 18
    
    // The number of times to run the optimizer
    #define RUNS 100000
    
    // Input each row (piece of gear) as {haste,crit,mastery,hit,expertise,0}
    // Any time I get a new piece of gear I have to update the entry for it here in this gear array
    // To change to reforging someone else's character I would have to input all their gear
    // This is a very shitty way to input a character.  Would be better to use simcraft to import from armory and then parse that output file.
    // If a piece of gear does not exist (or if it is a pure agi trink) input -1 in the 6th (last) column
    int gear[GEAR][6] = {
    // Input gear UNREFORGED
    // 0=Head
    {719,0,741,0,0,0},
    // 1=Neck
    {613,0,0,522,0,0},
    // 2=Shoulder
    {776,0,776,0,0,0},
    // 3=Back
    {0,0,588,0,564,0},
    // 4=Chest
    {0,1161,0,977,0,0},
    // 5=Wrist
    {569,525,0,0,0,0},
    // 6=Hands
    {0,747,0,0,701,0},
    // 7=Waist
    {732,0,0,732,0,0},
    // 8=Legs
    {1103,0,1070,0,0,0},
    // 9=Feet
    {0,724,740,0,0,0},
    // 10=Ring 1
    {654,0,654,0,0,0},
    // 11=Ring 2
    {0,494,629,0,0,0},
    // 12=Weapon 1
    {425,372,0,0,0,0},
    // 13=Weapon 2
    {0,479,0,0,333,0},
    // 14=Trinket 1
    {0,0,0,0,1657,0},
    // 15=Trinket 2
    {0,0,0,0,0,-1},
    // Don't change these two enchants even if you are using different ones.  Doing so will break the program.
    // 16=Glove enchant
    {170,0,0,0,0,0},
    // 17=Cloak enchant
    {0,180,0,0,0,0}
    };
    
    int best[GEAR],best2[GEAR],globalflag=0;
    
    double bestval=0.0,bestval2=0.0;
    
    double reforge(void);
    int score(void);
    void results(void);
    
    int main(void){
        long int i,j;
        
        srand(time(NULL));
        
        // The program works by throwing darts at a dart board, where the dart board is the space of possible reforges
        // and the darts are random reforges.  For each dart it then makes any changes that would improve the dart
        // so each dart is a local maximum.  It remembers the dart that is the biggest local maximum and thats the answer
        // 100k darts takes about 25 seconds on my computer to run
        // I recommend 1000k darts
        for(i=0;i<RUNS;i++){
            reforge();
            if(bestval>bestval2){
                bestval2=bestval;
                for(j=0;j<GEAR;j++) best2[j]=best[j];
                printf("NEW HIGH - %lf\n",bestval2);
            }
        }
        printf("END O_O %lf\n",bestval2);
        for(i=0;i<GEAR;i++) gear[i][5]=best2[i];
        results();
        printf("\nThe program has finished running and is now in an infinite loop for your convenience.\n");
        while(1);
    }
    
    // This function does 1 dart throw
    double reforge(void){
        int flag=1,i,j,k,temp;
        // Pick a random starting point
        for(i=0;i<GEAR;i++){
            if(gear[i][5]!=-1) gear[i][5]=rand()%7;
        }
        // Note the score
        bestval=0;
        score();
        // Attempt to find a local maxima... it tries to do this by going through all possible single reforges in a randomish order
        // the random order is not really very random at all, I just did a bit of work to make it not always the same order
        // if it makes an improvement it starts over again until it can't make an improvement any more
        while(flag){
            flag=0;
            k=rand()%GEAR;
            for(i=k;i<k+GEAR;i++){
                for(j=1;j<8;j++){
                    if(gear[i%GEAR][5]!=-1) gear[i%GEAR][5]=(gear[i%GEAR][5]+j)%7;
                    if(score()){
                        j=8;
                        i=k+GEAR;
                        flag=1;
                    }
                }
            }
        }
    }
    
    // This function checks to see how good a reforge is
    int score(void){
        // This is initialization based on enchants and gems... very shoddy needs improving and allowance for gem optimization
        int stats[5]={0,0,0,0,0};
        int gemstats[6]={0,0,0,0,0,0};
        int i,j,k,source,destination,flag,gemsused=0;
        double pts=0.0;
        // Initialize the gear, before reforges... this can be optimized to run faster since these are constant values
        for(i=0;i<GEAR;i++){
            for(j=0;j<5;j++){
                stats[j]+=gear[i][j];
            }
        }
        // Account for socket bonuses and the leg enchant
        stats[0]+=bhas;
        stats[1]+=bcri;
        stats[2]+=bmas;
        stats[3]+=bhit;
        stats[4]+=bexp;
        // Use at least 160 exp from reds gems and 160 hit from blues
        stats[3]+=BLUE*160;
        gemstats[3]+=BLUE*160;
        stats[4]+=RED*160;
        gemstats[4]+=RED*160;
        // Reforge gear (other than trinkets)
        for(i=0;i<14;i++){
            if(gear[i][5]>0){
                // find source
                if(gear[i][5]<4){
                    // first nonzero stat
                    k=0;
                    while(gear[i][k]==0) k++;
                }else{
                    // last nonzero stat
                    k=0;
                    while(gear[i][4-k]==0) k++;
                    k=4-k;
                }
                source = k;
                // find destination
                k=0;
                flag=(gear[i][5]-1)%3+1;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reforge the trinkets
        for(i=14;i<16;i++){
            if(gear[i][5]>0){
                // find source
                k=0;
                while(gear[i][k]==0) k++;
                source = k;
                // find destination
                k=0;
                flag=gear[i][5];
                if(flag>4)flag-=4;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reenchant the gloves
        if(gear[16][5]%3==1){stats[2]+=170;stats[0]-=170;}
        if(gear[16][5]%3==2){stats[4]+=170;stats[0]-=170;}
        // Reenchant the cloak
        if(gear[17][5]%2==1){stats[3]+=180;stats[1]-=180;}
        // Use gems! In a windwalkery way
        while(gemsused<RED+BLUE+YELLOW*2){
            //Use a red gem
            if(gemsused<RED){
                if(stats[4]<2470){
                    stats[4]+=160;
                    gemstats[4]+=160;
                }else{
                    if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                        if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                        else                  {stats[0]+=160;gemstats[0]+=160;}
                    }else{
                        stats[2]+=160;gemstats[2]+=160;
                    }
                }
            }else{
                // Use a blue gem
                if(gemsused<RED+BLUE){
                    if(stats[3]<2510){
                        stats[3]+=160;gemstats[3]+=160;
                    }else{
                        if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                            if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                            else                  {stats[0]+=160;gemstats[0]+=160;}
                        }else{
                            stats[2]+=160;gemstats[2]+=160;
                        }
                    }
                }else{
                    //Use a yellow gem
                    if(stats[3]<2510){
                        stats[3]+=160;gemstats[3]+=160;
                    }else{
                        if(stats[4]<2470){
                            stats[4]+=160;gemstats[4]+=160;
                        }else{
                            if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                                if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                                else                  {stats[0]+=160;gemstats[0]+=160;}
                            }else{
                                stats[2]+=160;gemstats[2]+=160;
                            }
                        }
                    }
                }
            }
            gemsused++;
        }
        gemsused=0;
        while(gemsused<RED&&stats[4]>2630){
            stats[4]-=160;gemstats[4]-=160;gemstats[5]+=80;
            pts+=300;
            gemsused++;
        }
        
        // determine score
        // if you were going to adapt this program for a different class, you would need to change the following few lines of code
        if(stats[4]<2550) pts-=(2550-stats[4])*5;
        if(stats[4]>2550) pts-=(stats[4]-2550)*2;
        if(stats[3]<2550) pts-=(2550-stats[3])*7;
        if(stats[3]>2550) pts-=(stats[3]-2550)*1;
        pts+=stats[0]*3;
        pts+=stats[1]*3;
        if(stats[0]>=stats[2]||stats[1]>=stats[2]) pts*=-1;
        if(globalflag){
            printf("\nFinal stats:\n");
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
            if(USE_GEM_TIPS==1){
                printf("\nChange in gemming:\n");
                if(gemstats[0]!=HASTE_FROM_GEMS*160) printf("%d haste\n",-HASTE_FROM_GEMS*160+gemstats[0]);
                if(gemstats[1]!=CRIT_FROM_GEMS*160) printf("%d crit\n",-CRIT_FROM_GEMS*160+gemstats[1]);
                if(gemstats[2]!=MAST_FROM_GEMS*160) printf("%d mastery\n",-MAST_FROM_GEMS*160+gemstats[2]);
                if(gemstats[3]!=HIT_FROM_GEMS*160) printf("%d hit\n",-HIT_FROM_GEMS*160+gemstats[3]);
                if(gemstats[4]!=EXP_FROM_GEMS*160) printf("%d expertise\n",-EXP_FROM_GEMS*160+gemstats[4]);
                if(gemstats[5]!=AGI_FROM_GEMS*80) printf("%d agility\n",-AGI_FROM_GEMS*80+gemstats[5]);
            }
        }
        //save score if it is good
        if(pts>bestval){
            bestval=pts;
            for(i=0;i<GEAR;i++) best[i]=gear[i][5];
            return(1);
        }
        return(0);
    }
    
    // This function just prints out the found solution
    void results(void){
        int i,k,flag,source,destination;
        for(i=0;i<16;i++){
            switch(i){
                case 0:
                printf("Head - ");
                break;
                case 1:
                printf("Neck - ");
                break;
                case 2:
                printf("Shoulder - ");
                break;
                case 3:
                printf("Back - ");
                break;
                case 4:
                printf("Chest - ");
                break;
                case 5:
                printf("Wrist - ");
                break;
                case 6:
                printf("Hands - ");
                break;
                case 7:
                printf("Waist - ");
                break;
                case 8:
                printf("Legs - ");
                break;
                case 9:
                printf("Feet - ");
                break;
                case 10:
                printf("Ring1 - ");
                break;
                case 11:
                printf("Ring2 - ");
                break;
                case 12:
                printf("Weapon1 - ");
                break;
                case 13:
                printf("Weapon2 - ");
                break;
                case 14:
                printf("Trinket1 - ");
                break;
                case 15:
                printf("Trinket2 - ");
                break;
            }
            if(best2[i]<1){
                printf("No reforge\n");
            }else{
                if(i<14){
                    // find source
                    if(best2[i]<4){
                        // first nonzero stat
                        k=0;
                        while(gear[i][k]==0) k++;
                    }else{
                        // last nonzero stat
                        k=0;
                        while(gear[i][4-k]==0) k++;
                        k=4-k;
                    }
                    source = k;
                    // find destination
                    k=0;
                    flag=(best2[i]-1)%3+1;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }else{
                    // find source
                    k=0;
                    while(gear[i][k]==0) k++;
                    source = k;
                    // find destination
                    k=0;
                    flag=best2[i];
                    if(flag>4)flag-=4;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }
                printf("Reforge out of ");
                switch(source){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf(" and into ");
                switch(destination){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf("\n");
            }
        }
        printf("Enchant gloves with 170 ");
        if(gear[16][5]%3==0) printf("haste\n");
        if(gear[16][5]%3==1) printf("mastery\n");
        if(gear[16][5]%3==2) printf("expertise\n");
        printf("Enchant cloak with 180 ");
        if(gear[17][5]%2==0) printf("crit\n");
        if(gear[17][5]%2==1) printf("hit\n");
        globalflag=1;
        score();
    }
    Here is a sample of what the gem output looks like:
    "Change in gemming:
    -640 haste
    320 crit
    160 mastery
    160 hit"
    Ok so what I'm going to do is copy your text exact and run it and make it it goes through properly if it does i'll re input my numbers as i had to of created the error.

    - Edit -

    Did the import and compile/run but it fails to compile erroring with - warning C4716: 'reforge' : must return a value

    ---------- Post added 2013-04-25 at 05:36 AM ----------

    Took me some extra work to get things working properly but I really like the potential of this script.
    Last edited by Requital; 2013-04-25 at 05:36 AM.
    Quote Originally Posted by Boubouille View Post
    Can you imagine if someone insulted you in a thread, you reported it, and I told you "sorry, wrong thread to be butthurt"?

  13. #33
    I use Ask Mr Robot to give me a good idea of what numbers to shoot for. I will add up all my secondary stats and divide by 3. Set the haste cap to a little below that value, and adjust accordingly.

    I use Reforgelite to check and see reforging to which of the three stats hits closest to that magic number, reforge to that stat, and use gems to cover the rest.

    Close enough is probably good enough. This seems like a case where trying to polish the turd will drive you crazy.

  14. #34
    Sigh... I tried everything and it just doesnt reforge into what I want... i have the feeling I do everything wrong. I cant link my character, its yengpeng (stormscale EU)

  15. #35
    This works really well keith, thanks for making it. I do have one suggestion: I'm not sure it's right to always hit socket bonuses. Check my armory, reforged and gemmed exactly as the program guessed: http://eu.battle.net/wow/en/characte...uotey/advanced

    If I were to replace my gloves gem for instance with a 320 yellow it'd end up a bit better but of course throw out reforgings. I could probably do this myself by subtracting the agi socket bonus from the listing and adding a yellow instead of a blue socket, I suppose. Can anyone think of any problems that might cause before I do it to get rid of my blue gems?

    e: if you want to play aobut with a heavily overcapped exp/hit gearset, here's my inputs (not for my regemmed one, these are what i originally used)

    Code:
    #define AGI_FROM_GEMS 6
    #define EXP_FROM_GEMS 0
    #define HASTE_FROM_GEMS 1
    #define CRIT_FROM_GEMS 18
    #define MAST_FROM_GEMS 5
    #define HIT_FROM_GEMS 2
    Code:
    #define RED 5
    #define YELLOW 8
    #define BLUE 4
    Code:
    // The value of your socket bonuses plus the 165 crit leg enchant and the 100 crit shoulder enchant and the 324p meta
    #define bcri 324+165+180+100
    #define bmas 180
    #define bhas 120
    #define bexp 0
    #define bhit 0
    Code:
    int gear[GEAR][6] = {
    // Input gear UNREFORGED
    // 0=Head
    {919,0,0,919,0,0},
    // 1=Neck
    {682,0,0,0,605,0},
    // 2=Shoulder
    {0,737,0,616,0,0},
    // 3=Back
    {0,0,588,0,564,0},
    // 4=Chest
    {0,0,893,0,935,0},
    // 5=Wrist
    {637,663,0,0,0,0},
    // 6=Hands
    {895,0,0,858,0,0},
    // 7=Waist
    {732,0,0,732,0,0},
    // 8=Legs
    {1103,0,1070,0,0,0},
    // 9=Feet
    {726,0,0,634,0,0},
    // 10=Ring 1
    {654,0,654,0,0,0},
    // 11=Ring 2
    {0,494,629,0,0,0},
    // 12=Weapon 1
    {0,492,492,0,0,0},
    // 13=Weapon 2
    {472,0,0,0,362,0},
    // 14=Trinket 1
    {0,0,0,0,1752,0},
    // 15=Trinket 2
    {0,0,0,0,0,-1},
    // Don't change these two enchants even if you are using different ones.  Doing so will break the program.
    // 16=Glove enchant
    {170,0,0,0,0,0},
    // 17=Cloak enchant
    {0,180,0,0,0,0}
    };
    Last edited by Quotey; 2013-04-26 at 03:16 PM.

  16. #36
    Hello,

    I just ran you prog with my current gear and it gives me the following result :

    Code:
    Final stats :
    Haste : 5325
    Crit : 5326
    Mastery : 5327
    
    Hit : 2550
    Expertise : 2550
    I feel my gear a bit light for this trinket am i right ?

  17. #37
    @Quotey: You're right, the program does always follow sockets and that might not be optimal. It would take a fair amount of work for it to be able to decide whether to do so or not. As you say, the way to handle it is to decide yourself if you want to skip out on a socket bonus and then change the number of sockets you have to reflect that.

    Still though I think all socket bonuses are usually worth it. The only ones that are kind of borderline are the 1 blue sockets for +60 agi when you are way over hit cap. Still though I think 60 agi + 160 hit (over cap) > 160 mast/crit/haste, for dual wield (but absolutely NOT for people using a 2H weapon). Generally speaking I think hit is worth around 1/2 as much as mast/crit/haste over cap and agi worth ~2x, so 60 agi + 160 hit ~= 200 mast/crit/haste, but if you have different relative stat values then it might be good to not go for those 60 agi blue socket gem bonuses.'

    @Porcinet - Those are pretty low stats, but RoRo is really OP. It really depends on what ilvl your RoRo is and what the trinket you could use instead is. If you really want to know, what I would do is input the RoRo set up into ask mr robot (manually), then press the ask mr robot export button to be able to export it into simulationcraft. Then sim that setup with SimC and compare it against your non RoRo set up.

    I would really like to be able to have my program read your character from the web, but I don't know how. I think the cURL library (libcurl) would provide the functions I need to grab the data from the web (I know where on the web to get it from the Blizz API), but for the life of me I can't manage to build the libcurl library and get it to link properly with my IDE/compiler. If anyone knows how to read the source of a web page into a C program, that would be great.
    WW Monk - Janxspirit @ US-Illidan
    [20:14:20.744] Janxspirit Rising Sun Kick Horridon *3,374,517* - MEGADAMAGE

  18. #38
    Keyboard Turner Wafflehauz's Avatar
    Join Date
    Jan 2013
    Location
    Houston
    Posts
    5
    And I'm going to do this tonight with the AMR / Sim. I burned some cash and several gems trying to determine if my LFR RoRo was worth it. Tangent question though, do you usually change out the fight style? I figured just keeping it on Patchwerk was just wrong considering I move so much. What's a good fight type to use when you Sim?

  19. #39
    I think just about everyone only uses the patchwork setting.

    It is true that encounter mechanics can change things, but not that much, and the mechanics are different for every fight.

    Generally speaking, I think the two big things are that when you have to move but can stay on target (EG following Primordius around as he is kited) raises the value of haste (since you cannot properly use FoF and therefore require more haste to have no downtime) and time spend moving with no target to hit lowers the value of haste (since you regen energy during downtime and therefore need less haste to maintain 100% uptime when you are actually on the boss).

    For anyone who cares about my program, I've temporarily given up on having it import from the web, but am now supporting importing your char yourself from the web. The way the latest version works is you go to the wow website that contains your char data (EG for me, Janxspirit@Illidan(US) http://us.battle.net/api/wow/charact...t?fields=items , you copy and paste the data from there and put it into a text file named "stats.txt". The program then parses that stats file.

    So far I've been able to get it to parse the stats from your gear, but I haven't added in the parsing of the stats from socket bonuses, enchants and gems. I'll post an update once I test it some more and make sure it is working.

    ---------- Post added 2013-04-27 at 12:41 AM ----------

    Here is version 3.0.0 which now loads your stats from gear (but still requires you to input your gems, gem bonuses and enchants). Again, to use it, you now have to go to the website

    Code:
    http://REGION.battle.net/api/wow/character/REALM/CHARACTER?fields=items
    IE for me (Janxspirit@US-Illidan) that would be
    Code:
    http://us.battle.net/api/wow/character/Illidan/Janxspirit?fields=items
    you take the data from there and copy and paste it into a text file called "stats.txt" which must be in the same directory as the program.

    Code:
    // WindwalkerReforge.c
    // Version 3.0.0
    // By Janxspirit AKA Keith C
    // Known bugs - Sometimes uses nonexistent gems (expertise+hit yellows, or haste+crit yellows), but since this hasn't actually happened I haven't fixed it yet (I just know it can in theory happen).
    // Latest feature - Gear data imports from text file taken from the web
    // Future features - also import gems, socket bonuses and enchants, and do it direct from web rather than from text file
    
    
    // This is an optional section.  You say how much stats you are getting from your gems.
    // It will NOT affect the optimizer, the only thing it changes is it uses these numbers to tell you
    // what the change in your gemming needs to be.
    // Remember if you do not input the stats you have from gems, the reforge solution from the program will still be correct
    // but where it tells you the change in gems WILL BE WRONG
    // Note that this section has NOTHING to do with gem socket bonuses, only the stats from gems you are using
    //
    // USE_GEM_TIPS should be set to 1 if you want the output to tell you the change in how to gem, or 0 if you do not want this feature
    #define USE_GEM_TIPS 1
    // Count every 80 you have from agi gems as 1 for agi, and every 160 for other stats as 1
    // In other words a 160expertise&160crit gem would count as +1 CRIT_FROM_GEMS and +1 EXP_FROM_GEMS, and a +320 haste gem would be +2 haste or a +160 agi gem would be +2 agi
    // I did it this way because I found it easy to count, if you don't BOLLOCKS TO YOU!
    #define AGI_FROM_GEMS 0
    #define EXP_FROM_GEMS 0
    #define HASTE_FROM_GEMS 0
    #define CRIT_FROM_GEMS 0
    #define MAST_FROM_GEMS 0
    #define HIT_FROM_GEMS 0
    
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    // The number of different types of sockets you have
    #define RED 3
    #define YELLOW 7
    #define BLUE 3
    
    // The value of your socket bonuses plus the 165 crit leg enchant and the 100 crit shoulder enchant and the 324p meta
    #define bcri 324+165+100
    #define bmas 60
    #define bhas 180
    #define bexp 0
    #define bhit 0
    
    // The total number of items/enchants
    // Don't fiddle with this, you'll break the program
    #define GEAR 18
    
    // The number of times to run the optimizer.  You can decrease this to make it run faster or increase it to make it slower
    // The more time you spend (more runs) the better your best solution will tend to be
    #define RUNS 100000
    
    // POINT OF NO RETURN
    // ABANDON ALL HOPE YE WHO GO PAST HERE
    // IF YOU ARE JUST TRYING TO USE MY PROGRAM THERE IS NOTHING YOU NEED TO CHANGE/UNDERSTAND PAST THIS POINT
    
    // These arrays are used by the parser as it reads in character data
    #define CSIZE 3000
    char item[CSIZE],item2[50];
    
    // Input each row (piece of gear) as {haste,crit,mastery,hit,expertise,0}
    // Any time I get a new piece of gear I have to update the entry for it here in this gear array
    // If a piece of gear does not exist (or if it is a pure agi trink) input -1 in the 6th (last) column and 0s in the rest
    // the last column is used for how the gear slot is reforged
    // 0=head, 1=neck, 2=shoul, 3=back, 4=chest, 5=wrist, 6=glove, 7=belt, 8=pant, 9= boot, 10=finger1, 11=finger2, 12= trinket1, 13=trinket2, 14=mainhand, 15=offhand, 16=glove enchant, 17=cloak enchant
    int gear[GEAR][6];
    
    int best[GEAR],best2[GEAR],globalflag=0;
    
    double bestval=0.0,bestval2=0.0;
    
    double reforge(void);
    int score(void);
    void results(void);
    void printitem(void);
    void import(void);
    
    int main(void){
        long int i,j;
        
        // randomize the RNG
        srand(time(NULL));
        
        // import stats
        import();
        // fix a couple things the import function should have done but did not
        gear[16][0]=170;
        gear[16][5]=0;
        gear[17][1]=180;
        gear[17][5]=0;
        
        // This little bit here just prints out the gear array to make sure it got imported right for debugging purposes.
        // I often leave it commented out
        for(i=0;i<GEAR;i++){
            for(j=0;j<6;j++){
                printf("%d ",gear[i][j]);
            }
            printf("\n");
        }
        
        // The program works by throwing darts at a dart board, where the dart board is the space of possible reforges
        // and the darts are random reforges.  For each dart it then makes any changes that would improve the dart
        // so each dart is a local maximum.  It remembers the dart that is the biggest local maximum and thats the answer
        // 100k darts takes about 25 seconds on my computer to run
        // I recommend 1000k darts
        for(i=0;i<RUNS;i++){
            reforge();
            if(bestval>bestval2){
                bestval2=bestval;
                for(j=0;j<GEAR;j++) best2[j]=best[j];
                printf("NEW HIGH - %lf\n",bestval2);
            }
        }
        printf("END O_O %lf\n",bestval2);
        for(i=0;i<GEAR;i++) gear[i][5]=best2[i];
        results();
        printf("\nThe program has finished running and is now in an infinite loop for your convenience.\n");
        while(1);
        return(0);
    }
    
    // This function does 1 dart throw
    double reforge(void){
        int flag=1,i,j,k,temp;
        // Pick a random starting point
        for(i=0;i<GEAR;i++){
            if(gear[i][5]!=-1) gear[i][5]=rand()%7;
        }
        // Note the score
        bestval=0;
        score();
        // Attempt to find a local maxima... it tries to do this by going through all possible single reforges in a randomish order
        // the random order is not really very random at all, I just did a bit of work to make it not always the same order
        // if it makes an improvement it starts over again until it can't make an improvement any more
        while(flag){
            flag=0;
            k=rand()%GEAR;
            for(i=k;i<k+GEAR;i++){
                for(j=1;j<8;j++){
                    if(gear[i%GEAR][5]!=-1) gear[i%GEAR][5]=(gear[i%GEAR][5]+j)%7;
                    if(score()){
                        j=8;
                        i=k+GEAR;
                        flag=1;
                    }
                }
            }
        }
    }
    
    // This function checks to see how good a reforge is
    int score(void){
        // This is initialization based on enchants and gems... very shoddy needs improving and allowance for gem optimization
        int stats[5]={0,0,0,0,0};
        int gemstats[6]={0,0,0,0,0,0};
        int i,j,k,source,destination,flag,gemsused=0;
        double pts=0.0;
        // Initialize the gear, before reforges... this can be optimized to run faster since these are constant values
        for(i=0;i<GEAR;i++){
            for(j=0;j<5;j++){
                stats[j]+=gear[i][j];
            }
        }
        // Account for socket bonuses and the leg enchant
        stats[0]+=bhas;
        stats[1]+=bcri;
        stats[2]+=bmas;
        stats[3]+=bhit;
        stats[4]+=bexp;
        // Use at least 160 exp from reds gems and 160 hit from blues
        stats[3]+=BLUE*160;
        gemstats[3]+=BLUE*160;
        stats[4]+=RED*160;
        gemstats[4]+=RED*160;
        // Reforge gear (other than trinkets)
        for(i=0;i<14;i++){
            if(gear[i][5]>0){
                // find source
                if(gear[i][5]<4){
                    // first nonzero stat
                    k=0;
                    while(gear[i][k]==0) k++;
                }else{
                    // last nonzero stat
                    k=0;
                    while(gear[i][4-k]==0) k++;
                    k=4-k;
                }
                source = k;
                // find destination
                k=0;
                flag=(gear[i][5]-1)%3+1;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reforge the trinkets
        for(i=14;i<16;i++){
            if(gear[i][5]>0){
                // find source
                k=0;
                while(gear[i][k]==0) k++;
                source = k;
                // find destination
                k=0;
                flag=gear[i][5];
                if(flag>4)flag-=4;
                while(flag){
                    while(gear[i][k]!=0) k++;
                    flag--;
                    if(flag) k++;
                }
                destination=k;
                // do the reforge from source stat into destination stat
                stats[source]=stats[source]-(int)(gear[i][source]*0.4);
                stats[destination]+=gear[i][source]*0.4;
            }
        }
        // Reenchant the gloves
        if(gear[16][5]%3==1){stats[2]+=170;stats[0]-=170;}
        if(gear[16][5]%3==2){stats[4]+=170;stats[0]-=170;}
        // Reenchant the cloak
        if(gear[17][5]%2==1){stats[3]+=180;stats[1]-=180;}
        // Use gems! In a windwalkery way
        while(gemsused<RED+BLUE+YELLOW*2){
            //Use a red gem
            if(gemsused<RED){
                if(stats[4]<2470){
                    stats[4]+=160;
                    gemstats[4]+=160;
                }else{
                    if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                        if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                        else                  {stats[0]+=160;gemstats[0]+=160;}
                    }else{
                        stats[2]+=160;gemstats[2]+=160;
                    }
                }
            }else{
                // Use a blue gem
                if(gemsused<RED+BLUE){
                    if(stats[3]<2510){
                        stats[3]+=160;gemstats[3]+=160;
                    }else{
                        if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                            if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                            else                  {stats[0]+=160;gemstats[0]+=160;}
                        }else{
                            stats[2]+=160;gemstats[2]+=160;
                        }
                    }
                }else{
                    //Use a yellow gem
                    if(stats[3]<2510){
                        stats[3]+=160;gemstats[3]+=160;
                    }else{
                        if(stats[4]<2470){
                            stats[4]+=160;gemstats[4]+=160;
                        }else{
                            if((stats[2]>stats[0]+160&&stats[2]>stats[1])||(stats[2]>stats[1]+160&&stats[2]>stats[0])){
                                if(stats[0]>stats[1]) {stats[1]+=160;gemstats[1]+=160;}
                                else                  {stats[0]+=160;gemstats[0]+=160;}
                            }else{
                                stats[2]+=160;gemstats[2]+=160;
                            }
                        }
                    }
                }
            }
            gemsused++;
        }
        gemsused=0;
        while(gemsused<RED&&stats[4]>2630){
            stats[4]-=160;gemstats[4]-=160;gemstats[5]+=80;
            pts+=300;
            gemsused++;
        }
        
        // determine score
        // if you were going to adapt this program for a different class, you would need to change the following few lines of code
        if(stats[4]<2550) pts-=(2550-stats[4])*5;
        if(stats[4]>2550) pts-=(stats[4]-2550)*2;
        if(stats[3]<2550) pts-=(2550-stats[3])*7;
        if(stats[3]>2550) pts-=(stats[3]-2550)*1;
        pts+=stats[0]*3;
        pts+=stats[1]*3;
        if(stats[0]>=stats[2]||stats[1]>=stats[2]) pts*=-1;
        if(globalflag){
            printf("\nFinal stats:\n");
            printf("Haste = %d\nCrit = %d\nMastery = %d\nHit = %d\nExpertise = %d\n",stats[0],stats[1],stats[2],stats[3],stats[4]);
            if(USE_GEM_TIPS==1){
                printf("\nChange in gemming:\n");
                if(gemstats[0]!=HASTE_FROM_GEMS*160) printf("%d haste\n",-HASTE_FROM_GEMS*160+gemstats[0]);
                if(gemstats[1]!=CRIT_FROM_GEMS*160) printf("%d crit\n",-CRIT_FROM_GEMS*160+gemstats[1]);
                if(gemstats[2]!=MAST_FROM_GEMS*160) printf("%d mastery\n",-MAST_FROM_GEMS*160+gemstats[2]);
                if(gemstats[3]!=HIT_FROM_GEMS*160) printf("%d hit\n",-HIT_FROM_GEMS*160+gemstats[3]);
                if(gemstats[4]!=EXP_FROM_GEMS*160) printf("%d expertise\n",-EXP_FROM_GEMS*160+gemstats[4]);
                if(gemstats[5]!=AGI_FROM_GEMS*80) printf("%d agility\n",-AGI_FROM_GEMS*80+gemstats[5]);
            }
        }
        //save score if it is good
        if(pts>bestval){
            bestval=pts;
            for(i=0;i<GEAR;i++) best[i]=gear[i][5];
            return(1);
        }
        return(0);
    }
    
    // This function just prints out the found solution
    void results(void){
        int i,k,flag,source,destination;
        for(i=0;i<16;i++){
            switch(i){
                case 0:
                printf("Head - ");
                break;
                case 1:
                printf("Neck - ");
                break;
                case 2:
                printf("Shoulder - ");
                break;
                case 3:
                printf("Back - ");
                break;
                case 4:
                printf("Chest - ");
                break;
                case 5:
                printf("Wrist - ");
                break;
                case 6:
                printf("Hands - ");
                break;
                case 7:
                printf("Waist - ");
                break;
                case 8:
                printf("Legs - ");
                break;
                case 9:
                printf("Feet - ");
                break;
                case 10:
                printf("Ring1 - ");
                break;
                case 11:
                printf("Ring2 - ");
                break;
                case 12:
                printf("Weapon1 - ");
                break;
                case 13:
                printf("Weapon2 - ");
                break;
                case 14:
                printf("Trinket1 - ");
                break;
                case 15:
                printf("Trinket2 - ");
                break;
            }
            if(best2[i]<1){
                printf("No reforge\n");
            }else{
                if(i<14){
                    // find source
                    if(best2[i]<4){
                        // first nonzero stat
                        k=0;
                        while(gear[i][k]==0) k++;
                    }else{
                        // last nonzero stat
                        k=0;
                        while(gear[i][4-k]==0) k++;
                        k=4-k;
                    }
                    source = k;
                    // find destination
                    k=0;
                    flag=(best2[i]-1)%3+1;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }else{
                    // find source
                    k=0;
                    while(gear[i][k]==0) k++;
                    source = k;
                    // find destination
                    k=0;
                    flag=best2[i];
                    if(flag>4)flag-=4;
                    while(flag){
                        while(gear[i][k]!=0) k++;
                        flag--;
                        if(flag) k++;
                    }
                    destination=k;
                }
                printf("Reforge out of ");
                switch(source){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf(" and into ");
                switch(destination){
                    case 0:
                    printf("haste");
                    break;
                    case 1:
                    printf("crit");
                    break;
                    case 2:
                    printf("mastery");
                    break;
                    case 3:
                    printf("hit");
                    break;
                    case 4:
                    printf("expertise");
                    break;
                }
                printf("\n");
            }
        }
        printf("Enchant gloves with 170 ");
        if(gear[16][5]%3==0) printf("haste\n");
        if(gear[16][5]%3==1) printf("mastery\n");
        if(gear[16][5]%3==2) printf("expertise\n");
        printf("Enchant cloak with 180 ");
        if(gear[17][5]%2==0) printf("crit\n");
        if(gear[17][5]%2==1) printf("hit\n");
        globalflag=1;
        score();
    }
    
    void import(void){
        char c;
        int i, j, brackets=0;
        FILE *fp = fopen("stats.txt", "rb");
    
        for(i=0;i<GEAR;i++){
            for(j=0;j<5;j++){
                gear[i][j]=0;
            }
            gear[i][j]=-1;
        }
    
        if(fp == NULL){
            perror("Failed to open file \"stats.txt\"");
            while(1);
        }
    
        for(i=0;i<2;i++){
            c=getc(fp);
            while(c!='{'){
                c=getc(fp);
            }
        }
        for(i=0;i<2;i++){
            c=getc(fp);
            while(c!=','){
                c=getc(fp);
            }
        }
    
        while(brackets>-1){
            if(c=='{') brackets++;
            if(c=='}') brackets--;
            c=getc(fp);
            i=0;
            while(!(c==','&&brackets==0)&&!(c=='}'&&brackets==-1)){
                item[i]=c;
                i++;
                if(c=='{') brackets++;
                if(c=='}') brackets--;
                c=getc(fp);
            }
            item[i]='\0';
            printitem();
        }
    
        fclose(fp);
    }
    
    // This function uses the data contained in the item array (which represents a single item) and parses it into the stats etc given by that item
    // technically speaking it has nothing at all to do with printing items and its name is very deceptive
    void printitem(void){
        int i,j,k,gearslot=-1,statnum,statnum2,stattype;
        string word;
        char word2[20];
        // i represents how far into the item array we are
        i=0;
        // first we must parse the item slot of the item
        j=0;
        k=0;
        while(j<2){
            if(item[i]=='"') j++;
            if(item[i]!='"'){
                word2[k]=item[i];
                k++;
            }
            i++;
        }
        word2[k]='\0';
        word=word2;
        // the word2 array now contains the item slot of the item
        if(word=="head") gearslot=0;
        if(word=="neck") gearslot=1;
        if(word=="shoulder") gearslot=2;
        if(word=="back") gearslot=3;
        if(word=="chest") gearslot=4;
        if(word=="wrist") gearslot=5;
        if(word=="hands") gearslot=6;
        if(word=="waist") gearslot=7;
        if(word=="legs") gearslot=8;
        if(word=="feet") gearslot=9;
        if(word=="finger1") gearslot=10;
        if(word=="finger2") gearslot=11;
        if(word=="mainHand") gearslot=12;
        if(word=="offHand") gearslot=13;
        if(word=="trinket1") gearslot=14;
        if(word=="trinket2") gearslot=15;
    
        // only continue if we found a valid piece of gear
        if(gearslot!=-1){
            // continue parsing up to two }} symbols
            k=0;
            while(k<2){
                if(item[i]=='}') k++;
                i++;
            }
            // keep parsing until you hit the ] which denotes the end of item stat listings
            while(item[i]!=']'){
                // find an entry between { } and put it in item2 array
                while(item[i]!='{') i++;
                k=0;
                i++;
                while(item[i]!='}'){
                    item2[k]=item[i];
                    k++;
                    i++;
                }
                i++;
    
                item2[k]='\0';
                // now this item contains some data which is after three : s
                // after the first : is a number representing what stat were talking about
                // after the second : is how much of it is there
                // if there is no third : , we're done
                // if there is a true after the third : it means we don't add the stat
                // if there is a negative number after the third : we subtract it
                // we do this because we want the unreforged stats of the gear rather than the reforged ones
                statnum=-1;
                k=0;
                while(item2[k]!='\0'){
                    // get to the first :
                    while(item2[k]!=':') k++;
                    k++;
                    // get the stattype, which is a char located inside item2 converted into an int
                    stattype=0;
                    while(item2[k]!=','){
                        stattype*=10;
                        stattype+=item2[k]-'0';
                        k++;
                    }
                    // get to the second :
                    while(item2[k]!=':') k++;
                    k++;
                    // get the statnum, which is a char located inside item2 converted into an int
                    statnum=0;
                    while(item2[k]!=','&&item2[k]!='\0'){
                        statnum*=10;
                        statnum+=item2[k]-'0';
                        k++;
                    }
                    // now get to the third : , if we are not already at the end
                    if(item2[k]!='\0'){
                        while(item2[k]!=':') k++;
                        k++;
                        // Now we are either at "true" or "-"
                        // if true, we add nothing
                        if(item2[k]=='t'){
                            statnum=0;
                            stattype=-1;
                        }else{
                            // otherwise we parse the negative number in and add it back in
                            k++;
                            statnum2=0;
                            while(item2[k]!='\0'){
                                statnum2*=10;
                                statnum2+=item2[k]-'0';
                                k++;
                            }
                            statnum+=statnum2;
                        }
                    }
                    // if we're not at the end yet(because we went up to the 't' of 'true' and stopped) get to the end
                    while(item2[k]!='\0') k++;
                    // now to actually use our statnum and statype which finally contain the data we want!
                    switch(stattype){
                        // haste!
                        case 36:
                            gear[gearslot][0]=statnum;
                            gear[gearslot][5]=0;
                            break;
                        // crit!
                        case 32:
                            gear[gearslot][1]=statnum;
                            gear[gearslot][5]=0;
                            break;
                        // mastery!
                        case 49:
                            gear[gearslot][2]=statnum;
                            gear[gearslot][5]=0;
                            break;
                        // hit!
                        case 31:
                            gear[gearslot][3]=statnum;
                            gear[gearslot][5]=0;
                            break;
                        // expertise!
                        case 37:
                            gear[gearslot][4]=statnum;
                            gear[gearslot][5]=0;
                            break;
                    }
                }
            }
        }
    }
    I'll try to extend the import parser support to handle gems, enchants and gem bonuses maybe on Sunday or Monday.
    Last edited by keithioapc; 2013-04-27 at 01:07 AM.
    WW Monk - Janxspirit @ US-Illidan
    [20:14:20.744] Janxspirit Rising Sun Kick Horridon *3,374,517* - MEGADAMAGE

  20. #40
    Great job. I have been working on something similar in objective-c (started a couple of days ago) but I'm no where near to this yet.

    ---------- Post added 2013-04-27 at 04:35 AM ----------

    also
    I would really like to be able to have my program read your character from the web, but I don't know how. I think the cURL library (libcurl) would provide the functions I need to grab the data from the web (I know where on the web to get it from the Blizz API), but for the life of me I can't manage to build the libcurl library and get it to link properly with my IDE/compiler. If anyone knows how to read the source of a web page into a C program, that would be great.
    http://www.json.org/

    Check that out, you can use a 3rd party JSON parser. That lists some places to check out and I think there are some basic examples up as well. Hope it helps a little
    Last edited by domwindle; 2013-04-27 at 04:36 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •