Changeset 1420 for trunk

Show
Ignore:
Timestamp:
06/01/09 11:06:50 (15 months ago)
Author:
ajps
Message:

Add some safety checking of input to the study commands - we can't assume that all game commands can be 'trusted'.

Location:
trunk/src
Files:
7 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/cmd-obj.c

    r1417 r1420  
    340340/*** Casting and browsing ***/ 
    341341 
    342 static bool obj_cast_pre(void) 
    343 { 
    344         if (!cp_ptr->spell_book) 
    345         { 
    346                 msg_print("You cannot pray or produce magics."); 
    347                 return FALSE; 
    348         } 
    349  
    350         if (p_ptr->timed[TMD_BLIND] || no_lite()) 
    351         { 
    352                 msg_print("You cannot see!"); 
    353                 return FALSE; 
    354         } 
    355  
    356         if (p_ptr->timed[TMD_CONFUSED]) 
    357         { 
    358                 msg_print("You are too confused!"); 
    359                 return FALSE; 
    360         } 
    361  
    362         return TRUE; 
    363 } 
    364  
    365 /* A prerequisite to studying */ 
    366 static bool obj_study_pre(void) 
    367 { 
    368         if (!obj_cast_pre()) 
    369                 return FALSE; 
    370  
    371         if (!p_ptr->new_spells) 
    372         { 
    373                 cptr p = ((cp_ptr->spell_book == TV_MAGIC_BOOK) ? "spell" : "prayer"); 
    374                 msg_format("You cannot learn any new %ss!", p); 
    375                 return FALSE; 
    376         } 
    377  
    378         return TRUE; 
    379 } 
    380  
    381  
    382342/* Peruse spells in a book */ 
    383343static void obj_browse(object_type *o_ptr, int item) 
     
    441401 
    442402/*** Using items the traditional way ***/ 
    443  
    444 /* Determine if the player can read scrolls. */ 
    445 static bool obj_read_pre(void) 
    446 { 
    447         if (p_ptr->timed[TMD_BLIND]) 
    448         { 
    449                 msg_print("You can't see anything."); 
    450                 return FALSE; 
    451         } 
    452  
    453         if (no_lite()) 
    454         { 
    455                 msg_print("You have no light to read by."); 
    456                 return FALSE; 
    457         } 
    458  
    459         if (p_ptr->timed[TMD_CONFUSED]) 
    460         { 
    461                 msg_print("You are too confused to read!"); 
    462                 return FALSE; 
    463         } 
    464  
    465         if (p_ptr->timed[TMD_AMNESIA]) 
    466         { 
    467                 msg_print("You can't remember how to read!"); 
    468                 return FALSE; 
    469         } 
    470  
    471         return TRUE; 
    472 } 
    473  
    474403 
    475404/* 
     
    772701        { obj_study, CMD_NULL, "study", 
    773702          "Study which book? ", "You have no books that you can read.", 
    774           obj_can_browse, (USE_INVEN | USE_FLOOR), obj_study_pre }, 
     703          obj_can_browse, (USE_INVEN | USE_FLOOR), player_can_study }, 
    775704 
    776705        { obj_cast, CMD_NULL, "cast", 
    777706          "Use which book? ", "You have no books that you can read.", 
    778           obj_can_browse, (USE_INVEN | USE_FLOOR), obj_cast_pre }, 
     707          obj_can_browse, (USE_INVEN | USE_FLOOR), player_can_cast }, 
    779708 
    780709        /*** Item usage ***/ 
     
    805734        { NULL, CMD_READ_SCROLL, "read", 
    806735      "Read which scroll? ", "You have no scrolls to read.", 
    807           obj_is_scroll, (USE_INVEN | USE_FLOOR), obj_read_pre }, 
     736          obj_is_scroll, (USE_INVEN | USE_FLOOR), player_can_read }, 
    808737 
    809738        { NULL, CMD_REFILL, "refill", 
  • trunk/src/cmd5.c

    r1417 r1420  
    525525} 
    526526 
     527/* Check if the given spell is in the given book. */ 
     528static bool spell_in_book(int spell, int book) 
     529{ 
     530        int i; 
     531        object_type *o_ptr = object_from_item_idx(book); 
     532 
     533        for (i = 0; i < SPELLS_PER_BOOK; i++) 
     534        { 
     535                if (spell == get_spell_index(o_ptr, i)) 
     536                        return TRUE; 
     537        } 
     538 
     539        return FALSE; 
     540} 
    527541 
    528542/* Gain a specific spell, specified by spell number (for mages). */ 
     
    531545        int spell = args[0].choice; 
    532546 
    533         spell_learn(spell); 
    534         p_ptr->energy_use = 100; 
     547        int item_list[INVEN_TOTAL + MAX_FLOOR_STACK]; 
     548        int item_num; 
     549        int i; 
     550 
     551        /* Check the player can study at all atm */ 
     552        if (!player_can_study()) 
     553                return; 
     554 
     555        /* Check that the player can actually learn the nominated spell. */ 
     556        item_tester_hook = obj_can_browse; 
     557        item_num = scan_items(item_list, N_ELEMENTS(item_list), (USE_INVEN | USE_FLOOR)); 
     558 
     559        /* Check through all available books */ 
     560        for (i = 0; i < item_num; i++) 
     561        { 
     562                if (spell_in_book(spell, item_list[i])) 
     563                { 
     564                        if (spell_okay(spell, FALSE, FALSE)) 
     565                        { 
     566                                /* Spell is in an available book, and player is capable. */ 
     567                                spell_learn(spell); 
     568                                p_ptr->energy_use = 100; 
     569                        } 
     570                        else 
     571                        { 
     572                                /* Spell is present, but player incapable. */ 
     573                                msg_format("You cannot learn that spell."); 
     574                        } 
     575 
     576                        return; 
     577                } 
     578        } 
     579} 
     580 
     581/* Check if the given item is available for the player to use. */ 
     582static bool item_is_available(int item, int mode) 
     583{ 
     584        int item_list[INVEN_TOTAL + MAX_FLOOR_STACK]; 
     585        int item_num; 
     586        int i; 
     587 
     588        item_num = scan_items(item_list, N_ELEMENTS(item_list), mode); 
     589 
     590        for (i = 0; i < item_num; i++) 
     591        { 
     592                if (item_list[i] == item) 
     593                        return TRUE; 
     594        } 
     595 
     596        return FALSE; 
    535597} 
    536598 
     
    545607 
    546608        cptr p = ((cp_ptr->spell_book == TV_MAGIC_BOOK) ? "spell" : "prayer"); 
     609 
     610        /* Check the player can study at all atm */ 
     611        if (!player_can_study()) 
     612                return; 
     613 
     614        /* Check that the player has access to the nominated spell book. */ 
     615        item_tester_hook = obj_can_browse; 
     616        if (!item_is_available(book, (USE_INVEN | USE_FLOOR))) 
     617        { 
     618                msg_format("That item is not within your reach."); 
     619                return; 
     620        } 
    547621 
    548622        /* Extract spells */ 
  • trunk/src/object/obj-ui.c

    r1417 r1420  
    598598        /* Allow it */ 
    599599        return (TRUE); 
    600 } 
    601  
    602  
    603 /* 
    604  * Verify the "okayness" of a given item. 
    605  * 
    606  * The item can be negative to mean "item on floor". 
    607  */ 
    608 static bool get_item_okay(int item) 
    609 { 
    610         object_type *o_ptr; 
    611  
    612         /* Inventory */ 
    613         if (item >= 0) 
    614         { 
    615                 o_ptr = &inventory[item]; 
    616         } 
    617  
    618         /* Floor */ 
    619         else 
    620         { 
    621                 o_ptr = &o_list[0 - item]; 
    622         } 
    623  
    624         /* Verify the item */ 
    625         return (item_tester_okay(o_ptr)); 
    626600} 
    627601 
  • trunk/src/object/obj-util.c

    r1417 r1420  
    36503650} 
    36513651 
     3652 
     3653/* 
     3654 * Verify the "okayness" of a given item. 
     3655 * 
     3656 * The item can be negative to mean "item on floor". 
     3657 */ 
     3658bool get_item_okay(int item) 
     3659{ 
     3660        /* Verify the item */ 
     3661        return (item_tester_okay(object_from_item_idx(item))); 
     3662} 
     3663 
     3664 
     3665/* 
     3666 * Get a list of "valid" item indexes. 
     3667 * 
     3668 * Fills item_list[] with items that are "okay" as defined by the 
     3669 * current item_tester_hook, etc.  mode determines what combination of 
     3670 * inventory, equipment and player's floor location should be used 
     3671 * when drawing up the list. 
     3672 * 
     3673 * Returns the number of items placed into the list. 
     3674 * 
     3675 * Maximum space that can be used is [INVEN_TOTAL + MAX_FLOOR_STACK], 
     3676 * though practically speaking much smaller numbers are likely. 
     3677 */ 
     3678int scan_items(int *item_list, size_t item_list_max, int mode) 
     3679{ 
     3680        bool use_inven = ((mode & USE_INVEN) ? TRUE : FALSE); 
     3681        bool use_equip = ((mode & USE_EQUIP) ? TRUE : FALSE); 
     3682        bool use_floor = ((mode & USE_FLOOR) ? TRUE : FALSE); 
     3683 
     3684        int floor_list[MAX_FLOOR_STACK]; 
     3685        int floor_num; 
     3686 
     3687        int i; 
     3688        int item_list_num = 0; 
     3689 
     3690        if (use_inven) 
     3691        { 
     3692                for (i = 0; i < INVEN_PACK && item_list_num < item_list_max; i++) 
     3693                { 
     3694                        if (get_item_okay(i)) 
     3695                                item_list[item_list_num++] = i; 
     3696                } 
     3697        } 
     3698 
     3699        if (use_equip) 
     3700        { 
     3701                for (i = INVEN_WIELD; i < INVEN_TOTAL && item_list_num < item_list_max; i++) 
     3702                { 
     3703                        if (get_item_okay(i)) 
     3704                                item_list[item_list_num++] = i; 
     3705                } 
     3706        } 
     3707 
     3708        /* Scan all non-gold objects in the grid */ 
     3709        if (use_floor) 
     3710        { 
     3711                floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), p_ptr->py, p_ptr->px, 0x03); 
     3712 
     3713                for (i = 0; i < floor_num && item_list_num < item_list_max; i++) 
     3714                { 
     3715                        if (get_item_okay(i)) 
     3716                                item_list[item_list_num++] = i; 
     3717                } 
     3718        } 
     3719 
     3720        return item_list_num; 
     3721} 
     3722 
     3723 
     3724 
  • trunk/src/object/object.h

    r1417 r1420  
    169169object_type *object_from_item_idx(int item); 
    170170bool obj_needs_aim(object_type *o_ptr); 
     171bool get_item_okay(int item); 
     172int scan_items(int *item_list, size_t item_list_max, int mode); 
    171173 
    172174/* obj-power.c and randart.c */ 
  • trunk/src/player/player.h

    r1174 r1420  
    1515/* util.c */ 
    1616s16b modify_stat_value(int value, int amount); 
     17bool player_can_cast(void); 
     18bool player_can_study(void); 
     19bool player_can_read(void); 
  • trunk/src/player/util.c

    r996 r1420  
    11#include "angband.h" 
     2#include "object/tvalsval.h" 
    23 
    34/* 
     
    4950} 
    5051 
     52/* Is the player capable of casting a spell? */ 
     53bool player_can_cast(void) 
     54{ 
     55        if (!cp_ptr->spell_book) 
     56        { 
     57                msg_print("You cannot pray or produce magics."); 
     58                return FALSE; 
     59        } 
     60 
     61        if (p_ptr->timed[TMD_BLIND] || no_lite()) 
     62        { 
     63                msg_print("You cannot see!"); 
     64                return FALSE; 
     65        } 
     66 
     67        if (p_ptr->timed[TMD_CONFUSED]) 
     68        { 
     69                msg_print("You are too confused!"); 
     70                return FALSE; 
     71        } 
     72 
     73        return TRUE; 
     74} 
     75 
     76/* Is the player capable of studying? */ 
     77bool player_can_study(void) 
     78{ 
     79        if (!player_can_cast()) 
     80                return FALSE; 
     81 
     82        if (!p_ptr->new_spells) 
     83        { 
     84                cptr p = ((cp_ptr->spell_book == TV_MAGIC_BOOK) ? "spell" : "prayer"); 
     85                msg_format("You cannot learn any new %ss!", p); 
     86                return FALSE; 
     87        } 
     88 
     89        return TRUE; 
     90} 
     91 
     92/* Determine if the player can read scrolls. */ 
     93bool player_can_read(void) 
     94{ 
     95        if (p_ptr->timed[TMD_BLIND]) 
     96        { 
     97                msg_print("You can't see anything."); 
     98                return FALSE; 
     99        } 
     100 
     101        if (no_lite()) 
     102        { 
     103                msg_print("You have no light to read by."); 
     104                return FALSE; 
     105        } 
     106 
     107        if (p_ptr->timed[TMD_CONFUSED]) 
     108        { 
     109                msg_print("You are too confused to read!"); 
     110                return FALSE; 
     111        } 
     112 
     113        if (p_ptr->timed[TMD_AMNESIA]) 
     114        { 
     115                msg_print("You can't remember how to read!"); 
     116                return FALSE; 
     117        } 
     118 
     119        return TRUE; 
     120}