<div dir="ltr">Idiomatic is quite a wide definition and depends what goal you are trying to achieve.<br><br>You can write your combattables.erl many ways and it would be idiomatic in<br>some sense. For example like this:<br><br>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<br>clericdruidmonk0() -> { 20, 18, 16, 14, 12, 10, 9 }.<br>fighter0() -> { 20, 20, 18, 16, 14, 12, 10, 08, 06, 04 }.<br>magicuserillusionist0() -> { 20, 19, 16, 13, 11 }.<br>thiefassassin0() -> { 20, 19, 16, 14, 12, 10 }.<br>monster0() -> { 20, 20, 19, 18, 16, 15, 13, 12, 10, 9, 8, 7 }.<br>f0(Level) -> (Level+1) div 3.<br>f1(Level) -> ((Level+1) div 2)+1.<br>f2(Level) -> (Level+3) div 4.<br>f3(Level) -> (Level+4) div 5.<br>monster_offset(Level) -><br> if <br>           Level < 0.5 -> 0;<br>               Level < 1 -> 1;<br>         Level < 1.5 -> 2;<br>               Level < 2 -> 3;<br>         true -> ((Level) div 2) + 3<br>        end.<br><br>basetohit(Class, Level, AC) -><br>    M = #{<br>        cleric => {fun f0/1, fun clericdruidmonk0/0},<br>        druid => {fun f0/1, fun clericdruidmonk0/0},<br>        monk => {fun f0/1, fun clericdruidmonk0/0},<br>        fighter => {fun f1/1, fun fighter0/0},<br>        paladin => {fun f1/1, fun fighter0/0},<br>        thief => {fun f2/1, fun thiefassassin0/0},<br>        assasin => {fun f2/1, fun thiefassassin0/0},<br>        magicuser => {fun f3/1, fun magicuserillusionist0/0},<br>        illusionist => {fun f3/1, fun magicuserillusionist0/0},<br>        monster => {fun monster_offset/1, fun monster0/0}<br>    },<br>    {F, D} = maps:get(Class, M),<br>    element(F(Level), D()) - AC.<br>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<br><br>or like this:<br><br>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<br>clericdruidmonk0() -> { 20, 18, 16, 14, 12, 10, 9 }.<br>fighter0() -> { 20, 20, 18, 16, 14, 12, 10, 08, 06, 04 }.<br>magicuserillusionist0() -> { 20, 19, 16, 13, 11 }.<br>thiefassassin0() -> { 20, 19, 16, 14, 12, 10 }.<br>monster0() -> { 20, 20, 19, 18, 16, 15, 13, 12, 10, 9, 8, 7 }.<br><br>get_level(cleric, Level) -> (Level+1) div 3;<br>get_level(druid, Level) -> (Level+1) div 3;<br>get_level(monk, Level) -> (Level+1) div 3;<br>get_level(fighter, Level) -> ((Level+1) div 2)+1;<br>get_level(paladin, Level) -> ((Level+1) div 2)+1;<br>get_level(thief, Level) -> (Level+3) div 4.;<br>get_level(assasin, Level) -> (Level+3) div 4;<br>get_level(magicuser, Level) -> (Level+4) div 5;<br>get_level(illusionist, Level) -> (Level+4) div 5;<br>get_level(monster, Level) -><br>    if <br>        Level < 0.5 -> 0;<br>        Level < 1 -> 1;<br>        Level < 1.5 -> 2;<br>        Level < 2 -> 3;<br>        true -> ((Level) div 2) + 3<br>       end.<br>% or    <br>% get_level(monster, Level) when Level < 0.5 -> 0;<br>% get_level(monster, Level) when Level < 1 -> 1;<br>% get_level(monster, Level) when Level < 1.5 -> 2;<br>% get_level(monster, Level) when Level < 2 -> 3;<br>% get_level(monster, Level) -> ((Level) div 2) + 3.<br><br>get_values(cleric) -> clericdruidmonk0();<br>get_values(druid) -> clericdruidmonk0();<br>get_values(monk) -> clericdruidmonk0();<br>get_values(fighter) -> fighter0();<br>get_values(paladin) -> fighter0();<br>get_values(thief) -> thiefassassin0();<br>get_values(assasin) -> thiefassassin0();<br>get_values(magicuser) -> magicuserillusionist0();<br>get_values(illusionist) -> magicuserillusionist0();<br>get_values(monster) -> monster0().<br>    <br>basetohit(Class, Level, AC) -><br>    element(get_level(Class, Level), get_values(Class)) - AC;<br>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">пн, 26 июл. 2021 г. в 13:43, Benjamin Scherrey <<a href="mailto:scherrey@biggestfan.net">scherrey@biggestfan.net</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Been a couple of decades since I did any Erlang coding from scratch and it seems to have improved significantly (didn't have proper strings back then for example). I have a little hobby project I'm using to get myself up to snuff so I can do some more serious work for an upcoming project. Would appreciate some feedback regarding a few issues/questions. The code can be found at <a href="https://github.com/scherrey/dnderl" target="_blank">https://github.com/scherrey/dnderl</a> . <br><br>If you've ever played Advanced Dungeons & Dragons you'll recognize that this is a simple implementation of the THAC0 (to-hit armour class 0) concept from the original combat tables in the Dungeon Masters Guide. So '<span style="color:rgb(0,0,0)"><font face="monospace">combat:thac0(fighter, 5, 2).'</font><font face="arial, sans-serif"> would correctly tell you that your 5th level fighter needs to roll a 14 or higher on a 20-sided die to hit an armour class 2 opponent whereas </font></span>'<span style="color:rgb(0,0,0)"><font face="monospace">combat:thac0(thief, 5, 2).'</font><font face="arial, sans-serif"> would tell you that a similar level thief requires a roll of 17 or better. Here are my questions:</font></span><div><font color="#000000" face="arial, sans-serif"><br></font><div>1) My top level module is combat.erl ( <a href="https://github.com/scherrey/dnderl/blob/master/combat.erl" target="_blank">https://github.com/scherrey/dnderl/blob/master/combat.erl</a> ). All it really does is introduce the class atom type and re-export combattables:basetohit/3 (albeit under a different name, thac0/3). Is it necessary to create a forwarding function like thac0/3 like I'm doing when I'd really just prefer to establish thac0/3 in the combattables module and re-export it from combat.erl? (Don't read anything into the different names - I just decided to rename it in the top level module because I liked it better and would be happy to use that same name throughout.) Attempting to re-export a function declared in another module gives me an error.<br><br><br>2) In combattables.erl ( <a href="https://github.com/scherrey/dnderl/blob/master/combattables.erl" target="_blank">https://github.com/scherrey/dnderl/blob/master/combattables.erl</a> ) I put monster_offset/1 as its own function because I couldn't figure out syntax for how to get the result of the if statement as an intermediate variable which I would have put inside the last basetohit/3 implementation. I tried several things but nothing that seemed correct to me would compile so I had to break it out into its own function. I feel like I'm missing something obvious but perhaps it's simply not allowed?</div><div><br></div><div><br></div><div>3) Is the way I've overloaded basetohit/3 with guards depending on which class is passed in the preferred idiomatic way to implement such a construct in Erlang? I thought of trying 'case' or 'if' but this seemed "cleanest" to me. I generally avoid if statements whenever possible in my other programming languages like C++ & Python. Appreciate any insights for such circumstances.</div><div><br></div><div><br></div><div>4) Is there no such thing as a module scope for a variable in Erlang? In combattables.erl I have 4 functions that return tuples representing the combat tables for each class. My initial thought was that they would be variables that could be referenced by any function in the module but that doesn't seem to work. The tuples in this case are constant lookup tables not to be updated. Am I doing this in the "correct" idiomatic manner for Erlang?</div><div><br></div><div><br></div><div>thanks & best regards,</div><div><br></div><div> -- Ben Scherrey</div></div></div>
</blockquote></div>