Beispiel #1
0
//--------- Begin of function NationArray::del_nation ---------//
//
// <int> recNo = the no. of the record to be deleted
//               (default : current record no.)
//
void NationArray::del_nation(int recNo)
{
	//-----------------------------------------//

	Nation* nationPtr = nation_array[recNo];       // operator[] will check for deleted nation error, can't use operator() because it use firm_array()->nation_recno

	nation_count--;

	if( nationPtr->nation_type == NATION_AI )
		ai_nation_count--;

	last_del_nation_date = info.game_date;

	//------ delete and linkout the nation ------//

	nationPtr->deinit();

	delete nationPtr;

	go(recNo);

	*( (Nation**) get() ) = NULL;   // Nullify the pointer
	linkout();

	//--- if the nation to be deleted is the player's nation ---//

	// ####### begin Gilbert 26/7 #########//
	if( recNo==player_recno )
	{
		player_ptr   = NULL;
		player_recno = 0;

		if( !sys.signal_exit_flag )
			sys.set_view_mode(MODE_NORMAL);		// set the view mode to normal mode to prevent possible problems
	}

	if( !sys.quick_exit_flag() )
	{
		//---------- update statistic ----------//
		update_statistic();		// as max_overall_nation_recno and others may be pointing to the deleted nation
	}
	// ####### end Gilbert 26/7 #########//
}
Beispiel #2
0
//--------- Begin of function NationArray::new_nation ---------//
//
// <int>  nationClassId		   = NATION_???, defined in ONATION2.H
// <int>  nationType  		   = NATION_OWN, NATION_AI, or NATION_REMOTE
// <int>  raceId      		   = id. of the race
// <int>  colorSchemeId 		= the color scheme id. of the nation
// [unsigned long] dpPlayerId = DirectPlayer player id. (only for multiplayer game)
//
//
// return : <int> nationRecno = the recno. of the newly added nation
//
int NationArray::new_nation(int nationClassId, int nationType, int raceId, int colorSchemeId, unsigned long dpPlayerId)
{
	//--------------------------------------------------------//

	int     nationRecno = create_nation(nationClassId);
	Nation* nationPtr   = nation_array[nationRecno];

	if( nationType == NATION_OWN )
	{
		player_ptr   = nationPtr;      // for ~nation_array to quick access
		player_recno = nationRecno;

		info.default_viewing_nation_recno = nationRecno;
		info.viewing_nation_recno = nationRecno;
	}

	//--- we must call init() after setting ai_type & nation_res_id ----//

	nationPtr->init(nationType, raceId, colorSchemeId, dpPlayerId);

	//--- store the colors of all nations into a single array for later fast access ---//

	nation_color_array[nationPtr->nation_recno] = nationPtr->nation_color;
	nation_power_color_array[nationPtr->nation_recno] = nationPtr->nation_color; 	// use a lighter color for the nation power area

	//-------------------------------------------//

	nation_count++;

	if( nationType == NATION_AI )
		ai_nation_count++;

	last_new_nation_date = info.game_date;

	//---------- update statistic ----------//

	update_statistic();

	return nationRecno;
}
Beispiel #3
0
//--------- Begin of function NationArray::next_month ---------//
//
void NationArray::next_month()
{
	int  i;
	Nation *nationPtr;

	LOG_MSG("begin NationArray::next_month");
	for( i=size() ; i>0 ; i-- )
	{
		nationPtr = (Nation*) get_ptr(i);

		if( nationPtr )    // nationPtr == NULL, if it's deleted
		{
			LOG_MSG(i);
			nationPtr->next_month();
			LOG_MSG(misc.get_random_seed() );
		}
	}
	LOG_MSG("end NationArray::next_month");

	//------- update statistic -----------//

	update_statistic();
}
Beispiel #4
0
//--------- Begin of function NationArray::new_nation ---------//
//
// used in creating human players in multi-player game
// return : <int> nationRecno = the recno. of the newly added nation
//
int NationArray::new_nation(NewNationPara& nationPara)
{
	err_when( info.game_date < last_del_nation_date + NEW_NATION_INTERVAL_DAYS );

	//--------------------------------------------------------//

	int nationClassId;

	if( nationPara.race_id > 0 )
		nationClassId = NATION_HUMAN;
	else
		nationClassId = NATION_MONSTER;

	int     nationRecno = create_nation(nationClassId);
	Nation* nationPtr   = nation_array[nationRecno];

	err_when( nationRecno != nationPara.nation_recno );
	err_when( !remote.is_enable() );

	char nationType =
		nationPara.dp_player_id == remote.self_player_id() ? NATION_OWN : NATION_REMOTE;

	if( nationType == NATION_OWN )
	{
		player_ptr   = nationPtr;      // for ~nation_array to quick access
		player_recno = nationRecno;

		info.default_viewing_nation_recno = nationRecno;
		info.viewing_nation_recno = nationRecno;
	}

	//--- we must call init() after setting ai_type & nation_res_id ----//

	nationPtr->init(nationType, nationPara.race_id, nationPara.color_scheme, nationPara.dp_player_id);

	if( nationPara.use_gem_stones )
	{
		nationPtr->init_cash( nationPara.use_gem_stones );
		game.total_gem_stones += nationPara.use_gem_stones;	// do not reset use_gemstones, as init_cash is called again in battle

		// update player profile
		if( nationPtr->is_own() )
		{
			player_profile.reload();
			if( player_profile.gem_stones >= nationPara.use_gem_stones )
				player_profile.gem_stones -= nationPara.use_gem_stones;
			else 
				player_profile.gem_stones = 0;
			player_profile.save();
		}
	}

	if( nationPara.ranking > game.max_ranking )
	{
		game.max_ranking = nationPara.ranking;
	}
	game.player_ranking[nationPtr->nation_recno-1] = nationPara.ranking;

	//--- store the colors of all nations into a single array for later fast access ---//

	nation_color_array[nationPtr->nation_recno] = nationPtr->nation_color;
	nation_power_color_array[nationPtr->nation_recno] = nationPtr->nation_color; 	// use a lighter color for the nation power area

	//-------------------------------------------//

	nation_count++;

	if( nationType == NATION_AI )
		ai_nation_count++;

	// ####### begin Gilbert 25/5 ##########//
	last_new_nation_date = info.game_date;
	// ####### end Gilbert 25/5 ##########//

	//---------- update statistic ----------//

	update_statistic();

	return nationRecno;
}
// Main test function. Locates the given magic pixel pattern on the screen, then
// runs one full latency test, sending input events and recording responses. On
// success, the results of the test are reported in the output parameters, and
// true is returned. If the test fails, the error parameter is filled in with
// an error message and false is returned.
bool measure_latency(
    const uint8_t magic_pattern[],
    double *out_key_down_latency_ms,
    double *out_scroll_latency_ms,
    double *out_max_js_pause_time_ms,
    double *out_max_css_pause_time_ms,
    double *out_max_scroll_pause_time_ms,
    char **error) {
  screenshot *screenshot = take_screenshot(0, 0, UINT32_MAX, UINT32_MAX);
  if (!screenshot) {
    *error = "Failed to take screenshot.";
    return false;
  }
  assert(screenshot->width > 0 && screenshot->height > 0);

  size_t x, y;
  bool found_pattern = find_pattern(magic_pattern, screenshot, &x, &y);
  free_screenshot(screenshot);
  if (!found_pattern) {
    *error = "Failed to find test pattern on screen.";
    return false;
  }
  uint8_t full_pattern[pattern_bytes];
  for (int i = 0; i < pattern_magic_bytes; i++) {
    full_pattern[i] = magic_pattern[i];
  }
  measurement_t measurement;
  measurement_t previous_measurement;
  memset(&measurement, 0, sizeof(measurement_t));
  memset(&previous_measurement, 0, sizeof(measurement_t));
  int screenshots = 0;
  bool first_screenshot_successful = read_data_from_screen((uint32_t)x,
      (uint32_t) y, magic_pattern, &measurement);
  if (!first_screenshot_successful) {
    *error = "Failed to read data from test pattern.";
    return false;
  }
  if (measurement.test_mode == TEST_MODE_NATIVE_REFERENCE) {
    uint8_t *test_pattern = (uint8_t *)malloc(pattern_bytes);
    memset(test_pattern, 0, pattern_bytes);
    for (int i = 0; i < pattern_magic_bytes; i++) {
      test_pattern[i] = rand();
    }
    if (!open_native_reference_window(test_pattern)) {
      *error = "Failed to open native reference window.";
      return false;
    }
    bool return_value = measure_latency(test_pattern, out_key_down_latency_ms, out_scroll_latency_ms, out_max_js_pause_time_ms, out_max_css_pause_time_ms, out_max_scroll_pause_time_ms, error);
    if (!close_native_reference_window()) {
      debug_log("Failed to close native reference window.");
    };
    return return_value;
  }
  int64_t start_time = measurement.screenshot_time;
  previous_measurement = measurement;
  statistic javascript_frames;
  statistic css_frames;
  statistic key_down_events;
  statistic scroll_stats;
  init_statistic("javascript_frames", &javascript_frames,
      measurement.javascript_frames, start_time);
  init_statistic("key_down_events", &key_down_events,
      measurement.key_down_events, start_time);
  init_statistic("css_frames", &css_frames, measurement.css_frames, start_time);
  init_statistic("scroll", &scroll_stats, measurement.scroll_position,
      start_time);
  int sent_events = 0;
  int scroll_x = x + 40;
  int scroll_y = y + 40;
  int64_t last_scroll_sent = start_time;
  if (measurement.test_mode == TEST_MODE_SCROLL_LATENCY) {
    send_scroll_down(scroll_x, scroll_y);
    scroll_stats.previous_change_time = get_nanoseconds();
  }
  while(true) {
    bool screenshot_successful = read_data_from_screen((uint32_t)x,
        (uint32_t) y, magic_pattern, &measurement);
    if (!screenshot_successful) {
      *error = "Test window moved during test. The test window must remain "
          "stationary and focused during the entire test.";
      return false;
    }
    if (measurement.test_mode == TEST_MODE_ABORT) {
      *error = "Test aborted.";
      return false;
    }
    screenshots++;
    int64_t screenshot_time = measurement.screenshot_time;
    int64_t previous_screenshot_time = previous_measurement.screenshot_time;
    debug_log("screenshot time %f",
        (screenshot_time - previous_screenshot_time) /
            (double)nanoseconds_per_millisecond);
    update_statistic(&javascript_frames, measurement.javascript_frames,
        screenshot_time, previous_screenshot_time);
    update_statistic(&key_down_events, measurement.key_down_events,
        screenshot_time, previous_screenshot_time);
    update_statistic(&css_frames, measurement.css_frames, screenshot_time,
        previous_screenshot_time);
    bool scroll_updated = update_statistic(&scroll_stats,
        measurement.scroll_position, screenshot_time, previous_screenshot_time);

    if (measurement.test_mode == TEST_MODE_JAVASCRIPT_LATENCY) {
      if (key_down_events.measurements >= latency_measurements_to_take) {
        break;
      }
      if (key_down_events.value_delta > sent_events) {
        *error = "More events received than sent! This is probably a bug in "
            "the test.";
        return false;
      }
      if (screenshot_time - key_down_events.previous_change_time >
          event_response_timeout_ms * nanoseconds_per_millisecond) {
        *error = "Browser did not respond to keyboard input. Make sure the "
            "test page remains focused for the entire test.";
        return false;
      }
      if (key_down_events.value_delta == sent_events) {
        // We want to avoid sending input events at a predictable time relative
        // to frames, so introduce a random delay of up to 1 frame (16.67 ms)
        // before sending the next event.
        usleep((rand() % 17) * 1000);
        if (!send_keystroke_z()) {
          *error = "Failed to send keystroke for \"Z\" key to test window.";
          return false;
        }
        key_down_events.previous_change_time = get_nanoseconds();
        sent_events++;
      }
    } else if (measurement.test_mode == TEST_MODE_SCROLL_LATENCY) {
        if (scroll_stats.measurements >= latency_measurements_to_take) {
          break;
        }
        if (screenshot_time - scroll_stats.previous_change_time >
            event_response_timeout_ms * nanoseconds_per_millisecond) {
          *error = "Browser did not respond to scroll events. Make sure the "
              "test page remains focused for the entire test.";
          return false;
        }
        if (scroll_updated) {
          // We saw the start of a scroll. Wait for the scroll animation to
          // finish before continuing. We assume the animation is finished if
          // it's been 100 milliseconds since we last saw the scroll position
          // change.
          int64_t scroll_update_time = screenshot_time;
          int64_t scroll_wait_start_time = screenshot_time;
          while (screenshot_time - scroll_update_time <
                 100 * nanoseconds_per_millisecond) {
            screenshot_successful = read_data_from_screen((uint32_t)x,
                (uint32_t) y, magic_pattern, &measurement);
            if (!screenshot_successful) {
              *error = "Test window moved during test. The test window must "
                  "remain stationary and focused during the entire test.";
              return false;
            }
            screenshot_time = measurement.screenshot_time;
            if (screenshot_time - scroll_wait_start_time >
                nanoseconds_per_second) {
              *error = "Browser kept scrolling for more than 1 second after a "
                  "single scrollwheel event.";
              return false;
            }
            if (measurement.scroll_position != scroll_stats.value) {
              scroll_stats.value = measurement.scroll_position;
              scroll_update_time = screenshot_time;
            }
          }
          // We want to avoid sending input events at a predictable time
          // relative to frames, so introduce a random delay of up to 1 frame
          // (16.67 ms) before sending the next event.
          usleep((rand() % 17) * 1000);
          send_scroll_down(scroll_x, scroll_y);
          scroll_stats.previous_change_time = get_nanoseconds();
        }
    } else if (measurement.test_mode == TEST_MODE_PAUSE_TIME) {
      // For the pause time test we want the browser to scroll continuously.
      // Send a scroll event every frame.
      if (screenshot_time - last_scroll_sent >
          17 * nanoseconds_per_millisecond) {
        send_scroll_down(scroll_x, scroll_y);
        last_scroll_sent = get_nanoseconds();
      }
    } else if (measurement.test_mode == TEST_MODE_PAUSE_TIME_TEST_FINISHED) {
      break;
    } else {
      *error = "Invalid test type. This is a bug in the test.";
      return false;
    }

    if (screenshot_time - start_time >
        test_timeout_ms * nanoseconds_per_millisecond) {
      *error = "Timeout.";
      return false;
    }
    previous_measurement = measurement;
    usleep(0);
  }
  // The latency we report is the midpoint of the interval given by the average
  // upper and lower bounds we've computed.
  *out_key_down_latency_ms =
      (upper_bound_ms(&key_down_events) + lower_bound_ms(&key_down_events)) / 2;
  *out_scroll_latency_ms =
      (upper_bound_ms(&scroll_stats) + lower_bound_ms(&scroll_stats) / 2);
  *out_max_js_pause_time_ms =
      javascript_frames.max_lower_bound / (double) nanoseconds_per_millisecond;
  *out_max_css_pause_time_ms =
      css_frames.max_lower_bound / (double) nanoseconds_per_millisecond;
  *out_max_scroll_pause_time_ms =
      scroll_stats.max_lower_bound / (double) nanoseconds_per_millisecond;
  debug_log("out_key_down_latency_ms: %f out_scroll_latency_ms: %f "
      "out_max_js_pause_time_ms: %f out_max_css_pause_time: %f\n "
      "out_max_scroll_pause_time_ms: %f",
      *out_key_down_latency_ms,
      *out_scroll_latency_ms,
      *out_max_js_pause_time_ms,
      *out_max_css_pause_time_ms,
      *out_max_scroll_pause_time_ms);
  return true;
}