Rogue ソースその後
昨日のちょっとコメントがあったのもあって、今現在のソースを公開してみる。ちなみにバグありです。<こら
デバッグ中の記述やらなにやらありますが。C プログラマならわかるでしょ?@ほったらかし
#include <stdio.h> #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (1) #endif /* * Things that appear on the screens */ #define PASSAGE ('#') #define DOOR ('+') #define FLOOR ('.') #define PLAYER ('@') #define TRAP ('^') #define TRAPDOOR ('>') #define ARROWTRAP ('{') #define SLEEPTRAP ('$') #define BEARTRAP ('}') #define TELTRAP ('~') #define DARTTRAP ('`') #define SECRETDOOR ('&') #define STAIRS ('%') #define GOLD ('*') #define POTION ('!') #define SCROLL ('?') #define MAGIC ('$') #define FOOD (':') #define WEAPON (')') #define ARMOR (']') #define AMULET (',') #define RING ('=') #define STICK ('/') #define SPACE (' ') #define CALLABLE (-1) /* * Various flag bits */ #define ISDARK (0x0000001) #define ISCURSED (0x000001) #define ISBLIND (0x0000001) #define ISGONE (0x0000002) #define ISKNOW (0x0000002) #define ISRUN (0x0000004) #define ISFOUND (0x0000010) #define ISINVIS (0x0000020) #define ISMEAN (0x0000040) #define ISGREED (0x0000100) #define ISBLOCK (0x0000200) #define ISHELD (0x0000400) #define ISHUH (0x0001000) #define ISREGEN (0x0002000) #define CANHUH (0x0004000) #define CANSEE (0x0010000) #define ISMISL (0x0020000) #define ISCANC (0x0020000) #define ISMANY (0x0040000) #define ISSLOW (0x0040000) #define ISHASTE (0x0100000) /* * Maximum number of different things */ #define MAXROOMS (9) //#define MAXROOMS (32) #define MAXTHINGS (9) #define MAXOBJ (9) #define MAXPACK (23) #define MAXTRAPS (10) #define NUMTHINGS (7) /* number of types of things (scrolls, rings, etc.) */ /* * Console size */ //#define COLS (640 / 16) //#define LINES (480 / 16) #define COLS (80) #define LINES (28) //#define COLS (256) //#define LINES (80) #define move(y, x)\ {\ map_x = x;\ map_y = y;\ } // printf("map-xy %d,%d\n", map_x, map_y);\ #define cmov(xy) move((xy).y, (xy).x) #define ce(a, b) ((a).x == (b).x && (a).y == (b).y) #define getyx(stdscr, y, x)\ {\ x = map_x;\ y = map_y;\ } #define addch(c)\ {\ floor_map[map_y][map_x] = c;\ map_x++;\ } // printf("add chr-xy '%c' %d,%d\n", c, map_x, map_y);\ #define mvaddch(y, x, c)\ {\ map_x = x;\ map_y = y;\ floor_map[map_y][map_x] = c;\ map_x++;\ } // printf("add map-xy %d,%d\n", map_x, map_y);\ #define mvinch(y, x) floor_map[y][x] /* * Coordinate data type */ typedef struct{ int x; int y; }COORD; /* * Room structure */ typedef struct{ COORD r_pos; /* Upper left corner */ COORD r_max; /* Size of room */ COORD r_gold; /* Where the gold is */ int r_goldval; /* How much the gold is worth */ int r_flags; /* Info about the room */ int r_nexits; /* Number of exits */ COORD r_exit[4]; /* Where the exits are */ }ROOM; typedef struct{ int conn[MAXROOMS]; /* possible to connect to room i? */ int isconn[MAXROOMS]; /* connection been made to room i? */ int ingraph; /* this room in graph already? */ }RDES; static void do_rooms(void); static void draw_room(ROOM *rp); static void horiz(int cnt); static void vert(int cnt); static void rnd_pos(ROOM *rp, COORD *cp); static int rnd_room(void); static void do_passages(void); static void conn(int r1, int r2); static void door(ROOM *rm, COORD *cp); static void add_pass(void); static int rnd(int val); static void disp_dungeon(void); ROOM rooms[MAXROOMS]; static char floor_map[LINES][COLS + 1]; static int map_x; static int map_y; static level; static RDES rdes[MAXROOMS] = { { { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, { { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, { { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, { { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, { { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, { { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, { { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, { { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, { { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, }; int main(int argc, char *argv[]) { int i; int s; level = 1; // s = (int)time(NULL); // printf("rand %d\n", s); // s = 1222095957; // OK // s = 1222095726; // NG s = 1222097302; // NG srand(s); do_rooms(); disp_dungeon(); do_passages(); disp_dungeon(); return 0; } void do_rooms(void) { int i, j; ROOM *rp; /* struct linked_list *item;*/ /* struct thing *tp;*/ int left_out; COORD top; COORD bsze; COORD mp; /* * bsze is the maximum room size */ bsze.x = COLS / 3; bsze.y = LINES / 3; //printf("baze %2d,%2d\n", bsze.x, bsze.y); /* * Clear things for a new level */ for(rp = rooms; rp <= &rooms[MAXROOMS - 1]; rp++){ rp->r_goldval = rp->r_nexits = rp->r_flags = 0; } /* * Clear things for a floor map */ for(i = 0; i < LINES; i++){ for(j = 0; j < COLS; j++){ floor_map[i][j] = SPACE; } floor_map[i][COLS] = 0; } /* * Put the gone rooms, if any, on the level */ left_out = rnd(4); for(i = 0; i < left_out; i++){ rooms[rnd_room()].r_flags |= ISGONE; } /* * dig and populate all the rooms on the level */ for(i = 0, rp = rooms; i < MAXROOMS; rp++, i++){ /* * Find upper left corner of box that this room goes in */ top.x = (i % 3) * bsze.x + 1; top.y = (i / 3) * bsze.y; if(rp->r_flags & ISGONE){ /* * Place a gone room. Make certain that there is a blank line * for passage drawing. */ do{ rp->r_pos.x = top.x + rnd(bsze.x - 2) + 1; rp->r_pos.y = top.y + rnd(bsze.y - 2) + 1; rp->r_max.x = -COLS; rp->r_max.y = -LINES; }while(!(rp->r_pos.y > 0 && rp->r_pos.y < (LINES - 1))); //printf("roomA %+2d,%+2d %+2d,%+2d\n", rp->r_pos.x, rp->r_pos.y, rp->r_max.x, rp->r_max.y); continue; } #if 0 if(rnd(10) < (level - 1)){ rp->r_flags |= ISDARK; } #endif /* * Find a place and size for a random room */ do{ rp->r_max.x = rnd(bsze.x - 4) + 4; rp->r_max.y = rnd(bsze.y - 4) + 4; rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x); rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y); }while(!(rp->r_pos.y != 0)); //printf("roomB %+2d,%+2d %+2d,%+2d\n", rp->r_pos.x, rp->r_pos.y, rp->r_max.x, rp->r_max.y); #if 0 /* * Put the gold in */ if(rnd(100) < 50 && (!amulet || level >= max_level)){ rp->r_goldval = GOLDCALC; rnd_pos(rp, &rp->r_gold); if(roomin(&rp->r_gold) != rp){ endwin(), abort(); } } #endif draw_room(rp); #if 0 /* * Put the monster in */ if(rnd(100) < (rp->r_goldval > 0 ? 80 : 25)){ item = new_item(sizeof *tp); tp = (struct thing *)ldata(item); do{ rnd_pos(rp, &mp); }while(!(mvwinch(stdscr, mp.y, mp.x) == FLOOR)); new_monster(item, randmonster(FALSE), &mp); /* * See if we want to give it a treasure to carry around. */ if(rnd(100) < monsters[tp->t_type - 'A'].m_carry){ attach(tp->t_pack, new_thing()); } } #endif } } /* * Draw a box around a room */ void draw_room(ROOM *rp) { int j, k; move(rp->r_pos.y, rp->r_pos.x + 1); vert(rp->r_max.y - 2); /* Draw left side */ move(rp->r_pos.y + rp->r_max.y - 1, rp->r_pos.x); horiz(rp->r_max.x); /* Draw bottom */ move(rp->r_pos.y, rp->r_pos.x); horiz(rp->r_max.x); /* Draw top */ vert(rp->r_max.y - 2); /* Draw right side */ /* * Put the floor down */ for(j = 1; j < (rp->r_max.y - 1); j++){ move(rp->r_pos.y + j, rp->r_pos.x + 1); for(k = 1; k < (rp->r_max.x - 1); k++){ addch(FLOOR); } } #if 0 /* * Put the gold there */ if(rp->r_goldval){ mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD); } #endif } /* * horiz: * draw a horizontal line */ void horiz(int cnt) { while(cnt--){ addch('-'); } } /* * vert: * draw a vertical line */ void vert(int cnt) { int x, y; getyx(stdscr, y, x); x--; while(cnt--){ move(++y, x); addch('|'); } } /* * rnd_pos: * pick a random spot in a room */ void rnd_pos(ROOM *rp, COORD *cp) { cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1; cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1; } /* * Pick a room that is really there */ int rnd_room(void) { int rm; do{ rm = rnd(MAXROOMS); }while(rooms[rm].r_flags & ISGONE); return rm; } /* * do_passages: * Draw all the passages on a level. */ void do_passages(void) { RDES *r1, *r2; int i, j, k = 0; int roomcount; /* * reinitialize room graph description */ for(r1 = rdes; r1 <= &rdes[MAXROOMS - 1]; r1++){ for(j = 0; j < MAXROOMS; j++){ r1->isconn[j] = FALSE; } r1->ingraph = FALSE; } /* * starting with one room, connect it to a random adjacent room and * then pick a new room to start with. */ roomcount = 1; r1 = &rdes[rnd(MAXROOMS)]; r1->ingraph = TRUE; do{ /* * find a room to connect with */ j = 0; for(i = 0; i < MAXROOMS; i++){ if(r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0){ r2 = &rdes[i]; } } /* * if no adjacent rooms are outside the graph, pick a new room * to look from */ if(j == 0){ do{ r1 = &rdes[rnd(MAXROOMS)]; }while(!(r1->ingraph)); }else{ /* * otherwise, connect new room to the graph, and draw a tunnel * to it */ r2->ingraph = TRUE; i = r1 - rdes; j = r2 - rdes; conn(i, j); r1->isconn[j] = TRUE; r2->isconn[i] = TRUE; roomcount++; } }while(roomcount < MAXROOMS); /* * attempt to add passages to the graph a random number of times so * that there isn't just one unique passage through it. */ for(roomcount = rnd(5); roomcount > 0; roomcount--){ r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */ /* * find an adjacent room not already connected */ j = 0; for(i = 0; i < MAXROOMS; i++){ if(r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0){ r2 = &rdes[i]; } } /* * if there is one, connect it and look for the next added * passage */ if(j != 0){ i = r1 - rdes; j = r2 - rdes; conn(i, j); r1->isconn[j] = TRUE; r2->isconn[i] = TRUE; } } } /* * conn: * Draw a corridor from a room in a certain direction. */ void conn(int r1, int r2) { ROOM *rpf, *rpt; char rmt; int distance, turn_spot, turn_distance; int rm; char direc; COORD delta, curr, turn_delta, spos, epos; if(r1 < r2){ rm = r1; if(r1 + 1 == r2){ printf("room type 1 direction right %d->%d\n", r1, r2); direc = 'r'; }else{ printf("room type 1 direction down %d->%d\n", r1, r2); direc = 'd'; } }else{ rm = r2; if(r2 + 1 == r1){ printf("room type 2 direction right %d->%d\n", r1, r2); direc = 'r'; }else{ printf("room type 2 direction down %d->%d\n", r1, r2); direc = 'd'; } } rpf = &rooms[rm]; //printf("room %d - %d / %d\n", r1, r2, rm); /* * Set up the movement variables, in two cases: * first drawing one down. */ if(direc == 'd'){ rmt = rm + 3; /* room # of dest */ rpt = &rooms[rmt]; /* room pointer of dest */ delta.x = 0; /* direction of move */ delta.y = 1; spos.x = rpf->r_pos.x; /* start of move */ spos.y = rpf->r_pos.y; epos.x = rpt->r_pos.x; /* end of move */ epos.y = rpt->r_pos.y; distance = 0; while(distance < 2){ if(!(rpf->r_flags & ISGONE)){ /* if not gone pick door pos */ spos.x += rnd(rpf->r_max.x - 2) + 1; spos.y += rpf->r_max.y - 1; } if(!(rpt->r_flags & ISGONE)){ epos.x += rnd(rpt->r_max.x-2)+1; } distance = abs(spos.y - epos.y) - 1; /* distance to move */ } turn_delta.y = 0; /* direction to turn */ turn_delta.x = (spos.x < epos.x ? 1 : -1); turn_distance = abs(spos.x - epos.x); /* how far to turn */ turn_spot = rnd(distance - 1) + 1; /* where turn starts */ }else if(direc == 'r'){ /* setup for moving right */ rmt = rm + 1; rpt = &rooms[rmt]; delta.x = 1; delta.y = 0; spos.x = rpf->r_pos.x; spos.y = rpf->r_pos.y; epos.x = rpt->r_pos.x; epos.y = rpt->r_pos.y; distance = 0; while(distance < 2){ if(!(rpf->r_flags & ISGONE)){ spos.x += rpf->r_max.x - 1; spos.y += rnd(rpf->r_max.y - 2) + 1; } if(!(rpt->r_flags & ISGONE)){ epos.y += rnd(rpt->r_max.y - 2) + 1; } distance = abs(spos.x - epos.x) - 1; } turn_delta.y = (spos.y < epos.y ? 1 : -1); turn_delta.x = 0; turn_distance = abs(spos.y - epos.y); turn_spot = rnd(distance - 1) + 1; }else{ /*fatal("error in connection tables");*/ printf("error in connection tables"); /* * Draw in the doors on either side of the passage or just put #'s * if the rooms are gone. */ if(!(rpf->r_flags & ISGONE)){ door(rpf, &spos); }else{ cmov(spos); addch(PASSAGE); //disp_dungeon(); } } if(!(rpt->r_flags & ISGONE)){ door(rpt, &epos); //disp_dungeon(); }else{ cmov(epos); addch(PASSAGE); //disp_dungeon(); } /* * Get ready to move... */ curr.x = spos.x; curr.y = spos.y; while(distance){ /* * Move to new position */ curr.x += delta.x; curr.y += delta.y; /* * Check if we are at the turn place, if so do the turn */ if(distance == turn_spot && turn_distance > 0) while(turn_distance--) { cmov(curr); addch(PASSAGE); //disp_dungeon(); curr.x += turn_delta.x; curr.y += turn_delta.y; } /* * Continue digging along */ cmov(curr); addch(PASSAGE); //disp_dungeon(); distance--; } curr.x += delta.x; curr.y += delta.y; if(!ce(curr, epos)){ printf("Warning, connectivity problem on this level.\n"); /*msg("Warning, connectivity problem on this level.");*/ } } /* * Add a door or possibly a secret door * also enters the door in the exits array of the room. */ void door(ROOM *rm, COORD *cp) { cmov(*cp); addch((rnd(10) < (level - 1) && rnd(100) < 20 ? SECRETDOOR : DOOR)); rm->r_exit[rm->r_nexits++] = *cp; } /* * add_pass: * add the passages to the current window (wizard command) */ void add_pass(void) { #if 0 int y, x, ch; for(y = 1; y < (LINES - 2); y++){ for(x = 0; x < COLS; x++){ if((ch = mvinch(y, x)) == PASSAGE || ch == DOOR || ch == SECRETDOOR){ mvwaddch(cw, y, x, ch); } } } #endif } int rnd(int val) { // if(!val) return 1; return rand() % val; } void disp_dungeon(void) { int i; for(i = 0; i < LINES; i++){ printf("%s\n", floor_map[i]); } printf("================================================================================\n"); }