Bookless spells take 2

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Therem Harth
    Knight
    • Jan 2008
    • 926

    Bookless spells take 2

    Neoband's bookless spell system is a dreadful mess at the moment.

    What I have: a bunch of similar looking source files, one for each bookless realm, each containing a full set of functions for dealing with the spells (i.e. lots of code duplication).

    What I want: each bookless realm being an object, containing a variable number of spells.

    (In C I guess that would translate into "typedef struct blah blah, etc.")

    Furthermore, each spell in a bookless realm would be an object, containing an integer mana cost, a description string, and methods for casting the spell, printing info, calculating fail rates, etc.

    I think I could achieve this with function pointers. e.g.

    Code:
    typedef struct {
        int cost;
        char *desc;
        int *cast;
        int *calc_fail;
        int *display_info;
    } spellholder;
    
    ...
    
    spellholder pyro_fire_bolt = {
        1,
        "Hurls a bolt of fire",
        (int *)fire_bolt(GF_FIRE, ...),
        ...
    };
    
    ...
    Still a pretty rough around the edges... But this way I could do things like having different spells rely on different stats, or fail under different conditions. And I could have any number of spells per realm; and it would be much easier to add spells; etc.

    Does this sound sane or am I missing something obvious?
  • AnonymousHero
    Veteran
    • Jun 2007
    • 1393

    #2
    Function pointers don't quite look like that (and casting like that will probably get you into trouble). Here's an example:

    Code:
    #include <stdio.h>
    
    int f(const char *a) {
       printf("hello, %s\n", a);
       return 42;
    }
    
    typedef struct {
       int (*cast)(const char *a);
    } my_struct;
    
    int main(int argc, char *argv[]) {
       my_struct s = { f };
       int r = (*s.cast)("world");
       printf("returned: %d\n", r);
    }
    This will, when run, print:
    Code:
    hello, world
    returned: 42
    Hopefully that makes sense.

    Comment

    • Therem Harth
      Knight
      • Jan 2008
      • 926

      #3
      ... I'm not quite seeing the difference there. Is it that the cast is made when it's called, not when the struct is created?

      Comment

      • AnonymousHero
        Veteran
        • Jun 2007
        • 1393

        #4
        No, the difference that matters is in the declaration:
        Code:
             int (*foo)();
        (a declaration of a no-arg function field.)
        is not the same as
        Code:
            int *foo;
        (a declaration of a point to an int or an array of ints.)

        You need the extra parantheses at the declaration site in the struct typedef.

        The fast that you need casts to "set" a field in your struct to function should be clue that you're doing something wrong.

        EDIT: I see my use of "cast" as a field name in the example may have been confusing. There's also no typecast in my example code; in your code there are.

        Comment

        • Therem Harth
          Knight
          • Jan 2008
          • 926

          #5
          Oh I see. Thanks.

          Comment

          • Therem Harth
            Knight
            • Jan 2008
            • 926

            #6
            Just embarked on a cleanup of the bookless spell files. The code is now somewhat more intelligent, and only calls screen_load() once (per file).

            However there is still a lot of code duplication between the files, as exemplified by me having to apply the same fix to all four of them at one point... There must be a way I can consolidate more code in one place, and without requiring a specific number of spells per class. Does anyone have advice?

            Comment

            • Magnate
              Angband Devteam member
              • May 2007
              • 5110

              #7
              Originally posted by Therem Harth
              Just embarked on a cleanup of the bookless spell files. The code is now somewhat more intelligent, and only calls screen_load() once (per file).

              However there is still a lot of code duplication between the files, as exemplified by me having to apply the same fix to all four of them at one point... There must be a way I can consolidate more code in one place, and without requiring a specific number of spells per class. Does anyone have advice?
              Take a look at the foo.c files which use a macro expansion of the accompanying list-foo.h file to populate a data structure which is then operated on by a series of functions in foo.c. Could you create a list-spells.h which gave you a single struct for each spell, and then have a single spells.c file which contained all the functions that used it? (Learning, casting, forgetting, whatever.)
              "Been away so long I hardly knew the place, gee it's good to be back home" - The Beatles

              Comment

              • Therem Harth
                Knight
                • Jan 2008
                • 926

                #8
                Thanks, that looks more sensible; I think I'll try porting the bookless system to that method.

                Comment

                Working...
                😀
                😂
                🥰
                😘
                🤢
                😎
                😞
                😡
                👍
                👎