home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume15
/
xstratego
/
part01
/
play.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-27
|
9KB
|
397 lines
/*
* Play.c
*/
#include "stratego.h"
static void announce_loser ();
void check_can_play ();
/*
* Remise Button Callback Routine.
*/
static Widget remise_button_widget = NULL;
void EnableRemiseButton()
{
if (remise_button_widget != NULL) {
XtSetSensitive(remise_button_widget, True);
remise_button_widget = NULL;
}
}
static XtCallbackProc Remise (widget)
Widget widget;
{
remise_button_widget = widget;
XtSetSensitive (widget, FALSE);
send_remise_offer ();
message ("On its way...");
}
/*
* Incoming remise offer.
*/
void RemiseOffered ()
{
char msg_buf[100];
sprintf (msg_buf, "%s offers a Remise. Do you accept %s?",
players[1].name, players[0].name);
if (DialogBoxResult (msg_buf, NULL, 0, ADD_CANCEL) == True) {
send_remise_answer (REMISE_ACCEPTED);
end_game ();
}
else
send_remise_answer (REMISE_DECLINED);
}
/*
* GiveUp button
*/
static XtCallbackProc GiveUp (widget)
Widget widget;
{
if (DialogBoxResult ("Loser!", NULL, 0, ADD_CANCEL) == True) {
send_quit ();
message ("You surrender unconditionally to %s...",
players[1].name);
end_game ();
}
}
/*
* Play module.
*/
static BUTTON play_buttons[] = {
" Remise ", Remise, TRUE, NULL,
" Message ", Mail, TRUE, NULL,
" Give Up ", GiveUp, TRUE, NULL,
};
void start_play ()
{
int i;
players[players[0].has_first_move ? 0 : 1].status = PL_PLAYING;
new_button_box (play_buttons, XtNumber(play_buttons));
if (players[0].has_first_move) {
players[0].status = PL_PLAYING;
message ("It is your move %s!", players[0].name);
check_can_play (O_PLAYER);
}
else {
message ("It is %s'%s move %s!", players[1].name,
(players[1].name[strlen (players[1].name) - 1] == 's') ? "" : "s", players[0].name);
check_can_play (O_ENEMY);
}
for (i = FLAG; i <= BOMB; i++)
UpdateTileCount (&tiles[i], tiles[i].available);
}
static Boolean legal_movement (from_pos, to_pos)
BOARD_POS *from_pos, *to_pos;
{
int y, x, dx, dy, dist_x, dist_y;
int from_x, from_y;
int legal;
from_x = from_pos->x;
from_y = from_pos->y;
y = to_pos->y;
x = to_pos->x;
dx = ((dist_x = from_x - x) < 0) ? 1 : -1;
dy = ((dist_y = from_y - y) < 0) ? 1 : -1;
if ((dist_x && dist_y) || (dist_x == 0 && dist_y == 0))
return False;
legal = 1;
if (abs (dist_x) > 1 || abs (dist_y) > 1) {
if (from_pos->value != SCOUT)
return False;
if (dist_x != 0) { /* Horizontal movement */
do {
from_x += dx;
legal = (board[from_y][from_x].value == FREE);
} while (from_x != x && legal);
}
else if (dist_y != 0) { /* Vertical movement */
do {
from_y += dy;
legal = (board[from_y][from_x].value == FREE);
} while (from_y != y && legal);
}
}
return legal ? True : False;
}
void play_tile (board_pos)
BOARD_POS *board_pos;
{
BOARD_POS *from_pos = players[0].from_pos;
if (players[0].status == PL_PLAYING) {
if (board_pos->value == FREE)
display_error (move_empty);
else if (board_pos->value == WATER)
display_error (illegal);
else if (board_pos->owner == O_ENEMY)
display_error (move_opponent);
else if (board_pos->value == FLAG)
display_error (move_flag);
else if (board_pos->value == BOMB)
display_error (move_bomb);
else {
players[0].status = PL_PICKED_UP;
players[0].from_pos = board_pos;
MarkBoardPosition (board_pos, True);
}
}
else if (players[0].status == PL_PICKED_UP) {
if (board_pos->value == WATER)
display_error (in_water);
else if (board_pos == from_pos)
;
else if (board_pos->owner == O_PLAYER)
display_error (kill_own);
else if (board_pos->value == FREE || board_pos->owner==O_ENEMY){
if (legal_movement (from_pos, board_pos)) {
switch (execute_move (from_pos, board_pos)) {
case DO_MOVE:
send_move (from_pos, board_pos);
players[0].status = PL_READY;
check_can_play (O_ENEMY);
break;
case REMISE_MOVE:
case WIN_MOVE:
send_move (from_pos, board_pos);
end_game ();
case UNDO_MOVE:
players[0].status = PL_PLAYING;
break;
}
return;
}
display_error (illegal);
}
/* Cancel move */
if (players[0].status == PL_PICKED_UP)
MarkBoardPosition (from_pos, False);
players[0].status = PL_PLAYING;
}
}
void ConfirmMove ()
{
AssignBoardPosition (players[0].from_pos, &tiles[FREE], O_NOBODY);
AssignBoardPosition (players[0].to_pos, players[0].to_tile,
players[0].to_owner);
players[0].confirm = False;
}
int execute_move (from_pos, to_pos)
BOARD_POS *from_pos, *to_pos;
{
TILE *from_tile, *to_tile;
int winner, move_type;
if (players[0].confirm)
ConfirmMove ();
players[0].from_pos = from_pos;
players[0].to_pos = to_pos;
from_tile = &tiles[from_pos->value];
to_tile = &tiles[to_pos->value];
if (to_pos->owner == O_NOBODY) {
/* Player move */
if (from_pos->owner == O_PLAYER) {
AssignBoardPosition (from_pos, &tiles[FREE], O_NOBODY);
AssignBoardPosition (to_pos, from_tile, O_PLAYER);
move_type = register_board (O_PLAYER);
if (move_type == UNDO_MOVE) {
AssignBoardPosition (from_pos, from_tile,
O_PLAYER);
AssignBoardPosition (to_pos, &tiles[FREE],
O_NOBODY);
}
return move_type;
}
/* Enemy move */
players[0].to_owner = from_pos->owner;
players[0].to_tile = from_tile;
players[0].confirm = True;
/* Show move on board */
AssignBoardPosition (from_pos, &tiles[ENEMY], from_pos->owner);
AssignBoardPosition (to_pos, &tiles[ENEMY], from_pos->owner);
MarkBoardPosition (from_pos, True);
MarkBoardPosition (to_pos, True);
/* Fill in right board values to register board setup */
from_pos->owner = O_NOBODY;
from_pos->value = tiles[FREE].value;
to_pos->owner = O_ENEMY;
to_pos->value = from_tile->value;
return register_board (O_ENEMY);
}
/* Battle stations */
MarkBoardPosition (from_pos, True);
MarkBoardPosition (to_pos, True);
if (to_tile->value == FLAG) {
UpdateTileCount (&tiles[FLAG], -1);
announce_loser (to_pos->owner);
return WIN_MOVE;
}
players[0].confirm = True;
if ((from_tile->value == SPY && to_tile->value == MARSHAL) ||
(from_tile->value == MINER && to_tile->value == BOMB) ||
(from_tile->value < to_tile->value && to_tile->value != BOMB)) {
players[0].to_owner = from_pos->owner;
players[0].to_tile = from_tile;
if ((winner = from_pos->owner) == O_PLAYER)
UpdateTileCount (to_tile, -1);
}
else if (to_tile->value == from_tile->value) {
players[0].to_owner = O_NOBODY;
players[0].to_tile = &tiles[FREE];
winner = (time (NULL) & 0x01) ? O_PLAYER : O_ENEMY;
UpdateTileCount (to_tile, -1);
}
else {
players[0].to_owner = to_pos->owner;
players[0].to_tile = to_tile;
winner = to_pos->owner;
if ((winner = to_pos->owner) == O_PLAYER)
UpdateTileCount (from_tile, -1);
}
display_error ((winner == O_PLAYER) ? win_capture : lose_capture);
register_hit ();
return DO_MOVE;
}
static void announce_loser (loser)
int loser;
{
if (loser == O_PLAYER)
message ("I'm afraid you bought it, old boy.");
else
message ("Nice one %s!", players[0].name);
}
void check_can_play (owner)
int owner;
{
BOARD_POS *board_pos;
int y, x, enemy;
enemy = (owner == O_PLAYER) ? O_ENEMY : O_PLAYER;
for (y = 0; y < MAX_ROWS; y++) {
for (x = 0; x < MAX_COLS; x++) {
board_pos = &board[y][x];
if (board_pos->owner != owner || board_pos->value <= FLAG ||
board_pos->value >= BOMB)
continue;
if (y - 1 >= 0 && (board[y - 1][x].value == FREE ||
board[y - 1][x].owner == enemy))
return;
if (y + 1 < MAX_ROWS && (board[y + 1][x].value == FREE ||
board[y + 1][x].owner == enemy))
return;
if (x - 1 >= 0 && (board[y][x - 1].value == FREE ||
board[y][x - 1].owner == enemy))
return;
if (x + 1 < MAX_COLS && (board[y][x + 1].value == FREE ||
board[y][x + 1].owner == enemy))
return;
}
}
announce_loser (owner);
end_game ();
}
/*
* End game routines.
*/
XtCallbackProc FastQuit (widget)
Widget widget;
{
XtDestroyApplicationContext (app_con);
exit (0);
}
static BUTTON endgame_buttons[] = {
" Quit ", FastQuit, TRUE, NULL,
" Store ", Store, TRUE, NULL
};
void end_game ()
{
BOARD_POS *board_pos;
int nr_buttons = XtNumber (endgame_buttons) - 1;
int y, x;
end_communications ();
if (players[0].confirm)
ConfirmMove ();
if (players[0].status <= PL_SETUP_READY)
nr_buttons++; /* Allow saving current position */
else { /* Show board */
for (y = 0; y < MAX_ROWS; y++) {
for (x = 0; x < MAX_COLS; x++) {
if (board[y][x].owner == O_ENEMY) {
board_pos = &board[y][x];
board_pos->value = abs(board_pos->value);
MarkBoardPosition (board_pos, True);
}
}
}
}
new_button_box (endgame_buttons, nr_buttons);
players[0].status = PL_ENDGAME;
}