View Full Version: How Can I Shank This Code

DimensioneX Forum > Developers' Pub > How Can I Shank This Code



Title: How Can I Shank This Code
Description: and speed up the processing time?


ricksan - April 24, 2006 07:31 PM (GMT)
This is what the code needs to do.
When a player puts items in to the forge and hits combine button.
ALL item in the forge are removed using the KILL command.
If the player put in the right items in the right amount and he has the right skill
a new item is made.

For example this is some the passable Combinations and the new item made.

Ore X1 + flask of water X1 = Metal bits X2
Metal bits X1 + File mould X1 = metal file X1
Metal bits X4 + metal file X1 = caltrops X1
Metal bits X3 + needle mould X1 + flask of water X1 = sowing needle X4

there are many more but this will give you an idea of that I am doing.

The getItemsIn($OWNER) command "$OWNER is the forge" gos throw each item in the forge
to see if it is there and how many are there. The problem is with so many items that can be put in the
forge to make a valid combine. I end up with a large list of If statements, as you can see from the code.

Is there a way to have it so that when it is going throw the long list If statements and finds that item
and quanty it is that it stop going throw the rest of the if statments.(like a return comand)

For example
If the item is ore. the frist If statment will do the job off recording that ore is presant in forge
and how mach. The other If statment after that one are only deal with other items. So I would like it
to skip the rest of the If statments dealing with the other items to save time.

I was thinking of put each If statment in to one another like so.

If X.name = "Ore"
oreq = oreq + Int(X.Quantity)
Else
If X.name = "Flask of Water"
fwatq = fwatq + Int(X.Quantity)
Else
If X.name = "Medium quality Ore"
mdoreq = mdoreq + Int(X.Quantity)
Else
If X.name = "Smiting hammer"
hamq = hamq + Int(X.Quantity)
Else
If X.name = "Metal File"
fileq = fileq + Int(X.Quantity)
Else
If X.name = "Mould Hammer Head"
mohamq = mohamq + Int(X.Quantity)
End_If
End_If
End_If
End_If
End_If

But this makes the code hard to read and harder to type
with the 17 smiting items add so far I can did it this way but when I add the other 25+ item I made
this code is to hard you event me to keep track off. not mention how long and slow it will when I add
all the passable valid combines.

Do the Dim statements need to be list before I use them in the If Statements?
under the NEXT, when it looks for each of the variable I crated in the Dim commands, If I
do not list them before all the If commands the program will be looking for variables that do not exist.

As far as the use of name to test if the item is present, I will change it to test for type when I
have finished changing over the tag attribute to type.

Any way any thing you can think of shanks the lines the code needed and the time taken to run this
will help a lot.



EVENT Forge1.onComb
Dim oreq = 0
Dim fwatq = 0
Dim mdoreq = 0
Dim hamq = 0
Dim fileq = 0
Dim mohamq = 0
Dim mopotq = 0
Dim moneedq = 0
Dim moarrowq = 0
Dim mostud = 0
Dim mostudq = 0
Dim mofileq = 0
Dim mohookq = 0
Dim bitq = 0
Dim fileq = 0
Dim studq = 0
Dim strapq = 0
Dim sheetq = 0
myset = getItemsIn($OWNER)
For Each X in myset
If X.useskill = "smith"'*****use X.type when the new type system is set up*****
If X.name = "Ore"
oreq = oreq + Int(X.Quantity)
End_If
If X.name = "Flask of Water"
fwatq = fwatq + Int(X.Quantity)
End_If
If X.name = "Medium quality Ore"
mdoreq = mdoreq + Int(X.Quantity)
End_If
If X.name = "Smiting hammer"
hamq = hamq + Int(X.Quantity)
End_If
If X.name = "Metal File"
fileq = fileq + Int(X.Quantity)
End_If
If X.name = "Mould Hammer Head"
mohamq = mohamq + Int(X.Quantity)
End_If
If X.name = "Mould Pot"
mopotq = mopotq + Int(X.Quantity)
End_If
If X.name = "Mould Needle"
moneedq = moneedq + Int(X.Quantity)
End_If
If X.name = "Mould Arrow head"
moarrowq = moarrowq + Int(X.Quantity)
End_If
If X.name = "Mould Studs"
mostudq = mostudq + Int(X.Quantity)
End_If
If X.name = "Mould File"
mofileq = mofileq + Int(X.Quantity)
End_If
If X.name = "Mould Fish hook"
mohookq = mohookq + Int(X.Quantity)
End_If
If X.name = "Metal bits"
bitq = bitq + Int(X.Quantity)
End_If
If X.name = "Metal File"
fileq = fileq + Int(X.Quantity)
End_If
If X.name = "Metal Studs"
studq = studq + Int(X.Quantity)
End_If
If X.name = "Metal Straps"
strapq = strapq + Int(X.Quantity)
End_If
If X.name = "Metal Sheet"
sheetq = sheetq + Int(X.Quantity)
End_If
End_If
KILL X
Next
If oreq >= 1 AND fwatq >= 1' makeing metal bits
If oreq >= fwatq'make the lowest amount
Dim num = Int(fwatq)
Else
Dim num = Int(oreq)
End_If
Dim matix = "C"
Call comSmi(1,num,13,matix)'min,amount,key,mat
Call upSmi(10,80)'put back to 50 after test
End_If
If bitq >= 1 AND mofileq >= 1' makeing metal file
If bitq >= mofileq
Dim num = Int(mofileq)
Else
Dim num = Int(bitq)
End_If
Dim matix = "C"
Call comSmi(5,num,5,matix)'min sill needed,amount to make,key to use,mat to use
Call upSmi(15,80)'put back to 50 after test'max skill,number to get over for success
End_If
If bitq >= 3 AND moneedq >= 1 AND fwatq >= 1' makeing metal sowing needle
If moneedq >= Int(bitq/3) AND fwatq >= Int(bitq/3)
Dim num = Int(bitq/3)
Else
If moneedq <= fwatq
Dim num = Int(moneedq)
Else
Dim num = Int(fwatq)
End_If
End_If
Dim matix = "C"
Call comSmi(10,num,29,matix)'min sill needed,amount to make,key to use,mat to use
Call upSmi(20,80)'put back to 50 after test'max skill,number to get over for success
End_If
End_EVENT

