예제 #1
0
void test_valid_move_from_maneuvre_stack_to_maneuvre_stacks() {
  struct stack *maneuvre_stacks[7];

  for (int i = 0; i < 7; i++) {
    stack_malloc(&maneuvre_stacks[i]);
    stack_init(maneuvre_stacks[i]);
  }
  card_set(maneuvre_stacks[0]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X);
  card_set(maneuvre_stacks[1]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X);
  card_set(maneuvre_stacks[2]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_2_BEGIN_X);
  card_set(maneuvre_stacks[3]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_3_BEGIN_X);
  card_set(maneuvre_stacks[4]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_4_BEGIN_X);
  card_set(maneuvre_stacks[5]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_5_BEGIN_X);
  card_set(maneuvre_stacks[6]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_6_BEGIN_X);
  for (int i = 0; i < 7; i++) {
    for (int j = 0; j < 7; j++) {
      if (i == j) {
        assert(!valid_move(maneuvre_stacks[i], maneuvre_stacks[j]));
      } else {
        assert(valid_move(maneuvre_stacks[i], maneuvre_stacks[j]));
      }
    }
  }
  for (int i = 0; i < 7; i++) {
    stack_free(maneuvre_stacks[i]);
  }
}
예제 #2
0
파일: AI.cpp 프로젝트: athul777/connectfour
/*
	Basically the same code as minimax. It initiates the move making process. 
*/
void AI::make_move(int current_player, Board* game_board) {
	//Defines max and min possible scores.
	int alpha = -2000;
	int beta = 2000;
	//The depth is initially 0. This will be incremented after every recursive call to minimax. 
	int depth = 0;
	//Defines the best possible score so far and a default position. 
	int best_score;
	int position = 4;

	//If player is X. 
	if (current_player == 1) {
		//We try to get a better score than alpha, so we default to alpha in the beginning. 
		best_score = alpha;
		//We basically perform all 7 (at most) possible moves. 
		for (int i = 1; i < 8; ++i) {
			//Only if i is a valid move.
			if (valid_move(i)) {
				//It plays the move i in the vector and simply recursively calls minimax to maximize (or minimize) its score and revert all moves.
				play(current_player, i);
				int score = minimax(best_score, beta, -current_player, game_board, depth);
				if (score > best_score) {
					//Score and position are stored. 
					best_score = score;
					position = i;
				}
				//Move is reverted. 
				revert(current_player, i);

				//Here we perform alpha beta pruning, which enables us to discard large sections of the Search Tree. 
				if (beta <= best_score) {
					break;
				}
			}
		}
	}

	//Same process as with 1. 
	else if (current_player == -1) {
		best_score = beta;
		for (int i = 1; i < 8; ++i) {
			if (valid_move(i)) {
				play(current_player, i);
				int score = minimax(alpha, best_score, -current_player, game_board, depth);
				if (score < best_score) {
					best_score = score;
					position = i;
				}
				revert(current_player, i);
				if (best_score <= alpha) {
					break;
				}
			}
		}
	}

	//After determining the best position (from the best score), it makes that move. 
	play(current_player, position);
}
예제 #3
0
static int check_nomove()
{
	unsigned char c;
	if (_othello->state != NO_MOVE && _othello->state != GAME_OVER)
		return 0;
	for (c = 0; c < 64; c++) {
		if (valid_move(&_othello->board, &_othello->b_set, S_WHITE, c))
			return 0;
		if (valid_move(&_othello->board, &_othello->b_set, S_BLACK, c))
			return 0;
	}
	_othello->state = GAME_OVER;
	return 1;
}
예제 #4
0
void test_valid_move_from_waste_pile_to_waste_pile() {
  struct stack *waste_pile_0, *waste_pile_1;

  stack_malloc(&waste_pile_0);
  stack_malloc(&waste_pile_1);
  stack_init(waste_pile_0);
  stack_init(waste_pile_1);
  card_set(waste_pile_0->card, ACE, SPADES, EXPOSED, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X);
  card_set(waste_pile_1->card, KING, HEARTS, EXPOSED, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X);
  assert(!valid_move(waste_pile_0, waste_pile_0));
  assert(!valid_move(waste_pile_0, waste_pile_1));
  assert(!valid_move(waste_pile_1, waste_pile_0));
  assert(!valid_move(waste_pile_1, waste_pile_1));
  stack_free(waste_pile_0);
  stack_free(waste_pile_1);
}
예제 #5
0
void test_valid_move_from_stock_to_maneuvre_stacks() {
  struct stack *stock, *maneuvre_stacks[7];

  stack_malloc(&stock);
  stack_init(stock);
  card_set(stock->card, ACE, SPADES, EXPOSED, STOCK_BEGIN_Y, STOCK_BEGIN_X);
  for (int i = 0; i < 7; i++) {
    stack_malloc(&maneuvre_stacks[i]);
    stack_init(maneuvre_stacks[i]);
  }
  card_set(maneuvre_stacks[0]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X);
  card_set(maneuvre_stacks[1]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X);
  card_set(maneuvre_stacks[2]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_2_BEGIN_X);
  card_set(maneuvre_stacks[3]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_3_BEGIN_X);
  card_set(maneuvre_stacks[4]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_4_BEGIN_X);
  card_set(maneuvre_stacks[5]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_5_BEGIN_X);
  card_set(maneuvre_stacks[6]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_6_BEGIN_X);
  for (int i = 0; i < 7; i++) {
    assert(!valid_move(stock, maneuvre_stacks[i]));
  }
  stack_free(stock);
  for (int i = 0; i < 7; i++) {
    stack_free(maneuvre_stacks[i]);
  }
}
예제 #6
0
void test_valid_move_from_stock_to_stock() {
  struct stack *stock_0, *stock_1;

  stack_malloc(&stock_0);
  stack_malloc(&stock_1);
  stack_init(stock_0);
  stack_init(stock_1);
  card_set(stock_0->card, ACE, SPADES, EXPOSED, STOCK_BEGIN_Y, STOCK_BEGIN_X);
  card_set(stock_1->card, KING, HEARTS, EXPOSED, STOCK_BEGIN_Y, STOCK_BEGIN_X);
  assert(!valid_move(stock_0, stock_0));
  assert(!valid_move(stock_0, stock_1));
  assert(!valid_move(stock_1, stock_0));
  assert(!valid_move(stock_1, stock_1));
  stack_free(stock_0);
  stack_free(stock_1);
}
예제 #7
0
void test_valid_move_from_maneuvre_stack_to_foundation_stacks() {
  struct stack *foundation_stacks[4];
  struct stack *maneuvre_stacks[7];

  for (int i = 0; i < 4; i++) {
    stack_malloc(&foundation_stacks[i]);
    stack_init(foundation_stacks[i]);
  }
  card_set(foundation_stacks[0]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_0_BEGIN_X);
  card_set(foundation_stacks[1]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_1_BEGIN_X);
  card_set(foundation_stacks[2]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_2_BEGIN_X);
  card_set(foundation_stacks[3]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_3_BEGIN_X);
  for (int i = 0; i < 7; i++) {
    stack_malloc(&maneuvre_stacks[i]);
    stack_init(maneuvre_stacks[i]);
  }
  card_set(maneuvre_stacks[0]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X);
  card_set(maneuvre_stacks[1]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X);
  card_set(maneuvre_stacks[2]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_2_BEGIN_X);
  card_set(maneuvre_stacks[3]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_3_BEGIN_X);
  card_set(maneuvre_stacks[4]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_4_BEGIN_X);
  card_set(maneuvre_stacks[5]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_5_BEGIN_X);
  card_set(maneuvre_stacks[6]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_6_BEGIN_X);
  for (int i = 0; i < 7; i++) {
    for (int j = 0; j < 4; j++) {
      assert(valid_move(maneuvre_stacks[i], foundation_stacks[j]));
    }
  }
  for (int i = 0; i < 4; i++) {
    stack_free(foundation_stacks[i]);
  }
  for (int i = 0; i < 7; i++) {
    stack_free(maneuvre_stacks[i]);
  }
}
예제 #8
0
void test_valid_move_from_maneuvre_stack_to_waste_pile() {
  struct stack *waste_pile, *maneuvre_stacks[7];

  stack_malloc(&waste_pile);
  stack_init(waste_pile);
  card_set(waste_pile->card, ACE, SPADES, EXPOSED, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X);
  for (int i = 0; i < 7; i++) {
    stack_malloc(&maneuvre_stacks[i]);
    stack_init(maneuvre_stacks[i]);
  }
  card_set(maneuvre_stacks[0]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X);
  card_set(maneuvre_stacks[1]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X);
  card_set(maneuvre_stacks[2]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_2_BEGIN_X);
  card_set(maneuvre_stacks[3]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_3_BEGIN_X);
  card_set(maneuvre_stacks[4]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_4_BEGIN_X);
  card_set(maneuvre_stacks[5]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_5_BEGIN_X);
  card_set(maneuvre_stacks[6]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_6_BEGIN_X);
  for (int i = 0; i < 7; i++) {
    assert(!valid_move(maneuvre_stacks[i], waste_pile));
  }
  stack_free(waste_pile);
  for (int i = 0; i < 7; i++) {
    stack_free(maneuvre_stacks[i]);
  }
}
예제 #9
0
// Player's turn
void player_turn(int board[][BOARD_SIZE], int player) {
	char turn;
	int x;
	int y;
	
	if (player == 1) {
	turn = 'X';
	}
	
	if (player == -1) {
	turn = 'O';
	
	}
	
	while(1) {
	
	printf("Player %c, enter a move: ", turn);
	scanf("%d %d", &x, &y);
	
	if (valid_move(x, y, board) == 1) break;
	
	else printf("Sorry, invalid move!\n");
	
	}
	
	make_move(x, y, board, player);
}
예제 #10
0
파일: AI.cpp 프로젝트: athul777/connectfour
//Almost identical to make_move, except we increment depth since it is being called recursively.
int AI::minimax(int alpha, int beta, int current_player, Board* game_board, int depth) {
	if (game_board->checkWin()) return current_player * -1000;
	else if (game_board->checkDraw()) return 0;

	if (depth == 7) {
		if (player == -1) return evaluate(game_board);
		else if (player == 1) return -(evaluate(game_board));
	}

	++depth;
	int best_score;

	if (current_player == 1) {
		best_score = alpha;
		for (int i = 1; i < 8; ++i) {
			if (valid_move(i)) {
				play(current_player, i);
				int score = minimax(best_score, beta, -current_player, game_board, depth);
				if (score > best_score) best_score = score;
				revert(current_player, i);
				if (beta <= best_score) {
					break;
				}
			}
		}
	}

	else if (current_player == -1) {
		best_score = beta;
		for (int i = 1; i < 8; ++i) {
			if (valid_move(i)) {
				play(current_player, i);
				int score = minimax(alpha, best_score, -current_player, game_board, depth);
				if (score < best_score) best_score = score;
				revert(current_player, i);
				if (best_score <= alpha) {
					break;
				}
			}
		}
	}

	return best_score;
}
예제 #11
0
take_move()
{
	// take keyboard input for opponents move
	char opToPos[2] = std_in; 

	// test opponents move for validity
	if( !valid_move( opPos, opToPos ) )
		fail("Opponent made invalid move");

	make_move()
}
예제 #12
0
std::vector<Move> Board::get_available_moves(bool is_black) {
    std::vector<Move> result;
    for (std::size_t i = 0; i < board.size(); i++) {
        for (std::size_t j = 0; j < board.size(); j++) {
            if (valid_move(i, j, is_black)) {
                Move tmp(i, j, is_black);
                result.push_back(tmp);
            }
        }
    }
    return result;
}
예제 #13
0
//checks a specific move from specific location on the board. If move viable and doesn't lead to duplicate board, 
//new board shows this move and 1 is returned. If no moves found, returns 0
int check_move (movement direction, int i, int j, hash *hash_array, Node *start, Node *latest_node, int parent_board [BOARD_HEIGHT][BOARD_WIDTH], int new_board[BOARD_HEIGHT][BOARD_WIDTH]){
    if (valid_move (direction, i, j, new_board)){
        move_piece (direction, i, j, new_board);
        latest_node->identifier = allocate_board_identifier (new_board);
        if (insert_hash (hash_array, latest_node, latest_node->identifier, new_board) == 1){
            copy_board (new_board, parent_board);
        }
        else{
            return 1;
        }
    }
    return 0;
}
예제 #14
0
void test_valid_move_from_waste_pile_to_stock() {
  struct stack *stock, *waste_pile;

  stack_malloc(&stock);
  stack_malloc(&waste_pile);
  stack_init(stock);
  stack_init(waste_pile);
  card_set(stock->card, ACE, SPADES, EXPOSED, STOCK_BEGIN_Y, STOCK_BEGIN_X);
  card_set(waste_pile->card, KING, HEARTS, EXPOSED, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X);
  assert(!valid_move(waste_pile, stock));
  stack_free(stock);
  stack_free(waste_pile);
}
예제 #15
0
void test_valid_move_from_foundation_stack_to_foundation_stacks() {
  struct stack *foundation_stacks[4];

  for (int i = 0; i < 4; i++) {
    stack_malloc(&foundation_stacks[i]);
    stack_init(foundation_stacks[i]);
  }
  card_set(foundation_stacks[0]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_0_BEGIN_X);
  card_set(foundation_stacks[1]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_1_BEGIN_X);
  card_set(foundation_stacks[2]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_2_BEGIN_X);
  card_set(foundation_stacks[3]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_3_BEGIN_X);
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      if (i == j) {
        assert(!valid_move(foundation_stacks[i], foundation_stacks[j]));
      } else {
        assert(valid_move(foundation_stacks[i], foundation_stacks[j]));
      }
    }
  }
  for (int i = 0; i < 4; i++) {
    stack_free(foundation_stacks[i]);
  }
}
예제 #16
0
void Game::move(Pile *from, Pile *to, int num) {
  assert(valid_move(from, to, num));
  to->move_from(*from, num);

  /* Flip tableau card if necessary */
  for (int i = 0; i < NUM_TABLEAU; i++) {
    if (from == tableau[i]) {
      if (VERBOSE)
        std::cout << "visibility check tableau found" << std::endl;
      if (!from->get_card(0).visible) {
        if (VERBOSE) std::cout << "Flipping card" << std::endl;
        from->get_card(0).visible = true;
      }
    }
  }
}
예제 #17
0
    bool move(char op) {

      if(__on_lift) {
        cerr << "the game is already over." << endl;
        assert(false);
      }

      // step++;

      __last_op = op;

      if(op == 'A') {
        score += 25 * got;
        return true;
      }

      if(!valid_move(op)) return false;

      Pos np = __next_pos(op);
      int diff_x = np.x - pos.x, diff_y = np.y - pos.y;

      if(at(np.x, np.y, step) == ROCK) {
        set(np.x + diff_x, np.y + diff_y, step, ROCK);
      } else if(at(np.x, np.y, step) == LAMBDA) {
        got++; score += 25;
        got_lambda = true;
      } else {
        got_lambda = false;
      }

      set(pos.x, pos.y, step, __on_lift ? LIFT : EMPTY);

      if(at(np.x, np.y, step) == LIFT) {
        score += 50 * got;
        __on_lift = true;
      } else {
        __on_lift = false;
      }
      set(np.x, np.y, step, ROBOT);

      pos = np;
      score--;

      return true;
    }
