WorldSim  inDev
2D tile-based sandbox RPG with procedurally generated fantasy world simulator 🌏
Recipe.hpp
Go to the documentation of this file.
1 #pragma once
2 #ifndef WORLDSIM_RECIPE_HPP
3 #define WORLDSIM_RECIPE_HPP
4 
5 /* Recipe.hpp
6  #include "Recipe.hpp"
7 
8 A recipe is any collection of objects which can be consumed to make another object. Usually there are three types
9 of recipes: Alchemy, crafting and cooking. I think most inputs/outputs will be items. But hey you never know.
10 
11 There are a lot of things to deal with here. For example what if you can make an object using either 2 wood or 2 metal,
12 but not one of each? For now I'm bypassing this by just creating a class for every non-inclusive recipe. So for example
13 you can have a Wooden_Wall_Recipe and a Stone_Wall_Recipe.
14 
15 There's a Crafting Manager to figure out what can and can't be made from the inventory. It uses double dispatch.
16 Basically each Item sends itself to the Manager which sorts it into each recipe. The recipes recieve the items if they
17 are relevant and keep an internal total of how many valid items they have been given. From that we can easily obtain
18 a list of all recipes which can be made with the current set of items. We can also figure out what an item can be used
19 for.
20 
21 I have no idea if this implementation is a good one. However I believe Minecraft just used typeId so fuck it, we'll
22 do it live.
23 
24 A proper polymorphic abstraction system would probably break up craftable items into components. However realistically
25 I don't think that's going to happen because some Recipes might depend on outputs from other recipes.
26 
27 One alternate possibility is having certain Items inherit a Craftable interface. But idk if it'll work out.
28 
29 Recipe_Wooden_Wall and Recipe_Stone_Wall should link to each other as variants, so they can be indicated as such in GUI
30 
31 Recipes could probably be grouped into categories. For example Wooden_Wall, Brick_Wall, Stone_Wall and Palisade could
32 all be of type Wall. The AI might mainly concern itself with building a wall, not the type of wall.
33 
34 A Wall Manager could decide which wall the AI should build in the circumstances.
35 
36 It's possible to override this system by using getName(), which basically functions as a typeID system.
37 
38 */
39 
40 class Item_Log;
41 class Item_Plank;
42 class Item_DeerPelt;
43 
44 class Recipe
45 {
46  public:
47 
48  Vector <WorldObject*> vInput;
50 
51  Recipe();
52  ~Recipe();
53 
54  /* Add a requirement to make this recipe. count is how many of the object you need. isConsumed true if the items
55  are removed from the world when you make this recipe */
56  void addRequirement(WorldObject* _object, int count, bool isConsumed);
57  void addRequirement(Item* _object, int count, bool isConsumed);
58 
59 
60  // Using double dispatch because I can't think of anything better
61  // In future we might decide on a small list of raw crafting inputs and just worry about those.
62  virtual int canUse (WorldObject*) /* return the amount of object needed. -1 means this object can't be used */
63  { return -1; }
64  // Every item must be listed here in order to specialise the base class.
65  virtual int canUse (Item *) { return -1; }
66  virtual int canUse (Item_Plank *) { return -1; }
67  virtual int canUse (Item_Log*) { return -1; }
68  virtual int canUse (Item_Fish *) { return -1; }
69  virtual int canUse (Item_DeerPelt *) { return -1; }
70 
71 
72  /* These should probably be in recipe manager. */
73  /* recipe will take object and add it up to determine how many of this recipe can be made */
74  virtual void countUp(WorldObject*) {}
75  virtual void countUp(Item*) {}
76  virtual void countUp(Item_Plank*) {}
77  virtual void countUp(Item_Log*) {}
78  virtual void countUp(Item_Fish*) {}
79  virtual void countUp(Item_DeerPelt*) {}
80 
81  virtual void make(Character*) { std::cout<<"RECIPE MAKED\n"; }
82 
83  virtual int getTotal()
84  {
85  return 0;
86  }
87 
88  virtual std::string getName()
89  {
90  return "Generic recipe";
91  }
92 
93 };
94 
95 class Recipe_Wall: public Recipe
96 {
97  public:
98  Vector <Item_Plank*> vPlank;
99 
100  virtual int canUse (Item_Plank * _object) override /* return the amount of object needed. -1 means this object can't be used */
101  {
102  std::cout<<"Item_Plank\n";
103  return 3;
104  }
105 
106  virtual std::string getName() override
107  {
108  return "Wooden Wall";
109  }
110 
111  virtual void countUp(WorldObject* _object) override {}
112  virtual void countUp(Item* _item) override {}
113  virtual void countUp(Item_Plank* _plank) override
114  {
115  vPlank.push(_plank);
116  }
117 
118  virtual int getTotal() override
119  {
120  // 5 planks to make a wall.
121  return (vPlank.size()/2);
122  }
123 };
125 
127 {
128  public:
129 
130  Vector <Item_Fish*> vFish;
131 
132  virtual int canUse (Item_Fish * _object) override /* return the amount of object needed. -1 means this object can't be used */
133  {
134  std::cout<<"Item_Fish\n";
135  return 3;
136  }
137 
138  virtual std::string getName() override
139  {
140  return "Grilled fish";
141  }
142 
143  virtual void countUp(WorldObject* _object) override {}
144  virtual void countUp(Item* _item) override {}
145  virtual void countUp(Item_Fish* _plank) override
146  {
147  std::cout<<"Addfish\n";
148  vFish.push(_plank);
149  }
150 
151  virtual int getTotal() override
152  {
153  std::cout<<"FISH: "<<vFish.size()<<"\n";
154  // 5 planks to make a wall.
155  return vFish.size();
156  }
157 };
159 
160 // LEATHER CLOTHES
161 // 5 of any pelt
163 {
164  public:
165 
166  Vector <Item_DeerPelt*> vPelt;
167 
168  virtual int canUse (Item_DeerPelt * _object) override /* return the amount of object needed. -1 means this object can't be used */
169  {
170  std::cout<<"Pelts\n";
171  return 1;
172  }
173 
174  virtual std::string getName() override
175  {
176  return "Leather clothes";
177  }
178 
179  virtual void countUp(WorldObject* _object) override {}
180  virtual void countUp(Item* _item) override {}
181  virtual void countUp(Item_DeerPelt* _input) override
182  {
183  std::cout<<"Add pelt\n";
184  vPelt.push(_input);
185  }
186 
187  virtual int getTotal() override
188  {
189  std::cout<<"PELTS: "<<vPelt.size()<<"\n";
190  // 5 pelts to make clothes.
191  return vPelt.size();
192  }
193 
194  virtual void make(Character* _character) override;
195 
196 };
198 
199 // Waterskin
200 // 1 of any pelt
202 {
203  public:
204 
205  Vector <Item_DeerPelt*> vPelt;
206 
207  virtual int canUse (Item_DeerPelt * _object) override /* return the amount of object needed. -1 means this object can't be used */
208  {
209  std::cout<<"Pelts\n";
210  return 1;
211  }
212 
213  virtual std::string getName() override
214  {
215  return "Waterskin";
216  }
217 
218  virtual void countUp(WorldObject* _object) override {}
219  virtual void countUp(Item* _item) override {}
220  virtual void countUp(Item_DeerPelt* _input) override
221  {
222  std::cout<<"Add pelt\n";
223  vPelt.push(_input);
224  }
225 
226  virtual int getTotal() override
227  {
228  std::cout<<"PELTS: "<<vPelt.size()<<"\n";
229  // 5 pelts to make clothes.
230  return vPelt.size();
231  }
232 
233  virtual void make(Character* _character) override;
234 
235 };
237 
238 // Log Shelter
239 // 1 of any pelt
241 {
242  public:
243 
244  Vector <Item_Log*> vInput;
245 
246  virtual int canUse (Item_Log * _object) override /* return the amount of object needed. -1 means this object can't be used */
247  {
248  return 1;
249  }
250 
251  virtual std::string getName() override
252  {
253  return "Shelter";
254  }
255 
256  virtual void countUp(WorldObject* _object) override {}
257  virtual void countUp(Item* _item) override {}
258  virtual void countUp(Item_Log* _input) override
259  {
260  std::cout<<"Adding log shelt\n";
261  vInput.push(_input);
262  }
263 
264  virtual int getTotal() override
265  {
266  std::cout<<" log shelt\n";
267  // 5 pelts to make clothes.
268  return vInput.size();
269  }
270 
271  virtual void make(Character* _character) override;
272 
273 };
275 
276 // Inventory manager can give 2 types of information. What recipes can be made with current items. And also what reciped
277 // an item can be used in.
279 {
280  public:
281 
282  int x,y; /* Where to put output */
283 
284  /* List of Recipes which can be made based on inputs */
285  Vector <Recipe*> vValidList;
286 
287  //put one of every recipe here
288 
289  Vector <Recipe*> vRecipe;
290 
291  int canUse (Item_Plank* _object)
292  {
293  return -1;
294  }
295 
296  void addRecipe(Recipe* _recipe)
297  {
298  vRecipe.push(_recipe);
299  }
300 
302  {
303  std::cout<<"Adding item\n";
304  }
306  {
307  std::cout<<"Adding plank\n";
308  recipeWall.countUp(_item);
309  }
310  void addToRecipes(Item_Fish* _item)
311  {
312  std::cout<<"adding fish\n";
313  recipeGrilledFish.countUp(_item);
314  }
316  {
317  recipeLeatherClothes.countUp(_item);
318  recipeWaterskin.countUp(_item);
319  }
320  void addToRecipes(Item_Log* _item)
321  {
322  std::cout<<"adding log\n";
323  recipeLogShelter.countUp(_item);
324  }
325 
326  int getTotals()
327  {
328  return recipeWall.getTotal();
329  return recipeGrilledFish.getTotal();
330  return recipeLeatherClothes.getTotal();
331  return recipeWaterskin.getTotal();
332  return recipeLogShelter.getTotal();
333  }
334 
335  Vector <Recipe*> * getValidRecipes()
336  {
337  vValidList.clear();
338  if ( recipeWall.getTotal() > 0 )
339  {
340  vValidList.push(&recipeWall);
341  }
342  if ( recipeGrilledFish.getTotal() > 0 )
343  {
344  vValidList.push(&recipeGrilledFish);
345  }
346  if ( recipeLeatherClothes.getTotal() > 0 )
347  {
348  vValidList.push(&recipeLeatherClothes);
349  }
350  if ( recipeWaterskin.getTotal() > 0 )
351  {
352  vValidList.push(&recipeWaterskin);
353  }
354  if ( recipeLogShelter.getTotal() > 0 )
355  {
356  vValidList.push(&recipeLogShelter);
357  }
358  return &vValidList;
359  }
360 
361  void makeRecipe(Character* _character, int _index)
362  {
363  if (vValidList.isSafe(_index))
364  {
365  std::cout<<"Making: "<<vValidList(_index)->getName()<<".\n";
366  vValidList(_index)->make(_character);
367  }
368  }
369 
370  std::string getPrerequisites()
371  {
372  std::string sPrerequisites = "";
373  for (int i=0;i<recipeGrilledFish.vInput.size();++i)
374  {
375  sPrerequisites+=recipeGrilledFish.vInput(i)->getName();
376  }
377  return sPrerequisites;
378  }
379 
380  // int canMakeRecipe(Recipe_Wall* _recipe, Vector <Item*> vInventory)
381  // {
382  // int nPlank=0;
383  // // for (int i=0;i<vInventory.size();++i)
384  // // {
385  // // if (recipeWall.canUse(vInventory(i))
386  // // {
387  // // ++nPlank;
388  // // }
389  // // }
390  // return nPlank;
391  // }
392 
393 
394 };
396 
397 #endif
virtual int canUse(Item *)
Definition: Recipe.hpp:65
virtual void countUp(Item_Log *)
Definition: Recipe.hpp:77
Definition: WorldObject.hpp:18
virtual void countUp(Item_Plank *_plank) override
Definition: Recipe.hpp:113
Vector< Item_DeerPelt * > vPelt
Definition: Recipe.hpp:166
virtual void make(Character *)
Definition: Recipe.hpp:81
virtual void countUp(Item *_item) override
Definition: Recipe.hpp:257
virtual void countUp(WorldObject *_object) override
Definition: Recipe.hpp:111
virtual std::string getName()
Definition: Recipe.hpp:88
virtual void countUp(WorldObject *)
Definition: Recipe.hpp:74
Vector< Item_Log * > vInput
Definition: Recipe.hpp:244
virtual void countUp(WorldObject *_object) override
Definition: Recipe.hpp:179
Vector< Recipe * > vValidList
Definition: Recipe.hpp:285
Vector< Item_DeerPelt * > vPelt
Definition: Recipe.hpp:205
virtual int getTotal() override
Definition: Recipe.hpp:118
int getTotals()
Definition: Recipe.hpp:326
virtual int getTotal() override
Definition: Recipe.hpp:187
virtual std::string getName() override
Definition: Recipe.hpp:213
virtual void countUp(Item_Fish *_plank) override
Definition: Recipe.hpp:145
Recipe_GrilledFish recipeGrilledFish
Definition: Recipe.hpp:158
Recipe_Wall recipeWall
Definition: Recipe.hpp:124
virtual int canUse(Item_Fish *_object) override
Definition: Recipe.hpp:132
Item * output
Definition: Recipe.hpp:49
Vector< Recipe * > vRecipe
Definition: Recipe.hpp:289
Vector< WorldObject * > vInput
Definition: Recipe.hpp:48
Definition: Recipe.hpp:278
virtual void countUp(Item_DeerPelt *)
Definition: Recipe.hpp:79
virtual void countUp(Item_Plank *)
Definition: Recipe.hpp:76
virtual int canUse(Item_DeerPelt *)
Definition: Recipe.hpp:69
virtual void countUp(Item_DeerPelt *_input) override
Definition: Recipe.hpp:181
Recipe()
Definition: Recipe.cpp:14
Definition: Recipe.hpp:201
virtual int canUse(Item_DeerPelt *_object) override
Definition: Recipe.hpp:168
virtual void countUp(Item_Fish *)
Definition: Recipe.hpp:78
Definition: Item.hpp:51
Definition: Recipe.hpp:44
Definition: Item.hpp:887
Vector< Item_Fish * > vFish
Definition: Recipe.hpp:130
virtual void countUp(WorldObject *_object) override
Definition: Recipe.hpp:256
virtual int getTotal() override
Definition: Recipe.hpp:151
virtual int getTotal() override
Definition: Recipe.hpp:226
virtual int canUse(Item_Log *_object) override
Definition: Recipe.hpp:246
virtual std::string getName() override
Definition: Recipe.hpp:138
void addToRecipes(Item *)
Definition: Recipe.hpp:301
void addToRecipes(Item_Plank *_item)
Definition: Recipe.hpp:305
virtual int canUse(Item_Plank *_object) override
Definition: Recipe.hpp:100
Recipe_LogShelter recipeLogShelter
Definition: Recipe.hpp:274
virtual void countUp(Item *)
Definition: Recipe.hpp:75
virtual int getTotal()
Definition: Recipe.hpp:83
Definition: Recipe.hpp:240
virtual int canUse(Item_Log *)
Definition: Recipe.hpp:67
void addToRecipes(Item_DeerPelt *_item)
Definition: Recipe.hpp:315
Vector< Recipe * > * getValidRecipes()
Definition: Recipe.hpp:335
Recipe_LeatherClothes recipeLeatherClothes
Definition: Recipe.hpp:197
void makeRecipe(Character *_character, int _index)
Definition: Recipe.hpp:361
Definition: Character.hpp:38
Definition: Recipe.hpp:162
virtual void countUp(WorldObject *_object) override
Definition: Recipe.hpp:218
void addToRecipes(Item_Log *_item)
Definition: Recipe.hpp:320
virtual void countUp(WorldObject *_object) override
Definition: Recipe.hpp:143
Definition: Recipe.hpp:126
virtual void countUp(Item *_item) override
Definition: Recipe.hpp:180
int canUse(Item_Plank *_object)
Definition: Recipe.hpp:291
void addRequirement(WorldObject *_object, int count, bool isConsumed)
Definition: Recipe.cpp:23
Recipe_Waterskin recipeWaterskin
Definition: Recipe.hpp:236
Definition: Item.hpp:737
virtual int canUse(Item_DeerPelt *_object) override
Definition: Recipe.hpp:207
virtual void countUp(Item *_item) override
Definition: Recipe.hpp:219
std::string getPrerequisites()
Definition: Recipe.hpp:370
virtual std::string getName() override
Definition: Recipe.hpp:251
void addRecipe(Recipe *_recipe)
Definition: Recipe.hpp:296
virtual void countUp(Item *_item) override
Definition: Recipe.hpp:112
virtual int canUse(Item_Fish *)
Definition: Recipe.hpp:68
int y
Definition: Recipe.hpp:282
virtual int canUse(WorldObject *)
Definition: Recipe.hpp:62
Definition: Recipe.hpp:95
~Recipe()
Definition: Recipe.cpp:19
Definition: Item.hpp:805
virtual void countUp(Item *_item) override
Definition: Recipe.hpp:144
Vector< Item_Plank * > vPlank
Definition: Recipe.hpp:98
Definition: Item.hpp:687
RecipeManager recipeManager
Definition: Recipe.hpp:395
virtual int getTotal() override
Definition: Recipe.hpp:264
virtual std::string getName() override
Definition: Recipe.hpp:106
virtual void countUp(Item_DeerPelt *_input) override
Definition: Recipe.hpp:220
virtual int canUse(Item_Plank *)
Definition: Recipe.hpp:66
virtual std::string getName() override
Definition: Recipe.hpp:174
void addToRecipes(Item_Fish *_item)
Definition: Recipe.hpp:310
virtual void countUp(Item_Log *_input) override
Definition: Recipe.hpp:258