Monday, May 22, 2023

Resource Editor Ostriv

 Hi All,


I have made a new Resource Editor Tool for Ostriv

It is early version. Let me know if you face issues.

It can do following:
  • Find storage buildings (warehouse, granary, camp storage, well, trading post, trading port, hay barrack)
  • Set stone and limestone rock values to desired(and maintain)
  • Edit farm / stone mining camp resources.
  • Edit resource in individual building.
  • Maintain resource to given value.
  • Clear individual resource in a building (set to 0).
  • Set capacity for each building.
  • Add resources to a building.

Tutorial






Updates

Updated to 1.50902b
  • Updated for Alpha 5 patch 9 hotfix 2
Updated to 1.5043o
  • Updated for Alpha 5 patch 4
  • Optimize search - Parrallel search is now much faster
  • Added new info for showing what is being maintained and where
  • Show charts for resources. Also, added option to save charts.

    • To show timeline double click on any resource in "Resources" group in Storage details window.
    • It shows history of resource for 5 mins. Note: in case game is paused the tools keeps on recording the data as it can not detect if game is paused.
  • Some Crash fixes reported by users.
  • Limit CPU usage.

  • Show trends of resources in storage (in case resources are changing quickly).
  • Show all rules for resource maintainance.


Updated to 1.5032c
  • Updated for Alpha 5 patch 3
  • Add setting for QuickScan. This significantly reduces scan time but some buildings may be missed. In that case disable this setting and try again. If still a building is not found save game and exit. Exit tool also and try again.




Updated to 1.5020d
  • Add a new info windows that displays total amount of resources stored in Storage buildings.
    This is helpful to see how much total does village/town has. Also you can search which resource is present in which buildings and how much.


    Storage Details

  • Support for adding resources that has life time.
    Some resources has life time as introduced in alpha 5. These resources can only be added correctly if the life time of these is know. The tool can only know the life of these reource if a builing that is storing these resources is added to tool. Also, initiialy the tool will guess the life and in that case the status will be RED.  Once the tool guesses the status will be YELLOW. It turns GREEN when the life is known. The two circles are for two kind of resources (Veggies and meat).
Resource Life known status


  • Update to work with alpha 5 patch 2.
  • The list of resources and buildings is now sorted.
  • This is a test build, so may have issues. Many new things got added in game and i had to change the mechanism. Please report back any issues.
  • Previous max storage limit has been increased to 10 times.
  • NOTE: Sometimes UI will be messed up or no update will be shown. Just do a maximise/restore operation on window to fix it!

Updated to beta 0.91
- Update to work with alpha 4 patch 7 hotfix 5

Updated to beta 0.9
Add auto resource maintenance in buildings. For this you need to have an entry in user settings like below. Click on "Automation" button at the top to open settings.


Updated to beta 0.8
- Added Apricot, Apple, Cherry, Garlic, Horseradish, Marrow, Peas, Pumpkin
- Fixed searching for alpha 4 patch 7

Updated to beta 0.6
- Added sheep hides, sheep skin, wool, broadcloth
- Fixed bug in maintaining resources.

Updates in beta 0.5.
- Fixed issue caused by Ostriv alpha 4 patch 4 update.

Updates in beta 0.4.
- Farms can add water and hay.
- Set default storage capacity for buildings that gets applied when a building is found after search.
- Set default amount of resources that are maintained in a building. This setting needs to be applied manually every time a new search is done or new game is loaded.

Note: beta 0.4 creates temporary files. So it is advised to put the tool in a separate folder. the files it will create (and deleted on exit) are:
- x64/Sqlite.interop.dll - library required for saving user settings
- Ostriv_resoure_editor.exe.config - this is required to save window position
- Ostriv_Resource_Editor.userpref - this file is a database file that saves default capacities of building and resource amounts.


Instructions:

1. Select a building and do search.
2. After search, select building from drop down list to view and change resources.
3. Minimum value to set is 1.0
4. Minimum value to maintain is 300.
5. Min/Max capacity of granary and warehouse is 20,000/200,000 & 10,000/100,000. 
    - For camp storage it is 7000/70000
    - For trading post it is 25000/250,000
    - For trading port it is 15000/250,000
    - For hay barrack it is 1000/10000
    - For well its is 5000/50,000. (Although may not be relevant)

Note: Please remove the building from tool before demolishing the building in game. If not removed, it may cause tool/game to crash.


Finally, if you enjoyed the trainer, you can help me in maintaining it by donating some amount  for my efforts to my PayPal account (you might need to create an account :), here:  DONATE HERE.

Download links

                 : Ostriv Resource Editor beta 1.5043o
