Пример #1
0
int
get_liberties_board (unsigned short pos)
{
    if (!on_board (pos) || get_point_board (pos) == EMPTY)
    {
        return -1;
    }

    setup_marks ();

    int ret_val = 0;
    unsigned char orig_color = get_point_board (pos);

    empty_stack (&parse_stack);
    push_pos_stack (&parse_stack, pos);

    /* Since we only ever test for liberties in order to determine
       captures and the like, there's no reason to count any liberties
       higher than 2 (we sometimes need to know if something has 1 liberty
       for dealing with ko) */
    while (pop_pos_stack (&parse_stack, &pos) && ret_val < 2)
    {
        ret_val += get_liberties_helper (NORTH (pos), orig_color);
        ret_val += get_liberties_helper (SOUTH (pos), orig_color);
        ret_val += get_liberties_helper (EAST (pos), orig_color);
        ret_val += get_liberties_helper (WEST (pos), orig_color);
    }

    /* if there's more than two liberties, the stack isn't empty, so empty
       it */
    empty_stack (&parse_stack);

    return ret_val;
}
Пример #2
0
void gamemap::set_terrain(const map_location& loc, const t_translation::terrain_code & terrain, const terrain_type_data::merge_mode mode, bool replace_if_failed) {
	if(!on_board_with_border(loc)) {
		DBG_G << "set_terrain: " << loc << " is not on the map.\n";
		// off the map: ignore request
		return;
	}

	t_translation::terrain_code new_terrain = tdata_->merge_terrains(get_terrain(loc), terrain, mode, replace_if_failed);

	if(new_terrain == t_translation::NONE_TERRAIN) {
		return;
	}

	if(on_board(loc)) {
		const bool old_village = is_village(loc);
		const bool new_village = tdata_->is_village(new_terrain);

		if(old_village && !new_village) {
			villages_.erase(std::remove(villages_.begin(),villages_.end(),loc),villages_.end());
		} else if(!old_village && new_village) {
			villages_.push_back(loc);
		}
	}

	(*this)[loc] = new_terrain;
}
Пример #3
0
int
flood_fill_board (unsigned short pos, unsigned char color)
{
    if (!on_board (pos) || get_point_board (pos) == color)
    {
        return 0;
    }

    empty_stack (&parse_stack);

    int ret_val = 0;

    unsigned char orig_color = get_point_board (pos);

    set_point_board (pos, color);
    ++ret_val;
    push_pos_stack (&parse_stack, pos);

    while (pop_pos_stack (&parse_stack, &pos))
    {
        ret_val += flood_fill_helper (NORTH (pos), orig_color, color);
        ret_val += flood_fill_helper (SOUTH (pos), orig_color, color);
        ret_val += flood_fill_helper (EAST (pos), orig_color, color);
        ret_val += flood_fill_helper (WEST (pos), orig_color, color);
    }

    return ret_val;
}
Пример #4
0
unsigned short
WRAP (unsigned short pos)
{
    int x, y;
    if (on_board (pos))
    {
        return pos;
    }
    else
    {
        x = I (pos);
        y = J (pos);

        if (x < 0)
        {
            x = board_width - 1;
        }
        else if ((unsigned int) x >= board_width)
        {
            x = 0;
        }

        if (y < 0)
        {
            y = board_height - 1;
        }
        else if ((unsigned int) y >= board_height)
        {
            y = 0;
        }
        return POS (x, y);
    }
}
Пример #5
0
bool GoBoard::is_self_atari(int point, int color) //  is_self_atari that is , add this point, the group of the move will be in atari(only one liberty)
{
    std::queue<int> q;
    q.push(point);
    int lib = 0;
    int* visited = new int[board_size * board_size];
    int cur;

    while (!q.empty())
    {
        cur = q.front();
        visited[cur] = 1;
        q.pop();
        for (int k = 0; k < 4; ++k)
        {
            int ai = I(cur) + deltai[k];
            int aj = J(cur) + deltaj[k];
            if (on_board(ai, aj) && !visited[POS(ai, aj)])
            {
                if (get_board(ai, aj) == color)
                    q.push(POS(ai, aj));
                else if (get_board(ai, aj) == EMPTY)
                {
                    ++lib;
                    visited[POS(ai, aj)] = 1;
                }
            }

        }
    }
    delete []visited;
    return lib == 1;
}
Пример #6
0
void gamemap::set_terrain(const map_location& loc, const t_translation::t_terrain & terrain, const terrain_type_data::tmerge_mode mode, bool replace_if_failed) {
	if(!on_board_with_border(loc)) {
		// off the map: ignore request
		return;
	}

	t_translation::t_terrain new_terrain = tdata_->merge_terrains(get_terrain(loc), terrain, mode, replace_if_failed);

	if(new_terrain == t_translation::NONE_TERRAIN) {
		return;
	}

	if(on_board(loc)) {
		const bool old_village = is_village(loc);
		const bool new_village = tdata_->is_village(new_terrain);

		if(old_village && !new_village) {
			villages_.erase(std::remove(villages_.begin(),villages_.end(),loc),villages_.end());
		} else if(!old_village && new_village) {
			villages_.push_back(loc);
		}
	}

	tiles_[loc.x + border_size_][loc.y + border_size_] = new_terrain;

	// Update the off-map autogenerated tiles
	map_location adj[6];
	get_adjacent_tiles(loc,adj);

	for(int n = 0; n < 6; ++n) {
		remove_from_border_cache(adj[n]);
	}
}
Пример #7
0
void
move_display (unsigned short pos)
{
    if (!on_board (pos))
    {
        return;
    }

    while ((unsigned) I (pos) >= REAL_MAX_X)
    {
        cursor_pos = EAST (cursor_pos);
        cursor_updated ();
    }
    while ((unsigned) I (pos) < REAL_MIN_X)
    {
        cursor_pos = WEST (cursor_pos);
        cursor_updated ();
    }

    while ((unsigned) J (pos) >= REAL_MAX_Y)
    {
        cursor_pos = SOUTH (cursor_pos);
        cursor_updated ();
    }
    while ((unsigned) J (pos) < REAL_MIN_Y)
    {
        cursor_pos = NORTH (cursor_pos);
        cursor_updated ();
    }
}
Пример #8
0
static void
draw_hoshi (unsigned short pos)
{
    /* color and drawmode are already set before this function (all lines
       and hoshi and stuff are drawn together) */

    if (!on_board(pos))
    {
        return;
    }

    if ((unsigned) I (pos) < MIN_X ||
        (unsigned) I (pos) >= MAX_X ||
        (unsigned) J (pos) < MIN_Y ||
        (unsigned) J (pos) >= MAX_Y)
    {
        return;
    }
    if (intersection_size > 8)
    {
        rb->lcd_fillrect (pixel_x (pos) + LINE_OFFSET - 1,
                          pixel_y (pos) + LINE_OFFSET - 1, 3, 3);
    }
    else
    {
        rb->lcd_drawpixel (pixel_x (pos) + LINE_OFFSET - 1,
                           pixel_y (pos) + LINE_OFFSET - 1);
        rb->lcd_drawpixel (pixel_x (pos) + LINE_OFFSET + 1,
                           pixel_y (pos) + LINE_OFFSET + 1);
    }
}
Пример #9
0
bool
legal_move_board (unsigned short pos, unsigned char color, bool allow_suicide)
{
    /* you can always pass */
    if (pos == PASS_POS)
    {
        return true;
    }

    if (!on_board (pos) || (color != BLACK && color != WHITE))
    {
        return false;
    }

    if (pos == ko_pos && color == current_player)
    {
        return false;
    }

    if (get_point_board (pos) != EMPTY)
    {
        return false;
    }

    /* don't need to save the current state, because it's always empty
       since we tested for that above */
    set_point_board (pos, color);

    /* if we have liberties, it can't be illegal */
    if (get_liberties_board (pos) > 0 ||
        /* if we can capture something, it can't be illegal */
        (get_point_board (NORTH (pos)) == OTHER (color) &&
         !get_liberties_board (NORTH (pos))) ||
        (get_point_board (SOUTH (pos)) == OTHER (color) &&
         !get_liberties_board (SOUTH (pos))) ||
        (get_point_board (EAST (pos)) == OTHER (color) &&
         !get_liberties_board (EAST (pos))) ||
        (get_point_board (WEST (pos)) == OTHER (color) &&
         !get_liberties_board (WEST (pos))) ||
        /* if we're allowed to suicide, only multi-stone suicide is legal
           (no ruleset allows single-stone suicide that I know of) */
        (allow_suicide && (get_point_board (NORTH (pos)) == color ||
                           get_point_board (SOUTH (pos)) == color ||
                           get_point_board (EAST (pos)) == color ||
                           get_point_board (WEST (pos)) == color)))
    {
        /* undo our previous set */
        set_point_board (pos, EMPTY);
        return true;
    }
    else
    {
        /* undo our previous set */
        set_point_board (pos, EMPTY);
        return false;
    }
}
Пример #10
0
static void
draw_stone (unsigned short pos, bool black)
{
    if (!on_board (pos))
    {
        return;
    }

    draw_stone_raw (pixel_x (pos), pixel_y (pos), black);
}
Пример #11
0
int anything_near()
{
  int i;
  
  for (i = 1; i < MAX_MOBS; i++)
    if (game->mob[i].type != MOB_NONE && on_board(&game->mob[i]))
      return true;

  return false;
}
void cave_map_generator::set_terrain(map_location loc, t_translation::t_terrain t)
{
	if (on_board(loc)) {
		if (t == clear_ && (rand() % 1000) < village_density_) {
			t = village_;
		}

		t_translation::t_terrain& c = map_[loc.x + gamemap::default_border][loc.y + gamemap::default_border];
		if(c == clear_ || c == wall_ || c == village_) {
			c = t;
		}
	}
}
Пример #13
0
static int
flood_fill_helper (unsigned short pos, unsigned char orig_color,
                   unsigned char color)
{
    if (on_board (pos) && get_point_board (pos) == orig_color)
    {
        set_point_board (pos, color);
        push_pos_stack (&parse_stack, pos);
        return 1;
    }

    return 0;
}
Пример #14
0
/* Generate a move. */
static void
generate_move(int *i, int *j, int color)
{
  int moves[MAX_BOARD * MAX_BOARD];
  int num_moves = 0;
  int move;
  int ai, aj;
  int k;

  memset(moves, 0, sizeof(moves));
  for (ai = 0; ai < board_size; ai++)
    for (aj = 0; aj < board_size; aj++) {
      /* Consider moving at (ai, aj) if it is legal and not suicide. */
      if (legal_move(ai, aj, color)
	  && !suicide(ai, aj, color)) {
	/* Further require the move not to be suicide for the opponent... */
	if (!suicide(ai, aj, OTHER_COLOR(color)))
	  moves[num_moves++] = POS(ai, aj);
	else {
	  /* ...however, if the move captures at least one stone,
           * consider it anyway.
	   */
	  for (k = 0; k < 4; k++) {
	    int bi = ai + deltai[k];
	    int bj = aj + deltaj[k];
	    if (on_board(bi, bj) && get_board(bi, bj) == OTHER_COLOR(color)) {
	      moves[num_moves++] = POS(ai, aj);
	      break;
	    }
	  }
	}
      }
    }

  /* Choose one of the considered moves randomly with uniform
   * distribution. (Strictly speaking the moves with smaller 1D
   * coordinates tend to have a very slightly higher probability to be
   * chosen, but for all practical purposes we get a uniform
   * distribution.)
   */
  if (num_moves > 0) {
    move = moves[xor_randn(num_moves)];
    *i = I(move);
    *j = J(move);
  }
  else {
    /* But pass if no move was considered. */
    *i = -1;
    *j = -1;
  }
}
Пример #15
0
static int
legal_move(int i, int j, int color)
{
  int other = OTHER_COLOR(color);
  
  /* Pass is always legal. */
  if (pass_move(i, j))
    return 1;

  /* Already occupied. */
  if (get_board(i, j) != EMPTY)
    return 0;

  /* Illegal ko recapture. It is not illegal to fill the ko so we must
   * check the color of at least one neighbor.
   */
  if (i == ko_i && j == ko_j
      && ((on_board(i - 1, j) && get_board(i - 1, j) == other)
	  || (on_board(i + 1, j) && get_board(i + 1, j) == other)))
    return 0;

  return 1;
}
void cave_map_generator::build_chamber(map_location loc, std::set<map_location>& locs, size_t size, size_t jagged)
{
	if(size == 0 || locs.count(loc) != 0 || !on_board(loc))
		return;

	locs.insert(loc);

	map_location adj[6];
	get_adjacent_tiles(loc,adj);
	for(size_t n = 0; n != 6; ++n) {
		if((rand() % 100) < (100l - static_cast<long>(jagged))) {
			build_chamber(adj[n],locs,size-1,jagged);
		}
	}
}
Пример #17
0
/* Compute final status. This function is only valid to call in a
 * position where generate_move() would return pass for at least one
 * color.
 *
 * Due to the nature of the move generation algorithm, the final
 * status of stones can be determined by a very simple algorithm:
 *
 * 1. Stones with two or more liberties are alive with territory.
 * 2. Stones in atari are dead.
 *
 * Moreover alive stones are unconditionally alive even if the
 * opponent is allowed an arbitrary number of consecutive moves.
 * Similarly dead stones cannot be brought alive even by an arbitrary
 * number of consecutive moves.
 *
 * Seki is not an option. The move generation algorithm would never
 * leave a seki on the board.
 *
 * Comment: This algorithm doesn't work properly if the game ends with
 *          an unfilled ko. If three passes are required for game end,
 *          that will not happen.
 */
