comparison items.pas @ 0:62966dd383ed default tip

initial
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Sun, 08 Dec 2013 19:39:15 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:62966dd383ed
1 { Items handling routines. }
2
3 UNIT Items;
4
5 INTERFACE
6
7 USES Global;
8
9 FUNCTION GetItemWeight(what: ItemSlot): INTEGER; { Counts the weight of an item. }
10 FUNCTION IsInThere(what,where: ItemSlot):BOOLEAN; { Checks if item WHAT is somwhere inside item WHERE. }
11 PROCEDURE GetItemLooks(VAR a:BYTE;VAR c:CHAR;what:ItemSlot); { Sets A and C to fit items looks. }
12 FUNCTION GetItemDesc(what: ItemSlot): STRING; { Returns item description. }
13 FUNCTION ItemName(what: ItemSlot): STRING; { Returns the name of an item. }
14 PROCEDURE ShowItem(what: ItemSlot); { Tells what kind of item is there. }
15
16 FUNCTION GenerateItem(id:BYTE):pItem; { Creates a new item from definitions. }
17 PROCEDURE DestroyItem(what: ItemSlot); { Destroys an item. }
18 PROCEDURE MoveInto(what,where: ItemSlot); { Tries to put item from WHAT into container in slot WHERE. }
19 PROCEDURE MoveItem(what,where: ItemSlot); { Tries to put item from WHAT into slot WHERE. }
20 PROCEDURE DropItem(what,where: ItemSlot); { Drops item from WHAT into slot WHERE, creating a pile if needed. }
21 PROCEDURE PutToPack(what: ItemSlot); { Tries to put an item into pack. }
22
23 FUNCTION ListItems(where: ItemSlot):ItemSlot; { Lists all items in the container and picks one. }
24 PROCEDURE SelectItem(what: ItemSlot); { Shows item description,asks for action and performs it. }
25 PROCEDURE CheckPile(where: ItemSlot); { Destroys a pile if itsn't needed anymore. }
26 PROCEDURE ExamInv; { Displays equipment. }
27
28 IMPLEMENTATION
29
30 USES Console;
31
32 TYPE pStack=^StackRec;
33 StackRec=RECORD
34 slt: pItem;
35 next: pStack;
36 END;
37
38 VAR stack: pStack;
39
40 { ------------------------------------------- Item information ---------- }
41
42 PROCEDURE StackPush(what: pItem); { Pushes an item entry on stack. }
43 VAR tmp: pStack;
44 BEGIN
45 New(tmp);
46 tmp^.slt:=what;
47 tmp^.next:=stack;
48 stack:=tmp;
49 END;
50
51 PROCEDURE StackPop(VAR what: pItem); { Pops an item entry from stack. }
52 VAR tmp: pStack;
53 BEGIN
54 IF stack=NIL THEN Exit;
55 what:=stack^.slt;
56 tmp:=stack;
57 stack:=stack^.next;
58 Dispose(tmp);
59 END;
60
61
62 FUNCTION GetItemWeight(what: ItemSlot): INTEGER; { Counts the weight of an item. }
63 VAR weight: INTEGER;
64 p: pItem;
65 BEGIN
66 stack:=NIL; { The stack is empty. }
67 weight:=what^^.def^.wgt*what^^.qnt; { Base weight. }
68 StackPush(what^^.con); { Now we search all the tree. }
69 REPEAT
70 StackPop(p);
71 WHILE p<>NIL DO BEGIN
72 Inc(weight,p^.def^.wgt*p^.qnt);
73 IF p^.con<>NIL THEN StackPush(p^.con);
74 p:=p^.next;
75 END;
76 UNTIL p=NIL;
77 GetItemWeight:=weight;
78 END;
79
80 FUNCTION IsInThere(what,where: ItemSlot):BOOLEAN; { Checks if item WHAT is somwhere inside item WHERE. }
81 VAR p: pItem;
82 BEGIN
83 IsInThere:=FALSE;
84 stack:=NIL;
85 StackPush(where^);
86 REPEAT
87 StackPop(p);
88 WHILE p<>NIL DO BEGIN
89 IF p=what^ THEN IsInThere:=TRUE;
90 IF p^.con<>NIL THEN StackPush(p^.con);
91 p:=p^.next;
92 END;
93 UNTIL p=NIL;
94 END;
95
96 PROCEDURE GetItemLooks(VAR a:BYTE;VAR c:CHAR;what:ItemSlot); { Sets A and C to fit items looks. }
97 VAR tmp: ItemDef;
98 BEGIN
99 IF (SLOT_KNOWN IN what^^.flg) THEN tmp:=what^^.def
100 ELSE tmp:=FindItem(what^^.def^.unk);
101 c:=tmp^.chr;
102 a:=tmp^.atr;
103 END;
104
105 FUNCTION GetItemDesc(what: ItemSlot): STRING; { Returns item description. }
106 BEGIN
107 IF (SLOT_KNOWN IN what^^.flg)OR(what^^.def^.unk=0) THEN { If item is known -- we return its description. }
108 GetItemDesc:=what^^.def^.dsc
109 ELSE GetItemDesc:=FindItem(what^^.def^.unk)^.dsc; { But if not, we return description of item type. }
110 END;
111
112 FUNCTION ItemName(what: ItemSlot): STRING; { Returns the name of an item. }
113 VAR s: STRING;
114 BEGIN
115 ItemName:='';
116 IF (what^=NIL) THEN BEGIN { If there is nothing, we return 'nothing'. }
117 ItemName:=FindItem(0)^.nam;
118 Exit;
119 END;
120
121 IF (SLOT_KNOWN IN what^^.flg) THEN s:=what^^.def^.nam { If item is known, we return its real name. }
122 ELSE s:=FindItem(what^^.def^.unk)^.nam;
123
124 { When there are many items of the same kind, we tell how many. }
125 IF (ITEM_MULTIPLE IN what^^.def^.flg) AND (what^^.qnt>1) THEN
126 s:=Replace(Plural(s),'@a',Num(what^^.qnt))
127 ELSE BEGIN { Elsewhen we add 'a' or 'an'. }
128 s:=Replace(s,'@a a','an a');
129 s:=Replace(s,'@a e','an e');
130 s:=Replace(s,'@a i','an i');
131 s:=Replace(s,'@a o','an o');
132 s:=Replace(s,'@a u','an u');
133 s:=Replace(s,'@a ' ,'a ');
134 s:=Replace(s,'@a' ,'a');
135 s:=Replace(s,'@s','');
136 END;
137 ItemName:=s;
138 END;
139
140 PROCEDURE ShowItem(what: ItemSlot); { Tells what kind of item is there. }
141 BEGIN
142 IF what^=NIL THEN Exit; { If there is nothing -- we won't bother. }
143 Msg(Replace(msgs[13],'@v',ItemName(what)));
144 END;
145
146 { ------------------------------------------- Item moving and creation -- }
147
148 FUNCTION GenerateItem(id:BYTE):pItem; { Creates a new item from definitions. }
149 VAR item: ItemDef;
150 tmp: pItem;
151 BEGIN
152 New(tmp); { We make room for item. }
153 item:=FindItem(id); { We find according definitions. }
154 tmp^.def:=item; { We fill in all data necessary. }
155 tmp^.qnt:=item^.qnt+Random(item^.qnt);
156 tmp^.flg:=[];
157 tmp^.con:=NIL;
158 tmp^.next:=NIL;
159 IF (ITEM_KNOWN IN item^.flg) THEN tmp^.flg:=tmp^.flg+[SLOT_KNOWN];
160 GenerateItem:=tmp; { And we have brand new item. }
161 END;
162
163 PROCEDURE DestroyItem(what: ItemSlot); { Destroys an item. }
164 VAR tmp: pItem;
165 BEGIN
166 tmp:=what^; { We take item from any container it may be in. }
167 what^:=tmp^.next; { We update this container's list of items. }
168 Dispose(tmp); { And we relase memory. }
169 END;
170
171 PROCEDURE MoveInto(what,where: ItemSlot); { Tries to put item from WHAT into container in slot WHERE. }
172 VAR tmp: pItem;
173 BEGIN
174 IF IsInThere(where,what) THEN Exit; { We dont want to put something into itself! }
175 tmp:=what^; { Now, we take item from any container it may be in. }
176 what^:=tmp^.next; { We update this container's list of items. }
177 tmp^.next:=where^^.con; { We put all items from WHERE behind our item. }
178 where^^.con:=tmp; { We put our item into item in slot WHERE. }
179 END;
180
181 PROCEDURE MoveItem(what,where: ItemSlot); { Tries to put item from WHAT into slot WHERE. }
182 VAR tmp: pItem;
183 BEGIN
184 IF where^<>NIL THEN Exit; { Is there something already? }
185 tmp:=what^; { Now, we take item from any container it may be in. }
186 what^:=tmp^.next; { We update this container's list of items. }
187 tmp^.next:=NIL; { Our item is the only one here. }
188 where^:=tmp; { We put our item into slot WHERE. }
189 END;
190
191 PROCEDURE DropItem(what,where: ItemSlot); { Drops item from WHAT into slot WHERE, creating a pile if needed. }
192 VAR tmp: ItemSlot;
193 p: pItem;
194 BEGIN
195 IF where^=NIL THEN BEGIN { If WHERE is empty, we simply put our item there. }
196 MoveItem(what,where);
197 Exit;
198 END;
199
200 IF where^^.def^.id=PILEITEM THEN BEGIN { If there is a pile already, we just add our item to the pile. }
201 MoveInto(what,where)
202 END ELSE BEGIN { If there is an item already... }
203 New(tmp); { We need 'third hand'. }
204 tmp^:=NIL;
205 MoveItem(where,tmp); { We pick the item from the floor. }
206 p:=GenerateItem(PILEITEM); { Then we create a pile... }
207 MoveItem(@p,where); { And put it on the floor. }
208 MoveInto(tmp,where); { Then we put both items into the pile. }
209 MoveInto(what,where);
210 Dispose(tmp); { W don't need third hand anymore. }
211 END;
212 END;
213
214 PROCEDURE PutToPack(what: ItemSlot); { Tries to put an item into pack. }
215 BEGIN
216 IF (pc.inv[INV_PACK]=NIL) OR { Have we any pack to put into? }
217 NOT (ITEM_EMPTY IN pc.inv[INV_PACK]^.def^.flg) THEN Exit;
218 { We inform the player about what we are doing. }
219 Msg(Replace(Replace(msgs[15],'@1',ItemName(@(pc.inv[INV_PACK]))),'@v',ItemName(what)));
220 MoveInto(what,@(pc.inv[INV_PACK])); { And we do it. }
221 END;
222
223 { ------------------------------------------- Menus and handling -------- }
224
225 PROCEDURE CheckCmd(VAR a:INTEGER;c:CHAR;b:BYTE);{ Checks if key C belong to command B }
226 BEGIN { and sets A to this command if so. }
227 IF c=cmd[b] THEN a:=b;
228 END;
229
230 FUNCTION ListItems(where: ItemSlot):ItemSlot; { Lists all items in the container and picks one. }
231 VAR p,page: ItemSlot;
232 c,k: CHAR;
233 BEGIN
234 ListItems:=NIL;
235 ClrMsg;
236 p:=@(where^^.con);
237 REPEAT { Tell what item we are looking into. }
238 Msg(Replace(msgs[29],'@v',ItemName(where)));
239
240 page:=p; { Mark the top of actual page. }
241 c:='a'; { Show a-p items. }
242 WHILE (p^<>NIL) AND (c<='p') DO BEGIN
243 Msg(Replace(Replace(msgs[30],'@1',c),'@v',ItemName(p)));
244 Inc(c);
245 p:=@(p^^.next);
246 END;
247 { Tell if there is more. }
248 IF (p^<>NIL) THEN Msg(msgs[19]);
249
250 k:=GetKey; { Get players choice. }
251 ClrMsg; { And find this item. }
252 IF (k>='a') AND (k<c) THEN BEGIN
253 p:=page;
254 c:='a';
255 WHILE (c<>k) DO BEGIN
256 Inc(c);
257 p:=@(p^^.next);
258 END;
259 ListItems:=p;
260 END;
261 IF k<>cmd[CMDMORE] THEN Exit; { If the player picked something -- we finish. }
262 IF p^=NIL THEN p:=@(where^^.con);
263 UNTIL FALSE; { And if not, we display another page. }
264 END;
265
266 PROCEDURE SelectItem(what: ItemSlot); { Shows item description,asks for action and performs it. }
267 VAR c: CHAR;
268 l: INTEGER;
269 tmp: pItem;
270 s: STRING;
271
272 AllowLoot, AllowPutInto, AllowHold, AllowDrop, AllowPack: BOOLEAN;
273 WhereEquip: BYTE;
274
275 BEGIN
276 REPEAT
277 IF (what=NIL) OR (what^=NIL) OR { We won't select an empty item nor pile. }
278 (what^^.def^.id=PILEITEM) THEN BEGIN
279 Msg(msgs[10]);
280 Exit;
281 END;
282
283 ClrMsg;
284 Msg(Replace(msgs[17],'@v',ItemName(what))); { We show item's name and description. }
285 {IF (ITEM_KNOWN IN what^^.flg) THEN}
286 Msg(GetItemDesc(what));
287
288 l:=GetItemWeight(what); { We display item's weight. }
289 IF l=1 THEN s:=Replace(msgs[33],'@s','')
290 ELSE s:=Plural(msgs[33]);
291 Msg(Replace(s,'@v',Num(l)));
292
293 AllowHold:=FALSE; { Now we determine what actions can be performed. }
294 AllowPutInto:=FALSE;
295 AllowLoot:=FALSE;
296 AllowDrop:=FALSE;
297 AllowPack:=FALSE;
298 WhereEquip:=0;
299
300 IF (pc.inv[INV_PACK]<>NIL)AND { If we have pack and the item we have selected isn't that pack, }
301 (ITEM_EMPTY IN pc.inv[INV_PACK]^.def^.flg)AND{we can put our item into pack. }
302 NOT(IsInThere(what,@(pc.inv[INV_PACK])))AND
303 (pc.inv[INV_PACK]<>what^) THEN AllowPack:=TRUE;
304
305 IF pc.inv[INV_HELD]=NIL THEN AllowHold:=TRUE; { If the player character is empty handed, we can hold something. }
306
307 IF (pc.inv[INV_HELD]<>NIL)AND { If the player holds something, and selected item is a container,
308 { he can put held item in. }
309 NOT(IsInThere(what,@(pc.inv[INV_HELD])))AND { But we have to make sure he won't put it into itself! }
310 (ITEM_EMPTY IN what^^.def^.flg) THEN AllowPutInto:=TRUE;
311
312 IF (what^^.con<>NIL) THEN AllowLoot:=TRUE; { If it isn't empty, we can loot it. }
313
314 { Dropping only when the item isn't on floor already. }
315 IF NOT(IsInThere(what,@(GetMap(playchr^.x,playchr^.y)^.slt))) THEN AllowDrop:=TRUE;
316
317 WhereEquip:=what^^.def^.eqp; { And we can equip is if it can be equipped. :) }
318
319 IF AllowHold THEN Msg(msgs[41]); { We display action names. }
320 IF AllowPutInto THEN Msg(msgs[42]);
321 IF WhereEquip>0 THEN Msg(msgs[44]);
322 IF AllowPack THEN Msg(msgs[45]);
323 IF AllowLoot THEN Msg(msgs[40]);
324 IF AllowDrop THEN Msg(msgs[43]);
325
326 l:=CMDNOTHING; { Ask for action. }
327 c:=GetKey;
328 ClrMsg;
329 IF AllowPack THEN CheckCmd(l,c,CMDPUTTOPACK);
330 IF AllowLoot THEN CheckCmd(l,c,CMDLOOT);
331 IF AllowHold THEN CheckCmd(l,c,CMDUPINAIR);
332 IF AllowPutInto THEN CheckCmd(l,c,CMDUPINAIR);
333 IF WhereEquip>0 THEN CheckCmd(l,c,CMDEQUIP);
334 IF AllowDrop THEN CheckCmd(l,c,CMDDROP);
335
336 CASE l OF { Perform the action. }
337 CMDLOOT: BEGIN { We list items inside and wait allow to select an item. }
338 what:=ListItems(what);
339 END;
340 CMDPUTTOPACK: BEGIN
341 PutToPack(what); { Simple. }
342 what:=NIL; { We don't want to select this item again. }
343 END;
344 CMDUPINAIR: IF AllowHold THEN BEGIN
345 MoveItem(what,@(pc.inv[INV_HELD]));
346 what:=NIL;
347 END ELSE IF AllowPutInto THEN BEGIN
348 MoveInto(@(pc.inv[INV_HELD]),what);
349 Msg(Replace(Replace(msgs[15],'@1',ItemName(what)) ,'@v',ItemName(@(pc.inv[INV_HELD]))));
350 what:=NIL;
351 END;
352 CMDDROP:BEGIN
353 DropItem(what,@(GetMap(playchr^.x,playchr^.y)^.slt));
354 ShowItem(@(GetMap(playchr^.x,playchr^.y)^.slt));
355 what:=NIL;
356 END;
357 CMDEQUIP:BEGIN { If there is an item equipped and player character is empty handed, we hold equipped item. }
358 IF pc.inv[WhereEquip]<>NIL THEN
359 IF pc.inv[INV_HELD]=NIL THEN MoveItem(@(pc.inv[WhereEquip]),@(pc.inv[INV_HELD]));
360
361 { If the slot is free, we equip selected item. }
362 IF pc.inv[WhereEquip]=NIL THEN MoveItem(what,@(pc.inv[WhereEquip]))
363 ELSE Msg(msgs[32]);
364 what:=NIL;
365 END;
366 CMDNOTHING:BEGIN { If no action, we cancel selection. }
367 Msg(msgs[10]);
368 what:=NIL;
369 END;
370 END;
371 UNTIL what=NIL; { If the player haven't selected another item, we finish. }
372 END;
373
374 PROCEDURE CheckPile(where: ItemSlot); { Destroys a pile if itsn't needed anymore. }
375 VAR tmp: ItemSlot;
376 BEGIN
377 IF where^=NIL THEN Exit; { If there is nothing there, we finish. }
378 IF where^^.def^.id<>PILEITEM THEN Exit; { If there is no pile, we finish too. }
379
380 IF where^^.con=NIL THEN BEGIN { If the pile is empty, we simply destroy it. }
381 DestroyItem(where);
382 Exit;
383 END;
384 IF (where^^.con^.next=NIL) THEN BEGIN { If there is only one item in the pile.. }
385 New(tmp); { We need 'third hand'. }
386 tmp^:=NIL;
387 MoveItem(@(where^^.con),tmp); { We take the item out of pile. }
388 DestroyItem(where); { We destroy the pile. }
389 MoveItem(tmp,where); { Then we put the item on the floor. }
390 Dispose(tmp); { We don't need third hand. }
391 END;
392 END;
393
394 PROCEDURE ExamInv; { Displays equipment. }
395 VAR c:CHAR;
396 BEGIN
397 ClrMsg;
398 Msg(Concat('@Ma@m)HELD: @M',ItemName(@(pc.inv[INV_HELD]))));
399 Msg(Concat('@Mb@m)PACK: @M',ItemName(@(pc.inv[INV_PACK]))));
400 Msg(Concat('@Mc@m)WEAR: @M',ItemName(@(pc.inv[INV_WEAR]))));
401 c:=GetKey;
402 ClrMsg;
403 CASE c OF
404 'a': SelectItem(@pc.inv[INV_HELD]);
405 'b': SelectItem(@pc.inv[INV_PACK]);
406 'c': SelectItem(@pc.inv[INV_WEAR]);
407 END;
408 END;
409
410 END.