Part I - Without package
I have created a function to compute a bridge score.
computeScore[level_, denomination_, vul_, dbl_, tricks_] := Module[
{
trickScore = 0,
trickMultiplier = 2^dbl,
numberEffectiveTricks,
trickValue = {20, 30, 30},
gameBid,
partialBonus = 0,
gameBonus = 0,
gameValue = {300, 500},
gameTricks = {5, 4, 3},
slamBonus = 0,
slamValue = {500, 750},
insult = 0,
overtrickScore = 0,
overtrickValue = {100, 200}, (* doubled overtricks non-vul/vul *)
undertrickScore = 0,
undertrickValue = {50, 100},
doubled = False,
redoubled = False,
suitIndex,
total
},
(* Convert the denomination argument into an index into a suit array *)
suitIndex = Which[
SameQ[denomination, $c] || SameQ[denomination, $d],
1,
SameQ[denomination, $h] || SameQ[denomination, $s],
2,
SameQ[denomination, $nt],
3
];
(* Take two paths depending upon whether
the contract made or was set *)
If[tricks >= level,
(* contract made *)
numberEffectiveTricks = 2^dbl*level;
trickScore = numberEffectiveTricks*trickValue[[suitIndex]] +
10*trickMultiplier*Floor[suitIndex/3];
overtrickScore = (tricks - level)*
(UnitStep[-dbl]*trickValue[[suitIndex]] +
dbl*overtrickValue[[vul + 1]]);
insult = 50*dbl;
gameBid = UnitStep[numberEffectiveTricks - gameTricks[[suitIndex]]];
partialBonus = (1 - gameBid)*50;
gameBonus = gameBid*gameValue[[vul + 1]];
slamBonus = (level - 5)*UnitStep[level - 5]*slamValue[[vul + 1]];
total =
trickScore + overtrickScore + insult + partialBonus + gameBonus +
slamBonus
,
(* contract was set *)
undertrickScore = With[
{
undertricks = level - tricks
},
If[dbl == 0,
-50*undertricks*(vul + 1),
dbl*If[vul == 0,
-100 - 200*(undertricks - 1)*UnitStep[undertricks - 2] -
100*(undertricks - 3)*UnitStep[undertricks - 4],
-200 - 300*(undertricks - 1)*UnitStep[undertricks - 2]
]
]
]
]
]
It works fine. Here is an example where the contract is 3 spades, not vulnerable, not doubled, making 3.
computeScore[3, $s, 0, 0, 3]
140
Note that I am using a set of undefined symbols inside the module, $c thru $nt to represent clubs through notrump.
Part II - Inside package
Now close Mathematica and start a new notebook.
Use the same function inside a package. To save space I won't re-copy the function. The new notebook looks like:
BeginPackage["bridgeScore`"]
computeScore::usage =
"Returns the score given the level, suit, vulnerability (0/1),\n\
doubled status (0/1/2) and the number of tricks";
Begin["`Private`"]
Copy computeScore code here ...
End[]
EndPackage[]
Now when I execute I get an error
computeScore[3, $s, 0, 0, 3]
Part::pkspec1: The expression Null cannot be used as a part specification.
I have traced it down to the statement where denomination is tested
suitIndex = Which[
SameQ[denomination, $c] || SameQ[denomination, $d],
1,
SameQ[denomination, $h] || SameQ[denomination, $s],
2,
SameQ[denomination, $nt],
3
];
For some reason this works fine until you place it in a package.
I don't have a clue why, can any one help?
Which, you might be able to shorten your code by usingSwitch. – Jason B. Oct 04 '16 at 22:09