static void
compute_final_status(void)
{
  int i, j;
  int pos;
  int k;

  for (pos = 0; pos < board_size * board_size; pos++)
    final_status[pos] = UNKNOWN;
  
  for (i = 0; i < board_size; i++)
    for (j = 0; j < board_size; j++)
      if (get_board(i, j) == EMPTY)
	for (k = 0; k < 4; k++) {
	  int ai = i + deltai[k];
	  int aj = j + deltaj[k];
	  if (!on_board(ai, aj))
	    continue;
	  /* When the game is finished, we know for sure that (ai, aj)
           * contains a stone. The move generation algorithm would
           * never leave two adjacent empty vertices. Check the number
           * of liberties to decide its status, unless it's known
           * already.
	   *
	   * If we should be called in a non-final position, just make
	   * sure we don't call set_final_status_string() on an empty
	   * vertex.
	   */
	  pos = POS(ai, aj);
	  if (final_status[pos] == UNKNOWN) {
	    if (get_board(ai, aj) != EMPTY) {
	      if (has_additional_liberty(ai, aj, i, j))
		set_final_status_string(pos, ALIVE);
	      else
		set_final_status_string(pos, DEAD);
	    }
	  }
	  /* Set the final status of the (i, j) vertex to either black
           * or white territory.
	   */
	  if (final_status[POS(i, j)] == UNKNOWN) {
	    if ((final_status[pos] == ALIVE) ^ (get_board(ai, aj) == WHITE))
	      final_status[POS(i, j)] = BLACK_TERRITORY;
	    else
	      final_status[POS(i, j)] = WHITE_TERRITORY;
	  }
	}
}
Пример #18
0
void
set_mark_display (unsigned short pos, unsigned char mark_char)
{
    if (!on_board (pos))
    {
        return;
    }

    if ((mark_char == 'b' || mark_char == 'w') &&
        display_marks[I (pos) + J (pos) * board_width] != ' ')
    {
        /* don't overwrite real board marks with last-move or variation
           marks */
        return;
    }

    display_marks[I (pos) + J (pos) * board_width] = mark_char;
}
Пример #19
0
std::string gamemap::write() const
{
	// Convert the starting positions to a map
	std::map<int, t_translation::coordinate> starting_positions;
	for (int i = 0; i < MAX_PLAYERS + 1; ++i)
	{
		if (!on_board(startingPositions_[i])) continue;
		t_translation::coordinate position(
				  startingPositions_[i].x + border_size_
				, startingPositions_[i].y + border_size_);
		starting_positions[i] = position;
	}

	// Let the low level converter do the conversion
	std::ostringstream s;
	s << t_translation::write_game_map(tiles_, starting_positions)
		<< "\n";
	return s.str();
}
Пример #20
0
static void
draw_cursor (unsigned short pos)
{
    if (!on_board (pos))
    {
        return;
    }

#if LCD_DEPTH > 1
    rb->lcd_set_foreground (CURSOR_COLOR);
#else
    rb->lcd_set_drawmode (DRMODE_COMPLEMENT);
#endif

    rb->lcd_drawrect (pixel_x (pos),
                      pixel_y (pos), intersection_size, intersection_size);

    rb->lcd_set_drawmode (DRMODE_SOLID);
}
Пример #21
0
std::string gamemap::write() const
{
	std::map<int, t_translation::coordinate> starting_positions = std::map<int, t_translation::coordinate>();

	// Convert the starting positions to a map
	for(int i = 0; i < MAX_PLAYERS+1; ++i) {
	if(on_board(startingPositions_[i])) {
			const struct t_translation::coordinate position =
				{startingPositions_[i].x + border_size_, startingPositions_[i].y + border_size_};

			 starting_positions.insert(std::pair<int, t_translation::coordinate>(i, position));
		}
	}

	// Let the low level convertor do the conversion
	const std::string& data = t_translation::write_game_map(tiles_, starting_positions);
	const std::string& header = "border_size=" + lexical_cast<std::string>(border_size_)
		+ "\nusage=" + (usage_ == IS_MAP ? "map" : "mask");
	return header + "\n\n" + data;
}
Пример #22
0
static int
get_liberties_helper (unsigned short pos, unsigned char orig_color)
{
    if (on_board (pos) &&
        get_point_board (pos) != OTHER (orig_color) && !is_marked (pos))
    {
        make_mark (pos);

        if (get_point_board (pos) == EMPTY)
        {
            return 1;
        }
        else
        {
            push_pos_stack (&parse_stack, pos);
        }
    }

    return 0;
}
Пример #23
0
/* Does the string at (i, j) have any more liberty than the one at
 * (libi, libj)?
 */