Sub upSmi(max,needed)' max = max skill for the combine, needed = the % you must get over
Dim pre = RndInt(100) + leanB($AGENT)
If pre > needed
If $AGENT.Smiting < max
If $AGENT.Smiting < getMSmi($AGENT)
$AGENT.Smiting = $AGENT.Smiting + 1
Display "GRATZ !! You Have gained a point in Smithing you Smithing Skill is now " + $AGENT.Smiting + " Way to Go!"
Else
Display "You are at the Max for a Level " + $AGENT.Level + " " + $AGENT.Race + " " + $AGENT.Class + " so you gain will not gain any more skill till next level!"
End_If
Else
Display "You Can not Lean any more from this combine! you're skill is to grate"
End_If
End_If
End_Sub

Sub comSmi(min,amount,key,mat)'min = minimum skill needed for combine
If $AGENT.Smiting >= min
Dim base = 100 + Int(min) * 4
Dim sucpre = RndInt(base)
Dim suc = $AGENT.Smiting + Int(stbon($AGENT.STR)) + 20
If sucpre <= suc
If mat = "A"
Call critemA($OWNER,key,amount)
Display "SUCCESS! You have made a " + matANAME(key) + "!"
End_If
If mat = "B"
Call critemB($OWNER,key,amount)
Display "SUCCESS! You have made a " + matBNAME(key) + "!"
End_If
If mat = "C"
Call critemC($OWNER,key,amount)
Display "SUCCESS! You have made " + amount + " " + matCNAME(key) + "!"
End_If
Else
Display "FAILURE! You need to work on your smithing skill"
End_If
Else
Display "You do not have the minimum skill for this combine"
End_If

Cris - April 25, 2006 12:08 PM (GMT)
Hi ricksan,
what you are trying to do can be done esaily by following these guidelines:

1. If you are about to write complex code with several IF branches, don't do it.
Make a Function instead.
Try to elaborate a scheme which is complete enough to handle all your cases and put all your code there.

2. Use SETS. They are great to pack information in some form which can be later unpacked and treated. The Function you make could use sets to apply the same logic to different set of data.

3. Don't use NAME to distinguish objects. Always use the TYPE attribute to distinguish object types. This is a DimensioneX standard, and it is used also for the AutoRestore function. It is likely that in future releases more functions will come up, using this TYPE attribute so you should use it and rely on it.

Now let's dig into your specific case.
Please note that what is below has not been tested so you will have to fix up some things. Post again if you get stuck.

First step

First let us define a SET of recipes. A recipe tells the system what is needed (object types and experience) to make what.

