Exemple #1
0
void get_bishop_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Pos curr;
	curr.col = piece.col + 1;
	curr.row = piece.row + 1;
	while (is_valid_pos(curr)){
		if (is_valid_dest(board, player, curr) == 1 || is_valid_dest(board, player, curr) == 2) add_move(piece, curr, 0);
		if (is_valid_dest(board, player, curr) == 0 || is_valid_dest(board, player, curr) == 2) break;
		curr.col++, curr.row++;
	}
	curr.col = piece.col - 1;
	curr.row = piece.row - 1;
	while (is_valid_pos(curr)){
		if (is_valid_dest(board, player, curr) == 1 || is_valid_dest(board, player, curr) == 2) add_move(piece, curr, 0);
		if (is_valid_dest(board, player, curr) == 0 || is_valid_dest(board, player, curr) == 2) break;
		curr.col--, curr.row--;
	}
	curr.col = piece.col - 1;
	curr.row = piece.row + 1;
	while (is_valid_pos(curr)){
		if (is_valid_dest(board, player, curr) == 1 || is_valid_dest(board, player, curr) == 2) add_move(piece, curr, 0);
		if (is_valid_dest(board, player, curr) == 0 || is_valid_dest(board, player, curr) == 2) break;
		curr.col--, curr.row++;
	}
	curr.col = piece.col + 1;
	curr.row = piece.row - 1;
	while (is_valid_pos(curr)){
		if (is_valid_dest(board, player, curr) == 1 || is_valid_dest(board, player, curr) == 2) add_move(piece, curr, 0);
		if (is_valid_dest(board, player, curr) == 0 || is_valid_dest(board, player, curr) == 2) break;
		curr.col++, curr.row--;
	}
}
int get_capture_moves(Pos start, Pos piece, char board[BOARD_SIZE][BOARD_SIZE], COLOR player, int count, Pos* dests){
	Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } };
	int found_now = 0, found_ahead;
	for (int p = 0; p < 4; p++)
		if (is_valid_pos(pos[p]) && is_opposite(player, board[pos[p].col][pos[p].row])){
			Pos new_piece = get_next_diag(piece, pos[p]);
			if (is_valid_pos(new_piece) && board[new_piece.col][new_piece.row] == EMPTY){
				found_now++;
				char tmp = board[pos[p].col][pos[p].row];
				board[pos[p].col][pos[p].row] = EMPTY;
				Pos* new_dests = malloc(sizeof(Pos) * (count + 1));
				for (int i = 0; i < count; i++){
					new_dests[i].row = dests[i].row;
					new_dests[i].col = dests[i].col;
				}
				new_dests[count].row = new_piece.row;
				new_dests[count].col = new_piece.col;
				found_ahead = get_capture_moves(start, new_piece, board, player, count + 1, new_dests);
				if (found_ahead == 0){
					add_move(start, new_dests, count + 1);
					free(new_dests);
				}
				board[pos[p].row][pos[p].col] = tmp;
			}
		}
	return found_now;
}
Exemple #3
0
// finds all moves of a single king piece
void get_king_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } };
	Pos curr, new_piece;
	int found_ahead = -1;

	for (int p = 0; p < 4; p++){
		curr = pos[p];
		while (is_valid_pos(curr) && board[curr.col][curr.row] == EMPTY){
			add_move(piece, &curr, 0);
			curr = get_next_diag(piece, curr);
		}
		if (is_valid_pos(curr) && is_opposite(player, board[curr.col][curr.row])){
			char tmp = board[curr.col][curr.row];
			board[curr.col][curr.row] = EMPTY;
			board[piece.col][piece.row] = EMPTY;
			new_piece = get_next_diag(piece, curr);
			if (is_valid_pos(new_piece) && board[new_piece.col][new_piece.row] == EMPTY){
				found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece);
				if (found_ahead == 0) add_move(piece, &new_piece, 1);
			}
			board[curr.col][curr.row] = tmp;
			board[piece.col][piece.row] = curr_piece;
		}
	}
}
void get_king_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Move* res = NULL;
	Move* res_head = res;
	Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } };
	Pos curr;
	int found_ahead;

	for (int p = 0; p < 4; p++){
		curr = pos[p];
		while (is_valid_pos(curr) && board[curr.col][curr.row] == EMPTY){
			add_move(piece, &curr, 1);
			curr = get_next_diag(piece, curr);
			// BUG - once dests_num == 1 and |dest-start| != 1 add_moves thinks its 1 capture and not a simple move..
		}
		if (is_valid_pos(curr) && is_opposite(player, board[curr.col][curr.row])){
			char tmp = board[curr.row][curr.col];
			board[curr.row][curr.col] = EMPTY;
			Pos new_piece = get_next_diag(piece, curr);
			if (is_valid_pos(new_piece) && board[new_piece.row][new_piece.col] == EMPTY){
				found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece);
				if (found_ahead == 0) add_move(piece, &new_piece, 1);
			}
			board[curr.row][curr.col] = tmp;
		}
	}
}
Exemple #5
0
static void
place_in_initial_fall (struct anim *g)
{
  struct pos pmt, pmtf, pmtb;
  struct pos fall_pos;

  int dirf = (g->f.dir == LEFT) ? -1 : +1;
  int dirb = (g->f.dir == LEFT) ? +1 : -1;
  survey (_mt, pos, &g->f, NULL, &pmt, NULL);
  prel (&pmt, &pmtf, +0, dirf);
  prel (&pmt, &pmtb, +0, dirb);

  invalid_pos (&fall_pos);

  if (is_strictly_traversable (&pmt)) fall_pos = pmt;
  else if (is_strictly_traversable (&pmtf)) fall_pos = pmtf;
  else if (is_strictly_traversable (&pmtb)) fall_pos = pmtb;

  struct frameset *frameset = get_guard_fall_frameset (g->type);

  if (is_valid_pos (&fall_pos))
    place_frame (&g->f, &g->f, frameset[0].frame,
                 &fall_pos,
                 (g->f.dir == LEFT) ? PLACE_WIDTH - 12 : +6,
                 (g->f.dir == LEFT) ? 23 : 27);
}
Exemple #6
0
bool
peq (struct pos *p0, struct pos *p1)
{
  struct pos np0, np1;

  if (! is_valid_pos (p0) || ! is_valid_pos (p1))
    return false;

  npos (p0, &np0);
  npos (p1, &np1);

  return
    /* np0.l == np1.l && */
    np0.room == np1.room
    && np0.floor == np1.floor
    && np0.place == np1.place;
}
void get_man_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Move* res = NULL;
	Move* res_head = res;
	Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } };
	int direction = 1, found_ahead;
	if (player == BLACK) direction = -1;

	for (int p = 0; p < 4; p++){
		if (is_valid_pos(pos[p]) && pos[p].row == piece.row + direction && board[pos[p].col][pos[p].row] == EMPTY) add_move(piece, &pos[p], 1);
		else if (is_valid_pos(pos[p]) && is_opposite(player, board[pos[p].col][pos[p].row])){
			char tmp = board[pos[p].row][pos[p].col];
			board[pos[p].row][pos[p].col] = EMPTY;
			Pos new_piece = get_next_diag(piece, pos[p]);
			if (is_valid_pos(new_piece) && board[new_piece.row][new_piece.col] == EMPTY){
				found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece);
				if (found_ahead == 0) add_move(piece, &new_piece, 1);
			}
			board[pos[p].row][pos[p].col] = tmp;
		}
	}
}
Exemple #8
0
void set_cell(board_t* board, player_t player, pos_t pos)
{
  assert(NULL != board);

  assert(is_valid_pos(pos));

  assert(is_valid_board(board));

  // make sure the given cell is empty
  assert(EMPTY == get_cell(board, pos));

  board->b[player][pos.y] = set(board->b[player][pos.y], trans_x(pos.x));
}
Exemple #9
0
void get_pawn_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	int direction = board[piece.col][piece.row] == BLACK_P ? -1 : 1;
	int pawn_row = board[piece.col][piece.row] == BLACK_P ? 6 : 1;

	Pos dest;
	dest.col = piece.col;
	dest.row = piece.row + direction;

	if (is_valid_pos(dest)){
		if (board[dest.col][dest.row] == EMPTY){
			add_move(piece, dest, 0);
			if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player));
		}
	}
	if (piece.row == pawn_row){
		dest.row = piece.row + (2 * direction);
		if (is_valid_pos(dest)){
			if (board[dest.col][dest.row] == EMPTY && board[piece.col][piece.row + direction] == EMPTY) add_move(piece, dest, 0);
		}
	}
	dest.col = piece.col + 1;
	dest.row = piece.row + direction;
	if (is_valid_pos(dest)){
		if (is_opposite(player, board[dest.col][dest.row])){
			add_move(piece, dest, 0);
			if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player));
		}
	}
	dest.col = piece.col - 1;
	if (is_valid_pos(dest)){
		if (is_opposite(player, board[dest.col][dest.row])){
			add_move(piece, dest, 0);
			if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player));
		}
	}
}
Exemple #10
0
void set_cell_state(board_t* board, pos_t pos, cell_t new_state)
{
  assert(NULL != board);
  
  assert(is_valid_board(board));

  assert(is_valid_pos(pos));


  /* // this assertion is tentative, it may prove too strict */
  /* // it relies on the caller checking the state of this cell */
  /* // before trying to change it */
  /* const cell_t old_state = get_cell(board, pos); */
  /* assert(new_state != old_state); */

  
  row* white_col = &board->b[W][pos.y];
  row* black_col = &board->b[B][pos.y];


  switch (new_state)
    {
    case WHITE:
      *black_col = unset(*black_col, trans_x(pos.x));
      *white_col = set(*white_col, trans_x(pos.x));
      break;

    case BLACK:
      *white_col = unset(*white_col, trans_x(pos.x));
      *black_col = set(*black_col, trans_x(pos.x));
      break;

    case EMPTY:
      // deactivate the bit representing the cell at _pos_
      // we apply the macro to both columns because we don't
      // know to which player it belongs

      *white_col = unset(*white_col, trans_x(pos.x));
      *black_col = unset(*black_col, trans_x(pos.x));
    }


  // make sure we didn't corrupt the board in the process of
  // updating the cell
  assert(is_valid_board(board));
}
Exemple #11
0
void get_moves_by_piece(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Pos* tmp_dests;
	switch (board[piece.col][piece.row]){
	case WHITE_B: case BLACK_B:
		get_bishop_moves(board, player, piece);
		return;
	case WHITE_R: case BLACK_R:
		get_rook_moves(board, player, piece);
		return;
	case WHITE_Q: case BLACK_Q:
		get_bishop_moves(board, player, piece);
		get_rook_moves(board, player, piece);
		return;
	case BLACK_P: case WHITE_P:
		get_pawn_moves(board, player, piece);
		return;
	case WHITE_K: case BLACK_K:
		tmp_dests = (Pos[8]) { { piece.col - 1, piece.row - 1 }, { piece.col - 1, piece.row }, { piece.col - 1, piece.row + 1 },
		{ piece.col + 1, piece.row - 1 }, { piece.col + 1, piece.row }, { piece.col + 1, piece.row + 1 },
		{ piece.col, piece.row - 1 }, { piece.col, piece.row + 1 }
		};
		break;
	case WHITE_N: case BLACK_N:
		tmp_dests = (Pos[8]) { { piece.col - 2, piece.row - 1 }, { piece.col - 2, piece.row + 1 },
		{ piece.col + 2, piece.row - 1 }, { piece.col + 2, piece.row + 1 },
		{ piece.col - 1, piece.row - 2 }, { piece.col + 1, piece.row - 2 },
		{ piece.col - 1, piece.row + 2 }, { piece.col + 1, piece.row + 2 }};
		break;
	default: return;
	}
	for (int i = 0; i < 8; i++){
		if (is_valid_pos(tmp_dests[i])){
			if (board[tmp_dests[i].col][tmp_dests[i].row] == EMPTY || is_opposite(player, board[tmp_dests[i].col][tmp_dests[i].row])){
				add_move(piece, tmp_dests[i], 0);
			}
		}
	}
	return;
}
Exemple #12
0
int n_neighbors(const board_t* board, pos_t pos, player_t player)
{
  assert(NULL != board);
  assert(is_valid_pos(pos));

  // TODO figure out the best way to introduce an offset


  const cell_t cell_content = get_cell(board, pos);

  // make sure the cell's occupied
  assert(W == player || B == player);

  
  // bit pattern to find the cell's active neighbors
  const row pattern = (1 | 2 | 4) << pos.x;


  // begin by -1 to prevent this cell from being counted
  // FIXME converting a cell_t to a player_t might be a bad idea, no?
  int n_neighbors = player == (player_t) cell_content ? -1 : 0;

  // count the neighbors in the three rows closest to the cell
  for (size_t i = max(0, pos.y - 1); i <= min(ROWS - 1, pos.y + 1); i++)
    {
      row neighbors = pattern & board->b[player][i];

      // count 1 bits (that is, neighbors)
      for (; neighbors; neighbors >>= 1)
	{
	  n_neighbors += neighbors & 1;
	}
    }

  assert(n_neighbors >= 0);

  return n_neighbors;
}
Exemple #13
0
void
draw_multi_rooms (void)
{
  int x, y;

  mr_map_rooms ();

  if (anim_cycle == 0) {
    generate_wall_colors_for_room (0, room0_wall_color);
  }

  if (em == PALACE && vm == VGA
      && (has_mr_view_changed ()
          || em != mr.last.em
          || vm != mr.last.vm))
    generate_wall_colors ();

  if (has_mr_view_changed ()) {
    generate_stars ();
    generate_mirrors_reflex ();
  }

  if (mouse_pos.room != mr.last.mouse_pos.room
      || mouse_pos.floor != mr.last.mouse_pos.floor
      || mouse_pos.place != mr.last.mouse_pos.place) {
    if (is_valid_pos (&mouse_pos))
      update_cache_pos (&mouse_pos, em, vm);
    if (is_valid_pos (&mr.last.mouse_pos))
      update_cache_pos (&mr.last.mouse_pos, em, vm);
  }

  if (anim_cycle == 0
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue) {
    update_room0_cache (em, vm);
  }

  if (anim_cycle == 0
      || has_mr_view_changed ()
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue
      || level.number != mr.last.level) {
    update_cache (em, vm);
  }

  size_t i;
  for (i = 0; i < changed_pos_nmemb; i++) {
    /* printf ("%i,%i,%i\n", changed_pos[i].room, changed_pos[i].floor, changed_pos[i].place); */
    update_cache_pos (&changed_pos[i], em, vm);
  }
  destroy_array ((void **) &changed_pos, &changed_pos_nmemb);

  clear_bitmap (screen, BLACK);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_background (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  if (! no_room_drawing) draw_bitmap (cache, screen, 0, 0, 0);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_foreground (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  if (mr.select_cycles > 0) {
    al_hold_bitmap_drawing (false);

    int x0 = ORIGINAL_WIDTH * mr.x;
    int y0 = ROOM_HEIGHT * mr.y + 3;
    int x1 = x0 + ORIGINAL_WIDTH;
    int y1 = y0 + ROOM_HEIGHT;
    draw_rectangle (screen, x0, y0, x1, y1, RED, 1);

    mr.select_cycles--;
  }

  mr.dx = mr.dy = -1;

  mr_update_last_settings ();
}
Exemple #14
0
// manages the users turn, game state user input loop
int user_turn(char board[BOARD_SIZE][BOARD_SIZE], COLOR color){
	get_all_moves(board, color);
	if (moves_head == NULL) return WIN_POS;
	char *word1;
	char *command = NULL;
	Move* new_move = NULL;
	int ret_val;
	while (1){
		printf(ENTER_YOUR_MOVE);
		if (new_move != NULL) clear_old_moves(new_move);
		new_move = malloc(sizeof(Move));
		new_move->dest = malloc(sizeof(Pos) * 2 * BOARD_SIZE);
		new_move->next = NULL;
		if (command != NULL) free(command);
		command = input2str(stdin);
		word1 = strtok(command, " ");
		if (strcmp(word1, "quit") == 0){
			ret_val = QUIT;
			break;
		}
		else if (strcmp(word1, "get_moves") == 0){
			print_moves(moves_head);
			continue;
		}
		else if (strcmp(word1, "move") == 0){
			char * piece_coor1 = strtok(NULL, " <,>");
			char * piece_coor2 = strtok(NULL, " <,>");
			new_move->piece.col = piece_coor1[0] - 'a';
			new_move->piece.row = atoi(piece_coor2) - 1;
			if (!is_valid_pos(new_move->piece)){
				printf(WRONG_POSITION);
				continue;
			}
			int i = 0;
			char * dest_coor1 = strtok(NULL, " <,>to");
			char * dest_coor2 = strtok(NULL, " <,>to");
			while (dest_coor1 != NULL){
				new_move->dest[i].col = dest_coor1[0] - 'a';
				new_move->dest[i].row = atoi(dest_coor2) - 1;
				if (!is_valid_pos(new_move->dest[i])){
					i = -1;
					break;
				}
				i++;
				dest_coor1 = strtok(NULL, " <,>[]");
				if (dest_coor1 != NULL) dest_coor2 = strtok(NULL, " <,>[]");
			}
			if (i == -1){
				printf(WRONG_POSITION);
				continue;
			}
			if (!is_valid_piece(board, new_move, color)){
				printf(NO_DISC);
				continue;
			}
			new_move->dest = realloc(new_move->dest, sizeof(Pos) * i);
			new_move->captures = i;
			Move * move2do = is_valid_move(moves_head, new_move);
			if (move2do == NULL){
				printf(ILLEGAL_MOVE);
				continue;
			}
			else{
				exc_move(board, move2do);
				print_board(board);
				ret_val = GAME_ON;
				break;
			}
		}
		else printf(ILLEGAL_COMMAND);
	}
	free(command);
	clear_old_moves(new_move);
	clear_old_moves(moves_head);
	return ret_val;
}
Exemple #15
0
void
draw_multi_rooms (void)
{
  int x, y;

  mr_set_origin (mr.room, mr.x, mr.y);

  bool mr_full_update = has_mr_view_changed ()
    || mr.full_update;

  if (mr_full_update) {
    mr_busy ();
    force_full_redraw = true;
  }

  if (anim_cycle == 0) {
    generate_wall_colors_for_room (0, room0_wall_color);
  }

  if (em == PALACE && vm == VGA
      && (mr_full_update
          || em != mr.last.em
          || vm != mr.last.vm))
    generate_wall_colors ();

  if (mouse_pos.room != mr.last.mouse_pos.room
      || mouse_pos.floor != mr.last.mouse_pos.floor
      || mouse_pos.place != mr.last.mouse_pos.place) {
    if (is_valid_pos (&mouse_pos))
      register_changed_pos (&mouse_pos);

    if (is_valid_pos (&mr.last.mouse_pos))
      register_changed_pos (&mr.last.mouse_pos);
  }

  if (anim_cycle == 0
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue) {
    update_room0_cache (em, vm);
    force_full_redraw = true;
  }

  size_t i;

  if (anim_cycle == 0
      || mr_full_update
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue
      || global_level.n != mr.last.level) {
    update_cache (em, vm);
  } else {
    bool depedv =
      ((em == DUNGEON && vm == VGA)
       || (em == DUNGEON && vm == EGA)
       || (em == PALACE && vm == EGA));

    /* optmize changed pos list */
    optimize_changed_pos ();

    /* update cache pos */
    for (i = 0; i < changed_pos_nmemb; i++) {
      update_cache_pos (&changed_pos[i], em, vm);
      struct pos pl; prel (&changed_pos[i], &pl, +0, -1);
      if (depedv && fake (&pl) == WALL)
        update_cache_pos (&pl, em, vm);
    }

    /* update cache room */
    for (i = 0; i < changed_room_nmemb; i++)
      update_cache_room (changed_room[i], em, vm);

    /* kept together so update_cache_pos and update_cache_room can
       access each other's arrays */
    destroy_array ((void **) &changed_pos, &changed_pos_nmemb);
    destroy_array ((void **) &changed_room, &changed_room_nmemb);
  }

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      clear_bitmap (mr.cell[x][y].screen, (mr.flicker > 0 && mr.flicker % 2)
                    ? mr.color : BLACK);

      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_background (mr.cell[x][y].screen,
                                mr.cell[x][y].room);
    }

  if (mr.flicker > 0) mr.flicker--;

  struct mr_room_list l;
  mr_get_room_list (&l);

  int xm, ym;
  if (! no_room_drawing)
    for (i = 0; i < l.nmemb; i++) {
      mr_coord (l.room[i], -1, &xm, &ym);
      for (y = mr.h - 1; y >= 0; y--)
        for (x = 0; x < mr.w; x++)
          if (mr.cell[x][y].room == l.room[i])
            draw_bitmap (mr.cell[xm][ym].cache,
                         mr.cell[x][y].screen, 0, 0, 0);
    }

  mr_destroy_room_list (&l);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_foreground (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  mr_update_last_settings ();
}
Exemple #16
0
int is_pos_threatened(Pos pos, char board[BOARD_SIZE][BOARD_SIZE], COLOR player){
	Pos curr; 
	int blocked[4] = { 0 };
	char* pieces;
	char bpieces[6] = { BLACK_P, BLACK_B, BLACK_N, BLACK_R, BLACK_Q, BLACK_K };
	char wpieces[6] = { WHITE_P, WHITE_B, WHITE_N, WHITE_R, WHITE_Q, WHITE_K };
	pieces = (player == WHITE) ? bpieces : wpieces;

	// check pawns
	int dir = player == WHITE ? 1 : -1;
	curr.row = pos.row + dir;
	curr.col = pos.col - 1;
	if (is_valid_pos(curr)){
		if (board[curr.col][curr.row] == pieces[0]) return 1;
	}
	curr.col = pos.col + 1;
	if (is_valid_pos(curr)){
		if (board[curr.col][curr.row] == pieces[0]) return 1;
	}

	// check bishops + queen
	for (int i = 1; i < BOARD_SIZE; i++){
		curr.col = pos.col - i, curr.row = pos.row - i;
		if (is_valid_pos(curr) && !blocked[0]){
			blocked[0] = (board[curr.col][curr.row] != EMPTY) ? 1 : 0;
			if (board[curr.col][curr.row] == pieces[1] || board[curr.col][curr.row] == pieces[4]) return 1;
		}
		curr.col = pos.col + i;
		if (is_valid_pos(curr) && !blocked[1]){
			blocked[1] = (board[curr.col][curr.row] != EMPTY) ? 1 : 0;
			if (board[curr.col][curr.row] == pieces[1] || board[curr.col][curr.row] == pieces[4]) return 1;
		}
		curr.row = pos.row + i;
		if (is_valid_pos(curr) && !blocked[2]){
			blocked[2] = (board[curr.col][curr.row] != EMPTY) ? 1 : 0;
			if (board[curr.col][curr.row] == pieces[1] || board[curr.col][curr.row] == pieces[4]) return 1;
		}
		curr.col = pos.col - i;
		if (is_valid_pos(curr) && !blocked[3]){
			blocked[3] = (board[curr.col][curr.row] != EMPTY) ? 1 : 0;
			if (board[curr.col][curr.row] == pieces[1] || board[curr.col][curr.row] == pieces[4]) return 1;
		}
	}


	// check knights
	Pos dests[8] = {{ pos.col - 2, pos.row - 1 }, { pos.col - 2, pos.row + 1 },
					{ pos.col + 2, pos.row - 1 }, { pos.col + 2, pos.row + 1 },
					{ pos.col - 1, pos.row - 2 }, { pos.col + 1, pos.row - 2 },
					{ pos.col - 1, pos.row + 2 }, { pos.col + 1, pos.row + 2 }};
	for (int i = 0; i < 8; i++){
		if (is_valid_pos(dests[i])){
			if (board[dests[i].col][dests[i].row] == pieces[2]) return 1;
		}
	}


	// check rooks + queen
	for (int j = 0; j < 4; j++) blocked[j] = 0;
	for (int i = 1; i < BOARD_SIZE; i++){
		curr.col = pos.col - i; curr.row = pos.row;
		if (is_valid_pos(curr) && !blocked[0]){
			blocked[0] = (board[curr.col][curr.row] != EMPTY) ? 1 : 0;
			if (board[curr.col][curr.row] == pieces[3] || board[curr.col][curr.row] == pieces[4]) return 1;
		}
		curr.col = pos.col + i;
		if (is_valid_pos(curr) && !blocked[1]){
			blocked[1] = (board[curr.col][curr.row] != EMPTY) ? 1 : 0;
			if (board[curr.col][curr.row] == pieces[3] || board[curr.col][curr.row] == pieces[4]) return 1;
		}
		curr.col = pos.col, curr.row = pos.row - i;
		if (is_valid_pos(curr) && !blocked[2]){
			blocked[2] = (board[curr.col][curr.row] != EMPTY) ? 1 : 0;
			if (board[curr.col][curr.row] == pieces[3] || board[curr.col][curr.row] == pieces[4]) return 1;
		}
		curr.row = pos.row + i;
		if (is_valid_pos(curr) && !blocked[3]){
			blocked[3] = (board[curr.col][curr.row] != EMPTY) ? 1 : 0;
			if (board[curr.col][curr.row] == pieces[3] || board[curr.col][curr.row] == pieces[4]) return 1;
		}
	}

	// check king
	Pos kdests[8] = { { pos.col - 1, pos.row - 1 }, { pos.col - 1, pos.row }, { pos.col - 1, pos.row + 1 },
	{ pos.col + 1, pos.row - 1 }, { pos.col + 1, pos.row }, { pos.col + 1, pos.row + 1 },
	{ pos.col, pos.row - 1 }, { pos.col, pos.row + 1 } };
	for (int i = 0; i < 8; i++){
		if (is_valid_pos(kdests[i])){
			if (board[kdests[i].col][kdests[i].row] == pieces[5]) return 1;
		}
	}

	// no threat
	return 0;
}
Exemple #17
0
// Helper func - checks if a piece belongs to the player
int is_valid_piece(char board[BOARD_SIZE][BOARD_SIZE], Move * move, COLOR color){
	if (is_valid_pos(move->piece) && board[move->piece.col][move->piece.row] != EMPTY)
		return !is_opposite(color, board[move->piece.col][move->piece.row]);
	return 0;
}
Exemple #18
0
void
fight_ai (struct anim *k)
{
  /* non-fightable characters don't fight */
  if (! is_fightable_anim (k)) return;

  /* controllables and non-fighters doesn't need AI to fight */
  if (k->controllable || ! k->fight) return;

  /* if forgetting about an enemy, no need to fight */
  if (k->enemy_refraction > 0) return;

  /* without an enemy or awareness, no need to fight */
  if (k->enemy_id == -1) {
    if (is_in_fight_mode (k)) leave_fight_mode (k);
    return;
  }

  /* first thing, enter in fight mode */
  if (! is_in_fight_mode (k)) {
    enter_fight_mode (k);
    return;
  }

  /* who's the enemy? */
  struct anim *ke = get_anim_by_id (k->enemy_id);

  /* what's the facing opposite direction? */
  enum dir odir = (k->f.dir == LEFT) ? RIGHT : LEFT;

  /* get positions */
  struct pos p, pe;
  survey (_m, pos, &k->f, NULL, &p, NULL);
  survey ((k->f.dir != ke->f.dir) ? _m : _mba,
          pos, &ke->f, NULL, &pe, NULL);
  pos2room (&pe, p.room, &pe);

  /* remember the place the enemy was last seen */
  if (pe.room == p.room && pe.floor == p.floor)
    k->enemy_pos = pe;
  else if (pe.floor > p.floor && is_valid_pos (&k->enemy_pos)
           && ! is_strictly_traversable (&k->enemy_pos))
    k->enemy_pos.place = pe.place;

  if (is_valid_pos (&k->enemy_pos)
      && is_strictly_traversable (&k->enemy_pos)) {
    struct pos pp;
    int d = (p.place < k->enemy_pos.place) ? -1 : +1;
    while (is_strictly_traversable (prel (&k->enemy_pos, &pp, +0, d)))
      k->enemy_pos = pp;
  }

  /* prevent enemy from passing through */
  if (ke->type == KID
      && is_in_range (k, ke, ATTACK_RANGE)
      && ! is_in_fight_mode (ke)
      && ! ke->immortal
      && ! (is_kid_climb (&ke->f) && ke->i <= 7)
      && ke->f.dir != k->f.dir
      && ke->current_lives > 0
      && ke->has_sword
      && ! is_kid_fall (&ke->f)
      && ! is_kid_hang (&ke->f)
      && ! is_kid_jump_air (&ke->f)
      && ! is_kid_run_jump_air (&ke->f)
      && is_safe_to_attack (ke)) {
    place_on_the_ground (&ke->f, &ke->f.c);
    kid_take_sword (ke);
    ke->auto_taken_sword = true;
  }

  /* prevent enemy from hiding near */
  if (ke->type == KID
      && is_in_range (k, ke, INVERSION_RANGE)
      && ! is_in_fight_mode (ke)
      && ke->current_lives > 0) {
    if (is_safe_to_walkb (k)) fight_walkb (k);
    else if (is_safe_to_turn (k)) fight_turn (k);
    return;
  }

  /* if the enemy is on the back, turn */
  if (is_on_back (k, ke) && is_anim_seeing (k, ke, odir)
      && p.floor == pe.floor
      && ! is_in_range (k, ke, INVERSION_RANGE)) {
    if (is_safe_to_turn (k)) fight_turn (k);
    else if (is_safe_to_walkb (k)) fight_walkb (k);
    return;
  }

  /* if too near to a wall, back off to have room for an attack */
  if (fight_crel (k, +0, +1) == WALL
      && is_safe_to_walkb (k)) {
    fight_walkb (k);
    return;
  }

  /* /\* if the enemy can be followed in the opposite direction, turn *\/ */
  /* if (! is_safe_to_follow (k, ke, k->f.dir) */
  /*     && is_safe_to_follow (k, ke, odir)) { */
  /*   fight_turn (k); */
  /*   return; */
  /* } */

  /* if the enemy is trying to bypass, attack him */
  if (! is_in_fight_mode (ke)
      && ! ke->has_sword
      && ! is_kid_stairs (&ke->f)
      && ke->f.dir != k->f.dir
      && ke->current_lives > 0
      && ! is_on_back (k, ke)
      && ((is_kid_run (&ke->f)
           && is_in_range (k, ke, 3 * PLACE_WIDTH - 4))
          || (is_kid_run_jump (&ke->f)
              && is_in_range (k, ke, 4 * PLACE_WIDTH - 4))
          || (is_kid_jump_air (&ke->f) && ke->i < 9
              && is_in_range (k, ke, 4 * PLACE_WIDTH)))) {
    if (is_safe_to_attack (k)) fight_attack (k);
    else if (is_safe_to_walkb (k)) fight_walkb (k);
    return;
  }

  /* stays at least in the fight range.  Advance, unless the enemy is
     not running towards you */
  if (! is_in_range (k, ke, FIGHT_RANGE + 10)
      && ! is_kid_stairs (&ke->f)
      && (ke->f.dir == k->f.dir
          || p.room != pe.room
          || p.floor != pe.floor
          || ! (is_kid_run (&ke->f)
                || is_kid_run_jump (&ke->f)
                || is_kid_jump (&ke->f)))
      && is_safe_to_follow (k, ke, k->f.dir)) {
    fight_walkf (k);
    return;
  }

  /* if the enemy is not targeting you, do nothing more */
  if (ke->enemy_id != -1 && ke->enemy_id != k->id) return;

  /* in fight range, if the enemy is not attacking, go towards attack
     range (with probability, unless the enemy is not in fight mode,
     then go immediately) */
  if (is_in_range (k, ke, FIGHT_RANGE + 10)
      && ! is_in_range (k, ke, ATTACK_RANGE)
      && ! is_kid_stairs (&ke->f)
      && is_safe_to_follow (k, ke, k->f.dir)
      && (prandom (99) <= k->skill.advance_prob
          || ! is_in_fight_mode (ke))
      && ! is_attacking (ke)
      && (! is_in_fight_mode (ke)
          || is_walking (ke)
          || ke->i >= 6 + prandom (24))) {
    fight_walkf (k);
    return;
  }

  /* in attack range, if being attacked, defend yourself (with
     probability) and counter attack (with probability handled
     elsewhere) */
  if (is_in_range (k, ke, ATTACK_RANGE + 16)
      && ! is_on_back (k, ke)
      && (is_attacking (ke) && ke->i == 0)
      && (prandom (99) <= k->skill.defense_prob
          || k->refraction > 0)
      && ke->current_lives > 0) {
    fight_defense (k);
    fight_attack (k);
    return;
  }

  /* if attacking, counter defend
     (with probability handled elsewhere) */
  if (is_in_range (k, ke, ATTACK_RANGE + 16)
      && is_attacking (k)) {
    fight_defense (k);
    fight_attack (k);
    return;
  }

  /* in attack range, if not being attacked, attack (with probability,
     unless the enemy is not in fight mode, then attack immediately) */
  if (is_in_range (k, ke, ATTACK_RANGE)
      && ! is_attacking (ke)
      && ! is_on_back (k, ke)
      && ! is_kid_stairs (&ke->f)
      && ! ((is_kid_climb (&ke->f)
             || is_kid_successfully_climbing (&ke->f))
            && ke->i >= 1)
      && ke->current_lives > 0
      && (prandom (99) <= k->skill.attack_prob
          || ! is_in_fight_mode (ke))) {
    if (is_safe_to_attack (k)) fight_attack (k);
    else if (is_safe_to_walkb (k)) fight_walkb (k);
    return;
  }

  /* in hit range, back off (with probability) */
  if (is_in_range (k, ke, HIT_RANGE - 10)
      && is_safe_to_walkb (k)
      && ! k->refraction
      && ! is_walkingb (ke)
      && prandom (99) <= k->skill.return_prob) {
    fight_walkb (k);
    return;
  }
}
Exemple #19
0
void
draw_multi_rooms (void)
{
  int x, y;

  mr_set_origin (mr.room, mr.x, mr.y);

  bool mr_view_changed = has_mr_view_changed ();

  if (mr_view_changed) force_full_redraw = true;

  if (anim_cycle == 0) {
    generate_wall_colors_for_room (0, room0_wall_color);
  }

  if (em == PALACE && vm == VGA
      && (mr_view_changed
          || em != mr.last.em
          || vm != mr.last.vm))
    generate_wall_colors ();

  if (mr_view_changed)
    generate_stars ();

  if (mouse_pos.room != mr.last.mouse_pos.room
      || mouse_pos.floor != mr.last.mouse_pos.floor
      || mouse_pos.place != mr.last.mouse_pos.place) {
    if (is_valid_pos (&mouse_pos))
      update_cache_pos (&mouse_pos, CHPOS_MOUSE_SELECT, em, vm);
    if (is_valid_pos (&mr.last.mouse_pos))
      update_cache_pos (&mr.last.mouse_pos, CHPOS_MOUSE_DESELECT, em, vm);
  }

  if (anim_cycle == 0
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue) {
    update_room0_cache (em, vm);
    force_full_redraw = true;
  }

  if (anim_cycle == 0
      || mr_view_changed
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue
      || global_level.number != mr.last.level) {
    update_cache (em, vm);
  }

  size_t i;
  for (i = 0; i < changed_pos_nmemb; i++)
    update_cache_pos (&changed_pos[i].p, changed_pos[i].reason, em, vm);
  destroy_array ((void **) &changed_pos, &changed_pos_nmemb);

  for (i = 0; i < changed_room_nmemb; i++)
    update_cache_room (changed_room[i], em, vm);
  destroy_array ((void **) &changed_room, &changed_room_nmemb);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      clear_bitmap (mr.cell[x][y].screen, (mr.flicker > 0 && mr.flicker % 2)
                    ? mr.color : BLACK);

      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_background (mr.cell[x][y].screen,
                                mr.cell[x][y].room);
    }

  if (mr.flicker > 0) mr.flicker--;

  struct mr_room_list l;
  mr_get_room_list (&l);

  int xm, ym;
  if (! no_room_drawing)
    for (i = 0; i < l.nmemb; i++) {
      mr_coord (l.room[i], -1, &xm, &ym);
      for (y = mr.h - 1; y >= 0; y--)
        for (x = 0; x < mr.w; x++)
          if (mr.cell[x][y].room == l.room[i])
            draw_bitmap (mr.cell[xm][ym].cache,
                         mr.cell[x][y].screen, 0, 0, 0);
    }

  mr_destroy_room_list (&l);

  /* if (! no_room_drawing) */
  /*   for (y = mr.h - 1; y >= 0; y--) */
  /*     for (x = 0; x < mr.w; x++) */
  /*       if (mr.cell[x][y].room) */
  /*         draw_bitmap (mr.cell[x][y].cache, mr.cell[x][y].screen, 0, 0, 0); */

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_foreground (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  /* if (mr.select_cycles > 0) { */
  /*   int t = max_int (mr.w, mr.h); */
  /*   draw_rectangle (mr.cell[mr.x][mr.y].screen, 0, 3, */
  /*                   ORIGINAL_WIDTH - t, */
  /*                   3 + ROOM_HEIGHT - t, RED, t); */
  /*   mr.select_cycles--; */
  /* } */

  mr_update_last_settings ();
}
Exemple #20
0
bool
is_safe_to_follow (struct anim *k0, struct anim *k1, enum dir dir)
{
  /* not aware of enemy position */
  if (! is_valid_pos (&k0->enemy_pos)) return false;

  struct pos p0, p, p1, pke, pk;
  survey (_m, pos, &k0->f, NULL, &p0, NULL);
  survey ((k0->f.dir == LEFT) ? _mr : _ml,
          pos, &k1->f, NULL, &p1, NULL);

  pos2room (&p1, p0.room, &p1);

  /* not reachable, to start with */
  if (p0.room != p1.room) return false;
  if (p0.floor > p1.floor) return false;

  /* the character went down after the enemy */
  if (p0.floor != k0->enemy_pos.floor) {
    /* enum dir odir = (dir == LEFT) ? RIGHT : LEFT; */
    /* if (is_on_back (k0, k1) && is_seeing (k0, k1, odir) */
    /*     && p0.floor == p1.floor) return true; */
    if (is_anim_seeing (k0, k1, LEFT)
        || is_anim_seeing (k0, k1, RIGHT)) return true;
    return false;
  }

  /* if falling the chasing is inevitable (necessary to prevent
     leave_fight_logic from forgeting enemy based on the facing
     direction of the is_in_range check) */
  if (is_anim_fall (&k0->f)) return true;

  if (dir == LEFT) {
    if (! is_safe_at_left (&p0)) return false;
    if (! is_safe_at_right (&k0->enemy_pos, &k0->f)) return false;
    if (peqr (&k0->enemy_pos, &p0, +0, -1)) return true;
    prel (&p0, &pk, +0, -1);
    prel (&k0->enemy_pos, &pke, +0, +1);
    if (is_collidable_at_right (&pk, &k0->f))
      return false;
  } else {
    if (! is_safe_at_right (&p0, &k0->f)) return false;
    if (! is_safe_at_left (&k0->enemy_pos)) return false;
    if (peqr (&k0->enemy_pos, &p0, +0, +1)) return true;
    prel (&p0, &pk, +0, +1);
    prel (&k0->enemy_pos, &pke, +0, -1);
    if (is_collidable_at_right (&p0, &k0->f))
      return false;
  }

  /* enemy went down */
  if (is_traversable (&k0->enemy_pos)) {
    prel (&k0->enemy_pos, &pke, +1, +0);
    if (is_traversable (&pke) || fg (&pke) == SPIKES_FLOOR)
      return false;
    int d = (dir == LEFT) ? -1 : +1;
    if (peq (&pk, &k0->enemy_pos)) return true;
    prel (&k0->enemy_pos, &pke, +0, -1 * d);
  } else if (peq (&p0, &k0->enemy_pos)
             && ! (is_anim_seeing (k0, k1, LEFT)
                   || is_anim_seeing (k0, k1, RIGHT)))
    return false;

  first_confg (&pk, &pke, dangerous_cs, &p);
  if (is_valid_pos (&p)) return false;

  first_confg (&pk, &pke, door_cs, &p);
  if (! is_valid_pos (&p)) return true;
  else return door_at_pos (&p)->action == OPEN_DOOR
         || ! is_collidable_at_right (&p, &k0->f);
}