bandit

oldschool thievery roguelike
git clone git://moonbender.net/bandit
Log | Files | Refs | README

bandit.c (9057B)


      1 #include <stdio.h>
      2 #include <curses.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 
      6 #include "common.h"
      7 
      8 extern u32 icons[MAXACTORS];
      9 extern Actor actors[MAXACTORS];
     10 
     11 u8 app_state = 1;
     12 u8 menu_state = 1;
     13 u8 menu_selection = 1;
     14 
     15 enum {
     16     ABILITY_STRONG =    1 << 0,
     17     ABILITY_ECHO =      1 << 1
     18 };
     19 
     20 Thief pc;
     21 
     22 unsigned int ltiles[MAXLEVELWIDTH * MAXLEVELHEIGHT] = {
     23 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     24 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
     25 	2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2,
     26 	2, 1, 1, 1, 1, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2,
     27 	2, 1, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 1, 2,
     28 	2, 1, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 1, 2,
     29 	2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2,
     30 	2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 2,
     31 	2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2,
     32 	2, 1, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 1, 2,
     33 	2, 3, 2, 2, 2, 2, 0, 0, 0, 2, 1, 1, 1, 1, 2,
     34 	2, 1, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 1, 2,
     35 	2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2,
     36 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
     37 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     38 };
     39 
     40 char *banner =
     41 				"\n\n"
     42 				"####                           #   ####   #   \n" 
     43 				"#   #   ###   ###       #  #   #   #   #  #   \n"
     44 				"####       #  #  #      #     ###  ####   #   \n"
     45 				"#   #   ####  #  #   ####  #   #   # #    #   \n"
     46 				"#   #  #   #  #  #  #   #  #   #   #  #   #   \n"  
     47 				"####    ####  #  #   ####  #   ##  #   #  ####\n" 
     48 				"\n\n"
     49 				"$ to roll a new scoundrel\n"
     50 				"@ to load your existing thief\n"
     51 				"q to exit\n\0";
     52 
     53 u32 tile_flags[MAXLEVELWIDTH * MAXLEVELHEIGHT];
     54 
     55 char* messages[3] = {" \n", " \n", " \n"};
     56 
     57 void draw_init_colors(void) {
     58 	start_color();
     59 	init_pair(1, COLOR_RED, COLOR_BLACK);
     60 	init_pair(2, COLOR_WHITE, COLOR_GREEN);
     61 	init_pair(3, COLOR_BLUE, COLOR_BLACK);
     62 	init_pair(4, COLOR_MAGENTA, COLOR_BLACK);
     63 }
     64 
     65 void draw_messagebox(void) {
     66 	u32 cursx, cursy;
     67     u32 i;
     68 	char* msg;
     69 
     70 	cursy = LINES - 1;
     71 
     72 	for (i = 0; i < 3; i++) {
     73 		msg = messages[i];
     74 		for (cursx = 0; cursx < 60; cursx++) {
     75 			if (*msg == '\0') {
     76 				mvaddch(cursy, cursx, ' ');
     77 			} else {
     78 				mvaddch(cursy, cursx, *msg);
     79 				msg++;
     80 			}
     81 		}
     82 		cursy -= 1;
     83 	}
     84 	cursy = LINES - 4;
     85 	for (cursx = 0; cursx < COLS; cursx++) {
     86 		mvaddch(cursy, cursx, '-');
     87 	}
     88 }
     89 
     90 void message_push(char* str) {
     91 	messages[2] = messages[1];
     92 	messages[1] = messages[0];
     93 	messages[0] = str;
     94 }
     95 
     96 void draw_screen_clear(void) {
     97     u32 i, j;
     98 
     99 	for (j = 0; j < COLS; j++) {
    100 		for (i = 0; i < LINES; i++) {
    101 			mvaddch(i, j, ' ');
    102 		}
    103 	}
    104 }
    105 
    106 void menu_title(void) {
    107     u32 i;
    108     int input;
    109 
    110     mvaddstr(LINES/4, COLS/4,banner);
    111     for (i = 0; i < COLS; i++) {
    112         mvaddch(0, i, '#');
    113         mvaddch(LINES - 1, i, '#');
    114     }
    115 
    116     input = getch();
    117     if      (input == 'q') { app_state = 0; }
    118     else if (input == '$') { app_state = 2; }
    119     else if (input == '@') { }
    120 }
    121 
    122 void thief_init_bat(Thief *in) {
    123     in->grace = 2;
    124     in->perception = 3;
    125     in->charisma = 0;
    126     in->lore = 1;
    127     in->abilities = ABILITY_ECHO;
    128 }
    129 
    130 void thief_init_snake(Thief *in) {
    131     in->grace = 0;
    132     in->perception = 1;
    133     in->charisma = 3;
    134     in->lore = 2;
    135     in->abilities = ABILITY_STRONG;
    136 }
    137 
    138 void thief_init_rat(Thief *in) {
    139     in->grace = 3;
    140     in->perception = 2;
    141     in->charisma = 1;
    142     in->lore = 0;
    143     in->abilities = 0;
    144 }
    145 
    146 void thief_init_raven(Thief *in) {
    147     in->grace = 1;
    148     in->perception = 0;
    149     in->charisma = 2;
    150     in->lore = 3;
    151     in->abilities = 0;
    152 }
    153 
    154 void menu_character_gen(void) {
    155     int input;
    156 
    157     if (menu_state == 2) {
    158         echo();
    159         mvprintw(10, 0, "Type your name...");
    160         mvprintw(11, 0, "");
    161         getstr((char*) pc.name);
    162         actors[0].x = 3;
    163         actors[0].y = 3;
    164         app_state = 3;
    165         noecho();
    166     } else {
    167         mvprintw(10, 0, "Choose what creature you are... (c to confirm)");
    168         mvprintw(12, 0, "Bat");
    169         mvprintw(13, 0, "Snake");
    170         mvprintw(14, 0, "Raven");
    171         mvprintw(15, 0, "Rat");
    172         if (menu_selection == 1) {
    173             attron(COLOR_PAIR(2));
    174             mvprintw(12, 0, "Bat");
    175             attroff(COLOR_PAIR(2));
    176             attron(COLOR_PAIR(3));
    177                 mvprintw(20, 0, "Grace		2");
    178                 mvprintw(21, 0, "Perception	3");
    179                 mvprintw(22, 0, "Lore		1");
    180                 mvprintw(23, 0, "Charisma	0");
    181             attroff(COLOR_PAIR(3));
    182             attron(COLOR_PAIR(4));
    183                 mvprintw(24, 0, "\n");
    184                 mvprintw(25, 0, "Walk Speed : 10");
    185                 mvprintw(26, 0, "Fly Speed : 90");
    186                 mvprintw(27, 0, "\n");
    187                 mvprintw(28, 0, "Echolocation");
    188             attroff(COLOR_PAIR(4));
    189         } else if (menu_selection == 2) {
    190             attron(COLOR_PAIR(2));
    191                 mvprintw(13, 0, "Snake");
    192             attroff(COLOR_PAIR(2));
    193             attron(COLOR_PAIR(3));
    194                 mvprintw(20, 0, "Grace		0");
    195                 mvprintw(21, 0, "Perception	1");
    196                 mvprintw(22, 0, "Lore		2");
    197                 mvprintw(23, 0, "Charisma	3");
    198             attroff(COLOR_PAIR(3));
    199             attron(COLOR_PAIR(4));
    200                 mvprintw(24, 0, "\n");
    201                 mvprintw(25, 0, "Slither Speed: 40");
    202                 mvprintw(26, 0, "\n");
    203                 mvprintw(27, 0, "Strong");
    204             attroff(COLOR_PAIR(4));
    205         } else if (menu_selection == 3) {
    206             attron(COLOR_PAIR(2));
    207                 mvprintw(14, 0, "Raven");
    208             attroff(COLOR_PAIR(2));
    209             attron(COLOR_PAIR(3));
    210                 mvprintw(20, 0, "Grace		1");
    211                 mvprintw(21, 0, "Perception	0");
    212                 mvprintw(22, 0, "Lore		3");
    213                 mvprintw(23, 0, "Charisma	2");
    214             attroff(COLOR_PAIR(3));
    215                 mvprintw(24, 0, "\n");
    216             attron(COLOR_PAIR(4));
    217                 mvprintw(25, 0, "Walk Speed: 30");
    218                 mvprintw(26, 0, "Fly Speed: 90");
    219             attroff(COLOR_PAIR(4));
    220         } else if (menu_selection == 4) {
    221             attron(COLOR_PAIR(2));
    222                 mvprintw(15, 0, "Rat");
    223             attroff(COLOR_PAIR(2));
    224             attron(COLOR_PAIR(3));
    225                 mvprintw(20, 0, "Grace		3");
    226                 mvprintw(21, 0, "Perception	2");
    227                 mvprintw(22, 0, "Lore		0");
    228                 mvprintw(23, 0, "Charisma	1");
    229                 mvprintw(24, 0, "\n");
    230             attroff(COLOR_PAIR(3));
    231             attron(COLOR_PAIR(4));
    232                 mvprintw(25, 0, "Walk Speed: 30");
    233                 mvprintw(26, 0, "Scurry Speed: 50");
    234             attroff(COLOR_PAIR(4));
    235         }
    236 
    237         input = getch();
    238         if (input == 'q') { app_state = 0; }
    239         else if (input == KEY_DOWN) {
    240             menu_selection++;
    241             if (menu_selection > 4) {  menu_selection = 4; }
    242         } else if (input == KEY_UP) {
    243             menu_selection--;
    244             if (menu_selection < 1) { menu_selection = 1; }
    245         } else if (input == 'c') {
    246             switch (menu_selection) {
    247                 case 1: thief_init_bat(&pc); break;
    248                 case 2: thief_init_snake(&pc); break;
    249                 case 3: thief_init_raven(&pc); break;
    250                 case 4: thief_init_rat(&pc);
    251             }
    252             menu_state = 2;
    253         }
    254     }
    255 }
    256 
    257 void draw_level(void) {
    258     u32 i;
    259 
    260 	attron(COLOR_PAIR(1));
    261 
    262 	for(i = 0; i < MAXLEVELWIDTH * MAXLEVELHEIGHT; i++) {
    263 		u32 curs_y = i / MAXLEVELWIDTH;
    264 		u32 curs_x = i % MAXLEVELWIDTH;
    265 		u32 local_x = curs_x/* - pov_x*/;
    266 		u32 local_y = curs_y/* - pov_y*/;
    267 
    268 		if ( local_y > LINES || local_x > COLS ) {
    269 			continue;
    270 		}
    271 
    272         if(ltiles[i] == TILE_NULL) {
    273             continue;
    274 		} else if(ltiles[i] == TILE_FLOOR) {
    275 			mvaddch(local_y, local_x, '.');
    276 		} else if(ltiles[i] == TILE_WALL) {
    277 			mvaddch(local_y, local_x, '#');
    278 		} else if(ltiles[i] == TILE_DOOR_CLOSED) {
    279 			mvaddch(local_y, local_x, '+');
    280 		} else if(ltiles[i] == TILE_DOOR_OPEN) {
    281 			mvaddch(local_y, local_x, '*');
    282 		}
    283 	}
    284 
    285 	attroff(COLOR_PAIR(1));
    286 
    287     /*
    288 	for (i = 0; i < MAXACTORS; i++) {
    289 		if (icons[i] != '?') {
    290 			mvaddch(actors[i].x - pov_y, actors[i].y - pov_x, icons[i]);
    291 		}
    292 	}
    293     */
    294 
    295 	mvaddch(actors[0].y, actors[0].x, '@');
    296 }
    297 
    298 u32 tile_index(u32 x, u32 y) {
    299 	if (x > MAXLEVELWIDTH || y > MAXLEVELHEIGHT) {
    300 		return 1; /* outside of level bounds */
    301 	}
    302 	return x + y * MAXLEVELWIDTH;
    303 }
    304 
    305 u8 bandit_time_advance(void) {
    306     bandit_actor_think();
    307     return 0;
    308 }
    309 
    310 int main(void) {
    311 	u32 doortile = MAXLEVELWIDTH * 7 + 7;
    312 	tile_flags[doortile] = DOOR_HAS_LOCK | DOOR_LOCK_ENGAGED;
    313 	
    314 	initscr();	/* init curses mode */
    315 	noecho();
    316 
    317     /*
    318      * input characters are immediately available,
    319      * instead of waiting for the user to hit enter
    320      */
    321 	raw(); 
    322 
    323     /* allows getch() to read arrow key inputs and such */
    324 	keypad(stdscr, TRUE); 
    325 
    326 	draw_init_colors();
    327 
    328 	while(0 != app_state) {
    329 		draw_screen_clear(); 
    330 		if (app_state == 1) {
    331             menu_title();
    332 		} else if (app_state == 2) {
    333             menu_character_gen();
    334 		} else if (app_state == 3) {
    335 			draw_level();
    336 			draw_messagebox();
    337 			curses_input_handle();
    338 		}
    339 		refresh();
    340 	}		
    341 	
    342 	endwin(); 
    343 }