CODE
setRecipes = NewSet(("mbitsX2=1.oreX1+waterX1,mfileX1=1.mbitsX1+fmouldX1,caltropsX1=1.mbitsX4+mfileX1")


This creates a set of recipes our funtion will read from.
Now the constructed set (use Print to verify) will b something like:

QUOTE
mbitsX2=1.oreX1+waterX1
mfileX1=1.mbitsX1+fmouldX1
caltropsX1=1.mbitsX4+mfileX1


the part before the equal (=) is the key, the part at the right is the value, and expresses what is need to make what is at the left.
It must be clear now that the key part is itself a packed information:

QUOTE
objectTypeXquantity


We will make our function to understand this. Now let's assume this part is done and let's go forward. It must be clear that the "X" character is a sort of special character for us so you cannot use it for type identifiers.

Let's look at what is on the right hand of the equal sign. The format is the following:

QUOTE
mimimun_experience_needed.ingredients_list


minimum_experience_needed is a number. Our function will check that you have at least these points of experience for the combination to succeed. If you want you can skip this bit of info if it is useless for you.

Next you have a dot used as a separator

Next you have an ingredients list. This is made as follows:

QUOTE
objectTypeXquantity+ [ objectTypeXquantity ]


so here we use the plus sign "+" as list separator .

As we see, in the setRecipes we used four types of separators which cannot be used for other purposes in the string.

QUOTE
=
X
.
+


Second step

these separate sets of related information. The string can be turned into an Array or set by using standard functions. This task should be done once in the onStart event.

CODE
setRecipes = NewSet(("mbitsX2=1.oreX1+waterX1,mfileX1=1.mbitsX1+fmouldX1,caltropsX1=1.mbitsX4+mfileX1")
Dim key
Dim setRecipesMinExp = NewSet() ' holds minimum experience
Dim setRecipesIngredients = NewSet() ' holds ingredients
Dim tmpSet = NewSet() ' temporary set for splitting
For Each key in SetKeys(setRecipes)
  tmpSet = Split(setRecipes(key),".")
  setRecipesMinExp(key) = tmpSet(1) ' first element is min exp
  setRecipesIngredients(key) = tmpSet(2) ' second element is ingredients
Next
Debug setRecipesMinExp ' see result in the debug file
Debug setRecipesIngredients
END_EVENT


Ok now we have two sets built from the first one:
setRecipesMinExp()
setRecipesIngredients()

we will use it in the function below.


Third step

Next we make a function.


CODE
' This function makes one object out of pieces put in the "aPot" container
' it is based on a list of recipes coded in our sets
' aPot = container of elements to combine - use another system if u want
'dest = destination object where objects will be created. A person is OK
' retuns: true if done, null if not
Function MakeSomething(aPot,dest)
' first we check ingredients
Dim what = checkNecessaryIngredients(aPot)
If what = null
   Print "I cannot make anything with these ingredients!"
   Return null
End_If

If setRecipesMinExp(what) > $AGENT.Experience
   Print "I do not have enough experience!"
   Return null
End_If

Dim arrTemp = Split(what,"X") ' first element is object type, second is quantity
Dim i
For i = 1 To arrTemp(2)
   Dim new = MakeItem(arrTemp(1),dest) ' this function MakeItem(type,dest) creates an object of type "type" in destination place "dest" - implement it yourself
Next
return true
End_Function


Now we just have to implement a function which is called checkNecessaryIngredients(aPot) which checks inside "aPot" against the list of ingredients for each recipe in the set setRecipeInredients. If found a valid cobination, it returns the key, null otherwise.

CODE
Function checkNecessaryIngredients(aPot)
Dim key
For Each key In SetKeys(setRecipeIngredients)
   Dim arrIngredients = Split(setRecipeIngredients(key),"+")
   ' Now we search aPot for all the ingredients / quantities
   Dim IngredientsOk = True ' initially we suppose they are there
   Dim ingreds
   For Each ingreds In arrIngredients
        Dim arrTemp = Split(arrIngredients,"X") ' first elem is type, second quantity
        If Not(IsThere(aPot,arrTemp(1),arrTemp(2)))
             Print "Missing: " + ingreds
             Return null
        End_If
   Next
   If IngredientsOk
       Print "Match found for recipe: " + key
       Return key ' quit - success!
   End_If
Next
' if we are here then not found
Print "No recipes matching with pot contents!"
Return null
End_Function


Now you simply miss the function IsThere, which has 3 parameters:

CODE
'IsThere
'aPot = where to look
'type = type of the searched object
'quantity = quantity of the searched object
' return true if found false otherwise
Function IsThere(aPot,type,quant)
Dim RealQuant = 0
For each obj In GetItemsIn(apot)
   If obj.type = type
       RealQuant = RealQuant+1
   End_If
Next
If RealQuant >= quant ' quantity sufficient found!
   Return true
End_If
return false ' otherwise
End_Function





Done!

Good luck!




Hosted for free by InvisionFree