Idiomatic Erlang?

Stanislav Ledenev s.ledenev@REDACTED
Mon Jul 26 14:51:10 CEST 2021


Idiomatic is quite a wide definition and depends what goal you are trying
to achieve.

You can write your combattables.erl many ways and it would be idiomatic in
some sense. For example like this:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clericdruidmonk0() -> { 20, 18, 16, 14, 12, 10, 9 }.
fighter0() -> { 20, 20, 18, 16, 14, 12, 10, 08, 06, 04 }.
magicuserillusionist0() -> { 20, 19, 16, 13, 11 }.
thiefassassin0() -> { 20, 19, 16, 14, 12, 10 }.
monster0() -> { 20, 20, 19, 18, 16, 15, 13, 12, 10, 9, 8, 7 }.
f0(Level) -> (Level+1) div 3.
f1(Level) -> ((Level+1) div 2)+1.
f2(Level) -> (Level+3) div 4.
f3(Level) -> (Level+4) div 5.
monster_offset(Level) ->
if
Level < 0.5 -> 0;
Level < 1 -> 1;
Level < 1.5 -> 2;
Level < 2 -> 3;
true -> ((Level) div 2) + 3
end.

basetohit(Class, Level, AC) ->
    M = #{
        cleric => {fun f0/1, fun clericdruidmonk0/0},
        druid => {fun f0/1, fun clericdruidmonk0/0},
        monk => {fun f0/1, fun clericdruidmonk0/0},
        fighter => {fun f1/1, fun fighter0/0},
        paladin => {fun f1/1, fun fighter0/0},
        thief => {fun f2/1, fun thiefassassin0/0},
        assasin => {fun f2/1, fun thiefassassin0/0},
        magicuser => {fun f3/1, fun magicuserillusionist0/0},
        illusionist => {fun f3/1, fun magicuserillusionist0/0},
        monster => {fun monster_offset/1, fun monster0/0}
    },
    {F, D} = maps:get(Class, M),
    element(F(Level), D()) - AC.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

or like this:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clericdruidmonk0() -> { 20, 18, 16, 14, 12, 10, 9 }.
fighter0() -> { 20, 20, 18, 16, 14, 12, 10, 08, 06, 04 }.
magicuserillusionist0() -> { 20, 19, 16, 13, 11 }.
thiefassassin0() -> { 20, 19, 16, 14, 12, 10 }.
monster0() -> { 20, 20, 19, 18, 16, 15, 13, 12, 10, 9, 8, 7 }.

get_level(cleric, Level) -> (Level+1) div 3;
get_level(druid, Level) -> (Level+1) div 3;
get_level(monk, Level) -> (Level+1) div 3;
get_level(fighter, Level) -> ((Level+1) div 2)+1;
get_level(paladin, Level) -> ((Level+1) div 2)+1;
get_level(thief, Level) -> (Level+3) div 4.;
get_level(assasin, Level) -> (Level+3) div 4;
get_level(magicuser, Level) -> (Level+4) div 5;
get_level(illusionist, Level) -> (Level+4) div 5;
get_level(monster, Level) ->
    if
        Level < 0.5 -> 0;
        Level < 1 -> 1;
        Level < 1.5 -> 2;
        Level < 2 -> 3;
        true -> ((Level) div 2) + 3
end.
% or
% get_level(monster, Level) when Level < 0.5 -> 0;
% get_level(monster, Level) when Level < 1 -> 1;
% get_level(monster, Level) when Level < 1.5 -> 2;
% get_level(monster, Level) when Level < 2 -> 3;
% get_level(monster, Level) -> ((Level) div 2) + 3.

get_values(cleric) -> clericdruidmonk0();
get_values(druid) -> clericdruidmonk0();
get_values(monk) -> clericdruidmonk0();
get_values(fighter) -> fighter0();
get_values(paladin) -> fighter0();
get_values(thief) -> thiefassassin0();
get_values(assasin) -> thiefassassin0();
get_values(magicuser) -> magicuserillusionist0();
get_values(illusionist) -> magicuserillusionist0();
get_values(monster) -> monster0().

basetohit(Class, Level, AC) ->
    element(get_level(Class, Level), get_values(Class)) - AC;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

пн, 26 июл. 2021 г. в 13:43, Benjamin Scherrey <scherrey@REDACTED>:

> 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 https://github.com/scherrey/dnderl .
>
> 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 'combat:thac0(fighter,
> 5, 2).' 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 'combat:thac0(thief, 5, 2).' would tell you that a similar level
> thief requires a roll of 17 or better. Here are my questions:
>
> 1) My top level module is combat.erl (
> https://github.com/scherrey/dnderl/blob/master/combat.erl ). 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.
>
>
> 2) In combattables.erl (
> https://github.com/scherrey/dnderl/blob/master/combattables.erl ) 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?
>
>
> 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.
>
>
> 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?
>
>
> thanks & best regards,
>
>  -- Ben Scherrey
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20210726/48cd3e91/attachment.htm>


More information about the erlang-questions mailing list