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 / sdpreds.c < prev    next >
C/C++ Source or Header  |  1992-09-15  |  39KB  |  1,016 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 function:
  22.    selectp
  23.  
  24. and the following external variables:
  25.    current_selector
  26.    selector_used
  27.    pred_table     which is filled with pointers to the predicate functions
  28. */
  29.  
  30. #include "sd.h"
  31.  
  32. /* These variables are external. */
  33.  
  34. selector_kind current_selector;
  35. long_boolean selector_used;
  36.  
  37.  
  38. /* If a real person and a person under test are XOR'ed, the result AND'ed with this constant,
  39.    and the low bits of that result examined, it will tell whether the person under test is real
  40.    and facing in the same direction (result = 0), the opposite direction (result == 2), or whatever. */
  41.  
  42. #define DIR_MASK (BIT_PERSON | 3)
  43.  
  44. #define ID2_ALL_ID (ID2_HEAD|ID2_SIDE|ID2_BOY|ID2_GIRL)
  45.  
  46.  
  47.  
  48.  
  49.  
  50. extern long_boolean selectp(setup *ss, int place)
  51. {
  52.    int pid2;
  53.  
  54.    selector_used = TRUE;
  55.  
  56.    /* Pull out the cases that do not require the person to be real. */
  57.  
  58.    switch (current_selector) {
  59.       case selector_all:
  60.          return(TRUE);
  61.       case selector_none:
  62.          return(FALSE);
  63.    }
  64.  
  65.    /* Demand that the subject be real. */
  66.  
  67.    if (!(ss->people[place].id1 & BIT_PERSON))
  68.       fail("Can't decide who are selected.");
  69.  
  70.    pid2 = ss->people[place].id2;
  71.  
  72.    switch (current_selector) {
  73.       case selector_boys:
  74.          if      ((pid2 & (ID2_BOY|ID2_GIRL)) == ID2_BOY) return(TRUE);
  75.          else if ((pid2 & (ID2_BOY|ID2_GIRL)) == ID2_GIRL) return(FALSE);
  76.          break;
  77.       case selector_girls:
  78.          if      ((pid2 & (ID2_BOY|ID2_GIRL)) == ID2_GIRL) return(TRUE);
  79.          else if ((pid2 & (ID2_BOY|ID2_GIRL)) == ID2_BOY) return(FALSE);
  80.          break;
  81.       case selector_heads:
  82.          if      ((pid2 & (ID2_HEAD|ID2_SIDE)) == ID2_HEAD) return(TRUE);
  83.          else if ((pid2 & (ID2_HEAD|ID2_SIDE)) == ID2_SIDE) return(FALSE);
  84.          break;
  85.       case selector_sides:
  86.          if      ((pid2 & (ID2_HEAD|ID2_SIDE)) == ID2_SIDE) return(TRUE);
  87.          else if ((pid2 & (ID2_HEAD|ID2_SIDE)) == ID2_HEAD) return(FALSE);
  88.          break;
  89.       case selector_headcorners:
  90.          if      ((pid2 & (ID2_HCOR|ID2_SCOR)) == ID2_HCOR) return(TRUE);
  91.          else if ((pid2 & (ID2_HCOR|ID2_SCOR)) == ID2_SCOR) return(FALSE);
  92.          break;
  93.       case selector_sidecorners:
  94.          if      ((pid2 & (ID2_HCOR|ID2_SCOR)) == ID2_SCOR) return(TRUE);
  95.          else if ((pid2 & (ID2_HCOR|ID2_SCOR)) == ID2_HCOR) return(FALSE);
  96.          break;
  97.       case selector_headboys:
  98.          if      ((pid2 & (ID2_ALL_ID|ID2_NHB)) == (ID2_HEAD|ID2_BOY)) return(TRUE);
  99.          else if ((pid2 & ID2_NHB) == ID2_NHB) return(FALSE);
  100.          break;
  101.       case selector_headgirls:
  102.          if      ((pid2 & (ID2_ALL_ID|ID2_NHG)) == (ID2_HEAD|ID2_GIRL)) return(TRUE);
  103.          else if ((pid2 & ID2_NHG) == ID2_NHG) return(FALSE);
  104.          break;
  105.       case selector_sideboys:
  106.          if      ((pid2 & (ID2_ALL_ID|ID2_NSB)) == (ID2_SIDE|ID2_BOY)) return(TRUE);
  107.          else if ((pid2 & ID2_NSB) == ID2_NSB) return(FALSE);
  108.          break;
  109.       case selector_sidegirls:
  110.          if      ((pid2 & (ID2_ALL_ID|ID2_NSG)) == (ID2_SIDE|ID2_GIRL)) return(TRUE);
  111.          else if ((pid2 & ID2_NSG) == ID2_NSG) return(FALSE);
  112.          break;
  113.       case selector_centers:
  114.          if      ((pid2 & (ID2_CENTER|ID2_END)) == ID2_CENTER) return(TRUE);
  115.          else if ((pid2 & (ID2_CENTER|ID2_END)) == ID2_END) return(FALSE);
  116.          break;
  117.       case selector_ends:
  118.          if      ((pid2 & (ID2_CENTER|ID2_END)) == ID2_END) return(TRUE);
  119.          else if ((pid2 & (ID2_CENTER|ID2_END)) == ID2_CENTER) return(FALSE);
  120.          break;
  121.       case selector_leads:
  122.          if      ((pid2 & (ID2_LEAD|ID2_TRAILER)) == ID2_LEAD) return(TRUE);
  123.          else if ((pid2 & (ID2_LEAD|ID2_TRAILER)) == ID2_TRAILER) return(FALSE);
  124.          break;
  125.       case selector_trailers:
  126.          if      ((pid2 & (ID2_LEAD|ID2_TRAILER)) == ID2_TRAILER) return(TRUE);
  127.          else if ((pid2 & (ID2_LEAD|ID2_TRAILER)) == ID2_LEAD) return(FALSE);
  128.          break;
  129.       case selector_beaux:
  130.          if      ((pid2 & (ID2_BEAU|ID2_BELLE)) == ID2_BEAU) return(TRUE);
  131.          else if ((pid2 & (ID2_BEAU|ID2_BELLE)) == ID2_BELLE) return(FALSE);
  132.          break;
  133.       case selector_belles:
  134.          if      ((pid2 & (ID2_BEAU|ID2_BELLE)) == ID2_BELLE) return(TRUE);
  135.          else if ((pid2 & (ID2_BEAU|ID2_BELLE)) == ID2_BEAU) return(FALSE);
  136.          break;
  137.       case selector_center2:
  138.          if      ((pid2 & (ID2_CTR2|ID2_OUTR6)) == ID2_CTR2) return(TRUE);
  139.          else if ((pid2 & (ID2_CTR2|ID2_OUTR6)) == ID2_OUTR6) return(FALSE);
  140.          break;
  141.       case selector_center6:
  142.          if      ((pid2 & (ID2_CTR6|ID2_OUTR2)) == ID2_CTR6) return(TRUE);
  143.          else if ((pid2 & (ID2_CTR6|ID2_OUTR2)) == ID2_OUTR2) return(FALSE);
  144.          break;
  145.       case selector_outer2:
  146.          if      ((pid2 & (ID2_CTR6|ID2_OUTR2)) == ID2_OUTR2) return(TRUE);
  147.          else if ((pid2 & (ID2_CTR6|ID2_OUTR2)) == ID2_CTR6) return(FALSE);
  148.          break;
  149.       case selector_outer6:
  150.          if      ((pid2 & (ID2_CTR2|ID2_OUTR6)) == ID2_OUTR6) return(TRUE);
  151.          else if ((pid2 & (ID2_CTR2|ID2_OUTR6)) == ID2_CTR2) return(FALSE);
  152.          break;
  153.       case selector_nearline:
  154.          if      ((pid2 & (ID2_NEARLINE|ID2_FARLINE)) == ID2_NEARLINE) return(TRUE);
  155.          else if ((pid2 & (ID2_NEARLINE|ID2_FARLINE)) == ID2_FARLINE) return(FALSE);
  156.          break;
  157.       case selector_farline:
  158.          if      ((pid2 & (ID2_NEARLINE|ID2_FARLINE)) == ID2_FARLINE) return(TRUE);
  159.          else if ((pid2 & (ID2_NEARLINE|ID2_FARLINE)) == ID2_NEARLINE) return(FALSE);
  160.          break;
  161.       case selector_nearcolumn:
  162.          if      ((pid2 & (ID2_NEARCOL|ID2_FARCOL)) == ID2_NEARCOL) return(TRUE);
  163.          else if ((pid2 & (ID2_NEARCOL|ID2_FARCOL)) == ID2_FARCOL) return(FALSE);
  164.          break;
  165.       case selector_farcolumn:
  166.          if      ((pid2 & (ID2_NEARCOL|ID2_FARCOL)) == ID2_FARCOL) return(TRUE);
  167.          else if ((pid2 & (ID2_NEARCOL|ID2_FARCOL)) == ID2_NEARCOL) return(FALSE);
  168.          break;
  169.       case selector_nearbox:
  170.          if      ((pid2 & (ID2_NEARBOX|ID2_FARBOX)) == ID2_NEARBOX) return(TRUE);
  171.          else if ((pid2 & (ID2_NEARBOX|ID2_FARBOX)) == ID2_FARBOX) return(FALSE);
  172.          break;
  173.       case selector_farbox:
  174.          if      ((pid2 & (ID2_NEARBOX|ID2_FARBOX)) == ID2_FARBOX) return(TRUE);
  175.          else if ((pid2 & (ID2_NEARBOX|ID2_FARBOX)) == ID2_NEARBOX) return(FALSE);
  176.          break;
  177.       default:
  178.          fail("ERROR - selector failed to get initialized.");
  179.    }
  180.    
  181.    fail("Can't decide who are selected.");
  182.    /* NOTREACHED */
  183. }
  184.  
  185.  
  186.  
  187. /* Here are the predicates.  They will get put into the array "pred_table". */
  188.  
  189. /* ARGSUSED */
  190. static long_boolean selected(setup *real_people, int real_index,
  191.    int real_direction, int northified_index)
  192. {
  193.    return(selectp(real_people, real_index));
  194. }
  195.  
  196. /* ARGSUSED */
  197. static long_boolean unselect(setup *real_people, int real_index,
  198.    int real_direction, int northified_index)
  199. {
  200.    return(!selectp(real_people, real_index));
  201. }
  202.  
  203. /* ARGSUSED */
  204. static long_boolean select_near_select(setup *real_people, int real_index,
  205.    int real_direction, int northified_index)
  206. {
  207.    return(selectp(real_people, real_index) && selectp(real_people, real_index ^ 1));
  208. }
  209.  
  210. /* ARGSUSED */
  211. static long_boolean select_near_unselect(setup *real_people, int real_index,
  212.    int real_direction, int northified_index)
  213. {
  214.    return(selectp(real_people, real_index) && !selectp(real_people, real_index ^ 1));
  215. }
  216.  
  217. /* ARGSUSED */
  218. static long_boolean unselect_near_select(setup *real_people, int real_index,
  219.    int real_direction, int northified_index)
  220. {
  221.    return(!selectp(real_people, real_index) && selectp(real_people, real_index ^ 1));
  222. }
  223.  
  224. /* ARGSUSED */
  225. static long_boolean unselect_near_unselect(setup *real_people, int real_index,
  226.    int real_direction, int northified_index)
  227. {
  228.    return(!(selectp(real_people, real_index) || selectp(real_people, real_index ^ 1)));
  229. }
  230.  
  231. /* ARGSUSED */
  232. static long_boolean always(setup *real_people, int real_index,
  233.    int real_direction, int northified_index)
  234. {
  235.    return(TRUE);
  236. }
  237.  
  238. /* ARGSUSED */
  239. static long_boolean x22_miniwave(setup *real_people, int real_index,
  240.    int real_direction, int northified_index)
  241. {
  242.    int this_person = real_people->people[real_index].id1;
  243.    int other_index = real_index ^ (((real_direction << 1) & 2) ^ 1);
  244.    int other_person = real_people->people[other_index].id1;
  245.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  246. }
  247.  
  248. /* ARGSUSED */
  249. static long_boolean x22_couple(setup *real_people, int real_index,
  250.    int real_direction, int northified_index)
  251. {
  252.    int this_person = real_people->people[real_index].id1;
  253.    int other_index = real_index ^ (((real_direction << 1) & 2) ^ 1);
  254.    int other_person = real_people->people[other_index].id1;
  255.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  256. }
  257.  
  258. /* ARGSUSED */
  259. static long_boolean x22_facing_someone(setup *real_people, int real_index,
  260.    int real_direction, int northified_index)
  261. {
  262.    int this_person = real_people->people[real_index].id1;
  263.    int other_index = real_index ^ (((real_direction << 1) & 2) ^ 3);
  264.    int other_person = real_people->people[other_index].id1;
  265.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  266. }
  267.  
  268. /* ARGSUSED */
  269. static long_boolean x14_once_rem_miniwave(setup *real_people, int real_index,
  270.    int real_direction, int northified_index)
  271. {
  272.    int this_person = real_people->people[real_index].id1;
  273.    int other_person = real_people->people[real_index ^ 3].id1;
  274.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  275. }
  276.  
  277. /* ARGSUSED */
  278. static long_boolean x14_once_rem_couple(setup *real_people, int real_index,
  279.    int real_direction, int northified_index)
  280. {
  281.    int this_person = real_people->people[real_index].id1;
  282.    int other_person = real_people->people[real_index ^ 3].id1;
  283.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  284. }
  285.  
  286. /* ARGSUSED */
  287. static long_boolean same_in_quad(setup *real_people, int real_index,
  288.    int real_direction, int northified_index)
  289. {
  290.    int this_person = real_people->people[real_index].id1;
  291.    int other_person = real_people->people[real_index ^ 1].id1;
  292.    if (real_people->kind == s_1x6 && real_index >= 2)
  293.       other_person = real_people->people[7 - real_index].id1;
  294.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  295. }
  296.  
  297. /* ARGSUSED */
  298. static long_boolean opp_in_quad(setup *real_people, int real_index,
  299.    int real_direction, int northified_index)
  300. {
  301.    int this_person = real_people->people[real_index].id1;
  302.    int other_person = real_people->people[real_index ^ 1].id1;
  303.    if (real_people->kind == s_1x6 && real_index >= 2)
  304.       other_person = real_people->people[7 - real_index].id1;
  305.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  306. }
  307.  
  308. /* ARGSUSED */
  309. static long_boolean same_in_pair(setup *real_people, int real_index,
  310.    int real_direction, int northified_index)
  311. {
  312.    int this_person = real_people->people[real_index].id1;
  313.    int other_person = real_people->people[real_index ^ 7].id1;
  314.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  315. }
  316.  
  317. /* ARGSUSED */
  318. static long_boolean opp_in_pair(setup *real_people, int real_index,
  319.    int real_direction, int northified_index)
  320. {
  321.    int this_person = real_people->people[real_index].id1;
  322.    int other_person = real_people->people[real_index ^ 7].id1;
  323.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  324. }
  325.  
  326. /* ARGSUSED */
  327. static long_boolean opp_in_magic(setup *real_people, int real_index,
  328.    int real_direction, int northified_index)
  329. {
  330.    int this_person = real_people->people[real_index].id1;
  331.    int other_person = real_people->people[real_index ^ 6].id1;
  332.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  333. }
  334.  
  335. /* ARGSUSED */
  336. static long_boolean same_in_magic(setup *real_people, int real_index,
  337.    int real_direction, int northified_index)
  338. {
  339.    int this_person = real_people->people[real_index].id1;
  340.    int other_person = real_people->people[real_index ^ 6].id1;
  341.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  342. }
  343.  
  344. /* ARGSUSED */
  345. static long_boolean lines_once_rem_miniwave(setup *real_people, int real_index,
  346.    int real_direction, int northified_index)
  347. {
  348.    int this_person = real_people->people[real_index].id1;
  349.    int other_person = real_people->people[real_index ^ 2].id1;
  350.    return(((this_person ^ other_person) & DIR_MASK) == 2);
  351. }
  352.  
  353. /* ARGSUSED */
  354. static long_boolean lines_once_rem_couple(setup *real_people, int real_index,
  355.    int real_direction, int northified_index)
  356. {
  357.    int this_person = real_people->people[real_index].id1;
  358.    int other_person = real_people->people[real_index ^ 2].id1;
  359.    return(((this_person ^ other_person) & DIR_MASK) == 0);
  360. }
  361.  
  362. /* Next test is used for figuring out how to hinge. */
  363. /* Legal from 1x2. */
  364. /* Returns TRUE if this person is beau, or else this belle is in a miniwave with
  365.    the other person.  Returns FALSE if this belle is in a couple with the
  366.    other person.  Complains if this belle can't tell. */
  367. /* ARGSUSED */
  368. static long_boolean x12_beau_or_miniwave(setup *real_people, int real_index,
  369.    int real_direction, int northified_index)
  370. {
  371.    if (northified_index == 0)
  372.       return(TRUE);
  373.    else {
  374.       int other_person = real_people->people[real_index ^ 1].id1;
  375.       if (!other_person)
  376.          fail("Need a real person to work with."); 
  377.       return (((other_person & 2) >> 1) == real_index);
  378.    }
  379. }
  380.  
  381. /* Test for wheel and deal to be done 2FL-style, or beau side of 1FL.  Returns
  382.    false if belle side of 1FL.  Raises an error if wheel and deal can't be done. */
  383. /* ARGSUSED */
  384. static long_boolean x14_wheel_and_deal(setup *real_people, int real_index,
  385.    int real_direction, int northified_index)
  386. {
  387.    /* We assume people have already been checked for coupleness. */
  388.  
  389.    if (northified_index <= 1)
  390.       /* We are in the beau-side couple -- it's OK. */
  391.       return(TRUE);
  392.    else {
  393.       /* We are in the belle-side couple -- find the two people in the other couple.
  394.          Just "or" them to be sure we get someone.  They are already known
  395.          to be facing consistently if they are both there. */
  396.       int other_people = real_people->people[real_index ^ 2].id1 |
  397.                            real_people->people[real_index ^ 3].id1;
  398.  
  399.       /* At least one of those people must exist. */
  400.       if (!other_people)
  401.          fail("Can't tell how to do this -- no live people.");
  402.  
  403.       /* See if they face the same way as myself.  Note that the "2" bit of
  404.          real_index is the complement of my own direction bit. */
  405.       if (((other_people ^ real_index) & 2))
  406.          return(FALSE);   /* This is a 1FL. */
  407.  
  408.       return(TRUE);       /* This is a 2FL. */
  409.    }
  410. }
  411.  
  412.  
  413. /* Test for 3X3 wheel_and_deal to be done 2FL-style, or beau side of 1FL. */
  414. /* ARGSUSED */
  415. static long_boolean x16_wheel_and_deal(setup *real_people, int real_index,
  416.    int real_direction, int northified_index)
  417. {
  418.    /* We assume people have already been checked for coupleness. */
  419.  
  420.    if (northified_index <= 2)
  421.       /* We are in the beau-side triad -- it's OK. */
  422.       return(TRUE);
  423.    else {
  424.       /* We are in the belle-side triad -- find the three people in the other triad.
  425.          Just "or" them to be sure we get someone.  They are already known
  426.          to be facing consistently if they are all there. */
  427.       int other_side = real_index <= 2 ? 3 : 0;
  428.       int other_people = real_people->people[other_side].id1 |
  429.                            real_people->people[other_side+1].id1 |
  430.                            real_people->people[other_side+2].id1;
  431.  
  432.       /* At least one of those people must exist. */
  433.       if (!other_people)
  434.          fail("Can't tell how to do this -- no live people.");
  435.  
  436.       /* See if they face the same way as myself. */
  437.       if (((other_people ^ real_people->people[real_index].id1) & 2))
  438.          return(TRUE);    /* This is a 2FL. */
  439.  
  440.       return(FALSE);      /* This is a 1FL. */
  441.    }
  442. }
  443.  
  444.  
  445. /* Test for 4X4 wheel_and_deal to be done 2FL-style, or beau side of 1FL. */
  446. /* ARGSUSED */
  447. static long_boolean x18_wheel_and_deal(setup *real_people, int real_index,
  448.    int real_direction, int northified_index)
  449. {
  450.    /* We assume people have already been checked for coupleness. */
  451.  
  452.    if (northified_index <= 3)
  453.       /* We are in the beau-side quad -- it's OK. */
  454.       return(TRUE);
  455.    else {
  456.       /* We are in the belle-side quad -- find the three people in the other quad.
  457.          Just "or" them to be sure we get someone.  They are already known
  458.          to be facing consistently if they are all there. */
  459.       int other_side = (real_index&4) ^ 4;
  460.       int other_people = real_people->people[other_side].id1 |
  461.                            real_people->people[other_side+1].id1 |
  462.                            real_people->people[other_side+2].id1 |
  463.                            real_people->people[other_side+3].id1;
  464.  
  465.       /* At least one of those people must exist. */
  466.       if (!other_people)
  467.          fail("Can't tell how to do this -- no live people.");
  468.  
  469.       /* See if they face the same way as myself. */
  470.       if (((other_people ^ real_people->people[real_index].id1) & 2))
  471.          return(TRUE);    /* This is a 2FL. */
  472.  
  473.       return(FALSE);      /* This is a 1FL. */
  474.    }
  475. }
  476.  
  477.  
  478.  
  479. static long_boolean vert1(setup *real_people, int real_index,
  480.    int real_direction, int northified_index)
  481. {
  482.    int this_person = real_people->people[real_index].id1;
  483.    int other_person = real_people->people[real_index ^ (((real_direction << 1) & 2) | 1)].id1;
  484.    if (northified_index & 1)
  485.       return(((this_person ^ other_person) & DIR_MASK) == 0);
  486.    else
  487.       return(TRUE);
  488. }
  489.  
  490. static long_boolean vert2(setup *real_people, int real_index,
  491.    int real_direction, int northified_index)
  492. {
  493.    int this_person = real_people->people[real_index].id1;
  494.    int other_person = real_people->people[real_index ^ (((real_direction << 1) & 2) | 1)].id1;
  495.    if (northified_index & 1)
  496.       return(((this_person ^ other_person) & DIR_MASK) == 2);
  497.    else
  498.       return(FALSE);
  499. }
  500.  
  501. /* ARGSUSED */
  502. static long_boolean inner_active_lines(setup *real_people, int real_index,
  503.    int real_direction, int northified_index)
  504. {
  505.    if ((real_index+3) & 2)
  506.       return(northified_index >= 4);     /* I am an end */
  507.    else
  508.       return(                            /* I am a center */
  509.          (012 - ((real_index & 4) >> 1)) == (real_people->people[real_index ^ 1].id1 & 017));
  510. }
  511.  
  512. /* ARGSUSED */
  513. static long_boolean outer_active_lines(setup *real_people, int real_index,
  514.    int real_direction, int northified_index)
  515. {
  516.    if ((real_index+3) & 2)
  517.       return(northified_index < 4);      /* I am an end */
  518.    else
  519.       return(                            /* I am a center */
  520.          (010 + ((real_index & 4) >> 1)) == (real_people->people[real_index ^ 1].id1 & 017));
  521. }
  522.  
  523. /* ARGSUSED */
  524. static long_boolean judge_is_right(setup *real_people, int real_index,
  525.    int real_direction, int northified_index)
  526. {
  527.    int this_person = real_people->people[real_index].id1;
  528.    int f = this_person & 2;
  529.    return(
  530.       (((real_people->people[f ^ 2].id1 ^ this_person) & 013) == 0)       /* judge exists to my right */
  531.          &&
  532.       (((real_people->people[f].id1 ^ this_person) & 013) != 2));         /* we do not have another judge to my left */
  533. }
  534.  
  535. /* ARGSUSED */
  536. static long_boolean judge_is_left(setup *real_people, int real_index,
  537.    int real_direction, int northified_index)
  538. {
  539.    int this_person = real_people->people[real_index].id1;
  540.    int f = this_person & 2;
  541.    return(
  542.       (((real_people->people[f].id1 ^ this_person) & 013) == 2)           /* judge exists to my left */
  543.          &&
  544.       (((real_people->people[f ^ 2].id1 ^ this_person) & 013) != 0));     /* we do not have another judge to my right */
  545. }
  546.  
  547. /* ARGSUSED */
  548. static long_boolean socker_is_right(setup *real_people, int real_index,
  549.    int real_direction, int northified_index)
  550. {
  551.    int this_person = real_people->people[real_index].id1;
  552.    int f = this_person & 2;
  553.    return(
  554.       (((real_people->people[f ^ 2].id1 ^ this_person) & 013) == 2)       /* socker exists to my right */
  555.          &&
  556.       (((real_people->people[f].id1 ^ this_person) & 013) != 0));         /* we do not have another socker to my left */
  557. }
  558.  
  559. /* ARGSUSED */
  560. static long_boolean socker_is_left(setup *real_people, int real_index,
  561.    int real_direction, int northified_index)
  562. {
  563.    int this_person = real_people->people[real_index].id1;
  564.    int f = this_person & 2;
  565.    return(
  566.       (((real_people->people[f].id1 ^ this_person) & 013) == 0)           /* socker exists to my left */
  567.          &&
  568.       (((real_people->people[f ^ 2].id1 ^ this_person) & 013) != 2));     /* we do not have another socker to my right */
  569. }
  570.  
  571. /* ARGSUSED */
  572. static long_boolean inroller_is_cw(setup *real_people, int real_index,
  573.    int real_direction, int northified_index)
  574. {
  575.    int inroll_direction;
  576.  
  577.    inroll_direction = 012 - ((real_index & 4) >> 1);
  578.    if (  /* cw_end exists and is inrolling */
  579.          ((real_people->people[real_index | 3].id1 & 017) == inroll_direction)
  580.       &&
  581.          /* we do not have ccw_end inrolling also */
  582.          ((real_people->people[real_index & 4].id1 & 017) != inroll_direction))
  583.       return(TRUE);
  584.    else if (
  585.          /* ccw_end exists and is inrolling */
  586.          ((real_people->people[real_index & 4].id1 & 017) == inroll_direction)
  587.       &&
  588.          /* we do not have cw_end inrolling also */
  589.          ((real_people->people[real_index | 3].id1 & 017) != inroll_direction))
  590.       return(FALSE);
  591.    else {
  592.       fail("Can't find end looking in.");
  593.       /* NOTREACHED */
  594.   }
  595. }
  596.  
  597. /* ARGSUSED */
  598. static long_boolean magic_inroller_is_cw(setup *real_people, int real_index,
  599.    int real_direction, int northified_index)
  600. {
  601.    static int cw[8] = {3, 7, 7, 3, 7, 3, 3, 7};
  602.    static int cc[8] = {0, 4, 4, 0, 4, 0, 0, 4};
  603.    static int id[8] = {012, 010, 010, 012, 010, 012, 012, 010};
  604.    int inroll_direction;
  605.  
  606.    inroll_direction = id[real_index];
  607.    if (  /* cw_end exists and is inrolling */
  608.          ((real_people->people[cw[real_index]].id1 & 017) == inroll_direction)
  609.       &&
  610.          /* we do not have ccw_end inrolling also */
  611.          ((real_people->people[cc[real_index]].id1 & 017) != inroll_direction))
  612.       return(TRUE);
  613.    else if (
  614.          /* ccw_end exists and is inrolling */
  615.          ((real_people->people[cc[real_index]].id1 & 017) == inroll_direction)
  616.       &&
  617.          /* we do not have cw_end inrolling also */
  618.          ((real_people->people[cw[real_index]].id1 & 017) != inroll_direction))
  619.       return(FALSE);
  620.    else {
  621.       fail("Can't find end looking in.");
  622.       /* NOTREACHED */
  623.    }
  624. }
  625.  
  626. /* ARGSUSED */
  627. static long_boolean outroller_is_cw(setup *real_people, int real_index,
  628.    int real_direction, int northified_index)
  629. {
  630.    int outroll_direction;
  631.  
  632.    outroll_direction = 010 + ((real_index & 4) >> 1);
  633.    if (  /* cw_end exists and is outrolling */
  634.          ((real_people->people[real_index | 3].id1 & 017) == outroll_direction)
  635.       &&
  636.          /* we do not have ccw_end outrolling also */
  637.          ((real_people->people[real_index & 4].id1 & 017) != outroll_direction))
  638.       return(TRUE);
  639.    else if (
  640.          /* ccw_end exists and is outrolling */
  641.          ((real_people->people[real_index & 4].id1 & 017) == outroll_direction)
  642.       &&
  643.          /* we do not have cw_end outrolling also */
  644.          ((real_people->people[real_index | 3].id1 & 017) != outroll_direction))
  645.       return(FALSE);
  646.    else {
  647.       fail("Can't find end looking out.");
  648.       /* NOTREACHED */
  649.    }
  650. }
  651.  
  652. /* ARGSUSED */
  653. static long_boolean outposter_is_cw(setup *real_people, int real_index,
  654.    int real_direction, int northified_index)
  655. {
  656.    /* cw_end exists and is looking out */
  657.    return(((real_people->people[real_index | 3].id1 & 017) == (010 + ((real_index & 4) >> 1))));
  658. }
  659.  
  660. /* ARGSUSED */
  661. static long_boolean outposter_is_ccw(setup *real_people, int real_index,
  662.    int real_direction, int northified_index)
  663. {
  664.    /* ccw_end exists and is looking out */
  665.    return(((real_people->people[real_index & 4].id1 & 017) == (010 + ((real_index & 4) >> 1))));
  666. }
  667.  
  668. /* ARGSUSED */
  669. static long_boolean nexttrnglspot_is_tboned(setup *real_people, int real_index,
  670.    int real_direction, int northified_index)
  671. {
  672.    int z;
  673.    static int aa[4][3] = {
  674.       {-3, -2, -2}, {2, -2, 0}, {-3, 0, 0}, {1, 0, -2}};
  675.    int this_person = real_people->people[real_index].id1;
  676.  
  677.    z = aa[real_direction][real_index];
  678.    if (z < -2)
  679.       fail("Can't determine where to go or which way to face.");
  680.    else if (z == -2)
  681.       return(FALSE);
  682.    else {
  683.       z = real_people->people[z].id1;
  684.       if (z & BIT_PERSON)
  685.          return((z ^ this_person) & 1);
  686.       else {
  687.          fail("Can't determine where to go or which way to face.");
  688.      /* NOTREACHED */
  689.       }
  690.    }
  691. }
  692.  
  693. /* ARGSUSED */
  694. static long_boolean next62spot_is_tboned(setup *real_people, int real_index,
  695.    int real_direction, int northified_index)
  696. {
  697.    int z;
  698.    static int aa[4][6] = {
  699.       {-2, -3, -2, -2, -3, -2}, {-2, 2, -2, -2, 3, -2}, {-2, -3, -2, -2, -3, -2}, {-2, 0, -2, -2, 5, -2}};
  700.    int this_person = real_people->people[real_index].id1;
  701.  
  702.    z = aa[real_direction][real_index];
  703.    if (z < -2)
  704.       fail("Can't determine where to go or which way to face.");
  705.    else if (z == -2)
  706.       return(FALSE);
  707.    else {
  708.       z = real_people->people[z].id1;
  709.       if (z & BIT_PERSON)
  710.          return((z ^ this_person) & 1);
  711.       else {
  712.          fail("Can't determine where to go or which way to face.");
  713.      /* NOTREACHED */
  714.      }
  715.    }
  716. }
  717.  
  718. /* ARGSUSED */
  719. static long_boolean next_magic62spot_is_tboned(setup *real_people, int real_index,
  720.    int real_direction, int northified_index)
  721. {
  722.    int z;
  723.    static int aa[4][6] = {
  724.       {-3, -3, -3, -3, -3, -3}, {-2, 3, -2, -2, 2, -2}, {-3, -3, -3, -3, -3, -3}, {-2, 5, -2, -2, 0, -2}};
  725.    int this_person = real_people->people[real_index].id1;
  726.  
  727.    z = aa[real_direction][real_index];
  728.    if (z < -2)
  729.       fail("Can't determine where to go or which way to face.");
  730.    else if (z == -2)
  731.       return(FALSE);
  732.    else {
  733.       z = real_people->people[z].id1;
  734.       if (z & BIT_PERSON)
  735.          return((z ^ this_person) & 1);
  736.       else {
  737.          fail("Can't determine where to go or which way to face."); 
  738.          /* NOTREACHED */
  739.       }
  740.    }
  741. }
  742.  
  743. /* ARGSUSED */
  744. static long_boolean next_galaxyspot_is_tboned(setup *real_people, int real_index,
  745.    int real_direction, int northified_index)
  746. {
  747.    int z;
  748.    static int aa[4][8] = {
  749.       { 1,  2, -3,  2,  3,  4, -3,  0},
  750.       {-3,  2,  3,  4, -3,  4,  5,  6},
  751.       { 7,  0, -3,  4,  5,  6, -3,  6},
  752.       {-3,  0,  1,  2, -3,  6,  7,  0}};
  753.    int this_person = real_people->people[real_index].id1;
  754.  
  755.    /* We always return true for centers.  That way
  756.       the centers can reverse flip a galaxy even if the
  757.       next point does not exist.  Maybe this isn't a good way
  758.       to do it, and we need another predicate.  Sigh. */
  759.    if (real_index & 1) return(TRUE);
  760.  
  761.    z = aa[real_direction][real_index];
  762.    if (z >= -2) {
  763.       z = real_people->people[z].id1;
  764.       if (z & BIT_PERSON) return((z ^ this_person) & 1);
  765.    }
  766.    fail("Can't determine where to go or which way to face.");
  767.    /* NOTREACHED */
  768. }
  769.  
  770. /* ARGSUSED */
  771. static long_boolean column_double_down(setup *real_people, int real_index,
  772.    int real_direction, int northified_index)
  773. {
  774.    return(
  775.       (northified_index < 3)              /* unless #1 in column, it's easy */
  776.          ||
  777.       (northified_index > 4)
  778.          ||
  779.       /* if #1, my adjacent end must exist and face in */
  780.       (((((real_index + 2) & 4) ^ 1) + 1) == (real_people->people[real_index ^ 7].id1 & 017)));
  781. }
  782.  
  783. /* ARGSUSED */
  784. static long_boolean boyp(setup *real_people, int real_index,
  785.    int real_direction, int northified_index)
  786. {
  787.    return((real_people->people[real_index].id2 & ID2_BOY) != 0);
  788. }
  789.  
  790. /* ARGSUSED */
  791. static long_boolean girlp(setup *real_people, int real_index,
  792.    int real_direction, int northified_index)
  793. {
  794.    return((real_people->people[real_index].id2 & ID2_GIRL) != 0);
  795. }
  796.  
  797. /* ARGSUSED */
  798. static long_boolean roll_is_cw(setup *real_people, int real_index,
  799.    int real_direction, int northified_index)
  800. {
  801.    return((real_people->people[real_index].id1 & ROLLBITR) != 0);
  802. }
  803.  
  804. /* ARGSUSED */
  805. static long_boolean roll_is_ccw(setup *real_people, int real_index,
  806.    int real_direction, int northified_index)
  807. {
  808.    return((real_people->people[real_index].id1 & ROLLBITL) != 0);
  809. }
  810.  
  811. /* ARGSUSED */
  812. static long_boolean x12_boy_facing_girl(setup *real_people, int real_index,
  813.    int real_direction, int northified_index)
  814. {
  815.    int this_person = real_people->people[real_index].id2;
  816.    int other_person = real_people->people[real_index ^ 1].id2;
  817.    return((this_person & ID2_BOY) && (other_person & ID2_GIRL));
  818. }
  819.  
  820. /* ARGSUSED */
  821. static long_boolean x12_girl_facing_boy(setup *real_people, int real_index,
  822.    int real_direction, int northified_index)
  823. {
  824.    int this_person = real_people->people[real_index].id2;
  825.    int other_person = real_people->people[real_index ^ 1].id2;
  826.    return((this_person & ID2_GIRL) && (other_person & ID2_BOY));
  827. }
  828.  
  829. /* ARGSUSED */
  830. static long_boolean x22_boy_facing_girl(setup *real_people, int real_index,
  831.    int real_direction, int northified_index)
  832. {
  833.    int this_person = real_people->people[real_index].id2;
  834.    int other_person = real_people->people[real_index ^ (((real_direction << 1) & 2) ^ 3)].id2;
  835.    return((this_person & ID2_BOY) && (other_person & ID2_GIRL));
  836. }
  837.  
  838. /* ARGSUSED */
  839. static long_boolean x22_girl_facing_boy(setup *real_people, int real_index,
  840.    int real_direction, int northified_index)
  841. {
  842.    int other_person = real_people->people[real_index ^ (((real_direction << 1) & 2) ^ 3)].id2;
  843.    int this_person = real_people->people[real_index].id2;
  844.    return((this_person & ID2_GIRL) && (other_person & ID2_BOY));
  845. }
  846.  
  847. /* ARGSUSED */
  848. static long_boolean dmd_ctrs_rh(setup *real_people, int real_index,
  849.    int real_direction, int northified_index)
  850. {
  851.    if (real_people->people[1].id1 | real_people->people[3].id1) {
  852.       if (     (!real_people->people[1].id1 || (real_people->people[1].id1 & d_mask)==d_east) &&
  853.                (!real_people->people[3].id1 || (real_people->people[3].id1 & d_mask)==d_west) )
  854.          return(TRUE);
  855.       else if ((!real_people->people[1].id1 || (real_people->people[1].id1 & d_mask)==d_west) &&
  856.                (!real_people->people[3].id1 || (real_people->people[3].id1 & d_mask)==d_east) )
  857.          return(FALSE);
  858.    }
  859.  
  860.    fail("Can't determine handedness of centers.");
  861.    /* NOTREACHED */
  862. }
  863.  
  864. /* ARGSUSED */
  865. static long_boolean trngl_pt_rh(setup *real_people, int real_index,
  866.    int real_direction, int northified_index)
  867. {
  868.    if ((real_people->people[0].id1 & d_mask)==d_west)
  869.       return(TRUE);
  870.    else if ((real_people->people[0].id1 & d_mask)==d_east)
  871.       return(FALSE);
  872.  
  873.    fail("Can't determine handedness of triangle point.");
  874.    /* NOTREACHED */
  875. }
  876.  
  877. /* ARGSUSED */
  878. static long_boolean q_tag_front(setup *real_people, int real_index,
  879.    int real_direction, int northified_index)
  880. {
  881.    if (real_index & 2)
  882.       /* I am in the center line, see if I have a miniwave. */
  883.       return(((real_people->people[real_index].id1 ^ real_people->people[real_index ^ 1].id1) & DIR_MASK) == 2);
  884.    else {
  885.       /* I am on the outside; find the end of the center line nearest me. */
  886.       int z;
  887.       if (real_index & 1) z = real_index ^ 3; else z = real_index ^ 6;
  888.       return(((real_people->people[z].id1 & 017) == (010 + (real_index >> 1))) &&
  889.             (((real_people->people[z].id1 ^ real_people->people[z ^ 1].id1) & DIR_MASK) == 2));
  890.    }
  891. }
  892.  
  893. /* ARGSUSED */
  894. static long_boolean q_tag_back(setup *real_people, int real_index,
  895.    int real_direction, int northified_index)
  896. {
  897.    if (real_index & 2)
  898.       /* I am in the center line, see if I have a miniwave. */
  899.       return(((real_people->people[real_index].id1 ^ real_people->people[real_index ^ 1].id1) & DIR_MASK) == 2);
  900.    else {
  901.       /* I am on the outside; find the end of the center line nearest me. */
  902.       int z;
  903.       if (real_index & 1) z = real_index ^ 3; else z = real_index ^ 6;
  904.       return(((real_people->people[z].id1 & 017) == (012 - (real_index >> 1))) &&
  905.             (((real_people->people[z].id1 ^ real_people->people[z ^ 1].id1) & DIR_MASK) == 2));
  906.    }
  907. }
  908.  
  909. /* ARGSUSED */
  910. static long_boolean q_line_front(setup *real_people, int real_index,
  911.    int real_direction, int northified_index)
  912. {
  913.    if (real_index & 2)
  914.       /* I am in the center line, see if I have a couple. */
  915.       return(((real_people->people[real_index].id1 ^ real_people->people[real_index ^ 1].id1) & DIR_MASK) == 0);
  916.    else {
  917.       /* I am on the outside; find the end of the center line nearest me. */
  918.       int z;
  919.       if (real_index & 1) z = real_index ^ 3; else z = real_index ^ 6;
  920.       return(((real_people->people[z].id1 & 017) == (010 + (real_index >> 1))) &&
  921.             (((real_people->people[z].id1 ^ real_people->people[z ^ 1].id1) & DIR_MASK) == 0));
  922.    }
  923. }
  924.  
  925. /* ARGSUSED */
  926. static long_boolean q_line_back(setup *real_people, int real_index,
  927.    int real_direction, int northified_index)
  928. {
  929.    if (real_index & 2)
  930.       /* I am in the center line, see if I have a couple. */
  931.       return(((real_people->people[real_index].id1 ^ real_people->people[real_index ^ 1].id1) & DIR_MASK) == 0);
  932.    else {
  933.       /* I am on the outside; find the end of the center line nearest me. */
  934.       int z;
  935.       if (real_index & 1) z = real_index ^ 3; else z = real_index ^ 6;
  936.       return(((real_people->people[z].id1 & 017) == (012 - (real_index >> 1))) &&
  937.             (((real_people->people[z].id1 ^ real_people->people[z ^ 1].id1) & DIR_MASK) == 0));
  938.    }
  939. }
  940.  
  941. /* BEWARE!!  This list must track the array "predtab" in the database maker. */
  942.  
  943. /* The first 6 of these (the constant to use is SELECTOR_PREDS) take a predicate.
  944.    Any call that uses one of these predicates in its definition will cause a
  945.    popup to appear asking "who?". */
  946.  
  947. long_boolean (*pred_table[])(
  948.    setup *real_people,
  949.    int real_index,
  950.    int real_direction,
  951.    int northified_index) = {
  952.       selected,                        /* "select" */
  953.       unselect,                        /* "unselect" */
  954.       select_near_select,              /* "select_near_select" */
  955.       select_near_unselect,            /* "select_near_unselect" */
  956.       unselect_near_select,            /* "unselect_near_select" */
  957.       unselect_near_unselect,          /* "unselect_near_unselect" */
  958.       always,                          /* "always" */
  959.       x22_miniwave,                    /* "x22_miniwave" */
  960.       x22_couple,                      /* "x22_couple" */
  961.       x22_facing_someone,              /* "x22_facing_someone" */
  962.       x14_once_rem_miniwave,           /* "x14_once_rem_miniwave" */
  963.       x14_once_rem_couple,             /* "x14_once_rem_couple" */
  964.       opp_in_quad,                     /* "lines_miniwave" */
  965.       same_in_quad,                    /* "lines_couple" */
  966.       opp_in_magic,                    /* "lines_magic_miniwave" */
  967.       same_in_magic,                   /* "lines_magic_couple" */
  968.       lines_once_rem_miniwave,         /* "lines_once_rem_miniwave" */
  969.       lines_once_rem_couple,           /* "lines_once_rem_couple" */
  970.       same_in_pair,                    /* "lines_tandem" */
  971.       opp_in_pair,                     /* "lines_antitandem" */
  972.       same_in_quad,                    /* "columns_tandem" */
  973.       opp_in_quad,                     /* "columns_antitandem" */
  974.       same_in_magic,                   /* "columns_magic_tandem" */
  975.       opp_in_magic,                    /* "columns_magic_antitandem" */
  976.       lines_once_rem_couple,           /* "columns_once_rem_tandem" */
  977.       lines_once_rem_miniwave,         /* "columns_once_rem_antitandem" */
  978.       same_in_pair,                    /* "columns_couple" */
  979.       opp_in_pair,                     /* "columns_miniwave" */
  980.       x12_beau_or_miniwave,            /* "1x2_beau_or_miniwave" */
  981.       x14_wheel_and_deal,              /* "1x4_wheel_and_deal" */
  982.       x16_wheel_and_deal,              /* "1x6_wheel_and_deal" */
  983.       x18_wheel_and_deal,              /* "1x8_wheel_and_deal" */
  984.       vert1,                           /* "vert1" */
  985.       vert2,                           /* "vert2" */
  986.       inner_active_lines,              /* "inner_active_lines" */
  987.       outer_active_lines,              /* "outer_active_lines" */
  988.       judge_is_right,                  /* "judge_is_right" */
  989.       judge_is_left,                   /* "judge_is_left" */
  990.       socker_is_right,                 /* "socker_is_right" */
  991.       socker_is_left,                  /* "socker_is_left" */
  992.       inroller_is_cw,                  /* "inroller_is_cw" */
  993.       magic_inroller_is_cw,            /* "magic_inroller_is_cw" */
  994.       outroller_is_cw,                 /* "outroller_is_cw" */
  995.       outposter_is_cw,                 /* "outposter_is_cw" */
  996.       outposter_is_ccw,                /* "outposter_is_ccw" */
  997.       nexttrnglspot_is_tboned,         /* "nexttrnglspot_is_tboned" */
  998.       next62spot_is_tboned,            /* "next62spot_is_tboned" */
  999.       next_magic62spot_is_tboned,      /* "next_magic62spot_is_tboned" */
  1000.       next_galaxyspot_is_tboned,       /* "next_galaxyspot_is_tboned" */
  1001.       column_double_down,              /* "column_double_down" */
  1002.       boyp,                            /* "boyp" */
  1003.       girlp,                           /* "girlp" */
  1004.       roll_is_cw,                      /* "roll_is_cw" */
  1005.       roll_is_ccw,                     /* "roll_is_ccw" */
  1006.       x12_boy_facing_girl,             /* "x12_boy_facing_girl" */
  1007.       x12_girl_facing_boy,             /* "x12_girl_facing_boy" */
  1008.       x22_boy_facing_girl,             /* "x22_boy_facing_girl" */
  1009.       x22_girl_facing_boy,             /* "x22_girl_facing_boy" */
  1010.       dmd_ctrs_rh,                     /* "dmd_ctrs_rh" */
  1011.       trngl_pt_rh,                     /* "trngl_pt_rh" */
  1012.       q_tag_front,                     /* "q_tag_front" */
  1013.       q_tag_back,                      /* "q_tag_back" */
  1014.       q_line_front,                    /* "q_line_front" */
  1015.       q_line_back};                    /* "q_line_back" */
  1016.