static int
has_additional_liberty(int i, int j, int libi, int libj)
{
  int pos = POS(i, j);
  do {
    int ai = I(pos);
    int aj = J(pos);
    int k;
    for (k = 0; k < 4; k++) {
      int bi = ai + deltai[k];
      int bj = aj + deltaj[k];
      if (on_board(bi, bj) && get_board(bi, bj) == EMPTY
	  && (bi != libi || bj != libj))
	return 1;
    }

    pos = next_stone[pos];
  } while (pos != POS(i, j));

  return 0;
}
Пример #24
0
/* Does (ai, aj) provide a liberty for a stone at (i, j)? */
static int
provides_liberty(int ai, int aj, int i, int j, int color)
{
  /* A vertex off the board does not provide a liberty. */
  if (!on_board(ai, aj))
    return 0;

  /* An empty vertex IS a liberty. */
  if (get_board(ai, aj) == EMPTY)
    return 1;

  /* A friendly string provides a liberty to (i, j) if it currently
   * has more liberties than the one at (i, j).
   */
  if (get_board(ai, aj) == color)
    return has_additional_liberty(ai, aj, i, j);

  /* An unfriendly string provides a liberty if and only if it is
   * captured, i.e. if it currently only has the liberty at (i, j).
   */
  return !has_additional_liberty(ai, aj, i, j);
}
Пример #25
0
bool GoBoard::is_virtual_eye(int point, int color)
{
    if (!is_surrounded(point, color)) return false;
    int nopponent = 0;
    int ai = I(point);
    int aj = J(point);
    bool at_edge = false;
    for (int i = 0; i < 4; i++) {
        int bi = ai + diag_i[i];
        int bj = aj + diag_j[i];
        if (!on_board(bi,bj))
        {
            at_edge = true;
            continue;
        }
        if( get_board(bi,bj) == OTHER_COLOR(color) ) {
            nopponent++;
        }
    }
    if(at_edge)
        ++nopponent;
    return nopponent < 2;
}
Пример #26
0
	bool is_keep(const map_location& loc) const
		{ return on_board(loc) && is_keep(get_terrain(loc)); }