alpha 5 patch 5  : Ostriv Resource Editor beta 1.50501b
alpha 5 p5 hf 5  : Ostriv Resource Editor 1.50505a
alpha 5 p6 hf 1  : Ostriv Resource Editor 1.50601a
alpha 5 p7 hf 1  : Ostriv Resource Editor 1.50701a
alpha 5 p8 hf 1  : Ostriv Resource Editor 1.50801a
alpha 5 p8 hf 2  : Ostriv Resource Editor 1.50801b
alpha 5 p8 hf 3  : Ostriv Resource Editor 1.50803c
alpha 5 p9 hf 2  : Ostriv Resource Editor 1.50902b










Friday, November 23, 2012

My Sudoko Solver



Sudoko Solver i wrote using C#. It's unfinished. But it solves sudoko puzzles.

If anyone wants to try and help me in findings errors/bugs here is the link : http://uploaded.net/file/42s0tnka


Tuesday, June 12, 2012

A new Project

Soon I will be uploading my UI project... It's ambitious but I will have time. (29 card game next, need help, any one volunteering? (Sriram Dash is helping already) ).

Here are some of the pics.






Saturday, May 12, 2012

Sum of Subsets (find all sums for given Number set)



Sample Output is shown above. This program will run in windows only. For Linux you must write your own gotoxy function.

#include<stdio.h>
#include<stdlib.h>

#define MAX_PRINT_LEVEL 5

#include <windows.h>

