You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

341 lines
7.1 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include "types.h"
  7. #include "util.h"
  8. #include "Bill.h"
  9. #include "Bucket.h"
  10. #include "Computer.h"
  11. #include "Cable.h"
  12. #include "Game.h"
  13. #include "Horde.h"
  14. #include "Network.h"
  15. #include "OS.h"
  16. #include "Scorelist.h"
  17. #include "Spark.h"
  18. #include "UI.h"
  19. #define SCREENSIZE 400
  20. /* Game states */
  21. #define STATE_PLAYING 1
  22. #define STATE_BETWEEN 2
  23. #define STATE_END 3
  24. #define STATE_WAITING 4
  25. /* Score related constants */
  26. #define SCORE_ENDLEVEL -1
  27. #define SCORE_BILLPOINTS 5
  28. static unsigned int state;
  29. static int efficiency;
  30. static int score, level, iteration;
  31. static Picture *logo, *icon, *about;
  32. static MCursor *defaultcursor, *downcursor;
  33. static Bill *grabbed;
  34. static const char *gui;
  35. static int screensize = SCREENSIZE;
  36. static void
  37. setup_level(int newlevel) {
  38. level = newlevel;
  39. Horde_setup();
  40. grabbed = NULL;
  41. UI_set_cursor(defaultcursor);
  42. Network_setup();
  43. iteration = 0;
  44. efficiency = 0;
  45. }
  46. void
  47. Game_start(int newlevel) {
  48. state = STATE_PLAYING;
  49. score = 0;
  50. UI_restart_timer();
  51. UI_set_pausebutton(1);
  52. setup_level(newlevel);
  53. }
  54. void
  55. Game_quit() {
  56. Scorelist_write();
  57. exit(0);
  58. }
  59. static void
  60. update_info(void) {
  61. char str[80];
  62. int on_screen = Horde_get_counter(HORDE_COUNTER_ON);
  63. int off_screen = Horde_get_counter(HORDE_COUNTER_OFF);
  64. int base = Network_get_counter(NETWORK_COUNTER_BASE);
  65. int off = Network_get_counter(NETWORK_COUNTER_OFF);
  66. int win = Network_get_counter(NETWORK_COUNTER_WIN);
  67. int units = Network_num_computers();
  68. sprintf(str, "Lenn:%d/%d System:%d/%d/%d Level:%d Score:%d",
  69. on_screen, off_screen, base, off, win, level, score);
  70. UI_draw_str(str, 5, screensize - 5);
  71. efficiency += ((100 * base - 10 * win) / units);
  72. }
  73. void
  74. Game_warp_to_level(int lev) {
  75. if (state == STATE_PLAYING) {
  76. if (lev <= level)
  77. return;
  78. setup_level(lev);
  79. }
  80. else {
  81. if (lev <= 0)
  82. return;
  83. Game_start(lev);
  84. }
  85. }
  86. void
  87. Game_add_high_score(const char *str) {
  88. Scorelist_recalc(str, level, score);
  89. }
  90. void
  91. Game_button_press(int x, int y) {
  92. int counter;
  93. if (state != STATE_PLAYING)
  94. return;
  95. UI_set_cursor(downcursor);
  96. if (Bucket_clicked(x, y)) {
  97. Bucket_grab(x, y);
  98. return;
  99. }
  100. grabbed = Horde_clicked_stray(x, y);
  101. if (grabbed != NULL) {
  102. OS_set_cursor(grabbed->cargo);
  103. return;
  104. }
  105. counter = Horde_process_click(x, y);
  106. score += (counter * counter * SCORE_BILLPOINTS);
  107. }
  108. void
  109. Game_button_release(int x, int y) {
  110. int i;
  111. UI_set_cursor(defaultcursor);
  112. if (state != STATE_PLAYING)
  113. return;
  114. if (grabbed == NULL) {
  115. Bucket_release(x, y);
  116. return;
  117. }
  118. for (i = 0; i < Network_num_computers(); i++) {
  119. Computer *computer = Network_get_computer(i);
  120. if (Computer_on(computer, x, y) &&
  121. Computer_compatible(computer, grabbed->cargo) &&
  122. (computer->os == OS_WINGDOWS || computer->os == OS_OFF)) {
  123. int counter;
  124. Network_inc_counter(NETWORK_COUNTER_BASE, 1);
  125. if (computer->os == OS_WINGDOWS)
  126. counter = NETWORK_COUNTER_WIN;
  127. else
  128. counter = NETWORK_COUNTER_OFF;
  129. Network_inc_counter(counter, -1);
  130. computer->os = grabbed->cargo;
  131. Horde_remove_bill(grabbed);
  132. grabbed = NULL;
  133. return;
  134. }
  135. }
  136. Horde_add_bill(grabbed);
  137. grabbed = NULL;
  138. }
  139. static void
  140. draw_logo(void) {
  141. UI_clear();
  142. UI_draw(logo,
  143. (screensize - UI_picture_width(logo)) / 2,
  144. (screensize - UI_picture_height(logo)) / 2);
  145. }
  146. void
  147. Game_update() {
  148. char str[40];
  149. switch (state) {
  150. case STATE_PLAYING:
  151. UI_clear();
  152. Bucket_draw();
  153. Network_update();
  154. Network_draw();
  155. Horde_update(iteration);
  156. Horde_draw();
  157. update_info();
  158. if (Horde_get_counter(HORDE_COUNTER_ON) +
  159. Horde_get_counter(HORDE_COUNTER_OFF) == 0) {
  160. score += (level * efficiency / iteration);
  161. state = STATE_BETWEEN;
  162. }
  163. if ((Network_get_counter(NETWORK_COUNTER_BASE) +
  164. Network_get_counter(NETWORK_COUNTER_OFF)) <= 1)
  165. state = STATE_END;
  166. break;
  167. case STATE_END:
  168. UI_set_cursor(defaultcursor);
  169. UI_clear();
  170. Network_toasters();
  171. Network_draw();
  172. UI_refresh();
  173. UI_popup_dialog(DIALOG_ENDGAME);
  174. if (Scorelist_ishighscore(score)) {
  175. UI_popup_dialog(DIALOG_ENTERNAME);
  176. Scorelist_update();
  177. }
  178. UI_popup_dialog(DIALOG_HIGHSCORE);
  179. draw_logo();
  180. UI_kill_timer();
  181. UI_set_pausebutton(0);
  182. state = STATE_WAITING;
  183. break;
  184. case STATE_BETWEEN:
  185. UI_set_cursor(defaultcursor);
  186. sprintf(str, "After Level %d:\nScore: %d", level, score);
  187. UI_update_dialog(DIALOG_SCORE, str);
  188. UI_popup_dialog(DIALOG_SCORE);
  189. state = STATE_PLAYING;
  190. setup_level(++level);
  191. break;
  192. }
  193. UI_refresh();
  194. iteration++;
  195. }
  196. int
  197. Game_score() {
  198. return score;
  199. }
  200. int
  201. Game_level() {
  202. return level;
  203. }
  204. int
  205. Game_screensize() {
  206. return screensize;
  207. }
  208. double
  209. Game_scale(int dimensions) {
  210. double scale = (double)screensize / SCREENSIZE;
  211. double d = 1;
  212. for ( ; dimensions > 0; dimensions--)
  213. d *= scale;
  214. return (d);
  215. }
  216. /*
  217. * Note - don't use getopt, since it might reorder the args or do something
  218. * that the UI-specific argument parser doesn't like.
  219. */
  220. static void
  221. parse_args(int argc, char **argv) {
  222. char *s;
  223. char *endp;
  224. int i;
  225. for (i = 1; i < argc; i++) {
  226. if (strncasecmp(argv[i], "-l", 2) == 0) {
  227. if (strlen(argv[i]) == 2 && i == argc - 1)
  228. fatal("-l takes an argument");
  229. if (strlen(argv[i]) > 2)
  230. s = argv[i] + 2;
  231. else
  232. s = argv[++i];
  233. level = strtol(s, &endp, 10);
  234. if (*endp != '\0' || level <= 0)
  235. fatal("invalid level '%s'", s);
  236. } else if (strcmp(argv[i], "--gui") == 0) {
  237. if (i == argc - 1)
  238. fatal("--gui takes an argument");
  239. gui = argv[++i];
  240. } else if (strcmp(argv[i], "--size") == 0) {
  241. if (i == argc - 1)
  242. fatal("--size takes an argument");
  243. s = argv[++i];
  244. screensize = strtol(s, &endp, 10);
  245. if (*endp != '\0' || screensize <= 0)
  246. fatal("invalid screensize '%s'", s);
  247. if (screensize < SCREENSIZE)
  248. fatal("screensize must be larger than '%d'",
  249. SCREENSIZE);
  250. } else if (strcmp(argv[1], "-v") == 0 ||
  251. strcmp(argv[1], "--version") == 0)
  252. {
  253. printf ("XLennart version 1.0\n\n");
  254. exit(0);
  255. } else if (strcmp(argv[1], "-h") == 0 ||
  256. strcmp(argv[1], "--help") == 0)
  257. {
  258. printf("XLennart version 1.0\n");
  259. printf("Options:\n");
  260. printf("-l <n>\tStart at level n.\n");
  261. printf("--gui <gui> \tUse a specific gui "
  262. "(athena, motif, gtk)\n");
  263. printf("--size <size>\t\tUse a larger playing area.\n");
  264. printf("-v\t\tPrint version number and exit.\n");
  265. printf("-h\t\tPrint help and exit.\n");
  266. printf("All standard toolkit options are also ");
  267. printf("supported.\n\n");
  268. exit(0);
  269. }
  270. }
  271. }
  272. int
  273. main(int argc, char **argv) {
  274. srand(time(NULL));
  275. parse_args(argc, argv);
  276. UI_initialize(gui, &argc, argv);
  277. UI_make_main_window(screensize);
  278. UI_graphics_init();
  279. UI_load_picture("logo", 0, &logo);
  280. UI_load_picture("icon", 0, &icon);
  281. UI_load_picture("about", 0, &about);
  282. draw_logo();
  283. UI_refresh();
  284. UI_make_dialogs(logo, icon, about);
  285. UI_set_icon(icon);
  286. Scorelist_read();
  287. Scorelist_update();
  288. UI_load_cursor("hand_up", CURSOR_SEP_MASK, &defaultcursor);
  289. UI_load_cursor("hand_down", CURSOR_SEP_MASK, &downcursor);
  290. UI_set_cursor(defaultcursor);
  291. Bill_load_pix();
  292. OS_load_pix();
  293. Computer_load_pix();
  294. Bucket_load_pix();
  295. Spark_load_pix();
  296. state = STATE_WAITING;
  297. if (level)
  298. Game_start(level);
  299. else
  300. UI_set_pausebutton(0);
  301. UI_main_loop();
  302. exit(0);
  303. }