Пример #27
0
	int gives_healing(const map_location& loc) const
		{ return on_board(loc) ?  gives_healing(get_terrain(loc)) : 0; }
Пример #28
0
bool gamemap::is_castle(const map_location& loc) const
	{ return on_board(loc) && is_castle(get_terrain(loc)); }
Пример #29
0
	bool is_village(const map_location& loc) const
		{ return on_board(loc) && is_village(get_terrain(loc)); }
Пример #30
0
t_translation::t_terrain gamemap::get_terrain(const map_location& loc) const
{

	if(on_board_with_border(loc)) {
		return tiles_[loc.x + border_size_][loc.y + border_size_];
	}

	if ( loc == map_location::null_location() ) {
		return t_translation::NONE_TERRAIN;
	}

	const std::map<map_location, t_translation::t_terrain>::const_iterator itor = borderCache_.find(loc);
	if(itor != borderCache_.end())
		return itor->second;

	// If not on the board, decide based on what surrounding terrain is
	t_translation::t_terrain items[6];
	int number_of_items = 0;

	map_location adj[6];
	get_adjacent_tiles(loc,adj);
	for(int n = 0; n != 6; ++n) {
		if(on_board(adj[n])) {
			items[number_of_items] = tiles_[adj[n].x][adj[n].y];
			++number_of_items;
		} else {
			// If the terrain is off map but already in the border cache,
			// this will be used to determine the terrain.
			// This avoids glitches
			// * on map with an even width in the top right corner
			// * on map with an odd height in the bottom left corner.
			// It might also change the result on other map and become random,
			// but the border tiles will be determined in the future, so then
			// this will no longer be used in the game
			// (The editor will use this feature to expand maps in a better way).
			std::map<map_location, t_translation::t_terrain>::const_iterator itor =
				borderCache_.find(adj[n]);

			// Only add if it is in the cache and a valid terrain
			if(itor != borderCache_.end() &&
					itor->second != t_translation::NONE_TERRAIN)  {

				items[number_of_items] = itor->second;
				++number_of_items;
			}
		}

	}

	// Count all the terrain types found,
	// and see which one is the most common, and use it.
	t_translation::t_terrain used_terrain;
	int terrain_count = 0;
	for(int i = 0; i != number_of_items; ++i) {
		if(items[i] != used_terrain && !tdata_->is_village(items[i]) && !tdata_->is_keep(items[i])) {
			const int c = std::count(items+i+1,items+number_of_items,items[i]) + 1;
			if(c > terrain_count) {
				used_terrain = items[i];
				terrain_count = c;
			}
		}
	}

	borderCache_.insert(std::pair<map_location, t_translation::t_terrain>(loc,used_terrain));
	return used_terrain;

}