Logo Search packages:      
Sourcecode: xbill version File versions  Download package

Game.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>

#include "types.h"
#include "util.h"

#include "Bill.h"
#include "Bucket.h"
#include "Computer.h"
#include "Cable.h"
#include "Game.h"
#include "Horde.h"
#include "Network.h"
#include "OS.h"
#include "Scorelist.h"
#include "Spark.h"
#include "UI.h"

#define SCREENSIZE 400

/* Game states */
#define STATE_PLAYING 1
#define STATE_BETWEEN 2
#define STATE_END 3
#define STATE_WAITING 4

/* Score related constants */
#define SCORE_ENDLEVEL -1
#define SCORE_BILLPOINTS 5

static unsigned int state;
static int efficiency;
static int score, level, iteration;
static Picture *logo, *icon, *about;
static MCursor *defaultcursor, *downcursor;
static Bill *grabbed;
static const char *gui;
static int screensize = SCREENSIZE;

static void
setup_level(int newlevel) {
      level = newlevel;
      Horde_setup();
      grabbed = NULL;
      UI_set_cursor(defaultcursor);
      Network_setup();
      iteration = 0;
      efficiency = 0;
}

void
Game_start(int newlevel) {
      state = STATE_PLAYING;
      score = 0;
      UI_restart_timer();
      UI_set_pausebutton(1);
      setup_level(newlevel);
}

void
Game_quit() {
      Scorelist_write();
      exit(0);
}

static void
update_info(void) {
      char str[80];
      int on_screen = Horde_get_counter(HORDE_COUNTER_ON);
      int off_screen = Horde_get_counter(HORDE_COUNTER_OFF);
      int base = Network_get_counter(NETWORK_COUNTER_BASE);
      int off = Network_get_counter(NETWORK_COUNTER_OFF);
      int win = Network_get_counter(NETWORK_COUNTER_WIN);
      int units = Network_num_computers();
      sprintf(str, "Bill:%d/%d  System:%d/%d/%d  Level:%d  Score:%d",
            on_screen, off_screen, base, off, win, level, score);
      UI_draw_str(str, 5, screensize - 5);
      efficiency += ((100 * base - 10 * win) / units);
}

void
Game_warp_to_level(int lev) {
      if (state == STATE_PLAYING) {
            if (lev <= level)
                  return;
            setup_level(lev);
      }
      else {
            if (lev <= 0)
                  return;
            Game_start(lev);
      }
}

void
Game_add_high_score(const char *str) {
      Scorelist_recalc(str, level, score);
}

void
Game_button_press(int x, int y) {
      int counter;

      if (state != STATE_PLAYING)
            return;
      UI_set_cursor(downcursor);

      if (Bucket_clicked(x, y)) {
            Bucket_grab(x, y);
            return;
      }

      grabbed = Horde_clicked_stray(x, y);
      if (grabbed != NULL) {
            OS_set_cursor(grabbed->cargo);
            return;
      }

      counter = Horde_process_click(x, y);
      score += (counter * counter * SCORE_BILLPOINTS);
}

void
Game_button_release(int x, int y) {
      int i;
      UI_set_cursor(defaultcursor);

      if (state != STATE_PLAYING)
            return;

      if (grabbed == NULL) {
            Bucket_release(x, y);
            return;
      }

      for (i = 0; i < Network_num_computers(); i++) {
            Computer *computer = Network_get_computer(i);

            if (Computer_on(computer, x, y) &&
                Computer_compatible(computer, grabbed->cargo) &&
                (computer->os == OS_WINGDOWS || computer->os == OS_OFF)) {
                  int counter;

                  Network_inc_counter(NETWORK_COUNTER_BASE, 1);
                  if (computer->os == OS_WINGDOWS)
                        counter = NETWORK_COUNTER_WIN;
                  else
                        counter = NETWORK_COUNTER_OFF;
                  Network_inc_counter(counter, -1);
                  computer->os = grabbed->cargo;
                  Horde_remove_bill(grabbed);
                  grabbed = NULL;
                  return;
            }
      }
      Horde_add_bill(grabbed);
      grabbed = NULL;
}

static void
draw_logo(void) {
      UI_clear();
      UI_draw(logo,
            (screensize - UI_picture_width(logo)) / 2,
            (screensize - UI_picture_height(logo)) / 2);
}

