home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume15 / xstratego / part01 / play.c < prev    next >
C/C++ Source or Header  |  1993-01-27  |  9KB  |  397 lines

  1. /*
  2.  * Play.c
  3.  */
  4.  
  5. #include "stratego.h"
  6.  
  7. static void announce_loser ();
  8. void check_can_play ();
  9.  
  10. /*
  11.  * Remise Button Callback Routine.
  12.  */
  13. static Widget remise_button_widget = NULL;
  14.  
  15. void EnableRemiseButton()
  16. {
  17.     if (remise_button_widget != NULL) {
  18.         XtSetSensitive(remise_button_widget, True);
  19.         remise_button_widget = NULL;
  20.     }
  21. }
  22.  
  23. static XtCallbackProc Remise (widget)
  24. Widget widget;
  25. {
  26.     remise_button_widget = widget;
  27.  
  28.     XtSetSensitive (widget, FALSE);
  29.  
  30.     send_remise_offer ();
  31.  
  32.     message ("On its way...");
  33. }
  34.  
  35. /*
  36.  * Incoming remise offer.
  37.  */
  38. void RemiseOffered ()
  39. {
  40.     char msg_buf[100];
  41.  
  42.     sprintf (msg_buf, "%s offers a Remise. Do you accept %s?",
  43.          players[1].name, players[0].name);
  44.  
  45.     if (DialogBoxResult (msg_buf, NULL, 0, ADD_CANCEL) == True) {
  46.         send_remise_answer (REMISE_ACCEPTED);
  47.         end_game ();
  48.     }
  49.     else
  50.         send_remise_answer (REMISE_DECLINED);
  51. }
  52.  
  53. /*
  54.  * GiveUp button
  55.  */
  56. static XtCallbackProc GiveUp (widget)
  57. Widget widget;
  58. {
  59.     if (DialogBoxResult ("Loser!", NULL, 0, ADD_CANCEL) == True) {
  60.         send_quit ();
  61.         message ("You surrender unconditionally to %s...",
  62.              players[1].name);
  63.         end_game ();
  64.     }
  65. }
  66.  
  67.  
  68. /*
  69.  * Play module.
  70.  */
  71. static BUTTON play_buttons[] = {
  72.     " Remise  ", Remise,    TRUE, NULL,
  73.     " Message ", Mail,      TRUE, NULL,
  74.     " Give Up ", GiveUp,    TRUE, NULL,
  75. };
  76.  
  77. void start_play ()
  78. {
  79.     int i;
  80.  
  81.     players[players[0].has_first_move ? 0 : 1].status = PL_PLAYING;
  82.  
  83.     new_button_box (play_buttons, XtNumber(play_buttons));
  84.  
  85.     if (players[0].has_first_move) {
  86.         players[0].status = PL_PLAYING;
  87.         message ("It is your move %s!", players[0].name);
  88.         check_can_play (O_PLAYER);
  89.     }
  90.     else {
  91.         message ("It is %s'%s move %s!", players[1].name, 
  92.             (players[1].name[strlen (players[1].name) - 1] == 's') ? "" : "s", players[0].name);
  93.         check_can_play (O_ENEMY);
  94.     }
  95.     
  96.     for (i = FLAG; i <= BOMB; i++)
  97.         UpdateTileCount (&tiles[i], tiles[i].available);
  98. }
  99.  
  100. static Boolean legal_movement (from_pos, to_pos)
  101. BOARD_POS *from_pos, *to_pos;
  102. {
  103.     int y, x, dx, dy, dist_x, dist_y;
  104.     int from_x, from_y;
  105.     int legal;
  106.  
  107.     from_x = from_pos->x;
  108.     from_y = from_pos->y;
  109.     y = to_pos->y;
  110.     x = to_pos->x;
  111.  
  112.     dx = ((dist_x = from_x - x) < 0) ? 1 : -1;
  113.     dy = ((dist_y = from_y - y) < 0) ? 1 : -1;
  114.  
  115.     if ((dist_x && dist_y) || (dist_x == 0 && dist_y == 0))
  116.         return False;
  117.  
  118.     legal = 1;
  119.  
  120.     if (abs (dist_x) > 1 || abs (dist_y) > 1) {
  121.         if (from_pos->value != SCOUT)
  122.             return False;
  123.  
  124.         if (dist_x != 0) {    /* Horizontal movement */
  125.             do {
  126.                 from_x += dx;
  127.                 legal = (board[from_y][from_x].value == FREE);
  128.             } while (from_x != x && legal);
  129.         }
  130.         else if (dist_y != 0) {    /* Vertical movement */
  131.             do {
  132.                 from_y += dy;
  133.                 legal = (board[from_y][from_x].value == FREE);
  134.             } while (from_y != y && legal);
  135.         }
  136.     }
  137.  
  138.     return legal ? True : False;
  139. }
  140.  
  141. void play_tile (board_pos)
  142. BOARD_POS *board_pos;
  143. {
  144.     BOARD_POS *from_pos = players[0].from_pos;
  145.  
  146.     if (players[0].status == PL_PLAYING) {
  147.         if (board_pos->value == FREE)
  148.             display_error (move_empty);
  149.         else if (board_pos->value == WATER)
  150.             display_error (illegal);
  151.         else if (board_pos->owner == O_ENEMY)
  152.             display_error (move_opponent);
  153.         else if (board_pos->value == FLAG)
  154.             display_error (move_flag);
  155.         else if (board_pos->value == BOMB)
  156.             display_error (move_bomb);
  157.         else {
  158.             players[0].status   = PL_PICKED_UP;
  159.             players[0].from_pos = board_pos;
  160.             MarkBoardPosition (board_pos, True);
  161.         }
  162.     }
  163.     else if (players[0].status == PL_PICKED_UP) {
  164.         if (board_pos->value == WATER)
  165.             display_error (in_water);
  166.         else if (board_pos == from_pos)
  167.             ;
  168.         else if (board_pos->owner == O_PLAYER)
  169.             display_error (kill_own);
  170.         else if (board_pos->value == FREE || board_pos->owner==O_ENEMY){
  171.             if (legal_movement (from_pos, board_pos)) {
  172.                 switch (execute_move (from_pos, board_pos)) {
  173.                 case DO_MOVE:
  174.                     send_move (from_pos, board_pos);
  175.                     players[0].status = PL_READY;
  176.                     check_can_play (O_ENEMY);
  177.                     break;
  178.                 case REMISE_MOVE:
  179.                 case WIN_MOVE:
  180.                     send_move (from_pos, board_pos);
  181.                     end_game ();
  182.                 case UNDO_MOVE:
  183.                     players[0].status = PL_PLAYING;
  184.                     break;
  185.                 }
  186.                 return;
  187.             }
  188.  
  189.             display_error (illegal);
  190.         }
  191.  
  192.     /* Cancel move */
  193.         if (players[0].status == PL_PICKED_UP)
  194.             MarkBoardPosition (from_pos, False);
  195.  
  196.         players[0].status = PL_PLAYING;
  197.  
  198.     }
  199. }
  200.  
  201. void ConfirmMove ()
  202. {
  203.     AssignBoardPosition (players[0].from_pos, &tiles[FREE], O_NOBODY);
  204.     AssignBoardPosition (players[0].to_pos, players[0].to_tile,
  205.                  players[0].to_owner);
  206.  
  207.     players[0].confirm = False;
  208. }
  209.  
  210. int execute_move (from_pos, to_pos)
  211. BOARD_POS *from_pos, *to_pos;
  212. {
  213.     TILE *from_tile, *to_tile;
  214.     int winner, move_type;
  215.  
  216.     if (players[0].confirm)
  217.         ConfirmMove ();
  218.  
  219.     players[0].from_pos = from_pos;
  220.     players[0].to_pos   = to_pos;
  221.  
  222.     from_tile = &tiles[from_pos->value];
  223.     to_tile   = &tiles[to_pos->value];
  224.  
  225.     if (to_pos->owner == O_NOBODY) {
  226.     /* Player move */
  227.         if (from_pos->owner == O_PLAYER) {
  228.             AssignBoardPosition (from_pos, &tiles[FREE], O_NOBODY);
  229.             AssignBoardPosition (to_pos, from_tile, O_PLAYER);
  230.  
  231.             move_type = register_board (O_PLAYER);
  232.             if (move_type == UNDO_MOVE) {
  233.                 AssignBoardPosition (from_pos, from_tile,
  234.                              O_PLAYER);
  235.                 AssignBoardPosition (to_pos, &tiles[FREE],
  236.                              O_NOBODY);
  237.             }
  238.  
  239.             return move_type;
  240.         }
  241.  
  242.     /* Enemy move */
  243.         players[0].to_owner = from_pos->owner;
  244.         players[0].to_tile  = from_tile;
  245.         players[0].confirm  = True;
  246.  
  247.     /* Show move on board */
  248.         AssignBoardPosition (from_pos, &tiles[ENEMY], from_pos->owner);
  249.         AssignBoardPosition (to_pos,   &tiles[ENEMY], from_pos->owner);
  250.         MarkBoardPosition (from_pos, True);
  251.         MarkBoardPosition (to_pos,   True);
  252.  
  253.     /* Fill in right board values to register board setup */
  254.         from_pos->owner = O_NOBODY;
  255.         from_pos->value = tiles[FREE].value;
  256.         to_pos->owner   = O_ENEMY;
  257.         to_pos->value   = from_tile->value;
  258.  
  259.         return register_board (O_ENEMY);
  260.     }
  261.  
  262. /* Battle stations */
  263.     MarkBoardPosition (from_pos, True);
  264.     MarkBoardPosition (to_pos,   True);
  265.  
  266.     if (to_tile->value == FLAG) {
  267.         UpdateTileCount (&tiles[FLAG], -1);
  268.         announce_loser (to_pos->owner);
  269.         return WIN_MOVE;
  270.     }
  271.  
  272.     players[0].confirm = True;
  273.  
  274.     if ((from_tile->value == SPY   && to_tile->value == MARSHAL) ||
  275.         (from_tile->value == MINER && to_tile->value == BOMB) ||
  276.         (from_tile->value < to_tile->value && to_tile->value != BOMB)) {
  277.         players[0].to_owner = from_pos->owner;
  278.         players[0].to_tile  = from_tile;
  279.         if ((winner = from_pos->owner) == O_PLAYER)
  280.             UpdateTileCount (to_tile, -1);
  281.     }
  282.     else if (to_tile->value == from_tile->value) {
  283.         players[0].to_owner = O_NOBODY;
  284.         players[0].to_tile  = &tiles[FREE];
  285.         winner = (time (NULL) & 0x01) ? O_PLAYER : O_ENEMY;
  286.         UpdateTileCount (to_tile, -1);
  287.     }
  288.     else {
  289.         players[0].to_owner = to_pos->owner;
  290.         players[0].to_tile  = to_tile;
  291.         winner = to_pos->owner;
  292.         if ((winner = to_pos->owner) == O_PLAYER)
  293.             UpdateTileCount (from_tile, -1);
  294.     }
  295.  
  296.     display_error ((winner == O_PLAYER) ? win_capture : lose_capture);
  297.  
  298.     register_hit ();
  299.  
  300.     return DO_MOVE;
  301. }
  302.  
  303. static void announce_loser (loser)
  304. int loser;
  305. {
  306.     if (loser == O_PLAYER)
  307.         message ("I'm afraid you bought it, old boy.");
  308.     else
  309.         message ("Nice one %s!", players[0].name);
  310. }
  311.  
  312. void check_can_play (owner)
  313. int owner;
  314. {
  315.     BOARD_POS *board_pos;
  316.     int y, x, enemy;
  317.  
  318.     enemy = (owner == O_PLAYER) ? O_ENEMY : O_PLAYER;
  319.  
  320.     for (y = 0; y < MAX_ROWS; y++) {
  321.         for (x = 0; x < MAX_COLS; x++) {
  322.         board_pos = &board[y][x];
  323.         if (board_pos->owner != owner || board_pos->value <= FLAG  ||
  324.                              board_pos->value >= BOMB)
  325.             continue;
  326.  
  327.         if (y - 1 >= 0 && (board[y - 1][x].value == FREE ||
  328.                        board[y - 1][x].owner == enemy))
  329.             return;
  330.  
  331.         if (y + 1 < MAX_ROWS && (board[y + 1][x].value == FREE ||
  332.                      board[y + 1][x].owner == enemy))
  333.             return;
  334.  
  335.         if (x - 1 >= 0 && (board[y][x - 1].value == FREE ||
  336.                        board[y][x - 1].owner == enemy))
  337.             return;
  338.  
  339.         if (x + 1 < MAX_COLS && (board[y][x + 1].value == FREE ||
  340.                      board[y][x + 1].owner == enemy))
  341.             return;
  342.  
  343.         }
  344.     }
  345.  
  346.     announce_loser (owner);
  347.     end_game ();
  348. }
  349.  
  350. /*
  351.  * End game routines.
  352.  */
  353.  
  354.  
  355. XtCallbackProc FastQuit (widget)
  356. Widget widget;
  357. {
  358.     XtDestroyApplicationContext (app_con);
  359.     exit (0);
  360. }
  361.  
  362. static BUTTON endgame_buttons[] = {
  363.     " Quit ",  FastQuit,  TRUE, NULL,
  364.     " Store ", Store,     TRUE, NULL
  365. };
  366.  
  367.  
  368. void end_game ()
  369. {
  370.     BOARD_POS *board_pos;
  371.     int nr_buttons = XtNumber (endgame_buttons) - 1;
  372.     int y, x;
  373.  
  374.     end_communications ();
  375.  
  376.     if (players[0].confirm)
  377.         ConfirmMove ();
  378.  
  379.     if (players[0].status <= PL_SETUP_READY)
  380.         nr_buttons++;        /* Allow saving current position */
  381.     else {                /* Show board              */
  382.         for (y = 0; y < MAX_ROWS; y++) { 
  383.             for (x = 0; x < MAX_COLS; x++) { 
  384.                 if (board[y][x].owner == O_ENEMY) {
  385.                        board_pos = &board[y][x];
  386.                        board_pos->value = abs(board_pos->value);
  387.                        MarkBoardPosition (board_pos, True);
  388.                 }
  389.             }
  390.         }
  391.     }
  392.  
  393.     new_button_box (endgame_buttons, nr_buttons);
  394.  
  395.     players[0].status = PL_ENDGAME;
  396. }
  397.