Advertisement
Guest User

Untitled

a guest
Nov 25th, 2015
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.11 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4.  
  5. /* MAP DIMENSIONS */
  6. #define MAX_HEIGHT (100 + 1)
  7. #define MAX_WIDTH (200 + 1)
  8.  
  9. /* MAP SYMBOLS */
  10. #define M_ROCKFORD '&'
  11. #define M_EMPTY ' '
  12. #define M_DIRT '.'
  13. #define M_ROCK '#'
  14. #define M_STONE 'O'
  15. #define M_DIAMOND '$'
  16. #define M_EXIT 'X'
  17.  
  18. /* MOVEMENT KEYS */
  19. #define DIR_UP 'w'
  20. #define DIR_DOWN 's'
  21. #define DIR_LEFT 'a'
  22. #define DIR_RIGHT 'd'
  23.  
  24.  
  25. /* Simple structure to define coordinates on map */
  26. typedef struct {
  27. int x;
  28. int y;
  29. } position;
  30.  
  31.  
  32. /* Returns position structure with given values */
  33. position make_position(int x, int y)
  34. {
  35. position p;
  36. p.x = x;
  37. p.y = y;
  38. return p;
  39. }
  40.  
  41.  
  42. /* UTILITY FUNCTIONS */
  43. int max(int a, int b)
  44. {
  45. return a > b ? a : b;
  46. }
  47.  
  48. /* Reads line from STDIN until end of line
  49. * Returns number of characters read */
  50. int getline(char *s)
  51. {
  52. char c;
  53. int i = 0;
  54. while( (c = getchar()) != '\n' && c != EOF && i < MAX_WIDTH)
  55. s[i++] = c;
  56. s[i] = '\n';
  57. return i+1;
  58. }
  59.  
  60. /* Computes new coordinates for given direction of movement */
  61. position get_position(position pos, char direction)
  62. {
  63. switch(direction)
  64. {
  65. case DIR_UP:
  66. pos.y--;
  67. break;
  68. case DIR_DOWN:
  69. pos.y++;
  70. break;
  71. case DIR_LEFT:
  72. pos.x--;
  73. break;
  74. case DIR_RIGHT:
  75. pos.x++;
  76. break;
  77. }
  78. return pos;
  79. }
  80. /* END UTILITY FUNCTIONS */
  81.  
  82.  
  83. /* GLOBAL VARIABLES */
  84.  
  85. /* Array contaning map data */
  86. char map[MAX_HEIGHT][MAX_WIDTH];
  87.  
  88. /* Map dimensions */
  89. int map_height,
  90. map_width;
  91.  
  92. /* Controls end of execution */
  93. bool RUNNING;
  94.  
  95. /* Rockford position (current and from previous iteration) */
  96. position player_position;
  97. position previous_position;
  98.  
  99. /* Number of uncollected diamonds */
  100. int diamond_counter;
  101.  
  102. /* END GLOBAL VARIABLES */
  103.  
  104.  
  105. /*
  106. * Reads map data from STDIN until it encounters
  107. * an empty line
  108. */
  109. void load_map(void)
  110. {
  111. char *s;
  112. int len;
  113. map_height = 0;
  114. map_width = 0;
  115.  
  116. s = (char *) malloc(MAX_WIDTH * sizeof(char));
  117.  
  118. /* Load until only \n is read */
  119. while ( ( len = getline(s) ) > 1)
  120. {
  121. int i;
  122. for (i = 0; i < len; i++)
  123. map[map_height][i] = s[i];
  124.  
  125. map_height++;
  126. map_width = max(map_width, len);
  127. }
  128.  
  129. free(s);
  130. }
  131.  
  132. /* Print map to STDOUT */
  133. void print_map(void)
  134. {
  135. int i,j;
  136. for (i = 0; i < map_height; i++)
  137. {
  138. char c;
  139. j = 0;
  140. while( (c = map[i][j++]) != '\n' ) putchar(c);
  141. putchar('\n');
  142. }
  143. }
  144.  
  145. /* Check if it is possible to push a stone */
  146. bool movement_allowed(position stone_pos, char direction)
  147. {
  148. switch(direction)
  149. {
  150. case DIR_UP:
  151. case DIR_DOWN:
  152. return false; /* Pushing stone up or down not allowed */
  153. break;
  154. case DIR_LEFT:
  155. stone_pos.x--;
  156. break;
  157. case DIR_RIGHT:
  158. stone_pos.x++;
  159. break;
  160. }
  161. return (map[stone_pos.y][stone_pos.x] == M_EMPTY);
  162. }
  163.  
  164. /* Moves source field to target field, marking source as empty */
  165. void move_field(position src, char direction)
  166. {
  167. position dst = get_position(src, direction);
  168.  
  169. map[dst.y][dst.x] = map[src.y][src.x];
  170. map[src.y][src.x] = M_EMPTY;
  171. }
  172.  
  173. /* Handle Rockford's movement based on chosen direction */
  174. void move_rockford(char direction)
  175. {
  176. position new_pos;
  177.  
  178. /* Compute new position */
  179. new_pos = get_position(player_position, direction);
  180.  
  181. /* Determine what to do based on target field type */
  182. switch(map[new_pos.y][new_pos.x])
  183. {
  184. case M_EMPTY: /* OK TO MOVE */
  185. case M_DIRT: /* OK TO MOVE */
  186. move_field(player_position, direction);
  187. player_position = new_pos;
  188. break;
  189.  
  190. case M_ROCK: /* DO NOTHING, NOT ALLOWED */
  191. break;
  192.  
  193. case M_STONE: /* OK, ONLY IF NEXT SPACE IS EMPTY*/
  194. if (movement_allowed(new_pos, direction))
  195. {
  196. move_field(new_pos, direction);
  197. move_field(player_position, direction);
  198. player_position = new_pos;
  199.  
  200. }
  201. break;
  202.  
  203. case M_DIAMOND: /* OK, REMOVE DIAMOND */
  204. diamond_counter--;
  205.  
  206. move_field(player_position, direction);
  207. player_position = new_pos;
  208. break;
  209.  
  210. case M_EXIT: /* OK, ONLY IF DIAMOND LIST IS EMPTY*/
  211. if (diamond_counter == 0)
  212. {
  213. move_field(player_position, direction);
  214. /* Rockford disappears */
  215. map[new_pos.y][new_pos.x] = M_EXIT;
  216. RUNNING = false;
  217. }
  218. break;
  219. }
  220. }
  221.  
  222.  
  223. /* Initialize variables */
  224. void init(void)
  225. {
  226. int x, y;
  227.  
  228. diamond_counter = 0;
  229. RUNNING = true;
  230.  
  231. /* Looks for diamonds and Rockford */
  232. for (y = 0; y < map_height; y++)
  233. {
  234. for (x = 0; x < map_width; x++)
  235. {
  236. switch(map[y][x])
  237. {
  238. case M_ROCKFORD:
  239. player_position.x = x;
  240. player_position.y = y;
  241.  
  242. previous_position = player_position;
  243. break;
  244. case M_STONE:
  245. break;
  246. case M_DIAMOND:
  247. diamond_counter++;
  248. break;
  249. }
  250. }
  251. }
  252. }
  253.  
  254.  
  255. /*
  256. * Update position of diamonds and stones in
  257. * given column
  258. */
  259. void updateColumn(int column)
  260. {
  261. int i;
  262. for (i = map_height - 1; i >= 0; i--)
  263. {
  264. char field = map[i][column];
  265. if(field == M_DIAMOND || field == M_STONE)
  266. {
  267. position p = make_position(column, i);
  268. /* If there is space below, move down */
  269. while(map[p.y + 1][column] == M_EMPTY)
  270. {
  271. move_field(p, DIR_DOWN);
  272. p.y++;
  273. }
  274. }
  275. }
  276. }
  277.  
  278. /* Stabilize map */
  279. void updateGlobal()
  280. {
  281. int i,j;
  282. for(i = map_height-1; i >= 0; i--)
  283. {
  284. for(j = 0; j < map_width; j++)
  285. {
  286. char field = map[i][j];
  287.  
  288. if(field == M_DIAMOND || field == M_STONE)
  289. {
  290. position p = make_position(j, i);
  291.  
  292. /* If there is space below, move down */
  293. while(map[p.y + 1][p.x] == M_EMPTY)
  294. {
  295. move_field(p, DIR_DOWN);
  296. p.y++;
  297. }
  298. }
  299. }
  300. }
  301.  
  302. }
  303.  
  304. /* Update columns near Rockford */
  305. void update()
  306. {
  307. /* Horizontal movement */
  308. if(previous_position.x != player_position.x)
  309. {
  310. /* Update column on left and right */;
  311. updateColumn(player_position.x + 1);
  312. updateColumn(player_position.x - 1);
  313. }
  314.  
  315. /* Vertival movement */
  316. if(previous_position.y != player_position.y)
  317. {
  318. updateColumn(player_position.x);
  319. }
  320.  
  321. previous_position = player_position;
  322. }
  323.  
  324. /* React to user's input */
  325. void handle_input(void)
  326. {
  327. char input = getchar();
  328. switch(input)
  329. {
  330. case DIR_UP:
  331. case DIR_DOWN:
  332. case DIR_LEFT:
  333. case DIR_RIGHT:
  334. move_rockford(input);
  335. break;
  336. case EOF: /* NOTHING TO DO. STOP AND EXIT*/
  337. RUNNING = false;
  338. }
  339. }
  340.  
  341. void start(void)
  342. {
  343. updateGlobal();
  344. while(RUNNING)
  345. {
  346. update();
  347. handle_input();
  348. }
  349. updateGlobal();
  350. }
  351.  
  352. int main(void)
  353. {
  354. load_map();
  355. init();
  356. start();
  357. print_map();
  358.  
  359. return 0;
  360. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement