Advertisement

Struggling with a small and simple bit of logic

Started by April 03, 2018 01:26 PM
9 comments, last by Lactose 6 years, 8 months ago

Hi =)

"Logic" is, quite sadly, my kryptonite and I am not exaggerating. Ask me a negated question and I will almost always answer incorrectly, and yes, that's outside of programming. I've taken courses on logic (from "this is what AND looks like" up to university-level courses, had an awesome private teacher for it for a couple of months, sadly with almost no effect. I struggle with learning any kind of language wich seems to love negated questions (I'm looking at you, spanish). It feels like my brain is coated in logic-repelling teflon and it is driving me nuts when I try to program stuff.

When it comes to programming, logic parts are almost always brute force try and error for me. I can build simple things like "if (x = 2 && y = 2)" (though sadly, nothing more complex), though "if (x = 2 || y =3)" still needs some time to think to understand what I am going to do. Usually, I use LEGO-stones on my desk to visualize what might happen and even then, I predict the wrong result quite regularly.

(Problem starts here) But now, I am at a part of my game, which I build in Unity, where I have to check if my player got the crafting materials needed for something either in his inventory or is storage area. To me, this is not a simple x=2 && y=2 thing, it is a bit more complex and I struggle a lot with how to make it work. Some help would be dearly appreciated.

This is how it looks like in my code right now:


for (int i = 0 ; i < neededmaterials ; i++)
        {
            if (!HasEnoughItems(item.craftmaterial_Menge[i], item.craftmaterial[i].currentlyIn_Inventory))
            {
                Debug.Log("not enough materials in Inventory");
                return; 
            }
        }

This part just checks if I have enough materials in my inventory and it works great, as long as I just want to check said inventory.

Now, I want to expand it to check for the materials in my inventory, as well as my storage area and added it like this right underneath the first if-statement inside the same for-loop seen above:


else if (!HasEnoughItems(item.craftmaterial_Menge[i], item.craftmaterial[i].currentlyIn_Lagerhaus))
	{
		Debug.Log("Not enough materials in storage");
		return; //Exit from the funtion
	}

The way I understand it, it should first check if I have the materials in my inventory. If there are none, check the material in my storage. If the second fails, too, the rest of the script won't be loaded. But if I have enough materials in either my storage area or my inventory, the rest of the script will run. If I would have to write it out in logic terms, it would look rougly something like this: "If inventory && storage == false, end function" and "if inventory || storage == true, run rest of script".

Interestingly enough, when I play the game with these two parts of script, it fails to craft no matter if I have enough materals either in my inventory or my storage area. For example: I have 2 wood and 3 iron in my inventory - enough to craft a sword. I click on the sword, starting the crafting-function. It looks for the materials in my inventory: Check, all that is needed is there. Superflously, it checks for materials in my storage next: Nope, none can be found, crafting won't happen - even though enough materials are at least in my inventory. Worse, if I want to craft with an empty inventory.

The rest of the function will only load if I have enough materials in my inventory as well as my storage area.

And I don't understand why.

I tried to comment out the first return where it looks for items in my inventory, thinking that it will probably just end the search for more materals and I think it might have helped a bit, but the end-result stays the same :|

Could somebody please explain to me, why this happens?

EDIT: Crossed this out because at a second glance, it looks like you will always bail out after the first check. As Lactose has said below, you either need to condense your code to make the "x or y" into a single check, or you need to count up the total items separately.

Also, as a suggestion, you want to get into the habit of simplifying your code lines and function names - that will mean that your code starts to look a lot more like the simpler '(x = 2 || y =3)' style.

The logic of your two if-checks looks reasonable (although you don't need the 'else' before the if, because the function will never reach the second check if the first condition was true). However, it's hard to be certain because we'd need to see the whole thing in context.

So, given that the logic is reasonable, the implementation is broken somewhere. So, you need to be methodical about your debugging:

  • You say "it fails to craft" but what does that mean? You've not posted the code between these if-checks and the actual crafting. You will need to add more Debug.Log calls to show the progress of the code.
  • What do currentlyIn_Inventory and currentlyIn_Lagerhaus mean? What type are those variables? Where are they set? What happens if you output them via a Debug.Log right before these if statements?
  • What is neededmaterials? What type, what value? Again, if you log it, what does it say?
Advertisement

As @Kylotan pointed out, the basic logic of your if-statements is sound. However, it looks like somewhere, something else is broken. Are you changing the array variables anywhere else in your code? It'd be helpful to see some more code. It's a bit tough to tell what's going on from these isolated segments. 

No one expects the Spanish Inquisition!

I would personally approach the problem like this:

You have some object that keeps tables of all your crafting requirements. For example, to build a chair you need 2 wood and 4 metal. When the user is attempting to craft you can simply pass in the inventory and storage list into a function which will do a direct check to confirm if crafting is possible by either inventory, storage or both.

I made an example for you to follow. It's not the "cleanest" but it will give you an idea of how to manage this. I rarely code in C# anymore as I'm usually programming in C++ so I apologize if I've done something a bit "off".


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{ 

    class Crafting
    {
        public bool craftChair(ref Player tPlayer)
        {
            // 2 Wood
            int itemIDWood = 0;
            int itemAmountNeededWood = 2;

            // 4 Metal
            int itemIDMetal = 1;
            int itemAmountNeededMetal = 4;

            bool itemCrafted = false;

            // Inventory Check
            if (tPlayer.getCraftingMaterialAmountFromInventory(itemIDWood) >= itemAmountNeededWood &&
                tPlayer.getCraftingMaterialAmountFromInventory(itemIDMetal) >= itemAmountNeededMetal)
            {
                tPlayer.removeCraftingMaterialFromInventory(itemIDWood, itemAmountNeededWood);
                tPlayer.removeCraftingMaterialFromInventory(itemIDMetal, itemAmountNeededMetal);

                Console.WriteLine("Chair Crafted From Inventory!");
                itemCrafted = true;
            }
            else
            {
                Console.WriteLine("Not Enough Materials In Inventory! Checking Storage!");
            }

            // Storage Check
            if (itemCrafted == false)
            {
                if (tPlayer.getCraftingMaterialAmountFromStorage(itemIDWood) >= itemAmountNeededWood &&
                    tPlayer.getCraftingMaterialAmountFromStorage(itemIDMetal) >= itemAmountNeededMetal)
                {
                    tPlayer.removeCraftingMaterialFromStorage(itemIDWood, itemAmountNeededWood);
                    tPlayer.removeCraftingMaterialFromStorage(itemIDMetal, itemAmountNeededMetal);

                    Console.WriteLine("Chair Crafted From Storage!");
                    itemCrafted = true;
                }
                else
                {
                    Console.WriteLine("Not Enough Materials In Storage! Checking Combined!");
                }
            }

            if (itemCrafted == false)
            {
                // Combined Check
                if (tPlayer.getCraftingMaterialAmountFromInventory(itemIDWood) + tPlayer.getCraftingMaterialAmountFromStorage(itemIDWood) >= itemAmountNeededWood &&
                tPlayer.getCraftingMaterialAmountFromInventory(itemIDMetal) + tPlayer.getCraftingMaterialAmountFromStorage(itemIDMetal) >= itemAmountNeededMetal)
                {
                    int woodCost = itemAmountNeededWood;
                    int metalCost = itemAmountNeededMetal;

                    while (woodCost != 0)
                    {
                        if (tPlayer.getCraftingMaterialAmountFromInventory(0) > 0)
                        {
                            tPlayer.removeCraftingMaterialFromInventory(0, 1);
                            woodCost--;
                        }
                        else if (tPlayer.getCraftingMaterialAmountFromStorage(0) > 0)
                        {
                            tPlayer.removeCraftingMaterialFromStorage(0, 1);
                            woodCost--;
                        }
                    }

                    while (metalCost != 0)
                    {
                        if (tPlayer.getCraftingMaterialAmountFromInventory(1) > 0)
                        {
                            tPlayer.removeCraftingMaterialFromInventory(1, 1);
                            metalCost--;
                        }
                        else if (tPlayer.getCraftingMaterialAmountFromStorage(1) > 0)
                        {
                            tPlayer.removeCraftingMaterialFromStorage(1, 1);
                            metalCost--;
                        }
                    }

                    Console.WriteLine("Chair Crafted From Inventory + Storage!");
                    itemCrafted = true;
                }
                else
                {
                    Console.WriteLine("Not Enough Materials In Inventory or Storage combined!");
                }
            }
            

            // Item Crafted - Craft
            if (itemCrafted == true)
            {
                return true;
            } else
            {
                return false;
            }
            
        }
    }
    class CraftingMaterial
    {
        public string name { get; set; }
        public int amount { get; set; }
    }

    class Player
    {
        private List<CraftingMaterial> craftingMaterialInventory = new List<CraftingMaterial>();
        private List<CraftingMaterial> craftingMaterialStorage = new List<CraftingMaterial>();

        public Player()
        {
            // Keys:
            // 0 = Wood
            // 1 = Metal

            // Setup Inventory
            craftingMaterialInventory.Add(new CraftingMaterial { name = "Wood", amount = 0 });
            craftingMaterialInventory.Add(new CraftingMaterial { name = "Metal", amount = 0 });

            // Setup Storage
            craftingMaterialStorage.Add(new CraftingMaterial { name = "Wood", amount = 0 });
            craftingMaterialStorage.Add(new CraftingMaterial { name = "Metal", amount = 0 });
        }

        public void printInventory()
        {
            Console.WriteLine();
            Console.WriteLine("Player: Inventory");

            for (int a = 0; a < craftingMaterialInventory.Count(); a++)
            {
                Console.WriteLine(craftingMaterialInventory[a].name + " : " + craftingMaterialInventory[a].amount);
            }
        }

        public void printStorage()
        {
            Console.WriteLine();
            Console.WriteLine("Player: Storage");

            for (int a = 0; a < craftingMaterialStorage.Count(); a++)
            {
                Console.WriteLine(craftingMaterialStorage[a].name + " : " + craftingMaterialStorage[a].amount);
            }
        }

        public void addCraftingMaterialToInventory(int tCraftingID, int tAmount)
        {
            craftingMaterialInventory[tCraftingID].amount += tAmount;
        }

        public void addCraftingMaterialToStorage(int tCraftingID, int tAmount)
        {
            craftingMaterialStorage[tCraftingID].amount += tAmount;
        }

        public void removeCraftingMaterialFromInventory(int tCraftingID, int tAmount)
        {
            craftingMaterialInventory[tCraftingID].amount -= tAmount;
        }

        public void removeCraftingMaterialFromStorage(int tCraftingID, int tAmount)
        {
            craftingMaterialStorage[tCraftingID].amount -= tAmount;
        }

        public int getCraftingMaterialAmountFromInventory(int tCraftingID)
        {
            return craftingMaterialInventory[tCraftingID].amount;
        }

        public int getCraftingMaterialAmountFromStorage(int tCraftingID)
        {
            return craftingMaterialStorage[tCraftingID].amount;
        }

        public int getMaterialInventoryCount()
        {
            return craftingMaterialInventory.Count();
        }

        public int getMaterialStorageCount()
        {
            return craftingMaterialStorage.Count();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Crafting myCraftingTable = new Crafting();
            Player myPlayer = new Player();

            myPlayer.printInventory();
            myPlayer.printStorage();

            // Lets Add 2 Wood but 3 Metal
            myPlayer.addCraftingMaterialToInventory(0, 2);
            myPlayer.addCraftingMaterialToInventory(1, 3);

            Console.WriteLine();
            Console.WriteLine("Added 2 Wood and 3 Metal to Inventory");
            myPlayer.printInventory();
            myPlayer.printStorage();

            Console.WriteLine();
            Console.WriteLine("Try Crafting a Chair!");
            Console.WriteLine();

            if (myCraftingTable.craftChair(ref myPlayer) == true)
            {
                Console.WriteLine("Chair Crafted!");
            } else
            {
                Console.WriteLine("Chair Cannot be Crafted - Need More Materials!");
            }

            Console.WriteLine();
            Console.WriteLine("Re-Check Inventory");
            myPlayer.printInventory();
            myPlayer.printStorage();

            /////////////

            // Lets Add 2 Wood but 1 Metal
            // We should have 2 extra wood left after crafting
            myPlayer.addCraftingMaterialToInventory(0, 2);
            myPlayer.addCraftingMaterialToInventory(1, 1);

            Console.WriteLine();
            Console.WriteLine("Added 2 Wood and 1 Metal to Inventory - Should have 2 Wood left");
            myPlayer.printInventory();
            myPlayer.printStorage();

            Console.WriteLine();
            Console.WriteLine("Try Crafting a Chair!");
            Console.WriteLine();

            if (myCraftingTable.craftChair(ref myPlayer) == true)
            {
                Console.WriteLine("Chair Crafted!");
            }
            else
            {
                Console.WriteLine("Chair Cannot be Crafted - Need More Materials!");
            }

            Console.WriteLine();
            Console.WriteLine("Re-Check Inventory");
            myPlayer.printInventory();
            myPlayer.printStorage();

            /////////////

            // Lets Add 1 Wood and 4 Metal
            // We will need a combined inventory + storage to craft this
            myPlayer.addCraftingMaterialToStorage(0, 1);
            myPlayer.addCraftingMaterialToStorage(1, 4);

            Console.WriteLine();
            Console.WriteLine("Added 1 Wood and 4 Metal to Storage");
            myPlayer.printInventory();
            myPlayer.printStorage();

            if (myCraftingTable.craftChair(ref myPlayer) == true)
            {
                Console.WriteLine("Chair Crafted!");
            }
            else
            {
                Console.WriteLine("Chair Cannot be Crafted - Need More Materials!");
            }

            Console.WriteLine();
            Console.WriteLine("Re-Check Inventory");
            myPlayer.printInventory();
            myPlayer.printStorage();

            ///

            // Lets Add 1 Wood and 4 Metal
            // We will need a combined inventory + storage to craft this
            myPlayer.addCraftingMaterialToInventory(1, 4);
            myPlayer.addCraftingMaterialToStorage(0, 1);

            Console.WriteLine();
            Console.WriteLine("Added 4 Metal to Inventory and 1 Wood to Storage");
            myPlayer.printInventory();
            myPlayer.printStorage();

            if (myCraftingTable.craftChair(ref myPlayer) == true)
            {
                Console.WriteLine("Chair Crafted!");
            }
            else
            {
                Console.WriteLine("Chair Cannot be Crafted - Need More Materials!");
            }

            Console.WriteLine();
            Console.WriteLine("Re-Check Inventory");
            myPlayer.printInventory();
            myPlayer.printStorage();

            Console.ReadLine();
        }
    }
}

The console window will show as follows:
 



Player: Inventory
Wood : 0
Metal : 0

Player: Storage
Wood : 0
Metal : 0

Added 2 Wood and 3 Metal to Inventory

Player: Inventory
Wood : 2
Metal : 3

Player: Storage
Wood : 0
Metal : 0

Try Crafting a Chair!

Not Enough Materials In Inventory! Checking Storage!
Not Enough Materials In Storage! Checking Combined!
Not Enough Materials In Inventory or Storage combined!
Chair Cannot be Crafted - Need More Materials!

Re-Check Inventory

Player: Inventory
Wood : 2
Metal : 3

Player: Storage
Wood : 0
Metal : 0

Added 2 Wood and 1 Metal to Inventory - Should have 2 Wood left

Player: Inventory
Wood : 4
Metal : 4

Player: Storage
Wood : 0
Metal : 0

Try Crafting a Chair!

Chair Crafted From Inventory!
Chair Crafted!

Re-Check Inventory

Player: Inventory
Wood : 2
Metal : 0

Player: Storage
Wood : 0
Metal : 0

Added 1 Wood and 4 Metal to Storage

Player: Inventory
Wood : 2
Metal : 0

Player: Storage
Wood : 1
Metal : 4
Not Enough Materials In Inventory! Checking Storage!
Not Enough Materials In Storage! Checking Combined!
Chair Crafted From Inventory + Storage!
Chair Crafted!

Re-Check Inventory

Player: Inventory
Wood : 0
Metal : 0

Player: Storage
Wood : 1
Metal : 0

Added 4 Metal to Inventory and 1 Wood to Storage

Player: Inventory
Wood : 0
Metal : 4

Player: Storage
Wood : 2
Metal : 0
Not Enough Materials In Inventory! Checking Storage!
Not Enough Materials In Storage! Checking Combined!
Chair Crafted From Inventory + Storage!
Chair Crafted!

Re-Check Inventory

Player: Inventory
Wood : 0
Metal : 0

Player: Storage
Wood : 0
Metal : 0

Let me know if this helps, or if you need more explaining for crafting from inventory, storage, or a combination of both.

Programmer and 3D Artist

2 hours ago, Kylotan said:

The logic of your two if-checks looks reasonable

What? To me it looks all wrong.

The posted code requires the required items to be present both in the inventory AND in the storage area. If the item is missing in either location, it will trigger the return and exit.

To solve this, you can do something like the following, which will allow you to craft if you have enough in either inventory or storage:


for (int i = 0 ; i < neededmaterials; i++)
{
	bool hasEnoughInInventory = HasEnoughItems(item.craftmaterial_Menge[i], item.craftmaterial[i].currentlyIn_Inventory);
	bool hasEnoughInStorage = HasEnoughItems(item.craftmaterial_Menge[i], item.craftmaterial[i].currentlyIn_Lagerhaus);

	bool hasEnoughInEitherLocation = hasEnoughInInventory || hasEnoughInStorage;

	if !hasEnoughInEitherLocation
	{
		Debug.Log("Not enough materials in either inventory or storage.");
		return;
	}
}

//Crafting code goes here.

 

That said, the above does not cover the case where you have enough if you combine the items from the inventory with the items in storage -- if you need 5 wood, and have 3 in your inventory and 3 in your storage.

If this scenario should work, you'd want something similar to:


for (int i = 0 ; i < neededmaterials; i++)
{
	int totalItems = item.craftmaterial[i].currentlyIn_Inventory + item.craftmaterial[i].currentlyIn_Lagerhaus;
	bool hasEnoughCombined = HasEnoughItems(item.craftmaterial_Menge[i], totalItems);

	if !hasEnoughCombined
	{
		Debug.Log("Not enough materials combined in inventory and storage.");
		return;
	}
}

//Crafting code goes here.

 

In either case, you'll want to make sure you subtract the required items from the correct location.

Hello to all my stalkers.

4 minutes ago, Lactose said:

What? To me it looks all wrong.

Yeah, I think I was just baffled by the verbosity of the post and the code. I edited my original post.

 

Advertisement

Hi again :)

Yeah, I tend to use tons of words - I'll try to be shorter in the future ;)

Thank you all so much for having a look at my problem! And Lactose, thank you so much for the solution! Now, it works like a charm :D The idea to use bools was great and I put it on my list of things to consider more often.

And Kylotan, I will consider posting longer parts of my scripts, too, when I stumble upon my next problem :) This time, I tried to make it short since the whole crafting-script worked right up until I made the check for items in my storage area. So the problem had to be in the couple of lines I posted. (Furthermore, my scripts are usually a strange bilingual mess of english and german and I'm not sure if posting more would help understand what I am trying to do... One more construction site to work on ;) )

Thank you all so much for your input, it was a great help :)!

I can't see the difficulty in any of this. Then again, I am a native Spanish speaker. :)

 

 

:D Yup, my spanish teacher didn't understand how I could struggle with this, either ;D

It's not something I chose to ignore or thought "yeah, I am so not going to learn this". I've tried numerous times but it just never clicked in my brain. Well, it is a very small thing in daily life, so I don't fuss about it too much and was able to find work-arounds in discussions when needed. And hey, Spanish is an awesome language! It was really that one test all about negated questions I totally failed xD

 

48 minutes ago, alvaro said:

Then again, I am a native Spanish speaker.

Huh, for some reason I thought you spoke Portuguese. Today I learned!

Hello to all my stalkers.

This topic is closed to new replies.

Advertisement