void
Game_update() {
      char str[40];

      switch (state) {
      case STATE_PLAYING:
            UI_clear(); 
            Bucket_draw();
            Network_update();
            Network_draw();
            Horde_update(iteration);
            Horde_draw();
            update_info();
            if (Horde_get_counter(HORDE_COUNTER_ON) +
                Horde_get_counter(HORDE_COUNTER_OFF) == 0) {
                  score += (level * efficiency / iteration);
                  state = STATE_BETWEEN;
            }
            if ((Network_get_counter(NETWORK_COUNTER_BASE) +
                 Network_get_counter(NETWORK_COUNTER_OFF)) <= 1)
                  state = STATE_END;
            break;
      case STATE_END:
            UI_set_cursor(defaultcursor);
            UI_clear();
            Network_toasters();
            Network_draw();
            UI_refresh();
            UI_popup_dialog(DIALOG_ENDGAME);
            if (Scorelist_ishighscore(score)) {
                  UI_popup_dialog(DIALOG_ENTERNAME);
                  Scorelist_update();
            }
            UI_popup_dialog(DIALOG_HIGHSCORE);
            draw_logo();
            UI_kill_timer();
            UI_set_pausebutton(0);
            state = STATE_WAITING;
            break;
      case STATE_BETWEEN:
            UI_set_cursor(defaultcursor);
            sprintf(str, "After Level %d:\nScore: %d", level, score);
            UI_update_dialog(DIALOG_SCORE, str);
            UI_popup_dialog(DIALOG_SCORE);
            state = STATE_PLAYING;
            setup_level(++level);
            break;
      }
      UI_refresh();
      iteration++;
}

int
Game_score() {
      return score;
}

int
Game_level() {
      return level;
}

int
Game_screensize() {
      return screensize;
}

double
Game_scale(int dimensions) {
      double scale = (double)screensize / SCREENSIZE;
      double d = 1;
      for ( ; dimensions > 0; dimensions--)
            d *= scale;
      return (d);
}

/*
 * Note - don't use getopt, since it might reorder the args or do something
 * that the UI-specific argument parser doesn't like.
 */
static void
parse_args(int argc, char **argv) {
      char *s;
      char *endp;
      int i;

      for (i = 1; i < argc; i++) {
            if (strncasecmp(argv[i], "-l", 2) == 0) {
                  if (strlen(argv[i]) == 2 && i == argc - 1)
                        fatal("-l takes an argument");
                  if (strlen(argv[i]) > 2)
                        s = argv[i] + 2;
                  else
                        s = argv[++i];
                  level = strtol(s, &endp, 10);
                  if (*endp != '\0' || level <= 0)
                        fatal("invalid level '%s'", s);
            } else if (strcmp(argv[i], "--gui") == 0) {
                  if (i == argc - 1)
                        fatal("--gui takes an argument");
                  gui = argv[++i];
            } else if (strcmp(argv[i], "--size") == 0) {
                  if (i == argc - 1)
                        fatal("--size takes an argument");
                  s = argv[++i];
                  screensize = strtol(s, &endp, 10);
                  if (*endp != '\0' || screensize <= 0)
                        fatal("invalid screensize '%s'", s);
                  if (screensize < SCREENSIZE)
                        fatal("screensize must be larger than '%d'",
                               SCREENSIZE);
            } else if (strcmp(argv[1], "-v") == 0 ||
                     strcmp(argv[1], "--version") == 0)
            {
                  printf ("XBill version 2.1\n\n");
                  exit(0);
            } else if (strcmp(argv[1], "-h") == 0 ||
                     strcmp(argv[1], "--help") == 0)
            {
                  printf("XBill version 2.1\n");
                  printf("Options:\n");
                  printf("-l <n>\tStart at level n.\n");
                  printf("--gui <gui> \tUse a specific gui "
                         "(athena, motif, gtk)\n");
                  printf("--size <size>\t\tUse a larger playing area.\n");
                  printf("-v\t\tPrint version number and exit.\n");
                  printf("-h\t\tPrint help and exit.\n");
                  printf("All standard toolkit options are also ");
                  printf("supported.\n\n");
                  exit(0);
            }
      }
}

int
main(int argc, char **argv) {
      srand(time(NULL));
      parse_args(argc, argv);
      UI_initialize(gui, &argc, argv);
      UI_make_main_window(screensize);
      UI_graphics_init();
      UI_load_picture("logo", 0, &logo);
      UI_load_picture("icon", 0, &icon);
      UI_load_picture("about", 0, &about);
      draw_logo();
      UI_refresh();
      UI_make_dialogs(logo, icon, about);
      UI_set_icon(icon);

      Scorelist_read();
      Scorelist_update();

      UI_load_cursor("hand_up", CURSOR_SEP_MASK, &defaultcursor);
      UI_load_cursor("hand_down", CURSOR_SEP_MASK, &downcursor);
      UI_set_cursor(defaultcursor);

      Bill_load_pix();
      OS_load_pix();
      Computer_load_pix();
      Bucket_load_pix();
      Spark_load_pix();

      state = STATE_WAITING;
      if (level)
            Game_start(level);
      else
            UI_set_pausebutton(0);
      UI_main_loop();
      exit(0);
}

Generated by  Doxygen 1.6.0   Back to index