home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / s / sd-27.zip / sdutil.c < prev   
C/C++ Source or Header  |  1992-11-29  |  99KB  |  2,666 lines

  1. /* SD -- square dance caller's helper.
  2.  
  3.     Copyright (C) 1990  William B. Ackerman.
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 1, or (at your option)
  8.     any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     This is for version 27. */
  20.  
  21. /* This defines the following functions:
  22.    clear_screen
  23.    writestuff
  24.    newline
  25.    doublespace_file
  26.    exit_program
  27.    fail
  28.    fail2
  29.    specialfail
  30.    string_copy
  31.    display_initial_history
  32.    write_history_line
  33.    warn
  34.    find_proper_call_list
  35.    assoc
  36.    find_calldef
  37.    clear_people
  38.    rotperson
  39.    rotcw
  40.    rotccw
  41.    clear_person
  42.    copy_person
  43.    copy_rot
  44.    swap_people
  45.    install_person
  46.    install_rot
  47.    process_final_concepts
  48.    fix_n_results
  49.    divided_setup_move
  50.    overlapped_setup_move
  51.  
  52. and the following external variables:
  53.    longjmp_buffer
  54.    longjmp_ptr
  55.    history
  56.    history_ptr
  57.    written_history_items
  58.    written_history_nopic
  59.    last_magic_diamond
  60.    error_message1
  61.    error_message2
  62.    collision_person1
  63.    collision_person2
  64.    enable_file_writing
  65.    selector_names
  66. */
  67.  
  68. #include <string.h>
  69. #include "sd.h"
  70.  
  71.  
  72.  
  73. /*  This is the line length beyond which we will take pity on
  74.    whatever device has to print the result, and break the text line.
  75.    It is presumably smaller than our internal text capacity. */
  76. # define MAX_PRINT_LENGTH 59
  77.  
  78. /* These variables are external. */
  79.  
  80. real_jmp_buf longjmp_buffer;
  81. real_jmp_buf *longjmp_ptr;
  82. configuration history[100];
  83. int history_ptr;
  84.  
  85. /* This tells how much of the history text written to the UI is "safe".  If this
  86.    is positive, the history items up to that number, inclusive, have valid
  87.    "text_line" fields, and have had their text written to the UI.  Furthermore,
  88.    the local variable "text_line_count" is >= any of those "text_line" fields,
  89.    and each "text_line" field shows the number of lines of text that were
  90.    written to the UI when that history item was written.  This variable is
  91.    -1 when none of the history is safe or the state of the text in the UI
  92.    is unknown. */
  93. int written_history_items;
  94. /* When written_history_items is positive, this tells how many of the initial lines
  95.    did not have pictures forced on (other than having been drawn as a natural consequence
  96.    of the "draw_pic" flag being on.  If this number ever becomes greater than
  97.    written_history_items, that's OK.  It just means that none of the lines had
  98.    forced pictures. */
  99. int written_history_nopic;
  100.  
  101. parse_block *last_magic_diamond;
  102. char error_message1[MAX_ERR_LENGTH];
  103. char error_message2[MAX_ERR_LENGTH];
  104. unsigned int collision_person1;
  105. unsigned int collision_person2;
  106. long_boolean enable_file_writing;
  107.  
  108. /* These variables are used by the text-packing stuff. */
  109.  
  110. static char *destcurr;
  111. static char lastchar;
  112. static char *lastblank;
  113. static char current_line[MAX_TEXT_LINE_LENGTH];
  114. static int text_line_count = 0;
  115.  
  116.  
  117.  
  118. static void open_text_line(void)
  119. {
  120.    destcurr = current_line;
  121.    lastchar = ' ';
  122.    lastblank = (char *) 0;
  123. }
  124.  
  125.  
  126. extern void clear_screen(void)
  127. {
  128.    written_history_items = -1;
  129.    text_line_count = 0;
  130.    uims_reduce_line_count(0);
  131.    open_text_line();
  132. }
  133.  
  134.  
  135. static void writechar(char src)
  136. {
  137.    char save_buffer[MAX_TEXT_LINE_LENGTH];
  138.    char *p;
  139.    char *q;
  140.  
  141.    *destcurr = (lastchar = src);
  142.    if (src == ' ' && destcurr != current_line) lastblank = destcurr;
  143.  
  144.    if (destcurr < ¤t_line[MAX_PRINT_LENGTH])
  145.       destcurr++;
  146.    else {
  147.       /* Line overflow.  Try to write everything up to the last
  148.          blank, then fill next line with everything since that blank. */
  149.       if (lastblank) {
  150.          p = lastblank+1;
  151.          q = save_buffer;
  152.          while (p <= destcurr) *q++ = *p++;
  153.          *q = '\0';
  154.          destcurr = lastblank;
  155.       }
  156.       else {
  157.          /* Must break a word. */
  158.          save_buffer[0] = *destcurr;
  159.          save_buffer[1] = '\0';
  160.       }
  161.  
  162.       newline();
  163.       writestuff("   ");
  164.       writestuff(save_buffer);
  165.    }
  166. }
  167.  
  168.  
  169. extern void newline(void)
  170. {
  171.    *destcurr = '\0';
  172.  
  173.    if (enable_file_writing)
  174.       write_file(current_line);
  175.  
  176.    text_line_count++;
  177.    uims_add_new_line(current_line);
  178.    open_text_line();
  179. }
  180.  
  181.  
  182.  
  183. extern void writestuff(char s[])
  184. {
  185.    char *f = s;
  186.    while (*f) writechar(*f++);
  187. }
  188.  
  189.  
  190.  
  191. static void writestuff_with_fraction(char s[], long_boolean do_number, int num)
  192. {
  193.    if (do_number) {
  194.       char *f = s;
  195.       while (*f) {
  196.          if (f[0] == 'N' && f[1] == '/' && f[2] == '4') {
  197.             if ((num & 0xFFFF) == 2)
  198.                writestuff("1/2");
  199.             else {
  200.                writechar('0' + (num & 0xFFFF));
  201.                writestuff("/4");
  202.             }
  203.             writestuff(&f[3]);
  204.             return;
  205.          }
  206.          else
  207.             writechar(*f++);
  208.       }
  209.    }
  210.    else {
  211.       writestuff(s);
  212.    }
  213. }
  214.  
  215.  
  216. extern void doublespace_file(void)
  217. {
  218.    write_file("");
  219. }
  220.  
  221.  
  222.  
  223. extern void exit_program(int code)
  224. {
  225.    uims_terminate();
  226.    final_exit(code);
  227. }
  228.  
  229.  
  230. extern void fail(char s[])
  231. {
  232.    (void) strncpy(error_message1, s, MAX_ERR_LENGTH);
  233.    error_message1[MAX_ERR_LENGTH-1] = '\0';
  234.    error_message2[0] = '\0';
  235.    longjmp(longjmp_ptr->the_buf, 1);
  236. }
  237.  
  238.  
  239. extern void fail2(char s1[], char s2[])
  240. {
  241.    (void) strncpy(error_message1, s1, MAX_ERR_LENGTH);
  242.    error_message1[MAX_ERR_LENGTH-1] = '\0';
  243.    (void) strncpy(error_message2, s2, MAX_ERR_LENGTH);
  244.    error_message2[MAX_ERR_LENGTH-1] = '\0';
  245.    longjmp(longjmp_ptr->the_buf, 2);
  246. }
  247.  
  248.  
  249. extern void specialfail(char s[])
  250. {
  251.    (void) strncpy(error_message1, s, MAX_ERR_LENGTH);
  252.    error_message1[MAX_ERR_LENGTH-1] = '\0';
  253.    error_message2[0] = '\0';
  254.    longjmp(longjmp_ptr->the_buf, 4);
  255. }
  256.  
  257.  
  258. extern void string_copy(char **dest, char src[])
  259. {
  260.    char *f = src;
  261.    char *t = *dest;
  262.  
  263.    while (*t++ = *f++);
  264.    *dest = t-1;
  265. }
  266.  
  267.  
  268. /* BEWARE!!  These two lists are keyed to the definition of "selector_kind" in sd.h,
  269.    and to the necessary stuff in SDUI. */
  270. /* This one is external, so that the user interface can use it for popup text. */
  271. char *selector_names[] = {
  272.    "???",
  273.    "boys",
  274.    "girls",
  275.    "heads",
  276.    "sides",
  277.    "head corners",
  278.    "side corners",
  279.    "head boys",
  280.    "head girls",
  281.    "side boys",
  282.    "side girls",
  283.    "centers",
  284.    "ends",
  285.    "leads",
  286.    "trailers",
  287.    "beaux",
  288.    "belles",
  289.    "center 2",
  290.    "center 6",
  291.    "outer 2",
  292.    "outer 6",
  293.    "near line",
  294.    "far line",
  295.    "near column",
  296.    "far column",
  297.    "near box",
  298.    "far box",
  299.    "everyone",
  300.    "no one",
  301.    NULL};         /* The X11 interface uses this when making the popup text. */
  302.  
  303. static char *selector_singular[] = {
  304.    "???",
  305.    "boy",
  306.    "girl",
  307.    "head",
  308.    "side",
  309.    "head corner",
  310.    "side corner",
  311.    "head boy",
  312.    "head girl",
  313.    "side boy",
  314.    "side girl",
  315.    "center",
  316.    "end",
  317.    "lead",
  318.    "trailer",
  319.    "beau",
  320.    "belle",
  321.    "center 2",
  322.    "center 6",
  323.    "outer 2",
  324.    "outer 6",
  325.    "near line",
  326.    "far line",
  327.    "near column",
  328.    "far column",
  329.    "near box",
  330.    "far box",
  331.    "everyone",
  332.    "no one"};
  333.  
  334. /* BEWARE!!  These strings are keyed to the definitions of "warn__<whatever>" in sd.h . */
  335. static char *warning_strings[] = {
  336.    /*  warn__do_your_part        */   "Do your part.",
  337.    /*  warn__tbonephantom        */   "This is a T-bone phantom setup call.  Everyone will do their own part.",
  338.    /*  warn__ends_work_to_spots  */   "Ends work to same spots.",
  339.    /*  warn__awkward_centers     */   "Awkward for centers.",
  340.    /*  warn__bad_concept_level   */   "This concept is not allowed at this level.",
  341.    /*  warn__not_funny           */   "That wasn't funny.",
  342.    /*  warn__hard_funny          */   "Very difficult funny concept.",
  343.    /*  warn__unusual             */   "This is an unusual setup for this call.",
  344.    /*  warn__rear_back           */   "Rear back from the handhold.",
  345.    /*  warn__awful_rear_back     */   "Rear back from the handhold -- this is very unusual.",
  346.    /*  warn__excess_split        */   "Split concept seems to be superfluous here.",
  347.    /*  warn__lineconc_perp       */   "Ends should opt for setup perpendicular to their original line.",
  348.    /*  warn__dmdconc_perp        */   "Ends should opt for setup perpendicular to their original diamond points.",
  349.    /*  warn__lineconc_par        */   "Ends should opt for setup parallel to their original line -- concentric rule does not apply.",
  350.    /*  warn__dmdconc_par         */   "Ends should opt for setup parallel to their original diamond points -- concentric rule does not apply.",
  351.    /*  warn__xclineconc_perp     */   "New ends should opt for setup perpendicular to their original (center) line.",
  352.    /*  warn__xcdmdconc_perp      */   "New ends should opt for setup perpendicular to their original (center) diamond points.",
  353.    /*  warn__ctrstand_endscpls   */   "Centers work in tandem, ends as couples.",
  354.    /*  warn__ctrscpls_endstand   */   "Centers work as couples, ends in tandem.",
  355.    /*  warn__each2x2             */   "Each 2x2.",
  356.    /*  warn__each1x4             */   "Each 1x4.",
  357.    /*  warn__each1x2             */   "Each 1x2.",
  358.    /*  warn__take_right_hands    */   "Take right hands.",
  359.    /*  warn__ctrs_are_dmd        */   "The centers are the diamond.",
  360.    /*  warn__full_pgram          */   "Completely offset parallelogram.",
  361.    /*  warn__offset_gone         */   "The offset goes away.",
  362.    /*  warn__overlap_gone        */   "The overlap goes away.",
  363.    /*  warn__to_o_spots          */   "Go back to 'O' spots.",
  364.    /*  warn__to_x_spots          */   "Go back to butterfly spots.",
  365.    /*  warn__some_rear_back      */   "Some people rear back.",
  366.    /*  warn__not_tbone_person    */   "Work with the person to whom you are not T-boned.",
  367.    /*  warn__check_c1_phan       */   "Check a 'C1 phantom' setup.",
  368.    /*  warn__check_dmd_qtag      */   "Fudge to a diamond/quarter-tag setup.",
  369.    /*  warn__check_2x4           */   "Check a 2x4 setup.",
  370.    /*  warn__check_pgram         */   "Opt for a parallelogram."};
  371.  
  372. static char *ordinals[] = {"1st", "2nd", "3rd", "4th", "5th"};
  373.  
  374. /* This variable is shared by "print_recurse", which is subordinate
  375.    to "write_history_line". */
  376.  
  377. static parse_block *static_cptr;
  378.  
  379. /* Bits that go into argument to print_recurse. */
  380. #define PRINT_RECURSE_STAR 01
  381. #define PRINT_RECURSE_TAGREACT 02
  382. #define PRINT_RECURSE_TAGENDING 04
  383.  
  384. static void print_recurse(int print_recurse_arg)
  385. {
  386.    long_boolean use_left_name = FALSE;
  387.    long_boolean use_cross_name = FALSE;
  388.    long_boolean comma_after_next_concept = FALSE;
  389.  
  390.    while (static_cptr) {
  391.       int i;
  392.       concept_kind k;
  393.       concept_descriptor *item;
  394.       int next_recurse_arg;
  395.       parse_block *saved_cptr;
  396.  
  397.       item = static_cptr->concept;
  398.       k = item->kind;
  399.  
  400.       if (k == concept_comment) {
  401.          comment_block *fubb;
  402.  
  403.          fubb = (comment_block *) static_cptr->call;
  404.          writestuff("{ ");
  405.          writestuff(fubb->txt);
  406.          writestuff(" } ");
  407.          static_cptr = static_cptr->next;
  408.       }
  409.       else if (k > marker_end_of_list) {
  410.          /* This is a concept. */
  411.  
  412.          int index = static_cptr->number;
  413.          long_boolean request_final_space = FALSE;
  414.          long_boolean you_owe_me_a_number = FALSE;
  415.          long_boolean request_comma_after_next_concept = FALSE;
  416.          concept_kind kk = k;
  417.          parse_block *cc = static_cptr;
  418.  
  419.          /* We turn off the funny name elision if concepts are present,
  420.             except for "cross" and "left", since we want "[cross flip] your neighbor"
  421.             and "[LEFT tag the star] your neighbor" to work. */
  422.  
  423.          for (;;) {
  424.             if (kk <= marker_end_of_list) {
  425.                break;
  426.             }
  427.             else if (kk != concept_left && kk != concept_cross) {
  428.                print_recurse_arg &= ~(PRINT_RECURSE_TAGREACT | PRINT_RECURSE_TAGENDING);
  429.                break;
  430.             }
  431.             cc = cc->next;
  432.             if (!cc) break;
  433.             kk = cc->concept->kind;
  434.          }
  435.  
  436.          if (concept_table[k].concept_prop & CONCPROP__USE_SELECTOR) {
  437.             selector_kind selector = static_cptr->selector;
  438.  
  439.             if (k == concept_some_vs_others) {
  440.                writestuff("OWN the ");
  441.                writestuff(selector_names[selector]);
  442.                writestuff(", ");
  443.             }
  444.             else if (k == concept_selbasedtrngl) {
  445.                writestuff(selector_singular[selector]);
  446.             }
  447.             else {
  448.                writestuff(selector_names[selector]);
  449.                writestuff(" ");
  450.             }
  451.          }
  452.  
  453.          /* These concepts are missing the word "are" in the menu, because otherwise the menu would
  454.             be excessively wide, so we put the word back in. */
  455.          if (k == concept_some_are_frac_tandem || k == concept_some_are_tandem)
  456.             writestuff("ARE ");
  457.  
  458.          if ((concept_table[k].concept_prop & (CONCPROP__USE_NUMBER | CONCPROP__USE_TWO_NUMBERS)) &&
  459.                      k != concept_nth_part && k != concept_replace_nth_part) {
  460.             if (k == concept_frac_stable || k == concept_frac_tandem || k == concept_some_are_frac_tandem ||
  461.                      k == concept_phantom_frac_tandem || k == concept_so_and_so_frac_stable || k == concept_gruesome_frac_tandem) {
  462.                you_owe_me_a_number = TRUE;
  463.             }
  464.             else {
  465.                char nn[3];
  466.                nn[0] = '0' + (index & 0xFFFF);
  467.                nn[1] = '\0';
  468.                writestuff(nn);
  469.                if (concept_table[k].concept_prop & CONCPROP__USE_TWO_NUMBERS) {
  470.                   nn[0] = '/';
  471.                   nn[1] = '0' + (index >> 16);
  472.                   nn[2] = '\0';
  473.                   writestuff(nn);
  474.                }
  475.                writestuff(" ");
  476.             }
  477.          }
  478.  
  479.          saved_cptr = static_cptr;
  480.          static_cptr = static_cptr->next;    /* Now it points to the thing after this concept. */
  481.  
  482.          if (concept_table[k].concept_prop & CONCPROP__SECOND_CALL) {
  483.             parse_block *subsidiary_ptr = saved_cptr->subsidiary_root;
  484.  
  485.             if (k == concept_centers_and_ends) {
  486.                if ((i = item->value.arg1) == 2)
  487.                   writestuff("CENTER 6 ");
  488.                else if (i)
  489.                   writestuff("CENTER 2 ");
  490.                else
  491.                   writestuff("CENTERS ");
  492.             }
  493.             else if (k == concept_some_vs_others)
  494.                ;
  495.             else if (k == concept_sequential) {
  496.                writestuff("(");
  497.             }
  498.             else if (k == concept_callrigger) {
  499.                writestuff("ENDS BEGIN A [");
  500.             }
  501.             else if (k == concept_replace_nth_part) {
  502.                writestuff("DELAY: ");
  503.                if (!static_cptr || !subsidiary_ptr) {
  504.                   if (saved_cptr->concept->value.arg1)
  505.                      writestuff("(interrupting after the ");
  506.                   else
  507.                      writestuff("(replacing the ");
  508.                   writestuff(ordinals[index-1]);
  509.                   writestuff(" part) ");
  510.                }
  511.             }
  512.             else {
  513.                writestuff(item->name);
  514.                writestuff(" ");
  515.             }
  516.  
  517.             print_recurse(0);
  518.  
  519.             if (k == concept_callrigger) {
  520.                writestuff("]-RIGGER");             /* We want to print this even if input is incomplete. */
  521.                if (!subsidiary_ptr) break;         /* Can happen if echoing incomplete input. */
  522.                request_final_space = TRUE;
  523.             }
  524.             else {
  525.                if (!subsidiary_ptr) break;         /* Can happen if echoing incomplete input. */
  526.  
  527.                request_final_space = TRUE;
  528.  
  529.                if (k == concept_centers_and_ends)
  530.                   writestuff(" WHILE THE ENDS");
  531.                else if (k == concept_on_your_own || k == concept_interlace)
  532.                   writestuff(" AND");
  533.                else if (k == concept_replace_nth_part) {
  534.                   if (saved_cptr->concept->value.arg1)
  535.                      writestuff(" BUT INTERRUPT AFTER THE ");
  536.                   else
  537.                      writestuff(" BUT REPLACE THE ");
  538.                   writestuff(ordinals[index-1]);
  539.                   writestuff(" PART WITH A [");
  540.                   request_final_space = FALSE;
  541.                }
  542.                else if (k == concept_sequential)
  543.                   writestuff(" ;");
  544.                else
  545.                   writestuff(" BY");
  546.             }
  547.  
  548.             static_cptr = subsidiary_ptr;
  549.          }
  550.          else if (k == concept_so_and_so_only) {
  551.             writestuff("ONLY");
  552.             request_final_space = TRUE;
  553.          }
  554.          else if (k == concept_selbasedtrngl) {
  555.             writestuff(&item->name[9]);      /* Strip off the "so-and-so". */
  556.             request_final_space = TRUE;
  557.          }
  558.          else if (k == concept_standard) {
  559.             writestuff("ARE STANDARD IN");
  560.             request_final_space = TRUE;
  561.          }
  562.          else if (k == concept_some_are_frac_tandem || k == concept_so_and_so_frac_stable ||
  563.                   k == concept_some_are_tandem || k == concept_so_and_so_stable || k == concept_so_and_so_begin) {
  564.             writestuff_with_fraction(&item->name[10], you_owe_me_a_number, index);      /* Strip off the "so-and-so ". */
  565.             writestuff(",");
  566.             request_final_space = TRUE;
  567.          }
  568.          else if (k == concept_frac_stable) {
  569.             writestuff_with_fraction(item->name, you_owe_me_a_number, index);
  570.             request_final_space = TRUE;
  571.          }
  572.          else if (k == concept_double_offset) {
  573.             int scarg1 = saved_cptr->concept->value.arg1;
  574.             if (scarg1 == 0)
  575.                writestuff("ARE CENTERS OF A DOUBLE-OFFSET 1/4 TAG");
  576.             else if (scarg1 == 1)
  577.                writestuff("ARE CENTERS OF A DOUBLE-OFFSET 3/4 TAG");
  578.             else if (scarg1 == 3)
  579.                writestuff("ARE CENTERS OF DOUBLE-OFFSET DIAMONDS");
  580.             else
  581.                writestuff("ARE CENTERS OF A DOUBLE-OFFSET QUARTER-SOMETHING");
  582.             request_final_space = TRUE;
  583.          }
  584.          else if (static_cptr && (k == concept_left || k == concept_cross || k == concept_single)) {
  585.  
  586.             /* These concepts want to take special action if there are no following concepts and
  587.                certain escape characters are found in the name of the following call. */
  588.  
  589.             final_set finaljunk;
  590.             callspec_block *target_call;
  591.             parse_block *tptr;
  592.             
  593.             /* Skip all final concepts, then demand that what remains is a marker (as opposed to a serious
  594.                 concept), and that a real call has been entered, and that its name starts with "@g". */
  595.             tptr = process_final_concepts(static_cptr, FALSE, &finaljunk);
  596.  
  597.             if (tptr) {
  598.                target_call = tptr->call;
  599.    
  600.                if ((tptr->concept->kind <= marker_end_of_list) && target_call && (target_call->name[0] == '@')) {
  601.                   if (k == concept_left) {
  602.                      /* See if this is a call whose name naturally changes when the "left" concept is used. */
  603.                      if (target_call->name[1] == 'g') {
  604.                         use_left_name = TRUE;
  605.                      }
  606.                      else {
  607.                         writestuff(item->name);
  608.                         request_final_space = TRUE;
  609.                      }
  610.                   }
  611.                   else if (k == concept_cross) {
  612.                      /* See if this is a call that wants the "cross" modifier to be moved inside its name. */
  613.                      if (target_call->name[1] == 'i') {
  614.                         use_cross_name = TRUE;
  615.                      }
  616.                      else {
  617.                         writestuff(item->name);
  618.                         request_final_space = TRUE;
  619.                      }
  620.                   }
  621.                   else {
  622.                      /* See if this is a call that wants the "single" concept to be given as "single file" instead. */
  623.                      if (target_call->name[1] == 'h') {
  624.                         writestuff("SINGLE FILE");
  625.                         request_final_space = TRUE;
  626.                      }
  627.                      else {
  628.                         writestuff(item->name);
  629.                         request_final_space = TRUE;
  630.                      }
  631.                   }
  632.                }
  633.                else {
  634.                   writestuff(item->name);
  635.                   request_final_space = TRUE;
  636.                }
  637.             }
  638.             else {
  639.                writestuff(item->name);
  640.                request_final_space = TRUE;
  641.             }
  642.          }
  643.          else if (k == concept_fractional)
  644.             /* Already printed the fraction; that's all we want. */
  645.             ;
  646.          else if (k == concept_nth_part) {
  647.             writestuff("DO THE ");
  648.             writestuff(ordinals[index-1]);
  649.             writestuff(" PART");
  650.             request_comma_after_next_concept = TRUE;
  651.             request_final_space = TRUE;
  652.          }
  653.          else if (k == concept_replace_nth_part) {
  654.             writestuff("DELAY -- REPLACE THE ");
  655.             writestuff(ordinals[index-1]);
  656.             writestuff(" PART");
  657.             request_comma_after_next_concept = TRUE;
  658.             request_final_space = TRUE;
  659.          }
  660.          else if ((k == concept_meta) && saved_cptr->concept->value.arg1 == 3) {
  661.             writestuff("START");
  662.             request_comma_after_next_concept = TRUE;
  663.             request_final_space = TRUE;
  664.          }
  665.          else {
  666.             writestuff_with_fraction(item->name, you_owe_me_a_number, index);      /* Strip off the "so-and-so are ". */
  667.             request_final_space = TRUE;
  668.          }
  669.  
  670.          if (comma_after_next_concept)
  671.             writestuff(", ");
  672.          else if (request_final_space)
  673.             writestuff(" ");
  674.  
  675.          comma_after_next_concept = request_comma_after_next_concept;
  676.       }
  677.       else {
  678.          /* This is a "marker", so it has a call, perhaps with a selector and/or number.
  679.             The call may be null if we are printing a partially entered line.  Beware. */
  680.  
  681.          parse_block *save_cptr;
  682.          parse_block *subsidiary_ptr;
  683.          parse_block *search;
  684.          selector_kind i16junk;
  685.          int i17junk;
  686.          callspec_block *localcall;
  687.          long_boolean pending_subst, subst_in_use;
  688.  
  689.          i16junk = static_cptr->selector;
  690.          i17junk = static_cptr->number;
  691.          localcall = static_cptr->call;
  692.  
  693.          save_cptr = static_cptr;
  694.          subst_in_use = FALSE;
  695.          next_recurse_arg = 0;
  696.  
  697.          if (k == concept_another_call_next_mod) {
  698.             search = save_cptr->next;
  699.             while (search) {
  700.                subsidiary_ptr = search->subsidiary_root;
  701.                if (subsidiary_ptr && ( (search->concept->kind == concept_another_call_next_mod) ||
  702.                                        (search->concept->kind == concept_another_call_next_modreact) ||
  703.                                        (search->concept->kind == concept_another_call_next_modtag))) {
  704.                   if (search->concept->kind == concept_another_call_next_modreact) next_recurse_arg = PRINT_RECURSE_TAGREACT;
  705.                   else if (search->concept->kind == concept_another_call_next_modtag) next_recurse_arg = PRINT_RECURSE_TAGENDING;
  706.                   subst_in_use = TRUE;
  707.                   static_cptr = subsidiary_ptr;
  708.                   break;
  709.                }
  710.                search = search->next;
  711.             }
  712.          }
  713.    
  714.          pending_subst = subst_in_use;
  715.  
  716.          /* Now "subst_in_use" is on if there is a replacement call that goes in naturally.  During the
  717.             scan of the name, we will try to fit that replacement into the name of the call as directed
  718.             by atsign-escapes.  If we succeed at this, we will clear "pending_subst".
  719.             In addition to all of this, there may be any number of forcible replacements. */
  720.  
  721.          if (localcall) {      /* Call = NIL means we are echoing input and user hasn't entered call yet. */
  722.             char *np;
  723.  
  724.             if (enable_file_writing) localcall->age = global_age;
  725.             np = localcall->name;
  726.  
  727.             /* Skip any "@g", "@h", or "@i" marker (we already acted on it.) */
  728.             if ((*np == '@') && ((np[1] == 'g') || (np[1] == 'h') || (np[1] == 'i'))) np += 2;
  729.  
  730.             while (*np) {
  731.                if (*np == '@') {
  732.                   if (np[1] == '6' || np[1] == 'k') {
  733.                      if (lastchar != ' ' && lastchar != '[') writestuff(" ");
  734.                      if (np[1] == '6')
  735.                         writestuff(selector_names[i16junk]);
  736.                      else
  737.                         writestuff(selector_singular[i16junk]);
  738.                      if (np[2] && np[2] != ' ' && np[2] != ']')
  739.                         writestuff(" ");
  740.                      np += 2;       /* skip the digit */
  741.                   }
  742.                   else if (np[1] == '9' || np[1] == 'a' || np[1] == 'b') {
  743.                      char nn[2];
  744.  
  745.                      if (lastchar != ' ' && lastchar != '[') writestuff(" ");
  746.                      nn[0] = '0' + i17junk;
  747.                      nn[1] = '\0';
  748.                      if (np[1] == '9')
  749.                         writestuff(nn);
  750.                      else if (i17junk == 2)
  751.                         writestuff("1/2");
  752.                      else if ((i17junk == 4) && (np[1] == 'a'))
  753.                         writestuff("full");
  754.                      else {
  755.                         writestuff(nn);
  756.                         writestuff("/4");
  757.                      }
  758.  
  759.                      np += 2;       /* skip the digit */
  760.                   }
  761.                   else if (np[1] == 'e') {
  762.                      if (use_left_name) {
  763.                         np += 2;
  764.                         while (*np != '@') np++;
  765.                         if (lastchar == ']') writestuff(" ");
  766.                         writestuff("left");
  767.                      }
  768.                      np += 2;
  769.                   }
  770.                   else if (np[1] == 'j') {
  771.                      if (!use_cross_name) {
  772.                         np += 2;
  773.                         while (*np != '@') np++;
  774.                      }
  775.                      np += 2;
  776.                   }
  777.                   else if (np[1] == 'l')
  778.                      np += 2;
  779.                   else if (np[1] == 'c') {
  780.                      if (print_recurse_arg & (PRINT_RECURSE_TAGREACT | PRINT_RECURSE_TAGENDING)) {
  781.                         np += 2;
  782.                         while (*np != '@') np++;
  783.                      }
  784.                      else {
  785.                         if ((lastchar == ' ' || lastchar == '[') && (np[2] == ' ')) np++;
  786.                      }
  787.                      np += 2;
  788.                   }
  789.                   else {
  790.                      char savec = np[1];
  791.       
  792.                      if (subst_in_use) {
  793.                         if (np[1] == '2' || np[1] == '4') {
  794.                            np += 2;
  795.                            while (*np != '@') np++;
  796.                         }
  797.                      }
  798.                      else {
  799.                         if (np[1] == '7') {
  800.                            np += 2;
  801.                            while (*np != '@') np++;
  802.                         }
  803.                      }
  804.       
  805.                      if (pending_subst && savec != '4' && savec != '7') {
  806.                         if (lastchar != ' ' && lastchar != '[') writestuff(" ");
  807.                         writestuff("[");
  808.                         print_recurse(next_recurse_arg | PRINT_RECURSE_STAR);
  809.                         writestuff("]");
  810.       
  811.                         pending_subst = FALSE;
  812.                      }
  813.       
  814.                      np += 2;        /* skip the digit */
  815.                   }
  816.                }
  817.                else {
  818.                   char c = *np++;
  819.  
  820.                   if (lastchar == ']' && c != ' ' && c != ']')
  821.                      writestuff(" ");
  822.  
  823.                   if ((lastchar != ' ' && lastchar != '[') || c != ' ') writechar(c);
  824.                }
  825.             }
  826.  
  827.             if (lastchar == ']' && *np && *np != ' ' && *np != ']')
  828.                writestuff(" ");
  829.          }
  830.          else if (print_recurse_arg & PRINT_RECURSE_STAR) {
  831.             writestuff("*");
  832.          }
  833.  
  834.          /* Now if "pending_subst" is still on, we have to do by hand what should have been
  835.             a natural replacement.  In any case, we have to find forcible replacements and
  836.             report them. */
  837.    
  838.          if (k == concept_another_call_next_mod) {
  839.             int first_replace = 0;
  840.  
  841.             search = save_cptr->next;
  842.             while (search) {
  843.                subsidiary_ptr = search->subsidiary_root;
  844.                if (subsidiary_ptr) {
  845.                   static_cptr = subsidiary_ptr;
  846.    
  847.                   if (  (search->concept->kind == concept_another_call_next_mod) ||
  848.                         (search->concept->kind == concept_another_call_next_modreact) ||
  849.                         (search->concept->kind == concept_another_call_next_modtag)) {
  850.                      /* This is a natural replacement.  It may already have been taken care of. */
  851.                      if (pending_subst) {
  852.                         writestuff(" [modification: ");
  853.                         print_recurse(PRINT_RECURSE_STAR);
  854.                         writestuff("]");
  855.                      }
  856.                   }
  857.                   else {
  858.                      /* This is a forced replacement.  Need to check for case of replacing
  859.                         one star turn with another. */
  860.                      localcall = search->call;
  861.  
  862.                      if ((!(first_replace++)) && static_cptr &&
  863.                            (localcall->callflags & cflag__is_star_call) &&
  864.                                  ((static_cptr->concept->kind == marker_end_of_list) ||
  865.                                  (static_cptr->concept->kind == concept_another_call_next_mod)) &&
  866.                            (static_cptr->call) &&
  867.                            (static_cptr->call->callflags & cflag__is_star_call)) {
  868.                         writestuff(" BUT [");
  869.                      }
  870.                      else {
  871.                         if (first_replace == 1)
  872.                            writestuff(" BUT REPLACE ");
  873.                         else
  874.                            writestuff(" AND REPLACE ");
  875.                         writestuff(localcall->name);
  876.                         writestuff(" WITH [");
  877.                      }
  878.  
  879.                      print_recurse(PRINT_RECURSE_STAR);
  880.                      writestuff("]");
  881.                   }
  882.                }
  883.                search = search->next;
  884.             }
  885.          }
  886.  
  887.          break;
  888.       }
  889.  
  890.       if (k == concept_sequential) {
  891.          print_recurse(PRINT_RECURSE_STAR);
  892.          writestuff(")");
  893.          return;
  894.       }
  895.       else if (k == concept_replace_nth_part) {
  896.          print_recurse(PRINT_RECURSE_STAR);
  897.          writestuff("]");
  898.          return;
  899.       }
  900.    }
  901. }
  902.  
  903.  
  904. /* These static variables are used by printperson. */
  905.  
  906. static char peoplenames[] = "1234";
  907. static char directions[] = "B?B>B?B<B?B?B?B?B^B?BVB?B?B?B?B?G?G>G?G<G?G?G?G?G^G?GVG?G?G?G?G?";
  908. static char personbuffer[] = " ZZZ";
  909.  
  910. static void printperson(int x)
  911. {
  912.    int i;
  913.  
  914.    if ((x & 01000) == 0) {
  915.       writestuff("    ");
  916.    }
  917.    else {
  918.       i = 2 * (x & 017);
  919.       if ((x & 0100) != 0) i = i+32;
  920.       personbuffer[1] = peoplenames[(x >> 7) & 3];
  921.       personbuffer[2] = directions[i];
  922.       personbuffer[3] = directions[i+1];
  923.       writestuff(personbuffer);
  924.    }
  925. }
  926.  
  927. /* These static variables are used by printsetup/print_4_person_setup/do_write/do_write4/do_write4_small. */
  928.  
  929. static int offs, roti, ri, modulus, personstart;
  930. static setup *printarg;
  931.  
  932. static void do_write4_small(char s[])
  933. {
  934.    char c;
  935.  
  936.    offs = (((roti >> 1) & 1) * (modulus / 2)) - modulus;
  937.    for (;;) {
  938.       if (!(c=(*s++))) return;
  939.       else if (c == '@') newline();
  940.       else if (c == ' ') writestuff(" ");
  941.       else if (c >= 'a' && c <= 'l')
  942.          printperson(rotperson(printarg->people[personstart + ((c-'a'-offs) % modulus)].id1, ri));
  943.       else writestuff("?");
  944.    }
  945. }
  946.  
  947.  
  948. static void do_write(char s[])
  949. {
  950.    char c;
  951.  
  952.    for (;;) {
  953.       if (!(c=(*s++))) return;
  954.       else if (c == '@') newline();
  955.       else if (c == ' ') writestuff(" ");
  956.       else if (c >= 'a' && c <= 'x')
  957.          printperson(rotperson(printarg->people[(c-'a'-offs) % modulus].id1, roti));
  958.       else writestuff("?");
  959.    }
  960. }
  961.  
  962.  
  963. static void print_4_person_setup(int ps, small_setup *s, int elong)
  964. {
  965.    roti = (s->srotation & 3);
  966.    ri = roti * 011;
  967.    personstart = ps;
  968.    
  969.    switch (s->skind) {
  970.       case s_1x2:
  971.          modulus = 2;
  972.          newline();
  973.          if (roti & 1)
  974.             do_write4_small("a@b@");
  975.          else
  976.             do_write4_small("a  b@");
  977.          break;
  978.       case s2x2:
  979.          modulus = 4;
  980.          newline();
  981.          if (roti & 1) {
  982.             if (elong < 0)
  983.                do_write4_small("da@cb@");
  984.             else if ((roti+elong) & 1)
  985.                do_write4_small("da@@@cb@");
  986.             else
  987.                do_write4_small("d    a@c    b@");
  988.          }
  989.          else {
  990.             if (elong < 0)
  991.                do_write4_small("ab@dc@");
  992.             else if ((roti+elong) & 1)
  993.                do_write4_small("ab@@@dc@");
  994.             else
  995.                do_write4_small("a    b@d    c@");
  996.          }
  997.          break;
  998.       case s_star:
  999.          modulus = 4;
  1000.          newline();
  1001.          if (roti & 1)
  1002.             do_write4_small("   a@d  b@   c@");
  1003.          else
  1004.             do_write4_small("   b@a  c@   d@");
  1005.          break;
  1006.       case s1x4:
  1007.          modulus = 4;
  1008.          newline();
  1009.          if (roti & 1)
  1010.             do_write4_small("a@b@d@c@");
  1011.          else
  1012.             do_write4_small("a  b  d  c@");
  1013.          break;
  1014.       case sdmd:
  1015.          modulus = 4;
  1016.          newline();
  1017.          if (roti & 1)
  1018.             do_write4_small("   a@@d  b@@   c@");
  1019.          else
  1020.             do_write4_small("     b@a      c@     d@");
  1021.          break;
  1022.       case s_2x3:
  1023.          modulus = 6;
  1024.          newline();
  1025.          if (roti & 1)
  1026.             do_write4_small("f  a@e  b@d  c@");
  1027.          else
  1028.             do_write4_small("a  b  c@f  e  d@");
  1029.          break;
  1030.       case s_short6:
  1031.          modulus = 6;
  1032.          newline();
  1033.          if (roti & 1)
  1034.             do_write4_small("   fa@e      b@   dc@");
  1035.          else
  1036.             do_write4_small("   b@a  c@f  d@   e@");
  1037.          break;
  1038.       case s_bone6:
  1039.          modulus = 6;
  1040.          newline();
  1041.          if (roti & 1)
  1042.             do_write4_small("ea@  f@  c@db@");
  1043.          else
  1044.             do_write4_small("a        b@    fc@e        d@");
  1045.          break;
  1046.       case s_1x6:
  1047.          modulus = 6;
  1048.          newline();
  1049.          if (roti & 1)
  1050.             do_write4_small("a@b@c@f@e@d@");
  1051.          else
  1052.             do_write4_small("a  b  c  f  e  d@");
  1053.          break;
  1054.       default:
  1055.          writestuff(" ????");
  1056.    }
  1057. }
  1058.  
  1059. static void printsetup(setup *x)
  1060. {
  1061.    printarg = x;
  1062.    modulus = setup_limits[x->kind]+1;
  1063.    roti = (x->rotation & 3) * 011;
  1064.    offs = ((x->rotation & 2) * (modulus / 4)) - modulus;
  1065.    
  1066.    newline();
  1067.  
  1068.    switch (x->kind) {
  1069.       case s2x4:
  1070.          if (x->rotation & 1)
  1071.             do_write("h  a@@g  b@@f  c@@e  d");
  1072.          else
  1073.             do_write("a  b  c  d@@h  g  f  e");
  1074.          break;
  1075.       case s1x8:
  1076.          if (x->rotation & 1)
  1077.             do_write("a@b@d@c@g@h@f@e");
  1078.          else
  1079.             do_write("a b d c g h f e");
  1080.          break;
  1081.       case s1x10:
  1082.          if (x->rotation & 1)
  1083.             do_write("a@b@c@d@e@j@i@h@g@f");
  1084.          else
  1085.             do_write("a b c d e j i h g f");
  1086.          break;
  1087.       case s1x12:
  1088.          if (x->rotation & 1)
  1089.             do_write("a@b@c@d@e@f@l@k@j@i@h@g");
  1090.          else
  1091.             do_write("a b c d e f l k j i h g");
  1092.          break;
  1093.       case s1x14:
  1094.          if (x->rotation & 1)
  1095.             do_write("a@b@c@d@e@f@g@n@m@l@k@j@i@h");
  1096.          else
  1097.             /* Sorry, they won't fit unless we run them together like this. */
  1098.             do_write("abcdefgnmlkjih");
  1099.          break;
  1100.       case s1x16:
  1101.          if (x->rotation & 1)
  1102.             do_write("a@b@c@d@e@f@g@h@p@o@n@m@l@k@j@i");
  1103.          else
  1104.             /* Sorry, they won't fit unless we run them together like this. */
  1105.             do_write("abcdefghponmlkji");
  1106.          break;
  1107.       case s_crosswave:
  1108.          if (x->rotation & 1)
  1109.             do_write("      a@      b@@ghdc@@      f@      e");
  1110.          else
  1111.             do_write("          c@          d@ab        fe@          h@          g");
  1112.          break;
  1113.       case s_qtag:
  1114.          if ((x->people[0].id1 & x->people[1].id1 & x->people[4].id1 & x->people[5].id1 & 1) &&
  1115.                (x->people[2].id1 & x->people[3].id1 & x->people[6].id1 & x->people[7].id1 & 010)) {
  1116.             /* People are in diamond-like orientation. */
  1117.             if (x->rotation & 1)
  1118.                do_write("      g@f        a@      h@@      d@e        b@      c");
  1119.             else {
  1120.                do_write("   a     b@@g h d c@@   f     e");
  1121.             }
  1122.          }
  1123.          else {
  1124.             /* People are not.  Probably 1/4-tag-like orientation. */
  1125.             if (x->rotation & 1)
  1126.                do_write("      g@f  h  a@e  d  b@      c");
  1127.             else {
  1128.                do_write("      a  b@@g  h  d  c@@      f  e");
  1129.             }
  1130.          }
  1131.          break;
  1132.       case s_bone:
  1133.          if (x->rotation & 1)
  1134.             do_write("fa@  g@  h@  d@  c@eb");
  1135.          else
  1136.             do_write("a                   b@    g h d c@f                   e");
  1137.          break;
  1138.       case s_rigger:
  1139.          if (x->rotation & 1)
  1140.             do_write("  g@  h@fa@eb@  d@  c");
  1141.          else
  1142.             do_write("        a b@gh         dc@        f e");
  1143.          break;
  1144.       case s_spindle:
  1145.          if (x->rotation & 1)
  1146.             do_write("  h@ga@fb@ec@  d");
  1147.          else
  1148.             do_write("    a b c@h              d@    g f e");
  1149.          break;
  1150.       case s_ptpd:
  1151.          if (x->rotation & 1)
  1152.             do_write("  a@@db@@  c@@  g@@fh@@  e");
  1153.          else
  1154.             do_write("    b           h@a    c   g    e@    d           f");
  1155.          break;
  1156.       case s_hrglass:
  1157.          if (x->rotation & 1)
  1158.             do_write("     g@f      a@   hd@e      b@     c");
  1159.          else
  1160.             do_write("  a  b@     d@g       c@     h@  f  e");
  1161.          break;
  1162.       case s_galaxy:
  1163.          offs = ((x->rotation & 3) * (modulus / 4)) - modulus;
  1164.          do_write("     c@   bd@a      e@   hf@     g");
  1165.          break;
  1166.       case s2x6:
  1167.          if (x->rotation & 1)
  1168.             do_write("l  a@@k  b@@j  c@@i  d@@h  e@@g  f");
  1169.          else
  1170.             do_write("a  b  c  d  e  f@@l  k  j  i  h  g");
  1171.          break;
  1172.       case s3x4:
  1173.          if (x->rotation & 1)
  1174.             do_write("j  k  a@@i  l  b@@h  f  c@@g  e  d");
  1175.          else
  1176.             do_write("a  b  c  d@@k  l  f  e@@j  i  h  g");
  1177.          break;
  1178.       case s_3x1dmd:
  1179.          if (x->rotation & 1)
  1180.             do_write("      a@@      b@@      c@h        d@      g@@      f@@      e");
  1181.          else
  1182.             do_write("             d@@a b c g f e@@             h");
  1183.          break;
  1184.       case s_3dmd:
  1185.          if (x->rotation & 1)
  1186.             do_write("      j@i        a@      k@@      l@h        b@      f@@      e@g        c@      d");
  1187.          else
  1188.             do_write("   a      b      c@@j k l f e d@@   i      h      g");
  1189.          break;
  1190.       case s_wingedstar:
  1191.          if (x->rotation & 1)
  1192.             do_write("   a@@   b@@   c@h  d@   g@@   f@@   e");
  1193.          else
  1194.             do_write("             d@a b c  g f e@             h");
  1195.          break;
  1196.       case s_wingedstar12:
  1197.          if (x->rotation & 1)
  1198.             do_write("   a@@   b@@   c@l  d@   e@   k@j  f@   i@@   h@@   g");
  1199.          else
  1200.             do_write("             d       f@a b c  e k  i h g@             l       j");
  1201.          break;
  1202.       case s_4dmd:
  1203.          if (x->rotation & 1)
  1204.             do_write("      m@l        a@      n@@      o@k        b@      p@@      h@j        c@      g@@      f@i        d@      e");
  1205.          else
  1206.             do_write("   a      b      c      d@@m n o p h g f e@@   l      k      j      i");
  1207.          break;
  1208.       case s2x8:
  1209.          if (x->rotation & 1)
  1210.             do_write("p  a@@o  b@@n  c@@m  d@@l  e@@k  f@@j  g@@i  h");
  1211.          else
  1212.             do_write("a  b  c  d  e  f  g  h@@p  o  n  m  l  k  j  i");
  1213.          break;
  1214.       case s4x4:
  1215.          offs = ((x->rotation & 3) * (modulus / 4)) - modulus;
  1216.          do_write("m  n  o  a@@k  p  d  b@@j  l  h  c@@i  g  f  e");
  1217.          break;
  1218.       case s_bigblob:
  1219.          offs = ((x->rotation & 3) * (modulus / 4)) - modulus;
  1220.          do_write("            a  b@@      v  w  c  d@@t  u  x  f  e  g@@s  q  r  l  i  h@@      p  o  k  j@@            n  m");
  1221.          break;
  1222.       case s_c1phan:
  1223.          offs = ((x->rotation & 3) * (modulus / 4)) - modulus;
  1224.          do_write("   b        e@a  c  h  f@   d        g@@   o        l@n  p  k  i@   m        j");
  1225.          break;
  1226.       case s4x6:
  1227.          if (x->rotation & 1)
  1228.             do_write("r  s  l  a@@q  t  k  b@@p  u  j  c@@o  v  i  d@@n  w  h  e@@m  x  g  f");
  1229.          else
  1230.             do_write("a  b  c  d  e  f@@l  k  j  i  h  g@@s  t  u  v  w  x@@r  q  p  o  n  m");
  1231.          break;
  1232.       case s_normal_concentric:
  1233.          writestuff(" centers:");
  1234.          newline();
  1235.          print_4_person_setup(0, &(x->inner), -1);
  1236.          writestuff(" ends:");
  1237.          newline();
  1238.          print_4_person_setup(12, &(x->outer), x->outer_elongation);
  1239.          break;
  1240.       default:
  1241.          writestuff("???? UNKNOWN SETUP ????");
  1242.    }
  1243.  
  1244.    newline();
  1245.    newline();
  1246. }
  1247.  
  1248.  
  1249. /* Clear the screen and display the initial part of the history.
  1250.    This attempts to re-use material already displayed on the screen.
  1251.    The "num_pics" argument tells how many of the last history items
  1252.    are to have pictures forced, so we can tell exactly what items
  1253.    have pictures. */
  1254. extern void display_initial_history(int upper_limit, int num_pics)
  1255. {
  1256.    int j, startpoint, compilerbug;
  1257.  
  1258.    /* See if we can re-use some of the safely written history. */
  1259.    /* First, cut down overly optimistic estimates. */
  1260.    if (written_history_items > upper_limit) written_history_items = upper_limit;
  1261.    /* And normalize the "nopic" number. */
  1262.    if (written_history_nopic > written_history_items) written_history_nopic = written_history_items;
  1263.  
  1264.    /* Check whether pictures are faithful.  If any item in the written history has its
  1265.       "picture forced" property (as determined by written_history_nopic)
  1266.       different from what we want that property to be (as determined by upper_limit-num_pics),
  1267.       and that item didn't have the draw_pic flag on, that item needs to be rewritten.
  1268.       We cut written_history_items down to below that item if such is the case. */
  1269.  
  1270.    for (j=1; j<=written_history_items; j++) {
  1271.       compilerbug = ((int) ((unsigned int) (written_history_nopic-j)) ^
  1272.                  ((unsigned int) (upper_limit-num_pics-j)));
  1273.       if (compilerbug < 0 && ~history[j].draw_pic) {
  1274.          written_history_items = j-1;
  1275.          break;
  1276.       }
  1277.    }
  1278.  
  1279.    if (written_history_items > 0) {
  1280.       /* We win.  Back up the text line count to the right place, and rewrite the rest. */
  1281.  
  1282.       text_line_count = history[written_history_items].text_line;
  1283.       uims_reduce_line_count(text_line_count);
  1284.       open_text_line();
  1285.       startpoint = written_history_items+1;
  1286.    }
  1287.    else {
  1288.       /* We lose, there is nothing we can use. */
  1289.       clear_screen();
  1290.       startpoint = 1;
  1291.    }
  1292.  
  1293.    for (j=startpoint; j<=upper_limit-num_pics; j++) write_history_line(j, (char *) 0, FALSE, file_write_no);
  1294.  
  1295.    /* Now write stuff with forced pictures. */
  1296.  
  1297.    for (j=upper_limit-num_pics+1; j<=upper_limit; j++) {
  1298.       if (j >= startpoint) write_history_line(j, (char *) 0, TRUE, file_write_no);
  1299.    }
  1300.  
  1301.    written_history_items = upper_limit;   /* This stuff is now safe. */
  1302.    written_history_nopic = written_history_items-num_pics;
  1303. }
  1304.  
  1305.  
  1306.  
  1307. extern void write_history_line(int history_index, char *header, long_boolean picture, file_write_flag write_to_file)
  1308. {
  1309.    int index, w;
  1310.  
  1311.    if (write_to_file == file_write_double)
  1312.       doublespace_file();
  1313.  
  1314.    index = history[history_index].centersp;
  1315.  
  1316.    if (header) {
  1317.       writestuff(header);
  1318.    }
  1319.  
  1320.    if (index != 0) {
  1321.       if (startinfolist[index].into_the_middle) goto morefinal;
  1322.       writestuff(startinfolist[index].name);
  1323.       goto final;
  1324.    }
  1325.  
  1326.    static_cptr = history[history_index].command_root;
  1327.    
  1328.    /* Need to check for the special case of starting a sequence with heads or sides.
  1329.       If this is the first line of the history, and we started with heads of sides,
  1330.       change the name of this concept from "centers" to the appropriate thing. */
  1331.  
  1332.    if (history_index == 2 && static_cptr->concept->kind == concept_centers_or_ends && static_cptr->concept->value.arg1 == 0) {
  1333.       index = history[1].centersp;
  1334.       if (startinfolist[index].into_the_middle) {
  1335.          writestuff(startinfolist[index].name);
  1336.          writestuff(" ");
  1337.          static_cptr = static_cptr->next;
  1338.       }
  1339.    }
  1340.    
  1341.    print_recurse(0);
  1342.    
  1343.    final:
  1344.  
  1345.    newline();
  1346.  
  1347.    morefinal:
  1348.  
  1349.    /* Check for warnings to print. */
  1350.    /* Do not double space them, even if writing final output. */
  1351.  
  1352.    for (w=0; w<64; w++) {
  1353.       if (((1 << (w & 0x1f)) & history[history_index].warnings.bits[w>>5]) != 0) {
  1354.          writestuff("  Warning:  ");
  1355.          writestuff(warning_strings[w]);
  1356.          newline();
  1357.       }
  1358.    }
  1359.  
  1360.    if (picture || history[history_index].draw_pic) {
  1361.       printsetup(&history[history_index].state);
  1362.    }
  1363.  
  1364.    /* Record that this history item has been written to the UI. */
  1365.    history[history_index].text_line = text_line_count;
  1366. }
  1367.  
  1368.  
  1369. extern void warn(int w)
  1370. {
  1371.    history[history_ptr+1].warnings.bits[w>>5] |= 1 << (w & 0x1f);
  1372. }
  1373.  
  1374.  
  1375. extern call_list_kind find_proper_call_list(setup *s)
  1376. {
  1377.    if (s->kind == s1x8) {
  1378.       if      ((s->people[0].id1 & 017) == 010 &&
  1379.                (s->people[1].id1 & 017) == 012 &&
  1380.                (s->people[2].id1 & 017) == 012 &&
  1381.                (s->people[3].id1 & 017) == 010 &&
  1382.                (s->people[4].id1 & 017) == 012 &&
  1383.                (s->people[5].id1 & 017) == 010 &&
  1384.                (s->people[6].id1 & 017) == 010 &&
  1385.                (s->people[7].id1 & 017) == 012)
  1386.          return(call_list_1x8);
  1387.       else if ((s->people[0].id1 & 017) == 012 &&
  1388.                (s->people[1].id1 & 017) == 010 &&
  1389.                (s->people[2].id1 & 017) == 010 &&
  1390.                (s->people[3].id1 & 017) == 012 &&
  1391.                (s->people[4].id1 & 017) == 010 &&
  1392.                (s->people[5].id1 & 017) == 012 &&
  1393.                (s->people[6].id1 & 017) == 012 &&
  1394.                (s->people[7].id1 & 017) == 010)
  1395.          return(call_list_l1x8);
  1396.       else if ((s->people[0].id1 & 015) == 1 &&
  1397.                (s->people[1].id1 & 015) == 1 &&
  1398.                (s->people[2].id1 & 015) == 1 &&
  1399.                (s->people[3].id1 & 015) == 1 &&
  1400.                (s->people[4].id1 & 015) == 1 &&
  1401.                (s->people[5].id1 & 015) == 1 &&
  1402.                (s->people[6].id1 & 015) == 1 &&
  1403.                (s->people[7].id1 & 015) == 1)
  1404.          return(call_list_gcol);
  1405.    }
  1406.    else if (s->kind == s2x4) {
  1407.       if      ((s->people[0].id1 & 017) == 1 &&
  1408.                (s->people[1].id1 & 017) == 1 &&
  1409.                (s->people[2].id1 & 017) == 3 &&
  1410.                (s->people[3].id1 & 017) == 3 &&
  1411.                (s->people[4].id1 & 017) == 3 &&
  1412.                (s->people[5].id1 & 017) == 3 &&
  1413.                (s->people[6].id1 & 017) == 1 &&
  1414.                (s->people[7].id1 & 017) == 1)
  1415.          return(call_list_dpt);
  1416.       else if ((s->people[0].id1 & 017) == 3 &&
  1417.                (s->people[1].id1 & 017) == 3 &&
  1418.                (s->people[2].id1 & 017) == 1 &&
  1419.                (s->people[3].id1 & 017) == 1 &&
  1420.                (s->people[4].id1 & 017) == 1 &&
  1421.                (s->people[5].id1 & 017) == 1 &&
  1422.                (s->people[6].id1 & 017) == 3 &&
  1423.                (s->people[7].id1 & 017) == 3)
  1424.          return(call_list_cdpt);
  1425.       else if ((s->people[0].id1 & 017) == 1 &&
  1426.                (s->people[1].id1 & 017) == 1 &&
  1427.                (s->people[2].id1 & 017) == 1 &&
  1428.                (s->people[3].id1 & 017) == 1 &&
  1429.                (s->people[4].id1 & 017) == 3 &&
  1430.                (s->people[5].id1 & 017) == 3 &&
  1431.                (s->people[6].id1 & 017) == 3 &&
  1432.                (s->people[7].id1 & 017) == 3)
  1433.          return(call_list_rcol);
  1434.       else if ((s->people[0].id1 & 017) == 3 &&
  1435.                (s->people[1].id1 & 017) == 3 &&
  1436.                (s->people[2].id1 & 017) == 3 &&
  1437.                (s->people[3].id1 & 017) == 3 &&
  1438.                (s->people[4].id1 & 017) == 1 &&
  1439.                (s->people[5].id1 & 017) == 1 &&
  1440.                (s->people[6].id1 & 017) == 1 &&
  1441.                (s->people[7].id1 & 017) == 1)
  1442.          return(call_list_lcol);
  1443.       else if ((s->people[0].id1 & 017) == 1 &&
  1444.                (s->people[1].id1 & 017) == 3 &&
  1445.                (s->people[2].id1 & 017) == 1 &&
  1446.                (s->people[3].id1 & 017) == 3 &&
  1447.                (s->people[4].id1 & 017) == 3 &&
  1448.                (s->people[5].id1 & 017) == 1 &&
  1449.                (s->people[6].id1 & 017) == 3 &&
  1450.                (s->people[7].id1 & 017) == 1)
  1451.          return(call_list_8ch);
  1452.       else if ((s->people[0].id1 & 017) == 3 &&
  1453.                (s->people[1].id1 & 017) == 1 &&
  1454.                (s->people[2].id1 & 017) == 3 &&
  1455.                (s->people[3].id1 & 017) == 1 &&
  1456.                (s->people[4].id1 & 017) == 1 &&
  1457.                (s->people[5].id1 & 017) == 3 &&
  1458.                (s->people[6].id1 & 017) == 1 &&
  1459.                (s->people[7].id1 & 017) == 3)
  1460.          return(call_list_tby);
  1461.       else if ((s->people[0].id1 & 017) == 012 &&
  1462.                (s->people[1].id1 & 017) == 012 &&
  1463.                (s->people[2].id1 & 017) == 012 &&
  1464.                (s->people[3].id1 & 017) == 012 &&
  1465.                (s->people[4].id1 & 017) == 010 &&
  1466.                (s->people[5].id1 & 017) == 010 &&
  1467.                (s->people[6].id1 & 017) == 010 &&
  1468.                (s->people[7].id1 & 017) == 010)
  1469.          return(call_list_lin);
  1470.       else if ((s->people[0].id1 & 017) == 010 &&
  1471.                (s->people[1].id1 & 017) == 010 &&
  1472.                (s->people[2].id1 & 017) == 010 &&
  1473.                (s->people[3].id1 & 017) == 010 &&
  1474.                (s->people[4].id1 & 017) == 012 &&
  1475.                (s->people[5].id1 & 017) == 012 &&
  1476.                (s->people[6].id1 & 017) == 012 &&
  1477.                (s->people[7].id1 & 017) == 012)
  1478.          return(call_list_lout);
  1479.       else if ((s->people[0].id1 & 017) == 010 &&
  1480.                (s->people[1].id1 & 017) == 012 &&
  1481.                (s->people[2].id1 & 017) == 010 &&
  1482.                (s->people[3].id1 & 017) == 012 &&
  1483.                (s->people[4].id1 & 017) == 012 &&
  1484.                (s->people[5].id1 & 017) == 010 &&
  1485.                (s->people[6].id1 & 017) == 012 &&
  1486.                (s->people[7].id1 & 017) == 010)
  1487.          return(call_list_rwv);
  1488.       else if ((s->people[0].id1 & 017) == 012 &&
  1489.                (s->people[1].id1 & 017) == 010 &&
  1490.                (s->people[2].id1 & 017) == 012 &&
  1491.                (s->people[3].id1 & 017) == 010 &&
  1492.                (s->people[4].id1 & 017) == 010 &&
  1493.                (s->people[5].id1 & 017) == 012 &&
  1494.                (s->people[6].id1 & 017) == 010 &&
  1495.                (s->people[7].id1 & 017) == 012)
  1496.          return(call_list_lwv);
  1497.       else if ((s->people[0].id1 & 017) == 010 &&
  1498.                (s->people[1].id1 & 017) == 010 &&
  1499.                (s->people[2].id1 & 017) == 012 &&
  1500.                (s->people[3].id1 & 017) == 012 &&
  1501.                (s->people[4].id1 & 017) == 012 &&
  1502.                (s->people[5].id1 & 017) == 012 &&
  1503.                (s->people[6].id1 & 017) == 010 &&
  1504.                (s->people[7].id1 & 017) == 010)
  1505.          return(call_list_r2fl);
  1506.       else if ((s->people[0].id1 & 017) == 012 &&
  1507.                (s->people[1].id1 & 017) == 012 &&
  1508.                (s->people[2].id1 & 017) == 010 &&
  1509.                (s->people[3].id1 & 017) == 010 &&
  1510.                (s->people[4].id1 & 017) == 010 &&
  1511.                (s->people[5].id1 & 017) == 010 &&
  1512.                (s->people[6].id1 & 017) == 012 &&
  1513.                (s->people[7].id1 & 017) == 012)
  1514.          return(call_list_l2fl);
  1515.    }
  1516.    else if (s->kind == s_qtag)
  1517.       return(call_list_qtag);
  1518.  
  1519.    return(call_list_any);
  1520. }
  1521.  
  1522.  
  1523. extern callarray *assoc(begin_kind key, setup *ss, callarray *spec)
  1524. {
  1525.    callarray *p;
  1526.    int t, u, i, k, mask;
  1527.  
  1528.    p = spec;
  1529.    for (;;) {
  1530.       if (p == 0) goto good;
  1531.       if (p->start_setup == key) {
  1532.          if (p->qualifier == sq_none) goto good;
  1533.          /* Can't be bothered to figure out what setup to create when
  1534.             calling this during initialization, so we send nil. */
  1535.          if (!ss) goto good;
  1536.  
  1537.          /* Note that we have to examine setups larger than the setup the
  1538.             qualifier is officially defined for.  If a qualifier were defined
  1539.             as being legal only on 1x4's (so that, in the database, we only had
  1540.             specifications of the sort "setup 1x4 1x4 qualifier wave_only") we could
  1541.             still find ourselves here with ss->kind equal to s2x4.  Why?  Because
  1542.             the setup could be a 2x4 and the splitter could be trying to decide
  1543.             whether to split the setup into parallel 1x4's.  This happens when
  1544.             trying to figure out whether to split a 2x4 into 1x4's or 2x2's for
  1545.             the call "recycle". */
  1546.  
  1547.          k = 0;   /* Many tests will find these values useful. */
  1548.          i = 2;
  1549.  
  1550.          switch(p->qualifier) {
  1551.             case sq_wave_only:                    /* 1x4 or 2x4 - wave */
  1552.                switch (ss->kind) {
  1553.                   case s1x4:
  1554.                      if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1555.                      if (t = ss->people[1].id1) { k |= ~t; i &= ~t; }
  1556.                      if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1557.                      if (t = ss->people[3].id1) { k |=  t; i &=  t; }
  1558.                      if (!(k & ~i & 2)) goto good;
  1559.                      goto bad;
  1560.                   case s2x4:
  1561.                      if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1562.                      if (t = ss->people[1].id1) { k |= ~t; i &= ~t; }
  1563.                      if (t = ss->people[2].id1) { k |=  t; i &=  t; }
  1564.                      if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1565.                      if (t = ss->people[4].id1) { k |= ~t; i &= ~t; }
  1566.                      if (t = ss->people[5].id1) { k |=  t; i &=  t; }
  1567.                      if (t = ss->people[6].id1) { k |= ~t; i &= ~t; }
  1568.                      if (t = ss->people[7].id1) { k |=  t; i &=  t; }
  1569.                      if (!(k & ~i & 2)) goto good;
  1570.                      goto bad;
  1571.                   default:
  1572.                      goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1573.                }
  1574.             case sq_2fl_only:                     /* 1x4 or 2x4 - 2FL */
  1575.                switch (ss->kind) {
  1576.                   case s1x4:
  1577.                      if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1578.                      if (t = ss->people[1].id1) { k |=  t; i &=  t; }
  1579.                      if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1580.                      if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1581.                      if (!(k & ~i & 2)) goto good;
  1582.                      goto bad;
  1583.                   case s2x4:
  1584.                      if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1585.                      if (t = ss->people[1].id1) { k |=  t; i &=  t; }
  1586.                      if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1587.                      if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1588.                      if (t = ss->people[4].id1) { k |= ~t; i &= ~t; }
  1589.                      if (t = ss->people[5].id1) { k |= ~t; i &= ~t; }
  1590.                      if (t = ss->people[6].id1) { k |=  t; i &=  t; }
  1591.                      if (t = ss->people[7].id1) { k |=  t; i &=  t; }
  1592.                      if (!(k & ~i & 2)) goto good;
  1593.                      goto bad;
  1594.                   default:
  1595.                      goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1596.                }
  1597.             case sq_miniwaves:                    /* miniwaves everywhere */
  1598.                switch (ss->kind) {
  1599.                   case s_1x2:
  1600.                      if ((t = ss->people[0].id1) & (u = ss->people[1].id1)) { k |= t|u; i &= t^u; }
  1601.                      if ((i & 2) && !(k & 1)) goto good;
  1602.                      goto bad;
  1603.                   case s1x4:
  1604.                      if ((t = ss->people[0].id1) & (u = ss->people[1].id1)) { k |= t|u; i &= t^u; }
  1605.                      if ((t = ss->people[3].id1) & (u = ss->people[2].id1)) { k |= t|u; i &= t^u; }
  1606.                      if ((i & 2) && !(k & 1)) goto good;
  1607.                      goto bad;
  1608.                   case s1x8:
  1609.                      if ((t = ss->people[0].id1) & (u = ss->people[1].id1)) { k |= t|u; i &= t^u; }
  1610.                      if ((t = ss->people[3].id1) & (u = ss->people[2].id1)) { k |= t|u; i &= t^u; }
  1611.                      if ((t = ss->people[6].id1) & (u = ss->people[7].id1)) { k |= t|u; i &= t^u; }
  1612.                      if ((t = ss->people[5].id1) & (u = ss->people[4].id1)) { k |= t|u; i &= t^u; }
  1613.                      if ((i & 2) && !(k & 1)) goto good;
  1614.                      goto bad;
  1615.                   case s2x4:
  1616.                      if ((t = ss->people[0].id1) & (u = ss->people[1].id1)) { k |= t|u; i &= t^u; }
  1617.                      if ((t = ss->people[2].id1) & (u = ss->people[3].id1)) { k |= t|u; i &= t^u; }
  1618.                      if ((t = ss->people[5].id1) & (u = ss->people[4].id1)) { k |= t|u; i &= t^u; }
  1619.                      if ((t = ss->people[7].id1) & (u = ss->people[6].id1)) { k |= t|u; i &= t^u; }
  1620.                      if ((i & 2) && !(k & 1)) goto good;
  1621.                      k = 1;
  1622.                      i = 2;
  1623.                      if ((t = ss->people[0].id1) & (u = ss->people[7].id1)) { k &= t&u; i &= t^u; }
  1624.                      if ((t = ss->people[1].id1) & (u = ss->people[6].id1)) { k &= t&u; i &= t^u; }
  1625.                      if ((t = ss->people[2].id1) & (u = ss->people[5].id1)) { k &= t&u; i &= t^u; }
  1626.                      if ((t = ss->people[3].id1) & (u = ss->people[4].id1)) { k &= t&u; i &= t^u; }
  1627.                      if ((i & 2) && (k & 1)) goto good;
  1628.                      goto bad;
  1629.                   case s2x2:
  1630.                      if ((t = ss->people[0].id1) & (u = ss->people[1].id1)) { k |= t|u; i &= t^u; }
  1631.                      if ((t = ss->people[3].id1) & (u = ss->people[2].id1)) { k |= t|u; i &= t^u; }
  1632.                      if ((i & 2) && !(k & 1)) goto good;
  1633.                      k = 1;
  1634.                      i = 2;
  1635.                      if ((t = ss->people[0].id1) & (u = ss->people[3].id1)) { k &= t&u; i &= t^u; }
  1636.                      if ((t = ss->people[1].id1) & (u = ss->people[2].id1)) { k &= t&u; i &= t^u; }
  1637.                      if ((i & 2) && (k & 1)) goto good;
  1638.                      goto bad;
  1639.                   case sdmd:
  1640.                      k = 1;
  1641.                      i = 2;
  1642.                      if ((t = ss->people[1].id1) & (u = ss->people[3].id1)) { k &= t&u; i &= t^u; }
  1643.                      if ((i & 2) && (k & 1)) goto good;
  1644.                      goto bad;
  1645.                   case s_trngl:
  1646.                      if ((t = ss->people[1].id1) & (u = ss->people[2].id1)) { k |= t|u; i &= t^u; }
  1647.                      if ((i & 2) && !(k & 1)) goto good;
  1648.                      goto bad;
  1649.                   case s_qtag:
  1650.                      if ((t = ss->people[6].id1) & (u = ss->people[7].id1)) { k |= t|u; i &= t^u; }
  1651.                      if ((t = ss->people[3].id1) & (u = ss->people[2].id1)) { k |= t|u; i &= t^u; }
  1652.                      if ((i & 2) && !(k & 1)) goto good;
  1653.                      goto bad;
  1654.                   default:
  1655.                      goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1656.                }
  1657.             case sq_rwave_only:
  1658.                if (ss->kind == s_1x2) {
  1659.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_north) &&
  1660.                       (!(t = ss->people[1].id1 & d_mask) || t == d_south))
  1661.                   goto good;
  1662.                   goto bad;
  1663.                }
  1664.                else if (ss->kind == s1x4) {
  1665.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_north) &&
  1666.                       (!(t = ss->people[1].id1 & d_mask) || t == d_south) &&
  1667.                       (!(t = ss->people[3].id1 & d_mask) || t == d_north) &&
  1668.                       (!(t = ss->people[2].id1 & d_mask) || t == d_south))
  1669.                   goto good;
  1670.                   goto bad;
  1671.                }
  1672.                else if (ss->kind == s1x8) {
  1673.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_north) &&
  1674.                       (!(t = ss->people[1].id1 & d_mask) || t == d_south) &&
  1675.                       (!(t = ss->people[3].id1 & d_mask) || t == d_north) &&
  1676.                       (!(t = ss->people[2].id1 & d_mask) || t == d_south) &&
  1677.                       (!(t = ss->people[6].id1 & d_mask) || t == d_north) &&
  1678.                       (!(t = ss->people[7].id1 & d_mask) || t == d_south) &&
  1679.                       (!(t = ss->people[5].id1 & d_mask) || t == d_north) &&
  1680.                       (!(t = ss->people[4].id1 & d_mask) || t == d_south))
  1681.                   goto good;
  1682.                   goto bad;
  1683.                }
  1684.                else if (ss->kind == s2x4) {
  1685.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_north) &&
  1686.                       (!(t = ss->people[1].id1 & d_mask) || t == d_south) &&
  1687.                       (!(t = ss->people[2].id1 & d_mask) || t == d_north) &&
  1688.                       (!(t = ss->people[3].id1 & d_mask) || t == d_south) &&
  1689.                       (!(t = ss->people[4].id1 & d_mask) || t == d_south) &&
  1690.                       (!(t = ss->people[5].id1 & d_mask) || t == d_north) &&
  1691.                       (!(t = ss->people[6].id1 & d_mask) || t == d_south) &&
  1692.                       (!(t = ss->people[7].id1 & d_mask) || t == d_north))
  1693.                   goto good;
  1694.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_east) &&
  1695.                       (!(t = ss->people[1].id1 & d_mask) || t == d_east) &&
  1696.                       (!(t = ss->people[2].id1 & d_mask) || t == d_east) &&
  1697.                       (!(t = ss->people[3].id1 & d_mask) || t == d_east) &&
  1698.                       (!(t = ss->people[4].id1 & d_mask) || t == d_west) &&
  1699.                       (!(t = ss->people[5].id1 & d_mask) || t == d_west) &&
  1700.                       (!(t = ss->people[6].id1 & d_mask) || t == d_west) &&
  1701.                       (!(t = ss->people[7].id1 & d_mask) || t == d_west))
  1702.                   goto good;
  1703.                   goto bad;
  1704.                }
  1705.                else if (ss->kind == s2x2) {
  1706.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_north) &&
  1707.                       (!(t = ss->people[1].id1 & d_mask) || t == d_south) &&
  1708.                       (!(t = ss->people[2].id1 & d_mask) || t == d_south) &&
  1709.                       (!(t = ss->people[3].id1 & d_mask) || t == d_north))
  1710.                   goto good;
  1711.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_east) &&
  1712.                       (!(t = ss->people[1].id1 & d_mask) || t == d_east) &&
  1713.                       (!(t = ss->people[2].id1 & d_mask) || t == d_west) &&
  1714.                       (!(t = ss->people[3].id1 & d_mask) || t == d_west))
  1715.                   goto good;
  1716.                   goto bad;
  1717.                }
  1718.                else if (ss->kind == sdmd) {
  1719.                   if ((!(t = ss->people[1].id1 & d_mask) || t == d_east) &&
  1720.                       (!(t = ss->people[3].id1 & d_mask) || t == d_west))
  1721.                   goto good;
  1722.                   goto bad;
  1723.                }
  1724.                else if (ss->kind == s_trngl) {
  1725.                   if ((!(t = ss->people[1].id1 & d_mask) || t == d_north) &&
  1726.                       (!(t = ss->people[2].id1 & d_mask) || t == d_south))
  1727.                   goto good;
  1728.                   goto bad;
  1729.                }
  1730.                else if (ss->kind == s_qtag) {
  1731.                   if ((!(t = ss->people[2].id1 & d_mask) || t == d_south) &&
  1732.                       (!(t = ss->people[3].id1 & d_mask) || t == d_north) &&
  1733.                       (!(t = ss->people[6].id1 & d_mask) || t == d_north) &&
  1734.                       (!(t = ss->people[7].id1 & d_mask) || t == d_south))
  1735.                   goto good;
  1736.                   goto bad;
  1737.                }
  1738.                else {
  1739.                   goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1740.                }
  1741.             case sq_lwave_only:
  1742.                if (ss->kind == s_1x2) {
  1743.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_south) &&
  1744.                       (!(t = ss->people[1].id1 & d_mask) || t == d_north))
  1745.                   goto good;
  1746.                   goto bad;
  1747.                }
  1748.                else if (ss->kind == s1x4) {
  1749.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_south) &&
  1750.                       (!(t = ss->people[1].id1 & d_mask) || t == d_north) &&
  1751.                       (!(t = ss->people[3].id1 & d_mask) || t == d_south) &&
  1752.                       (!(t = ss->people[2].id1 & d_mask) || t == d_north))
  1753.                   goto good;
  1754.                   goto bad;
  1755.                }
  1756.                else if (ss->kind == s1x8) {
  1757.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_south) &&
  1758.                       (!(t = ss->people[1].id1 & d_mask) || t == d_north) &&
  1759.                       (!(t = ss->people[3].id1 & d_mask) || t == d_south) &&
  1760.                       (!(t = ss->people[2].id1 & d_mask) || t == d_north) &&
  1761.                       (!(t = ss->people[6].id1 & d_mask) || t == d_south) &&
  1762.                       (!(t = ss->people[7].id1 & d_mask) || t == d_north) &&
  1763.                       (!(t = ss->people[5].id1 & d_mask) || t == d_south) &&
  1764.                       (!(t = ss->people[4].id1 & d_mask) || t == d_north))
  1765.                   goto good;
  1766.                   goto bad;
  1767.                }
  1768.                else if (ss->kind == s2x4) {
  1769.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_south) &&
  1770.                       (!(t = ss->people[1].id1 & d_mask) || t == d_north) &&
  1771.                       (!(t = ss->people[2].id1 & d_mask) || t == d_south) &&
  1772.                       (!(t = ss->people[3].id1 & d_mask) || t == d_north) &&
  1773.                       (!(t = ss->people[4].id1 & d_mask) || t == d_north) &&
  1774.                       (!(t = ss->people[5].id1 & d_mask) || t == d_south) &&
  1775.                       (!(t = ss->people[6].id1 & d_mask) || t == d_north) &&
  1776.                       (!(t = ss->people[7].id1 & d_mask) || t == d_south))
  1777.                   goto good;
  1778.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_west) &&
  1779.                       (!(t = ss->people[1].id1 & d_mask) || t == d_west) &&
  1780.                       (!(t = ss->people[2].id1 & d_mask) || t == d_west) &&
  1781.                       (!(t = ss->people[3].id1 & d_mask) || t == d_west) &&
  1782.                       (!(t = ss->people[4].id1 & d_mask) || t == d_east) &&
  1783.                       (!(t = ss->people[5].id1 & d_mask) || t == d_east) &&
  1784.                       (!(t = ss->people[6].id1 & d_mask) || t == d_east) &&
  1785.                       (!(t = ss->people[7].id1 & d_mask) || t == d_east))
  1786.                   goto good;
  1787.                   goto bad;
  1788.                }
  1789.                else if (ss->kind == s2x2) {
  1790.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_south) &&
  1791.                       (!(t = ss->people[1].id1 & d_mask) || t == d_north) &&
  1792.                       (!(t = ss->people[2].id1 & d_mask) || t == d_north) &&
  1793.                       (!(t = ss->people[3].id1 & d_mask) || t == d_south))
  1794.                   goto good;
  1795.                   if ((!(t = ss->people[0].id1 & d_mask) || t == d_west) &&
  1796.                       (!(t = ss->people[1].id1 & d_mask) || t == d_west) &&
  1797.                       (!(t = ss->people[2].id1 & d_mask) || t == d_east) &&
  1798.                       (!(t = ss->people[3].id1 & d_mask) || t == d_east))
  1799.                   goto good;
  1800.                   goto bad;
  1801.                }
  1802.                else if (ss->kind == sdmd) {
  1803.                   if ((!(t = ss->people[1].id1 & d_mask) || t == d_west) &&
  1804.                       (!(t = ss->people[3].id1 & d_mask) || t == d_east))
  1805.                   goto good;
  1806.                   goto bad;
  1807.                }
  1808.                if (ss->kind == s_trngl) {
  1809.                   if ((!(t = ss->people[1].id1 & d_mask) || t == d_south) &&
  1810.                       (!(t = ss->people[2].id1 & d_mask) || t == d_north))
  1811.                   goto good;
  1812.                   goto bad;
  1813.                }
  1814.                else if (ss->kind == s_qtag) {
  1815.                   if ((!(t = ss->people[2].id1 & d_mask) || t == d_north) &&
  1816.                       (!(t = ss->people[3].id1 & d_mask) || t == d_south) &&
  1817.                       (!(t = ss->people[6].id1 & d_mask) || t == d_south) &&
  1818.                       (!(t = ss->people[7].id1 & d_mask) || t == d_north))
  1819.                   goto good;
  1820.                   goto bad;
  1821.                }
  1822.                else {
  1823.                   goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1824.                }
  1825.             case sq_ctrwv_end2fl:
  1826.                /* Note that this qualifier is kind of strict.  We won't permit the call "with
  1827.                   confidence" do be done unless everyone can trivially determine which
  1828.                   part to do. */
  1829.                if (ss->kind == s_crosswave) {
  1830.                   if (((ss->people[0].id1 ^ ss->people[1].id1) & d_mask) == 0 &&
  1831.                       ((ss->people[4].id1 ^ ss->people[5].id1) & d_mask) == 0 &&
  1832.                       ((ss->people[2].id1 | ss->people[3].id1) == 0 || ((ss->people[2].id1 ^ ss->people[3].id1) & d_mask) == 2) &&
  1833.                       ((ss->people[6].id1 | ss->people[7].id1) == 0 || ((ss->people[6].id1 ^ ss->people[7].id1) & d_mask) == 2))
  1834.                   goto good;
  1835.                   goto bad;
  1836.                }
  1837.                else {
  1838.                   goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1839.                }
  1840.             case sq_ctr2fl_endwv:
  1841.                /* Note that this qualifier is kind of strict.  We won't permit the call "with
  1842.                   confidence" do be done unless everyone can trivially determine which
  1843.                   part to do. */
  1844.                if (ss->kind == s_crosswave) {
  1845.                   if (((ss->people[2].id1 ^ ss->people[3].id1) & d_mask) == 0 &&
  1846.                       ((ss->people[6].id1 ^ ss->people[7].id1) & d_mask) == 0 &&
  1847.                       ((ss->people[0].id1 | ss->people[1].id1) == 0 || ((ss->people[0].id1 ^ ss->people[1].id1) & d_mask) == 2) &&
  1848.                       ((ss->people[4].id1 | ss->people[5].id1) == 0 || ((ss->people[4].id1 ^ ss->people[5].id1) & d_mask) == 2))
  1849.                   goto good;
  1850.                   goto bad;
  1851.                }
  1852.                else {
  1853.                   goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1854.                }
  1855.             case sq_true_Z:                    /* 2x3, 3x4, or 2x6 - real Z spots occupied, so can do Z axle */
  1856.                mask = 0;
  1857.  
  1858.                for (i=0, k=1; i<=setup_limits[ss->kind]; i++, k<<=1) {
  1859.                   if (ss->people[i].id1) mask |= k;
  1860.                }
  1861.  
  1862.                if (ss->kind == s_2x3) {
  1863.                   if (mask == 033 || mask == 066) goto good;
  1864.                   goto bad;
  1865.                }
  1866.                else if (ss->kind == s3x4) {
  1867.                   if (mask == 0xEBA || mask == 0xD75) goto good;
  1868.                   goto bad;
  1869.                }
  1870.                else if (ss->kind == s2x6) {
  1871.                   if (mask == 03333 || mask == 06666) goto good;
  1872.                   goto bad;
  1873.                }
  1874.                else {
  1875.                   goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1876.                }
  1877.             case sq_3_4_tag:                      /* dmd or qtag - is a 3/4 tag, i.e. points looking out */
  1878.                switch (ss->kind) {
  1879.                   case sdmd:
  1880.                      if ((!(t = ss->people[0].id1 & d_mask) || t == d_west) &&
  1881.                          (!(t = ss->people[2].id1 & d_mask) || t == d_east))
  1882.                      goto good;
  1883.                      goto bad;
  1884.                   case s_qtag:
  1885.                      if ((!(t = ss->people[0].id1 & d_mask) || t == d_north) &&
  1886.                          (!(t = ss->people[1].id1 & d_mask) || t == d_north) &&
  1887.                          (!(t = ss->people[4].id1 & d_mask) || t == d_south) &&
  1888.                          (!(t = ss->people[5].id1 & d_mask) || t == d_south))
  1889.                      goto good;
  1890.                      goto bad;
  1891.                   default:
  1892.                      goto good;                 /* We don't understand the setup -- we'd better accept it. */
  1893.                }
  1894.             case sq_dmd_same_pt:                   /* dmd or pdmd - centers would circulate to same point */
  1895.                if (((ss->people[1].id1 & 01011) == d_east) &&                        /* faces either east or west */
  1896.                    (!((ss->people[3].id1 ^ ss->people[1].id1) & d_mask)))   /* and both face same way */
  1897.                   goto good;
  1898.                goto bad;
  1899.             case sq_dmd_facing:                    /* dmd or pdmd - diamond is fully occupied and fully facing */
  1900.                if ((ss->people[0].id1 & d_mask) == d_north &&
  1901.                    (ss->people[1].id1 & d_mask) == d_west &&
  1902.                    (ss->people[2].id1 & d_mask) == d_south &&
  1903.                    (ss->people[3].id1 & d_mask) == d_east)
  1904.                   goto good;
  1905.                if ((ss->people[0].id1 & d_mask) == d_south &&
  1906.                    (ss->people[1].id1 & d_mask) == d_east &&
  1907.                    (ss->people[2].id1 & d_mask) == d_north &&
  1908.                    (ss->people[3].id1 & d_mask) == d_west)
  1909.                   goto good;
  1910.                goto bad;
  1911.          }
  1912.       }
  1913.       bad:
  1914.       p = p->next;
  1915.    }
  1916.  
  1917.    good:
  1918.    return(p);
  1919. }
  1920.  
  1921.  
  1922. extern unsigned int find_calldef(
  1923.    callarray *tdef,
  1924.    setup *scopy,
  1925.    int real_index,
  1926.    int real_direction,
  1927.    int northified_index)
  1928. {
  1929.    unsigned short *calldef_array;
  1930.    predptr_pair *predlistptr;
  1931.    unsigned int z;
  1932.  
  1933.    if (tdef->callarray_flags & CAF__PREDS) {
  1934.       predlistptr = tdef->stuff.prd.predlist;
  1935.       while (predlistptr != (predptr_pair *) 0) {
  1936.          if ((*(predlistptr->pred))(scopy, real_index, real_direction, northified_index)) {
  1937.             calldef_array = predlistptr->arr;
  1938.             goto got_it;
  1939.          }
  1940.          predlistptr = predlistptr->next;
  1941.       }
  1942.       fail(tdef->stuff.prd.errmsg);
  1943.    }
  1944.    else
  1945.       calldef_array = tdef->stuff.def;
  1946.  
  1947. got_it:
  1948.  
  1949.    z = calldef_array[northified_index];
  1950.    if (!z) {
  1951.       collision_person1 = scopy->people[real_index].id1;
  1952.       error_message1[0] = '\0';
  1953.       error_message2[0] = '\0';
  1954.       longjmp(longjmp_ptr->the_buf, 6);
  1955.    }
  1956.  
  1957.    return(z);
  1958. }
  1959.  
  1960.  
  1961. extern void clear_people(setup *z)
  1962. {
  1963.    int i;
  1964.  
  1965.    for (i=0; i<MAX_PEOPLE; i++) {
  1966.       z->people[i].id1 = 0;
  1967.       z->people[i].id2 = 0;
  1968.    }
  1969. }
  1970.  
  1971.  
  1972. extern unsigned int rotperson(unsigned int n, int amount)
  1973. {
  1974.    if (n == 0) return(0); else return((n + amount) & ~064);
  1975. }
  1976.  
  1977.  
  1978. extern unsigned int rotcw(unsigned int n)
  1979. {
  1980.    if (n == 0) return(0); else return((n + 011) & ~064);
  1981. }
  1982.  
  1983.  
  1984. extern unsigned int rotccw(unsigned int n)
  1985. {
  1986.    if (n == 0) return(0); else return((n + 033) & ~064);
  1987. }
  1988.  
  1989.  
  1990. extern void clear_person(setup *resultpeople, int resultplace)
  1991. {
  1992.    resultpeople->people[resultplace].id1 = 0;
  1993.    resultpeople->people[resultplace].id2 = 0;
  1994. }
  1995.  
  1996.  
  1997. extern unsigned int copy_person(setup *resultpeople, int resultplace, setup *sourcepeople, int sourceplace)
  1998. {
  1999.    resultpeople->people[resultplace] = sourcepeople->people[sourceplace];
  2000.    return(resultpeople->people[resultplace].id1);
  2001. }
  2002.  
  2003.  
  2004. extern unsigned int copy_rot(setup *resultpeople, int resultplace, setup *sourcepeople, int sourceplace, int rotamount)
  2005. {
  2006.    unsigned int newperson = sourcepeople->people[sourceplace].id1;
  2007.  
  2008.    if (newperson) newperson = (newperson + rotamount) & ~064;
  2009.    resultpeople->people[resultplace].id2 = sourcepeople->people[sourceplace].id2;
  2010.    return(resultpeople->people[resultplace].id1 = newperson);
  2011. }
  2012.  
  2013.  
  2014. extern void swap_people(setup *ss, int oneplace, int otherplace)
  2015. {
  2016.    personrec temp = ss->people[otherplace];
  2017.    ss->people[otherplace] = ss->people[oneplace];
  2018.    ss->people[oneplace] = temp;
  2019. }
  2020.  
  2021.  
  2022. extern void install_person(setup *resultpeople, int resultplace, setup *sourcepeople, int sourceplace)
  2023. {
  2024.    unsigned int newperson = sourcepeople->people[sourceplace].id1;
  2025.  
  2026.    if (resultpeople->people[resultplace].id1 == 0)
  2027.       resultpeople->people[resultplace] = sourcepeople->people[sourceplace];
  2028.    else if (newperson) {
  2029.       collision_person1 = resultpeople->people[resultplace].id1;
  2030.       collision_person2 = newperson;
  2031.       error_message1[0] = '\0';
  2032.       error_message2[0] = '\0';
  2033.       longjmp(longjmp_ptr->the_buf, 3);
  2034.    }
  2035. }
  2036.  
  2037.  
  2038. extern void install_rot(setup *resultpeople, int resultplace, setup *sourcepeople, int sourceplace, int rotamount)
  2039. {
  2040.    unsigned int newperson = sourcepeople->people[sourceplace].id1;
  2041.  
  2042.    if (newperson) {
  2043.       if (resultpeople->people[resultplace].id1 == 0) {
  2044.          resultpeople->people[resultplace].id1 = (newperson + rotamount) & ~064;
  2045.          resultpeople->people[resultplace].id2 = sourcepeople->people[sourceplace].id2;
  2046.       }
  2047.       else {
  2048.          collision_person1 = resultpeople->people[resultplace].id1;
  2049.          collision_person2 = newperson;
  2050.          error_message1[0] = '\0';
  2051.          error_message2[0] = '\0';
  2052.          longjmp(longjmp_ptr->the_buf, 3);
  2053.       }
  2054.    }
  2055. }
  2056.  
  2057.  
  2058. /* Take a concept pointer and scan for all "final" concepts,
  2059.    returning an updated concept pointer and a mask of all such concepts found.
  2060.    "Final" concepts are those that modify the execution of a call but
  2061.    do not cause it to be executed in a virtual or distorted setup.
  2062.    This has a side-effect that is occasionally used:  When it passes over
  2063.    any "magic" or "interlocked" concept, it drops a pointer to where the
  2064.    last such occurred into the external variable "last_magic_diamond". */
  2065.  
  2066. extern parse_block *process_final_concepts(
  2067.    parse_block *cptr,
  2068.    long_boolean check_errors,
  2069.    final_set *final_concepts)
  2070. {
  2071.    parse_block *tptr = cptr;
  2072.  
  2073.    *final_concepts = 0;
  2074.  
  2075.    while (tptr) {
  2076.       final_set bit_to_set = 0;
  2077.  
  2078.       switch (tptr->concept->kind) {
  2079.          case concept_comment:
  2080.             break;               /* Need to skip these. */
  2081.          case concept_triangle:
  2082.             bit_to_set = FINAL__TRIANGLE; break;
  2083.          case concept_magic:
  2084.             last_magic_diamond = tptr;
  2085.             if (check_errors && (*final_concepts & (FINAL__SINGLE | FINAL__DIAMOND)))
  2086.                fail("Modifiers specified in illegal order.");
  2087.             bit_to_set = FINAL__MAGIC; break;
  2088.          case concept_grand:
  2089.             if (check_errors && (*final_concepts & FINAL__SINGLE))
  2090.                fail("Modifiers specified in illegal order.");
  2091.             bit_to_set = FINAL__GRAND; break;
  2092.          case concept_cross:
  2093.             bit_to_set = FINAL__CROSS; break;
  2094.          case concept_single:
  2095.             bit_to_set = FINAL__SINGLE; break;
  2096.          case concept_interlocked:
  2097.             last_magic_diamond = tptr;
  2098.             if (check_errors && (*final_concepts & (FINAL__SINGLE | FINAL__DIAMOND)))
  2099.                fail("Modifiers specified in illegal order.");
  2100.             bit_to_set = FINAL__INTERLOCKED; break;
  2101.          case concept_split:
  2102.             bit_to_set = FINAL__SPLIT; break;
  2103.          case concept_reverse:
  2104.             bit_to_set = FINAL__REVERSE; break;
  2105.          case concept_left:
  2106.             bit_to_set = FINAL__LEFT; break;
  2107.          case concept_12_matrix:
  2108.             bit_to_set = FINAL__12_MATRIX; break;
  2109.          case concept_diamond:
  2110.             if (check_errors && (*final_concepts & FINAL__SINGLE))
  2111.                fail("Modifiers specified in illegal order.");
  2112.             bit_to_set = FINAL__DIAMOND; break;
  2113.          case concept_funny:
  2114.             bit_to_set = FINAL__FUNNY; break;
  2115.          default:
  2116.             goto exit5;
  2117.       }
  2118.  
  2119.       if (check_errors && (*final_concepts & bit_to_set))
  2120.          fail("Redundant call modifier.");
  2121.       *final_concepts |= bit_to_set;
  2122.  
  2123.       tptr = tptr->next;
  2124.    }
  2125.    exit5:
  2126.  
  2127.    return(tptr);
  2128. }
  2129.  
  2130.  
  2131. /* Prepare several setups to be assembled into one, by making them all have
  2132.    the same kind and rotation. */
  2133. extern long_boolean fix_n_results(int arity, setup z[])
  2134. {
  2135.    int i;
  2136.    long_boolean lineflag = FALSE;
  2137.    long_boolean miniflag = FALSE;
  2138.    setup_kind kk = nothing;
  2139.    int rr = -1;
  2140.  
  2141.    /* There are 3 things that make this task nontrivial.  First, some setups could
  2142.       be "nothing", in which case we turn them into the same type of setup as
  2143.       their neighbors, with no people.  Second, some types of "grand working"
  2144.       can leave setups confused about whether they are lines or diamonds,
  2145.       because only the ends/points are occupied.  We turn those setups into
  2146.       whatever matches their more-fully-occupied neighbors.  (If completely in
  2147.       doubt, we opt for 1x4's.)  Third, some 1x4's may have been shrunk to 1x2's.
  2148.       This can happen in some cases of "triple box patch the so-and-so", which lead
  2149.       to triple lines in which the outer lines collapsed from 1x4's to 1x2's while
  2150.       the center line is fully occupied.  In this case we repopulate the outer lines
  2151.       to 1x4's. */
  2152.  
  2153.    for (i=0; i<arity; i++) {
  2154.       if (z[i].kind == s_normal_concentric) {
  2155.          /* We definitely have a problem.  A common way for this to happen is if a concentric call
  2156.             was done and there were no ends, so we don't know what the setup really is.  Example:
  2157.             from normal columns, do a split phantom lines hocus-pocus.  Do we leave space for the
  2158.             phantoms?  Humans would probably say yes because they know where the phantoms went, but
  2159.             this program has no idea in general.  If a call is concentrically executed and the
  2160.             outsides are all phantoms, we don't know what the setup is.  Concentric_move signifies
  2161.             this by creating a "concentric" setup with "nothing" for the outer setup.  So we raise
  2162.             an error that is somewhat descriptive. */
  2163.          if (z[i].outer.skind == nothing)
  2164.             fail("Can't do this: don't know where the phantoms went.");
  2165.          else if (z[i].inner.skind == nothing && z[i].outer.skind == s_1x2) {
  2166.             /* We can fix this up.  Just turn it into a 1x4 with the ends missing.
  2167.             (If a diamond is actually required, that will get fixed up below.)
  2168.             The test case for this is split phantom lines cross to a diamond from 2FL. */
  2169.  
  2170.             z[i].kind = s1x4;
  2171.             z[i].rotation = z[i].outer.srotation;
  2172.             copy_person(&z[i], 0, &z[i], 12);
  2173.             copy_person(&z[i], 2, &z[i], 13);
  2174.             clear_person(&z[i], 1);
  2175.             clear_person(&z[i], 3);
  2176.          }
  2177.          else
  2178.             fail("Don't recognize ending setup for this call.");
  2179.       }
  2180.  
  2181.       if (z[i].kind != nothing) {
  2182.          canonicalize_rotation(&z[i]);
  2183.  
  2184.          if (z[i].kind == s_1x2)
  2185.             miniflag = TRUE;
  2186.          else if ((z[i].kind == s1x4 || z[i].kind == sdmd) && (z[i].people[1].id1 | z[i].people[3].id1) == 0)
  2187.             lineflag = TRUE;
  2188.          else {
  2189.             if (kk == nothing) kk = z[i].kind;
  2190.             if (kk != z[i].kind) goto lose;
  2191.          }
  2192.  
  2193.          if (rr < 0) rr = z[i].rotation;
  2194.          if (rr != z[i].rotation) goto lose;
  2195.       }
  2196.    }
  2197.  
  2198.    if (kk == nothing) {
  2199.       if (lineflag) kk = s1x4;
  2200.       else if (miniflag) kk = s_1x2;
  2201.       else return(TRUE);
  2202.    }
  2203.    
  2204.    /* If something wasn't sure whether it was points of a diamond or
  2205.       ends of a 1x4, that's OK if something else had a clue. */
  2206.    if (lineflag && kk != s1x4 && kk != sdmd) goto lose;
  2207.  
  2208.    /* If something was a 1x2, that's OK if something else was a 1x4. */
  2209.    if (miniflag && kk != s1x4 && kk != s_1x2) goto lose;
  2210.  
  2211.    for (i=0; i<arity; i++) {
  2212.       if (z[i].kind == nothing)
  2213.          clear_people(&z[i]);
  2214.       else if (z[i].kind == s_1x2 && kk == s1x4) {
  2215.          /* We have to expand a 1x2 to the center spots of a 1x4. */
  2216.          (void) copy_person(&z[i], 3, &z[i], 1);
  2217.          clear_person(&z[i], 2);
  2218.          (void) copy_person(&z[i], 1, &z[i], 0);
  2219.          clear_person(&z[i], 0);
  2220.       }
  2221.  
  2222.       z[i].kind = kk;
  2223.       z[i].rotation = rr;
  2224.    }
  2225.  
  2226.    return(FALSE);
  2227.  
  2228.    lose:
  2229.  
  2230.    fail("This is a ridiculously inconsistent shape or orientation changer!!");
  2231.    /* NOTREACHED */
  2232. }
  2233.  
  2234.  
  2235. static void innards(
  2236.    setup *ss,
  2237.    parse_block *parseptr,
  2238.    callspec_block *callspec,
  2239.    final_set final_concepts,
  2240.    map_thing *maps,
  2241.    long_boolean recompute_id,
  2242.    setup *a1,
  2243.    setup *a2,
  2244.    setup *a3,
  2245.    setup *a4,
  2246.    setup *result)
  2247. {
  2248.    int i, r;
  2249.    map_thing *final_map;
  2250.    map_hunk *hunk;
  2251.    setup *x[4];
  2252.    setup z[4];
  2253.  
  2254.    int finalsetupflags = 0;
  2255.    setup_kind kn = maps->inner_kind;
  2256.    int rot = maps->rot;
  2257.    int vert = maps->vert;
  2258.    int arity = maps->arity;
  2259.  
  2260.    clear_people(result);
  2261.    
  2262.    x[0] = a1;
  2263.    x[1] = a2;
  2264.    x[2] = a3;
  2265.    x[3] = a4;
  2266.    
  2267.    for (i=0; i<arity; i++) {
  2268.       /* It is clearly too late to expand the matrix -- that can't be what is wanted. */
  2269.       x[i]->setupflags = (ss->setupflags & ~SETUPFLAG__OFFSET_Z) | SETUPFLAG__DISTORTED | SETUPFLAG__NO_EXPAND_MATRIX;
  2270.       x[i]->kind = kn;
  2271.       x[i]->rotation = 0;
  2272.       if (recompute_id) update_id_bits(x[i]);
  2273.       move(x[i], parseptr, callspec, final_concepts, FALSE, &z[i]);
  2274.       finalsetupflags |= z[i].setupflags;
  2275.    }
  2276.  
  2277.    if (fix_n_results(arity, z)) {
  2278.       result->kind = nothing;
  2279.       return;
  2280.    }
  2281.    
  2282.    /* Set the final setupflags to the OR of everything that happened.
  2283.       The PAR_CONC_END flag doesn't matter --- if the result is a 2x2
  2284.       begin done around the outside, the procedure that called us
  2285.       (basic_move) knows what is happening and will fix that bit. */
  2286.  
  2287.    result->setupflags = finalsetupflags;
  2288.  
  2289.    /* Some maps (the ones used in "triangle peel and trail") do not want the result
  2290.       to be reassembled, so we get out now.  These maps are indicated by arity = 1
  2291.       and map3[1] nonzero. */
  2292.  
  2293.    if ((arity == 1) && (maps->map3[1])) {
  2294.       *result = z[0];
  2295.       goto getout;
  2296.    }
  2297.  
  2298.    /* See if we can put things back with the same map we used before. */
  2299.  
  2300.    if (z[0].kind == kn && (z[0].rotation&3) == 0) {
  2301.       final_map = maps;
  2302.       result->rotation = 0;
  2303.       goto finish;
  2304.    }
  2305.  
  2306.    /* If this is a special map that flips the second setup upside-down, do so. */
  2307.    if (rot == 2) {
  2308.       z[1].rotation += 2;
  2309.       canonicalize_rotation(&z[1]);
  2310.    }
  2311.    else if (rot == 3) {    /* or the first setup */
  2312.       z[0].rotation += 2;
  2313.       canonicalize_rotation(&z[0]);
  2314.    }
  2315.  
  2316.    z[0].rotation += (rot & 1) + vert;
  2317.    z[1].rotation += (rot & 1) + vert;
  2318.    z[2].rotation += (rot & 1) + vert;
  2319.    z[3].rotation += (rot & 1) + vert;
  2320.  
  2321.    /* Do various special things. */
  2322.  
  2323.    switch (maps->map_kind) {
  2324.       case MPKIND__4_QUADRANTS:
  2325.          /* These particular maps misrepresent the rotation of subsetups 2 and 4, so
  2326.             we have to repair things when a shape-changer is called. */
  2327.          z[1].rotation += 2;
  2328.          z[3].rotation += 2;
  2329.          break;
  2330.       case MPKIND__DMD_STUFF:
  2331.          /* These particular maps misrepresent the rotation of subsetup 2, so
  2332.             we have to repair things when a shape-changer is called. */
  2333.          z[1].rotation += 2;
  2334.          break;
  2335.       case MPKIND__O_SPOTS:
  2336.          warn(warn__to_o_spots);
  2337.          break;
  2338.       case MPKIND__X_SPOTS:
  2339.          warn(warn__to_x_spots);
  2340.          break;
  2341.       case MPKIND__NONE:
  2342.          fail("Can't do shape changer with complex line/box/column/diamond identification concept.");
  2343.    }
  2344.  
  2345.    for (i=0; i<arity; i++)
  2346.       canonicalize_rotation(&z[i]);
  2347.  
  2348.    final_map = 0;
  2349.    hunk = map_lists[z[0].kind][arity-1];
  2350.    if (hunk) final_map = (*hunk)[maps->map_kind][(z[0].rotation & 1)];
  2351.  
  2352.    if (z[0].rotation & 2) {
  2353.       if (final_map == &map_s6_trngl) final_map = &map_b6_trngl;
  2354.       else final_map = 0;        /* Raise an error. */
  2355.    }
  2356.  
  2357.    if ((ss->setupflags & SETUPFLAG__OFFSET_Z) && final_map && (maps->map_kind == MPKIND__OFFS_L_HALF || maps->map_kind == MPKIND__OFFS_R_HALF)) {
  2358.       if (final_map->outer_kind == s2x6) warn(warn__check_pgram);
  2359.       else final_map = 0;        /* Raise an error. */
  2360.    }
  2361.  
  2362.    if (!final_map) {
  2363.       if (arity == 1)
  2364.          fail("Don't know how far to re-offset this.");
  2365.       else
  2366.          fail("Can't do shape changer with complex line/box/column/diamond identification concept.");
  2367.    }
  2368.  
  2369.    result->rotation = z[0].rotation;
  2370.    if ((z[0].rotation & 1) && (final_map->rot & 1))
  2371.       result->rotation = 0;
  2372.  
  2373.    result->rotation -= vert;
  2374.  
  2375.    /* For single arity maps, nonzero map3 item means to give warning. */
  2376.    if ((arity == 1) && (final_map->map3[0])) warn(warn__offset_gone);
  2377.    /* For triple arity maps, nonzero map4 item means to give warning. */
  2378.    if ((arity == 3) && (final_map->map4[0])) warn(warn__overlap_gone);
  2379.  
  2380.    /* If this is a special map that expects the second setup to have been flipped upside-down, do so. */
  2381.    if (final_map->rot == 2) {
  2382.       z[1].rotation += 2;
  2383.       canonicalize_rotation(&z[1]);
  2384.    }
  2385.    else if (final_map->rot == 3) {    /* or the first setup */
  2386.       z[0].rotation += 2;
  2387.       canonicalize_rotation(&z[0]);
  2388.    }
  2389.  
  2390.    finish:
  2391.  
  2392.    if (arity != final_map->arity) fail("Confused about number of setups to divide into.");
  2393.  
  2394.    rot = final_map->rot;
  2395.    r = rot * 011;
  2396.  
  2397.    for (i=0; i<=setup_limits[final_map->inner_kind]; i++) {
  2398.       int t;
  2399.  
  2400.       if (rot & 1) {
  2401.          install_rot(result, final_map->map1[i], &z[0], i, r);
  2402.          if (maps->map_kind == MPKIND__4_QUADRANTS) {
  2403.             install_person(result, final_map->map2[i], &z[1], i);
  2404.             install_rot(result, final_map->map3[i], &z[2], i, 011);
  2405.             install_person(result, final_map->map4[i], &z[3], i);
  2406.          }
  2407.          else if (maps->map_kind == MPKIND__DMD_STUFF) {
  2408.             install_person(result, final_map->map2[i], &z[1], i);
  2409.          }
  2410.          else {
  2411.             if (final_map->arity >= 2) install_rot(result, final_map->map2[i], &z[1], i, 011);
  2412.             if (final_map->arity >= 3) install_rot(result, final_map->map3[i], &z[2], i, 011);
  2413.             if (final_map->arity == 4) install_rot(result, final_map->map4[i], &z[3], i, 011);
  2414.          }
  2415.       }
  2416.       else {
  2417.          t = final_map->map1[i];
  2418.  
  2419.          if (t >= 0)
  2420.             install_person(result, t, &z[0], i);
  2421.          else if (z[0].people[i].id1 & BIT_PERSON)
  2422.             fail("This would go into an excessively large matrix.");
  2423.  
  2424.          if (maps->map_kind == MPKIND__4_QUADRANTS) {
  2425.             install_rot(result, final_map->map2[i], &z[1], i, 011);
  2426.             install_person(result, final_map->map3[i], &z[2], i);
  2427.             install_rot(result, final_map->map4[i], &z[3], i, 011);
  2428.          }
  2429.          else if (maps->map_kind == MPKIND__DMD_STUFF) {
  2430.             install_rot(result, final_map->map2[i], &z[1], i, 011);
  2431.          }
  2432.          else {
  2433.             if (final_map->arity >= 2) {
  2434.                t = final_map->map2[i];
  2435.    
  2436.                if (t >= 0)
  2437.                   install_rot(result, t, &z[1], i, r);
  2438.                else if (z[1].people[i].id1 & BIT_PERSON)
  2439.                   fail("This would go into an excessively large matrix.");
  2440.             }
  2441.    
  2442.             if (final_map->arity >= 3) {
  2443.                t = final_map->map3[i];
  2444.       
  2445.                if (t >= 0)
  2446.                   install_person(result, t, &z[2], i);
  2447.                else if (z[2].people[i].id1 & BIT_PERSON)
  2448.                   fail("This would go into an excessively large matrix.");
  2449.             }
  2450.    
  2451.             if (final_map->arity == 4) {
  2452.                t = final_map->map4[i];
  2453.       
  2454.                if (t >= 0)
  2455.                   install_person(result, t, &z[3], i);
  2456.                else if (z[3].people[i].id1 & BIT_PERSON)
  2457.                   fail("This would go into an excessively large matrix.");
  2458.             }
  2459.          }
  2460.       }
  2461.    }
  2462.  
  2463.    result->kind = final_map->outer_kind;
  2464.  
  2465.    getout:
  2466.  
  2467.    canonicalize_rotation(result);
  2468.    reinstate_rotation(ss, result);
  2469. }
  2470.  
  2471.  
  2472. extern void divided_setup_move(
  2473.    setup *ss,
  2474.    parse_block *parseptr,
  2475.    callspec_block *callspec,
  2476.    final_set final_concepts,
  2477.    map_thing *maps,
  2478.    phantest_kind phancontrol,
  2479.    long_boolean recompute_id,
  2480.    setup *result)
  2481. {
  2482.    int i, mm, v1flag, v2flag, v3flag, v4flag;
  2483.    setup a1, a2, a3, a4;
  2484.  
  2485.    setup_kind kn = maps->inner_kind;
  2486.    int rot = maps->rot;
  2487.    int arity = maps->arity;
  2488.    
  2489.    v1flag = 0;
  2490.    v2flag = 0;
  2491.    v3flag = 0;
  2492.    v4flag = 0;
  2493.  
  2494.    for (i=0; i<=setup_limits[kn]; i++) {
  2495.       setup tstuff;
  2496.       clear_people(&tstuff);
  2497.  
  2498.       mm = maps->map1[i];
  2499.       if (mm >= 0)
  2500.          tstuff.people[0] = ss->people[mm];
  2501.       v1flag |= tstuff.people[0].id1;
  2502.  
  2503.       if (arity >= 2) {
  2504.          mm = maps->map2[i];
  2505.          if (mm >= 0)
  2506.             tstuff.people[1] = ss->people[mm];
  2507.          v2flag |= tstuff.people[1].id1;
  2508.       }
  2509.  
  2510.       if (arity >= 3) {
  2511.          mm = maps->map3[i];
  2512.          if (mm >= 0)
  2513.             tstuff.people[2] = ss->people[mm];
  2514.          v3flag |= tstuff.people[2].id1;
  2515.       }
  2516.  
  2517.       if (arity == 4) {
  2518.          mm = maps->map4[i];
  2519.          if (mm >= 0)
  2520.             tstuff.people[3] = ss->people[mm];
  2521.          v4flag |= tstuff.people[3].id1;
  2522.       }
  2523.  
  2524.       if (rot & 1) {
  2525.          /* Rotation is odd.  3 is a special case. */
  2526.          (void) copy_rot(&a1, i, &tstuff, 0, (rot==3 ? 011 : 033));
  2527.          if (maps->map_kind == MPKIND__4_QUADRANTS) {
  2528.             (void) copy_person(&a2, i, &tstuff, 1);
  2529.             (void) copy_rot(&a3, i, &tstuff, 2, 033);
  2530.             (void) copy_person(&a4, i, &tstuff, 3);
  2531.          }
  2532.          else if (maps->map_kind == MPKIND__DMD_STUFF) {
  2533.             (void) copy_person(&a2, i, &tstuff, 1);
  2534.          }
  2535.          else {
  2536.             if (arity >= 2) (void) copy_rot(&a2, i, &tstuff, 1, 033);
  2537.             if (arity >= 3) (void) copy_rot(&a3, i, &tstuff, 2, 033);
  2538.             if (arity == 4) (void) copy_rot(&a4, i, &tstuff, 3, 033);
  2539.          }
  2540.       }
  2541.       else {
  2542.          /* Rotation is even.  2 is a special case. */
  2543.          (void) copy_person(&a1, i, &tstuff, 0);
  2544.          if (maps->map_kind == MPKIND__4_QUADRANTS) {
  2545.             (void) copy_rot(&a2, i, &tstuff, 1, 033);
  2546.             (void) copy_person(&a3, i, &tstuff, 2);
  2547.             (void) copy_rot(&a4, i, &tstuff, 3, 033);
  2548.          }
  2549.          else if (maps->map_kind == MPKIND__DMD_STUFF) {
  2550.             (void) copy_rot(&a2, i, &tstuff, 1, 033);
  2551.          }
  2552.          else {
  2553.             if (arity >= 2) {
  2554.                if (rot == 2) {
  2555.                   (void) copy_rot(&a2, i, &tstuff, 1, 022);
  2556.                }
  2557.                else {
  2558.                   (void) copy_person(&a2, i, &tstuff, 1);
  2559.                }
  2560.             }
  2561.             if (arity >= 3) (void) copy_person(&a3, i, &tstuff, 2);
  2562.             if (arity == 4) (void) copy_person(&a4, i, &tstuff, 3);
  2563.          }
  2564.       }
  2565.    }
  2566.  
  2567.    switch (phancontrol) {
  2568.       case phantest_impossible:
  2569.          if (!(v1flag && v2flag))
  2570.             fail("This is impossible in a symmetric setup!!!!");
  2571.          break;
  2572.       case phantest_both:
  2573.          if (!(v1flag && v2flag))
  2574.             /* Only one of the two setups is occupied. */
  2575.             fail("Don't use phantom concept if you don't mean it.");
  2576.          break;
  2577.       case phantest_only_one:
  2578.          if (v1flag && v2flag) fail("Can't find the setup to work in.");
  2579.          break;
  2580.       case phantest_only_first_one:
  2581.          if (v2flag) fail("Not in correct setup.");
  2582.          break;
  2583.       case phantest_only_second_one:
  2584.          if (v1flag) fail("Not in correct setup.");
  2585.          break;
  2586.       case phantest_first_or_both:
  2587.          if (!v1flag)
  2588.             fail("Don't use phantom concept if you don't mean it.");
  2589.          break;
  2590.       case phantest_2x2_both:
  2591.          /* Test for "C1" blocks. */
  2592.          if (!((v1flag | v3flag) && (v2flag | v4flag)))
  2593.             fail("Don't use phantom concept if you don't mean it.");
  2594.          break;
  2595.       case phantest_not_just_centers:
  2596.          if (!(v1flag && v3flag))
  2597.             fail("Don't use phantom concept if you don't mean it.");
  2598.          break;
  2599.       case phantest_2x2_only_two:
  2600.          /* Test for NOT "C1" blocks. */
  2601.          if ((v1flag | v3flag) && (v2flag | v4flag)) fail("Not in blocks.");
  2602.          break;
  2603.    }
  2604.  
  2605.    innards(ss, parseptr, callspec,
  2606.       final_concepts, maps, recompute_id,
  2607.       &a1, &a2, &a3, &a4, result);
  2608. }
  2609.  
  2610.  
  2611. extern void overlapped_setup_move(setup *s, map_thing *maps,
  2612.    int m1, int m2, int m3, parse_block *parseptr, setup *result)
  2613. {
  2614.    int i, j;
  2615.    setup a1, a2, a3;
  2616.  
  2617.    setup_kind kn = maps->inner_kind;
  2618.    int rot = maps->rot;
  2619.    int arity = maps->arity;
  2620.  
  2621.    if (arity >= 4) fail("Can't handle this many overlapped setups.");
  2622.  
  2623.    for (i=0, j=1; i<=setup_limits[kn]; i++, j<<=1) {
  2624.       setup tstuff;
  2625.  
  2626.       tstuff.people[0] = s->people[maps->map1[i]];
  2627.       if (arity >= 2) tstuff.people[1] = s->people[maps->map2[i]];
  2628.       if (arity == 3) tstuff.people[2] = s->people[maps->map3[i]];
  2629.  
  2630.       if (rot & 1) {
  2631.          /* Rotation is odd.  3 is a special case. */
  2632.          if (rot == 3) tstuff.people[0].id1 = rotcw(tstuff.people[0].id1); else tstuff.people[0].id1 = rotccw(tstuff.people[0].id1);
  2633.          if (arity >= 2) tstuff.people[1].id1 = rotccw(tstuff.people[1].id1);
  2634.          if (arity == 3) tstuff.people[2].id1 = rotccw(tstuff.people[2].id1);
  2635.       }
  2636.       else {
  2637.          /* Rotation is even.  2 is a special case. */
  2638.          if (rot == 2) tstuff.people[1].id1 = rotperson(tstuff.people[1].id1, 022);
  2639.       }
  2640.  
  2641.       if (j & m1)
  2642.          (void) copy_person(&a1, i, &tstuff, 0);
  2643.       else
  2644.          clear_person(&a1, i);
  2645.  
  2646.       if (arity >= 2) {
  2647.          if (j & m2)
  2648.             (void) copy_person(&a2, i, &tstuff, 1);
  2649.          else
  2650.             clear_person(&a2, i);
  2651.       }
  2652.  
  2653.       if (arity >= 3) {
  2654.          if (j & m3)
  2655.             (void) copy_person(&a3, i, &tstuff, 2);
  2656.          else
  2657.             clear_person(&a3, i);
  2658.       }
  2659.    }
  2660.  
  2661.    innards(s, parseptr, NULLCALLSPEC, 0, maps,
  2662.       FALSE, &a1, &a2, &a3, &a3, result);
  2663. /* Note: we pass garbage    ^^^   for a4. */
  2664.  
  2665. }
  2666.