jsy@poplar.cray.com (Jeff Young) (09/12/90)
Submitted-by: jsy@poplar.cray.com (Jeff Young) Posting-number: Volume 9, Issue 21 Archive-name: xmahjongg/part01 Here is the first of 5 shar files for an updated xmahjongg. It is almost totally rewritten, so that I am just submitting sources instead of patches. Jeff Young jsy@cray.com #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # If this archive is complete, you will see the following message at the end: # "End of archive 1 (of 5)." # # Contents: # draw.c event.c initial.c packet.c play.c random.c sysdep.c # variables.c xmahjongg.c # # Wrapped by jsy@cray.com on Sun Sep 9 12:43:56 1990 # PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f draw.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"draw.c\" else echo shar: Extracting \"draw.c\" \(7171 characters\) sed "s/^X//" >draw.c <<'END_OF_draw.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#include <stdio.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include <sys/time.h> X#include "xmahjongg.h" X#include "variables.h" X X#define DRAW_NAME(pp) { \ X int xpos = X_NAMES; \ X \ X sprintf((char *)buffer, "%8.8s", pp->name); \ X draw_string((char *)buffer, xpos, pp->y, XGameTextGC[0]); \ X} X X#define DRAW_BOARD(pp, pos) { \ X int xpos = X_BOARD+50*pos; \ X \ X sprintf((char *)buffer, "%5.5d", pp->board[pos]); \ X draw_string((char *)buffer, xpos, Y_BOARD, XGameTextGC[0]); \ X} X X#define DRAW_SCORE(pp, pos) { \ X int itmp; \ X int xpos = pp->x+50*pos; \ X int score = pp->tiles[pos]; \ X \ X if (score < 0) score *= -1; \ X itmp = (pp->tiles[pos] > 0) ? 0 : 1; \ X sprintf((char *)buffer, " %3.3d ", score); \ X draw_string((char *)buffer, xpos, pp->y, XGameTextGC[itmp]); \ X} X X#define DRAW_TOTAL(pp, pos) { \ X int itmp; \ X int xpos = X_BOARD+50*pos; \ X \ X sprintf((char *)buffer, "TOTAL"); \ X draw_string((char *)buffer, xpos, Y_BOARD, XGameTextGC[0]); \ X xpos = pp->x + 50*pos; \ X itmp = (pp->quit == 0) ? 0 : 1; \ X sprintf((char *)buffer, " %3.3d ", pp->total); \ X draw_string((char *)buffer, xpos, pp->y, XGameTextGC[itmp]); \ X} X Xchar copy[] = "(c) 1990 by Jeff Young. "; Xchar rights[] = "All rights reserved. "; X Xdraw_user(pp, type) XPlayer *pp; Xint type; X{ X int i; X char buffer[20]; X GC userGC; X X if (type == GAME_START) { X DRAW_NAME(pp); X X for (i = 0; i < MAX_BOARDS; i++) { X if (pp->tiles[i] > TILES) break; X DRAW_BOARD(pp, i); X DRAW_SCORE(pp, i); X }; X X DRAW_TOTAL(pp, num_games); X } else if (type == GAME_PLAY) { X DRAW_BOARD(pp, pp->done); X DRAW_SCORE(pp, pp->done); X DRAW_TOTAL(pp, num_games); X } else if (type == GAME_DONE) { X DRAW_BOARD(pp, pp->done); X DRAW_SCORE(pp, pp->done); X } else if (type == GAME_QUIT) { X DRAW_BOARD(pp, pp->done); X DRAW_SCORE(pp, pp->done); X DRAW_TOTAL(pp, num_games); X } else { X fprintf(stderr, "bad draw_user type (%d)\n", type); X exit(1); X }; X X return(0); X} X Xdraw_data() X{ X int i, j, x, y; X char string[2]; X X/* X * Display the tiles on the screen before the start of the game. Order: X * dragons, seasons, plants, directions, circles, bamboos, ideographs. X * The 'if' statement below is just a way to figure out the x and y X * coordinates of the tiles. X * X */ X for (i = 10; i <= 51; i++) { X if ((10 <= i) && (i <= 12)) { X j = 6; X x = 2*(i%9); X y = 198; X } else if ((13 <= i) && (i <= 16)) { X j = 5; X x = (2*i + 7)%8; X y = 278 + 80*((i-13)/4); X } else if ((17 <= i) && (i <= 20)) { X j = 4; X x = (2*i + 7)%8; X y = 278 + 80*((i-13)/4); X } else if ((21 <= i) && (i <= 24)) { X j = 3; X x = (2*i + 7)%8; X y = 278 + 80*((i-13)/4); X } else if ((25 <= i) && (i <= 33)) { X j = 1; X x = (i+2)%9; X y = 278 + 80*((i+2)/9); X } else if ((34 <= i) && (i <= 42)) { X j = 0; X x = (i+2)%9; X y = 278 + 80*((i+2)/9); X } else if ((43 <= i) && (i <= 51)) { X j = 2; X x = (i+2)%9; X y = 278 + 80*((i+2)/9); X }; X X x = 42 + 106*x; X string[0] = tile_data[i]; X XDrawImageString(XGameDisplay, XGameWindow, X XGameTileGC[j][0], x, y, string, 1); X }; X X return(0); X} X Xdraw_tiles() X{ X int i, j, k; X char string[2]; X Tile *tp; X X XClearWindow(XGameDisplay, XGamePlayWindow); X X XCopyArea(XGameDisplay, XGamePlayWindow, XGamePixmap, XGameTextGC[0], X 0, 0, PLAY_WIDTH, PLAY_HEIGHT, 0, 0); X X for (i = 0, tp = order[0]; i < TILES; i++, tp = order[i]) { X if (tp == NULL) break; X if (tp->state != USED) continue; X string[0] = tp->data; X j = (tp != tile1p) ? 0 : 1; X k = (color_type == 0) ? tp->lev : (tp->data/16) - 1; X XDrawImageString(XGameDisplay, XGamePixmap, X XGameTileGC[k][j], tp->x, tp->y, string, 1); X X draw_border(tp->x, tp->y); X }; X X XCopyArea(XGameDisplay, XGamePixmap, XGamePlayWindow, XGameTextGC[0], X 0, 0, PLAY_WIDTH, PLAY_HEIGHT, 0, 0); X X XFlush(XGameDisplay); X X return(0); X} X Xdraw_count() X{ X char string[4]; X int count = (done_count != 0) ? done_count : tiles_remaining; X X string[0] = count/100; X string[1] = (count/10)%10; X string[2] = count%10; X X XDrawImageString(XGameDisplay, XGameCountWindow, XGameOtherGC[0], X 0, 0, string, 3); X X XFlush(XGameDisplay); X X return(0); X} X Xdraw_border(x, y) Xint x; Xint y; X{ X int i; X X for (i = 0; i < 12; i++) { X XGamePoint[i].x += x; X XGamePoint[i].y += y; X }; X X XDrawLines(XGameDisplay, XGamePixmap, XGameBorderGC, XGamePoint, X 12, CoordModeOrigin); X X for (i = 0; i < 12; i++) { X XGamePoint[i].x -= x; X XGamePoint[i].y -= y; X }; X X return(0); X} X Xdraw_letter(index, x, y) Xint index; Xint x; Xint y; X{ X char string[2]; X X string[0] = index; X string[1] = index+16; X X XDrawImageString(XGameDisplay, XGameWindow, XGameOtherGC[0], X x, y+00, &string[0], 1); X XDrawImageString(XGameDisplay, XGameWindow, XGameOtherGC[0], X x, y+64, &string[1], 1); X X XFlush(XGameDisplay); X X return(0); X} X Xdraw_window() X{ X int i, k, x, y; X char string[64]; X X k = XGameTextFont->ascent + XGameTextFont->descent + 1; X x = 55; X y = (Y_COUNT-4*k)/2; X X/* X * Print out the strings in the upper window X */ X XClearWindow(XGameDisplay, XGameWindow); X X sprintf(string, "Board number: %5d", seed); X draw_string(copy, x, y+0*k, XGameTextGC[1]); X draw_string(rights, x, y+1*k, XGameTextGC[1]); X draw_string(string, x, y+3*k, XGameTextGC[1]); X X draw_matches(); X X/* X * If in tournament mode, then reprint the current scores X */ X if (tourn_flag != 0) { X for (i = 0, pp = player; i < num_players; i++, pp++) { X pp->y = Y_SCORE+i*k; X draw_user(pp, GAME_START); X }; X }; X X XFlush(XGameDisplay); X X return(0); X} X Xdraw_option(index, window) Xint index; XWindow window; X{ X int i; X char string[2]; X X X string[0] = index; X i = ((window == XGameDoneWindow) && (done_count != 0)) ? 1 : 0; X XDrawImageString(XGameDisplay, window, XGameOtherGC[i], X 0, 0, string, 1); X XFlush(XGameDisplay); X X return(0); X} X Xdraw_string(data, x, y, imageGC) Xchar *data; Xint x, y; XGC imageGC; X{ X X XDrawImageString(XGameDisplay, XGameWindow, imageGC, X x, y, data, strlen(data)); X X XFlush(XGameDisplay); X X return(0); X} X Xdraw_matches() { X int i, j, k; X int matches = 0; X char string[80]; X Tile *t1p, *t2p; X X if (done_count == 0) return(0); X X/* X * Count the number of matches remaining. X */ X for(i = 0, t1p = &tiles[0][0][0]; i < ROWS*COLS*LEVS-1; i++, t1p++) { X if (t1p->state != USED) continue; X if (not_free(t1p->row, t1p->col, t1p->lev)) continue; X X for(j = i+1, t2p = t1p+1; j < ROWS*COLS*LEVS; j++, t2p++) { X if (t2p->state != USED) continue; X if (not_free(t2p->row, t2p->col, t2p->lev)) continue; X if (t1p->type == t2p->type) matches++; X }; X }; X X/* X * Display the number of matches. X */ X i = XGameTextFont->ascent; X j = XGameTextFont->descent; X k = (184-Y_DONE-OPTION_HEIGHT-i-j)/2; X sprintf(string, " Matches remaining = %3d ", matches); X draw_string(string, 800, Y_DONE+OPTION_HEIGHT+k+i, XGameTextGC[1]); X XFlush(XGameDisplay); X X return(0); X} END_OF_draw.c if test 7171 -ne `wc -c <draw.c`; then echo shar: \"draw.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f event.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"event.c\" else echo shar: Extracting \"event.c\" \(8545 characters\) sed "s/^X//" >event.c <<'END_OF_event.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#include <stdio.h> X#include <signal.h> X#include <sys/time.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include "xmahjongg.h" X#include "variables.h" X Xevent_process() { X int readfds; X X/* X * Wait for an event and then process it. X */ X event_wait(); X Xnext_event: X XNextEvent(XGameDisplay, &XGameEvent); X switch (XGameEvent.type) { X case Expose: X if (XGameEvent.xexpose.count != 0) goto next_event; X event_expose(); X break; X case ButtonPress: X event_button(); X break; X default: X break; X }; X X return(0); X} X Xevent_packet(readfds) Xint readfds; X{ X int i; X X for (i = 0, pp = player; i < num_players; i++, pp++) { X if (pp->type == 'M') continue; X if ((readfds & (1 << pp->fd)) != 0) { X packet_recv(pp->fd); X }; X }; X X return(0); X} X Xevent_expose() { X X if (XGameEvent.xexpose.window == XGameWindow) { X draw_window(); X } else if (XGameEvent.xexpose.window == XGameNewWindow) { X draw_option(INDEX_NEW, XGameNewWindow); X } else if (XGameEvent.xexpose.window == XGameDoneWindow) { X draw_option(INDEX_DONE, XGameDoneWindow); X } else if (XGameEvent.xexpose.window == XGameQuitWindow) { X draw_option(INDEX_QUIT, XGameQuitWindow); X } else if (XGameEvent.xexpose.window == XGameSameWindow) { X draw_option(INDEX_SAME, XGameSameWindow); X } else if (XGameEvent.xexpose.window == XGamePlayWindow) { X draw_tiles(); X } else if (XGameEvent.xexpose.window == XGameCountWindow) { X draw_count(); X }; X X return(0); X} X Xevent_button() { X int i, j, k; X X if (XGameEvent.xbutton.window == XGameNewWindow) { X event_new(); X } else if (XGameEvent.xbutton.window == XGameDoneWindow) { X event_done(); X } else if (XGameEvent.xbutton.window == XGameSameWindow) { X event_same(); X } else if (XGameEvent.xbutton.window == XGameQuitWindow) { X event_quit(); X } else if (XGameEvent.xbutton.window == XGamePlayWindow) { X event_play(); X }; X X return(0); X} X Xevent_new() { X int i, j, k; X X/* X * If this is a tournament, the the user can't go to a new board X * unless this is not the last game in the series. X */ X if ((tourn_flag != 0) && (mypp->done == num_games-1)) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X return(0); X }; X X/* X * If this is setup mode, then clear all of the tiles. X */ X if (setup_flag != 0) { X for (i = 0; i < TILES; i++) { X order[i] = NULL; X }; X X for (i = 0; i < ROWS; i++) { X for (j = 0; j < COLS; j++) { X for (k = 0; k < LEVS; k++) { X tiles[i][j][k].state = FREE; X }; X }; X }; X }; X X/* X * Clear all the windows. X */ X keep_playing = 0; X packet_send(GAME_DONE); X XClearArea(XGameDisplay, XGameWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameNewWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameDoneWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameSameWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameQuitWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGamePlayWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameCountWindow, 0, 0, 0, 0, True); X XFlush(XGameDisplay); X X return(0); X} X Xevent_same() { X X/* X * If this is a tournament, then the user can't play the same board X * twice. If this is setup mode, then do nothing; X */ X if ((num_games != 0) || (setup_flag != 0)) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X } else { X seed = -seed; X keep_playing = 0; X XClearArea(XGameDisplay, XGameWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameNewWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameDoneWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameSameWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameQuitWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGamePlayWindow, 0, 0, 0, 0, True); X XClearArea(XGameDisplay, XGameCountWindow, 0, 0, 0, 0, True); X XFlush(XGameDisplay); X }; X X return(0); X} X Xevent_done() { X int i; X FILE *stdconf; X X/* X * If this is not setup mode, then mark the game as done and display X * the matches remaining. X */ X if (setup_flag == 0) { X if (done_count == 0) { X done_count = tiles_remaining; X packet_send(GAME_DONE); X }; X X draw_option(INDEX_DONE, XGameDoneWindow); X draw_matches(); X return(0); X }; X X/* X * For setup mode, we must check to be sure that all the tiles have X * been placed. If they have, then write out the configuration file. X */ X if (tiles_remaining != 0) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X return(0); X }; X X/* X * Open the configuration file. X */ X if (layout != NULL) { X if ((stdconf = fopen(layout, "w")) == NULL) { X fprintf(stderr, "can't open layout file\n"); X exit(1); X }; X } else { X stdconf = stdout; X }; X X/* X * Dump out the configuration. X */ X for (i = 0; i < TILES; i++) { X fprintf(stdconf, "%3d %3d %3d\n", X order[i]->row, order[i]->col, order[i]->lev); X }; X X fclose(stdconf); X event_quit(); X X return(0); X} X Xevent_quit() { X int i; X X packet_send(GAME_QUIT); X X/* X * Free all of the X resources which we grabbed. X */ X XUnloadFont(XGameDisplay, XGameTextFont->fid); X XUnloadFont(XGameDisplay, XGameTileFont->fid); X X XFreeGC(XGameDisplay, XGameBorderGC); X XFreeGC(XGameDisplay, XGameTextGC[0]); X XFreeGC(XGameDisplay, XGameTextGC[1]); X XFreeGC(XGameDisplay, XGameOtherGC[0]); X XFreeGC(XGameDisplay, XGameOtherGC[1]); X X for (i = 0; i < LEVS; i++) { X XFreeGC(XGameDisplay, XGameTileGC[i][0]); X XFreeGC(XGameDisplay, XGameTileGC[i][1]); X }; X X XFreeCursor(XGameDisplay, XGameCursor); X XFreePixmap(XGameDisplay, XGamePixmap); X X XCloseDisplay(XGameDisplay); X X exit(0); X} X Xevent_play() { X int i, j, k; X int x, y; X X x_coor = XGameEvent.xbutton.x; X y_coor = XGameEvent.xbutton.y; X X/* X * If we are in setup mode, then call the routine which will create a X * new tile or delete one from the board. X */ X if (setup_flag != 0) { X if (XGameEvent.xbutton.button == Button1) { X event_create(); X } else { X event_delete(); X }; X X return(0); X }; X X/* X * We are in play mode. Check the make sure the button was pushed on a X * tile. X */ X for (k = LEVS-1; k >= 0; k--) { X x = (y_coor - Y_TILE + (4*k))/(TILE_SIDE/2); X y = (x_coor - X_TILE - (4*k))/(TILE_SIDE/2); X X for (i = 0; i < 2; i++) { X for (j = 0; j < 2; j++) { X if (in_bounds(x-i, y-j)) { X if (tiles[x-i][y-j][k].state == USED) { X play_tile(&tiles[x-i][y-j][k]); X return(0); X }; X }; X }; X }; X }; X X/* X * The button was pushed in a bad area. We beep the bell and continue. X */ X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X X return(0); X} X Xevent_create() { X int i, j, k; X int x, y; X X if (tiles_remaining == 0) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X return(0); X } else if (x_coor < X_TILE) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X return(0); X } else if (y_coor < Y_TILE) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X return(0); X }; X X/* X * Check the make sure the button was pushed on a tile. X */ X for (k = 0; k < LEVS; k++) { X x = (y_coor - Y_TILE + (4*k))/(TILE_SIDE/2); X y = (x_coor - X_TILE - (4*k))/(TILE_SIDE/2); X X for (i = 0; i < 2; i++) { X for (j = 0; j < 2; j++) { X if (in_bounds(x-i, y-j) == 0) continue; X if (ok_below(x-i, y-j, k) != 0) continue; X if (tiles[x-i][y-j][k].state == USED) continue; X create_tile(&tiles[x-i][y-j][k]); X return(0); X }; X }; X }; X X/* X * The button was pushed in a bad area. We beep the bell and continue. X */ X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X X return(0); X} X Xevent_delete() { X int i, j, k; X int x, y; X X if (tiles_remaining == TILES) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X return(0); X } else if (x_coor < X_TILE) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X return(0); X } else if (y_coor < Y_TILE) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X return(0); X }; X X/* X * Check the make sure the button was pushed on a tile. X */ X for (k = LEVS-1; k >= 0; k--) { X x = (y_coor - Y_TILE + (4*k))/(TILE_SIDE/2); X y = (x_coor - X_TILE - (4*k))/(TILE_SIDE/2); X X for (i = 0; i < 2; i++) { X for (j = 0; j < 2; j++) { X if (in_bounds(x-i, y-j) == 0) continue; X if (ok_above(x-i, y-j, k) != 0) continue; X if (tiles[x-i][y-j][k].state == FREE) continue; X delete_tile(&tiles[x-i][y-j][k]); X return(0); X }; X }; X }; X X/* X * The button was pushed in a bad area. We beep the bell and continue. X */ X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X X return(0); X} END_OF_event.c if test 8545 -ne `wc -c <event.c`; then echo shar: \"event.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f initial.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"initial.c\" else echo shar: Extracting \"initial.c\" \(19579 characters\) sed "s/^X//" >initial.c <<'END_OF_initial.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#include <netdb.h> X#include <stdio.h> X#include <signal.h> X#include <sys/time.h> X#include <sys/types.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include <X11/cursorfont.h> X#include "xmahjongg.h" X#include "variables.h" X#include "icon.h" X Xint initial_flag = 0; Xchar copyright[] = " Copyright (c) 1990 by Jeff Young (exceptions). All rights reserved. "; X Xinitialize() { X X initialize_conf(); X initialize_data(); X initialize_pool(); X initialize_tiles(); X initialize_socket(); X initialize_window(); X X return(0); X} X Xinitialize_conf() { X int i, j, k; X int cnt, row, col, lev; X char line[128], file[128]; X FILE *stdconf; X X if (initial_flag != 0) return(0); X if (setup_flag != 0) return(0); X X/* X * Set all tiles to FREE before reading in the configuration. X */ X for (i = 0; i < ROWS; i++) { X for (j = 0; j < COLS; j++) { X for (k = 0; k < LEVS; k++) { X tiles[i][j][k].init = FREE; X tiles[i][j][k].state = FREE; X }; X }; X }; X X/* X * Open the file containing the specified layout. X */ X cnt = 0; X if (layout == NULL) { X sprintf(file, "%s/default", LAYOUT); X } else if ((layout[0] != '/') && (layout[0] != '.')) { X sprintf(file, "%s/%s", LAYOUT, layout); X } else { X strcpy(file, layout); X }; X X if ((stdconf = fopen(file, "r")) == NULL) { X fprintf(stderr, "can't open layout file \n"); X exit(1); X }; X X/* X * Read in the row, col, lev lines X */ X while (fgets(line, 127, stdconf) != NULL) { X if (line[0] == '#') continue; X X sscanf(line, "%d %d %d", &row, &col, &lev); X tiles[row][col][lev].init = USED; X tiles[row][col][lev].state = USED; X order[cnt++] = &tiles[row][col][lev]; X }; X X fclose(stdconf); X X/* X * Do a rudimentary check on the number of tiles read X */ X if (cnt != TILES) { X fprintf(stderr, "invalid layout file (%d)\n", cnt); X exit(1); X }; X X return(0); X} X Xinitialize_data() { X int i, j, k, l; X int dx, dy, dz; X Tile *tp, *temp; X X done_count = 0; X tiles_remaining = TILES; X if (initial_flag != 0) return(0); X X/* X * Initialize the bitmap pointers for shuffling into the pool. X */ X tile_data[ 0] = INDEX_NUMBER + 0; X tile_data[ 1] = INDEX_NUMBER + 1; X tile_data[ 2] = INDEX_NUMBER + 2; X tile_data[ 3] = INDEX_NUMBER + 3; X tile_data[ 4] = INDEX_NUMBER + 4; X tile_data[ 5] = INDEX_NUMBER + 5; X tile_data[ 6] = INDEX_NUMBER + 6; X tile_data[ 7] = INDEX_NUMBER + 7; X tile_data[ 8] = INDEX_NUMBER + 8; X tile_data[ 9] = INDEX_NUMBER + 9; X tile_data[10] = INDEX_DRAGON + 0; X tile_data[11] = INDEX_DRAGON + 1; X tile_data[12] = INDEX_DRAGON + 2; X tile_data[13] = INDEX_SEASON + 0; X tile_data[14] = INDEX_SEASON + 1; X tile_data[15] = INDEX_SEASON + 2; X tile_data[16] = INDEX_SEASON + 3; X tile_data[17] = INDEX_PLANT + 0; X tile_data[18] = INDEX_PLANT + 1; X tile_data[19] = INDEX_PLANT + 2; X tile_data[20] = INDEX_PLANT + 3; X tile_data[21] = INDEX_DIRECTION + 0; X tile_data[22] = INDEX_DIRECTION + 1; X tile_data[23] = INDEX_DIRECTION + 2; X tile_data[24] = INDEX_DIRECTION + 3; X tile_data[25] = INDEX_CIRCLE + 0; X tile_data[26] = INDEX_CIRCLE + 1; X tile_data[27] = INDEX_CIRCLE + 2; X tile_data[28] = INDEX_CIRCLE + 3; X tile_data[29] = INDEX_CIRCLE + 4; X tile_data[30] = INDEX_CIRCLE + 5; X tile_data[31] = INDEX_CIRCLE + 6; X tile_data[32] = INDEX_CIRCLE + 7; X tile_data[33] = INDEX_CIRCLE + 8; X tile_data[34] = INDEX_BAMBOO + 0; X tile_data[35] = INDEX_BAMBOO + 1; X tile_data[36] = INDEX_BAMBOO + 2; X tile_data[37] = INDEX_BAMBOO + 3; X tile_data[38] = INDEX_BAMBOO + 4; X tile_data[39] = INDEX_BAMBOO + 5; X tile_data[40] = INDEX_BAMBOO + 6; X tile_data[41] = INDEX_BAMBOO + 7; X tile_data[42] = INDEX_BAMBOO + 8; X tile_data[43] = INDEX_IDEOGRAPH + 0; X tile_data[44] = INDEX_IDEOGRAPH + 1; X tile_data[45] = INDEX_IDEOGRAPH + 2; X tile_data[46] = INDEX_IDEOGRAPH + 3; X tile_data[47] = INDEX_IDEOGRAPH + 4; X tile_data[48] = INDEX_IDEOGRAPH + 5; X tile_data[49] = INDEX_IDEOGRAPH + 6; X tile_data[50] = INDEX_IDEOGRAPH + 7; X tile_data[51] = INDEX_IDEOGRAPH + 8; X X/* X * Initialize the coordinates for all the tiles. X */ X l = TILE_SIDE/2; X for (i = 0; i < ROWS; i++) { X for (j = 0; j < COLS; j++) { X for (k = 0; k < LEVS; k++) { X tiles[i][j][k].row = i; X tiles[i][j][k].col = j; X tiles[i][j][k].lev = k; X tiles[i][j][k].x = X_TILE+(j*l)+(4*k); X tiles[i][j][k].y = Y_TILE+(i*l)-(4*k); X if (setup_flag != 0) { X tiles[i][j][k].state = FREE; X }; X }; X }; X }; X X/* X * Put the randomized images into the tiles and sort them according X * to the drawing order. X */ X if (setup_flag == 0) { X for (i = 0; i < TILES-1; i++) { X for (j = i+1; j < TILES; j++) { X dx = order[i]->row - order[j]->row; X dy = order[i]->col - order[j]->col; X dz = order[i]->lev - order[j]->lev; X X if (dz < 0) continue; X X if (dz > 0) { X temp = order[i]; X order[i] = order[j]; X order[j] = temp; X } else if (dy < dx) { X temp = order[i]; X order[i] = order[j]; X order[j] = temp; X } else if ((dy == dx) && (dy > 0)) { X temp = order[i]; X order[i] = order[j]; X order[j] = temp; X }; X }; X X order[i]->value = i; X }; X X order[TILES-1]->value = TILES-1; X }; X X return(0); X} X Xinitialize_pool() { X int i, j, k; X int seed1, seed2; X long save; X X if (setup_flag != 0) return(0); X X/* X * Set up the randomness for the game X */ X get_seed(); X random_init(seed); X X/* X * Place the circle, bamboo, and ideograph tiles in the pool X */ X for (j = 0, k = 0; j < 4; j++) { X for (i = 21; i <= 51; i++) { X buffer[k++] = i; X }; X }; X X/* X * Place the dragon tiles in the pool X */ X for (j = 0; j < 4; j++) { X for (i = 10; i <= 12; i++) { X buffer[k++] = i; X }; X }; X X/* X * Place the season and plant tiles in the pool X */ X for (i = 13; i <= 20; i++) { X buffer[k++] = i; X }; X X/* X * Shuffle the pool of tiles X */ X for (i = 0; i < 16384; i++) { X seed1 = (random_next() & 0xfffffff)%TILES; X seed2 = (random_next() & 0xfffffff)%TILES; X save = buffer[seed1]; X buffer[seed1] = buffer[seed2]; X buffer[seed2] = save; X }; X X return(0); X} X Xinitialize_tiles() { X int i; X int s1_tile = tile_data[13]; X int s2_tile = tile_data[16]; X int p1_tile = tile_data[17]; X int p2_tile = tile_data[20]; X Tile *tp; X X if (setup_flag != 0) return(0); X X/* X * Put the randomized images into the tiles and sort them according X * to the drawing order. X */ X for (i = 0, tp = order[0]; i < TILES; i++, tp = order[i]) { X tp->state = tp->init; X tp->data = tile_data[get_tile()]; X if ((s1_tile <= tp->data) && (tp->data <= s2_tile)) { X tp->type = s1_tile; X } else if ((p1_tile <= tp->data) && (tp->data <= p2_tile)) { X tp->type = p1_tile; X } else { X tp->type = tp->data; X }; X X }; X X/* X * Set the tile pointers to NULL for starters. X */ X tile1p = NULL; X tile2p = NULL; X X return(0); X} X Xinitialize_socket() { X int i, s; X int sizeon; X int namelen; X int on = 1; X struct sockaddr_in name; X struct hostent *hp, *gethostbyname(); X X if (setup_flag != 0) return(0); X if (tourn_flag != 1) return(0); X printf("attempting connections\n"); X X/* X * Attempt connects X */ X i = 0; X for (pp = &player[num_players-1]; pp >= player; pp--, i++) { X if (pp->type != 'C') continue; X X namelen = sizeof(name); X name.sin_family = AF_INET; X name.sin_port = htons(pp->port); X hp = gethostbyname(pp->machine); X bcopy(hp->h_addr, (char *)&name.sin_addr, hp->h_length); X X while (1) { X if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { X sleep(1); X } else if (connect(s, (char *)&name, namelen) < 0) { X close(s); X sleep(1); X } else { X pp->fd = s; X break; X }; X }; X }; X X/* X * Attempt accepts X */ X name.sin_family = AF_INET; X name.sin_port = htons(mypp->port); X name.sin_addr.s_addr = 0; X namelen = sizeof(name); X sizeon = sizeof(on); X X if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { X perror("can't open socket"); X exit(1); X } else if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeon) < 0) { X perror("can't reset socket"); X exit(1); X } else if (bind(s, (char *)&name, namelen) < 0) { X perror("can't bind socket"); X exit(1); X } else if (listen(s, 5) < 0) { X perror("can't listen socket"); X exit(1); X }; X X for (i = 0, pp = player; i < num_players; i++, pp++) { X if (pp->type != 'A') continue; X namelen = sizeof(name); X X if ((pp->fd = accept(s, (char *)&name, &namelen)) < 0) { X sleep(1); X }; X }; X X for (i = 0, pp = player; i < num_players; i++, pp++) { X if (pp->type != 'M') playfds |= (1 << pp->fd); X }; X X tourn_flag = 2; X printf("connections established\n"); X X return(0); X} X Xinitialize_window() { X int color[9]; X int i, j, k, x, y; X int init_x, init_y; X int other_fore_color; X int other_back_color; X int window_fore_color; X int window_back_color; X int border_fore_color; X int border_back_color; X XWMHints XGameWMHints; X X/* X * Only initialize the window if the initial_flag is zero X */ X if (initial_flag != 0) return(0); X X/* X * Open up the display. X */ X if ((XGameDisplay = XOpenDisplay(display_name)) == NULL) { X fprintf(stderr, "can't connect to display\n"); X exit(1); X }; X X/* X * Set some default variables from the server. X */ X XGameScreen = DefaultScreen(XGameDisplay); X XGameColormap = DefaultColormap(XGameDisplay, XGameScreen); X XGameVisual = DefaultVisual(XGameDisplay, XGameScreen); X XGameDepth = DefaultDepth(XGameDisplay, XGameScreen); X XGameFD = ConnectionNumber(XGameDisplay); X X/* X * Get the colors that we need. X */ X if (XGameDepth > 1) { X XGameBlack = setup_color(0x0000, 0x0000, 0x0000); X XGameWhite = setup_color(0xffff, 0xffff, 0xffff); X XGameGrey = setup_color(0x7fff, 0x7fff, 0x7fff); X X color[0] = setup_color(0x0000, 0x8fff, 0xffff); X color[1] = setup_color(0x0000, 0xffff, 0xffff); X color[2] = setup_color(0x0000, 0xffff, 0x0000); X color[3] = setup_color(0xffff, 0xffff, 0x0000); X color[4] = setup_color(0xffff, 0x7fff, 0x0000); X color[5] = setup_color(0xffff, 0x0000, 0x0000); X color[6] = setup_color(0xffff, 0x0000, 0xafff); X X for (i = 0; i < LEVS; i++) { X fore_colors[i] = XGameBlack; X back_colors[i] = color[i]; X }; X X if (reverse_video == 0) { X other_fore_color = XGameBlack; X other_back_color = XGameWhite; X border_fore_color = XGameGrey; X border_back_color = XGameGrey; X window_fore_color = XGameBlack; X window_back_color = XGameWhite; X } else { X other_fore_color = XGameWhite; X other_back_color = XGameBlack; X border_fore_color = XGameGrey; X border_back_color = XGameGrey; X window_fore_color = XGameWhite; X window_back_color = XGameBlack; X }; X } else { X XGameBlack = BlackPixel(XGameDisplay, XGameScreen); X XGameWhite = WhitePixel(XGameDisplay, XGameScreen); X X if (reverse_video == 0) { X for (i = 0; i < LEVS; i++) { X fore_colors[i] = XGameBlack; X back_colors[i] = XGameWhite; X }; X X other_fore_color = XGameBlack; X other_back_color = XGameWhite; X border_fore_color = XGameWhite; X border_back_color = XGameBlack; X window_fore_color = XGameBlack; X window_back_color = XGameWhite; X } else { X for (i = 0; i < LEVS; i++) { X fore_colors[i] = XGameWhite; X back_colors[i] = XGameBlack; X }; X X other_fore_color = XGameWhite; X other_back_color = XGameBlack; X border_fore_color = XGameBlack; X border_back_color = XGameWhite; X window_fore_color = XGameWhite; X window_back_color = XGameBlack; X }; X X color_type = 0; X }; X X/* X * Get the font for text printing and tile printing. X */ X if ((XGameTextFont = XLoadQueryFont(XGameDisplay, TEXT_FONT)) == NULL) { X fprintf(stderr, "can't load text font %s\n", TEXT_FONT); X exit(1); X }; X X if ((XGameTileFont = XLoadQueryFont(XGameDisplay, tile_font)) == NULL) { X fprintf(stderr, "can't load tile font %s\n", tile_font); X exit(1); X }; X X/* X * Define an icon for the game X */ X XGameIcon = XCreateBitmapFromData( X XGameDisplay, DefaultRootWindow(XGameDisplay), X icon_tiles_bits, ICON_WIDTH, ICON_HEIGHT); X X/* X * Open the main window. X */ X init_x = (DisplayWidth(XGameDisplay, XGameScreen)-WINDOW_WIDTH)/2; X init_y = (DisplayHeight(XGameDisplay, XGameScreen)-WINDOW_HEIGHT)/2; X X XGameWindow = XCreateSimpleWindow( X XGameDisplay, DefaultRootWindow(XGameDisplay), X init_x, init_y, WINDOW_WIDTH, WINDOW_HEIGHT, X BORDER_WIDTH, window_fore_color, window_back_color); X X if (XGameWindow == 0) { X fprintf(stderr, "can't open main window"); X exit(1); X }; X X/* X * Open the subwindows X */ X XGameCountWindow = XCreateSimpleWindow( X XGameDisplay, XGameWindow, X X_COUNT, Y_COUNT, COUNT_WIDTH, COUNT_HEIGHT, X BORDER_WIDTH, window_fore_color, window_back_color); X X if (XGameCountWindow == 0) { X fprintf(stderr, "can't open COUNT window"); X exit(1); X }; X X XGamePlayWindow = XCreateSimpleWindow( X XGameDisplay, XGameWindow, X X_PLAY, Y_PLAY, PLAY_WIDTH, PLAY_HEIGHT, X BORDER_WIDTH, window_fore_color, window_back_color); X X if (XGamePlayWindow == 0) { X fprintf(stderr, "can't open PLAY window"); X exit(1); X }; X X XGameDoneWindow = XCreateSimpleWindow( X XGameDisplay, XGameWindow, X X_DONE, Y_DONE, OPTION_WIDTH, OPTION_HEIGHT, X BORDER_WIDTH, window_fore_color, window_back_color); X X if (XGameDoneWindow == 0) { X fprintf(stderr, "can't open DONE window"); X exit(1); X }; X X XGameQuitWindow = XCreateSimpleWindow( X XGameDisplay, XGameWindow, X X_QUIT, Y_QUIT, OPTION_WIDTH, OPTION_HEIGHT, X BORDER_WIDTH, window_fore_color, window_back_color); X X if (XGameQuitWindow == 0) { X fprintf(stderr, "can't open QUIT window"); X exit(1); X }; X X XGameSameWindow = XCreateSimpleWindow( X XGameDisplay, XGameWindow, X X_SAME, Y_SAME, OPTION_WIDTH, OPTION_HEIGHT, X BORDER_WIDTH, window_fore_color, window_back_color); X X if (XGameSameWindow == 0) { X fprintf(stderr, "can't open SAME window"); X exit(1); X }; X X XGameNewWindow = XCreateSimpleWindow( X XGameDisplay, XGameWindow, X X_NEW, Y_NEW, OPTION_WIDTH, OPTION_HEIGHT, X BORDER_WIDTH, window_fore_color, window_back_color); X X if (XGameNewWindow == 0) { X fprintf(stderr, "can't open NEW window"); X exit(1); X }; X X/* X * Tell the window manager about us X */ X XSetStandardProperties( X XGameDisplay, XGameWindow, X "xmahjongg", NULL, X XGameIcon, NULL, 0, X &XGameHints); X X XGameWMHints.flags = IconPixmapHint | StateHint; X XGameWMHints.icon_pixmap = XGameIcon; X XGameWMHints.initial_state = (iconic_start) ? IconicState : NormalState; X XSetWMHints(XGameDisplay, XGameWindow, &XGameWMHints); X X/* X * Create a pixmap for tile image copying. X */ X XGamePixmap = XCreatePixmap(XGameDisplay, XGameWindow, X PLAY_WIDTH, PLAY_HEIGHT, XGameDepth); X X/* X * Setup the offsets for the border drawing. X */ X XGamePoint[ 0].x = -1; XGamePoint[ 0].y = 1; X XGamePoint[ 1].x = -1; XGamePoint[ 1].y = 64; X XGamePoint[ 2].x = 62; XGamePoint[ 2].y = 64; X XGamePoint[ 3].x = 61; XGamePoint[ 3].y = 65; X XGamePoint[ 4].x = -2; XGamePoint[ 4].y = 65; X XGamePoint[ 5].x = -2; XGamePoint[ 5].y = 2; X XGamePoint[ 6].x = -3; XGamePoint[ 6].y = 3; X XGamePoint[ 7].x = -3; XGamePoint[ 7].y = 66; X XGamePoint[ 8].x = 60; XGamePoint[ 8].y = 66; X XGamePoint[ 9].x = 59; XGamePoint[ 9].y = 67; X XGamePoint[10].x = -4; XGamePoint[10].y = 67; X XGamePoint[11].x = -4; XGamePoint[11].y = 4; X X/* X * Setup the GCs for the text and tiles X */ X XGameBorderGC = XCreateGC(XGameDisplay, XGameWindow, 0, 0); X XSetForeground(XGameDisplay, XGameBorderGC, border_back_color); X XSetBackground(XGameDisplay, XGameBorderGC, border_fore_color); X XSetFont(XGameDisplay, XGameBorderGC, XGameTileFont->fid); X X XGameTextGC[0] = XCreateGC(XGameDisplay, XGameWindow, 0, 0); X XSetForeground(XGameDisplay, XGameTextGC[0], other_fore_color); X XSetBackground(XGameDisplay, XGameTextGC[0], other_back_color); X XSetFont(XGameDisplay, XGameTextGC[0], XGameTextFont->fid); X X XGameTextGC[1] = XCreateGC(XGameDisplay, XGameWindow, 0, 0); X XSetForeground(XGameDisplay, XGameTextGC[1], other_back_color); X XSetBackground(XGameDisplay, XGameTextGC[1], other_fore_color); X XSetFont(XGameDisplay, XGameTextGC[1], XGameTextFont->fid); X X XGameOtherGC[0] = XCreateGC(XGameDisplay, XGameWindow, 0, 0); X XSetForeground(XGameDisplay, XGameOtherGC[0], other_fore_color); X XSetBackground(XGameDisplay, XGameOtherGC[0], other_back_color); X XSetFont(XGameDisplay, XGameOtherGC[0], XGameTileFont->fid); X X XGameOtherGC[1] = XCreateGC(XGameDisplay, XGameWindow, 0, 0); X XSetForeground(XGameDisplay, XGameOtherGC[1], other_back_color); X XSetBackground(XGameDisplay, XGameOtherGC[1], other_fore_color); X XSetFont(XGameDisplay, XGameOtherGC[1], XGameTileFont->fid); X X for (i = 0; i < LEVS; i++) { X XGameTileGC[i][0] = XCreateGC(XGameDisplay, XGameWindow, 0, 0); X XSetForeground(XGameDisplay, XGameTileGC[i][0], fore_colors[i]); X XSetBackground(XGameDisplay, XGameTileGC[i][0], back_colors[i]); X XSetFont(XGameDisplay, XGameTileGC[i][0], XGameTileFont->fid); X X XGameTileGC[i][1] = XCreateGC(XGameDisplay, XGameWindow, 0, 0); X XSetForeground(XGameDisplay, XGameTileGC[i][1], back_colors[i]); X XSetBackground(XGameDisplay, XGameTileGC[i][1], fore_colors[i]); X XSetFont(XGameDisplay, XGameTileGC[i][1], XGameTileFont->fid); X }; X X/* X * Define the cursor for the game X */ X XGameCursor = XCreateFontCursor(XGameDisplay, XC_left_ptr); X XDefineCursor(XGameDisplay, XGameWindow, XGameCursor); X X/* X * Select window exposure events to see if the contents of the window X * have been erased or altered. X */ X XSelectInput(XGameDisplay, XGameWindow, XGameEvents); X XSelectInput(XGameDisplay, XGameNewWindow, XGameEvents); X XSelectInput(XGameDisplay, XGameDoneWindow, XGameEvents); X XSelectInput(XGameDisplay, XGameQuitWindow, XGameEvents); X XSelectInput(XGameDisplay, XGameSameWindow, XGameEvents); X XSelectInput(XGameDisplay, XGamePlayWindow, XGameEvents); X XSelectInput(XGameDisplay, XGameCountWindow, XGameEvents); X X/* X * Map the game window to the screen. X */ X XMapRaised(XGameDisplay, XGameWindow); X while (1) { X XNextEvent(XGameDisplay, &XGameEvent); X if (XGameEvent.type == Expose) break; X }; X X/* X * Display the game name. X */ X XDrawLine(XGameDisplay, XGameWindow, XGameTextGC[0], 0, 184, 1000, 184); X X draw_letter(INDEX_X, 42, 50); X draw_letter(INDEX_M, 148, 50); X draw_letter(INDEX_A, 254, 50); X draw_letter(INDEX_H, 360, 50); X draw_letter(INDEX_J, 466, 50); X draw_letter(INDEX_O, 572, 50); X draw_letter(INDEX_N, 678, 50); X draw_letter(INDEX_G, 784, 50); X draw_letter(INDEX_G, 890, 50); X X/* X * Display the copyright notice X */ X i = strlen(copyright); X j = XGameTextFont->max_bounds.width; X k = XGameTextFont->ascent; X X j = (WINDOW_WIDTH - i*j)/2; X k = (174 - k); X draw_string(copyright, j, k, XGameTextGC[1]); X X/* X * Display the tiles on the screen before the start of the game. Order: X * dragons, seasons, plants, directions, circles, bamboos, ideographs X */ X draw_data(); X X XFlush(XGameDisplay); X sleep(5); X X/* X * Find the maximum file descriptor for the select system call and set X * the initialization flag. X */ X initial_flag++; X maxfds = 31; X X/* X * Map the subwindows X */ X XClearArea(XGameDisplay, XGameWindow, 0, 0, 0, 0, True); X XMapSubwindows(XGameDisplay, XGameWindow); X XFlush(XGameDisplay); X return(0); X} X Xsetup_color(r, g, b) Xint r; Xint g; Xint b; X{ X XColor XGameColor; X X XGameColor.red = r; X XGameColor.green = g; X XGameColor.blue = b; X X if (XAllocColor(XGameDisplay,XGameColormap, &XGameColor) == 0) { X fprintf(stderr, "can't allocate color\n"); X exit(1); X }; X X return(XGameColor.pixel); X} X Xget_tile() { X int i, j; X X i = random_next()%TILES; X j = ((random_next()%2) == 0) ? 1 : -1; X X/* X * Walk through the tile pool looking for an unused tile X */ X while (buffer[i] == 0) { X i = (i+j)%TILES; X if (i < 0) i = TILES-1; X }; X X j = buffer[i]; X buffer[i] = 0; X X return(j); X} X END_OF_initial.c if test 19579 -ne `wc -c <initial.c`; then echo shar: \"initial.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f packet.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"packet.c\" else echo shar: Extracting \"packet.c\" \(3553 characters\) sed "s/^X//" >packet.c <<'END_OF_packet.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#include <stdio.h> X#include <signal.h> X#include <sys/time.h> X#include <sys/types.h> X#include <sys/socket.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include <netinet/in.h> X#include "xmahjongg.h" X#include "variables.h" X Xpacket_send(type) Xint type; X{ X int i; X int packetlen = sizeof(Packet); X char ascii[24]; X X if (tourn_flag == 0) return(0); X i = mypp->done; X X/* X * Update the information on my board X */ X if (type == GAME_START) { X mypp->done++; X mypp->tiles[mypp->done] = TILES; X mypp->board[mypp->done] = seed; X if ((i >= 0) && (mypp->tiles[i] > 0)) mypp->tiles[i] *= -1; X draw_user(mypp, GAME_START); X } else if (type == GAME_PLAY) { X mypp->total -= 2; X mypp->tiles[i] = tiles_remaining; X draw_user(mypp, GAME_PLAY); X } else if (type == GAME_DONE) { X if (mypp->tiles[i] > 0) mypp->tiles[i] *= -1; X draw_user(mypp, GAME_DONE); X } else if (type == GAME_QUIT) { X draw_user(mypp, GAME_QUIT); X } else { X fprintf(stderr, "bad packet type = %d\n", type); X exit(1); X }; X X/* X * Send the information to the other players X */ X packet.type = htons(type); X packet.port = htons(mypp->port); X packet.tiles = htons(tiles_remaining); X packet.board = htonl(seed); X strcpy(packet.name, mypp->name); X X for (i = 0, pp = player; i < num_players; i++, pp++) { X if ((pp->fd < 0) || (pp->type == 'M')) continue; X if (write(pp->fd, (char *)&packet, packetlen) != packetlen) { X fprintf(stderr, "can't send to %s\n", pp->name); X playfds ^= (1 << pp->fd); X close(pp->fd); X pp->fd = -1; X }; X }; X X return(0); X} X Xpacket_recv(fd) Xint fd; X{ X int i; X int readfds = 1 << fd; X int packetlen = sizeof(Packet); X struct timeval timeout; X char ascii[32]; X char *cp; X X/* X * Read in the packet which is waiting for us. X */ X timeout.tv_sec = 0L; X timeout.tv_usec = 0L; X X if (select(maxfds, &readfds, NULL, NULL, &timeout) <= 0) { X return(0); X } else if ((i = read(fd, (char *)&packet, packetlen)) != packetlen) { X fprintf(stderr, "can't read from %s\n", pp->name); X playfds ^= (1 << pp->fd); X close(pp->fd); X pp->fd = -1; X return(0); X }; X X/* X * Find this players structure. X */ X packet.type = ntohs(packet.type); X packet.port = ntohs(packet.port); X packet.tiles = ntohs(packet.tiles); X packet.board = ntohl(packet.board); X X for (i = 0, pp = player; i < num_players; i++, pp++) { X if (pp->port == packet.port) break; X }; X X if (i == num_players) { X fprintf(stderr, "****** BAD PACKET ******\n"); X fprintf(stderr, "packet name = %s port=%d\n", X packet.name, packet.port); X return(0); X }; X X i = pp->done; X X switch (packet.type) { X case GAME_START: X pp->done++; X pp->board[i+1] = packet.board; X pp->tiles[i+1] = packet.tiles; X if ((i >= 0) && (pp->tiles[i] > 0)) pp->tiles[i] *= -1; X draw_user(pp, GAME_START); X break; X case GAME_PLAY: X pp->total -= 2; X pp->tiles[i] = packet.tiles; X draw_user(pp, GAME_PLAY); X break; X case GAME_DONE: X if (pp->tiles[i] > 0) pp->tiles[i] *= -1; X draw_user(pp, GAME_DONE); X break; X case GAME_QUIT: X pp->tiles[i] = -packet.tiles; X pp->quit = 1; X draw_user(pp, GAME_QUIT); X playfds ^= (1 << pp->fd); X close(pp->fd); X pp->fd = -1; X break; X default: X fprintf(stderr, "bad switch (%d)\n", packet.type); X exit(1); X break; X }; X X return(0); X} END_OF_packet.c if test 3553 -ne `wc -c <packet.c`; then echo shar: \"packet.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f play.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"play.c\" else echo shar: Extracting \"play.c\" \(7196 characters\) sed "s/^X//" >play.c <<'END_OF_play.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#include <stdio.h> X#include <sys/time.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include "xmahjongg.h" X#include "variables.h" X Xextern int initial_flag; Xint x_dist[] = { 0, -1, 1, 0, -1, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1}; Xint y_dist[] = { 2, 2, 2, -2, -2, -2, -1, -1, -1, 0, 0, 0, 1, 1, 1}; Xint z_dist[] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}; X Xplay_tile(tp) XTile *tp; X{ X X if (not_free(tp->row, tp->col, tp->lev)) { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X } else if (tile1p == NULL) { X invert_tile(tp, 1); X tile1p = tp; X } else if (tp == tile1p) { X invert_tile(tp, 0); X tile1p = NULL; X } else if (tp->type == tile1p->type) { X tiles_remaining -= 2; X remove_tile(tile1p); X remove_tile(tp); X tile1p = NULL; X draw_count(); X draw_matches(); X if (done_count == 0) packet_send(GAME_PLAY); X } else { X XBell(XGameDisplay, 100); X XFlush(XGameDisplay); X }; X X return(0); X} X Xinvert_tile(tp, type) XTile *tp; Xint type; X{ X X redraw_tile(tp, type); X XFlush(XGameDisplay); X X return(0); X} X Xremove_tile(tp) XTile *tp; X{ X X tp->state = FREE; X redraw_tile(tp, 0); X XFlush(XGameDisplay); X X return(0); X} X Xcreate_tile(tp) XTile *tp; X{ X int i, j; X int dx, dy, dz; X X for (i = 0; i < TILES; i++) { X if (order[i] == NULL) break; X X dx = order[i]->row - tp->row; X dy = order[i]->col - tp->col; X dz = order[i]->lev - tp->lev; X X if (dz < 0) continue; X X if (dz > 0) break; X if (dy < dx) break; X if ((dy == dx) && (dy > 0)) break; X }; X X for (j = TILES - tiles_remaining; j > i; j--) { X order[j] = order[j-1]; X }; X X order[i] = tp; X tiles_remaining--; X draw_count(); X X tp->data = tp->lev; X tp->state = USED; X redraw_tile(tp, 0); X XFlush(XGameDisplay); X X return(0); X} X Xdelete_tile(tp) XTile *tp; X{ X int i, j; X X for (i = 0; i < TILES; i++) { X if (order[i] == NULL) break; X if (order[i]->row != tp->row) continue; X if (order[i]->col != tp->col) continue; X if (order[i]->lev != tp->lev) continue; X X for (j = i; j < TILES-1; j++) { X order[j] = order[j+1]; X }; X X order[TILES-1] = 0; X break; X }; X X tiles_remaining++; X draw_count(); X X tp->state = FREE; X redraw_tile(tp, 0); X XFlush(XGameDisplay); X X return(0); X} X Xredraw_tile(tp, type) XTile *tp; Xint type; X{ X int x_src, y_src; X int x_dst, y_dst; X int row, col, lev; X int i, j, k, l, x, y, rv; X char string[4]; X Tile *xp[144]; X GC gc; X X/* X * Copy the tiles into the pixmap and then dump the pixmap into X * the window. X */ X row = tp->row; X col = tp->col; X lev = tp->lev; X X string[0] = 127; X string[1] = 127; X string[2] = 127; X XDrawImageString(XGameDisplay, XGamePixmap, XGameOtherGC[0], X 0, 0*TILE_SIDE, string, 3); X XDrawImageString(XGameDisplay, XGamePixmap, XGameOtherGC[0], X 0, 1*TILE_SIDE, string, 3); X XDrawImageString(XGameDisplay, XGamePixmap, XGameOtherGC[0], X 0, 2*TILE_SIDE, string, 3); X X l = load_tiles(xp, row, col); X X for (i = 0; i < l; i++) { X rv = (xp[i] == tp) ? type : 0; X k = (color_type == 0) ? xp[i]->lev : (xp[i]->data/16) - 1; X X string[0] = xp[i]->data; X x = (xp[i]->col + 2-col)*(TILE_SIDE/2) + 4*xp[i]->lev; X y = (xp[i]->row + 2-row)*(TILE_SIDE/2) - 4*xp[i]->lev; X XDrawImageString(XGameDisplay, XGamePixmap, X XGameTileGC[k][rv], x, y, string, 1); X X draw_border(x, y); X }; X X x_src = TILE_SIDE + 4*(lev-1); X y_src = TILE_SIDE - 4*(lev-0); X x_dst = tp->x - 4; X y_dst = tp->y + 0; X X XCopyArea(XGameDisplay, XGamePixmap, XGamePlayWindow, XGameTextGC[0], X x_src, y_src, TILE_SIDE+4, TILE_SIDE+4, x_dst, y_dst); X X return(0); X} X Xnot_free(row, col, lev) Xint row, col, lev; X{ X int i, mask; X int r1, c1, l1; X X for (i = 0, mask = 0; i < 15; i++) { X r1 = row+x_dist[i]; X c1 = col+y_dist[i]; X l1 = lev+z_dist[i]; X if ((r1 < 0) || (r1 >= ROWS)) continue; X if ((c1 < 0) || (c1 >= COLS)) continue; X if ((l1 < 0) || (l1 >= LEVS)) continue; X X if (tiles[r1][c1][l1].state == USED) { X mask |= (1 << i); X }; X }; X X if ((mask & 077700) != 0) { X return(1); X } else if ((mask & 000070) == 0) { X return(0); X } else if ((mask & 000007) != 0) { X return(1); X } else { X return(0); X }; X} X Xload_tiles(xp, row, col) XTile *xp[]; Xint row; Xint col; X{ X register int i, m; X register int dx, dy; X register Tile *tp; X X m = 0; X X for (i = 0, tp = order[0]; i < TILES; i++, tp = order[i]) { X if (tp == NULL) break; X if (tp->state != USED) continue; X X dx = tp->row - row; X dy = tp->col - col; X X if (dx < 0) dx = -dx; X if (dy < 0) dy = -dy; X X if ((dx <= 2) && (dy <= 2)) xp[m++] = tp; X }; X X return(m); X} X Xok_below(x, y, z) Xint x; Xint y; Xint z; X{ X int i, j, k; X X/* X * Check this level to be sure that this tile will not overlap another X * tile. X */ X for (i = x-1; i <= x+1; i++) { X for (j = y-1; j <= y+1; j++) { X if ((i < 0) || (i >= ROWS)) continue; X if ((j < 0) || (j >= COLS)) continue; X if ((i == x) && (j == y)) continue; X if (tiles[i][j][z].state == USED) return(-1); X }; X }; X X if (z == 0) return(0); X X/* X * Check the level below this tile to be sure that all four quadrants are X * covered. X */ Xquadrant1: X if (tiles[x-1][y-1][z-1].state == USED) goto quadrant2; X if (tiles[x-1][y-0][z-1].state == USED) goto quadrant2; X if (tiles[x-0][y-1][z-1].state == USED) goto quadrant2; X if (tiles[x-0][y-0][z-1].state == USED) goto quadrant2; X return(-1); X Xquadrant2: X if (tiles[x-1][y-0][z-1].state == USED) goto quadrant3; X if (tiles[x-1][y+1][z-1].state == USED) goto quadrant3; X if (tiles[x-0][y-0][z-1].state == USED) goto quadrant3; X if (tiles[x-0][y+1][z-1].state == USED) goto quadrant3; X return(-1); X Xquadrant3: X if (tiles[x-0][y-1][z-1].state == USED) goto quadrant4; X if (tiles[x-0][y-0][z-1].state == USED) goto quadrant4; X if (tiles[x+1][y-1][z-1].state == USED) goto quadrant4; X if (tiles[x+1][y-0][z-1].state == USED) goto quadrant4; X return(-1); X Xquadrant4: X if (tiles[x-0][y-0][z-1].state == USED) goto quadrant5; X if (tiles[x-0][y+1][z-1].state == USED) goto quadrant5; X if (tiles[x+1][y-0][z-1].state == USED) goto quadrant5; X if (tiles[x+1][y+1][z-1].state == USED) goto quadrant5; X return(-1); X Xquadrant5: X return(0); X} X Xok_above(x, y, z) Xint x; Xint y; Xint z; X{ X int i, j, k; X X if (z == (LEVS-1)) return(0); X X/* X * Check the level above this tile to be sure that all four quadrants are X * free. X */ X for (i = -1; i <= 1; i++) { X for (j = -1; j <= 1; j++) { X if (((x+i) < 0) || ((x+i) >= ROWS)) continue; X if (((y+j) < 0) || ((y+j) >= COLS)) continue; X if (tiles[x+i][y+i][z+1].state == USED) return(-1); X }; X }; X X/* X if (tiles[x-1][y-1][z+1].state == USED) return(-1); X if (tiles[x-1][y-0][z+1].state == USED) return(-1); X if (tiles[x-1][y+1][z+1].state == USED) return(-1); X X if (tiles[x-0][y-1][z+1].state == USED) return(-1); X if (tiles[x-0][y-0][z+1].state == USED) return(-1); X if (tiles[x-0][y+1][z+1].state == USED) return(-1); X X if (tiles[x+1][y-1][z+1].state == USED) return(-1); X if (tiles[x+1][y-0][z+1].state == USED) return(-1); X if (tiles[x+1][y+1][z+1].state == USED) return(-1); X*/ X X return(0); X} END_OF_play.c if test 7196 -ne `wc -c <play.c`; then echo shar: \"play.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f random.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"random.c\" else echo shar: Extracting \"random.c\" \(1155 characters\) sed "s/^X//" >random.c <<'END_OF_random.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#include <stdio.h> X#include <sys/time.h> X X#define POLY_SIZE 31 X#define TAP_1 0 X#define TAP_2 3 X#define TAP_3 POLY_SIZE X Xlong poly[POLY_SIZE+1]; Xlong *p1 = &poly[TAP_1]; Xlong *p2 = &poly[TAP_2]; Xlong *p3 = &poly[TAP_3]; X Xlong random_init(x) Xint x; X{ X int i; X X poly[0] = x; X for (i = 1; i < POLY_SIZE; i++) { X poly[i] = 3234846615*poly[i-1] + 47027; X }; X X p1 = &poly[TAP_1]; X p2 = &poly[TAP_2]; X p3 = &poly[TAP_3]; X X for (i = 0; i < 2*POLY_SIZE; i++) { X random(); X }; X X return(0L); X} X Xlong random_next() X{ X long x; X X *p3 = (*p2 + *p1); X x = (*p3 >> 1) & 0x7fffffff; X X if (p3 == &poly[POLY_SIZE]) { X p3 = poly; X p2++; X p1++; X } else if (p2 == &poly[POLY_SIZE]) { X p3++; X p2 = poly; X p1++; X } else if (p1 == &poly[POLY_SIZE]) { X p3++; X p2++; X p1 = poly; X } else { X p3++; X p2++; X p1++; X }; X X return(x); X} END_OF_random.c if test 1155 -ne `wc -c <random.c`; then echo shar: \"random.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f sysdep.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"sysdep.c\" else echo shar: Extracting \"sysdep.c\" \(2001 characters\) sed "s/^X//" >sysdep.c <<'END_OF_sysdep.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#ifndef VMS X X#include <pwd.h> X#include <stdio.h> X#include <string.h> X#include <sys/time.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include "xmahjongg.h" X#include "variables.h" X Xget_user(name) Xchar *name; X{ X struct passwd *pwp; X X if ((pwp = getpwuid(getuid())) == NULL) { X fprintf(stderr, "can't getpwuid\n"); X exit(1); X } else { X strcpy(name, pwp->pw_name); X }; X X return(0); X} X Xget_seed() X{ X struct timeval tv; X struct timezone tz; X X if (seed == 0) { X gettimeofday(&tv, &tz); X seed = 1 + (tv.tv_sec%100000); X } else if (seed < 0) { X seed = (-seed)%100000; X } else { X seed = 1 + (random_next(seed)%100000); X }; X X return(0); X} X Xevent_wait() X{ X int readfds; X X/* X * If there are no events pending, then sleep until one occurs. X */ X while (XEventsQueued(XGameDisplay, QueuedAfterReading) == 0) { X readfds = (1 << XGameFD) | playfds; X select(maxfds, &readfds, NULL, NULL, NULL); X X if ((readfds & playfds) != 0) { X event_packet(readfds); X }; X }; X X return(0); X} X X#else X X#include <stdio.h> X#include <string.h> X#include <sys/time.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include "xmahjongg.h" X#include "variables.h" X X Xget_user(name) Xchar *name; X{ X X if (cuserid(name) == NULL) { X fprintf(stderr, "can't cuserid\n"); X exit(1); X }; X X return(0); X} X Xget_seed() X{ X struct tm *tv; X time_t clock_time; X X if (seed == 0) { X time(&clock_time); X tv = localtime(&clock_time); X seed = 1 + (tv->tm_sec%100000); X } else if (seed < 0) { X seed = (-seed)%100000; X } else { X seed = 1 + (random_next(seed)%100000); X }; X X return(0); X} X Xevent_wait() X{ X X/* X * Since VMS doesn't have tournament mode, this is really a dummy X * routine. X */ X X return(0); X} X X#endif END_OF_sysdep.c if test 2001 -ne `wc -c <sysdep.c`; then echo shar: \"sysdep.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f variables.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"variables.c\" else echo shar: Extracting \"variables.c\" \(567 characters\) sed "s/^X//" >variables.c <<'END_OF_variables.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#ifdef GLOBAL X#undef GLOBAL X#endif X#define GLOBAL X X#include <pwd.h> X#include <stdio.h> X#include <string.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include "xmahjongg.h" X#include "variables.h" X Xvariables() X{ X X return(0); X} END_OF_variables.c if test 567 -ne `wc -c <variables.c`; then echo shar: \"variables.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f xmahjongg.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"xmahjongg.c\" else echo shar: Extracting \"xmahjongg.c\" \(3724 characters\) sed "s/^X//" >xmahjongg.c <<'END_OF_xmahjongg.c' X/* X ****************************************************************************** X * * X * Copyright (c) 1990 by Jeff S. Young. All rights reserved under the * X * copyright laws of the United States. * X * * X ****************************************************************************** X */ X X#include <stdio.h> X#include <string.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include "xmahjongg.h" X#include "variables.h" X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X X get_parameters(argc, argv); X X while(1) { X initialize(); X keep_playing = 1; X packet_send(GAME_START); X X while(keep_playing != 0) { X event_process(); X }; X }; X} X Xget_parameters(argc, argv) Xint argc; Xchar *argv[]; X{ X int i, j, c; X char username[32]; X char *cp, hostname[HOSTNAMELEN]; X Player tmp, *pp = player; X X/* X * Parse the arguments. X */ X layout = NULL; X tile_font = TILE_FONT; X X while ((c = getopt(argc, argv, "icrsb:d:f:l:n:p:")) != EOF) { X switch (c) { X case 'b': X seed = -atoi(optarg); X break; X case 'c': X color_type = 1; X break; X case 'd': X display_name = optarg; X break; X case 'f': X tile_font = optarg; X break; X case 'i': X iconic_start = 1; X break; X case 'l': X layout = optarg; X break; X case 'n': X num_games = atoi(optarg); X break; X case 'p': X tourn_flag = 1; X cp = strchr(optarg, '@'); X if (cp == NULL) usage(BAD_USERNAME); X strncpy(pp->name, optarg, cp-optarg); X strcpy(pp->machine, cp+1); X num_players++; X pp++; X break; X case 'r': X reverse_video = 1; X break; X case 's': X setup_flag = 1; X break; X default: X usage(NULL); X break; X }; X }; X X/* X * Check to see if we are in setup mode. If we are only certain param- X * eters are valid. X */ X if (setup_flag != 0) { X if (seed < 0) usage(BAD_SEED); X if (num_games != 0) usage(BAD_GAMES); X if (tourn_flag != 0) usage(BAD_TOURN); X if (color_type != 0) usage(BAD_COLOR); X X return(0); X }; X X/* X * Set up the tournament if requested. X */ X if (num_players == 0) return(0); X if (num_games == 0) num_games = 3; X X get_user(username); X gethostname(hostname, sizeof(hostname)); X mypp = &player[num_players++]; X strcpy(mypp->name, username); X strcpy(mypp->machine, hostname); X X for (i = 0; i < num_players-1; i++) { X for (j = i+1; j < num_players; j++) { X if (strcmp(player[i].name, player[j].name) > 0) { X tmp = player[i]; X player[i] = player[j]; X player[j] = tmp; X }; X }; X X }; X X for (i = 0; i < num_players; i++) { X player[i].x = X_SCORE; X player[i].y = Y_SCORE+15*i; X player[i].port = XPORT+i; X player[i].done = -1; X player[i].total = 144*num_games; X X for (j = 0; j < MAX_BOARDS; j++) { X player[i].tiles[j] = 2*TILES; X }; X X if (strcmp(player[i].name, username) < 0) { X player[i].type = 'C'; X } else if (strcmp(player[i].name, username) > 0) { X player[i].type = 'A'; X } else { X mypp = &player[i]; X player[i].type = 'M'; X }; X }; X X return(0); X} X Xusage(s) Xchar *s; X{ X X if (s != NULL) fprintf(stderr, "xmahjongg: %s\n\n", s); X X fprintf(stderr, "xmahjongg \n"); X fprintf(stderr, " [-b #] - board number\n"); X fprintf(stderr, " [-c] - color tiles by group\n"); X fprintf(stderr, " [-d display] - display name\n"); X fprintf(stderr, " [-f fontname] - font name\n"); X fprintf(stderr, " [-i] - iconic start\n"); X fprintf(stderr, " [-l file] - board layout file\n"); X fprintf(stderr, " [-n #] - # of games (tournament)\n"); X fprintf(stderr, " [-p nx@mx] - another player\n"); X fprintf(stderr, " [-r] - reverse video\n"); X fprintf(stderr, " [-s] - setup mode\n"); X exit(1); X} END_OF_xmahjongg.c if test 3724 -ne `wc -c <xmahjongg.c`; then echo shar: \"xmahjongg.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 1 \(of 5\). cp /dev/null ark1isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.