home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume13 / dominion / part22 / menus.c < prev    next >
C/C++ Source or Header  |  1992-02-11  |  19KB  |  726 lines

  1.   /* menus.c -- various menus for dominion */
  2.  
  3. /*
  4.  * Copyright (C) 1990 Free Software Foundation, Inc.
  5.  * Written by the dominion project.
  6.  *
  7.  * This file is part of dominion.
  8.  *
  9.  * dominion is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU General Public License as published
  11.  * by the Free Software Foundation; either version 1, or (at your option)
  12.  * any later version.
  13.  *
  14.  * This software is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this software; see the file COPYING.  If not, write to
  21.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #ifdef SYSV
  27. # include <string.h>
  28. #else
  29. # include <strings.h>
  30. #endif /* SYSV */
  31.  
  32. #include "dominion.h"
  33. #include "misc.h"
  34. #include "army.h"
  35.  
  36. extern Sworld world;
  37. extern Suser user;
  38.   /* info about all spirits */
  39. extern struct spirit_type *spirit_types;
  40. extern char help_tag[];
  41.  
  42.   /* asks the user what the display should look like */
  43. display_menu()
  44. {
  45.   WINDOW *dispw;
  46.   char c;
  47.  
  48.   strcpy(help_tag, "Display options");
  49.   if (user.xmode) {
  50.     statline("[r,c,n,d,p,A,w,M,t,T,s,m,j,h,o,a,y,O,l,u,-,C,W]", "display_menu");
  51.   } else {
  52.     statline("choose an option (space to exit)", "display menu");
  53.     dispw = newwin(9, COLS-4, LINES-11, 2);
  54.     wmove(dispw, 1, 1);
  55.     waddstr(dispw, "Map Style:         [r]egular, [c]ompact");
  56.     wmove(dispw, 2, 1);
  57.     waddstr(dispw, "Display Options:   ");
  58.     waddstr(dispw, "[n]ation mark, [d]esignation, [p]opulation,");
  59.     wmove(dispw, 3, 1);
  60.     waddstr(dispw, "                   ");
  61.     waddstr(dispw, "[A]ltitude, [w] Climate, army [M]ovecost, [t]errain,");
  62.     wmove(dispw, 4, 1);
  63.     waddstr(dispw, "                   ");
  64.     waddstr(dispw, "[s]oil, [m]etal, [j]ewels, [T]errain move cost");
  65.     wmove(dispw, 5, 1);
  66.     waddstr(dispw, "Highlight Options: ");
  67.     waddstr(dispw, "[o]wnership, [a]rmies, [y]our armies, [O]ther armies,");
  68.     wmove(dispw, 6, 1);
  69.     waddstr(dispw, "                   ");
  70.     waddstr(dispw, "[l] move left, [h]ostile, [u]nemployment, [-]none");
  71.     wmove(dispw, 7, 1);
  72.     waddstr(dispw, "Other Things:      ");
  73.     waddstr(dispw, "[C]enter screen at cursor, [W]ater/underwater toggle");
  74.     box(dispw, '|', '-');
  75.     wrefresh(dispw);
  76.   }
  77.   switch (c = mygetch()) {
  78.   case ' ':
  79.     break;
  80.   case 'h':
  81.     user.highlight = H_HOSTILE;
  82.     break;
  83.   case 'M':
  84.     user.display = ARMY_MOVECOST;
  85.     break;
  86.   case 'r':
  87.     user.map_style = NORMAL_MAP; /* map style */
  88.     wclear(stdscr);
  89.     break;
  90.   case 'c':
  91.     user.map_style = COMPACT_MAP;
  92.     wclear(stdscr);
  93.     break;
  94.   case 'd':
  95.     user.display = DESIGNATION; /* display */
  96.     break;
  97.   case 'n':
  98.     user.display = NATION_MARK;
  99.     break;
  100.   case 's':
  101.     user.display = SOIL;
  102.     break;
  103.   case 'm':
  104.     user.display = METAL;
  105.     break;
  106.   case 'j':
  107.     user.display = JEWELS;
  108.     break;
  109.   case 'A':
  110.     user.display = ALTITUDE;
  111.     break;
  112.   case 'w':
  113.     user.display = CLIMATE;
  114.     break;
  115.   case 'p':
  116.     user.display = POPULATION;
  117.     break;
  118.   case 'T':
  119.     user.display = MOVECOST;
  120.     break;
  121.   case 't':
  122.     user.display = TERRAIN;
  123.     break;
  124.   case 'o':
  125.     user.highlight = H_OWNED;    /* highlighting */
  126.     break;
  127.   case 'a':
  128.     user.highlight = H_ARMIES;
  129.     break;
  130.   case 'y':
  131.     user.highlight = H_YOUR_ARMIES;
  132.     break;
  133.   case 'O':
  134.     user.highlight = H_OTHER_ARMIES;
  135.     break;
  136.   case 'l':
  137.     user.highlight = H_MOVE_LEFT;
  138.     break;
  139.   case 'u':
  140.     user.highlight = H_UNEMP;
  141.     break;
  142.   case '-':            /* no highlighting */
  143.     user.highlight = H_NONE;
  144.     break;
  145.   case 'C':            /* center screen around current cursor */
  146.     user.center = user.cursor;
  147. #ifdef hpux            /* HP curses is baaad */
  148.     redraw();
  149. #endif /* hpux */
  150.     break;
  151.   case 'W':            /* above/below water toggle */
  152.     user.underwater = !user.underwater;
  153.     break;
  154.   default:
  155.     bad_key();
  156.     break;
  157.   }
  158.   if (!user.xmode) {
  159.     delwin(dispw);
  160.   }
  161.   touchwin(stdscr);
  162.   user.just_moved = 1;
  163. }
  164.  
  165.   /* wizardry commands */
  166. wizardry_menu()
  167. {
  168.   WINDOW *wizw;
  169.   char c;
  170.   int done = 0;
  171.   char s[PATHLEN];
  172.   Snation *np = user.np;
  173.   Ssector *sp = &world.map[user.cursor.x][user.cursor.y];
  174.  
  175.   if (user.xmode) {
  176.     wizw = (WINDOW *) NULL;
  177.   } else {
  178.     wizw = newwin(6, COLS-4, LINES-8, 2);
  179.   }
  180.     /* now see if we can automatically select the first mage
  181.        on this sector.
  182.      */
  183.   if (first_sect_mage_id(user.np, sp) != -1) {
  184.     user.current_army = first_sect_mage_id(user.np, sp);
  185.     show_armies(sp);
  186.   }
  187.   while (!done) {
  188.     strcpy(help_tag, "Wizardry");
  189.     if (user.xmode) {
  190.       sprintf(s, "%d spell pts. [l,c,s,h,i]", np->spell_pts);
  191.       statline(s, "wizardry_menu");
  192.     } else {
  193.       statline("Choose a wizardry command (space to leave)","wizardry_menu");
  194.       mvwaddstr(wizw, 1, 1,
  195.     "  [l]ist spells and spirits, [c]ast a spell, [s]ummon a spirit");
  196.       mvwaddstr(wizw, 2, 1, "  list [h]anging spells, [i]nitiate a mage");
  197.       mvwprintw(wizw, 3, 1, "    You have %d spell points", np->spell_pts);
  198.       box(wizw, '|', '-');
  199.       wrefresh(wizw);
  200.     }
  201.     switch (c = getch()) {
  202.     case ' ':
  203.       done = 1;
  204.       break;
  205.     case 'l':
  206.       if (!user.xmode) {
  207.     wmove(wizw, 2, 1);
  208.     wprintw(wizw,
  209.         "  listing spells and spirits for nation %s (order of %s)",
  210.         user.np->name, user.np->mag_order);
  211.       }
  212.       list_spells(&user);
  213.       list_spirits(&user);
  214.       statline2_err("Type space to get back", "spells and spirits list");
  215.       touchwin(stdscr);
  216.       refresh();
  217.       fflush(stdin);
  218.       user.just_moved = 1;
  219.       break;
  220.     case 's':
  221.       if (!user.xmode) {
  222.     list_spirits(&user);
  223.       }
  224.       summon(&user, wizw);
  225.       break;
  226.     case 'c':
  227.       if (!user.xmode) {
  228.     list_spells(&user);
  229.       }
  230.       cast_spell(&user, wizw);
  231.       break;
  232.     case 'i':
  233.       initiate_mage(&user, wizw);
  234.       break;
  235.     case 'h':
  236.       show_hanging_spells(&user);
  237.       break;
  238.     case '?':
  239.       online_info();
  240.       break;
  241.     default:
  242.       break;
  243.     }
  244.     statline2("", "");
  245.     if (!user.xmode) {
  246.       wmove(wizw, 2, 1);
  247.       wclrtobot(wizw);
  248.     }
  249.   }
  250.   if (!user.xmode) {
  251.     touchwin(stdscr);
  252.     delwin(wizw);
  253.     user.just_moved = 1;
  254.   }
  255. }
  256.  
  257.   /* conjures a spirit */
  258. summon(up, w)
  259.      Suser *up;
  260.      WINDOW *w;
  261. {
  262.   char type[NAMELEN], name[NAMELEN];
  263.   int type_index;
  264.   Sspirit *spiritp = user.spirit_list;
  265.   Sarmy *ap, *get_army();
  266.   Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  267.  
  268.   strcpy(help_tag, "Spirit types");
  269.  
  270.   if ((ap = get_army(up->np, up->current_army)) == NULL  ||  !is_mage(ap) ) {
  271.     statline2_err("only mages can summon. hit space.", "summon");
  272.     return;
  273.   }
  274.   if (sp->owner != up->np->id) {
  275.     statline2_err("must summon in your own land", "summon");
  276.     return;
  277.   }
  278.   if (w) {
  279.     mvwprintw(w, 2, 1, "Which type of spirit do you wish to summon? ");
  280.   } else {
  281.     statline_prompt("Which type? ", "summon");
  282.   }
  283.   wget_name(w, type);
  284.   if ((type_index = spirit_type_index(type)) < 0) {
  285.     statline2_err("couldn't find a spirit of that type. hit space.", "summon");
  286.     return;
  287.   }
  288.     /* get the spirit pointer from the list of available spirits */
  289.   while (spiritp && (strcmp(type, spiritp->type) != 0)) {
  290.     spiritp = spiritp->next;
  291.   }
  292.   if (spiritp == NULL) {
  293.     statline2_err("That is not available to you. hit space.", "summon");
  294.     return;
  295.   }
  296.     /* now see if they can afford it */
  297.   if (spiritp->cost > up->np->spell_pts) {
  298.     statline2_err("you do not have enough spell points. hit space.", "summon");
  299.     return;
  300.   }
  301.   if (w) {
  302.     mvwprintw(w, 3, 1, "Give a name to your spirit (default %s: ", type);
  303.   } else {
  304.     statline("Give name: ", "summon");
  305.     move(LINES-1, strlen("Give name: "));
  306.   }
  307.   if (wget_name(w, name) <= 0) {
  308.     sprintf(name, "%s", type);
  309.   }
  310.   exec_summon(type_index, name);
  311.   statline2_err("spirit has been summoned, hit space to get back", "summon");
  312. }
  313.  
  314.   /* initiates a mage */
  315. initiate_mage(up, w)
  316.      Suser *up;
  317.      WINDOW *w;
  318. {
  319.   char c;
  320.   char name[NAMELEN], s[NAMELEN];
  321.   Ssector *sp;
  322.   char def_name [NAMELEN];
  323.  
  324.   strcpy(help_tag, "Mages");
  325.   sp = &world.map[user.cursor.x][user.cursor.y];
  326.   if ((sp->designation != D_CITY && sp->designation != D_UNIVERSITY
  327.       && sp->designation != D_TEMPLE && sp->designation != D_CAPITAL)
  328.       || (sp->owner != user.id)) {
  329.     statline2_err("must initiate in *your* city/univ/temple. hit space.",
  330.           "initiate_mage");
  331.     return;
  332.   }
  333.   name[0] = '\0';
  334.   if (w) {
  335.     mvwprintw(w, 3, 1,
  336.           "initiation costs %d jewels.  go ahead (y/n)? ",
  337.           INITIATION_JEWELS);
  338.     wrefresh(w);
  339.   } else {
  340.     sprintf(s, "costs %d jewels.  go ahead (y/n)? ", INITIATION_JEWELS);
  341.     statline(s, "initiate");
  342.     move(LINES-1, strlen(s));
  343.   }
  344.   c = getchar();
  345.   if (c == '?') {
  346.     online_info();
  347.   }
  348.   if (c != 'y' && c != 'y') {
  349.     return;
  350.   }
  351.   if (up->np->jewels < INITIATION_JEWELS) {
  352.     statline2_err("You do not have enough jewels. hit space.","initiate_mage");
  353.     return;
  354.   }
  355.   if (next_thon_jewels (up->np) - MAGE_JEWELS_MAINT < 0) {
  356.     statline2_err ("You would have negative jewels next thon.  hit space.",
  357.            "initiate_mage");
  358.     return;
  359.   }
  360.  
  361.   sprintf (def_name, "Mage");
  362.   sprintf (s, "Name (default \"%s\"): ", def_name);
  363.  
  364.   if (w) {
  365.     mvwprintw(w, 4, 1,"Give a name to your new mage (default \"%s\"): ",
  366.           def_name);
  367.   } else {
  368.     statline(s, "initiate");
  369.     move(LINES-1,strlen (s));
  370.   }
  371.   if ((wget_name(w, name)) == NULL) {
  372.     strcpy (name, def_name);
  373.   }
  374.     /* if we got this far, it means that the initiation is valid */
  375.   exec_initiate(name);
  376.   statline2_err("mage has been initiated, hit space to get back",
  377.         "initiate_mage");
  378. }
  379.  
  380.   /* list a user's spells */
  381. list_spells(up)
  382.      Suser *up;
  383. {
  384.   Sspell *spells = up->spell_list;
  385.   WINDOW *listw;
  386.   int i, n_spells = 0;
  387.  
  388.   while (spells != NULL) {
  389.     spells = spells->next;
  390.     ++n_spells;
  391.   }
  392.   listw = newwin(n_spells+3, NAMELEN, 2, 37);
  393.   box(listw, '|', '-');
  394.   wstandout(listw);
  395.   mvwaddstr(listw, 0, 2, "Spell");
  396.   wstandend(listw);
  397.   waddstr(listw, "(cost,time)");
  398.   spells = up->spell_list;
  399.   for (i = 0; i < n_spells; ++i) {
  400.     mvwprintw(listw, i+2, 1, "%s(%d,%d)",
  401.           spells->name, spells->cost, spells->duration);
  402.     spells = spells->next;
  403.   }
  404.   wrefresh(listw);
  405.   delwin(listw);
  406. }
  407.  
  408.   /* list a user's spirits */
  409. list_spirits(up)
  410.      Suser *up;
  411. {
  412.   Sspirit *spirits = up->spirit_list;
  413.   int n_spirits = 0, i;
  414.   WINDOW *listw;
  415.  
  416.   while (spirits != NULL) {
  417.     spirits = spirits->next;
  418.     ++n_spirits;
  419.   }
  420.   listw = newwin(n_spirits+3, NAMELEN, 2, 7);
  421.   box(listw, '|', '-');
  422.   wstandout(listw);
  423.   mvwaddstr(listw, 0, 4, "Spirit");
  424.   wstandend(listw);
  425.   waddstr(listw, "(cost)");
  426.   spirits = up->spirit_list;
  427.     /* run through the list and print them out */
  428.   for (i = 0; i < n_spirits; ++i) {
  429.     if (spirit_type_index(spirits->type) >= 0) {
  430.       mvwprintw(listw, i+2, 1, "%s(%d)", spirits->type, spirits->cost);
  431.     }
  432.     spirits = spirits->next;
  433.   }
  434.   wrefresh(listw);
  435.   delwin(listw);
  436. }
  437.  
  438. cast_spell(up, w)
  439.      Suser *up;
  440.      WINDOW *w;
  441. {
  442.   Sspell *slist = up->spell_list;
  443.   char name[NAMELEN], s[NAMELEN];
  444.   Sarmy *ap, *get_army();
  445.   int cost;
  446.  
  447.   if ((ap = get_army(up->np, up->current_army)) == NULL  ||  !is_mage(ap) ) {
  448.     statline2_err("only mages can cast spells. hit space.", "cast_spell");
  449.     return;
  450.   }
  451.   if (w) {
  452.     mvwprintw(w, 4, 1, "which spell do you want to cast? ");
  453.   } else {
  454.     statline_prompt("Which spell? ", "cast_spell");
  455.   }
  456.   wget_name(w, name);
  457.   while (slist != NULL) {
  458.     if (strcmp(slist->name, name) == 0) {
  459.       break;            /* found it */
  460.     }
  461.     slist = slist->next;
  462.   }
  463.   if (slist == NULL) {
  464.     statline2_err("no spell by that name. hit space.", "cast_spell");
  465.     return;
  466.   }
  467.   if (slist->cost > 0 && slist->cost > up->np->spell_pts) {
  468.     statline2_err("you do not have enough spell points. hit space.",
  469.           "cast_spell");
  470.     return;
  471.   }
  472.     /* if we got this far, it means that the spell is valid */
  473.   cost = exec_spell(slist, w);
  474.   show_armies(&world.map[up->cursor.x][up->cursor.y]);
  475.   if (cost > 0) {
  476.     statline2_err("spell has been cast, hit space to get back", "cast_spell");
  477.   }
  478. }
  479.  
  480.   /* this sets up the spirit as a new army */
  481. exec_summon(type_index, name)
  482.      int type_index;
  483.      char name[];
  484. {
  485.   Sarmy army, make_army();
  486.   Ssector *sp = &world.map[user.cursor.x][user.cursor.y];
  487.   char s[EXECLEN];
  488.  
  489.   army = make_army(spirit_types[type_index].type, name,
  490.            spirit_types[type_index].size, A_DEFEND,
  491.            user.np->id, sp->loc);
  492.   army.id = free_army_id(user.np);
  493.    /* spirits cost spell points to draft *and* maintain (set in make_army) */
  494.   army.next = NULL;
  495.   army.flags = spirit_types[type_index].flags;
  496.     /* now insert it into the list */
  497.   ++user.np->n_armies;
  498.   if (user.np->armies == NULL) { /* special case:  empty list */
  499.     user.np->armies = (Sarmy *) malloc(sizeof(Sarmy));
  500.     *(user.np->armies) = army;
  501.     user.np->armies->next = NULL;
  502.   } else {
  503.     insert_army_nation(user.np, &army, -1);
  504.   }
  505.   insert_army_sector(sp, &army);
  506.   user.np->spell_pts -= spirit_types[type_index].spell_pts_draft;
  507.   cspell_pts(user.np, -spirit_types[type_index].spell_pts_draft);
  508.     /* now prepare the exec string for making the army and costs */
  509.   sprintf(s, "AMAKE:%d:%d:%d:%d:%s:%s\n", army.id, army.n_soldiers,
  510.       army.pos.x, army.pos.y, army.type, army.name);
  511.   gen_exec(s);
  512.     /* now a last detail:  the "current_army" variable
  513.        must be set (like in draft_army())
  514.      */
  515.   if (user.current_army == -1) {
  516.     user.current_army = first_sect_army(sp);
  517.   }
  518.   show_armies(sp);
  519. }
  520.  
  521.   /* this sets up the mage as a new army */
  522. exec_initiate(name)
  523.      char name[];
  524. {
  525.   Sarmy army, make_army();
  526.   Ssector *sp = &world.map[user.cursor.x][user.cursor.y];
  527.   char s[EXECLEN];
  528.  
  529.   army = make_army("Mage", name, 1, A_DEFEND,
  530.            user.np->id, sp->loc);
  531.     /* now give the mage maintainance costs */
  532.   army.jewel_maint = 1000;
  533. /*  army.spell_pts_maint = 1; */
  534.   army.id = free_army_id(user.np);
  535.   army.flags |= AF_WIZARD;
  536.   army.next = NULL;
  537.     /* now insert it into the list */
  538.   ++user.np->n_armies;
  539.   if (user.np->armies == NULL) { /* special case:  empty list */
  540.     user.np->armies = (Sarmy *) malloc(sizeof(Sarmy));
  541.     *(user.np->armies) = army;
  542.     user.np->armies->next = NULL;
  543.   } else {
  544.     insert_army_nation(user.np, &army, -1);
  545.   }
  546.   insert_army_sector(sp, &army);
  547.   user.np->jewels -= INITIATION_JEWELS;
  548.   cjewels(user.np, -INITIATION_JEWELS);
  549.     /* now prepare the exec string for making the army and costs */
  550.   sprintf(s, "AMAKE:%d:%d:%d:%d:%s:%s\n", army.id, army.n_soldiers,
  551.       army.pos.x, army.pos.y, army.type, army.name);
  552.   gen_exec(s);
  553.   aflag_set(&army, AF_WIZARD);
  554. /*  sprintf(s, "%d:%d", army.id, AF_WIZARD); */
  555. /*  aflag_set(&army, AF_NOFIGHT); */
  556.     /* now a last detail:  the "current_army" var must be set
  557.        (like in draft_army())
  558.      */
  559.   if (user.current_army == -1) {
  560.     user.current_army = first_sect_army(sp);
  561.   }
  562.   show_armies(sp);
  563. }
  564.  
  565.   /* make a window to show user her/his hanging spells */
  566. show_hanging_spells(up)
  567.      Suser *up;
  568. {
  569.   WINDOW *sw;
  570.   int done = 0, i;
  571.   Sh_spell *h_list;        /* list of hanging spells for this user */
  572.  
  573.   strcpy(help_tag, "Spells");
  574.   statline("Hit space to get back", "show_hanging_spells");
  575.   sw = newwin(20, 30, 2, 2);
  576.   while (!done) {
  577.     mvwprintw(sw, 1, 1, "     Spell       thons");
  578.     wclrtobot(sw);
  579.     if (up->id == 0) { waddstr(sw, " (nat)"); }
  580.     mvwprintw(sw, 2, 1, "   --------       --- ");
  581.     if (up->id == 0) { waddstr(sw, "  --- "); }
  582.     for (i = 0, h_list = up->h_spells; h_list != NULL;
  583.      ++i,h_list = h_list->next) {
  584.       mvwprintw(sw, 3+i, 1, " %2d %-12.12s  %2d", i, h_list->name,
  585.         h_list->thons_left);
  586.       if (up->id == 0) { wprintw(sw, "    %3d", h_list->nat_id); }
  587.       wclrtoeol(sw);
  588.     }
  589.     mvwaddstr(sw, 18, 1, " [z]oom, [d]elete ");
  590.     wclrtoeol(sw);
  591.     box(sw, '|', '-');
  592.     wrefresh(sw);
  593.     switch(getch()) {
  594.     case 'z':
  595.       zoom_on_h_spell(up->h_spells, sw);
  596.       break;
  597.     case 'd':
  598.       zoom_del_h_spell(up->h_spells, sw);
  599.       break;
  600.  
  601.     case ' ':
  602.       done = 1;
  603.       break;
  604.     case '?':
  605.       online_info();
  606.       break;
  607.     default:
  608.       break;
  609.     }
  610.   }
  611.   delwin(sw);
  612.   touch_all_wins();
  613. }
  614.  
  615.   /* allows the user to focus on a specific spell */
  616. zoom_on_h_spell(h_list, sw)
  617.      Sh_spell *h_list;
  618.      WINDOW *sw;
  619. {
  620.   WINDOW *zoomw;
  621.   int n, i;
  622.   char s[EXECLEN];
  623.  
  624.     /* first ask the user which spell s/he wants to see */
  625.   mvwaddstr(sw, 18, 1, " On which spell? ");
  626.   wclrtoeol(sw);
  627.   box(sw, '|', '-');
  628.   wrefresh(sw);
  629.   if (wget_number(sw, &n) < 0 || n < 0) {
  630.     return -1;
  631.   }
  632.   for (i = 0; h_list && i < n; ++i) {
  633.     h_list = h_list->next;
  634.   }
  635.   if (h_list == NULL) {
  636.     return -1;
  637.   }
  638.     /* then zoom in on it */
  639.   zoomw = newwin(h_list->n_lines/2+3, 30, 4, 25);
  640.   mvwprintw(zoomw, 1, 3, " Spell <%s>  ", h_list->name);
  641.   for (i = 0; i < h_list->n_lines; i += 2) {
  642.       /* now insert the hiding of coordinates */
  643.     strcpy(s, h_list->lines[i]);
  644.     fix_sector_line(h_list->lines[i], s);
  645.     mvwprintw(zoomw, i/2+2, 1, " %s", s);
  646.   }
  647.   box(zoomw, '|', '-');
  648.   wrefresh(zoomw);
  649.   statline2_err("Hit space to return", "zoom_on_h_spell");
  650.   delwin(zoomw);
  651.   return 1;
  652. }
  653.  
  654.   /* fix the exec line if it has references to a sector by
  655.      absolute coordinates.  put the "censored" line into s.
  656.      this is quite a hack, what?
  657.    */
  658. fix_sector_line(line, s)
  659.      char line[], s[];
  660. {
  661.   int xabs, yabs, x_rel, y_rel, arg;
  662.   char *s2, s3[EXECLEN];    /* for temporary work */
  663.  
  664.     /* if there is no '_', then just return */
  665.   if ((s2 = strrchr(line, '_')) == NULL) {
  666.     strcpy(s, line);
  667.     return;
  668.   }
  669.     /* the convention is, if the exec line ends with "_SECTOR"
  670.        then the first 2 numbers are the x and y coordinates.
  671.      */
  672.   if (strncmp(s2+1, "SECTOR", strlen("SECTOR")) != 0) {
  673.     strcpy(s, line);
  674.     return;
  675.   }
  676.     /* for now make the gross assumption that
  677.        the only arguments are x, y and a third "arg"
  678.      */
  679.   s2 = line;
  680.   s2 = strchr(s2, ':')+1;
  681.   sscanf(s2, "%d", &xabs);
  682.   s2 = strchr(s2, ':')+1;
  683.   sscanf(s2, "%d", &yabs);
  684.   s2 = strchr(s2, ':')+1;
  685.   sscanf(s2, "%d", &arg);
  686.   if (user.id == 0) {
  687.     x_rel = xabs;
  688.     y_rel = yabs;
  689.   } else {
  690.     x_rel = xrel(xabs, yabs, user.np->capital);
  691.     y_rel = yrel(xabs, yabs, user.np->capital);
  692.   }
  693.   /*    sprintf(s3, "%d:%d:%d\n", xabs, yabs, arg); (debug) */
  694.   sprintf(s3, ":%d:%d:%d\n", x_rel, y_rel, arg);
  695.   strcpy(strchr(s, ':'), s3);
  696.   /*    statline(s, "final s, hit space"); */
  697. }
  698.  
  699. zoom_del_h_spell(h_list, sw)
  700.      Sh_spell *h_list;
  701.      WINDOW *sw;
  702. {
  703.   WINDOW *zoomw;
  704.   int n, i;
  705.   char s[EXECLEN];
  706.  
  707.     /* first ask the user which spell s/he wants to see */
  708.   mvwaddstr(sw, 18, 1, " Remove which spell? ");
  709.   wclrtoeol(sw);
  710.   box(sw, '|', '-');
  711.   wrefresh(sw);
  712.   if (wget_number(sw, &n) < 0 || n < 0) {
  713.     return -1;
  714.   }
  715.   for (i = 0; h_list && i < n; ++i) {
  716.     h_list = h_list->next;
  717.   }
  718.   if (h_list == NULL) {
  719.     return -1;
  720.   }
  721.  
  722.   delete_hanging_spell(h_list);
  723.   return 1;
  724. }
  725.  
  726.