home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume15
/
xmines2
/
part01
/
xmines.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-27
|
13KB
|
545 lines
#include <math.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <signal.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <xview/xview.h>
#include <xview/panel.h>
#include <xview/frame.h>
#include <xview/canvas.h>
#include <xview/notice.h>
#include "xmines.h"
#include "xmines.icons"
#define CREATE_ICON(bits,width,height) XCreateBitmapFromData(display,RootWindow(display,screen),\
bits,width,height)
#define PLACE_ICON(icon,wherey,wherex) XCopyPlane(display,icon,pmap,def_gc,0,0, \
IC_WIDTH,IC_HEIGHT,wherex,wherey,1L)
/*#define DEBUG */
#define POW(x,y) pow((double)(x),(double)(y))
#define INITRAND srandom(time((time_t *)0))
#define MAXRANDOM 2147483648 /* 2^31 */
#define RAND01 (((double)(random()))/MAXRANDOM)
#define FRAND(min,max) (RAND01*((max)-(min))+(min))
#define RAND(min,max) (int)FRAND(min,max)
#ifndef lint
static char sccsid[] = "@(#)xmines,v0.1 by Manolis Lourakis.";
static char Copyright[] = "(c) 1992 Lourakis Manolis.\n";
static char Mail[] = "lourakis@csd.uch.gr";
#endif
extern char *optarg ;
extern int optind ;
void canvas_event_proc(Xv_Window, Event*);
void canvas_repaint_proc(void);
void settime(void);
void finish(char *);
Display *display;
Visual *visual;
int screen;
GC def_gc;
Frame frame;
Panel panel1,panel2;
Panel_item pmsg,smsg,tmsg;
Canvas canvas;
Window dr_win;
Pixmap pmap,icons[NUM_ICONS];
cell *Cells;
char buff[256];
int quit_proc(),init();
int place_tiles(int,int);
int mark_tile(int,int);
int open_tile(int,int);
int auto_open(int,int);
int mines_2_go,closed_tiles,playing,checks,secs;
int width=HORIZ_CELLS,
height=VERT_CELLS,
mines=NUM_MINES,
quantum=QUANTUM;
struct itimerval timer;
int first_tile;
void main(int argc, char *argv[]){
int ret,tmp;
register int i,j;
int errflag = 0,gc;
XWMHints wm_hints;
XClassHint class_hints;
XTextProperty windowName, iconName;
char *window_name = "Xmines";
char *icon_name = "Xmines";
xv_init (XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
while ((gc = getopt(argc, argv, "w:h:m:q:")) != EOF)
switch (gc) {
case 'w' :
tmp=atoi(optarg);
if(tmp>0) width=tmp;
break ;
case 'h' :
tmp=atoi(optarg);
if(tmp>0) height=tmp;
break ;
case 'm' :
tmp=atoi(optarg);
if(tmp>0) mines=tmp;
break;
case 'q' :
tmp=atoi(optarg);
if(tmp>0) quantum=tmp;
break;
case '?' :
errflag++;
break ;
}
if(errflag){
fprintf(stderr,
"Usage: xmines [-w width] [-h height] [-m mines] [-q quantum]\n");
exit(1);
}
if(mines>=width*height){
fprintf(stderr,"xmines: Too many mines, using defaults\n");
width=HORIZ_CELLS;
height=VERT_CELLS;
mines=NUM_MINES;
}
Cells=(cell *)malloc(width*height*sizeof(cell));
if(Cells==NULL){
fprintf(stderr,"xmines: malloc failed\n");
exit(1);
}
frame = (Frame) xv_create (NULL, FRAME,
FRAME_LABEL,PROG_NAME,
XV_WIDTH,width*IC_WIDTH,
NULL);
display = (Display *)xv_get (frame, XV_DISPLAY);
screen = DefaultScreen(display);
visual = DefaultVisual(display, screen);
def_gc = DefaultGC(display, screen);
panel1 = xv_create (frame, PANEL,
PANEL_LAYOUT,PANEL_HORIZONTAL,
NULL);
xv_create (panel1, PANEL_BUTTON,
PANEL_LABEL_STRING, "Quit",
PANEL_NOTIFY_PROC, quit_proc,
NULL);
xv_create (panel1, PANEL_BUTTON,
PANEL_LABEL_STRING, "New",
PANEL_NOTIFY_PROC, init,
NULL);
tmsg=xv_create (panel1, PANEL_MESSAGE,
PANEL_LABEL_STRING,"Time: 0:0",
PANEL_LABEL_BOLD,TRUE,
NULL);
window_fit_height(panel1);
panel2 = xv_create (frame, PANEL,
PANEL_LAYOUT,PANEL_HORIZONTAL,
NULL);
sprintf(buff,"Mines: %d\n",mines);
xv_create(panel2,PANEL_MESSAGE,
PANEL_LABEL_STRING,buff,
PANEL_LABEL_BOLD,TRUE,
NULL);
sprintf(buff,"Checks: 0");
pmsg=xv_create(panel2,PANEL_MESSAGE,
PANEL_LABEL_STRING,buff,
PANEL_LABEL_BOLD,TRUE,
NULL);
smsg=xv_create(panel2,PANEL_MESSAGE,
XV_SHOW, FALSE,
NULL);
window_fit_height(panel2);
canvas = xv_create (frame, CANVAS,
CANVAS_X_PAINT_WINDOW, TRUE,
XV_WIDTH,IC_WIDTH*width,
XV_HEIGHT,IC_HEIGHT*height,
WIN_EVENT_PROC, canvas_event_proc,
CANVAS_REPAINT_PROC, canvas_repaint_proc,
NULL);
xv_set (canvas_paint_window (canvas), WIN_CONSUME_EVENTS,
WIN_MOUSE_BUTTONS,
NULL,
WIN_EVENT_PROC, canvas_event_proc,
NULL);
dr_win = xv_get(canvas_paint_window (canvas), XV_XID);
pmap=XCreatePixmap(display,dr_win,IC_WIDTH*width,
IC_HEIGHT*height,DefaultDepth(display,screen));
icons[EMPTY]=CREATE_ICON(empty_bits,empty_width,empty_height);
icons[ONE]=CREATE_ICON(one_bits,one_width,one_height);
icons[TWO]=CREATE_ICON(two_bits,two_width,two_height);
icons[THREE]=CREATE_ICON(three_bits,three_width,three_height);
icons[FOUR]=CREATE_ICON(four_bits,four_width,four_height);
icons[FIVE]=CREATE_ICON(five_bits,five_width,five_height);
icons[SIX]=CREATE_ICON(six_bits,six_width,six_height);
icons[SEVEN]=CREATE_ICON(seven_bits,seven_width,seven_height);
icons[EIGHT]=CREATE_ICON(eight_bits,eight_width,eight_height);
icons[CLOSED]=CREATE_ICON(closed_bits,closed_width,closed_height);
icons[MARKED]=CREATE_ICON(marked_bits,marked_width,marked_height);
icons[MINE]=CREATE_ICON(mine_bits,mine_width,mine_height);
icons[QUEST]=CREATE_ICON(quest_bits,quest_width,quest_height);
if (XStringListToTextProperty(&window_name, 1, &windowName) == 0) {
fprintf(stderr, "structure allocation for windowName failed\n");
exit(1);
}
if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0) {
fprintf(stderr, "structure allocation for windowName failed\n");
exit(1);
}
wm_hints.initial_state = NormalState;
wm_hints.input = True;
wm_hints.icon_pixmap = icons[MINE];
wm_hints.flags = StateHint | IconPixmapHint | InputHint;
class_hints.res_name = "Xmines";
class_hints.res_class = "Games";
XSetWMProperties(display, xv_get(frame,XV_XID), &windowName, &iconName, argv,
argc, NULL, &wm_hints, &class_hints);
timer.it_interval.tv_sec=quantum;
timer.it_interval.tv_usec=0;
timer.it_value.tv_sec=quantum;
timer.it_value.tv_usec=0;
init();
window_fit(frame);
xv_main_loop(frame);
}
void
canvas_repaint_proc ()
{
XCopyArea(display,pmap,dr_win,def_gc,0,0,
width*IC_WIDTH,height*IC_HEIGHT,0,0);
}
void
canvas_event_proc (Xv_Window window, Event *event)
{
int x,y;
cell *aux;
if(!playing) return;
switch (event_xevent (event)->type)
{
case ButtonRelease:
get_cell(event_xevent (event)->xbutton.x,event_xevent (event)->xbutton.y,
&x,&y);
switch (event_xevent (event)->xbutton.button){
case Button1:
if(open_tile(x,y)){
XCopyArea(display,pmap,dr_win,def_gc,0,0,
width*IC_WIDTH,height*IC_HEIGHT,0,0);
}
if(mines_2_go==0 && closed_tiles==mines)
finish(" Successful");
break;
case Button2:
aux=Cells+x*width+y;
if(aux->out_state!=CLOSED) break;
PLACE_ICON(icons[QUEST],x*IC_WIDTH,
y*IC_HEIGHT);
aux->out_state=QUEST;
XCopyArea(display,pmap,dr_win,def_gc,0,0,
width*IC_WIDTH,height*IC_HEIGHT,0,0);
break;
case Button3:
if(mark_tile(x,y)){
XCopyArea(display,pmap,dr_win,def_gc,0,0,
width*IC_WIDTH,height*IC_HEIGHT,0,0);
}
if(mines_2_go==0 && closed_tiles==mines)
finish(" Successful");
break;
}
break;
default:
break;
}
}
error(char *msg)
{
fprintf(stderr,"xmines: %s\n",msg);
exit(1);
}
get_cell(int where_x,int where_y,int *i,int *j)
{
register int k;
for(k=0;k*IC_WIDTH<where_x;k++)
;
*j=k-1;
for(k=0;k*IC_HEIGHT<where_y;k++)
;
*i=k-1;
}
quit_proc()
{
int result;
result = notice_prompt(panel1, NULL,
NOTICE_MESSAGE_STRINGS,
"Realy Quit?",
"Press YES to confirm",
"Press NO to cancel",
NULL,
NOTICE_BUTTON_YES, "YES",
NOTICE_BUTTON_NO, "NO",
NULL);
switch(result) {
case NOTICE_YES:
exit(0);
break;
case NOTICE_NO:
break;
case NOTICE_FAILED:
default: break;
}
}
place_tiles(int len,int num_mines)
{
register int i,j;
int where,aux,cnt;
for(i=0;i<len;i++){
(Cells+i)->in_state=EMPTY;
(Cells+i)->out_state=CLOSED;
}
INITRAND;
for(i=0;i<num_mines; ){
aux=RAND(0,len);
if((Cells+aux)->in_state==MINE) continue;
(Cells+aux)->in_state=MINE;
i++;
}
for(j=0;j<width;j++)
for(i=0;i<height;i++){
where=i*width+j;
if((Cells+where)->in_state==MINE) continue;
cnt=0;
if(i-1>=0){
if((Cells+where-width)->in_state==MINE) cnt++;
if(j-1>=0)
if((Cells+where-width-1)->in_state==MINE) cnt++;
if(j+1<width)
if((Cells+where-width+1)->in_state==MINE) cnt++;
}
if(i+1<height){
if((Cells+where+width)->in_state==MINE) cnt++;
if(j-1>=0)
if((Cells+where+width-1)->in_state==MINE) cnt++;
if(j+1<width)
if((Cells+where+width+1)->in_state==MINE) cnt++;
}
if(j-1>=0)
if((Cells+where-1)->in_state==MINE) cnt++;
if(j+1<width)
if((Cells+where+1)->in_state==MINE) cnt++;
(Cells+where)->in_state=cnt;
}
#ifdef DEBUG
for(i=0;i<height;i++){
for(j=0;j<width;j++)
if((Cells+i*width+j)->in_state==MINE) printf("* "); else
printf("%d ",(Cells+i*width+j)->in_state);
printf("\n");
}
#endif
}
open_tile(int i,int j)
{
cell *aux;
if (first_tile) {
signal(SIGALRM,settime);
setitimer(ITIMER_REAL,&timer,NULL);
first_tile=0;
}
aux=Cells+i*width+j;
if(aux->out_state!=CLOSED && aux->out_state!=MARKED && aux->out_state!=QUEST)
return FALSE;
if(aux->in_state==MINE){
finish(" Game Over");
}
else if(aux->in_state==EMPTY)
return auto_open(i,j);
else {
if(aux->out_state==MARKED){
checks--;
sprintf(buff,"Checks: %d\n",checks);
xv_set(pmsg,PANEL_LABEL_STRING,buff,NULL);
}
PLACE_ICON(icons[aux->in_state],i*IC_WIDTH,
j*IC_HEIGHT);
aux->out_state=aux->in_state;
closed_tiles--;
return TRUE;
}
}
mark_tile(int i,int j)
{
cell *aux;
aux=Cells+i*width+j;
if(aux->out_state==MARKED || aux->out_state!=CLOSED && aux->out_state!=QUEST)
return FALSE;
PLACE_ICON(icons[MARKED],i*IC_WIDTH,j*IC_HEIGHT);
aux->out_state=MARKED;
checks++;
if(aux->in_state==MINE)
mines_2_go--;
sprintf(buff,"Checks: %d\n",checks);
xv_set(pmsg,PANEL_LABEL_STRING,buff,NULL);
return TRUE;
}
auto_open(int i,int j)
{
int where;
cell *ptr;
ptr=Cells+i*width+j;
if(ptr->out_state!=CLOSED && ptr->out_state!=MARKED && ptr->out_state!=QUEST
|| ptr->in_state>EIGHT) return FALSE;
if(ptr->out_state==MARKED){
checks--;
sprintf(buff,"Checks: %d\n",checks);
xv_set(pmsg,PANEL_LABEL_STRING,buff,NULL);
}
PLACE_ICON(icons[ptr->in_state],i*IC_WIDTH,j*IC_HEIGHT);
ptr->out_state=ptr->in_state;
closed_tiles--;
if(ptr->in_state==EMPTY){
if(i-1>=0){
auto_open(i-1,j);
if(j-1>=0) auto_open(i-1,j-1);
if(j+1<width) auto_open(i-1,j+1);
}
if(i+1<height){
auto_open(i+1,j);
if(j-1>=0) auto_open(i+1,j-1);
if(j+1<width) auto_open(i+1,j+1);
}
if(j-1>=0) auto_open(i,j-1);
if(j+1<width) auto_open(i,j+1);
return TRUE;
}
}
int init(){
register int i;
int j;
place_tiles(width*height,mines);
mines_2_go=mines;
playing=TRUE;
j=closed_tiles=width*height;
checks=0;
for(i=0;i<j;i++)
#ifndef DEBUG
PLACE_ICON(icons[CLOSED],(i/width)*IC_WIDTH,(i%width)*IC_HEIGHT);
#else
PLACE_ICON(icons[(Cells+i)->in_state],(i/width)*IC_WIDTH,(i%width)*IC_HEIGHT);
#endif
XCopyArea(display,pmap,dr_win,def_gc,0,0,
width*IC_WIDTH,height*IC_HEIGHT,0,0);
xv_set(smsg,XV_SHOW,FALSE,NULL);
xv_set(tmsg,PANEL_LABEL_STRING,"Time: 0:0",NULL);
xv_set(pmsg,PANEL_LABEL_STRING,"Checks: 0",NULL);
secs=0;
first_tile=1;
signal(SIGALRM,SIG_IGN);
}
show_placements(int len){
register int i;
for(i=0;i<len;i++)
if((Cells+i)->in_state==MINE) PLACE_ICON(icons[MINE],(i/width)*IC_WIDTH,
(i%width)*IC_HEIGHT);
XCopyArea(display,pmap,dr_win,def_gc,0,0,
width*IC_WIDTH,height*IC_HEIGHT,0,0);
}
void settime(void)
{
secs+=quantum;
sprintf(buff,"Time: %2d:%2d",secs/60,secs%60);
xv_set(tmsg,PANEL_LABEL_STRING,buff,NULL);
}
void finish(char *result)
{
playing=FALSE;
show_placements(width*height);
xv_set(smsg,PANEL_LABEL_STRING,result,
XV_SHOW,TRUE,
NULL);
getitimer(ITIMER_REAL,&timer);
secs+=quantum-timer.it_value.tv_sec;
sprintf(buff,"Time: %2d:%2d",secs/60,secs%60);
xv_set(tmsg,PANEL_LABEL_STRING,buff,NULL);
signal(SIGALRM,SIG_IGN);
}