X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fpacman.c;h=4eda4590c4e9a4354806b6390fbd03b81aa69d03;hp=b079605f14c73bdc15ce9e5ffa755620e4dbab46;hb=447db08c956099b3b183886729108bf5b364c4b8;hpb=2d04c4f22466851aedb6ed0f2919d148f726b889 diff --git a/hacks/pacman.c b/hacks/pacman.c index b079605f..4eda4590 100644 --- a/hacks/pacman.c +++ b/hacks/pacman.c @@ -1,7 +1,10 @@ -/* -*- Mode: C; tab-width: 4 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* pacman --- Mr. Pacman and his ghost friends */ -/*static const char sccsid[] = "@(#)pacman.c 5.00 2000/11/01 xlockmore";*/ +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)pacman.c 5.00 2000/11/01 xlockmore"; + +#endif /*- * Copyright (c) 2002 by Edwin de Jong . @@ -19,8 +22,14 @@ * other special, indirect and consequential damages. * * Revision History: - * 15-Aug-2004: Added support for pixmap pacman. Jeremy English jenglish@myself.com - * 11-Aug-2004: Added support for pixmap ghost. jenglish@myself.com + * 25-Feb-2005: Added bonus dots. I am using a recursive back track algorithm + * to help the ghost find there way home. This also means that + * they do not know the shorts path. + * Jeremy English jhe@jeremyenglish.org + * 15-Aug-2004: Added support for pixmap pacman. + * Jeremy English jhe@jeremyenglish.org + * 11-Aug-2004: Added support for pixmap ghost. + * Jeremy English jhe@jeremyenglish.org * 13-May-2002: Added -trackmouse feature thanks to code from 'maze.c'. * splitted up code into several files. Retouched AI code, cleaned * up code. @@ -32,8 +41,7 @@ */ /* TODO: - 1. add "bonus" dots - 2. think of a better level generation algorithm + 1. think of a better level generation algorithm */ #define DEF_TRACKMOUSE "False" @@ -47,13 +55,16 @@ # define DEFAULTS "*delay: 10000 \n" \ "*size: 0 \n" \ "*ncolors: 6 \n" \ - "*trackmouse: " DEF_TRACKMOUSE "\n" + # define UNIFORM_COLORS # define BRIGHT_COLORS -# include "xlockmore.h" /* in xscreensaver distribution */ +#include +#include + +# include "xlockmore.h" /* in xscreensaver distribution */ #else /* STANDALONE */ -# include "xlock.h" /* in xlockmore distribution */ +# include "xlock.h" /* in xlockmore distribution */ #endif /* STANDALONE */ #ifdef MODE_pacman @@ -80,7 +91,8 @@ # include "images/pacman/ghost-l2.xpm" # include "images/pacman/ghost-d1.xpm" # include "images/pacman/ghost-d2.xpm" -# include "images/pacman/ghost-mask.xpm" /* Used to clean up the dust left by wag. */ +/* Used to clean up the dust left by wag. */ +# include "images/pacman/ghost-mask.xpm" # include "images/pacman/pacman-u1.xpm" # include "images/pacman/pacman-u2.xpm" # include "images/pacman/pacman-r1.xpm" @@ -90,48 +102,71 @@ # include "images/pacman/pacman-d1.xpm" # include "images/pacman/pacman-d2.xpm" # include "images/pacman/pacman-0.xpm" +# include "images/pacman/ghost-s1.xpm" +# include "images/pacman/ghost-s2.xpm" +# include "images/pacman/ghost-sf1.xpm" +# include "images/pacman/ghost-sf2.xpm" +# include "images/pacman/eyes-l.xpm" +# include "images/pacman/eyes-r.xpm" +# include "images/pacman/eyes-u.xpm" +# include "images/pacman/eyes-d.xpm" +# include "images/pacman/pacman-ds1.xpm" +# include "images/pacman/pacman-ds2.xpm" +# include "images/pacman/pacman-ds3.xpm" +# include "images/pacman/pacman-ds4.xpm" +# include "images/pacman/pacman-ds5.xpm" +# include "images/pacman/pacman-ds6.xpm" +# include "images/pacman/pacman-ds7.xpm" +# include "images/pacman/pacman-ds8.xpm" #endif +static const struct +{ + int dx, dy; +} dirvecs[DIRVECS] = { { +-1, 0}, { +0, 1}, { +1, 0}, { +0, -1}}; + #ifdef DISABLE_INTERACTIVE ModeSpecOpt pacman_opts = { - 0, - (XrmOptionDescRec *) NULL, - 0, - (argtype *) NULL, - (OptionStruct *) NULL + 0, + (XrmOptionDescRec *) NULL, + 0, + (argtype *) NULL, + (OptionStruct *) NULL }; #else -static XrmOptionDescRec opts[] = -{ - {"-trackmouse", ".pacman.trackmouse", XrmoptionNoArg, "on"}, - {"+trackmouse", ".pacman.trackmouse", XrmoptionNoArg, "off"} +static XrmOptionDescRec opts[] = { + {"-trackmouse", ".pacman.trackmouse", XrmoptionNoArg, "on"}, + {"+trackmouse", ".pacman.trackmouse", XrmoptionNoArg, "off"} }; -static argtype vars[] = -{ - {&trackmouse, "trackmouse", "TrackMouse", DEF_TRACKMOUSE, t_Bool} +static argtype vars[] = { + {&trackmouse, "trackmouse", "TrackMouse", DEF_TRACKMOUSE, t_Bool} }; -static OptionStruct desc[] = -{ - {"-/+trackmouse", "turn on/off the tracking of the mouse"} +static OptionStruct desc[] = { + {"-/+trackmouse", "turn on/off the tracking of the mouse"} }; ModeSpecOpt pacman_opts = -{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, +desc }; #endif #ifdef USE_MODULES -ModStruct pacman_description = { - "pacman", /* *cmdline_arg; */ - "init_pacman", /* *init_name; */ - "draw_pacman", /* *callback_name; */ - "release_pacman", /* *release_name; */ - "refresh_pacman", /* *refresh_name; */ - "change_pacman", /* *change_name; */ - (char *) NULL, /* *unused_name; */ - &pacman_opts, /* *msopts */ - 10000, 4, 1, 0, 64, 1.0, "", "Shows Pacman(tm)", 0, NULL +ModStruct pacman_description = { + "pacman", /* *cmdline_arg; */ + "init_pacman", /* *init_name; */ + "draw_pacman", /* *callback_name; */ + "release_pacman", /* *release_name; */ + "refresh_pacman", /* *refresh_name; */ + "change_pacman", /* *change_name; */ + (char *) NULL, /* *unused_name; */ + &pacman_opts, /* *msopts */ + 10000, 4, 1, 0, 64, 1.0, "", "Shows Pacman(tm)", 0, NULL }; #endif @@ -140,307 +175,568 @@ Bool trackmouse; pacmangamestruct *pacmangames = (pacmangamestruct *) NULL; -static void repopulate(ModeInfo * mi); -static void drawlevel(ModeInfo * mi); +static void repopulate (ModeInfo * mi); +static void drawlevel (ModeInfo * mi); static void -free_pacman(Display *display, pacmangamestruct *pp) +free_pacman (Display * display, pacmangamestruct * pp) { - int dir, mouth, i, j, k; - - if (pp->ghosts != NULL) { - free(pp->ghosts); - pp->ghosts = (ghoststruct *) NULL; - } - if (pp->stippledGC != None) { - XFreeGC(display, pp->stippledGC); - pp->stippledGC = None; - } - for (i = 0; i < 4; i++){ - for (j = 0; j < MAXGDIR; j++){ - for (k = 0; k < MAXGWAG; k++){ - if (pp->ghostPixmap[i][j][k] != None) { - XFreePixmap(display, pp->ghostPixmap[i][j][k]); - pp->ghostPixmap[i][j][k] = None; - } - } - } - } - for (dir = 0; dir < 4; dir++) - for (mouth = 0; mouth < MAXMOUTH; mouth++) - if (pp->pacmanPixmap[dir][mouth] != None) { - XFreePixmap(display, - pp->pacmanPixmap[dir][mouth]); - pp->pacmanPixmap[dir][mouth] = None; - } + int dir, mouth, i, j, k; + + if (pp->ghosts != NULL) { + free (pp->ghosts); + pp->ghosts = (ghoststruct *) NULL; + } + if (pp->stippledGC != None) { + XFreeGC (display, pp->stippledGC); + pp->stippledGC = None; + } + for (i = 0; i < 4; i++) { + for (j = 0; j < MAXGDIR; j++) { + for (k = 0; k < MAXGWAG; k++) { + if (pp->ghostPixmap[i][j][k] != None) { + XFreePixmap (display, pp->ghostPixmap[i][j][k]); + pp->ghostPixmap[i][j][k] = None; + } + } + } + } + for (dir = 0; dir < 4; dir++) + for (mouth = 0; mouth < MAXMOUTH; mouth++) + if (pp->pacmanPixmap[dir][mouth] != None) { + XFreePixmap (display, pp->pacmanPixmap[dir][mouth]); + pp->pacmanPixmap[dir][mouth] = None; + } +} + +/* set pacman and the ghost in there starting positions, but don't draw a new + level */ +static void +reset_level (ModeInfo * mi, int n, int pac_init) +{ + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + unsigned int ghost; + + MI_CLEARWINDOW (mi); + drawlevel (mi); + + pp->gamestate = GHOST_DANGER; + + if ( pac_init ){ + pp->pacman.row = (LEVHEIGHT + JAILHEIGHT) / 2 - n; + pp->pacman.init_row = pp->pacman.row; + } + else{ + pp->pacman.row = pp->pacman.init_row; + } + pp->pacman.col = (LEVWIDTH / 2); + pp->pacman.nextrow = NOWHERE; + pp->pacman.nextcol = NOWHERE; + pp->pacman.cf = NOWHERE; + pp->pacman.rf = NOWHERE; + pp->pacman.oldcf = NOWHERE; + pp->pacman.oldrf = NOWHERE; + pp->pacman.oldlx = NOWHERE; + pp->pacman.oldly = NOWHERE; + pp->pacman.aistate = ps_eating; + pp->pacman.cur_trace = 0; + pp->pacman.roundscore = 0; + pp->pacman.speed = 4; + pp->pacman.lastturn = 0; + pp->pacman.delta.x = 0; + pp->pacman.delta.y = 0; + + for (ghost = 0; ghost < pp->nghosts; ghost++) { + pp->ghosts[ghost].col = (LEVWIDTH / 2); + pp->ghosts[ghost].row = (LEVHEIGHT / 2); + pp->ghosts[ghost].nextcol = NOWHERE; + pp->ghosts[ghost].nextrow = NOWHERE; + pp->ghosts[ghost].dead = 0; + pp->ghosts[ghost].lastbox = START; + pp->ghosts[ghost].cf = NOWHERE; + pp->ghosts[ghost].rf = NOWHERE; + pp->ghosts[ghost].oldcf = NOWHERE; + pp->ghosts[ghost].oldrf = NOWHERE; + pp->ghosts[ghost].aistate = inbox; + pp->ghosts[ghost].timeleft = ghost * 20; + pp->ghosts[ghost].speed = 3; + pp->ghosts[ghost].delta.x = 0; + pp->ghosts[ghost].delta.y = 0; + pp->ghosts[ghost].flash_scared = False; + pp->ghosts[ghost].wait_pos = False; + ghost_update (pp, &(pp->ghosts[ghost])); + } + pac_update (mi, pp, &(pp->pacman)); +} + +static int +pacman_ghost_collision(unsigned int ghost, pacmangamestruct * pp) +{ + return (((pp->ghosts[ghost].nextrow == pp->pacman.nextrow) && + (pp->ghosts[ghost].nextcol == pp->pacman.nextcol)) || + ((pp->ghosts[ghost].nextrow == pp->pacman.row) && + (pp->ghosts[ghost].nextcol == pp->pacman.col) && + (pp->ghosts[ghost].row == pp->pacman.nextrow) && + (pp->ghosts[ghost].col == pp->pacman.nextcol))); } /* Checks for death of any ghosts/pacman and updates. It also makes a new level if all ghosts are dead or all dots are eaten. */ static void -check_death(ModeInfo * mi, pacmangamestruct *pp) +check_death (ModeInfo * mi, pacmangamestruct * pp) { - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - unsigned int ghost; - int alldead; - - alldead = 1; - for (ghost = 0; ghost < pp->nghosts; ghost++) { - if (pp->ghosts[ghost].dead == True) - continue; - - if ((pp->ghosts[ghost].nextrow == NOWHERE && - pp->ghosts[ghost].nextcol == NOWHERE)) { - alldead = 0; - continue; - } - - if (((pp->ghosts[ghost].nextrow == pp->pacman.nextrow) && - (pp->ghosts[ghost].nextcol == pp->pacman.nextcol)) || - ((pp->ghosts[ghost].nextrow == pp->pacman.row) && - (pp->ghosts[ghost].nextcol == pp->pacman.col) && - (pp->ghosts[ghost].row == pp->pacman.nextrow) && - (pp->ghosts[ghost].col == pp->pacman.nextcol))) { - pp->ghosts[ghost].dead = 1; - XSetForeground(display, - pp->stippledGC, - MI_BLACK_PIXEL(mi)); - XFillRectangle(display, window, - pp->stippledGC, - pp->ghosts[ghost].cf, - pp->ghosts[ghost].rf, - pp->spritexs, - pp->spriteys); - - } else - alldead = 0; - } - - if (alldead == 1 || pp->dotsleft == 0) - repopulate(mi); + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + unsigned int ghost; + int alldead; + + if (pp->pacman.aistate == ps_dieing) return; + + alldead = 1; + for (ghost = 0; ghost < pp->nghosts; ghost++) { + + /* The ghost have to be scared before you can kill them */ + if ( pacman_ghost_collision ( ghost, pp ) ) { + if (pp->ghosts[ghost].aistate == goingin) continue; + + if (pp->ghosts[ghost].aistate == hiding) { + pp->ghosts[ghost].dead = 1; + pp->ghosts[ghost].aistate = goingin; + pp->ghosts[ghost].wait_pos = True; + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + XFillRectangle (display, window, + pp->stippledGC, + pp->ghosts[ghost].cf, + pp->ghosts[ghost].rf, + pp->spritexs, pp->spriteys); + } + /* DIE PACMAN... */ + else { + pp->pacman.deaths++; + pp->pacman.aistate = ps_dieing; + + } + continue; + } + + alldead = 0; + } + + } /* Resets state of ghosts + pacman. Creates a new level, draws that level. */ static void -repopulate(ModeInfo * mi) +repopulate (ModeInfo * mi) { - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; - unsigned int ghost; - int i = createnewlevel(mi); - - MI_CLEARWINDOW(mi); - drawlevel(mi); - - pp->gamestate = GHOST_DANGER; - - pp->pacman.row = (LEVHEIGHT + JAILHEIGHT)/2 - i; - pp->pacman.col = (LEVWIDTH/2); - pp->pacman.nextrow = NOWHERE; - pp->pacman.nextcol = NOWHERE; - pp->pacman.cf = NOWHERE; - pp->pacman.rf = NOWHERE; - pp->pacman.oldcf = NOWHERE; - pp->pacman.oldrf = NOWHERE; - pp->pacman.oldlx = NOWHERE; - pp->pacman.oldly = NOWHERE; - pp->pacman.aistate = ps_eating; - pp->pacman.cur_trace = 0; - pp->pacman.roundscore = 0; - pp->pacman.speed = 4; - pp->pacman.lastturn = 0; - pp->pacman.delta.x = 0; - pp->pacman.delta.y = 0; - pac_clear_trace(&(pp->pacman)); - - for (ghost = 0; ghost < pp->nghosts; ghost++) { - pp->ghosts[ghost].col = (LEVWIDTH/2); - pp->ghosts[ghost].row = (LEVHEIGHT/2); - pp->ghosts[ghost].nextcol = NOWHERE; - pp->ghosts[ghost].nextrow = NOWHERE; - pp->ghosts[ghost].dead = 0; - pp->ghosts[ghost].lastbox = START; - pp->ghosts[ghost].cf = NOWHERE; - pp->ghosts[ghost].rf = NOWHERE; - pp->ghosts[ghost].oldcf = NOWHERE; - pp->ghosts[ghost].oldrf = NOWHERE; - pp->ghosts[ghost].aistate = inbox; - pp->ghosts[ghost].timeleft = ghost * 50; - pp->ghosts[ghost].speed = 3; - pp->ghosts[ghost].delta.x = 0; - pp->ghosts[ghost].delta.y = 0; - - ghost_update(pp, &(pp->ghosts[ghost])); - } - check_death(mi, pp); - pac_update(mi, pp, &(pp->pacman)); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + pp->pacman.deaths = 0; + reset_level (mi, createnewlevel (mi), True); + check_death (mi, pp); } /* Sets the color to the color of a wall. */ -static void -setwallcolor(ModeInfo * mi) +static void +setwallcolor (ModeInfo * mi) { - Display *display = MI_DISPLAY(mi); - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; - - if (MI_NPIXELS(mi) > 2) - XSetForeground(display, pp->stippledGC, - MI_PIXEL(mi, BLUE)); - else - XSetForeground(display, pp->stippledGC, - MI_WHITE_PIXEL(mi)); + Display *display = MI_DISPLAY (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + + if (MI_NPIXELS (mi) > 2) + XSetForeground (display, pp->stippledGC, MI_PIXEL (mi, BLUE)); + else + XSetForeground (display, pp->stippledGC, MI_WHITE_PIXEL (mi)); } /* Sets the color to the color of a dot. */ -static void -setdotcolor(ModeInfo * mi) +static void +setdotcolor (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + + XSetForeground (display, pp->stippledGC, MI_WHITE_PIXEL (mi)); +} + +static void +cleardotcolor (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); +} + +#if 0 +static void +draw_position (ModeInfo * mi, int x, int y, int color) { - Display *display = MI_DISPLAY(mi); - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + XFontStruct *font = NULL; + char *f_name = "-*-utopia-*-r-*-*-*-600-*-*-p-*-*-*"; + char *s = NULL; + + font = XLoadQueryFont (display, f_name); + assert (font != NULL); + + s = (char *) malloc (256); + assert (s != NULL); + sprintf (s, "(%d,%d)", x, y); + XSetForeground (display, pp->stippledGC, color); + XDrawString (display, window, pp->stippledGC, x, y, s, strlen (s)); + free (s); + free (font); +} +#endif +#if 0 +static void +draw_number (ModeInfo * mi, int x, int y, int num, int color) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + XFontStruct *font = NULL; + char *f_name = "-*-utopia-*-r-*-*-*-600-*-*-p-*-*-*"; + char *s = NULL; + + font = XLoadQueryFont (display, f_name); + assert (font != NULL); + + s = (char *) malloc (256); + assert (s != NULL); + sprintf (s, "%d", num); + XSetForeground (display, pp->stippledGC, color); + XDrawString (display, window, pp->stippledGC, x, y, s, strlen (s)); + free (s); + free (font); +} +#endif - XSetForeground(display, pp->stippledGC, - MI_WHITE_PIXEL(mi)); +#if 0 +/* draw_grid - draws a grid on top of the playing field. + * Used so that I can determine if I'm converting from rows and columns to x and y + * coordinates correctly. + */ +static void +draw_grid (ModeInfo * mi) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + int h = MI_HEIGHT (mi); + int w = MI_WIDTH (mi); + int y = 0; + int x = 0; + XSetForeground (display, pp->stippledGC, 0xff0000); + while (y < h) { + while (x < w) { + XDrawLine (display, window, pp->stippledGC, x, 0, x, h); + x += 10; + } + x = 0; + XDrawLine (display, window, pp->stippledGC, 0, y, w, y); + y += 10; + } +} +#endif + +#if 0 +static void +draw_string (ModeInfo * mi, int x, int y, char *s, int color) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + XFontStruct *font = NULL; + char *f_name = "-*-utopia-*-r-*-*-*-600-*-*-p-*-*-*"; + + font = XLoadQueryFont (display, f_name); + assert (font != NULL); + + assert (s != NULL); + XSetForeground (display, pp->stippledGC, color); + XDrawString (display, window, pp->stippledGC, x, y, s, strlen (s)); + free (font); +} + +/* I think this function has a memory leak. Be careful if you enable it. */ +/* I only used it briefly to help me debug the ghost's aistate. It prints */ +/* the state of each ghost on the left hand side of the screen */ +static void +print_ghost_stats (ModeInfo *mi, ghoststruct *g , int ghost_num) +{ + char s[1024]; + + sprintf (s, "GHOST: %d", ghost_num ); + switch (g->aistate){ + case inbox: + sprintf (s, "%s inbox", s); + break; + case goingout: + sprintf (s, "%s goingout", s); + break; + case randdir: + sprintf (s, "%s randdir", s); + break; + case chasing: + sprintf (s, "%s chasing", s); + break; + case hiding: + sprintf (s, "%s hiding", s); + break; + case goingin: + sprintf (s, "%s goingin",s); + break; + } + draw_string (mi, 0, (ghost_num *3) *10+50, g->last_stat, 0x000000); + draw_string (mi, 0, (ghost_num *3) *10+50, s, 0xff0000); + strcpy(g->last_stat,s); +} + +/* prints the number of times pacman has died and his aistate on the left hand */ +/* side of the screen */ +static void +print_pac_stats ( ModeInfo *mi, pacmanstruct *pac ) +{ + static char last_pac_stat[1024] = "\0"; + char s[1024]; + sprintf (s, "Pacman, Deaths: %d", pac->deaths ); + switch ( pac->aistate ){ + case ps_eating: + sprintf(s, "%s ps_eating",s ); + break; + case ps_chasing: + sprintf(s, "%s ps_chasing",s ); + break; + case ps_hiding: + sprintf(s, "%s ps_hiding",s ); + break; + case ps_random: + sprintf(s, "%s ps_random",s ); + break; + case ps_dieing: + sprintf(s, "%s ps_dieing",s ); + break; + } + draw_string ( mi, 0, 200, last_pac_stat, 0x000000); + draw_string ( mi, 0, 200, s, 0xff0000); + strcpy(last_pac_stat, s ); +} + +#endif + +/*Ok, yeah whatever?*/ +/*dot_rc_to_pixel - magic that converts row and columns into + *the x and y coordinates of the screen. + */ +static void +dot_rc_to_pixel (ModeInfo * mi, int *x, int *y) +{ + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + *x = (pp->xs * *x) + + (pp->xs / 2) - (pp->xs > 32 ? (pp->xs / 16) : 1) + pp->xb; + *y = (pp->ys * *y) + + (pp->ys / 2) - (pp->ys > 32 ? (pp->ys / 16) : 1) + pp->yb; +} + +/* dot_width_height - magic used to get the width and height of + * a dot. This dot can also be scaled by a value. + */ +static void +dot_width_height (ModeInfo *mi, int *w, int *h) +{ + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + if (pp->xs > 32){ + *w = *h = (pp->xs / 32 ); + }else { + *w = *h = 1; + } +} + +static void +bonus_dot_width_height (ModeInfo *mi, int *w, int *h ) +{ + *w = *h = MI_HEIGHT (mi) / 65; +} + + + +static void +draw_dot (ModeInfo * mi, pacmangamestruct * pp, int x, int y, + void (*width_height)(ModeInfo * mi, int *w, int *h), + int (*arc_func) (Display * display, Drawable d, GC gc, + int x, int y, unsigned int width, + unsigned int height, int angle1, + int angle2)) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + int w, h; + dot_rc_to_pixel (mi, &x, &y); + width_height(mi, &w, &h); + (void) arc_func (display, window, pp->stippledGC, + x, y, w, h, 0, 23040); +} + +static void +draw_bonus_dot (ModeInfo * mi, pacmangamestruct * pp, int x, int y) +{ + int x2 = x; + int y2 = y; + setdotcolor (mi); + draw_dot (mi, pp, x, y, bonus_dot_width_height, XFillArc); + dot_rc_to_pixel (mi, &x2, &y2); +#if 0 + draw_position (mi, x2, y2, 0xff0000); +#endif +} + +static void +clear_bonus_dot (ModeInfo * mi, pacmangamestruct * pp, int x, int y) +{ + cleardotcolor (mi); + draw_dot (mi, pp, x, y, bonus_dot_width_height, XFillArc); +} + +static void +draw_regular_dot (ModeInfo * mi, pacmangamestruct * pp, int x, int y) +{ + setdotcolor (mi); + draw_dot (mi, pp, x, y, dot_width_height, XDrawArc); } /* Draws a block in the level at the specified x and y locations. */ static void -drawlevelblock(ModeInfo * mi, pacmangamestruct *pp, - const unsigned x, const unsigned y) +drawlevelblock (ModeInfo * mi, pacmangamestruct * pp, + const unsigned x, const unsigned y) { - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - int dx = 0, dy = 0; - - if (pp->xs % 2 == 1) dx = -1; - if (pp->ys % 2 == 1) dy = -1; - - XSetFillStyle(display, pp->stippledGC, FillSolid); - XSetLineAttributes(display, pp->stippledGC, pp->wallwidth, - LineSolid, CapRound, JoinMiter); - - if (pp->xs < 2 || pp->ys < 2) { - switch(pp->level[y*LEVWIDTH + x]) { - case ' ': - case '=': - break; - case '.': - setdotcolor(mi); - (void)XDrawPoint(display, window, - pp->stippledGC, - x * pp->xs + pp->xb, - y * pp->ys + pp->yb); - break; - default: - setwallcolor(mi); - (void)XDrawPoint(display, window, - pp->stippledGC, - x * pp->xs + pp->xb, - y * pp->ys + pp->yb); - } - - return; - } - - switch (pp->level[y*LEVWIDTH + x]) { - case ' ': - case '=': - break; - - case '.': - setdotcolor(mi); - if (pp->xs < 8 || pp->ys < 8) { - (void)XDrawPoint(display, window, - pp->stippledGC, - x * pp->xs + pp->xb + - pp->xs/2, - y * pp->ys + pp->yb + - pp->ys/2); - break; - } - - (void)XDrawArc(display, window, pp->stippledGC, - (pp->xs * x) + - (pp->xs / 2) - - (pp->xs > 32 ? (pp->xs / 16) : 1) + - pp->xb, - (pp->ys * y) + - (pp->ys / 2) - - (pp->ys > 32 ? (pp->ys / 16) : 1) + - pp->yb, - (pp->xs > 32 ? (pp->xs / 32) : 1), - (pp->ys > 32 ? (pp->ys / 32) : 1), - 0, 23040); - break; - - case '-': - setwallcolor(mi); - (void)XDrawLine(display, window, pp->stippledGC, - (pp->xs * x) + pp->xb, - (pp->ys * y) + (pp->ys / 2) + pp->yb, - (pp->xs * (x + 1)) + pp->xb, - (pp->ys * y) + (pp->ys / 2) + pp->yb); - break; - - case '|': - setwallcolor(mi); - (void)XDrawLine(display, window, pp->stippledGC, - (pp->xs * x) + (pp->xs / 2) + pp->xb, - (pp->ys * y) + pp->yb, - (pp->xs * x) + (pp->xs / 2) + pp->xb, - (pp->ys * (y + 1)) + pp->yb); - break; - - case '_': - setwallcolor(mi); - (void)XDrawArc(display, window, pp->stippledGC, - (pp->xs * x) - (pp->ys / 2) + pp->xb + dx, - (pp->ys * y) + (pp->ys / 2) + pp->yb, - pp->xs, pp->ys, - 0*64, 90*64); - break; - - case ',': - setwallcolor(mi); - (void)XDrawArc(display, window, pp->stippledGC, - (pp->xs * x) + (pp->ys / 2) + pp->xb, - (pp->ys * y) + (pp->ys / 2) + pp->yb, - pp->xs, pp->ys, - 90*64, 90*64); - break; - - case '`': - setwallcolor(mi); - (void)XDrawArc(display, window, pp->stippledGC, - (pp->xs * x) + (pp->ys / 2) + pp->xb, - (pp->ys * y) - (pp->ys / 2) + pp->yb + dy, - pp->xs, pp->ys, - 180*64, 90*64); - break; - - case '\'': - setwallcolor(mi); - (void)XDrawArc(display, window, pp->stippledGC, - (pp->xs * x) - (pp->ys / 2) + pp->xb + dx, - (pp->ys * y) - (pp->ys / 2) + pp->yb + dy, - pp->xs, pp->ys, - 270*64, 90*64); - break; - - } + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + int dx = 0, dy = 0; + + if (pp->xs % 2 == 1) + dx = -1; + if (pp->ys % 2 == 1) + dy = -1; + + XSetFillStyle (display, pp->stippledGC, FillSolid); + XSetLineAttributes (display, pp->stippledGC, pp->wallwidth, + LineSolid, CapRound, JoinMiter); + + if (pp->xs < 2 || pp->ys < 2) { + switch (pp->level[y * LEVWIDTH + x]) { + case ' ': + case '=': + break; + case '.': + setdotcolor (mi); + (void) XDrawPoint (display, window, + pp->stippledGC, + x * pp->xs + pp->xb, y * pp->ys + pp->yb); + break; + default: + setwallcolor (mi); + (void) XDrawPoint (display, window, + pp->stippledGC, + x * pp->xs + pp->xb, y * pp->ys + pp->yb); + } + + return; + } + + switch (pp->level[y * LEVWIDTH + x]) { + case ' ': + case '=': + break; + + case '.': + setdotcolor (mi); + if (pp->xs < 8 || pp->ys < 8) { + (void) XDrawPoint (display, window, + pp->stippledGC, + x * pp->xs + pp->xb + + pp->xs / 2, y * pp->ys + pp->yb + pp->ys / 2); + break; + } + + draw_regular_dot (mi, pp, x, y); + break; + /* What we will probably want to do here is have the pp->level store a 'o' for + * the bonus dots. The we can use the drawing routine above just with a bigger + * radius. + */ + case 'o': + draw_bonus_dot (mi, pp, x, y); + break; + + + case '-': + setwallcolor (mi); + (void) XDrawLine (display, window, pp->stippledGC, + (pp->xs * x) + pp->xb, + (pp->ys * y) + (pp->ys / 2) + pp->yb, + (pp->xs * (x + 1)) + pp->xb, + (pp->ys * y) + (pp->ys / 2) + pp->yb); + break; + + case '|': + setwallcolor (mi); + (void) XDrawLine (display, window, pp->stippledGC, + (pp->xs * x) + (pp->xs / 2) + pp->xb, + (pp->ys * y) + pp->yb, + (pp->xs * x) + (pp->xs / 2) + pp->xb, + (pp->ys * (y + 1)) + pp->yb); + break; + + case '_': + setwallcolor (mi); + (void) XDrawArc (display, window, pp->stippledGC, + (pp->xs * x) - (pp->ys / 2) + pp->xb + dx, + (pp->ys * y) + (pp->ys / 2) + pp->yb, + pp->xs, pp->ys, 0 * 64, 90 * 64); + break; + + case ',': + setwallcolor (mi); + (void) XDrawArc (display, window, pp->stippledGC, + (pp->xs * x) + (pp->ys / 2) + pp->xb, + (pp->ys * y) + (pp->ys / 2) + pp->yb, + pp->xs, pp->ys, 90 * 64, 90 * 64); + break; + + case '`': + setwallcolor (mi); + (void) XDrawArc (display, window, pp->stippledGC, + (pp->xs * x) + (pp->ys / 2) + pp->xb, + (pp->ys * y) - (pp->ys / 2) + pp->yb + dy, + pp->xs, pp->ys, 180 * 64, 90 * 64); + break; + + case '\'': + setwallcolor (mi); + (void) XDrawArc (display, window, pp->stippledGC, + (pp->xs * x) - (pp->ys / 2) + pp->xb + dx, + (pp->ys * y) - (pp->ys / 2) + pp->yb + dy, + pp->xs, pp->ys, 270 * 64, 90 * 64); + break; + + } } /* Draws a complete level. */ static void -drawlevel(ModeInfo * mi) -{ - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; - unsigned int x, y; - - for (y = 0; y < LEVHEIGHT; y++) - for (x = 0; x < LEVWIDTH; x++) - drawlevelblock(mi, pp, x, y); +drawlevel (ModeInfo * mi) +{ + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + unsigned int x, y; + + for (y = 0; y < LEVHEIGHT; y++) + for (x = 0; x < LEVWIDTH; x++) + drawlevelblock (mi, pp, x, y); } /* There is some overlap so it can be made more efficient */ @@ -463,285 +759,520 @@ drawlevel(ModeInfo * mi) #if defined(USE_PIXMAP) static void -draw_pacman_sprite(ModeInfo * mi) +draw_pacman_sprite (ModeInfo * mi) { - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; - unsigned int dir = 0; - int old_mask_dir = 0; - int old_mask_mouth = 0; - static int mouth = 0; - static int mouth_delay = 0; - static int open_mouth = 0; - -#define MAX_MOUTH_DELAY 10 - - pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x * - pp->pacman.cfactor + pp->xb + pp->spritedx; - pp->pacman.rf = pp->pacman.row * pp->ys + pp->pacman.delta.y * - pp->pacman.rfactor + pp->yb + pp->spritedy; - - dir = (ABS(pp->pacman.cfactor) * (2 - pp->pacman.cfactor) + - ABS(pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4; - - if (mouth_delay == MAX_MOUTH_DELAY){ - if (mouth == (MAXMOUTH - 1)|| mouth == 0){ - open_mouth = !open_mouth; - } - open_mouth ? mouth++ : mouth--; - mouth_delay = 0; - }else { - mouth_delay++; - } - - XSetForeground(display, - pp->stippledGC, - MI_BLACK_PIXEL(mi)); - - XSetClipMask(display, pp->stippledGC, pp->pacmanMask[old_mask_dir][old_mask_mouth]); - XSetClipOrigin(display, pp->stippledGC, - pp->pacman.oldcf, pp->pacman.oldrf); - XFillRectangle(display, - window, - pp->stippledGC, - pp->pacman.oldcf, - pp->pacman.oldrf, - pp->spritexs, pp->spriteys); - XSetClipMask(display, pp->stippledGC, pp->pacmanMask[dir][mouth]); - XSetClipOrigin(display, pp->stippledGC, - pp->pacman.cf, pp->pacman.rf); - XCopyArea(display, pp->pacmanPixmap[dir][mouth], window, - pp->stippledGC,0,0,pp->spritexs,pp->spriteys, - pp->pacman.cf, pp->pacman.rf); - XSetClipMask(display, pp->stippledGC, None); - pp->pacman.oldcf = pp->pacman.cf; - pp->pacman.oldrf = pp->pacman.rf; - old_mask_dir = dir; - old_mask_mouth = mouth; + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + unsigned int dir = 0; + int old_mask_dir = 0; + int old_mask_mouth = 0; + static int mouth = 0; + static int mouth_delay = 0; + static int open_mouth = 0; + static int death_frame = 0; + static int death_delay = 0; + Pixmap old_mask, new_mask; + Pixmap pacman; + +#define MAX_MOUTH_DELAY 2 +#define MAX_DEATH_DELAY 20 + + if (pp->pacman.aistate == ps_dieing){ + pp->pacman.cf = pp->pacman.oldcf; + pp->pacman.rf = pp->pacman.oldrf; + } + else { + pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x * + pp->pacman.cfactor + pp->xb + pp->spritedx; + pp->pacman.rf = pp->pacman.row * pp->ys + pp->pacman.delta.y * + pp->pacman.rfactor + pp->yb + pp->spritedy; + } + + dir = (ABS (pp->pacman.cfactor) * (2 - pp->pacman.cfactor) + + ABS (pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4; + + if (mouth_delay == MAX_MOUTH_DELAY) { + if (mouth == (MAXMOUTH - 1) || mouth == 0) { + open_mouth = !open_mouth; + } + open_mouth ? mouth++ : mouth--; + mouth_delay = 0; + } + else { + mouth_delay++; + } + + if (pp->pacman.aistate == ps_dieing){ + if (death_frame >= PAC_DEATH_FRAMES) { + pp->pacman.aistate = ps_eating; + death_frame = 0; + death_delay = 0; + reset_level (mi, 0, False); + return; + } + else { + old_mask = pp->pacmanMask[0][0]; + new_mask = pp->pacmanMask[0][0]; + pacman = pp->pacman_ds[death_frame]; + if (death_delay == MAX_DEATH_DELAY){ + death_frame++; + death_delay = 0; + } + else{ + death_delay++; + } + } + } + else{ + old_mask = pp->pacmanMask[old_mask_dir][old_mask_mouth]; + new_mask = pp->pacmanMask[dir][mouth]; + pacman = pp->pacmanPixmap[dir][mouth]; + } + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + + XSetClipMask (display, pp->stippledGC, old_mask); + + XSetClipOrigin (display, pp->stippledGC, pp->pacman.oldcf, + pp->pacman.oldrf); + XFillRectangle (display, window, pp->stippledGC, pp->pacman.oldcf, + pp->pacman.oldrf, pp->spritexs, pp->spriteys); + XSetClipMask (display, pp->stippledGC, new_mask); + XSetClipOrigin (display, pp->stippledGC, pp->pacman.cf, pp->pacman.rf); + XCopyArea (display, pacman, window, + pp->stippledGC, 0, 0, pp->spritexs, pp->spriteys, + pp->pacman.cf, pp->pacman.rf); + XSetClipMask (display, pp->stippledGC, None); + if (pp->pacman.aistate != ps_dieing){ + pp->pacman.oldcf = pp->pacman.cf; + pp->pacman.oldrf = pp->pacman.rf; + } + old_mask_dir = dir; + old_mask_mouth = mouth; } +#if 0 +static void +draw_ghost_position (ModeInfo * mi, ghoststruct * ghost) +{ + draw_position (mi, ghost->oldcf, ghost->oldrf, MI_BLACK_PIXEL (mi)); + draw_position (mi, ghost->cf, ghost->rf, 0x00ff00); +} +#endif +#if 0 +static void +draw_ghost_ndirs ( ModeInfo *mi, ghoststruct * ghost) +{ + draw_number (mi, ghost->oldcf, ghost->oldrf, ghost->oldndirs, MI_BLACK_PIXEL (mi)); + ghost->oldndirs = ghost->ndirs; + draw_number (mi, ghost->cf, ghost->rf, ghost->ndirs, 0x00ff00); +} +#endif static void -draw_ghost_sprite(ModeInfo * mi, const unsigned ghost){ - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; - static int wag = 0; +draw_ghost_sprite (ModeInfo * mi, const unsigned ghost) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + static int wag = 0; #define MAX_WAG_COUNT 50 - static int wag_count = 0; - unsigned int dir = 0; - - dir = (ABS(pp->ghosts[ghost].cfactor) * (2 - pp->ghosts[ghost].cfactor) + - ABS(pp->ghosts[ghost].rfactor) * (1 + pp->ghosts[ghost].rfactor)) % 4; - - pp->ghosts[ghost].cf = - pp->ghosts[ghost].col * pp->xs + pp->ghosts[ghost].delta.x * - pp->ghosts[ghost].cfactor + pp->xb + pp->spritedx; - pp->ghosts[ghost].rf = - pp->ghosts[ghost].row * pp->ys + pp->ghosts[ghost].delta.y * - pp->ghosts[ghost].rfactor + pp->yb + pp->spritedy; - XSetForeground(display, - pp->stippledGC, - MI_BLACK_PIXEL(mi)); - - XSetClipMask(display, pp->stippledGC, pp->ghostMask); - XSetClipOrigin(display, pp->stippledGC, - pp->ghosts[ghost].oldcf, pp->ghosts[ghost].oldrf); - XFillRectangle(display, - window, - pp->stippledGC, - pp->ghosts[ghost].oldcf, - pp->ghosts[ghost].oldrf, - pp->spritexs, pp->spriteys); - drawlevelblock(mi, pp, - (unsigned int)pp->ghosts[ghost].col, - (unsigned int)pp->ghosts[ghost].row); - XSetClipOrigin(display, pp->stippledGC, - pp->ghosts[ghost].cf, pp->ghosts[ghost].rf); - XCopyArea(display, pp->ghostPixmap[ghost][dir][wag], window, - pp->stippledGC,0,0,pp->spritexs,pp->spriteys, - pp->ghosts[ghost].cf, pp->ghosts[ghost].rf); - XSetClipMask(display, pp->stippledGC, None); - pp->ghosts[ghost].oldcf = pp->ghosts[ghost].cf; - pp->ghosts[ghost].oldrf = pp->ghosts[ghost].rf; - if (wag_count++ == MAX_WAG_COUNT){ - wag = !wag; - wag_count = 0; - } + static int wag_count = 0; + unsigned int dir = 0; + unsigned int fs = 0; /*flash scared*/ + Pixmap g_pix; /*ghost pixmap*/ + + + dir = (ABS (pp->ghosts[ghost].cfactor) * (2 - pp->ghosts[ghost].cfactor) + + ABS (pp->ghosts[ghost].rfactor) * (1 + pp->ghosts[ghost].rfactor)) % 4; + + + fs = pp->ghosts[ghost].flash_scared; + assert (fs == 0 || fs == 1); + + /* Choose the pixmap */ + switch (pp->ghosts[ghost].aistate){ + case hiding: + g_pix = pp->s_ghostPixmap[fs][wag]; + break; + case goingin: + g_pix = pp->ghostEyes[dir]; +#if 1 + { + int i = 0; + while ( i < pp->ghosts[ghost].trace_idx ){ + XFillRectangle (display, + window, + pp->stippledGC, + pp->ghosts[ghost].trace[i].vx, + pp->ghosts[ghost].trace[i].vy, + pp->spritexs, pp->spriteys); + + i++; + } + } +#endif + + break; + default: + g_pix = pp->ghostPixmap[ghost][dir][wag]; + } + + pp->ghosts[ghost].cf = + pp->ghosts[ghost].col * pp->xs + pp->ghosts[ghost].delta.x * + pp->ghosts[ghost].cfactor + pp->xb + pp->spritedx; + pp->ghosts[ghost].rf = + pp->ghosts[ghost].row * pp->ys + pp->ghosts[ghost].delta.y * + pp->ghosts[ghost].rfactor + pp->yb + pp->spritedy; + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + + XSetClipMask (display, pp->stippledGC, pp->ghostMask); + XSetClipOrigin (display, pp->stippledGC, + pp->ghosts[ghost].oldcf, pp->ghosts[ghost].oldrf); + XFillRectangle (display, + window, + pp->stippledGC, + pp->ghosts[ghost].oldcf, + pp->ghosts[ghost].oldrf, pp->spritexs, pp->spriteys); + + + if (pp->pacman.aistate != ps_dieing) { + drawlevelblock (mi, pp, + (unsigned int) pp->ghosts[ghost].col, + (unsigned int) pp->ghosts[ghost].row); + + + + XSetClipOrigin (display, pp->stippledGC, + pp->ghosts[ghost].cf, pp->ghosts[ghost].rf); + + XCopyArea (display, g_pix, window, pp->stippledGC, 0, 0, + pp->spritexs, pp->spriteys, pp->ghosts[ghost].cf, + pp->ghosts[ghost].rf); + } + XSetClipMask (display, pp->stippledGC, None); + +#if 0 + draw_ghost_position (mi, &(pp->ghosts[ghost])); +#endif + +#if 0 + draw_ghost_ndirs ( mi, &(pp->ghosts[ghost])); +#endif + + if (pp->pacman.aistate != ps_dieing) { + pp->ghosts[ghost].oldcf = pp->ghosts[ghost].cf; + pp->ghosts[ghost].oldrf = pp->ghosts[ghost].rf; + if (wag_count++ == MAX_WAG_COUNT) { + wag = !wag; + wag_count = 0; + } + } } #else /* USE_PIXMAP */ /* Draws the pacman sprite, removing the previous location. */ static void -draw_pacman_sprite(ModeInfo * mi) +draw_pacman_sprite (ModeInfo * mi) { - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; - unsigned int dir; - - pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x * - pp->pacman.cfactor + pp->xb + pp->spritedx; - pp->pacman.rf = pp->pacman.row * pp->ys + pp->pacman.delta.y * - pp->pacman.rfactor + pp->yb + pp->spritedy; - - dir = (ABS(pp->pacman.cfactor) * (2 - pp->pacman.cfactor) + - ABS(pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4; - - XSetForeground(display, pp->stippledGC, - MI_BLACK_PIXEL(mi)); - if (pp->pacman.oldcf != NOWHERE && pp->pacman.oldrf != NOWHERE) { + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + unsigned int dir; + + pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x * + pp->pacman.cfactor + pp->xb + pp->spritedx; + pp->pacman.rf = pp->pacman.row * pp->ys + pp->pacman.delta.y * + pp->pacman.rfactor + pp->yb + pp->spritedy; + + dir = (ABS (pp->pacman.cfactor) * (2 - pp->pacman.cfactor) + + ABS (pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4; + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + if (pp->pacman.oldcf != NOWHERE && pp->pacman.oldrf != NOWHERE) { #ifdef FLASH - XFillRectangle(display, window, pp->stippledGC, - pp->pacman.oldcf, pp->pacman.oldrf, - pp->spritexs, pp->spriteys); + XFillRectangle (display, window, pp->stippledGC, + pp->pacman.oldcf, pp->pacman.oldrf, + pp->spritexs, pp->spriteys); #else - ERASE_IMAGE(display, window, pp->stippledGC, - pp->pacman.cf, pp->pacman.rf, - pp->pacman.oldcf, pp->pacman.oldrf, - pp->spritexs, pp->spriteys); + ERASE_IMAGE (display, window, pp->stippledGC, + pp->pacman.cf, pp->pacman.rf, + pp->pacman.oldcf, pp->pacman.oldrf, + pp->spritexs, pp->spriteys); #endif - } - - XSetTSOrigin(display, pp->stippledGC, - pp->pacman.cf, pp->pacman.rf); - if (MI_NPIXELS(mi) > 2) - XSetForeground(display, pp->stippledGC, - MI_PIXEL(mi, YELLOW)); - else - XSetForeground(display, pp->stippledGC, - MI_WHITE_PIXEL(mi)); - - XSetStipple(display, pp->stippledGC, - pp->pacmanPixmap[dir][pp->pacman.mouthstage]); + } + + XSetTSOrigin (display, pp->stippledGC, pp->pacman.cf, pp->pacman.rf); + if (MI_NPIXELS (mi) > 2) + XSetForeground (display, pp->stippledGC, MI_PIXEL (mi, YELLOW)); + else + XSetForeground (display, pp->stippledGC, MI_WHITE_PIXEL (mi)); + + XSetStipple (display, pp->stippledGC, + pp->pacmanPixmap[dir][pp->pacman.mouthstage]); #ifdef FLASH - XSetFillStyle(display, pp->stippledGC, FillStippled); + XSetFillStyle (display, pp->stippledGC, FillStippled); #else - XSetFillStyle(display, pp->stippledGC, - FillOpaqueStippled); + XSetFillStyle (display, pp->stippledGC, FillOpaqueStippled); #endif - if (pp->xs < 2 || pp->ys < 2) - XDrawPoint(display, window, pp->stippledGC, - pp->pacman.cf, pp->pacman.rf); - else - XFillRectangle(display, window, pp->stippledGC, - pp->pacman.cf, pp->pacman.rf, - pp->spritexs, pp->spriteys); - pp->pacman.mouthstage += pp->pacman.mouthdirection; - if ((pp->pacman.mouthstage >= MAXMOUTH) || - (pp->pacman.mouthstage < 0)) { - pp->pacman.mouthdirection *= -1; - pp->pacman.mouthstage += pp->pacman.mouthdirection * 2; - } - pp->pacman.oldcf = pp->pacman.cf; - pp->pacman.oldrf = pp->pacman.rf; + if (pp->xs < 2 || pp->ys < 2) + XDrawPoint (display, window, pp->stippledGC, + pp->pacman.cf, pp->pacman.rf); + else + XFillRectangle (display, window, pp->stippledGC, + pp->pacman.cf, pp->pacman.rf, + pp->spritexs, pp->spriteys); + pp->pacman.mouthstage += pp->pacman.mouthdirection; + if ((pp->pacman.mouthstage >= MAXMOUTH) || (pp->pacman.mouthstage < 0)) { + pp->pacman.mouthdirection *= -1; + pp->pacman.mouthstage += pp->pacman.mouthdirection * 2; + } + pp->pacman.oldcf = pp->pacman.cf; + pp->pacman.oldrf = pp->pacman.rf; } /* Draws a ghost sprite, removing the previous sprite and restores the level. */ static void -draw_ghost_sprite(ModeInfo * mi, const unsigned ghost) { - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; - - pp->ghosts[ghost].cf = - pp->ghosts[ghost].col * pp->xs + pp->ghosts[ghost].delta.x * - pp->ghosts[ghost].cfactor + pp->xb + pp->spritedx; - pp->ghosts[ghost].rf = - pp->ghosts[ghost].row * pp->ys + pp->ghosts[ghost].delta.y * - pp->ghosts[ghost].rfactor + pp->yb + pp->spritedy; - - XSetForeground(display, - pp->stippledGC, - MI_BLACK_PIXEL(mi)); - XFillRectangle(display, - window, - pp->stippledGC, - pp->ghosts[ghost].cf, - pp->ghosts[ghost].rf, - pp->spritexs, pp->spriteys); - - if (pp->ghosts[ghost].oldcf != NOWHERE || - pp->ghosts[ghost].oldrf != NOWHERE) { +draw_ghost_sprite (ModeInfo * mi, const unsigned ghost) +{ + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + + pp->ghosts[ghost].cf = + pp->ghosts[ghost].col * pp->xs + pp->ghosts[ghost].delta.x * + pp->ghosts[ghost].cfactor + pp->xb + pp->spritedx; + pp->ghosts[ghost].rf = + pp->ghosts[ghost].row * pp->ys + pp->ghosts[ghost].delta.y * + pp->ghosts[ghost].rfactor + pp->yb + pp->spritedy; + + XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi)); + XFillRectangle (display, + window, + pp->stippledGC, + pp->ghosts[ghost].cf, + pp->ghosts[ghost].rf, pp->spritexs, pp->spriteys); + + if (pp->ghosts[ghost].oldcf != NOWHERE || + pp->ghosts[ghost].oldrf != NOWHERE) { #ifdef FLASH - XFillRectangle(display, window, - pp->stippledGC, pp->ghosts[ghost].oldcf, - pp->ghosts[ghost].oldrf, - pp->spritexs, pp->spriteys); + XFillRectangle (display, window, + pp->stippledGC, pp->ghosts[ghost].oldcf, + pp->ghosts[ghost].oldrf, pp->spritexs, pp->spriteys); #else - ERASE_IMAGE(display, window, pp->stippledGC, - pp->ghosts[ghost].cf, pp->ghosts[ghost].rf, - pp->ghosts[ghost].oldcf, pp->ghosts[ghost].oldrf, - pp->spritexs, pp->spriteys); + ERASE_IMAGE (display, window, pp->stippledGC, + pp->ghosts[ghost].cf, pp->ghosts[ghost].rf, + pp->ghosts[ghost].oldcf, pp->ghosts[ghost].oldrf, + pp->spritexs, pp->spriteys); #endif - } + } - drawlevelblock(mi, pp, - (unsigned int)pp->ghosts[ghost].col, - (unsigned int)pp->ghosts[ghost].row); + drawlevelblock (mi, pp, + (unsigned int) pp->ghosts[ghost].col, + (unsigned int) pp->ghosts[ghost].row); - XSetTSOrigin(display, pp->stippledGC, - pp->ghosts[ghost].cf, pp->ghosts[ghost].rf); + XSetTSOrigin (display, pp->stippledGC, + pp->ghosts[ghost].cf, pp->ghosts[ghost].rf); - if (MI_NPIXELS(mi) > 2) - XSetForeground(display, - pp->stippledGC, - MI_PIXEL(mi, GREEN)); - else - XSetForeground(display, - pp->stippledGC, - MI_WHITE_PIXEL(mi)); + if (MI_NPIXELS (mi) > 2) + XSetForeground (display, pp->stippledGC, MI_PIXEL (mi, GREEN)); + else + XSetForeground (display, pp->stippledGC, MI_WHITE_PIXEL (mi)); - XSetStipple(display, pp->stippledGC, - pp->ghostPixmap[0][0][0]); + XSetStipple (display, pp->stippledGC, pp->ghostPixmap[0][0][0]); #ifdef FLASH - XSetFillStyle(display, - pp->stippledGC, - FillStippled); + XSetFillStyle (display, pp->stippledGC, FillStippled); #else - XSetFillStyle(display, - pp->stippledGC, - FillOpaqueStippled); + XSetFillStyle (display, pp->stippledGC, FillOpaqueStippled); #endif - if (pp->xs < 2 || pp->ys < 2) - XDrawPoint(display, window, pp->stippledGC, - pp->ghosts[ghost].cf, - pp->ghosts[ghost].rf); - else - XFillRectangle(display, - window, - pp->stippledGC, - pp->ghosts[ghost].cf, - pp->ghosts[ghost].rf, - pp->spritexs, pp->spriteys); - - pp->ghosts[ghost].oldcf = pp->ghosts[ghost].cf; - pp->ghosts[ghost].oldrf = pp->ghosts[ghost].rf; + if (pp->xs < 2 || pp->ys < 2) + XDrawPoint (display, window, pp->stippledGC, + pp->ghosts[ghost].cf, pp->ghosts[ghost].rf); + else + XFillRectangle (display, + window, + pp->stippledGC, + pp->ghosts[ghost].cf, + pp->ghosts[ghost].rf, pp->spritexs, pp->spriteys); + + pp->ghosts[ghost].oldcf = pp->ghosts[ghost].cf; + pp->ghosts[ghost].oldrf = pp->ghosts[ghost].rf; } #endif /* USE_PIXMAP */ -/* Does all drawing of moving sprites in the level. */ +static int +ghost_over (ModeInfo * mi, int x, int y) +{ + int ghost = 0; + int ret = False; + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + dot_rc_to_pixel (mi, &x, &y); + for (ghost = 0; ghost < pp->nghosts; ghost++) { + if ((pp->ghosts[ghost].cf <= x + && x <= pp->ghosts[ghost].cf + pp->spritexs) + && (pp->ghosts[ghost].rf <= y + && y <= pp->ghosts[ghost].rf + pp->spriteys)) { + ret = True; + break; + } + } + return ret; +} + + +static void +flash_bonus_dots (ModeInfo * mi) +{ +#define MAX_FLASH_COUNT 25 + static int flash_count = 0; + static int on = 0; + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + int i, x, y; + for (i = 0; i < NUM_BONUS_DOTS; i++) { + if (!bonus_dot_eaten (i)) { + bonus_dot_pos (i, &x, &y); + if (ghost_over (mi, x, y)) + continue; + if (on) + draw_bonus_dot (mi, pp, x, y); + else + clear_bonus_dot (mi, pp, x, y); + } + } + if (flash_count-- == 0) { + flash_count = MAX_FLASH_COUNT; + on = !on; + } +} + +static unsigned int +ate_bonus_dot (ModeInfo * mi) +{ + /*Check pacman's position. If it is over a bonus dot and that dot + *has not been eaten, then return true + */ + unsigned int ret = 0; + int idx = 0; + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + if (is_bonus_dot (pp->pacman.col, pp->pacman.row, &idx)) { + ret = !bonus_dot_eaten (idx); + eat_bonus_dot (idx); + } + return ret; +} + static void -pacman_tick(ModeInfo * mi) +ghost_scared (ModeInfo * mi) { - Display *display = MI_DISPLAY(mi); - pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)]; - unsigned int ghost; + unsigned int ghost; + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + for (ghost = 0; ghost < pp->nghosts; ghost++) { + if (pp->ghosts[ghost].aistate == goingin || + pp->ghosts[ghost].aistate == goingout || + pp->ghosts[ghost].aistate == inbox ) continue; + pp->ghosts[ghost].aistate = hiding; + pp->ghosts[ghost].flash_scared = 0; + if (pp->pacman.aistate != ps_dieing) + pp->pacman.aistate = ps_chasing; + } +} - for (ghost = 0; ghost < pp->nghosts; ghost++) { - if (pp->ghosts[ghost].dead == True) - continue; - draw_ghost_sprite(mi, ghost); - } +static void +ghost_not_scared (ModeInfo * mi) +{ + unsigned int ghost; + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + for (ghost = 0; ghost < pp->nghosts; ghost++){ + if (pp->ghosts[ghost].aistate == goingin || + pp->ghosts[ghost].aistate == goingout || + pp->ghosts[ghost].aistate == inbox ) continue; + pp->ghosts[ghost].aistate = chasing; + } + if (pp->pacman.aistate != ps_dieing) + pp->pacman.aistate = ps_eating; + +} - draw_pacman_sprite(mi); +static void +ghost_flash_scared (ModeInfo * mi) +{ + unsigned int ghost; + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + for (ghost = 0; ghost < pp->nghosts; ghost++) + pp->ghosts[ghost].flash_scared = !pp->ghosts[ghost].flash_scared; +} - (void)XFlush(display); +/* Does all drawing of moving sprites in the level. */ +static void +pacman_tick (ModeInfo * mi) +{ +#define DEFAULT_SCARED_TIME 500 +#define START_FLASH 200 +#define FLASH_COUNT 25 + + Display *display = MI_DISPLAY (mi); + pacmangamestruct *pp = &pacmangames[MI_SCREEN (mi)]; + unsigned int ghost; + static int ghost_scared_timer = 0; + static int flash_timer = 0; + static PacmanState old_pac_state = chasing; +#if 0 + draw_grid (mi); +#endif + for (ghost = 0; ghost < pp->nghosts; ghost++) { + draw_ghost_sprite (mi, ghost); +#if 0 + print_ghost_stats (mi, &(pp->ghosts[ghost]), ghost); +#endif + } +#if 0 + print_pac_stats (mi, &(pp->pacman)); +#endif + draw_pacman_sprite (mi); + flash_bonus_dots (mi); + if (ate_bonus_dot (mi)) { + ghost_scared_timer = (random () % 100) + DEFAULT_SCARED_TIME; + ghost_scared (mi); + } + + if (ghost_scared_timer > 0) { + if (--ghost_scared_timer == 0) + ghost_not_scared (mi); + else if (ghost_scared_timer <= START_FLASH) { + if (flash_timer <= 0) { + flash_timer = FLASH_COUNT; + ghost_flash_scared (mi); + } + flash_timer--; + } + } + + /* + We don't want to miss the last death sequence. So if pacman has died three times + we wait for his state to change from dieing to something else before we repopulate + the level. If pacman ate all of the dots then we just repopulate. + */ + + if (pp->dotsleft == 0 ) + repopulate (mi); + else if (pp->pacman.deaths >= 3){ + if (old_pac_state == ps_dieing && pp->pacman.aistate != ps_dieing) + repopulate (mi); + } + + old_pac_state = pp->pacman.aistate; + + (void) XFlush (display); } + + +/* CODE TO LOAD AND SCALE THE PIXMAPS + */ #if defined(USE_PIXMAP) /* Grabbed the scaling routine off of usenet. @@ -756,453 +1287,555 @@ pacman_tick(ModeInfo * mi) * -jeremy */ -static Pixmap -scale_pixmap( Display **dpy, GC gc, Pixmap source, int dwidth, int dheight) +static Pixmap +scale_pixmap (Display ** dpy, GC gc, Pixmap source, int dwidth, int dheight) { - Pixmap temp,dest; - int j,end; - float i; - float xscale, yscale; - unsigned int swidth, sheight; - Window window; - int x, y; - unsigned border_width_return, depth; - XGetGeometry(*dpy, source, &window, &x, &y, &swidth, &sheight, &border_width_return, &depth); - - xscale = (float) swidth / (float) dwidth; /* Scaling factors */ - yscale = (float) sheight / (float) dheight; - - dest = XCreatePixmap(*dpy,window,dwidth,dheight,depth); - if (!dest){ - fprintf(stderr, "%s Could not scale image", progname); - } - temp = XCreatePixmap(*dpy,window,dwidth,sheight,depth); - if (!temp){ - fprintf(stderr, "%s Could not scale image", progname); - } - - j = 0; - end = dwidth*xscale; - /* Scale width of source into temp pixmap */ - for(i=0;ispritexs; - int h = pp->spriteys; - GC gc = 0; - Pixmap temp; - - for (i = 0; i < 4; i++){ - m = 0; - for ( j = 0; j < MAXGDIR; j++){ - for ( k = 0; k < MAXGWAG; k++){ - bits[m][2] = colors[i]; - pp->ghostPixmap[i][j][k] = xpm_data_to_pixmap (display, window, bits[m], - &w, &h, &pp->ghostMask); - - if (!pp->ghostPixmap[i][j][k]) pacman_fail("Cannot load ghost images"); - - pp->ghostPixmap[i][j][k] = scale_pixmap(&display, pp->stippledGC, - pp->ghostPixmap[i][j][k], pp->spritexs, pp->spriteys); - - if (!pp->ghostPixmap[i][j][k]) pacman_fail("Cannot scale ghost images"); - m++; - } - } - } - /* We really only need a single mask. This saves the headache of getting the bottom of the ghost - * to clip just right. What we'll do is mask the top portion of the ghost, but the bottom of the - * the ghost will be solid. I did this by setting the pixels between the fringe of their sheets - * to black instead of none. -jeremy - */ - temp = xpm_data_to_pixmap (display, window, ghost_mask_xpm, - &w, &h, &pp->ghostMask); - - if (!temp) pacman_fail("Cannot load temporary ghost image"); - - temp = scale_pixmap(&display, pp->stippledGC, - temp, pp->spritexs, pp->spriteys); - - if (!temp) pacman_fail("Cannot scale temporary ghost image"); - - gc = XCreateGC(display, pp->ghostMask, 0, 0); - - pp->ghostMask = scale_pixmap(&display, gc, pp->ghostMask, - pp->spritexs, pp->spriteys); - XFreePixmap(display, temp); + pacmangamestruct *pp = *ps; + Display *display = *dpy; + static char *colors[] = { + ". c #FF0000", /*Red */ + ". c #00FFDE", /*Blue */ + ". c #FFB847", /*Orange */ + ". c #FFB8DE", /*Pink */ + }; + + static char **bits[] = { + ghost_u1_xpm, ghost_u2_xpm, ghost_r1_xpm, ghost_r2_xpm, + ghost_d1_xpm, ghost_d2_xpm, ghost_l1_xpm, ghost_l2_xpm + }; + static char **s_bits[] = { + ghost_s1_xpm, ghost_s2_xpm, + ghost_sf1_xpm, ghost_sf2_xpm + }; + static char **e_bits[] = { + eyes_u_xpm, eyes_r_xpm, eyes_d_xpm, eyes_l_xpm + }; + + int i, j, k, m; + int w = pp->spritexs; + int h = pp->spriteys; + GC gc = 0; + Pixmap temp; + + for (i = 0; i < 4; i++) { + m = 0; + for (j = 0; j < MAXGDIR; j++) { + for (k = 0; k < MAXGWAG; k++) { + bits[m][2] = colors[i]; + pp->ghostPixmap[i][j][k] = + xpm_data_to_pixmap (display, window, bits[m], &w, &h, + &pp->ghostMask); + + if (!pp->ghostPixmap[i][j][k]) + pacman_fail ("Cannot load ghost images"); + + pp->ghostPixmap[i][j][k] = + scale_pixmap (&display, pp->stippledGC, + pp->ghostPixmap[i][j][k], pp->spritexs, + pp->spriteys); + + if (!pp->ghostPixmap[i][j][k]) + pacman_fail ("Cannot scale ghost images"); + m++; + } + } + } + /* load the scared ghost */ + m = 0; + for (i = 0; i < MAXGFLASH; i++) { + for (j = 0; j < MAXGWAG; j++) { + pp->s_ghostPixmap[i][j] = + xpm_data_to_pixmap (display, window, s_bits[m++], &w, &h, + &pp->ghostMask); + + if (!pp->s_ghostPixmap[i][j]) + pacman_fail ("Cannot Scare Ghost images"); + pp->s_ghostPixmap[i][j] = scale_pixmap (&display, pp->stippledGC, + pp->s_ghostPixmap[i][j], + pp->spritexs, + pp->spriteys); + + if (!pp->s_ghostPixmap[i][j]) + pacman_fail ("Cannot scale Scared Ghost images"); + } + } + /* load the ghost eyes */ + for (i = 0; i < MAXGDIR; i++) { + pp->ghostEyes[i] = + xpm_data_to_pixmap (display, window, e_bits[i], &w, &h, + &pp->ghostMask); + + if (!pp->ghostEyes[i]) + pacman_fail ("Cannot open ghost eye images"); + + pp->ghostEyes[i] = scale_pixmap (&display, pp->stippledGC, + pp->ghostEyes[i], + pp->spritexs, + pp->spriteys); + + if (!pp->ghostEyes[i]) + pacman_fail ("Cannot open ghost eye images"); + } + + + + /* We really only need a single mask. This saves the headache of getting the + * bottom of the ghost to clip just right. What we'll do is mask + * the top portion of the ghost, but the bottom of the ghost will be solid. + * I did this by setting the pixels between the fringe of their sheets + * to black instead of none. -jeremy + */ + temp = xpm_data_to_pixmap (display, window, ghost_mask_xpm, + &w, &h, &pp->ghostMask); + + if (!temp) + pacman_fail ("Cannot load temporary ghost image"); + + temp = scale_pixmap (&display, pp->stippledGC, + temp, pp->spritexs, pp->spriteys); + + if (!temp) + pacman_fail ("Cannot scale temporary ghost image"); + + gc = XCreateGC (display, pp->ghostMask, 0, 0); + + pp->ghostMask = scale_pixmap (&display, gc, pp->ghostMask, + pp->spritexs, pp->spriteys); + XFreePixmap (display, temp); } /* Load the pacman pixmaps and their mask. */ static void -load_pacman_pixmaps(Display **dpy, Window window, pacmangamestruct **ps) +load_pacman_pixmaps (Display ** dpy, Window window, pacmangamestruct ** ps) { - pacmangamestruct *pp = *ps; - Display *display = *dpy; - - static char **bits[] = { - pacman_0_xpm, pacman_u1_xpm, pacman_u2_xpm, - pacman_0_xpm, pacman_r1_xpm, pacman_r2_xpm, - pacman_0_xpm, pacman_d1_xpm, pacman_d2_xpm, - pacman_0_xpm, pacman_l1_xpm, pacman_l2_xpm - }; - int i, j, m; - int w = pp->spritexs; - int h = pp->spriteys; - GC gc = 0; - - m = 0; - for (i = 0; i < 4; i++){ - for ( j = 0; j < MAXMOUTH; j++){ - pp->pacmanPixmap[i][j] = xpm_data_to_pixmap (display, window, bits[m++], - &w, &h, &pp->pacmanMask[i][j]); - - if (!pp->pacmanPixmap[i][j]) pacman_fail("Cannot load pacman pixmap."); - - pp->pacmanPixmap[i][j] = scale_pixmap(&display, pp->stippledGC, - pp->pacmanPixmap[i][j], pp->spritexs, pp->spriteys); - - if (!pp->pacmanPixmap[i][j]) pacman_fail("Cannot scale pacman pixmap."); - - if (!gc) - gc = XCreateGC(display, pp->pacmanMask[i][j], 0, 0); - - pp->pacmanMask[i][j] = scale_pixmap(&display, gc, pp->pacmanMask[i][j], - pp->spritexs, pp->spriteys); - } - } + pacmangamestruct *pp = *ps; + Display *display = *dpy; + + static char **bits[] = { + pacman_0_xpm, pacman_u1_xpm, pacman_u2_xpm, + pacman_0_xpm, pacman_r1_xpm, pacman_r2_xpm, + pacman_0_xpm, pacman_d1_xpm, pacman_d2_xpm, + pacman_0_xpm, pacman_l1_xpm, pacman_l2_xpm + }; + + static char **ds_bits[] = { + pacman_ds1_xpm, pacman_ds2_xpm, pacman_ds3_xpm, pacman_ds4_xpm, + pacman_ds5_xpm, pacman_ds6_xpm, pacman_ds7_xpm, pacman_ds8_xpm + }; + + int i, j, m; + int w = pp->spritexs; + int h = pp->spriteys; + GC gc = 0; + + m = 0; + for (i = 0; i < 4; i++) { + for (j = 0; j < MAXMOUTH; j++) { + pp->pacmanPixmap[i][j] = + xpm_data_to_pixmap (display, window, bits[m++], &w, &h, + &pp->pacmanMask[i][j]); + + if (!pp->pacmanPixmap[i][j]) + pacman_fail ("Cannot load pacman pixmap."); + + pp->pacmanPixmap[i][j] = scale_pixmap (&display, pp->stippledGC, + pp->pacmanPixmap[i][j], + pp->spritexs, + pp->spriteys); + + if (!pp->pacmanPixmap[i][j]) + pacman_fail ("Cannot scale pacman pixmap."); + + if (!gc) + gc = XCreateGC (display, pp->pacmanMask[i][j], 0, 0); + + pp->pacmanMask[i][j] = + scale_pixmap (&display, gc, pp->pacmanMask[i][j], + pp->spritexs, pp->spriteys); + } + } + + /* Load pacman death sequence */ + for ( i = 0; i < PAC_DEATH_FRAMES; i++ ){ + pp->pacman_ds[i] = + xpm_data_to_pixmap (display, window, ds_bits[i], &w, &h, + &pp->pacman_ds_mask[i]); + + if (!pp->pacman_ds[i]) + pacman_fail ("Cannot load pacman death frame."); + + pp->pacman_ds[i] = scale_pixmap ( &display, pp->stippledGC, + pp->pacman_ds[i], + pp->spritexs, + pp->spriteys); + + if (!pp->pacman_ds[i]) + pacman_fail ("Cannot scale pixmap."); + + if (!gc) + gc = XCreateGC (display, pp->pacman_ds_mask[i], 0, 0); + + pp->pacman_ds_mask[i] = + scale_pixmap (&display, gc, pp->pacman_ds_mask[i], + pp->spritexs, pp->spriteys); + } + } #endif /* USE_PIXMAP */ /* Hook function, sets state to initial position. */ void -init_pacman(ModeInfo * mi) +init_pacman (ModeInfo * mi) { - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - int size = MI_SIZE(mi); - pacmangamestruct *pp; - XGCValues gcv; - int i, j, k; + Display *display = MI_DISPLAY (mi); + Window window = MI_WINDOW (mi); + int size = MI_SIZE (mi); + pacmangamestruct *pp; + XGCValues gcv; + int i, j, k; #if (! defined( USE_PIXMAP )) - GC fg_gc, bg_gc; - XPoint points[9]; - int dir, mouth; + GC fg_gc, bg_gc; + XPoint points[9]; + int dir, mouth; #endif - if (pacmangames == NULL) { - if ((pacmangames = (pacmangamestruct *) - calloc((size_t)MI_NUM_SCREENS(mi), - sizeof (pacmangamestruct))) == NULL) - return; - } - pp = &pacmangames[MI_SCREEN(mi)]; - - pp->width = (unsigned short)MI_WIDTH(mi); - pp->height = (unsigned short)MI_HEIGHT(mi); - for (i = 0; i < 4; i++){ - for (j = 0; j < MAXGDIR; j++){ - for (k = 0; k < MAXGWAG; k++){ - if (pp->ghostPixmap[i][j][k] != None) { - XFreePixmap(display, pp->ghostPixmap[i][j][k]); - pp->ghostPixmap[i][j][k] = None; - pp->graphics_format = 0 /*IS_NONE*/; - } - } - } - } - if (size == 0 || - MINGRIDSIZE * size > (int)pp->width || - MINGRIDSIZE * size > (int)pp->height) { - - pp->ys = pp->xs = MAX(MIN(pp->width/LEVWIDTH, - pp->height/LEVHEIGHT), 1); - } else { - if (size < -MINSIZE) - pp->ys = (short)(NRAND( MIN( -size, MAX( MINSIZE, - MIN( pp->width, pp->height) / MINGRIDSIZE)) - - MINSIZE + 1) + MINSIZE); - else if (size < MINSIZE) - pp->ys = MINSIZE; - else - pp->ys = (short)(MIN(size, - MAX(MINSIZE, MIN(pp->width, pp->height) / - MINGRIDSIZE))); - pp->xs = pp->ys; - } - - pp->wallwidth = (unsigned int)(pp->xs + pp->ys) >> 4; - if (pp->wallwidth < 1) pp->wallwidth = 1; - pp->incx = (pp->xs >> 3) + 1; - pp->incy = (pp->ys >> 3) + 1; - pp->ncols = (unsigned short)MAX(LEVWIDTH, 2); - pp->nrows = (unsigned short)MAX(LEVHEIGHT, 2); - pp->xb = (pp->width - pp->ncols * pp->xs) >> 1; - pp->yb = (pp->height - pp->nrows * pp->ys) >> 1; - pp->spritexs = MAX(pp->xs + (pp->xs >> 1) - 1, 1); - pp->spriteys = MAX(pp->ys + (pp->ys >> 1) - 1, 1); - pp->spritedx = (pp->xs - pp->spritexs) >> 1; - pp->spritedy = (pp->ys - pp->spriteys) >> 1; - - if (!pp->stippledGC) { - gcv.foreground = MI_BLACK_PIXEL(mi); - gcv.background = MI_BLACK_PIXEL(mi); - if ((pp->stippledGC = XCreateGC(display, window, - GCForeground | GCBackground, &gcv)) == None) { - free_pacman(display, pp); - return; - } - } + if (pacmangames == NULL) { + if ((pacmangames = (pacmangamestruct *) + calloc ((size_t) MI_NUM_SCREENS (mi), + sizeof (pacmangamestruct))) == NULL) + return; + } + pp = &pacmangames[MI_SCREEN (mi)]; + + pp->width = (unsigned short) MI_WIDTH (mi); + pp->height = (unsigned short) MI_HEIGHT (mi); + for (i = 0; i < 4; i++) { + for (j = 0; j < MAXGDIR; j++) { + for (k = 0; k < MAXGWAG; k++) { + if (pp->ghostPixmap[i][j][k] != None) { + XFreePixmap (display, pp->ghostPixmap[i][j][k]); + pp->ghostPixmap[i][j][k] = None; + pp->graphics_format = 0 /*IS_NONE */ ; + } + } + } + } + + for (i = 0; i < MAXGFLASH; i++) { + for (j = 0; j < MAXGWAG; j++) { + if (pp->s_ghostPixmap[i][j] != None) { + XFreePixmap (display, pp->s_ghostPixmap[i][j]); + pp->s_ghostPixmap[i][j] = None; + } + } + } + + if (size == 0 || + MINGRIDSIZE * size > (int) pp->width || + MINGRIDSIZE * size > (int) pp->height) { + + pp->ys = pp->xs = MAX (MIN (pp->width / LEVWIDTH, + pp->height / LEVHEIGHT), 1); + } + else { + if (size < -MINSIZE) + pp->ys = (short) (NRAND (MIN (-size, MAX (MINSIZE, + MIN (pp->width, + pp->height) / + MINGRIDSIZE)) + - MINSIZE + 1) + MINSIZE); + else if (size < MINSIZE) + pp->ys = MINSIZE; + else + pp->ys = (short) (MIN (size, + MAX (MINSIZE, MIN (pp->width, pp->height) / + MINGRIDSIZE))); + pp->xs = pp->ys; + } + + pp->wallwidth = (unsigned int) (pp->xs + pp->ys) >> 4; + if (pp->wallwidth < 1) + pp->wallwidth = 1; + pp->incx = (pp->xs >> 3) + 1; + pp->incy = (pp->ys >> 3) + 1; + pp->ncols = (unsigned short) MAX (LEVWIDTH, 2); + pp->nrows = (unsigned short) MAX (LEVHEIGHT, 2); + pp->xb = (pp->width - pp->ncols * pp->xs) >> 1; + pp->yb = (pp->height - pp->nrows * pp->ys) >> 1; + pp->spritexs = MAX (pp->xs + (pp->xs >> 1) - 1, 1); + pp->spriteys = MAX (pp->ys + (pp->ys >> 1) - 1, 1); + pp->spritedx = (pp->xs - pp->spritexs) >> 1; + pp->spritedy = (pp->ys - pp->spriteys) >> 1; + + if (!pp->stippledGC) { + gcv.foreground = MI_BLACK_PIXEL (mi); + gcv.background = MI_BLACK_PIXEL (mi); + if ((pp->stippledGC = XCreateGC (display, window, + GCForeground | GCBackground, + &gcv)) == None) { + free_pacman (display, pp); + return; + } + } #if defined(USE_PIXMAP) - load_ghost_pixmaps(&display,window,&pp); - load_pacman_pixmaps(&display,window,&pp); + load_ghost_pixmaps (&display, window, &pp); + load_pacman_pixmaps (&display, window, &pp); #else - if ((pp->ghostPixmap[0][0][0] = XCreatePixmap(display, window, - pp->spritexs, pp->spriteys, 1)) == None) { - free_pacman(display, pp); - return; - } - - gcv.foreground = 0; - gcv.background = 1; - if ((bg_gc = XCreateGC(display, pp->ghostPixmap[0][0][0], - GCForeground | GCBackground, &gcv)) == None) { - free_pacman(display, pp); - return; - } - - gcv.foreground = 1; - gcv.background = 0; - if ((fg_gc = XCreateGC(display, pp->ghostPixmap[0][0][0], - GCForeground | GCBackground, &gcv)) == None) { - XFreeGC(display, bg_gc); - free_pacman(display, pp); - return; - } + if ((pp->ghostPixmap[0][0][0] = XCreatePixmap (display, window, + pp->spritexs, pp->spriteys, + 1)) == None) { + free_pacman (display, pp); + return; + } + + gcv.foreground = 0; + gcv.background = 1; + if ((bg_gc = XCreateGC (display, pp->ghostPixmap[0][0][0], + GCForeground | GCBackground, &gcv)) == None) { + free_pacman (display, pp); + return; + } + + gcv.foreground = 1; + gcv.background = 0; + if ((fg_gc = XCreateGC (display, pp->ghostPixmap[0][0][0], + GCForeground | GCBackground, &gcv)) == None) { + XFreeGC (display, bg_gc); + free_pacman (display, pp); + return; + } #define SETPOINT(p, xp, yp) p.x = xp; p.y = yp - /* draw the triangles on the bottom (scalable) */ - SETPOINT(points[0], 1, pp->spriteys * 5 / 6); - SETPOINT(points[1], pp->spritexs / 6, pp->spriteys); - SETPOINT(points[2], pp->spritexs / 3, pp->spriteys * 5 / 6); - SETPOINT(points[3], pp->spritexs / 2, pp->spriteys); - SETPOINT(points[4], pp->spritexs * 2 / 3, pp->spriteys * 5 / 6); - SETPOINT(points[5], pp->spritexs * 5 / 6, pp->spriteys); - SETPOINT(points[6], pp->spritexs, pp->spriteys * 5 / 6); - SETPOINT(points[7], pp->spritexs, pp->spriteys / 2); - SETPOINT(points[8], 1, pp->spriteys / 2); - - XFillRectangle(display, pp->ghostPixmap[0][0][0], bg_gc, - 0, 0, pp->spritexs, pp->spriteys); - XFillArc(display, pp->ghostPixmap[0][0][0], fg_gc, - 0, 0, pp->spritexs, pp->spriteys, 0, 11520); - XFillPolygon(display, pp->ghostPixmap[0][0][0], fg_gc, - points, 9, Nonconvex, CoordModeOrigin); - XFreeGC(display, bg_gc); - XFreeGC(display, fg_gc); - - - if (pp->pacmanPixmap[0][0] != None) - for (dir = 0; dir < 4; dir++) - for (mouth = 0; mouth < MAXMOUTH; mouth++) - XFreePixmap(display, - pp->pacmanPixmap[dir] - [mouth]); - - for (dir = 0; dir < 4; dir++) - for (mouth = 0; mouth < MAXMOUTH; mouth++) { - if ((pp->pacmanPixmap[dir][mouth] = XCreatePixmap( - display, MI_WINDOW(mi), - pp->spritexs, pp->spriteys, 1)) == - None) { - free_pacman(display, pp); - return; - } - gcv.foreground = 1; - gcv.background = 0; - if ((fg_gc = XCreateGC(display, pp->pacmanPixmap[dir][mouth], - GCForeground | GCBackground, &gcv)) == None) { - free_pacman(display, pp); - return; - } - gcv.foreground = 0; - gcv.background = 0; - if ((bg_gc = XCreateGC(display, - pp->pacmanPixmap[dir][mouth], - GCForeground | - GCBackground, &gcv)) == - None) { - XFreeGC(display, fg_gc); - free_pacman(display, pp); - return; - } - XFillRectangle(display, - pp->pacmanPixmap[dir][mouth], bg_gc, - 0, 0, pp->spritexs, pp->spriteys); - if (pp->spritexs == 1 && pp->spriteys == 1) - XFillRectangle(display, - pp->pacmanPixmap[dir][mouth], - fg_gc, 0, 0, pp->spritexs, - pp->spriteys); - else - XFillArc(display, - pp->pacmanPixmap[dir][mouth], - fg_gc, - 0, 0, pp->spritexs, pp->spriteys, - ((90 - dir * 90) + mouth * 5) * 64, - (360 + (-2 * mouth * 5)) * 64); - XFreeGC(display, fg_gc); - XFreeGC(display, bg_gc); - } + /* draw the triangles on the bottom (scalable) */ + SETPOINT (points[0], 1, pp->spriteys * 5 / 6); + SETPOINT (points[1], pp->spritexs / 6, pp->spriteys); + SETPOINT (points[2], pp->spritexs / 3, pp->spriteys * 5 / 6); + SETPOINT (points[3], pp->spritexs / 2, pp->spriteys); + SETPOINT (points[4], pp->spritexs * 2 / 3, pp->spriteys * 5 / 6); + SETPOINT (points[5], pp->spritexs * 5 / 6, pp->spriteys); + SETPOINT (points[6], pp->spritexs, pp->spriteys * 5 / 6); + SETPOINT (points[7], pp->spritexs, pp->spriteys / 2); + SETPOINT (points[8], 1, pp->spriteys / 2); + + XFillRectangle (display, pp->ghostPixmap[0][0][0], bg_gc, + 0, 0, pp->spritexs, pp->spriteys); + XFillArc (display, pp->ghostPixmap[0][0][0], fg_gc, + 0, 0, pp->spritexs, pp->spriteys, 0, 11520); + XFillPolygon (display, pp->ghostPixmap[0][0][0], fg_gc, + points, 9, Nonconvex, CoordModeOrigin); + XFreeGC (display, bg_gc); + XFreeGC (display, fg_gc); + + + if (pp->pacmanPixmap[0][0] != None) + for (dir = 0; dir < 4; dir++) + for (mouth = 0; mouth < MAXMOUTH; mouth++) + XFreePixmap (display, pp->pacmanPixmap[dir] + [mouth]); + + for (dir = 0; dir < 4; dir++) + for (mouth = 0; mouth < MAXMOUTH; mouth++) { + if ((pp->pacmanPixmap[dir][mouth] = + XCreatePixmap (display, MI_WINDOW (mi), pp->spritexs, + pp->spriteys, 1)) == None) { + free_pacman (display, pp); + return; + } + gcv.foreground = 1; + gcv.background = 0; + if ((fg_gc = XCreateGC (display, pp->pacmanPixmap[dir][mouth], + GCForeground | GCBackground, + &gcv)) == None) { + free_pacman (display, pp); + return; + } + gcv.foreground = 0; + gcv.background = 0; + if ((bg_gc = XCreateGC (display, + pp->pacmanPixmap[dir][mouth], + GCForeground | + GCBackground, &gcv)) == None) { + XFreeGC (display, fg_gc); + free_pacman (display, pp); + return; + } + XFillRectangle (display, + pp->pacmanPixmap[dir][mouth], bg_gc, + 0, 0, pp->spritexs, pp->spriteys); + if (pp->spritexs == 1 && pp->spriteys == 1) + XFillRectangle (display, + pp->pacmanPixmap[dir][mouth], + fg_gc, 0, 0, pp->spritexs, pp->spriteys); + else + XFillArc (display, + pp->pacmanPixmap[dir][mouth], + fg_gc, + 0, 0, pp->spritexs, pp->spriteys, + ((90 - dir * 90) + mouth * 5) * 64, + (360 + (-2 * mouth * 5)) * 64); + XFreeGC (display, fg_gc); + XFreeGC (display, bg_gc); + } #endif /* USE_PIXMAP */ - pp->pacman.lastbox = START; - pp->pacman.mouthdirection = 1; - pp->pacman.nextcol = NOWHERE; - pp->pacman.nextrow = NOWHERE; - - if (pp->ghosts != NULL) { - free(pp->ghosts); - pp->ghosts = (ghoststruct *) NULL; - } - pp->nghosts = GHOSTS; - - if (!pp->ghosts) - if ((pp->ghosts = (ghoststruct *) calloc((size_t)pp->nghosts, - sizeof (ghoststruct))) == NULL) { - free_pacman(display, pp); - return; - } - - pp->pacman.mouthstage = MAXMOUTH - 1; - - MI_CLEARWINDOW(mi); - repopulate(mi); + pp->pacman.lastbox = START; + pp->pacman.mouthdirection = 1; + pp->pacman.nextcol = NOWHERE; + pp->pacman.nextrow = NOWHERE; + + if (pp->ghosts != NULL) { + free (pp->ghosts); + pp->ghosts = (ghoststruct *) NULL; + } + pp->nghosts = GHOSTS; + + if (!pp->ghosts) + if ((pp->ghosts = (ghoststruct *) calloc ((size_t) pp->nghosts, + sizeof (ghoststruct))) == + NULL) { + free_pacman (display, pp); + return; + } + + pp->pacman.mouthstage = MAXMOUTH - 1; + + MI_CLEARWINDOW (mi); + repopulate (mi); } /* Callback function called for each tick. This is the complete machinery of everything that moves. */ void -draw_pacman(ModeInfo * mi) +draw_pacman (ModeInfo * mi) { - unsigned int g; - pacmangamestruct *pp; - - if (pacmangames == NULL) - return; - pp = &pacmangames[MI_SCREEN(mi)]; - if (pp->ghosts == NULL) - return; - - pp->pacman.err.x = (pp->pacman.err.x + 1) % pp->pacman.speed; - pp->pacman.err.y = (pp->pacman.err.y + 1) % pp->pacman.speed; - pp->pacman.delta.x += pp->pacman.err.x != 0 ? pp->incx : 0; - pp->pacman.delta.y += pp->pacman.err.y != 0 ? pp->incy : 0; - - if (pp->pacman.delta.x >= pp->xs && pp->pacman.delta.y >= pp->ys) { - pac_update(mi, pp, &(pp->pacman)); - check_death(mi, pp); - pp->pacman.delta.x = pp->incx; - pp->pacman.delta.y = pp->incy; - } - - if (pp->pacman.delta.x > pp->xs + pp->incx) - pp->pacman.delta.x = pp->xs + pp->incx; - if (pp->pacman.delta.y > pp->ys + pp->incy) - pp->pacman.delta.y = pp->ys + pp->incy; - - for (g = 0; g < pp->nghosts; g++) { - if (pp->ghosts[g].dead == True) continue; - - pp->ghosts[g].err.x = (pp->ghosts[g].err.x + 1) % - pp->ghosts[g].speed; - pp->ghosts[g].err.y = (pp->ghosts[g].err.y + 1) % - pp->ghosts[g].speed; - pp->ghosts[g].delta.x += pp->ghosts[g].err.x != 0 ? - pp->incx : 0; - pp->ghosts[g].delta.y += pp->ghosts[g].err.y != 0 ? - pp->incy : 0; - - if (pp->ghosts[g].delta.x >= pp->xs && - pp->ghosts[g].delta.y >= pp->ys) { - ghost_update(pp, &(pp->ghosts[g])); - pp->ghosts[g].delta.x = pp->incx; - pp->ghosts[g].delta.y = pp->incy; - } - - if (pp->ghosts[g].delta.x > pp->xs + pp->incx) - pp->ghosts[g].delta.x = pp->xs + pp->incx; - if (pp->ghosts[g].delta.y > pp->ys + pp->incy) - pp->ghosts[g].delta.y = pp->ys + pp->incy; - } - - pacman_tick(mi); + unsigned int g; + pacmangamestruct *pp; + + if (pacmangames == NULL) + return; + pp = &pacmangames[MI_SCREEN (mi)]; + if (pp->ghosts == NULL) + return; + + pp->pacman.err.x = (pp->pacman.err.x + 1) % pp->pacman.speed; + pp->pacman.err.y = (pp->pacman.err.y + 1) % pp->pacman.speed; + pp->pacman.delta.x += pp->pacman.err.x != 0 ? pp->incx : 0; + pp->pacman.delta.y += pp->pacman.err.y != 0 ? pp->incy : 0; + + if (pp->pacman.delta.x >= pp->xs && pp->pacman.delta.y >= pp->ys) { + pac_update (mi, pp, &(pp->pacman)); + check_death (mi, pp); + pp->pacman.delta.x = pp->incx; + pp->pacman.delta.y = pp->incy; + } + + if (pp->pacman.delta.x > pp->xs + pp->incx) + pp->pacman.delta.x = pp->xs + pp->incx; + if (pp->pacman.delta.y > pp->ys + pp->incy) + pp->pacman.delta.y = pp->ys + pp->incy; + + for (g = 0; g < pp->nghosts; g++) { + pp->ghosts[g].err.x = (pp->ghosts[g].err.x + 1) % pp->ghosts[g].speed; + pp->ghosts[g].err.y = (pp->ghosts[g].err.y + 1) % pp->ghosts[g].speed; + pp->ghosts[g].delta.x += pp->ghosts[g].err.x != 0 ? pp->incx : 0; + pp->ghosts[g].delta.y += pp->ghosts[g].err.y != 0 ? pp->incy : 0; + + if (pp->ghosts[g].delta.x >= pp->xs && + pp->ghosts[g].delta.y >= pp->ys) { + ghost_update (pp, &(pp->ghosts[g])); + pp->ghosts[g].delta.x = pp->incx; + pp->ghosts[g].delta.y = pp->incy; + } + + if (pp->ghosts[g].delta.x > pp->xs + pp->incx) + pp->ghosts[g].delta.x = pp->xs + pp->incx; + if (pp->ghosts[g].delta.y > pp->ys + pp->incy) + pp->ghosts[g].delta.y = pp->ys + pp->incy; + } + pacman_tick (mi); } /* Releases resources. */ void -release_pacman(ModeInfo * mi) +release_pacman (ModeInfo * mi) { - if (pacmangames != NULL) { - int screen; - - for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) - free_pacman(MI_DISPLAY(mi), &pacmangames[screen]); - free(pacmangames); - pacmangames = (pacmangamestruct *) NULL; - } + if (pacmangames != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS (mi); screen++) + free_pacman (MI_DISPLAY (mi), &pacmangames[screen]); + free (pacmangames); + pacmangames = (pacmangamestruct *) NULL; + } } /* Refresh current level. */ void -refresh_pacman(ModeInfo * mi) +refresh_pacman (ModeInfo * mi) { - drawlevel(mi); - pacman_tick(mi); + drawlevel (mi); + pacman_tick (mi); } /* Callback to change level. */ void -change_pacman(ModeInfo * mi) +change_pacman (ModeInfo * mi) { - MI_CLEARWINDOW(mi); - repopulate(mi); + MI_CLEARWINDOW (mi); + repopulate (mi); } #endif /* MODE_pacman */