Vanilla Code Questions

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • DavidMedley
    Veteran
    • Oct 2019
    • 1004

    Vanilla Code Questions

    I'm hacking around with vanilla at the moment. I'm going to post some questions as they come up.

    My background: I don't have a lot of experience with C but I have 15+ years experience as a professional software developer. I'm more familiar with Perl than any other language.
    Last edited by DavidMedley; March 16, 2020, 03:31.
    Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames
  • DavidMedley
    Veteran
    • Oct 2019
    • 1004

    #2
    Where do things like PLAYER_LEVEL from class.txt get interpreted? I only find that string in text files and player-spell.c.
    Code:
    expression_base_value_f spell_value_base_by_name(const char *name)
    {
    	static const struct value_base_s {
    		const char *name;
    		expression_base_value_f function;
    	} value_bases[] = {
    		{ "SPELL_POWER", spell_value_base_spell_power },
    		{ "PLAYER_LEVEL", spell_value_base_player_level },
    		{ "DUNGEON_LEVEL", spell_value_base_dungeon_level },
    		{ "MAX_SIGHT", spell_value_base_max_sight },
    		{ "WEAPON_DAMAGE", spell_value_base_weapon_damage },
    		{ "PLAYER_HP", spell_value_base_player_hp },
    		{ "MONSTER_PERCENT_HP_GONE", spell_value_base_monster_percent_hp_gone },
    		{ NULL, NULL },
    	};
    	const struct value_base_s *current = value_bases;
    
    	while (current->name != NULL && current->function != NULL) {
    		if (my_stricmp(name, current->name) == 0)
    			return current->function;
    
    		current++;
    	}
    
    	return NULL;
    }
    When I saw this I thought "Jackpot!" But when I try to put in things like WEAPON_DAMAGE into class.txt, angband gives me a parse error when I run it. I tried PLAYER_HP and DUNGEON_LEVEL as well and they give the same error, though MONSTER_PERCENT_HP_GONE obviously works since it's part of the Necro class.

    So where are these codes, such as PLAYER_LEVEL and MONSTER_PERCENT_HP_GONE interpretted?
    Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames

    Comment

    • DavidMedley
      Veteran
      • Oct 2019
      • 1004

      #3
      Confirming: "s32b" means "signed 32 bit integer"? Example:
      Code:
      	s32b new_mana, new_mana_frac;
      If so, why use this construction instead of "signed long int"? Or just "long" for brevity?
      Last edited by DavidMedley; March 16, 2020, 03:56.
      Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames

      Comment

      • wobbly
        Prophet
        • May 2012
        • 2629

        #4
        Originally posted by DavidMedley
        Where do things like PLAYER_LEVEL from class.txt get interpreted? I only find that string in text files and player-spell.c.
        Code:
        expression_base_value_f spell_value_base_by_name(const char *name)
        {
        	static const struct value_base_s {
        		const char *name;
        		expression_base_value_f function;
        	} value_bases[] = {
        		{ "SPELL_POWER", spell_value_base_spell_power },
        		{ "PLAYER_LEVEL", spell_value_base_player_level },
        		{ "DUNGEON_LEVEL", spell_value_base_dungeon_level },
        		{ "MAX_SIGHT", spell_value_base_max_sight },
        		{ "WEAPON_DAMAGE", spell_value_base_weapon_damage },
        		{ "PLAYER_HP", spell_value_base_player_hp },
        		{ "MONSTER_PERCENT_HP_GONE", spell_value_base_monster_percent_hp_gone },
        		{ NULL, NULL },
        	};
        	const struct value_base_s *current = value_bases;
        
        	while (current->name != NULL && current->function != NULL) {
        		if (my_stricmp(name, current->name) == 0)
        			return current->function;
        
        		current++;
        	}
        
        	return NULL;
        }
        When I saw this I thought "Jackpot!" But when I try to put in things like WEAPON_DAMAGE into class.txt, angband gives me a parse error when I run it. I tried PLAYER_HP and DUNGEON_LEVEL as well and they give the same error, though MONSTER_PERCENT_HP_GONE obviously works since it's part of the Necro class.

        So where are these codes, such as PLAYER_LEVEL and MONSTER_PERCENT_HP_GONE interpretted?
        look in init.c for Initialize player classes

        Comment

        • backwardsEric
          Knight
          • Aug 2019
          • 527

          #5
          Originally posted by DavidMedley
          Confirming: "s32b" means "signed 32 bit integer"? Example:
          Code:
          	s32b new_mana, new_mana_frac;
          If so, why use this construction instead of "signed long int"? Or just "long" for brevity?
          Yes, it means a 32-bit signed integer. If one uses long, you don't have a guarantee about the size. For instance, when compiling 64-bit applications on Linux or Mac OS, a long is a 64-bit signed integer. There's a standard way of referring to integers with a known number of bits (int32_t, uint32_t, ....), and you'll see that used in h-basic.h to define what s32b is. But those types were introduced after Angband was originally written, and it's understandable that Angband adopted its own convention.

          Comment

          • wobbly
            Prophet
            • May 2012
            • 2629

            #6
            Originally posted by DavidMedley
            When I saw this I thought "Jackpot!" But when I try to put in things like WEAPON_DAMAGE into class.txt, angband gives me a parse error when I run it. I tried PLAYER_HP and DUNGEON_LEVEL as well and they give the same error, though MONSTER_PERCENT_HP_GONE obviously works since it's part of the Necro class.
            Changing:

            Code:
            spell:Magic Missile:1:1:22:4
            effect:BOLT_OR_BEAM:MISSILE:0:-10
            dice:$Dd4
            expr:D:PLAYER_LEVEL:- 1 / 5 + 3
            desc:Fires a magic missile that always hits its target and does
            desc: unresistable damage.
            desc:  Sometimes a beam is fired instead that hurts each monster
            desc: in its path.
            desc:  The chance to get a beam goes up with your character level.
            to

            Code:
            spell:Magic Missile:1:1:22:4
            effect:BOLT_OR_BEAM:MISSILE:0:-10
            dice:$Dd4
            expr:D:WEAPON_DAMAGE:- 1 / 5 + 3
            desc:Fires a magic missile that always hits its target and does
            desc: unresistable damage.
            desc:  Sometimes a beam is fired instead that hurts each monster
            desc: in its path.
            desc:  The chance to get a beam goes up with your character level.
            is working for me, & gives me a magic missile damage based on the dice of my weapon.

            What parser error are you getting?

            Comment

            • DavidMedley
              Veteran
              • Oct 2019
              • 1004

              #7
              Originally posted by wobbly
              is working for me
              Hmm ok
              Code:
              expr:D:WEAPON_DAMAGE: #<--doesn't parse
              expr:D:WEAPON_DAMAGE:+ 0 #<-- does parse
              Thanks!
              Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames

              Comment

              • DavidMedley
                Veteran
                • Oct 2019
                • 1004

                #8
                Originally posted by backwardsEric
                those types were introduced after Angband was originally written
                Makes sense. Thanks, Eric!
                Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames

                Comment

                • DavidMedley
                  Veteran
                  • Oct 2019
                  • 1004

                  #9
                  Originally posted by wobbly
                  look in init.c for Initialize player classes
                  OK. Now that we have the other thing figured out, hopefully I won't have to make any changes in here!
                  Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames

                  Comment

                  • DavidMedley
                    Veteran
                    • Oct 2019
                    • 1004

                    #10
                    OK, this is a pretty big ask, but I'll put it out into the universe and see what happens.

                    I want to create a spell that includes a melee blow as one of its effects. I've looked at
                    Code:
                    static bool py_attack_real(struct player *p, struct loc grid, bool *fear)
                    /**Attack the monster at the given location with a single blow.*/
                    And that seems to be perfect for what I have in mind, so I shouldn't have to write a whole new attack sequence.

                    But when I look at
                    Code:
                    bool spell_cast(int spell_index, int dir) {
                    ...
                    	effect_do(spell->effect, source_player(), NULL, ident, true, dir, beam, 0)
                    ...
                    }
                    It's really abstract and hard to follow. This probably makes it very flexible and powerful and (I'm hoping) pretty easy to get it to do what I want.

                    So can anyone provide me with hints or examples of how to do this?
                    Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames

                    Comment

                    • wobbly
                      Prophet
                      • May 2012
                      • 2629

                      #11
                      Well here's a start:

                      Code:
                      /**
                       * Execute an effect chain.
                       *
                       * \param effect is the effect chain
                       * \param origin is the origin of the effect (player, monster etc.)
                       * \param obj    is the object making the effect happen (or NULL)
                       * \param ident  will be updated if the effect is identifiable
                       *               (NB: no effect ever sets *ident to false)
                       * \param aware  indicates whether the player is aware of the effect already
                       * \param dir    is the direction the effect will go in
                       * \param beam   is the base chance out of 100 that a BOLT_OR_BEAM effect will beam
                       * \param boost  is the extent to which skill surpasses difficulty, used as % boost. It
                       *               ranges from 0 to 138.
                       */
                      bool effect_do(struct effect *effect,
                      		struct source origin,
                      		struct object *obj,
                      		bool *ident,
                      		bool aware,
                      		int dir,
                      		int beam,
                      		int boost)

                      Comment

                      • Nick
                        Vanilla maintainer
                        • Apr 2007
                        • 9634

                        #12
                        I think you'll have to write an effect handler (see effects.c - there are a whole lot of them) which will need to call py_attack_real() for each monster you want to hit. To do this you'll need to make py_attack_real() callable from other files, which means adding its definition to player-attack.h and including player-attack.h in effects.c.
                        One for the Dark Lord on his dark throne
                        In the Land of Mordor where the Shadows lie.

                        Comment

                        • DavidMedley
                          Veteran
                          • Oct 2019
                          • 1004

                          #13
                          OK, thanks!
                          Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames

                          Comment

                          • Pete Mack
                            Prophet
                            • Apr 2007
                            • 6883

                            #14
                            The reason things are so abstract now is that, while the code is somewhat harder to understand, it is much easier to add things. In the old days, you would need to modify:
                            * the parser
                            * at least one .h file
                            * the global spell list
                            * the config files

                            Now to add most spells all you need to change is a couple config (.txt) files and possibly a .h file. Your change requires new interpretation in-code, as you need to surface weapon attacks as a magic effect, so you need a new spell effect procedure.

                            Comment

                            • DavidMedley
                              Veteran
                              • Oct 2019
                              • 1004

                              #15
                              Originally posted by Pete Mack
                              while the code is somewhat harder to understand, it is much easier to add things.
                              Yeah, that's what I figured. Thanks!
                              Please like my indie game company on Facebook! https://www.facebook.com/RatherFunGames

                              Comment

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