root/trunk/src/death.c

Revision 966, 9.3 kB (checked in by takkaria, 4 weeks ago)

Remove the "new savefile" code, since it's not suitable for shipping and won't be used because it's not space-efficient enough. This should fix #505, too.

  • Property svn:eol-style set to native
Line 
1 /*
2  * File: death.c
3  * Purpose: Handle the UI bits that happen after the character dies.
4  *
5  * Copyright (c) 1987 - 2007 Angband contributors
6  *
7  * This work is free software; you can redistribute it and/or modify it
8  * under the terms of either:
9  *
10  * a) the GNU General Public License as published by the Free Software
11  *    Foundation, version 2, or
12  *
13  * b) the "Angband licence":
14  *    This software may be copied and distributed for educational, research,
15  *    and not for profit purposes provided that this copyright and statement
16  *    are included in all such copies.  Other copyrights may also apply.
17  */
18 #include "angband.h"
19 #include "ui-menu.h"
20 #include "cmds.h"
21
22
23 /*
24  * Hack - save the time of death
25  */
26 static time_t death_time = (time_t)0;
27
28
29
30 /*
31  * Write formatted string `fmt` on line `y`, centred between points x1 and x2.
32  */
33 static void put_str_centred(int y, int x1, int x2, const char *fmt, ...)
34 {
35         va_list vp;
36         char *tmp;
37         size_t len;
38         int x;
39
40         /* Format into the (growable) tmp */
41         va_start(vp, fmt);
42         tmp = vformat(fmt, vp);
43         va_end(vp);
44
45         /* Centre now */
46         len = strlen(tmp);
47         x = x1 + ((x2-x1)/2 - len/2);
48
49         put_str(tmp, y, x);
50 }
51
52
53 /*
54  * Display the tombstone
55  */
56 static void print_tomb(void)
57 {
58         ang_file *fp;
59         char buf[1024];
60         int line = 0;
61
62
63         Term_clear();
64
65         /* Open the death file */
66         path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, "dead.txt");
67         fp = file_open(buf, MODE_READ, -1);
68
69         if (fp)
70         {
71                 while (file_getl(fp, buf, sizeof(buf)))
72                         put_str(buf, line++, 0);
73
74                 file_close(fp);
75         }
76
77         line = 7;
78
79         put_str_centred(line++, 8, 8+31, "%s", op_ptr->full_name);
80         put_str_centred(line++, 8, 8+31, "the");
81         if (p_ptr->total_winner)
82                 put_str_centred(line++, 8, 8+31, "Magnificent");
83         else
84                 put_str_centred(line++, 8, 8+31, "%s", c_text + cp_ptr->title[(p_ptr->lev - 1) / 5]);
85
86         line++;
87
88         put_str_centred(line++, 8, 8+31, "%s", c_name + cp_ptr->name);
89         put_str_centred(line++, 8, 8+31, "Level: %d", (int)p_ptr->lev);
90         put_str_centred(line++, 8, 8+31, "Exp: %d", (int)p_ptr->exp);
91         put_str_centred(line++, 8, 8+31, "AU: %d", (int)p_ptr->au);
92         put_str_centred(line++, 8, 8+31, "Killed on Level %d", p_ptr->depth);
93         put_str_centred(line++, 8, 8+31, "by %s.", p_ptr->died_from);
94
95         line++;
96
97         put_str_centred(line++, 8, 8+31, "by %-.24s", ctime(&death_time));
98 }
99
100
101 /*
102  * Know inventory and home items upon death
103  */
104 static void death_knowledge(void)
105 {
106         store_type *st_ptr = &store[STORE_HOME];
107         object_type *o_ptr;
108
109         int i;
110
111         for (i = 0; i < INVEN_TOTAL; i++)
112         {
113                 o_ptr = &inventory[i];
114                 if (!o_ptr->k_idx) continue;
115
116                 object_aware(o_ptr);
117                 object_known(o_ptr);
118         }
119
120         for (i = 0; i < st_ptr->stock_num; i++)
121         {
122                 o_ptr = &st_ptr->stock[i];
123                 if (!o_ptr->k_idx) continue;
124
125                 object_aware(o_ptr);
126                 object_known(o_ptr);
127         }
128
129         /* Hack -- Recalculate bonuses */
130         p_ptr->update |= (PU_BONUS);
131         handle_stuff();
132 }
133
134
135
136 /*
137  * Display the winner crown
138  */
139 static void display_winner(void)
140 {
141         char buf[1024];
142         ang_file *fp;
143
144         int wid, hgt;
145         int i = 2;
146         int width = 0;
147
148
149         path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, "crown.txt");
150         fp = file_open(buf, MODE_READ, -1);
151
152         Term_clear();
153         Term_get_size(&wid, &hgt);
154
155         if (fp)
156         {
157                 /* Get us the first line of file, which tells us how long the */
158                 /* longest line is */
159                 file_getl(fp, buf, sizeof(buf));
160                 sscanf(buf, "%d", &width);
161                 if (!width) width = 25;
162
163                 /* Dump the file to the screen */
164                 while (file_getl(fp, buf, sizeof(buf)))
165                         put_str(buf, i++, (wid/2) - (width/2));
166
167                 file_close(fp);
168         }
169
170         put_str_centred(i, 0, wid, "All Hail the Mighty %s!", sp_ptr->winner);
171
172         flush();
173         pause_line(Term->hgt - 1);
174 }
175
176
177 /*
178  * Menu command: dump character dump to file.
179  */
180 static void death_file(void *unused, const char *title)
181 {
182         char ftmp[80];
183         strnfmt(ftmp, sizeof(ftmp), "%s.txt", op_ptr->base_name);
184
185         (void)unused;
186         (void)title;
187
188         if (!get_string("File name: ", ftmp, sizeof(ftmp)))
189                 return;
190
191         if (ftmp[0] && (ftmp[0] != ' '))
192         {
193                 errr err;
194
195                 /* Dump a character file */
196                 screen_save();
197                 err = file_character(ftmp, FALSE);
198                 screen_load();
199
200                 /* Check result */
201                 if (err)
202                         msg_print("Character dump failed!");
203                 else
204                         msg_print("Character dump successful.");
205
206                 /* Flush messages */
207                 message_flush();
208         }
209 }
210
211 /*
212  * Menu command: view character dump and inventory.
213  */
214 static void death_info(void *unused, const char *title)
215 {
216         int i, j, k;
217         object_type *o_ptr;
218         store_type *st_ptr = &store[STORE_HOME];
219
220         (void)unused;
221         (void)title;
222
223
224         screen_save();
225
226         /* Display player */
227         display_player(0);
228
229         /* Prompt for inventory */
230         prt("Hit any key to see more information: ", 0, 0);
231
232         /* Allow abort at this point */
233         (void)anykey();
234
235
236         /* Show equipment and inventory */
237
238         /* Equipment -- if any */
239         if (p_ptr->equip_cnt)
240         {
241                 Term_clear();
242                 item_tester_full = TRUE;
243                 show_equip();
244                 prt("You are using: -more-", 0, 0);
245                 (void)anykey();
246         }
247
248         /* Inventory -- if any */
249         if (p_ptr->inven_cnt)
250         {
251                 Term_clear();
252                 item_tester_full = TRUE;
253                 show_inven();
254                 prt("You are carrying: -more-", 0, 0);
255                 (void)anykey();
256         }
257
258
259
260         /* Home -- if anything there */
261         if (st_ptr->stock_num)
262         {
263                 /* Display contents of the home */
264                 for (k = 0, i = 0; i < st_ptr->stock_num; k++)
265                 {
266                         /* Clear screen */
267                         Term_clear();
268
269                         /* Show 12 items */
270                         for (j = 0; (j < 12) && (i < st_ptr->stock_num); j++, i++)
271                         {
272                                 byte attr;
273
274                                 char o_name[80];
275                                 char tmp_val[80];
276
277                                 /* Get the object */
278                                 o_ptr = &st_ptr->stock[i];
279
280                                 /* Print header, clear line */
281                                 strnfmt(tmp_val, sizeof(tmp_val), "%c) ", I2A(j));
282                                 prt(tmp_val, j+2, 4);
283
284                                 /* Get the object description */
285                                 object_desc(o_name, sizeof(o_name), o_ptr, TRUE, ODESC_FULL);
286
287                                 /* Get the inventory color */
288                                 attr = tval_to_attr[o_ptr->tval % N_ELEMENTS(tval_to_attr)];
289
290                                 /* Display the object */
291                                 c_put_str(attr, o_name, j+2, 7);
292                         }
293
294                         /* Caption */
295                         prt(format("Your home contains (page %d): -more-", k+1), 0, 0);
296
297                         /* Wait for it */
298                         (void)anykey();
299                 }
300         }
301
302         screen_load();
303 }
304
305 /*
306  * Menu command: peruse pre-death messages.
307  */
308 static void death_messages(void *unused, const char *title)
309 {
310         (void)unused;
311         (void)title;
312
313         screen_save();
314         do_cmd_messages();
315         screen_load();
316 }
317
318 /*
319  * Menu command: see top twenty scores.
320  */
321 static void death_scores(void *unused, const char *title)
322 {
323         (void)unused;
324         (void)title;
325
326         screen_save();
327         show_scores();
328         screen_load();
329 }
330
331 /*
332  * Menu command: examine items in the inventory.
333  */
334 static void death_examine(void *unused, const char *title)
335 {
336         int item;
337         cptr q, s;
338
339         (void)unused;
340         (void)title;
341
342         /* Get an item */
343         q = "Examine which item? ";
344         s = "You have nothing to examine.";
345
346         while (get_item(&item, q, s, (USE_INVEN | USE_EQUIP)))
347         {
348                 object_type *o_ptr = &inventory[item];
349
350                 /* Describe */
351                 text_out_hook = text_out_to_screen;
352                 screen_save();
353                 Term_gotoxy(0, 0);
354
355                 object_info_header(o_ptr);
356                 if (!object_info_known(o_ptr))
357                         text_out("This item does not possess any special abilities.");
358
359                 text_out_c(TERM_L_BLUE, "\n\n[Press any key to continue]\n");
360                 (void)anykey();
361
362                 screen_load();
363         }
364 }
365
366
367 /*
368  * Menu command: view character history.
369  */
370 static void death_history(void *unused, const char *title)
371 {
372         (void)unused;
373         (void)title;
374
375         history_display();
376 }
377
378
379 /*
380  * Menu structures for the death menu.
381  */
382 static menu_type death_menu;
383 static menu_action death_actions[] =
384 {
385         { 'i', "Information",   death_info,     NULL },
386         { 'm', "Messages",      death_messages, NULL },
387         { 'f', "File dump",     death_file,     NULL },
388         { 'v', "View scores",   death_scores,   NULL },
389         { 'x', "Examine items", death_examine,  NULL },
390         { 'h', "History",       death_history,  NULL },
391         { 'q', "Quit",          death_examine,  NULL },
392 };
393
394 /* Return the tag for a menu entry */
395 static char death_menu_tag(menu_type *menu, int oid)
396 {
397         (void)menu;
398         return death_actions[oid].id;
399 }
400
401 /* Display a menu entry */
402 static void death_menu_display(menu_type *menu, int oid, bool cursor, int row, int col, int width)
403 {
404         byte attr = curs_attrs[CURS_KNOWN][(int)cursor];
405         (void)menu;
406         (void)width;
407         c_prt(attr, death_actions[oid].name, row, col);
408 }
409
410 static const menu_iter death_iter =
411 {
412         death_menu_tag,
413         NULL,
414         death_menu_display,
415         NULL
416 };
417
418
419
420
421 /*
422  * Handle character death
423  */
424 void death_screen(void)
425 {
426         menu_type *menu;
427         const char cmd_keys[] = { ARROW_LEFT, ARROW_RIGHT, '\0' };
428         const region area = { 51, 2, 0, 7 };
429
430         int cursor = 0;
431         ui_event_data c = EVENT_EMPTY;
432
433
434         /* Retire in the town in a good state */
435         if (p_ptr->total_winner)
436         {
437                 p_ptr->depth = 0;
438                 my_strcpy(p_ptr->died_from, "Ripe Old Age", sizeof(p_ptr->died_from));
439                 p_ptr->exp = p_ptr->max_exp;
440                 p_ptr->lev = p_ptr->max_lev;
441                 p_ptr->au += 10000000L;
442
443                 display_winner();
444         }
445
446         /* Save dead player */
447         if (!old_save())
448         {
449                 msg_print("death save failed!");
450                 message_flush();
451         }
452
453         /* Get time of death */
454         (void)time(&death_time);
455         print_tomb();
456         death_knowledge();
457         enter_score(&death_time);
458
459         /* Flush all input and output */
460         flush();
461         message_flush();
462
463
464         /* Initialize the menu */
465         menu = &death_menu;
466         WIPE(menu, menu_type);
467         menu->menu_data = death_actions;
468         menu->flags = MN_CASELESS_TAGS;
469         menu->cmd_keys = cmd_keys;
470         menu->count = N_ELEMENTS(death_actions);
471
472         menu_init(menu, MN_SKIN_SCROLL, &death_iter, &area);
473
474         while (TRUE)
475         {
476                 c = menu_select(&death_menu, &cursor, 0);
477
478                 if (c.key == ESCAPE || cursor == 6)
479                 {
480                         if (get_check("Do you want to quit? "))
481                                 break;
482                 }
483                 else if (c.type == EVT_SELECT && death_actions[cursor].action)
484                 {
485                         death_actions[cursor].action(death_actions[cursor].data, NULL);
486                 }
487         }
488 }
Note: See TracBrowser for help on using the browser.