예제 #18
0
void player_move() {
	int pos, valid = 1;
	int ch, flag = 0; // for invalid characters in scanf
	do {
		if(!valid && !flag){
			printf("Invalid move! Try Again.\n");
		}
		printf("\n\nEnter position you want to play: ");
		if(scanf("%d", &pos) <= 0) {
			valid = 1;
			while ((ch = getchar()) != '\n' && ch != EOF);
			printf("Weird character encountered!!!\n");
			flag = 1;
			continue;
		}
		flag = 0;
	}while(!(valid = valid_move(pos, 1)));
}
예제 #19
0
static signed char best_move(uint64_t *bo, uint64_t *bs, char side)
{
	uint64_t t_bo, t_bs;
	unsigned char c, bc = 0;
	int best = NOMOVE;
	int pts;

	for (c = 0; c < 64; c++) {
		if (!valid_move(bo, bs, side, c))
			continue;
		memcpy(&t_bo, bo, sizeof(uint64_t));
		memcpy(&t_bs, bs, sizeof(uint64_t));
		pts = move_piece(&t_bo, &t_bs, side, c);
		if (pts > best) {
			best = pts;
			bc = c;
		}
	}
	return (best != NOMOVE) ? bc : NOMOVE;
}
예제 #20
0
void test_valid_move_from_stock_to_foundation_stacks() {
  struct stack *stock, *foundation_stacks[4];

  stack_malloc(&stock);
  stack_init(stock);
  card_set(stock->card, ACE, SPADES, EXPOSED, STOCK_BEGIN_Y, STOCK_BEGIN_X);
  for (int i = 0; i < 4; i++) {
    stack_malloc(&foundation_stacks[i]);
    stack_init(foundation_stacks[i]);
  }
  card_set(foundation_stacks[0]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_0_BEGIN_X);
  card_set(foundation_stacks[1]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_1_BEGIN_X);
  card_set(foundation_stacks[2]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_2_BEGIN_X);
  card_set(foundation_stacks[3]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_3_BEGIN_X);
  for (int i = 0; i < 4; i++) {
    assert(!valid_move(stock, foundation_stacks[i]));
  }
  stack_free(stock);
  for (int i = 0; i < 4; i++) {
    stack_free(foundation_stacks[i]);
  }
}
예제 #21
0
void test_valid_move_from_foundation_stack_to_waste_pile() {
  struct stack *waste_pile, *foundation_stacks[4];

  stack_malloc(&waste_pile);
  stack_init(waste_pile);
  card_set(waste_pile->card, ACE, SPADES, EXPOSED, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X);
  for (int i = 0; i < 4; i++) {
    stack_malloc(&foundation_stacks[i]);
    stack_init(foundation_stacks[i]);
  }
  card_set(foundation_stacks[0]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_0_BEGIN_X);
  card_set(foundation_stacks[1]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_1_BEGIN_X);
  card_set(foundation_stacks[2]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_2_BEGIN_X);
  card_set(foundation_stacks[3]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_3_BEGIN_X);
  for (int i = 0; i < 4; i++) {
    assert(!valid_move(foundation_stacks[i], waste_pile));
  }
  stack_free(waste_pile);
  for (int i = 0; i < 4; i++) {
    stack_free(foundation_stacks[i]);
  }
}
예제 #22
0
void _droidzebra_redo_turn(int *side_to_move) {
    int target_disks_played = 0;
    int curr_move;

    if (!_droidzebra_can_redo()) return;

    target_disks_played = _droidzebra_undo_stack_pop();
    droidzebra_message_debug("redo: score_sheet_row %d, disks_played %d, new_disks_played %d",
                             score_sheet_row, disks_played, target_disks_played);
    while (disks_played < target_disks_played) {
        generate_all(*side_to_move);

        if (move_count[disks_played] > 0) {
            curr_move = get_stored_move(disks_played);
            if (curr_move == ILLEGAL || !valid_move(curr_move, *side_to_move)) {
                fatal_error("Invalid move %c%c in redo sequence", TO_SQUARE(curr_move));
            }
            (void) make_move(*side_to_move, curr_move, TRUE);
        } else {
            curr_move = PASS;
        }

        droidzebra_message_debug(
                "redo: score_sheet_row %d, curr_move %d, side_to_move %d, disks_played %d",
                score_sheet_row, curr_move, *side_to_move, disks_played);

        if (*side_to_move == BLACKSQ)
            black_moves[score_sheet_row] = curr_move;
        else {
            white_moves[score_sheet_row] = curr_move;
        }

        *side_to_move = OPP(*side_to_move);

        if (*side_to_move == BLACKSQ)
            score_sheet_row++;
    }
}
예제 #23
0
//keyboard function - gameplay implementation
void keyboard(unsigned char ch, int x, int y) {
    float aux_x = player_x;
    float aux_y = player_y;
    if (!finished) {
        switch(ch) {
        case 27:	//esc
            exit(0);
            break;
        //move forward
        case 'w':
            aux_x += -sin((3.14 * player_r) / 180) * 0.05;
            aux_y += cos((3.14 * player_r) / 180) * 0.05;
            if (valid_move(aux_x, aux_y)) {
                player_x = aux_x;
                player_y= aux_y;
            }
            break;
        //move backward
        case 's':
            aux_x -= -sin((3.14 * player_r) / 180) * 0.05;
            aux_y -= cos((3.14 * player_r) / 180) * 0.05;
            if (valid_move(aux_x, aux_y)) {
                player_x = aux_x;
                player_y= aux_y;
            }
            break;
        //move right
        case 'd':
            aux_y += sin((3.14 * player_r) / 180) * 0.05;
            aux_x += cos((3.14 * player_r) / 180) * 0.05;
            if (valid_move(aux_x, aux_y)) {
                player_x = aux_x;
                player_y= aux_y;
            }
            break;
        //move left
        case 'a':
            aux_y -= sin((3.14 * player_r) / 180) * 0.05;
            aux_x -= cos((3.14 * player_r) / 180) * 0.05;
            if (valid_move(aux_x, aux_y)) {
                player_x = aux_x;
                player_y= aux_y;
            }
            break;
        //modify direction in the trigonometric sens
        case 'q':
            player_r += 3;
            if (player_r == 360)
                player_r = 0;
            break;
        //modify direction in the opposite sense
        case 'e':
            player_r -= 3;
            if (player_r == 0)
                player_r = 360;
            break;
        //move forward at high speed
        case 'x':
            aux_x += -sin((3.14 * player_r) / 180) * 0.2;
            aux_y += cos((3.14 * player_r) / 180) * 0.2;
            if (valid_move(aux_x, aux_y)) {
                player_x = aux_x;
                player_y= aux_y;
            }
            break;
        //change camera up
        case '0':
            cam = 0;
            break;
        //change camera first-person
        case '1':
            cam = 1;
            break;
        //change camera third-person
        case '2':
            cam = 2;
            break;
        default:
            break;
        }

        if (cam == 2)
            switch (ch) {
            case '3':
                break;
            case '4':
                break;
            case '5':
                break;
            case '6':
                break;
            case '7':
                break;
            case '8':
                break;

            }

        if ((abs(player_x - portal_x) < 0.20) && (abs(player_y - portal_y) < 0.20))
            finished = 1;
    }

    //give a signal if you won
    if (finished)
        Beep(2000, 200);

    glutPostRedisplay();
}
예제 #24
0
std::vector<tripoint> map::route( const tripoint &f, const tripoint &t,
                                  const pathfinding_settings &settings,
                                  const std::set<tripoint> &pre_closed ) const
{
    /* TODO: If the origin or destination is out of bound, figure out the closest
     * in-bounds point and go to that, then to the real origin/destination.
     */
    std::vector<tripoint> ret;

    if( f == t || !inbounds( f ) ) {
        return ret;
    }

    if( !inbounds( t ) ) {
        tripoint clipped = t;
        clip_to_bounds( clipped );
        return route( f, clipped, settings, pre_closed );
    }
    // First, check for a simple straight line on flat ground
    // Except when the line contains a pre-closed tile - we need to do regular pathing then
    static const auto non_normal = PF_SLOW | PF_WALL | PF_VEHICLE | PF_TRAP;
    if( f.z == t.z ) {
        const auto line_path = line_to( f, t );
        const auto &pf_cache = get_pathfinding_cache_ref( f.z );
        // Check all points for any special case (including just hard terrain)
        if( std::all_of( line_path.begin(), line_path.end(), [&pf_cache]( const tripoint & p ) {
        return !( pf_cache.special[p.x][p.y] & non_normal );
        } ) ) {
            const std::set<tripoint> sorted_line( line_path.begin(), line_path.end() );

            if( is_disjoint( sorted_line, pre_closed ) ) {
                return line_path;
            }
        }
    }

    // If expected path length is greater than max distance, allow only line path, like above
    if( rl_dist( f, t ) > settings.max_dist ) {
        return ret;
    }

    int max_length = settings.max_length;
    int bash = settings.bash_strength;
    int climb_cost = settings.climb_cost;
    bool doors = settings.allow_open_doors;
    bool trapavoid = settings.avoid_traps;

    const int pad = 16;  // Should be much bigger - low value makes pathfinders dumb!
    int minx = std::min( f.x, t.x ) - pad;
    int miny = std::min( f.y, t.y ) - pad;
    int minz = std::min( f.z, t.z ); // TODO: Make this way bigger
    int maxx = std::max( f.x, t.x ) + pad;
    int maxy = std::max( f.y, t.y ) + pad;
    int maxz = std::max( f.z, t.z ); // Same TODO as above
    clip_to_bounds( minx, miny, minz );
    clip_to_bounds( maxx, maxy, maxz );

    pathfinder pf( minx, miny, maxx, maxy );
    // Make NPCs not want to path through player
    // But don't make player pathing stop working
    for( const auto &p : pre_closed ) {
        if( p.x >= minx && p.x < maxx && p.y >= miny && p.y < maxy ) {
            pf.close_point( p );
        }
    }

    // Start and end must not be closed
    pf.unclose_point( f );
    pf.unclose_point( t );
    pf.add_point( 0, 0, f, f );

    bool done = false;

    do {
        auto cur = pf.get_next();

        const int parent_index = flat_index( cur.x, cur.y );
        auto &layer = pf.get_layer( cur.z );
        auto &cur_state = layer.state[parent_index];
        if( cur_state == ASL_CLOSED ) {
            continue;
        }

        if( layer.gscore[parent_index] > max_length ) {
            // Shortest path would be too long, return empty vector
            return std::vector<tripoint>();
        }

        if( cur == t ) {
            done = true;
            break;
        }

        cur_state = ASL_CLOSED;

        const auto &pf_cache = get_pathfinding_cache_ref( cur.z );
        const auto cur_special = pf_cache.special[cur.x][cur.y];

        // 7 3 5
        // 1 . 2
        // 6 4 8
        constexpr std::array<int, 8> x_offset{{ -1,  1,  0,  0,  1, -1, -1, 1 }};
        constexpr std::array<int, 8> y_offset{{  0,  0, -1,  1, -1,  1, -1, 1 }};
        for( size_t i = 0; i < 8; i++ ) {
            const tripoint p( cur.x + x_offset[i], cur.y + y_offset[i], cur.z );
            const int index = flat_index( p.x, p.y );

            // @todo: Remove this and instead have sentinels at the edges
            if( p.x < minx || p.x >= maxx || p.y < miny || p.y >= maxy ) {
                continue;
            }

            if( layer.state[index] == ASL_CLOSED ) {
                continue;
            }

            // Penalize for diagonals or the path will look "unnatural"
            int newg = layer.gscore[parent_index] + ( ( cur.x != p.x && cur.y != p.y ) ? 1 : 0 );

            const auto p_special = pf_cache.special[p.x][p.y];
            // @todo: De-uglify, de-huge-n
            if( !( p_special & non_normal ) ) {
                // Boring flat dirt - the most common case above the ground
                newg += 2;
            } else {
                int part = -1;
                const maptile &tile = maptile_at_internal( p );
                const auto &terrain = tile.get_ter_t();
                const auto &furniture = tile.get_furn_t();
                const vehicle *veh = veh_at_internal( p, part );

                const int cost = move_cost_internal( furniture, terrain, veh, part );
                // Don't calculate bash rating unless we intend to actually use it
                const int rating = ( bash == 0 || cost != 0 ) ? -1 :
                                   bash_rating_internal( bash, furniture, terrain, false, veh, part );

                if( cost == 0 && rating <= 0 && ( !doors || !terrain.open ) && veh == nullptr && climb_cost <= 0 ) {
                    layer.state[index] = ASL_CLOSED; // Close it so that next time we won't try to calculate costs
                    continue;
                }

                newg += cost;
                if( cost == 0 ) {
                    if( climb_cost > 0 && p_special & PF_CLIMBABLE ) {
                        // Climbing fences
                        newg += climb_cost;
                    } else if( doors && terrain.open &&
                               ( !terrain.has_flag( "OPENCLOSE_INSIDE" ) || !is_outside( cur ) ) ) {
                        // Only try to open INSIDE doors from the inside
                        // To open and then move onto the tile
                        newg += 4;
                    } else if( veh != nullptr ) {
                        part = veh->obstacle_at_part( part );
                        int dummy = -1;
                        if( doors && veh->part_flag( part, VPFLAG_OPENABLE ) &&
                            ( !veh->part_flag( part, "OPENCLOSE_INSIDE" ) ||
                              veh_at_internal( cur, dummy ) == veh ) ) {
                            // Handle car doors, but don't try to path through curtains
                            newg += 10; // One turn to open, 4 to move there
                        } else if( part >= 0 && bash > 0 ) {
                            // Car obstacle that isn't a door
                            // @todo: Account for armor
                            int hp = veh->parts[part].hp();
                            if( hp / 20 > bash ) {
                                // Threshold damage thing means we just can't bash this down
                                layer.state[index] = ASL_CLOSED;
                                continue;
                            } else if( hp / 10 > bash ) {
                                // Threshold damage thing means we will fail to deal damage pretty often
                                hp *= 2;
                            }

                            newg += 2 * hp / bash + 8 + 4;
                        } else if( part >= 0 ) {
                            if( !doors || !veh->part_flag( part, VPFLAG_OPENABLE ) ) {
                                // Won't be openable, don't try from other sides
                                layer.state[index] = ASL_CLOSED;
                            }

                            continue;
                        }
                    } else if( rating > 1 ) {
                        // Expected number of turns to bash it down, 1 turn to move there
                        // and 5 turns of penalty not to trash everything just because we can
                        newg += ( 20 / rating ) + 2 + 10;
                    } else if( rating == 1 ) {
                        // Desperate measures, avoid whenever possible
                        newg += 500;
                    } else {
                        // Unbashable and unopenable from here
                        if( !doors || !terrain.open ) {
                            // Or anywhere else for that matter
                            layer.state[index] = ASL_CLOSED;
                        }

                        continue;
                    }
                }

                if( trapavoid && p_special & PF_TRAP ) {
                    const auto &ter_trp = terrain.trap.obj();
                    const auto &trp = ter_trp.is_benign() ? tile.get_trap_t() : ter_trp;
                    if( !trp.is_benign() ) {
                        // For now make them detect all traps
                        if( has_zlevels() && terrain.has_flag( TFLAG_NO_FLOOR ) ) {
                            // Special case - ledge in z-levels
                            // Warning: really expensive, needs a cache
                            if( valid_move( p, tripoint( p.x, p.y, p.z - 1 ), false, true ) ) {
                                tripoint below( p.x, p.y, p.z - 1 );
                                if( !has_flag( TFLAG_NO_FLOOR, below ) ) {
                                    // Otherwise this would have been a huge fall
                                    auto &layer = pf.get_layer( p.z - 1 );
                                    // From cur, not p, because we won't be walking on air
                                    pf.add_point( layer.gscore[parent_index] + 10,
                                                  layer.score[parent_index] + 10 + 2 * rl_dist( below, t ),
                                                  cur, below );
                                }

                                // Close p, because we won't be walking on it
                                layer.state[index] = ASL_CLOSED;
                                continue;
                            }
                        } else if( trapavoid ) {
                            // Otherwise it's walkable
                            newg += 500;
                        }
                    }
                }
            }

            // If not visited, add as open
            // If visited, add it only if we can do so with better score
            if( layer.state[index] == ASL_NONE || newg < layer.gscore[index] ) {
                pf.add_point( newg, newg + 2 * rl_dist( p, t ), cur, p );
            }
        }

        if( !has_zlevels() || !( cur_special & PF_UPDOWN ) || !settings.allow_climb_stairs ) {
            // The part below is only for z-level pathing
            continue;
        }

        const maptile &parent_tile = maptile_at_internal( cur );
        const auto &parent_terrain = parent_tile.get_ter_t();
        if( settings.allow_climb_stairs && cur.z > minz && parent_terrain.has_flag( TFLAG_GOES_DOWN ) ) {
            tripoint dest( cur.x, cur.y, cur.z - 1 );
            dest = vertical_move_destination<TFLAG_GOES_UP>( *this, dest );
            if( inbounds( dest ) ) {
                auto &layer = pf.get_layer( dest.z );
                pf.add_point( layer.gscore[parent_index] + 2,
                              layer.score[parent_index] + 2 * rl_dist( dest, t ),
                              cur, dest );
            }
        }
        if( settings.allow_climb_stairs && cur.z < maxz && parent_terrain.has_flag( TFLAG_GOES_UP ) ) {
            tripoint dest( cur.x, cur.y, cur.z + 1 );
            dest = vertical_move_destination<TFLAG_GOES_DOWN>( *this, dest );
            if( inbounds( dest ) ) {
                auto &layer = pf.get_layer( dest.z );
                pf.add_point( layer.gscore[parent_index] + 2,
                              layer.score[parent_index] + 2 * rl_dist( dest, t ),
                              cur, dest );
            }
        }
        if( cur.z < maxz && parent_terrain.has_flag( TFLAG_RAMP ) &&
            valid_move( cur, tripoint( cur.x, cur.y, cur.z + 1 ), false, true ) ) {
            auto &layer = pf.get_layer( cur.z + 1 );
            for( size_t it = 0; it < 8; it++ ) {
                const tripoint above( cur.x + x_offset[it], cur.y + y_offset[it], cur.z + 1 );
                pf.add_point( layer.gscore[parent_index] + 4,
                              layer.score[parent_index] + 4 + 2 * rl_dist( above, t ),
                              cur, above );
            }
        }
    } while( !done && !pf.empty() );

    if( done ) {
        ret.reserve( rl_dist( f, t ) * 2 );
        tripoint cur = t;
        // Just to limit max distance, in case something weird happens
        for( int fdist = max_length; fdist != 0; fdist-- ) {
            const int cur_index = flat_index( cur.x, cur.y );
            const auto &layer = pf.get_layer( cur.z );
            const tripoint &par = layer.parent[cur_index];
            if( cur == f ) {
                break;
            }

            ret.push_back( cur );
            // Jumps are acceptable on 1 z-level changes
            // This is because stairs teleport the player too
            if( rl_dist( cur, par ) > 1 && abs( cur.z - par.z ) != 1 ) {
                debugmsg( "Jump in our route! %d:%d:%d->%d:%d:%d",
                          cur.x, cur.y, cur.z, par.x, par.y, par.z );
                return ret;
            }

            cur = par;
        }

        std::reverse( ret.begin(), ret.end() );
    }

    return ret;
}
예제 #25
0
int
compute_move( int side_to_move,
	      int update_all,
	      int my_time,
	      int my_incr,
	      int timed_depth,
	      int book,
	      int mid,
	      int exact,
	      int wld,
	      int search_forced,
	      EvaluationType *eval_info ) {
  FILE *log_file;
  EvaluationType book_eval_info, mid_eval_info, end_eval_info;
  char *eval_str;
  double midgame_diff;
  enum { INTERRUPTED_MOVE, BOOK_MOVE, MIDGAME_MOVE, ENDGAME_MOVE } move_type;
  int i;
  int curr_move, midgame_move;
  int empties;
  int midgame_depth, interrupted_depth, max_depth;
  int book_move_found;
  int endgame_reached;
  int offset;

  log_file = NULL;
  if ( use_log_file )
    log_file = fopen( log_file_path, "a" );

  if ( log_file )
    display_board( log_file, board, side_to_move, FALSE, FALSE, FALSE );

  /* Initialize various components of the move system */

  piece_count[BLACKSQ][disks_played] = disc_count( BLACKSQ );
  piece_count[WHITESQ][disks_played] = disc_count( WHITESQ );
  init_moves();
  generate_all( side_to_move );
  determine_hash_values( side_to_move, board );

  calculate_perturbation();

  if ( log_file ) {
    fprintf( log_file, "%d %s: ", move_count[disks_played], MOVE_GEN_TEXT );
    for ( i = 0; i < move_count[disks_played]; i++ )
      fprintf( log_file, "%c%c ", TO_SQUARE( move_list[disks_played][i] ) );
    fputs( "\n", log_file );
  }

  if ( update_all ) {
    reset_counter( &evaluations );
    reset_counter( &nodes );
  }

  for ( i = 0; i < 100; i++ )
    evals[disks_played][i] = 0;
  max_depth_reached = 1;
  empties = 60 - disks_played;
  reset_buffer_display();

  determine_move_time( my_time, my_incr, disks_played + 4 );
  if ( !get_ponder_move() )
    clear_ponder_times();

  remove_coeffs( disks_played );

  /* No feasible moves? */

  if ( move_count[disks_played] == 0 ) {
    *eval_info = create_eval_info( PASS_EVAL, UNSOLVED_POSITION,
				   0.0, 0.0, 0, FALSE );
    set_current_eval( *eval_info );
    if ( echo ) {
      eval_str = produce_eval_text( *eval_info, FALSE );
      send_status( "-->         " );
      send_status( "%-8s  ", eval_str );
      display_status( stdout, FALSE );
      free( eval_str );
    }
    if ( log_file ) {
      fprintf( log_file, "%s: %s\n", BEST_MOVE_TEXT, PASS_TEXT );
      fclose( log_file );
    }
    last_time_used = 0.0;
    clear_pv();
    return PASS;
  }

  /* If there is only one move available:
     Don't waste any time, unless told so or very close to the end,
     searching the position. */
   	
  if ( (empties > DISABLE_FORCED_MOVES) &&
       (move_count[disks_played] == 1) &&
       !search_forced ) {  /* Forced move */
    *eval_info = create_eval_info( FORCED_EVAL, UNSOLVED_POSITION,
				   0.0, 0.0, 0, FALSE );
    set_current_eval( *eval_info );
    if ( echo ) {
      eval_str = produce_eval_text( *eval_info, FALSE );
      send_status( "-->         " );
      send_status( "%-8s  ", eval_str );
      free( eval_str );
      send_status( "%c%c ", TO_SQUARE( move_list[disks_played][0] ) );
      display_status( stdout, FALSE );
    }
    if ( log_file ) {
      fprintf( log_file, "%s: %c%c  (%s)\n", BEST_MOVE_TEXT,
	       TO_SQUARE(move_list[disks_played][0]), FORCED_TEXT );
      fclose( log_file );
    }
    last_time_used = 0.0;
    return move_list[disks_played][0];
  }

  /* Mark the search as interrupted until a successful search
     has been performed. */

  move_type = INTERRUPTED_MOVE;
  interrupted_depth = 0;
  curr_move = move_list[disks_played][0];

  /* Check the opening book for midgame moves */

  book_move_found = FALSE;
  midgame_move = PASS;

  if ( forced_opening != NULL ) {
    /* Check if the position fits the currently forced opening */
    curr_move = check_forced_opening( side_to_move, forced_opening );
    if ( curr_move != PASS ) {
      book_eval_info = create_eval_info( UNDEFINED_EVAL, UNSOLVED_POSITION,
					 0, 0.0, 0, TRUE );
      midgame_move = curr_move;
      book_move_found = TRUE;
      move_type = BOOK_MOVE;
      if ( echo ) {
	send_status( "-->   Forced opening move        " );
	if ( get_ponder_move() )
	  send_status( "{%c%c} ", TO_SQUARE( get_ponder_move() ) );
	send_status( "%c%c", TO_SQUARE( curr_move ) );
	display_status( stdout, FALSE );
      }
      clear_pv();
      pv_depth[0] = 1;
      pv[0][0] = curr_move;
    }
  }

  if ( !book_move_found && play_thor_match_openings ) {

    /* Optionally use the Thor database as opening book. */

    int threshold = 2;
    database_search( board, side_to_move );
    if ( get_match_count() >= threshold ) {
      int game_index = (my_random() >> 8) % get_match_count();
      curr_move = get_thor_game_move( game_index, disks_played );

      if ( valid_move( curr_move, side_to_move ) ) {
	book_eval_info = create_eval_info( UNDEFINED_EVAL, UNSOLVED_POSITION,
					   0, 0.0, 0, TRUE );
	midgame_move = curr_move;
	book_move_found = TRUE;
	move_type = BOOK_MOVE;
	if ( echo ) {
	  send_status( "-->   %s        ", THOR_TEXT );
	  if ( get_ponder_move() )
	    send_status( "{%c%c} ", TO_SQUARE( get_ponder_move() ) );
	  send_status( "%c%c", TO_SQUARE( curr_move ) );
	  display_status( stdout, FALSE );
	}
	clear_pv();
	pv_depth[0] = 1;
	pv[0][0] = curr_move;
      }
      else
	fatal_error( "Thor book move %d is invalid!", curr_move );
    }
예제 #26
0
JNIEXPORT void
JNIFn(zebra, ZebraEngine, zePlay)(JNIEnv *env, jobject thiz, jint providedMoveCount,
                                  jbyteArray providedMoves) {
    EvaluationType eval_info;
    const char *black_name;
    const char *white_name;
    const char *opening_name;
    const char *op;
    double move_start, move_stop;
    int i;
    int side_to_move;
    int curr_move;
    int timed_search;
    int black_hash1, black_hash2, white_hash1, white_hash2;
    ui_event_t evt;
    int provided_move_count;
    int provided_move_index;
    int provided_move[65];
    int silent = FALSE;
    int use_book = s_use_book;

    DROIDZEBRA_JNI_SETUP;

    force_exit = 0;

    if (skill[BLACKSQ] < 0 || skill[WHITESQ] < 0) {
        fatal_error("Set Player Info first");
    }

    /* copy provided moves */
    provided_move_index = 0;
    provided_move_count = 0;
    if (providedMoveCount > 0 && providedMoves) {
        jbyte *providedMovesJNI;
        provided_move_count = providedMoveCount;
        i = (*env)->GetArrayLength(env, providedMoves);
        if (provided_move_count > i)
            fatal_error("Provided move count is greater than array size %d>%d", provided_move_count,
                        i);
        if (provided_move_count > 64)
            fatal_error("Provided move count is greater that 64: %d", provided_move_count);
        providedMovesJNI = (*env)->GetByteArrayElements(env, providedMoves, 0);
        if (!providedMovesJNI)
            fatal_error("failed to get provide moves (jni)");
        for (i = 0; i < provided_move_count; i++) {
            provided_move[i] = providedMovesJNI[i];
        }
        (*env)->ReleaseByteArrayElements(env, providedMoves, providedMovesJNI, 0);
    }

    /* Set up the position and the search engine */
    game_init(NULL, &side_to_move);
    setup_hash(TRUE);
    clear_stored_game();
    set_slack(floor(s_slack * 128.0));
    set_perturbation(floor(s_perturbation * 128.0));
    toggle_human_openings(s_human_opening);
    set_forced_opening(s_forced_opening_seq);
    opening_name = NULL;

    reset_book_search();
    set_deviation_value(0, 0, 0.0);

    if (skill[BLACKSQ] == 0)
        black_name = "Player";
    else
        black_name = "Zebra";

    if (skill[WHITESQ] == 0)
        white_name = "Player";
    else
        white_name = "Zebra";

    set_names(black_name, white_name);
    set_move_list(black_moves, white_moves, score_sheet_row);
    set_evals(0.0, 0.0);

    for (i = 0; i < 60; i++) {
        black_moves[i] = PASS;
        white_moves[i] = PASS;
    }

    black_hash1 = my_random();
    black_hash2 = my_random();
    white_hash1 = my_random();
    white_hash2 = my_random();

    droidzebra_msg_game_start();

    AGAIN:
    curr_move = PASS;
    while (game_in_progress() && !force_exit) {
        force_return = 0;
        silent = (provided_move_index < provided_move_count);

        droidzebra_enable_messaging(!silent);

        droidzebra_msg_move_start(side_to_move);

        remove_coeffs(disks_played);
        clear_evaluated();

        if (SEPARATE_TABLES) {  /* Computer players won't share hash tables */
            if (side_to_move == BLACKSQ) {
                hash1 ^= black_hash1;
                hash2 ^= black_hash2;
            } else {
                hash1 ^= white_hash1;
                hash2 ^= white_hash2;
            }
        }

        generate_all(side_to_move);

        if (side_to_move == BLACKSQ)
            score_sheet_row++;

        // echo
        droidzebra_msg_candidate_moves();
        set_move_list(black_moves, white_moves, score_sheet_row);
        set_times(floor(player_time[BLACKSQ]),
                  floor(player_time[WHITESQ]));
        op = find_opening_name();
        if (op != NULL && (!opening_name || strcmp(op, opening_name))) {
            opening_name = op;
        }
        droidzebra_msg_opening_name(opening_name);
        droidzebra_msg_last_move(disks_played > 0 ? get_stored_move(disks_played - 1) : PASS);
        display_board(stdout, board, side_to_move, TRUE, TRUE, TRUE);
        // echo

        if (move_count[disks_played] != 0) {
            move_start = get_real_timer();
            clear_panic_abort();

            if (provided_move_index >= provided_move_count) {
                if (skill[side_to_move] == 0) {
                    curr_move = -1;

                    if (auto_make_forced_moves && move_count[disks_played] == 1) {
                        curr_move = move_list[disks_played][0];
                    } else {
                        // compute evaluations
                        if (s_practice_mode) {
                            _droidzebra_compute_evals(side_to_move);
                            if (force_exit) break;
                            if (force_return) force_return = 0; // interrupted by user input
                        }

                        // wait for user event
                        droidzebra_msg_get_user_input(side_to_move, &evt);
                        if (evt.type == UI_EVENT_EXIT) {
                            force_exit = 1;
                            break;
                        } else if (evt.type == UI_EVENT_MOVE) {
                            curr_move = evt.evt_move.move;
                            _droidzebra_undo_stack_clear(); // once player makes the move undo info is stale
                        } else if (evt.type == UI_EVENT_UNDO) {
                            _droidzebra_undo_turn(&side_to_move);
                            // adjust for increment at the beginning of the game loop
                            if (side_to_move == BLACKSQ)
                                score_sheet_row--;
                            continue;
                        } else if (evt.type == UI_EVENT_REDO) {
                            _droidzebra_redo_turn(&side_to_move);
                            // adjust for increment at the beginning of the game loop
                            if (side_to_move == BLACKSQ)
                                score_sheet_row--;
                            continue;
                        } else if (evt.type == UI_EVENT_SETTINGS_CHANGE) {
                            _droidzebra_on_settings_change();
                            // repeat move on settings change
                            if (side_to_move == BLACKSQ)
                                score_sheet_row--; // adjust for increment at the beginning of the game loop
                            continue;
                        } else {
                            fatal_error("Unsupported UI event: %d", evt.type);
                        }
                    }
                    assert(curr_move >= 0);
                } else {
                    start_move(player_time[side_to_move],
                               player_increment[side_to_move],
                               disks_played + 4);
                    determine_move_time(player_time[side_to_move],
                                        player_increment[side_to_move],
                                        disks_played + 4);
                    timed_search = (skill[side_to_move] >= 60);
                    toggle_experimental(FALSE);

                    curr_move =
                            compute_move(side_to_move, TRUE, player_time[side_to_move],
                                         player_increment[side_to_move], timed_search,
                                         use_book, skill[side_to_move],
                                         exact_skill[side_to_move], wld_skill[side_to_move],
                                         FALSE, &eval_info);
                    if (side_to_move == BLACKSQ)
                        set_evals(produce_compact_eval(eval_info), 0.0);
                    else
                        set_evals(0.0, produce_compact_eval(eval_info));
                }
            } else {
                curr_move = provided_move[provided_move_index];
                if (!valid_move(curr_move, side_to_move))
                    fatal_error("Invalid move %c%c in move sequence", TO_SQUARE(curr_move));
            }

            move_stop = get_real_timer();
            if (player_time[side_to_move] != INFINIT_TIME)
                player_time[side_to_move] -= (move_stop - move_start);

            store_move(disks_played, curr_move);

            (void) make_move(side_to_move, curr_move, TRUE);
            if (side_to_move == BLACKSQ)
                black_moves[score_sheet_row] = curr_move;
            else {
                white_moves[score_sheet_row] = curr_move;
            }
        } else {
            // this is where we pass
            if (side_to_move == BLACKSQ)
                black_moves[score_sheet_row] = PASS;
            else
                white_moves[score_sheet_row] = PASS;
            if (!auto_make_forced_moves && skill[side_to_move] == 0) {
                droidzebra_msg_pass();
            }
        }

        droidzebra_msg_move_end(side_to_move);

        side_to_move = OPP(side_to_move);

        provided_move_index++;
    }

    droidzebra_enable_messaging(TRUE);

    if (side_to_move == BLACKSQ)
        score_sheet_row++;

    set_move_list(black_moves, white_moves, score_sheet_row);
    set_times(floor(player_time[BLACKSQ]), floor(player_time[WHITESQ]));
    droidzebra_msg_opening_name(opening_name);
    display_board(stdout, board, side_to_move, TRUE, TRUE, TRUE);

    /*
    double node_val, eval_val;
    adjust_counter( &total_nodes );
    node_val = counter_value( &total_nodes );
    adjust_counter( &total_evaluations );
    eval_val = counter_value( &total_evaluations );
    printf( "\nBlack: %d   White: %d\n", disc_count( BLACKSQ ),
            disc_count( WHITESQ ) );
    printf( "Nodes searched:        %-10.0f\n", node_val );

    printf( "Positions evaluated:   %-10.0f\n", eval_val );

    printf( "Total time: %.1f s\n", total_time );
    */

    if (!force_exit)
        droidzebra_msg_game_over();

    // loop here until we are told to exit so the user has a chance to undo
    while (!force_exit) {
        droidzebra_msg_get_user_input(side_to_move, &evt);
        if (evt.type == UI_EVENT_EXIT) {
            force_exit = 1;
            break;
        } else if (evt.type == UI_EVENT_UNDO) {
            _droidzebra_undo_turn(&side_to_move);
            // adjust for increment at the beginning of the game loop
            if (side_to_move == BLACKSQ)
                score_sheet_row--;
            goto AGAIN;
        } else if (evt.type == UI_EVENT_SETTINGS_CHANGE) {
            _droidzebra_on_settings_change();
        }
    }

    DROIDZEBRA_JNI_CLEAN;
}
예제 #27
0
파일: traffic.c 프로젝트: BHoweBHowe/school
int main() {
    FILE* bFile;
    char *board = malloc(sizeof(char) * 128);
    int cars[26][3];
    char car = '\0'; // car to move
    char dir = '\0'; // direction of move
    int amount = -1; // number of spaces to move
    int temp = 0;

    print_heading(3, "The Traffic Game");

    bFile = fopen("board.txt", "r");
    if(bFile == NULL) {
        printf("Could not open file board.txt.\n");
        return -1;
    }

    scan_board(bFile, board, cars);

    fclose(bFile);

    printf("Welcome to the traffic game!\n\n");
    printf("Move the vehicles so that the Red car (RR) can\n");
    printf("exit the board to the right. Each move should be\n");
    printf("of the form:    CDN    where C is the vehicle to\n");
    printf("be moved,  D ids the direction (u for up, d for down,\n");
    printf("l for left or r for right), and N is the number of\n");
    printf("squares to move it. For example GR2 means move the\n");
    printf("G vehicle to the right 2 squares. Lower-case input\n");
    printf("such as   gr2   is also accepted.   Entre x to exit the\n");
    printf("program.\n");

    while(1) {
        print_board(board);

        do {
            get_input(&car, &dir, &amount);

            // printf("\n%c%c%d\n", car, dir, amount); //for testing

            if(car == 'X') {
                printf("Thanks for playing! Exiting...\n");
                free(board);
                return 0;
            }

            temp = valid_move(car, dir, amount, cars, board);

            if(! temp) {
                printf("Move not valid. try again.\n");
            }

        }while(! temp);

        if(make_move(car, dir, amount, cars, board)) {
            print_board(board);
            printf("\nCongradulations!! You Win!!!\n\n");
            printf("Thanks for playing! Exiting...\n");
            free(board);
            return 0;
        }
    }
}