1 /* $Id$ */
2 /* File: lua_bind.c */
3 
4 /* Purpose: various lua bindings */
5 
6 /*
7  * Copyright (c) 2001 DarkGod
8  *
9  * This software may be copied and distributed for educational, research, and
10  * not for profit purposes provided that this copyright and statement are
11  * included in all such copies.
12  */
13 
14 #include "angband.h"
15 #include "lua.h"
16 #include "lualib.h"
17 #include "lauxlib.h"
18 #include "tolua.h"
19 
20 extern lua_State* L;
21 
22 /* items */
23 static char *lua_item_tester_fct;
lua_item_tester(object_type * o_ptr)24 static bool lua_item_tester(object_type* o_ptr)
25 {
26 	int oldtop = lua_gettop(L);
27 	bool ret;
28 
29 	lua_getglobal(L, lua_item_tester_fct);
30 	tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type"));
31 	lua_call(L, 1, 1);
32 	ret = lua_tonumber(L, -1);
33 	lua_settop(L, oldtop);
34 	return (ret);
35 }
36 
lua_set_item_tester(int tval,char * fct)37 void    lua_set_item_tester(int tval, char *fct)
38 {
39 	if (tval)
40 	{
41 		item_tester_tval = tval;
42 	}
43 	else
44 	{
45 		lua_item_tester_fct = fct;
46 		item_tester_hook = lua_item_tester;
47 	}
48 }
49 
50 
51 /* Spell schools */
new_school(int i,cptr name,s16b skill)52 s16b new_school(int i, cptr name, s16b skill)
53 {
54         schools[i].name = string_make(name);
55         schools[i].skill = skill;
56         return (i);
57 }
58 
new_spell(int i,cptr name)59 s16b new_spell(int i, cptr name)
60 {
61         school_spells[i].name = string_make(name);
62         school_spells[i].level = 0;
63         school_spells[i].level = 0;
64         return (i);
65 }
66 
grab_spell_type(s16b num)67 spell_type *grab_spell_type(s16b num)
68 {
69 	return (&school_spells[num]);
70 }
71 
grab_school_type(s16b num)72 school_type *grab_school_type(s16b num)
73 {
74 	return (&schools[num]);
75 }
76 
77 /* Change this fct if I want to switch to learnable spells */
lua_get_level(int Ind,s32b s,s32b lvl,s32b max,s32b min,s32b bonus)78 s32b lua_get_level(int Ind, s32b s, s32b lvl, s32b max, s32b min, s32b bonus)
79 {
80         s32b tmp;
81 
82         tmp = lvl - ((school_spells[s].skill_level - 1) * (SKILL_STEP / 10));
83         lvl = (tmp * (max * (SKILL_STEP / 10)) / (SKILL_MAX / 10)) / (SKILL_STEP / 10);
84         if (lvl < min) lvl = min;
85         else if (lvl > 0)
86         {
87                 tmp += bonus;
88                 lvl = (tmp * (max * (SKILL_STEP / 10)) / (SKILL_MAX / 10)) / (SKILL_STEP / 10);
89 		if (school_spells[s].spell_power) {
90 			lvl *= (100 + get_skill_scale(p_ptr, SKILL_SPELL, 40));
91 			lvl /= 100;
92 		}
93         }
94         return lvl;
95 }
96 
97 /* adj_mag_stat? stat_ind??  pfft */
lua_spell_chance(int i,s32b chance,int level,int skill_level,int mana,int cur_mana,int stat)98 s32b lua_spell_chance(int i, s32b chance, int level, int skill_level, int mana, int cur_mana, int stat)
99 {
100         int             minfail;
101 
102         /* correct LUA overflow bug */
103         if (chance >= 156) chance -= 256;
104 
105 	/* Reduce failure rate by "effective" level adjustment */
106         chance -= 3 * (level - skill_level);
107 
108 	/* Reduce failure rate by INT/WIS adjustment */
109         chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[stat]] - 1);
110 
111 	 /* Not enough mana to cast */
112         if (chance < 0) chance = 0;
113 #if 0 /* just confuses and casting without mana is disabled anyway */
114         if (mana > cur_mana) chance += 15 * (mana - cur_mana);
115 #endif
116 	/* Extract the minimum failure rate */
117         minfail = adj_mag_fail[p_ptr->stat_ind[stat]];
118 
119 #if 0	/* disabled for the time being */
120 	/*
121          * Non mage characters never get too good
122 	 */
123 	if (!(PRACE_FLAG(PR1_ZERO_FAIL)))
124 	{
125 		if (minfail < 5) minfail = 5;
126 	}
127 
128 	/* Hack -- Priest prayer penalty for "edged" weapons  -DGK */
129 	if ((forbid_non_blessed()) && (p_ptr->icky_wield)) chance += 25;
130 #endif	/* 0 */
131 
132 	/* Minimum failure rate */
133 	if (chance < minfail) chance = minfail;
134 
135 	/* Stunning makes spells harder */
136 	if (p_ptr->stun > 50) chance += 25;
137 	else if (p_ptr->stun) chance += 15;
138 
139 	/* Always a 5 percent chance of working */
140 	if (chance > 95) chance = 95;
141 
142 	/* Return the chance */
143 	return (chance);
144 }
145 
146 #if 0
147 /* Cave */
148 cave_type *lua_get_cave(int y, int x)
149 {
150         return (&(cave[y][x]));
151 }
152 
153 void set_target(int y, int x)
154 {
155         target_who = -1;
156         target_col = x;
157         target_row = y;
158 }
159 
160 /* Level gen */
161 void get_map_size(char *name, int *ysize, int *xsize)
162 {
163         *xsize = 0;
164 	*ysize = 0;
165 	init_flags = INIT_GET_SIZE;
166 	process_dungeon_file_full = TRUE;
167 	process_dungeon_file(name, ysize, xsize, cur_hgt, cur_wid, TRUE);
168 	process_dungeon_file_full = FALSE;
169 
170 }
171 
172 void load_map(char *name, int *y, int *x)
173 {
174 	/* Set the correct monster hook */
175 	set_mon_num_hook();
176 
177 	/* Prepare allocation table */
178 	get_mon_num_prep();
179 
180 	init_flags = INIT_CREATE_DUNGEON;
181 	process_dungeon_file_full = TRUE;
182 	process_dungeon_file(name, y, x, cur_hgt, cur_wid, TRUE);
183 	process_dungeon_file_full = FALSE;
184 }
185 
186 bool alloc_room(int by0, int bx0, int ysize, int xsize, int *y1, int *x1, int *y2, int *x2)
187 {
188         int xval, yval, x, y;
189 
190 	/* Try to allocate space for room.  If fails, exit */
191 	if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return FALSE;
192 
193 	/* Get corner values */
194 	*y1 = yval - ysize / 2;
195 	*x1 = xval - xsize / 2;
196 	*y2 = yval + (ysize) / 2;
197 	*x2 = xval + (xsize) / 2;
198 
199 	/* Place a full floor under the room */
200 	for (y = *y1 - 1; y <= *y2 + 1; y++)
201 	{
202 		for (x = *x1 - 1; x <= *x2 + 1; x++)
203 		{
204 			cave_type *c_ptr = &cave[y][x];
205 			cave_set_feat(y, x, floor_type[rand_int(100)]);
206 			c_ptr->info |= (CAVE_ROOM);
207 			c_ptr->info |= (CAVE_GLOW);
208 		}
209         }
210         return TRUE;
211 }
212 
213 
214 /* Files */
215 void lua_print_hook(cptr str)
216 {
217         fprintf(hook_file, str);
218 }
219 
220 
221 /*
222  * Finds a good random bounty monster
223  * Im too lazy to write it in lua since the lua API for monsters is not very well yet
224  */
225 
226 /*
227  * Hook for bounty monster selection.
228  */
229 static bool lua_mon_hook_bounty(int r_idx)
230 {
231 	monster_race* r_ptr = &r_info[r_idx];
232 
233 
234 	/* Reject uniques */
235 	if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
236 
237 	/* Reject those who cannot leave anything */
238 	if (!(r_ptr->flags9 & RF9_DROP_CORPSE)) return (FALSE);
239 
240         /* Accept only monsters that can be generated */
241         if (r_ptr->flags9 & RF9_SPECIAL_GENE) return (FALSE);
242         if (r_ptr->flags9 & RF9_NEVER_GENE) return (FALSE);
243 
244 	/* Reject pets */
245 	if (r_ptr->flags7 & RF7_PET) return (FALSE);
246 
247 	/* Reject friendly creatures */
248 	if (r_ptr->flags7 & RF7_FRIENDLY) return (FALSE);
249 
250         /* Accept only monsters that are not breeders */
251         if (r_ptr->flags4 & RF4_MULTIPLY) return (FALSE);
252 
253         /* Forbid joke monsters */
254         if (r_ptr->flags8 & RF8_JOKEANGBAND) return (FALSE);
255 
256         /* Accept only monsters that are not good */
257         if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
258 
259 	/* The rest are acceptable */
260 	return (TRUE);
261 }
262 
263 int lua_get_new_bounty_monster(int lev)
264 {
265         int r_idx;
266 
267 	/*
268 	 * Set up the hooks -- no bounties on uniques or monsters
269 	 * with no corpses
270 	 */
271 	get_mon_num_hook = lua_mon_hook_bounty;
272 	get_mon_num_prep();
273 
274 	/* Set up the quest monster. */
275 	r_idx = get_mon_num(lev);
276 
277 	/* Undo the filters */
278 	get_mon_num_hook = NULL;
279         get_mon_num_prep();
280 
281         return r_idx;
282 }
283 
284 #endif
285 
get_inven_sval(int Ind,int inven_slot)286 int get_inven_sval(int Ind, int inven_slot) {
287 	return (inventory[inven_slot].sval);
288 }
get_inven_pval(int Ind,int inven_slot)289 int get_inven_pval(int Ind, int inven_slot) {
290 	return (inventory[inven_slot].pval);
291 }
get_inven_xtra(int Ind,int inven_slot,int n)292 int get_inven_xtra(int Ind, int inven_slot, int n) {
293 	/* browsing item in a store? */
294 	if (inven_slot < 0) {
295 		switch (n) {
296 		case 1: return (store.stock[(-inven_slot) - 1].xtra1);
297 		case 2: return (store.stock[(-inven_slot) - 1].xtra2);
298 		case 3: return (store.stock[(-inven_slot) - 1].xtra3);
299 		case 4: return (store.stock[(-inven_slot) - 1].xtra4);
300 		case 5: return (store.stock[(-inven_slot) - 1].xtra5);
301 		case 6: return (store.stock[(-inven_slot) - 1].xtra6);
302 		case 7: return (store.stock[(-inven_slot) - 1].xtra7);
303 		case 8: return (store.stock[(-inven_slot) - 1].xtra8);
304 		case 9: return (store.stock[(-inven_slot) - 1].xtra9);
305 		default: return (0); //failure
306 		}
307 	} else  { /* browsing item in inventory */
308 		switch (n) {
309 		case 1: return (inventory[inven_slot].xtra1);
310 		case 2: return (inventory[inven_slot].xtra2);
311 		case 3: return (inventory[inven_slot].xtra3);
312     		case 4: return (inventory[inven_slot].xtra4);
313         	case 5: return (inventory[inven_slot].xtra5);
314 		case 6: return (inventory[inven_slot].xtra6);
315 		case 7: return (inventory[inven_slot].xtra7);
316 		case 8: return (inventory[inven_slot].xtra8);
317 		case 9: return (inventory[inven_slot].xtra9);
318 		default: return (0); //failure
319 		}
320 	}
321 }
322 
323 /* lua wrapper for c_get_item that feeds the arguments to c_get_item correctly */
get_item_aux(int * cp,cptr pmt,bool equip,bool inven,bool floor)324 bool get_item_aux(int *cp, cptr pmt, bool equip, bool inven, bool floor) {
325 	int mode = 0;
326 
327 	if (equip) mode |= USE_EQUIP;
328 	if (inven) mode |= USE_INVEN;
329 	if (floor) mode |= USE_FLOOR;
330 
331 	return c_get_item(cp, pmt, mode);
332 }
333