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 / sdtop.c < prev    next >
C/C++ Source or Header  |  1992-12-02  |  45KB  |  1,030 lines

  1. /* SD -- square dance caller's helper.
  2.  
  3.     Copyright (C) 1990, 1991, 1992  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.    update_id_bits
  23.    touch_or_rear_back
  24.    do_matrix_expansion
  25.    normalize_setup
  26.    toplevelmove
  27. */
  28.  
  29. #include "sd.h"
  30.  
  31. typedef struct {
  32.    short source_indices[16];
  33.    int size;
  34.    setup_kind inner_kind;
  35.    setup_kind outer_kind;
  36.    int rot;
  37.    } expand_thing;
  38.  
  39. typedef struct {
  40.    int warning;
  41.    int forbidden_elongation;
  42.    expand_thing *expand_lists;
  43.    } full_expand_thing;
  44.  
  45. static expand_thing exp_1x8_4dm_stuff   = {{12, 13, 15, 14, 4, 5, 7, 6}, 8, s1x8, s_4dmd, 0};
  46. static expand_thing exp_qtg_4dm_stuff   = {{1, 2, 6, 7, 9, 10, 14, 15}, 8, nothing, s_4dmd, 0};
  47. static expand_thing exp_3x1d_3d_stuff   = {{9, 10, 11, 1, 3, 4, 5, 7}, 8, s_3x1dmd, s_3dmd, 0};
  48. static expand_thing exp_4x4_4dm_stuff_a = {{0, 1, 2, 14, 3, 5, 4, 7, 8, 9, 10, 6, 11, 13, 12, 15}, 16, nothing, s_4dmd, 1};
  49. static expand_thing exp_4x4_4dm_stuff_b = {{3, 4, 5, 6, 8, 9, 10, 7, 11, 12, 13, 14, 0, 1, 2, 15}, 16, nothing, s_4dmd, 0};
  50. static expand_thing exp_2x4_2x6_stuff   = {{1, 2, 3, 4, 7, 8, 9, 10}, 8, s2x4, s2x6, 0};
  51. static expand_thing exp_qtg_3x4_stuff   = {{1, 2, 4, 5, 7, 8, 10, 11}, 8, nothing, s3x4, 0};
  52. static expand_thing exp_2x6_2x8_stuff   = {{1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14}, 12, s2x6, s2x8, 0};
  53. static expand_thing exp_1x8_1x12_stuff  = {{2, 3, 5, 4, 8, 9, 11, 10}, 8, nothing, s1x12, 0};
  54. static expand_thing exp_1x10_1x12_stuff = {{1, 2, 3, 4, 5, 7, 8, 9, 10, 11}, 10, s1x10, s1x12, 0};
  55. static expand_thing exp_1x12_1x14_stuff = {{1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13}, 12, s1x12, s1x14, 0};
  56. static expand_thing exp_1x14_1x16_stuff = {{1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15}, 14, s1x14, s1x16, 0};
  57. static expand_thing exp_1x8_1x10_stuff = {{1, 2, 4, 3, 6, 7, 9, 8}, 8, s1x8, s1x10, 0};
  58. static expand_thing exp_2x6_4x6_stuff   = {{11, 10, 9, 8, 7, 6, 23, 22, 21, 20, 19, 18}, 12, nothing, s4x6, 0};
  59. static expand_thing exp_2x4_2x8_stuff   = {{2, 3, 4, 5, 10, 11, 12, 13}, 8, nothing, s2x8, 0};
  60. static expand_thing exp_2x4_4x4_stuff   = {{10, 15, 3, 1, 2, 7, 11, 9}, 8, s2x4, s4x4, 0};
  61. static expand_thing exp_4x4_blob_stuff  = {{3, 4, 8, 5, 9, 10, 14, 11, 15, 16, 20, 17, 21, 22, 2, 23}, 16, nothing, s_bigblob, 0};
  62.  
  63.  
  64.  
  65. static void compress_setup(expand_thing *thing, setup *stuff)
  66. {
  67.    int i;
  68.    setup temp = *stuff;
  69.  
  70.    stuff->kind = thing->inner_kind;
  71.    for (i=0; i<thing->size; i++) {
  72.       (void) copy_person(stuff, i, &temp, thing->source_indices[i]);
  73.    }
  74. }
  75.  
  76.  
  77.  
  78.  
  79. static int bit_table_2x2[][4] = {
  80.    {ID2_LEAD|ID2_BEAU,     ID2_TRAILER|ID2_BEAU,  ID2_TRAILER|ID2_BELLE, ID2_LEAD|ID2_BELLE},
  81.    {ID2_LEAD|ID2_BELLE,    ID2_LEAD|ID2_BEAU,     ID2_TRAILER|ID2_BEAU,  ID2_TRAILER|ID2_BELLE},
  82.    {ID2_TRAILER|ID2_BELLE, ID2_LEAD|ID2_BELLE,    ID2_LEAD|ID2_BEAU,     ID2_TRAILER|ID2_BEAU},
  83.    {ID2_TRAILER|ID2_BEAU,  ID2_TRAILER|ID2_BELLE, ID2_LEAD|ID2_BELLE,    ID2_LEAD|ID2_BEAU}};
  84.  
  85. static int bit_table_2x4[][4] = {
  86.    {ID2_LEAD|ID2_BEAU|ID2_END,        ID2_TRAILER|ID2_BEAU|ID2_END,     ID2_TRAILER|ID2_BELLE|ID2_END,    ID2_LEAD|ID2_BELLE|ID2_END},
  87.    {ID2_LEAD|ID2_BELLE|ID2_CENTER,    ID2_LEAD|ID2_BEAU|ID2_CENTER,     ID2_TRAILER|ID2_BEAU|ID2_CENTER,  ID2_TRAILER|ID2_BELLE|ID2_CENTER},
  88.    {ID2_LEAD|ID2_BEAU|ID2_CENTER,     ID2_TRAILER|ID2_BEAU|ID2_CENTER,  ID2_TRAILER|ID2_BELLE|ID2_CENTER, ID2_LEAD|ID2_BELLE|ID2_CENTER},
  89.    {ID2_LEAD|ID2_BELLE|ID2_END,       ID2_LEAD|ID2_BEAU|ID2_END,        ID2_TRAILER|ID2_BEAU|ID2_END,     ID2_TRAILER|ID2_BELLE|ID2_END},
  90.    {ID2_TRAILER|ID2_BELLE|ID2_END,    ID2_LEAD|ID2_BELLE|ID2_END,       ID2_LEAD|ID2_BEAU|ID2_END,        ID2_TRAILER|ID2_BEAU|ID2_END},
  91.    {ID2_TRAILER|ID2_BEAU|ID2_CENTER,  ID2_TRAILER|ID2_BELLE|ID2_CENTER, ID2_LEAD|ID2_BELLE|ID2_CENTER,    ID2_LEAD|ID2_BEAU|ID2_CENTER},
  92.    {ID2_TRAILER|ID2_BELLE|ID2_CENTER, ID2_LEAD|ID2_BELLE|ID2_CENTER,    ID2_LEAD|ID2_BEAU|ID2_CENTER,     ID2_TRAILER|ID2_BEAU|ID2_CENTER},
  93.    {ID2_TRAILER|ID2_BEAU|ID2_END,     ID2_TRAILER|ID2_BELLE|ID2_END,    ID2_LEAD|ID2_BELLE|ID2_END,       ID2_LEAD|ID2_BEAU|ID2_END}};
  94.  
  95. static int bit_table_1x2[][4] = {
  96.    {ID2_BEAU,              ID2_TRAILER,           ID2_BELLE,             ID2_LEAD},
  97.    {ID2_BELLE,             ID2_LEAD,              ID2_BEAU,              ID2_TRAILER}};
  98.  
  99. static int bit_table_1x4[][4] = {
  100.    {ID2_BEAU|ID2_END,        ID2_TRAILER|ID2_END,      ID2_BELLE|ID2_END,       ID2_LEAD|ID2_END},
  101.    {ID2_BELLE|ID2_CENTER,    ID2_LEAD|ID2_CENTER,      ID2_BEAU|ID2_CENTER,     ID2_TRAILER|ID2_CENTER},
  102.    {ID2_BELLE|ID2_END,       ID2_LEAD|ID2_END,         ID2_BEAU|ID2_END,        ID2_TRAILER|ID2_END},
  103.    {ID2_BEAU|ID2_CENTER,     ID2_TRAILER|ID2_CENTER,   ID2_BELLE|ID2_CENTER,    ID2_LEAD|ID2_CENTER}};
  104.  
  105. static int bit_table_1x8[][4] = {
  106.    {ID2_BEAU|ID2_OUTR6|ID2_OUTR2,   ID2_TRAILER|ID2_OUTR6|ID2_OUTR2, ID2_BELLE|ID2_OUTR6|ID2_OUTR2,  ID2_LEAD|ID2_OUTR6|ID2_OUTR2},
  107.    {ID2_BELLE|ID2_OUTR6|ID2_CTR6,   ID2_LEAD|ID2_OUTR6|ID2_CTR6,     ID2_BEAU|ID2_OUTR6|ID2_CTR6,    ID2_TRAILER|ID2_OUTR6|ID2_CTR6},
  108.    {ID2_BELLE|ID2_CTR2|ID2_CTR6,    ID2_LEAD|ID2_CTR2|ID2_CTR6,      ID2_BEAU|ID2_CTR2|ID2_CTR6,     ID2_TRAILER|ID2_CTR2|ID2_CTR6},
  109.    {ID2_BEAU|ID2_OUTR6|ID2_CTR6,    ID2_TRAILER|ID2_OUTR6|ID2_CTR6,  ID2_BELLE|ID2_OUTR6|ID2_CTR6,   ID2_LEAD|ID2_OUTR6|ID2_CTR6},
  110.    {ID2_BELLE|ID2_OUTR6|ID2_OUTR2,  ID2_LEAD|ID2_OUTR6|ID2_OUTR2,    ID2_BEAU|ID2_OUTR6|ID2_OUTR2,   ID2_TRAILER|ID2_OUTR6|ID2_OUTR2},
  111.    {ID2_BEAU|ID2_OUTR6|ID2_CTR6,    ID2_TRAILER|ID2_OUTR6|ID2_CTR6,  ID2_BELLE|ID2_OUTR6|ID2_CTR6,   ID2_LEAD|ID2_OUTR6|ID2_CTR6},
  112.    {ID2_BEAU|ID2_CTR2|ID2_CTR6,     ID2_TRAILER|ID2_CTR2|ID2_CTR6,   ID2_BELLE|ID2_CTR2|ID2_CTR6,    ID2_LEAD|ID2_CTR2|ID2_CTR6},
  113.    {ID2_BELLE|ID2_OUTR6|ID2_CTR6,   ID2_LEAD|ID2_OUTR6|ID2_CTR6,     ID2_BEAU|ID2_OUTR6|ID2_CTR6,    ID2_TRAILER|ID2_OUTR6|ID2_CTR6}};
  114.  
  115. static int bit_table_qtag[][4] = {
  116.    {ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6},
  117.    {ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6},
  118.    {ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6},
  119.    {ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2},
  120.    {ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6},
  121.    {ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6},
  122.    {ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6},
  123.    {ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2}};
  124.  
  125. static int bit_table_hrglass[][4] = {
  126.    {ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6},
  127.    {ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6},
  128.    {ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6},
  129.    {ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2},
  130.    {ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6},
  131.    {ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6,    ID2_END|ID2_OUTR6},
  132.    {ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6, ID2_CENTER|ID2_OUTR6},
  133.    {ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2,  ID2_CENTER|ID2_CTR2}};
  134.  
  135. static int bit_table_spindle[][4] = {
  136.    {ID2_CTR6,    ID2_CTR6,   ID2_CTR6,   ID2_CTR6},
  137.    {ID2_CTR6,    ID2_CTR6,   ID2_CTR6,   ID2_CTR6},
  138.    {ID2_CTR6,    ID2_CTR6,   ID2_CTR6,   ID2_CTR6},
  139.    {ID2_OUTR2,   ID2_OUTR2,  ID2_OUTR2,  ID2_OUTR2},
  140.    {ID2_CTR6,    ID2_CTR6,   ID2_CTR6,   ID2_CTR6},
  141.    {ID2_CTR6,    ID2_CTR6,   ID2_CTR6,   ID2_CTR6},
  142.    {ID2_CTR6,    ID2_CTR6,   ID2_CTR6,   ID2_CTR6},
  143.    {ID2_OUTR2,   ID2_OUTR2,  ID2_OUTR2,  ID2_OUTR2}};
  144.  
  145. #define BITS_TO_CLEAR (ID2_LEAD|ID2_TRAILER|ID2_BEAU|ID2_BELLE|ID2_CENTER|ID2_END|ID2_CTR2|ID2_CTR6|ID2_OUTR2|ID2_OUTR6)
  146. #define UNSYM_BITS_TO_CLEAR (ID2_NEARCOL|ID2_NEARLINE|ID2_NEARBOX|ID2_FARCOL|ID2_FARLINE|ID2_FARBOX)
  147.  
  148.  
  149.  
  150.  
  151. typedef int bit_table[4];
  152.  
  153. extern void update_id_bits(setup *ss)
  154.  
  155. {
  156.    int i, j;
  157.    bit_table *ptr;
  158.  
  159.    for (i=0; i<MAX_PEOPLE; i++) ss->people[i].id2 &= ~BITS_TO_CLEAR;
  160.  
  161.    switch (ss->kind) {
  162.       case s_1x2:
  163.          ptr = bit_table_1x2; break;
  164.       case s1x4:
  165.          ptr = bit_table_1x4; break;
  166.       case s2x2:
  167.          ptr = bit_table_2x2; break;
  168.       case s2x4:
  169.          ptr = bit_table_2x4; break;
  170.       case s1x8:
  171.          ptr = bit_table_1x8; break;
  172.       case s_qtag:
  173.          ptr = bit_table_qtag; break;
  174.       case s_hrglass:
  175.          ptr = bit_table_hrglass; break;
  176.       case s_spindle:
  177.          ptr = bit_table_spindle; break;
  178.       default:
  179.          return;
  180.    }
  181.  
  182.    j = setup_limits[ss->kind];
  183.    for (i=0; i<=j; i++) {
  184.       if (ss->people[i].id1 & BIT_PERSON)
  185.          ss->people[i].id2 |= ptr[i][ss->people[i].id1 & 3];
  186.    }
  187. }
  188.  
  189.  
  190. static expand_thing rear_wave_stuff = {{3, 0, 1, 2}, 4, nothing, s2x2, 0};
  191. static expand_thing rear_bone_stuff = {{0, 3, 2, 5, 4, 7, 6, 1}, 8, nothing, s2x4, 0};
  192. static expand_thing rear_wing_stuff = {{1, 2, 3, 4, 5, 6, 7, 0}, 8, nothing, s2x4, 0};
  193. static expand_thing rear_c1a_stuff = {{0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1, 7, -1}, 16, nothing, s2x4, 0};
  194. static expand_thing rear_c1b_stuff = {{-1, 0, -1, 1, -1, 3, -1, 2, -1, 4, -1, 5, -1, 7, -1, 6}, 16, nothing, s2x4, 0};
  195. static expand_thing rear_c1c_stuff = {{6, -1, 7, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1}, 16, nothing, s2x4, 1};
  196. static expand_thing rear_c1d_stuff = {{-1, 7, -1, 6, -1, 0, -1, 1, -1, 3, -1, 2, -1, 4, -1, 5}, 16, nothing, s2x4, 1};
  197. static expand_thing rear_miniwave_stuff = {{1, 0}, 2, nothing, s_1x2, 1};
  198. static expand_thing rear_2x4_stuff = {{6, 7, 1, 0, 2, 3, 5, 4}, 8, nothing, s2x4, 1};
  199. static expand_thing rear_col_stuff = {{0, 3, 6, 5, 4, 7, 2, 1}, 8, nothing, s1x8, 0};
  200. static expand_thing rear_vrbox_stuff = {{1, 0, 3, 2}, 4, nothing, s1x4, 1};
  201. static expand_thing rear_hrbox_stuff = {{0, 3, 2, 1}, 4, nothing, s1x4, 0};
  202. static expand_thing rear_gwave_stuff = {{7, 0, 1, 6, 3, 4, 5, 2}, 8, nothing, s2x4, 0};
  203. static expand_thing rear_qtag_stuff = {{7, 0, 1, 2, 3, 4, 5, 6}, 8, nothing, s2x4, 1};
  204. static expand_thing rear_sqtag_stuff = {{0, 1, 2, 3}, 4, nothing, s1x4, 0};
  205.  
  206. static full_expand_thing rear_wave_pair     = {warn__rear_back,       0, &rear_wave_stuff};
  207. static full_expand_thing rear_bone_pair     = {warn__some_rear_back,  0, &rear_bone_stuff};
  208. static full_expand_thing rear_wing_pair     = {warn__some_rear_back,  0, &rear_wing_stuff};
  209. static full_expand_thing rear_c1a_pair      = {warn__some_rear_back,  0, &rear_c1a_stuff};
  210. static full_expand_thing rear_c1b_pair      = {warn__some_rear_back,  0, &rear_c1b_stuff};
  211. static full_expand_thing rear_c1c_pair      = {warn__some_rear_back,  0, &rear_c1c_stuff};
  212. static full_expand_thing rear_c1d_pair      = {warn__some_rear_back,  0, &rear_c1d_stuff};
  213. static full_expand_thing rear_miniwave_pair = {warn__rear_back,       0, &rear_miniwave_stuff};
  214. static full_expand_thing rear_2x4_pair      = {warn__rear_back,       0, &rear_2x4_stuff};
  215. static full_expand_thing rear_col_pair      = {warn__awful_rear_back, 0, &rear_col_stuff};
  216. static full_expand_thing rear_vrbox_pair    = {warn__awful_rear_back, 0, &rear_vrbox_stuff};
  217. static full_expand_thing rear_hrbox_pair    = {warn__awful_rear_back, 0, &rear_hrbox_stuff};
  218. static full_expand_thing rear_gwave_pair    = {warn__rear_back,       0, &rear_gwave_stuff};
  219. static full_expand_thing rear_qtag_pair     = {warn__rear_back,       0, &rear_qtag_stuff};
  220. static full_expand_thing rear_sqtag_pair    = {warn__awful_rear_back, 0, &rear_sqtag_stuff};
  221.  
  222. static expand_thing step_1x8_stuff = {{0, 7, 6, 1, 4, 3, 2, 5}, 8, nothing, s2x4, 0};
  223. static expand_thing step_1x4_side_stuff = {{0, 1, 2, 3}, 4, nothing, sdmd, 0};
  224. static expand_thing step_1x4_stuff = {{0, 3, 2, 1}, 4, nothing, s2x2, 0};
  225. static expand_thing step_1x2_stuff = {{0, 1}, 2, nothing, s_1x2, 1};
  226. static expand_thing step_2x2v_stuff = {{1, 2, 3, 0}, 4, nothing, s1x4, 0};
  227. static expand_thing step_2x2h_stuff = {{0, 1, 2, 3}, 4, nothing, s1x4, 1};
  228. static expand_thing step_8ch_stuff = {{7, 6, 0, 1, 3, 2, 4, 5}, 8, nothing, s2x4, 1};
  229. static expand_thing step_li_stuff = {{1, 2, 7, 4, 5, 6, 3, 0}, 8, nothing, s1x8, 0};
  230. static expand_thing step_tby_stuff = {{5, 6, 7, 0, 1, 2, 3, 4}, 8, nothing, s_qtag, 1};
  231.  
  232. static full_expand_thing step_1x8_pair =      {0, 0, &step_1x8_stuff};
  233. static full_expand_thing step_1x4_side_pair = {0, 0, &step_1x4_side_stuff};
  234. static full_expand_thing step_1x4_pair =      {0, 0, &step_1x4_stuff};
  235. static full_expand_thing step_2x2v_pair =     {0, 2*SETUPFLAG__ELONGATE_BIT, &step_2x2v_stuff};
  236. static full_expand_thing step_2x2h_pair =     {0, 1*SETUPFLAG__ELONGATE_BIT, &step_2x2h_stuff};
  237. static full_expand_thing step_8ch_pair =      {0, 0, &step_8ch_stuff};
  238. static full_expand_thing step_li_pair =       {0, 0, &step_li_stuff};
  239. static full_expand_thing step_tby_pair =      {0, 0, &step_tby_stuff};
  240. static full_expand_thing step_1x2_pair =      {0, 0, &step_1x2_stuff};
  241.  
  242.  
  243.  
  244. extern void touch_or_rear_back(
  245.    setup *scopy,
  246.    int callflags)
  247.  
  248. {
  249.    int i, j;
  250.    setup stemp;
  251.    full_expand_thing *tptr;
  252.    expand_thing *zptr;
  253.    int directions, livemask;
  254.  
  255.    directions = 0;
  256.    livemask = 0;
  257.    tptr = 0;
  258.  
  259.    for (i=0, j=1; i<=setup_limits[scopy->kind]; i++, j<<=1) {
  260.       int p = scopy->people[i].id1;
  261.       directions = (directions<<2) | (p&3);
  262.       if (p) livemask |= j;
  263.    }
  264.  
  265.    if (callflags & cflag__rear_back_from_r_wave) {
  266.       if (scopy->kind == s1x4 && (livemask == 0xF) && (directions == 0x28)) {
  267.          tptr = &rear_wave_pair;          /* Rear back from a wave to facing couples. */
  268.       }
  269.       else if (scopy->kind == s_1x2 && (livemask == 0x3) && (directions == 0x2)) {
  270.          tptr = &rear_miniwave_pair;      /* Rear back from a miniwave to facing people. */
  271.       }
  272.       else if (scopy->kind == s2x4) {
  273.          if ((livemask == 0xFF) && (directions == 0x2288)) {
  274.             tptr = &rear_2x4_pair;        /* Rear back from parallel waves to an 8 chain. */
  275.          }
  276.          else if ((livemask == 0xFF) && (directions == 0x55FF)) {
  277.             tptr = &rear_col_pair;        /* Rear back from columns to end-to-end single 8-chains. */
  278.          }
  279.       }
  280.       else if (scopy->kind == s2x2) {
  281.          if ((livemask == 0xF) && (directions == 0x28)) {
  282.             tptr = &rear_vrbox_pair;      /* Rear back from a right-hand box to a single 8 chain. */
  283.          }
  284.          else if ((livemask == 0xF) && (directions == 0x5F)) {
  285.             tptr = &rear_hrbox_pair;      /* Rear back from a right-hand box to a single 8 chain. */
  286.          }
  287.       }
  288.       else if (scopy->kind == s1x8 && (livemask == 0xFF) && (directions == 0x2882)) {
  289.          tptr = &rear_gwave_pair;         /* Rear back from a grand wave to facing lines. */
  290.       }
  291.       else if (scopy->kind == s_bone && livemask == 0xFF && ((directions == 0xA802) || (directions == 0x78D2))) {
  292.          /* Centers rear back from a "bone" to lines facing or "split square thru" setup. */
  293.          tptr = &rear_bone_pair;
  294.       }
  295.       else if (scopy->kind == s_rigger && livemask == 0xFF && ((directions == 0xA802) || (directions == 0xD872))) {
  296.          /* Ends rear back from a "wing" to lines facing or "split square thru" setup. */
  297.          tptr = &rear_wing_pair;
  298.       }
  299.       else if (scopy->kind == s_c1phan) {
  300.          /* Check for certain people rearing back from C1 phantoms. */
  301.          if ((livemask == 0x5555) && ((directions == 0x884C00C4) || (directions == 0x4C4CC4C4))) {
  302.             tptr = &rear_c1a_pair;
  303.          }
  304.          else if ((livemask == 0xAAAA) && ((directions == 0x13223100) || (directions == 0x13313113))) {
  305.             tptr = &rear_c1b_pair;
  306.          }
  307.          else if ((livemask == 0x5555) && ((directions == 0x08CC8044) || (directions == 0x08808008))) {
  308.             tptr = &rear_c1c_pair;
  309.          }
  310.          else if ((livemask == 0xAAAA) && ((directions == 0x11203302) || (directions == 0x20200202))) {
  311.             tptr = &rear_c1d_pair;
  312.          }
  313.       }
  314.    }
  315.    else if (callflags & cflag__rear_back_from_qtag) {
  316.       if (scopy->kind == s_qtag && livemask == 0xFF && ((directions == 0x08A2) || (directions == 0xA802))) {
  317.          tptr = &rear_qtag_pair;         /* Have the centers rear back from a 1/4 tag or 3/4 tag. */
  318.       }
  319.       else if (scopy->kind == sdmd && livemask == 0xF && ((directions == 0x5F) || (directions == 0xD7))) {
  320.          tptr = &rear_sqtag_pair;         /* Have the centers rear back from a single 1/4 tag or 3/4 tag. */
  321.       }
  322.    }
  323.    else {      /* We know that (callflags & cflag__step_to_wave) is true here. */
  324.       switch (scopy->kind) {
  325.          case s2x2:
  326.             if ((livemask == 0xF) && (directions == 0x7D)) {
  327.                tptr = &step_2x2h_pair;
  328.             }
  329.             else if ((livemask == 0xF) && (directions == 0xA0)) {
  330.                tptr = &step_2x2v_pair;
  331.             }
  332.             break;
  333.          case s2x4:
  334.             if ((livemask == 0xFF) && (directions == 0x77DD)) {
  335.                tptr = &step_8ch_pair;         /* Check for stepping to parallel waves from an 8 chain. */
  336.             }
  337.             else if ((livemask == 0xFF) && (directions == 0xAA00)) {
  338.                tptr = &step_li_pair;          /* Check for stepping to a grand wave from lines facing. */
  339.             }
  340.             else if ((livemask == 0xFF) && ((directions == 0xDD77) || (directions == 0x5FF5))) {
  341.                tptr = &step_tby_pair;         /* Check for stepping to a 1/4 tag or 3/4 tag from a DPT or trade-by. */
  342.             }
  343.             break;
  344.          case s_1x2:
  345.             if ((livemask == 0x3) && (directions == 0x7)) {
  346.                tptr = &step_1x2_pair;         /* Check for stepping to a miniwave from people facing. */
  347.             }
  348.             break;
  349.          case s1x4:
  350.             /* Check for stepping to a box from a 1x4 single 8 chain -- we allow some phantoms.  This is what makes
  351.                triple columns turn and weave legal in certain interesting cases. */
  352.             if ((livemask == 0xF) && (directions == 0x7D))
  353.                tptr = &step_1x4_pair;
  354.             else if ((livemask == 0x3) && (directions == 0x70))
  355.                tptr = &step_1x4_pair;
  356.             else if ((livemask == 0xC) && (directions == 0x0D))
  357.                tptr = &step_1x4_pair;
  358.             /* Check for stepping to a single 1/4 tag or 3/4 tag from a single-file DPT or trade-by --
  359.                we allow some phantoms, as above. */
  360.             else if ((livemask == 0xF) && ((directions == 0xD7) || (directions == 0x5F)))
  361.                tptr = &step_1x4_side_pair;
  362.             else if ((livemask == 0xA) && (directions == 0x13))
  363.                tptr = &step_1x4_side_pair;
  364.             break;
  365.          case s1x8:
  366.             if ((livemask == 0xFF) && (directions == 0x7DD7)) {
  367.                tptr = &step_1x8_pair;         /* Check for stepping to a column from a 1x8 single 8 chain. */
  368.             }
  369.             break;
  370.       }
  371.    }
  372.  
  373.    if (!tptr) return;
  374.    if (tptr->warning) warn(tptr->warning);
  375.    if ((scopy->setupflags & tptr->forbidden_elongation) && (!(scopy->setupflags & SETUPFLAG__NO_CHK_ELONG)))
  376.       fail("People are too far away to work with each other on this call.");
  377.    zptr = tptr->expand_lists;
  378.  
  379.    scopy->setupflags |= SETUPFLAG__DISTORTED;
  380.  
  381.    stemp = *scopy;
  382.    clear_people(scopy);
  383.  
  384.    if (zptr->rot) {
  385.       for (i=0; i<zptr->size; i++) {
  386.          int idx = zptr->source_indices[i];
  387.          if (idx < 0) {
  388.             if (stemp.people[i].id1) fail("Don't understand this setup at all.");
  389.          }
  390.          else {
  391.             (void) copy_rot(scopy, idx, &stemp, i, 033);
  392.          }
  393.       }
  394.       scopy->rotation++;
  395.    }
  396.    else {
  397.       for (i=0; i<zptr->size; i++) {
  398.          int idx = zptr->source_indices[i];
  399.          if (idx < 0) {
  400.             if (stemp.people[i].id1) fail("Don't understand this setup at all.");
  401.          }
  402.          else {
  403.             (void) copy_person(scopy, idx, &stemp, i);
  404.          }
  405.       }
  406.    }
  407.  
  408.    scopy->kind = zptr->outer_kind;
  409.    canonicalize_rotation(scopy);
  410. }
  411.  
  412.  
  413.  
  414. extern void do_matrix_expansion(setup *ss, concept_kind ckind)
  415. {
  416.    int i, j;
  417.    expand_thing *eptr;
  418.    setup stemp;
  419.    unsigned int concprops = concept_table[ckind].concept_prop;
  420.  
  421.    for (;;) {
  422.       if (concprops & (CONCPROP__NEED_4X4 | CONCPROP__NEED_BLOB | CONCPROP__NEED_4X6)) {
  423.          if (ss->kind == s2x4) {
  424.             eptr = &exp_2x4_4x4_stuff; goto expand_me;
  425.          }
  426.       }
  427.    
  428.       if (concprops & (CONCPROP__NEED_BLOB)) {
  429.          if (ss->kind == s4x4) {
  430.             eptr = &exp_4x4_blob_stuff; goto expand_me;
  431.          }
  432.       }
  433.       else if (concprops & CONCPROP__NEED_4DMD) {
  434.          int livemask;
  435.    
  436.          switch (ss->kind) {
  437.             case s1x8:
  438.                eptr = &exp_1x8_4dm_stuff; goto expand_me;
  439.             case s_qtag:
  440.                eptr = &exp_qtg_4dm_stuff; goto expand_me;
  441.             case s4x4:
  442.                for (i=0, j=1, livemask=0; i<16; i++, j<<=1) {
  443.                   if (ss->people[i].id1) livemask |= j;
  444.                }
  445.    
  446.                if (livemask == 0x1717) {
  447.                   eptr = &exp_4x4_4dm_stuff_a; goto expand_me;
  448.                }
  449.                else if (livemask == 0x7171) {
  450.                   eptr = &exp_4x4_4dm_stuff_b; goto expand_me;
  451.                }
  452.          }
  453.       }
  454.       else if (concprops & CONCPROP__NEED_3DMD) {
  455.          if (ss->kind == s_3x1dmd) {         /* Need to expand to real triple diamonds. */
  456.             eptr = &exp_3x1d_3d_stuff; goto expand_me;
  457.          }
  458.       }
  459.       else if (concprops & CONCPROP__NEED_2X8) {
  460.          switch (ss->kind) {         /* Need to expand to a 2x8. */
  461.             case s2x4:
  462.                eptr = &exp_2x4_2x8_stuff; goto expand_me;
  463.             case s2x6:
  464.                eptr = &exp_2x6_2x8_stuff; goto expand_me;
  465.          }
  466.       }
  467.       else if (concprops & CONCPROP__NEED_2X6) {
  468.          if (ss->kind == s2x4) {         /* Need to expand to a 2x6. */
  469.             eptr = &exp_2x4_2x6_stuff; goto expand_me;
  470.          }
  471.       }
  472.       else if (concprops & CONCPROP__NEED_4X6) {
  473.          if (ss->kind == s2x6) {         /* Need to expand to a 4x6. */
  474.             eptr = &exp_2x6_4x6_stuff; goto expand_me;
  475.          }
  476.       }
  477.       else if (concprops & CONCPROP__NEED_3X4_1X12) {
  478.          switch (ss->kind) {             /* Need to expand to a 3x4 or 1x12. */
  479.             case s1x8:
  480.                eptr = &exp_1x8_1x12_stuff; goto expand_me;
  481.             case s1x10:
  482.                eptr = &exp_1x10_1x12_stuff; goto expand_me;
  483.             case s_qtag:                 /* Need to expand to a 3x4. */
  484.                eptr = &exp_qtg_3x4_stuff; goto expand_me;
  485.          }
  486.       }
  487.       else if (concprops & CONCPROP__NEED_3X4) {
  488.          if (ss->kind == s_qtag) {       /* Need to expand to a 3x4. */
  489.             eptr = &exp_qtg_3x4_stuff; goto expand_me;
  490.          }
  491.       }
  492.       else if (concprops & CONCPROP__NEED_4X4_1X16) {
  493.          switch (ss->kind) {             /* Need to expand to a 4x4 or 1x16. */
  494.             case s2x4:
  495.                eptr = &exp_2x4_4x4_stuff; goto expand_me;
  496.             case s1x8:
  497.                eptr = &exp_1x8_1x12_stuff; goto expand_me;
  498.             case s1x10:
  499.                eptr = &exp_1x10_1x12_stuff; goto expand_me;
  500.             case s1x12:
  501.                eptr = &exp_1x12_1x14_stuff; goto expand_me;
  502.             case s1x14:
  503.                eptr = &exp_1x14_1x16_stuff; goto expand_me;
  504.          }
  505.       }
  506.    
  507.       /* If get here, we did NOT see any concept that requires a setup expansion. */
  508.    
  509.       return;
  510.    
  511.       expand_me:
  512.    
  513.       /* If get here, we DID see a concept that requires a setup expansion. */
  514.    
  515.       stemp = *ss;
  516.       clear_people(ss);
  517.       if (eptr->rot) {
  518.          for (i=0; i<eptr->size; i++) (void) copy_rot(ss, eptr->source_indices[i], &stemp, i, 033);
  519.          ss->rotation++;
  520.       }
  521.       else {
  522.          for (i=0; i<eptr->size; i++) (void) copy_person(ss, eptr->source_indices[i], &stemp, i);
  523.       }
  524.    
  525.       /* Unsymmetrical selectors are disabled if we expanded the matrix. */
  526.       for (i=0; i<MAX_PEOPLE; i++) ss->people[i].id2 &= ~UNSYM_BITS_TO_CLEAR;
  527.       ss->kind = eptr->outer_kind;
  528.  
  529.       canonicalize_rotation(ss);
  530.    
  531.       /* Put in position-identification bits (leads/trailers/beaux/belles/centers/ends etc.) */
  532.       update_id_bits(ss);
  533.    }
  534. }
  535.  
  536.  
  537. static void normalize_4x4(setup *stuff)
  538. {
  539.    if (!(stuff->people[0].id1 | stuff->people[4].id1 | stuff->people[8].id1 | stuff->people[12].id1)) {
  540.       if (!(stuff->people[5].id1 | stuff->people[6].id1 | stuff->people[13].id1 | stuff->people[14].id1)) {
  541.          compress_setup(&exp_2x4_4x4_stuff, stuff);
  542.       }
  543.       else if (!(stuff->people[1].id1 | stuff->people[2].id1 | stuff->people[9].id1 | stuff->people[10].id1)) {
  544.          stuff->kind = s2x4;
  545.          stuff->rotation++;
  546.          (void) copy_rot(stuff, 1, stuff, 3, 033);     /* careful -- order is important */
  547.          (void) copy_rot(stuff, 2, stuff, 7, 033);
  548.          (void) copy_rot(stuff, 3, stuff, 5, 033);
  549.          (void) copy_rot(stuff, 4, stuff, 6, 033);
  550.          (void) copy_rot(stuff, 0, stuff, 14, 033);
  551.          (void) copy_rot(stuff, 5, stuff, 11, 033);
  552.          (void) copy_rot(stuff, 6, stuff, 15, 033);
  553.          (void) copy_rot(stuff, 7, stuff, 13, 033);
  554.       }
  555.    }
  556. }
  557.  
  558.  
  559. static void normalize_blob(setup *stuff)
  560.  
  561. {
  562.    if (!(stuff->people[0].id1 | stuff->people[1].id1 | stuff->people[12].id1 | stuff->people[13].id1)) {
  563.       stuff->kind = s4x6;
  564.       (void) copy_person(stuff, 13, stuff, 9);         /* careful -- order is important */
  565.       (void) copy_person(stuff, 9, stuff, 23);
  566.       (void) copy_person(stuff, 23, stuff, 7);
  567.       (void) copy_person(stuff, 7, stuff, 4);
  568.       (void) copy_person(stuff, 4, stuff, 3);
  569.       (void) copy_person(stuff, 3, stuff, 2);
  570.       (void) copy_person(stuff, 2, stuff, 22);
  571.       (void) copy_person(stuff, 22, stuff, 8);
  572.       (void) copy_person(stuff, 8, stuff, 5);
  573.       (void) copy_person(stuff, 1, stuff, 21);
  574.       (void) copy_person(stuff, 21, stuff, 11);
  575.       (void) copy_person(stuff, 11, stuff, 19);
  576.       (void) copy_person(stuff, 19, stuff, 16);
  577.       (void) copy_person(stuff, 16, stuff, 15);
  578.       (void) copy_person(stuff, 15, stuff, 14);
  579.       (void) copy_person(stuff, 14, stuff, 10);
  580.       (void) copy_person(stuff, 10, stuff, 20);
  581.       (void) copy_person(stuff, 20, stuff, 17);
  582.  
  583.       clear_person(stuff, 5);
  584.       clear_person(stuff, 17);
  585.    }
  586.    else if (!(stuff->people[6].id1 | stuff->people[7].id1 | stuff->people[18].id1 | stuff->people[19].id1)) {
  587.       stuff->kind = s4x6;
  588.       stuff->rotation++;
  589.       (void) copy_rot(stuff, 18, stuff, 0, 033);       /* careful -- order is important */
  590.       (void) copy_rot(stuff, 7, stuff, 10, 033);
  591.       (void) copy_rot(stuff, 10, stuff, 2, 033);
  592.       (void) copy_rot(stuff, 2, stuff, 4, 033);
  593.       (void) copy_rot(stuff, 4, stuff, 9, 033);
  594.       (void) copy_rot(stuff, 9, stuff, 5, 033);
  595.       (void) copy_rot(stuff, 6, stuff, 12, 033);
  596.       (void) copy_rot(stuff, 19, stuff, 22, 033);
  597.       (void) copy_rot(stuff, 22, stuff, 14, 033);
  598.       (void) copy_rot(stuff, 14, stuff, 16, 033);
  599.       (void) copy_rot(stuff, 16, stuff, 21, 033);
  600.       (void) copy_rot(stuff, 21, stuff, 17, 033);
  601.  
  602.       (void) copy_rot(stuff, 0, stuff, 3, 033);
  603.       (void) copy_rot(stuff, 3, stuff, 8, 033);
  604.       (void) copy_rot(stuff, 8, stuff, 11, 033);
  605.       (void) copy_rot(stuff, 11, stuff, 1, 033);
  606.       (void) copy_person(stuff, 1, stuff, 0);
  607.  
  608.       (void) copy_rot(stuff, 0, stuff, 23, 033);
  609.       (void) copy_rot(stuff, 23, stuff, 13, 033);
  610.       (void) copy_rot(stuff, 13, stuff, 15, 033);
  611.       (void) copy_rot(stuff, 15, stuff, 20, 033);
  612.       (void) copy_person(stuff, 20, stuff, 0);
  613.  
  614.       clear_person(stuff, 0);
  615.       clear_person(stuff, 5);
  616.       clear_person(stuff, 12);
  617.       clear_person(stuff, 17);
  618.    }
  619. }
  620.  
  621.  
  622.  
  623.  
  624. static void normalize_4x6(setup *stuff)
  625. {
  626.    if (!(stuff->people[0].id1 | stuff->people[11].id1 | stuff->people[18].id1 | stuff->people[17].id1 |
  627.             stuff->people[5].id1 | stuff->people[6].id1 | stuff->people[23].id1 | stuff->people[12].id1)) {
  628.       stuff->kind = s4x4;
  629.       (void) copy_person(stuff, 6, stuff, 15);         /* careful -- order is important */
  630.       (void) copy_person(stuff, 15, stuff, 9);
  631.       (void) copy_person(stuff, 9, stuff, 19);
  632.       (void) copy_person(stuff, 11, stuff, 20);
  633.       (void) copy_person(stuff, 5, stuff, 14);
  634.       (void) copy_person(stuff, 14, stuff, 3);
  635.       (void) copy_person(stuff, 3, stuff, 8);
  636.       (void) copy_person(stuff, 8, stuff, 16);
  637.       (void) copy_person(stuff, 12, stuff, 1);
  638.       (void) copy_person(stuff, 1, stuff, 7);
  639.       (void) copy_person(stuff, 7, stuff, 21);
  640.       (void) copy_person(stuff, 0, stuff, 4);
  641.       (void) copy_person(stuff, 4, stuff, 13);
  642.       (void) copy_person(stuff, 13, stuff, 2);
  643.       (void) copy_person(stuff, 2, stuff, 22);
  644.  
  645.       canonicalize_rotation(stuff);
  646.    }
  647.    else if (!(stuff->people[0].id1 | stuff->people[1].id1 | stuff->people[2].id1 | stuff->people[3].id1 |
  648.             stuff->people[4].id1 | stuff->people[5].id1 | stuff->people[17].id1 | stuff->people[16].id1 |
  649.             stuff->people[15].id1 | stuff->people[14].id1 | stuff->people[13].id1 | stuff->people[12].id1)) {
  650.       stuff->kind = s2x6;
  651.  
  652.       (void) copy_person(stuff, 0, stuff, 11);         /* careful -- order is important */
  653.       (void) copy_person(stuff, 11, stuff, 18);
  654.       (void) copy_person(stuff, 1, stuff, 10);
  655.       (void) copy_person(stuff, 10, stuff, 19);
  656.       (void) copy_person(stuff, 2, stuff, 9);
  657.       (void) copy_person(stuff, 9, stuff, 20);
  658.       (void) copy_person(stuff, 3, stuff, 8);
  659.       (void) copy_person(stuff, 8, stuff, 21);
  660.       (void) copy_person(stuff, 4, stuff, 7);
  661.       (void) copy_person(stuff, 7, stuff, 22);
  662.       (void) copy_person(stuff, 5, stuff, 6);
  663.       (void) copy_person(stuff, 6, stuff, 23);
  664.    }
  665. }
  666.  
  667.  
  668. static void normalize_4dmd(setup *stuff)
  669.  
  670. {
  671.    setup temp;
  672.  
  673.    if (!(stuff->people[0].id1 | stuff->people[3].id1 | stuff->people[4].id1 | stuff->people[5].id1 |
  674.             stuff->people[8].id1 | stuff->people[11].id1 | stuff->people[12].id1 | stuff->people[13].id1)) {
  675.  
  676.       /* Danger!  If the people were in side-by-side quarter-tags, turning this into
  677.          a single quarter-tag would require that the outsides slide together.  That
  678.          would be wrong.  The bug show up in cases like
  679.             1P2P; pass the ocean; swing and mix; follow thru; truck twice;
  680.             split phantom twin boxes sets in motion.
  681.          So, if people do not have diamond-like orientation, we go into an "H". */
  682.  
  683.       if (!(((stuff->people[6].id1 | stuff->people[7].id1 | stuff->people[14].id1 | stuff->people[15].id1) & 1) |
  684.             ((stuff->people[1].id1 | stuff->people[2].id1 | stuff->people[9].id1 | stuff->people[10].id1) & 010))) {
  685.          temp = *stuff;
  686.  
  687.          stuff->kind = s_qtag;
  688.          (void) copy_person(stuff, 0, &temp, 1);
  689.          (void) copy_person(stuff, 1, &temp, 2);
  690.          (void) copy_person(stuff, 2, &temp, 6);
  691.          (void) copy_person(stuff, 3, &temp, 7);
  692.          (void) copy_person(stuff, 4, &temp, 9);
  693.          (void) copy_person(stuff, 5, &temp, 10);
  694.          (void) copy_person(stuff, 6, &temp, 14);
  695.          (void) copy_person(stuff, 7, &temp, 15);
  696.       }
  697.       else {
  698.          temp = *stuff;
  699.          clear_people(stuff);
  700.  
  701.          stuff->kind = s3x4;
  702.          (void) copy_person(stuff, 0, &temp, 1);
  703.          (void) copy_person(stuff, 3, &temp, 2);
  704.          (void) copy_person(stuff, 4, &temp, 6);
  705.          (void) copy_person(stuff, 5, &temp, 7);
  706.          (void) copy_person(stuff, 6, &temp, 9);
  707.          (void) copy_person(stuff, 9, &temp, 10);
  708.          (void) copy_person(stuff, 10, &temp, 14);
  709.          (void) copy_person(stuff, 11, &temp, 15);
  710.       }
  711.    }
  712.    else if (!(stuff->people[0].id1 | stuff->people[1].id1 | stuff->people[2].id1 | stuff->people[3].id1 |
  713.             stuff->people[8].id1 | stuff->people[9].id1 | stuff->people[10].id1 | stuff->people[11].id1)) {
  714.       compress_setup(&exp_1x8_4dm_stuff, stuff);
  715.    }
  716.    else if (!(stuff->people[4].id1 | stuff->people[5].id1 | stuff->people[6].id1 | stuff->people[7].id1 |
  717.             stuff->people[12].id1 | stuff->people[13].id1 | stuff->people[14].id1 | stuff->people[15].id1)) {
  718.       temp = *stuff;
  719.       clear_people(stuff);
  720.  
  721.       stuff->kind = s4x4;
  722.       (void) copy_person(stuff, 12, &temp, 0);
  723.       (void) copy_person(stuff, 13, &temp, 1);
  724.       (void) copy_person(stuff, 14, &temp, 2);
  725.       (void) copy_person(stuff, 0, &temp, 3);
  726.       (void) copy_person(stuff, 4, &temp, 8);
  727.       (void) copy_person(stuff, 5, &temp, 9);
  728.       (void) copy_person(stuff, 6, &temp, 10);
  729.       (void) copy_person(stuff, 8, &temp, 11);
  730.  
  731.       canonicalize_rotation(stuff);
  732.    }
  733. }
  734.  
  735.  
  736. /* See if this 3x4 is actually occupied only in spots of a qtag. */
  737.  
  738. static void normalize_3x4(setup *stuff)
  739. {
  740.    if ((!stuff->people[0].id1) && (!stuff->people[3].id1) && (!stuff->people[6].id1) && (!stuff->people[9].id1)) {
  741.       stuff->kind = s_qtag;
  742.       (void) copy_person(stuff, 0, stuff, 1);         /* careful -- order is important */
  743.       (void) copy_person(stuff, 1, stuff, 2);
  744.       (void) copy_person(stuff, 2, stuff, 4);
  745.       (void) copy_person(stuff, 3, stuff, 5);
  746.       (void) copy_person(stuff, 4, stuff, 7);
  747.       (void) copy_person(stuff, 5, stuff, 8);
  748.       (void) copy_person(stuff, 6, stuff, 10);
  749.       (void) copy_person(stuff, 7, stuff, 11);
  750.    }
  751. }
  752.  
  753.  
  754. /* Check whether "C1 phantom" setup is only occupied in 2x4 spots, and fix it if so. */
  755.  
  756. static void normalize_c1_phan(setup *stuff)
  757.  
  758. {
  759.    if (!(stuff->people[1].id1 | stuff->people[3].id1 | stuff->people[4].id1 | stuff->people[6].id1 |
  760.             stuff->people[9].id1 | stuff->people[11].id1 | stuff->people[12].id1 | stuff->people[14].id1)) {
  761.       stuff->kind = s2x4;
  762.       (void) copy_person(stuff, 1, stuff, 2);                /* careful -- order is important */
  763.       (void) copy_person(stuff, 2, stuff, 7);
  764.       (void) copy_person(stuff, 3, stuff, 5);
  765.       (void) copy_person(stuff, 4, stuff, 8);
  766.       (void) copy_person(stuff, 5, stuff, 10);
  767.       (void) copy_person(stuff, 6, stuff, 15);
  768.       (void) copy_person(stuff, 7, stuff, 13);
  769.    }
  770.    else if (!(stuff->people[0].id1 | stuff->people[2].id1 | stuff->people[5].id1 | stuff->people[7].id1 |
  771.             stuff->people[8].id1 | stuff->people[10].id1 | stuff->people[13].id1 | stuff->people[15].id1)) {
  772.       stuff->kind = s2x4;
  773.       stuff->rotation++;
  774.       (void) copy_rot(stuff, 7, stuff, 1, 033);        /* careful -- order is important */
  775.       (void) copy_rot(stuff, 0, stuff, 4, 033);
  776.       (void) copy_rot(stuff, 2, stuff, 11, 033);
  777.       (void) copy_rot(stuff, 1, stuff, 6, 033);
  778.       (void) copy_rot(stuff, 6, stuff, 3, 033);
  779.       (void) copy_rot(stuff, 3, stuff, 9, 033);
  780.       (void) copy_rot(stuff, 4, stuff, 12, 033);
  781.       (void) copy_rot(stuff, 5, stuff, 14, 033);
  782.    }
  783. }
  784.  
  785.  
  786.  
  787.  
  788. /* The "nlevel" argument tells how hard we work to remove the outside phantoms.
  789.    When merging the results of "on your own" or "own the so-and-so",
  790.    we set nlevel=normalize_before_merge to work very hard at stripping away
  791.    outside phantoms, so that we can see more readily how to put things together.
  792.    When preparing for an isolated call, we work at it a little, so
  793.    nlevel=normalize_before_isolated_call.   For normal usage, nlevel=simple_normalize. */
  794. extern void normalize_setup(setup *ss, normalize_level nlevel)
  795. {
  796.    /* Normalize setup by removing outboard phantoms. */
  797.  
  798.    if (ss->kind == s1x16) {         /* This might leave a 1x14, which might be reduced further. */
  799.       if (!(ss->people[0].id1 | ss->people[8].id1)) {
  800.          compress_setup(&exp_1x14_1x16_stuff, ss);
  801.       }
  802.    }
  803.  
  804.    if (ss->kind == s1x14) {         /* This might leave a 1x12, which might be reduced further. */
  805.       if (!(ss->people[0].id1 | ss->people[7].id1)) {
  806.          compress_setup(&exp_1x12_1x14_stuff, ss);
  807.       }
  808.    }
  809.  
  810.    if (ss->kind == s1x12) {         /* This might leave a 1x10, which might be reduced further. */
  811.       if (!(ss->people[0].id1 | ss->people[6].id1)) {
  812.          compress_setup(&exp_1x10_1x12_stuff, ss);
  813.       }
  814.    }
  815.  
  816.    if (ss->kind == s_bigblob)
  817.       normalize_blob(ss);           /* This might leave a 4x6, which might be reduced further. */
  818.  
  819.    if (ss->kind == s4x6)
  820.       normalize_4x6(ss);            /* This might leave a 4x4 or 2x6, which might be reduced further. */
  821.  
  822.    if (ss->kind == s1x10) {
  823.       if (!(ss->people[0].id1 | ss->people[5].id1)) {
  824.          compress_setup(&exp_1x8_1x10_stuff, ss);
  825.       }
  826.    }
  827.    else if (ss->kind == s4x4)
  828.       normalize_4x4(ss);
  829.    else if (ss->kind == s_3dmd) {
  830.       if (!(ss->people[0].id1 | ss->people[2].id1 | ss->people[6].id1 | ss->people[8].id1)) {
  831.          compress_setup(&exp_3x1d_3d_stuff, ss);
  832.       }
  833.    }
  834.    else if (ss->kind == s_4dmd)
  835.       normalize_4dmd(ss);
  836.    else if (ss->kind == s_c1phan)
  837.       normalize_c1_phan(ss);
  838.    else if (ss->kind == s3x4)
  839.       normalize_3x4(ss);
  840.    else if (ss->kind == s2x8) {  /* This might leave a 2x6, which could then be reduced to 2x4, below. */
  841.       if (!(ss->people[7].id1 | ss->people[8].id1 | ss->people[0].id1 | ss->people[15].id1)) {
  842.          compress_setup(&exp_2x6_2x8_stuff, ss);
  843.       }
  844.    }
  845.  
  846.    if (ss->kind == s2x6) {
  847.       if (!(ss->people[0].id1 | ss->people[5].id1 | ss->people[6].id1 | ss->people[11].id1)) {
  848.          compress_setup(&exp_2x4_2x6_stuff, ss);
  849.       }
  850.    }
  851.  
  852.    /* If preparing for a "so-and-so only do whatever", we remove outboard phantoms
  853.       more aggressively.  For example, if we are selecting just the center line of
  854.       a quarter tag, we reduce the setup all the way down to a line.  Normally we
  855.       wouldn't do this, lest we lose phantoms when gluing setups together. */
  856.  
  857.    if (nlevel >= normalize_before_merge) {
  858.       /* This reduction is necessary to make "ends only rotate 1/4" work from a DPT, yielding a rigger. */
  859.       if ((ss->kind == s2x4) && (!(ss->people[0].id1 | ss->people[3].id1 | ss->people[4].id1 | ss->people[7].id1))) {
  860.          ss->kind = s2x2;
  861.          (void) copy_person(ss, 0, ss, 1);
  862.          (void) copy_person(ss, 1, ss, 2);
  863.          (void) copy_person(ss, 2, ss, 5);
  864.          (void) copy_person(ss, 3, ss, 6);
  865.       }
  866.       else if ((ss->kind == s1x8) && (!(ss->people[0].id1 | ss->people[1].id1 | ss->people[4].id1 | ss->people[5].id1))) {
  867.          ss->kind = s1x4;
  868.          (void) copy_person(ss, 0, ss, 3);
  869.          (void) copy_person(ss, 1, ss, 2);
  870.          (void) copy_person(ss, 2, ss, 7);
  871.          (void) copy_person(ss, 3, ss, 6);
  872.       }
  873.    }
  874.  
  875.    if (nlevel >= normalize_before_isolated_call) {
  876.       if (ss->kind == s_qtag) {
  877.          if (!(ss->people[0].id1 | ss->people[1].id1 | ss->people[4].id1 | ss->people[5].id1)) {
  878.             ss->kind = s1x4;
  879.             (void) copy_person(ss, 0, ss, 6);
  880.             (void) copy_person(ss, 1, ss, 7);
  881.          }
  882.          if (!(ss->people[2].id1 | ss->people[3].id1 | ss->people[6].id1 | ss->people[7].id1)) {
  883.             /* We do NOT compress to a 2x2 -- doing so might permit people to
  884.                work with each other across the set when they shouldn't, as in
  885.                "heads pass the ocean; heads recycle while the sides star thru". */
  886.             ss->kind = s2x4;
  887.             ss->rotation++;
  888.             (void) copy_rot(ss, 7, ss, 0, 033);         /* careful -- order is important */
  889.             (void) copy_rot(ss, 3, ss, 4, 033);
  890.             (void) copy_rot(ss, 0, ss, 1, 033);
  891.             (void) copy_rot(ss, 4, ss, 5, 033);
  892.             clear_person(ss, 1);
  893.             clear_person(ss, 5);
  894.             canonicalize_rotation(ss);
  895.          }
  896.       }
  897.    }
  898. }
  899.  
  900.  
  901.  
  902. /* Top level move routine. */
  903.  
  904. extern void toplevelmove(void)
  905. {
  906.    int i;
  907.    parse_block *conceptptr;
  908.    setup new_setup;
  909.  
  910.    int concept_read_base = 0;
  911.    setup starting_setup = history[history_ptr].state;
  912.    configuration *newhist = &history[history_ptr+1];
  913.    /* Be sure that the amount of written history that we consider to be safely
  914.       written is less than the item we are about to change. */
  915.    if (written_history_items > history_ptr)
  916.       written_history_items = history_ptr;
  917.  
  918.    starting_setup.setupflags = 0;
  919.  
  920.    /* If we are starting a sequence with the "so-and-so into the center and do whatever"
  921.       flag on, and this call is a "sequence starter", take special action. */
  922.  
  923.    if (startinfolist[history[history_ptr].centersp].into_the_middle) {
  924.    
  925.       /* If the call is a special sequence starter (e.g. spin a pulley) remove the implicit
  926.          "centers" concept and just do it.  The setup in this case will be a squared set
  927.          with so-and-so moved into the middle, which is what the encoding of these calls
  928.          wants. */
  929.    
  930.       if (parse_state.topcallflags & cflag__sequence_starter)
  931.          concept_read_base = 1;
  932.    
  933.       /* If the call is a "split square thru" type of call, we do the same.  We leave the
  934.          "split" concept in place.  Other mechanisms will do the rest. */
  935.  
  936.       else if ((parse_state.topcallflags & cflag__split_like_square_thru) &&
  937.             ((newhist->command_root->next->concept->kind == concept_split) ||
  938.                   ((newhist->command_root->next->concept->kind == concept_left) &&
  939.                   (newhist->command_root->next->next->concept->kind == concept_split))))
  940.          concept_read_base = 1;
  941.  
  942.       /* If the call is a "split dixie style" type of call, we do something similar,
  943.          but the transformation we perform on the starting setup is highly peculiar. */
  944.    /* ****** bug: ability to handle "left" concept patched out!  It does it wrong! */
  945.    
  946.       else if ((parse_state.topcallflags & cflag__split_like_dixie_style) &&
  947.                newhist->command_root->next->concept->kind == concept_split &&
  948.                newhist->command_root->next->next->concept->kind == marker_end_of_list) {
  949.          personrec x;
  950.  
  951.          concept_read_base = 2;
  952.          starting_setup.rotation++;
  953.          x = starting_setup.people[0];
  954.          (void) copy_rot(&starting_setup, 0, &starting_setup, 6, 022);
  955.          (void) copy_person(&starting_setup, 6, &starting_setup, 5);
  956.          (void) copy_rot(&starting_setup, 5, &starting_setup, 7, 033);
  957.          starting_setup.people[7].id1 = rotccw(x.id1);
  958.          starting_setup.people[7].id2 = x.id2;
  959.  
  960.          x = starting_setup.people[4];
  961.          (void) copy_rot(&starting_setup, 4, &starting_setup, 2, 022);
  962.          (void) copy_person(&starting_setup, 2, &starting_setup, 1);
  963.          (void) copy_rot(&starting_setup, 1, &starting_setup, 3, 033);
  964.          starting_setup.people[3].id1 = rotccw(x.id1);
  965.          starting_setup.people[3].id2 = x.id2;
  966.       }
  967.    }
  968.  
  969.    if (concept_read_base == 2)
  970.       conceptptr = newhist->command_root->next->next;
  971.    else if (concept_read_base == 1)
  972.       conceptptr = newhist->command_root->next;
  973.    else
  974.       conceptptr = newhist->command_root;
  975.  
  976.    /* Clear a few things.  We do NOT clear the warnings, because some (namely the
  977.       "concept not allowed at this level" warning) may have already been logged. */
  978.    newhist->centersp = 0;
  979.    newhist->draw_pic = FALSE;
  980.    newhist->resolve_flag.kind = resolve_none;
  981.  
  982.    /* Set the selector to "uninitialized", so that, if we do a call like "run", we
  983.       will query the user to find out who is selected. */
  984.  
  985.    current_selector = selector_uninitialized;
  986.  
  987.    /* Put in identification bits for unsymmetrical stuff, if possible. */
  988.  
  989.    for (i=0; i<MAX_PEOPLE; i++) starting_setup.people[i].id2 &= ~UNSYM_BITS_TO_CLEAR;
  990.  
  991.    if (starting_setup.kind == s2x4) {
  992.       int nearbit = 0;
  993.       int farbit = 0;
  994.  
  995.       if (starting_setup.rotation & 1) {
  996.          nearbit = ID2_NEARBOX;
  997.          farbit = ID2_FARBOX;
  998.       }
  999.       else {
  1000.          int tbonetest = 0;
  1001.          for (i=0; i<8; i++) tbonetest |= starting_setup.people[i].id1;
  1002.  
  1003.          if (!(tbonetest & 1)) {
  1004.             nearbit = ID2_NEARLINE;
  1005.             farbit = ID2_FARLINE;
  1006.          }
  1007.          else if (!(tbonetest & 010)) {
  1008.             nearbit = ID2_NEARCOL;
  1009.             farbit = ID2_FARCOL;
  1010.          }
  1011.       }
  1012.  
  1013.       for (i=0; i<8; i++) {
  1014.          if (starting_setup.people[i].id1 & BIT_PERSON)
  1015.             starting_setup.people[i].id2 |= ((i + (starting_setup.rotation << 1)) & 4) ? nearbit:farbit;
  1016.       }
  1017.    }
  1018.  
  1019.    /* Put in position-identification bits (leads/trailers/beaux/belles/centers/ends etc.) */
  1020.    update_id_bits(&starting_setup);
  1021.    move(&starting_setup, conceptptr, NULLCALLSPEC, 0, FALSE, &new_setup);
  1022.  
  1023.    /* Remove outboard phantoms from the resulting setup. */
  1024.  
  1025.    normalize_setup(&new_setup, simple_normalize);
  1026.  
  1027.    newhist->state = new_setup;
  1028.    newhist->resolve_flag = resolve_p(&new_setup);
  1029. }
  1030.