void gotoxy(int col, int row)     //starting from 0
{
    COORD coord;
    coord.X = col;
    coord.Y = row;

    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

struct tree_node
{
       struct tree_node *left,*right;
       int data;
};

typedef struct tree_node TNODE;

TNODE* create_tree(int *input,int num);
void add_num(TNODE *node,int *input,int num);
void print_tree(TNODE *root,int num,int col,int row);
int print_subsets(TNODE *root,int sum,int *input,int *subsets,int index,int num);
int pow(int a, int b);

//array to store all possible sums, remove if not neeeded
/*int *sums,sum_count=0;*/

int main()
{
       int sum;

       int *input,num;
       int *subsets;
       TNODE *root=NULL;



       int i;

       printf("\nHOW MANY NUMBERS: ");
       scanf("%d",&num);
       if(num<0)
       {
              printf("\nERROR: Invalid num value...\n\n");
              exit(1);
       }
       if( (input = (int*)malloc(num*sizeof(int))) == NULL)
       {
              printf("\n\nERROR: MEMORY NOT ALLOCATED\n\n");
              exit(1);
       }
       if( (subsets = (int*)malloc(num*sizeof(int))) == NULL)
       {
              printf("\n\nERROR: MEMORY NOT ALLOCATED\n\n");
              exit(1);
       }
       printf("\nEnter numbers: \n");
       for(i=0;i<num;i++)
       {
              printf("NUM[%d] : ",i);
              scanf("%d",&input[i]);
       }

       //array to store all possible sums, remove if not neeeded
       /*if( (sums = (int*)malloc(pow(2,num)*sizeof(int))) == NULL)
       {
              printf("\n\nERROR: MEMORY NOT ALLOCATED\n\n");
              exit(1);
       }*/

       root = create_tree(input,num);

       system("cls");
       print_tree(root,num,0,0);
       printf("\n\nINPUT ARRAY :");
       for(i=num-1;i>=0;i--)
              printf(" %d",input[i]);
      
       printf("\n\n");

       //print all sums possible
       /*for(i=sum_count-1;i>=0;i--)
       {
              if(print_subsets(root,sums[i],input,subsets,num,num))
                     printf("\n********** SUBSETS WITH SUM = %d **********",sums[i]);
       }*/


       //print  a particular sum
       printf("\n\nENTER SUM: ");
       scanf("%d",&sum);
       printf("\n********** SUBSETS WITH SUM = %d **********",sum);
       if(!print_subsets(root,sum,input,subsets,num,num))
              printf("\n\nOOPS : NO SUBSET CAN BE FOUND");

       printf("\n\n\n");
       return 0;
}

int print_subsets(TNODE *node,int sum,int *input,int *subsets,int index,int num)
{
       int i,found=0,a,b;

       if(node->left==NULL && node->right == NULL)
       {
              if(node->data == sum)
              {
                     printf("\n{ ");
                     for(i=0;i<num;i++)
                           if(subsets[i] == 1)
                           {
                                  found = 1;
                                  printf("%d,",input[i]);
                           }

                     if(found)
                           printf("\b } ");
                     else
                           printf("NULL SET }");

                     return 1;
              }
              else
                     return 0;
       }
       if(node->left)
       {
              subsets[index-1] = 1;
              a=print_subsets(node->left,sum,input,subsets,index-1,num);
       }
       if(node->right)
       {
              subsets[index-1] = 0;
              b=print_subsets(node->right,sum,input,subsets,index-1,num);
       }

       return (a||b);
}

void print_tree(TNODE *root,int level,int col,int row)
{
       int gap,pos,slash;
       int i;
       int bcol,brow;

       if(level>MAX_PRINT_LEVEL)
       {
              printf("\nTree cant be displayed for level > %d...",MAX_PRINT_LEVEL);
              return;
       }
       gap = pow(2,level) - 1;
       bcol = col;
       brow = row;

       col=col+gap;
       gotoxy(col,row);

       printf("%d",root->data);
       if(root->left)
       {
              slash = pow(2,level-1);
              for(i=0;i<slash;i++)
              {
                     gotoxy(--col,++row);
                     printf("/");
              }
              print_tree(root->left,level-1,bcol,row+1);
       }
       if(root->right)
       {
              col = bcol+gap;
              row = brow;
              slash = pow(2,level-1);
              for(i=0;i<slash;i++)
              {
                     gotoxy(++col,++row);
                     printf("\\");
              }
              if(level>1)
                     print_tree(root->right,level-1,bcol+gap+1,row+1);
              else
                     print_tree(root->right,level-1,bcol+gap+1,row+2);
       }
}

int pow(int a, int b)
{
       int ans=1;

       if(b==0)
              return 1;

       while(b>0)
       {
              ans = ans * a;
              b--;
       }

       return ans;
}

TNODE* create_tree(int *input,int num)
{
       TNODE *temp;
       int i;

       temp = (TNODE*)malloc(1*sizeof(TNODE));
       temp->data=0;
       temp->left=NULL;
       temp->right=NULL;

       add_num(temp,input,num);

       return temp;
}

void add_num(TNODE *node,int *input,int num)
{
       if(num == 0)
       {
              //array to store all possible sums, remove if not neeeded
              /*sums[sum_count++] = node->data;*/

              return;
       }

       node->left=(TNODE*)malloc(1*sizeof(TNODE));
       node->right=(TNODE*)malloc(1*sizeof(TNODE));

       node->left->data = node->data + input[num-1];
       node->left->left = NULL;
       node->left->right = NULL;

       node->right->data = node->data + 0;
       node->right->left = NULL;
       node->right->right = NULL;

       add_num(node->left,input,num-1);
       add_num(node->right,input,num-1);
}

Recursive Decent Parser


Sample Output when syntax is correct

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>

#define MAX   100

#define ID           261           //identifier
#define ARRAY        262           //array
#define COMMA        265           //','
#define SMCOLON      266           //';'
#define PNTR         267           //pointer
#define OBRCS        268           //'{'
#define CBRCS        269           //'}'
#define INVALID      270           //not a valid type for our tokens

#define FAILURE      0
#define SUCCESS      1

//this program will now detect Structure declaration like " struct abc{int a,*v,p[]; float e,*o,y[]; char r,*t,w[];}; "
//grammer:
//     str_stmt      ->     struct sname{ dec_list };
//     dec_list      ->     dec_stmt rest_stmts
//     rest_stmts    ->     dec_stmt rest_stmts | NULL
//     dec_stmt      ->     type var_list;
//     type          ->     int | float | char
//     var_list      ->     var rest_list
//     rest_list     ->     , var_list | NULL
//     sname         ->     ID
//     var                  ->     ID
//                                |ARRAY
//                                |PNTR

char str[MAX];             //our input string
char token[MAX];           //contains a token
int token_type;            //the type of token
char *s;                   //pointer to str
void get_token();          //function to get next token

int str_stmt();            //struct statement
int dec_list();            //declaration of struct members
int rest_stmts();          //rest of dec_stmts if there
int dec_stmt();            //function to verify declaration syntax
int type();                //function to check type
int var_list();            //function to check varaible syntax
int rest_list();           //fuction to check variable list,rest_list and var_list work               recursively and call each other

int main()
{
       while(1)
       {
              s=str;
              printf("\nENTER DECLARTATION SYNTAX: ");
              gets(s);

              if( str_stmt() )
                     printf("\n\n***** SYNTAX CORRECT *****\n\n");
              else
                     printf("\n\n***** SYNTAX INCORRECT *****\n\n");       
       }

       return 0;
}

int str_stmt()
{
       get_token();
       if(strcmp(token,"struct") == 0)
       {
              printf("\tMATCHED KEYWORD    : %s",token);
              get_token();
              if(token_type == ID)
              {
                     printf("\tMATCHED IDENTIFIER : %s",token);
                     get_token();
                     if(token_type == OBRCS)
                     {
                           printf("\tMATCHED OBRCS      : %s",token);
                           if(dec_list())
                                  return SUCCESS;
                     }
                     else
                           printf("\tExpecting '{'");
              }
              else
                     printf("\tExpecting struct name.");
       }
       else
              printf("\tExpecting struct keyword");

       return FAILURE;
}

int dec_list()
{
       get_token();
       if(dec_stmt())
       {
              printf("\n\t\t\t\t\t-> MATCHED DEC_STMT");
              if(rest_stmts())
                     return SUCCESS;
       }
       else
              printf("\n\t\t\t\t\t-> DEC_STMT INCORRECT");
       return FAILURE;
}

int rest_stmts()
{
       get_token();
       if(token_type == CBRCS)
       {
              printf("\tMATCHED CBRCS      : %s",token);
              get_token();
              if(token_type == SMCOLON)
              {
                     printf("\tMATCHED SMCOLON    : %s",token);
                     return SUCCESS;
              }
              else
                     printf("\tExpecting ';'");
       }
       else if(dec_stmt())
       {
              printf("\n\t\t\t\t\t-> MATCHED DEC_STMT");
              if(rest_stmts())
                     return SUCCESS;
       }
       else
              printf("\n\t\t\t\t\t->Expecting valid dec_stmt or '}'.");

       return FAILURE;
}

int dec_stmt()
{
       if( (strcmp(token,"int") == 0) ||(strcmp(token,"float") == 0) || (strcmp(token,"char") == 0) )
       {
              printf("\tMATCHED TYPE       : %s",token);
              if(var_list() )
                     return SUCCESS;
       }
       else
              printf("\tExpecting correct TYPE");

       return FAILURE;
}

int var_list()
{
       get_token();
       if(token_type == ID)
       {
              printf("\tMATCHED IDENTIFIER : %s",token);
              if( rest_list() )
                     return SUCCESS;
       }
       else if(token_type == ARRAY)
       {
              printf("\tMATCHED ARRAY-ID   : %s",token);
              if( rest_list() )
                     return SUCCESS;
       }
       else if(token_type == PNTR)
       {
              printf("\tMATCHED POINTER    : %s",token);
              if( rest_list() )
                     return SUCCESS;
       }
       else
              printf("\tExpecting an ID, POINTER or ARRAY");

       return FAILURE;
}

int rest_list()
{
       get_token();

       if(token_type == COMMA)
       {
              printf("\tMATCHED COMMA      : %s",token);
              if( var_list() )
                     return SUCCESS;
       }
       else if(token_type == SMCOLON)
       {
              printf("\tMATCHED SMCOLON    : %s",token);
              return SUCCESS;
       }
       else
              printf("\tExpecting ',' or ';'");
      
       return FAILURE;
}

void get_token()
{
       //before writing this function, remember this is the base of whole program
       //have in mind what we need : ID ARRAY ( ) , ; =
       //rest are invalid for our needs right now
       char* tostr_tt(int token_type);

       int i = 0;                        //index for token string

       while(*s == ' ' || *s == '\t')    //eat white spaces
              s++;

       if(*s == '*')  //pointer
       {
              token[i++] = *s++;
              if(isalpha(*s) || *s == '_')
              {
                     token_type=PNTR;
                     while(isalnum(*s) || *s == '_')   //while token is a valid ID
                           token[i++] = *s++;
              }
              else
                     token_type=INVALID;

              token[i] = '\0';
       }
       else if( isalpha(*s) || *s == '_')       //if current token starts with an alphaber or _ it is an ID
       {
              token_type=ID;
              while(isalnum(*s) || *s == '_')   //while token is a valid ID
              {
                     token[i++] = *s++;
              }

              token[i] = '\0';
       }
       else
       {
              if(*s == ',')
                     token_type = COMMA;
              else if(*s == ';')
                     token_type = SMCOLON;
              else if(*s == '{')
                     token_type = OBRCS;
              else if(*s == '}')
                     token_type = CBRCS;
              else
                     token_type = INVALID;
              token[i++] = *s++;
              token[i] = '\0';
       }

       if(token_type == ID)  //array is ID[]
       {
              if(*s == '[')
              {
                     token_type = INVALID;
                     token[i++] = '[';
                     s++;
                     if(*s == ']')
                     {
                           token_type = ARRAY;
                           token[i++] = ']';
                           s++;
                     }
                     token[i] = '\0';
              }
       }

       printf("\nTOKEN : %s\t\tTYPE:%-10s",token,tostr_tt(token_type));
}

char* tostr_tt(int token_type)
{
       switch(token_type)
       {
              case ID:             return "ID";         break;
              case ARRAY:          return "ARRAY";      break;
              case COMMA:          return "COMMA";      break;
              case SMCOLON:        return "SMCOLON";    break;
              case PNTR:           return "POINTER";    break;
              case OBRCS:          return "OBRACES";    break;
              case CBRCS:          return "CBRACES";    break;
              case INVALID:        return "INVALID";    break;
              default:             return "ERROR";      break;

       }     
}