Пример #1
0
//--------- Begin of function UnitB::process_move --------//
// process unit movement
//
void UnitB::process_move()
{
	//----- if the sprite has reach the destintion ----//

	if( cur_x==go_x && cur_y==go_y )
	{
		err_when( cur_x!=next_x || cur_y!=next_y );	// if the unit reach its destination, then	cur_? == next_? == go_?

		if( cur_path_result_id > 0)		// 0 means it has completed all its move
		{
			next_move();

			if( cur_action != SPRITE_MOVE )     // if next_move() is not successful, the movement has been stopped
				return;

			if(cur_action==SPRITE_MOVE && cur_x==go_x && cur_y==go_y)
				next_move();
		}
	}

	err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));

	//------- call Sprite::process_move --------//

	Sprite::process_move();

	err_when( cur_x < 0 || cur_y < 0 || cur_x >= MAX_WORLD_X_LOC * LOCATE_WIDTH || cur_y >= MAX_WORLD_Y_LOC * LOCATE_HEIGHT );
	//---- reset the wait counter when the unit moves ----//

	wait_count = 0;
}
Пример #2
0
int quiescent(app_t *app, cnodeptr_t parent, int alpha, int beta)
{
	int i, score = -MATE;
	node_t node;
	int delta = 200;

	init_node(&node);

	assert(app);

	app->search.nodes++;

	/* max depth */
	if (app->game.board->ply > (SEARCH_MAXDEPTH - 1)) {
		return evaluate(app->game.board);
	}

	/* draws */
	if (repetitions(app) || (app->game.board->half >= 100)) {
		return 0;
	}

	score = evaluate(app->game.board);

	if (score >= beta) return beta;
	/* delta pruning based on a material value of delta (this should be disabled
	   in the endgame) */
	/* The idea here is that, even if our score can improve alpha, it doesn't
	   improve it by a significant amount, so don't bother searching these nodes */
	if (score < (alpha - delta)) return alpha;
	if (score > alpha) alpha = score;


	/* generate moves (with separate captures) */
	generate_moves(app->game.board, &node.ml, &node.cl);

	for (i = 0; i < node.cl.count; i++) {
		/* get the next move ordered */
		next_move(i, &node.cl);

		if (!(do_move(app->game.board, &app->game.undo, node.cl.moves[i])))
			continue;

		score = -quiescent(app, &node, -beta, -alpha);

		node.made++;
		undo_move(app->game.board, &app->game.undo);

		if (score > alpha) {
			if (score >= beta) {
				return beta;
			}

			/* update alpha */
			alpha = score;
		}
	}

	return alpha;
}
Пример #3
0
// -------------------------------------------------------
// This is the one function called by the timer interrupt.
// It calls a few other functions, though.
// -------------------------------------------------------
/// Take a step or go to the next move.
void queue_step() {
	// do our next step
	DDA* current_movebuffer = &movebuffer[mb_tail];
	if (current_movebuffer->live) {
		if (current_movebuffer->waitfor_temp) {
			setTimer(HEATER_WAIT_TIMEOUT);
			if (temp_achieved()) {
				current_movebuffer->live = current_movebuffer->waitfor_temp = 0;
				serial_writestr_P(PSTR("Temp achieved\n"));
			}

			#if STEP_INTERRUPT_INTERRUPTIBLE
				sei();
			#endif
		}
		else {
			// NOTE: dda_step makes this interrupt interruptible after steps have been sent but before new speed is calculated.
			dda_step(current_movebuffer);
		}
	}

	// fall directly into dda_start instead of waiting for another step
	// the dda dies not directly after its last step, but when the timer fires and there's no steps to do
	if (current_movebuffer->live == 0)
		next_move();
}
Пример #4
0
void enqueue(TARGET *t)
{
	// don't call this function when the queue is full, but just in case, wait for a move to complete and free up the space for the passed target
	while (queue_full())
		delay(WAITING_DELAY);

	uint8_t h = mb_head + 1;
	h &= (MOVEBUFFER_SIZE - 1);

	if (t != NULL)
	{
		dda_create(&movebuffer[h], t);
	}
	else
	{
		// it's a wait for temp
		movebuffer[h].waitfor_temp = 1;
		movebuffer[h].nullmove = 0;
		// set "step" timeout to maximum
		movebuffer[h].c = 0xFFFFFF00;
	}

	mb_head = h;

	// fire up in case we're not running yet
	if (isHwTimerEnabled(0) == 0)
		next_move();
}
Пример #5
0
// -------------------------------------------------------
// This is the one function called by the timer interrupt.
// It calls a few other functions, though.
// -------------------------------------------------------
void queue_step()
{
	// do our next step
	if (movebuffer[mb_tail].live)
	{
		if (movebuffer[mb_tail].waitfor_temp)
		{
			if (temp_achieved(EXTRUDER_0))
			{
				movebuffer[mb_tail].live = movebuffer[mb_tail].waitfor_temp = 0;
				serial_writestr("Temp achieved\r\n");
			}
		}
		else
		{
			// NOTE: dda_step makes this interrupt interruptible after steps have been sent but before new speed is calculated.
			dda_step(&(movebuffer[mb_tail]));
		}
	}

	// fall directly into dda_start instead of waiting for another step
	// the dda dies not directly after its last step, but when the timer fires and there's no steps to do
	if (movebuffer[mb_tail].live == 0)
		next_move();
}
Пример #6
0
int main()
{
	int q;
	srand(time(0));	
	init_ncurses();
	
	new SnakeHead(Snake_map);
	
	erase();
	Snake_map.display();
	q = getch();
	
	int Game_over = 1;
	while (Game_over)
	{
		q = -1;
		erase();
		Snake_map.display();
		printw("%d\n", Snake_map.cnt_food());
		halfdelay(1);
		q = getch();
		Game_over = next_move(q);
		usleep(40000);
	}
	erase();
	printw("YOU LOOSE!\nYour score: %d\n\n\nPlease ENTER!\n", Snake_map.cnt_food());
	nocbreak();
	getch();
	endwin();
	return 0;
}
Пример #7
0
int main(){
    uint i = 0;
    uint double_count = 0;
    vector<uint> probs(40, 0);
    uint limit = 1000000;
    for(uint j = 0; j < limit; j++){
        i = next_move(i, double_count);
        probs[i]++;
    }

    //Find 3 largest values
    uint min = limit;
    for(uint k = 0; k < 3; k++){
        uint max = 0;
        uint tmp = 0;
        for(uint j = 0; j < 40; j++){
            if(probs[j] > max && probs[j] < min){
                max = probs[j];
                tmp = j;
            }
        }
        cout << setfill('0') << setw(2) << tmp;
        min = max;
    }
        cout << endl;
}
Пример #8
0
void play_game(void) {
    // Identify myself
    fprintf(stdout, "#name %s\n", name);
    fflush(stdout);

    // Wait for start of game
    wait_for_start();

    // Main game loop
    for (;;) {
        if (current_player == my_player) {
            // My turn
            // Check if game is over (optional)

            // Determine next move
            next_move();

            // Apply it to local state

            // Tell the world
            print_and_recv_echo(next_move_cache);

            // It is the opponents turn
            current_player = (current_player == player1) ? player2 : player1;
        } else {
            // Wait for move from other player
            // Get server's next instruction
            read_msg_and_tokenize();

            if (tokens_size == 6 && strcmp(tokens[0], "MOVE") == 0) {
                // Translate to local coordinates and update our local state

                // It is now my turn
                current_player = (current_player == player1) ? player2 : player1;
            } else if (tokens_size == 4 && strcmp(tokens[0], "FINAL") == 0 &&
                       strcmp(tokens[2], "BEATS") == 0) {
                // Game over
                if (strcmp(tokens[1], name) == 0 && strcmp(tokens[3], opp_name) == 0) {
                    fprintf(stderr, "I, %s, have won!\n", name);
                    fflush(stderr);
                } else if (strcmp(tokens[3], name) == 0&& strcmp(tokens[1], opp_name) == 0) {
                    fprintf(stderr, "I, %s, have lost.\n", name);
                    fflush(stderr);
                } else {
                    fprintf(stderr, "Did not find expected players in FINAL command.\n");
                    fprintf(stderr, "Found '%s' and '%s'.\n", tokens[1], tokens[3]);
                    fprintf(stderr, "Expected '%s' and '%s'.\n", name, opp_name);
                    fprintf(stderr, "Received message '%s'\n", message);
                    fflush(stderr);
                }
                break;
            } else {
                // Unknown command
                fprintf(stderr, "Unknown command of '%s' from the server\n", message);
                fflush(stderr);
            }
        }
    }
}
Пример #9
0
PacSolver::Result PacSolver::process()
{
    std::deque<PacBoard *>::iterator itr = this_generation.begin();
    std::vector<Position> next_pos;

    if (this_generation.empty()) {
        std::cout << "all generation extinct." << std::endl;
        return PacSolver::Failed;
    }

    if (this_generation[0]->rest_time_counter == 0) {
        std::cout << "all generation timed up." << std::endl;
        return PacSolver::Failed;
    }

    while (itr != this_generation.end()) {
        next_pos = trunc_next_pos(*itr, next_move(*itr));

        if (next_pos.empty()) {
            PacBoard *branch_top = (*itr)->find_and_cut_last_branch();
            delete branch_top;
        }

        std::vector<Position>::iterator pi = next_pos.begin();
        while (pi != next_pos.end()) {
            PacBoard *child = (*itr)->create_and_register_child(*pi);
            if (child->dots == 0) {
                end_board = child;
                return PacSolver::Solved;
            }
            if (child->dots < remaining_dots) {
                remaining_dots = child->dots;
                delete highest_score_now;
                highest_score_now = new PacBoard(*child);
            }
            next_generation.push_back(child);
            pi ++;
        }
        itr ++;
    }

    if (next_generation.size() > threshold_leaves) {
        std::sort(next_generation.begin(), next_generation.end(), Comparator());
        for (int i = trunc_leaves_to; i < next_generation.size(); i ++) {
            PacBoard *b = next_generation[i]->find_and_cut_last_branch();
            delete b;
        }
        next_generation.resize(trunc_leaves_to);
    }
    this_generation = next_generation;
    next_generation.clear();
    return PacSolver::Solving;
}
// -------------------------------------------------------
// This is the one function called by the timer interrupt.
// It calls a few other functions, though.
// -------------------------------------------------------
/// Take a step or go to the next move.
void queue_step() {
        // do our next step
        DDA* current_movebuffer = &movebuffer[mb_tail];
        if (current_movebuffer->live) {
                // NOTE: dda_step makes this interrupt interruptible after steps have been sent but before new speed is calculated.
                dda_step(current_movebuffer);
        }

        // fall directly into dda_start instead of waiting for another step
        // the dda dies not directly after its last step, but when the timer fires and there's no steps to do
        if (current_movebuffer->live == 0)
                next_move();
}
Пример #11
0
void enqueue_home(TARGET *t, uint8_t endstop_check, uint8_t endstop_stop_cond) {
	// don't call this function when the queue is full, but just in case, wait for a move to complete and free up the space for the passed target
	while (queue_full())
		delay(WAITING_DELAY);

	uint8_t h = mb_head + 1;
	h &= (MOVEBUFFER_SIZE - 1);

	DDA* new_movebuffer = &(movebuffer[h]);
	
	if (t != NULL) {
		dda_create(new_movebuffer, t);
		new_movebuffer->endstop_check = endstop_check;
		new_movebuffer->endstop_stop_cond = endstop_stop_cond;
	}
	else {
		// it's a wait for temp
		new_movebuffer->waitfor_temp = 1;
		new_movebuffer->nullmove = 0;
	}

	// make certain all writes to global memory
	// are flushed before modifying mb_head.
	MEMORY_BARRIER();
	
	mb_head = h;
	
	uint8_t save_reg = SREG;
	cli();
	CLI_SEI_BUG_MEMORY_BARRIER();

	uint8_t isdead = (movebuffer[mb_tail].live == 0);
	
	MEMORY_BARRIER();
	SREG = save_reg;
	
	if (isdead) {
		timer1_compa_deferred_enable = 0;
		next_move();
		if (timer1_compa_deferred_enable) {
			uint8_t save_reg = SREG;
			cli();
			CLI_SEI_BUG_MEMORY_BARRIER();
			
			TIMSK1 |= MASK(OCIE1A);
			
			MEMORY_BARRIER();
			SREG = save_reg;
		}
	}	
}
Пример #12
0
static void eload(Space *s, uint8_t old_type, int32_t &addr) {
	uint8_t num = read_8(addr);
	if (!s->setup_nums(num, num)) {
		debug("Failed to set up extruder axes");
		uint8_t n = min(s->num_axes, s->num_motors);
		if (!s->setup_nums(n, n)) {
			debug("Trouble!  Failed to abort.  Cancelling.");
			s->cancel_update();
		}
	}
	for (int a = EDATA(s).num_axes; a < s->num_axes; ++a) {
		s->axis[a]->type_data = new ExtruderAxisData;
		for (int i = 0; i < 3; ++i)
			EADATA(s, a).offset[i] = 0;
	}
	EDATA(s).num_axes = s->num_axes;
	bool move = false;
	if (motors_busy && !computing_move && settings.queue_start == settings.queue_end && !settings.queue_full) {
		move = true;
		queue[settings.queue_end].probe = false;
		queue[settings.queue_end].cb = false;
		queue[settings.queue_end].f[0] = INFINITY;
		queue[settings.queue_end].f[1] = INFINITY;
		for (int i = 0; i < spaces[0].num_axes; ++i) {
			queue[settings.queue_end].data[i] = spaces[0].axis[i]->settings.current;
			for (int ss = 0; ss < 2; ++ss)
				queue[settings.queue_end].data[i] = space_types[spaces[ss].type].unchange0(&spaces[ss], i, queue[settings.queue_end].data[i]);
			if (i == 2)
				queue[settings.queue_end].data[i] -= zoffset;
		}
		for (int i = spaces[0].num_axes; i < QUEUE_LENGTH; ++i) {
			queue[settings.queue_end].data[i] = NAN;
		}
		cpdebug(0, 0, "eload end");
		settings.queue_end = (settings.queue_end + 1) % QUEUE_LENGTH;
		// This shouldn't happen and causes communication problems, but if you have a 1-item buffer it is correct.
		if (settings.queue_end == settings.queue_start)
			settings.queue_full = true;
	}
	for (int a = 0; a < s->num_axes; ++a) {
		for (int o = 0; o < 3; ++o)
			EADATA(s, a).offset[o] = read_float(addr);
	}
	if (move) {
		next_move();
		buffer_refill();
	}
}
Пример #13
0
enum Status move_snake(Board* board, enum Direction dir) {
  // Create a new beginning. Check boundaries.
  PointList* beginning = next_move(board, dir);
  if (beginning == NULL) {
    return FAILURE;
  }

  // If we've gone backwards, don't do anything
  if (board->snake->next && is_same_place(beginning, board->snake->next)) {
    beginning->next = NULL;
    free(beginning);
    return SUCCESS;
  }

  // Check for collisions
  if (list_contains(beginning, board->snake)) {
    return FAILURE;
  }

  // Check for food
  if (list_contains(beginning, board->foods)) {
    // Attach the beginning to the rest of the snake;
    beginning->next = board->snake;
    board->snake = beginning;
    remove_from_list(beginning, &(board->foods));
    add_new_food(board);

    return SUCCESS;
  }

  // Attach the beginning to the rest of the snake
  beginning->next = board->snake;
  board->snake = beginning;


  // Cut off the end
  PointList* end = board->snake;
  while(end->next->next) {
    end = end->next;
  }
  free(end->next);
  end->next = NULL;

  return SUCCESS;
}
Пример #14
0
void queue_step(){
    DDA *current_movebuffer = &movebuffer[mb_tail];
    if(current_movebuffer->live){
        if(current_movebuffer->waitfor_temp){
            setTimer(HEATER_WAIT_TIMEOUT);
            if(temp_achieved()){
                current_movebuffer->live = current_movebuffer->waitfor_temp = 0;
                serial_writestr_P(PSTR("Temp achieved\n"));
            }//end if temp achieved
        }//endif waitfortemp
        else{
            dda_step(current_movebuffer);
        }
    }//end if current_movebuffer->live

    if(current_movebuffer->live == 0)
        next_move();
}//queue_step()
Пример #15
0
/// add a move to the movebuffer
/// \note this function waits for space to be available if necessary, check queue_full() first if waiting is a problem
/// This is the only function that modifies mb_head and it always called from outside an interrupt.
void enqueue_home(TARGET *t, uint8_t endstop_check, uint8_t endstop_stop_cond) {
	// don't call this function when the queue is full, but just in case, wait for a move to complete and free up the space for the passed target
	while (queue_full())
		delay_us(100);

	uint8_t h = mb_head + 1;
	h &= (MOVEBUFFER_SIZE - 1);

	DDA* new_movebuffer = &(movebuffer[h]);
  DDA* prev_movebuffer = (queue_empty() != 0) ? NULL : &movebuffer[mb_head];

  if (t != NULL) {
    dda_create(new_movebuffer, t, prev_movebuffer);
		new_movebuffer->endstop_check = endstop_check;
		new_movebuffer->endstop_stop_cond = endstop_stop_cond;
	}
	else {
		// it's a wait for temp
		new_movebuffer->waitfor_temp = 1;
		new_movebuffer->nullmove = 0;
	}

	// make certain all writes to global memory
	// are flushed before modifying mb_head.
	MEMORY_BARRIER();

	mb_head = h;

  uint8_t isdead;

  ATOMIC_START
    isdead = (movebuffer[mb_tail].live == 0);
  ATOMIC_END

	if (isdead) {
		next_move();
		// Compensate for the cli() in setTimer().
		sei();
	}
}
Пример #16
0
// -------------------------------------------------------
// This is the one function called by the timer interrupt.
// It calls a few other functions, though.
// -------------------------------------------------------
/// Take a step or go to the next move.
void queue_step() {
	// do our next step
	DDA* current_movebuffer = &movebuffer[mb_tail];
	if (current_movebuffer->live) {
		if (current_movebuffer->waitfor_temp) {
			setTimer(HEATER_WAIT_TIMEOUT);
			if (temp_achieved()) {
				current_movebuffer->live = current_movebuffer->waitfor_temp = 0;
				serial_writestr_P(PSTR("Temp achieved\n"));
			}
		}
		else {
			// NOTE: dda_step makes this interrupt interruptible for some time,
			//       see STEP_INTERRUPT_INTERRUPTIBLE.
			dda_step(current_movebuffer);
		}
	}

  // Start the next move if this one is done.
	if (current_movebuffer->live == 0)
		next_move();
}
Пример #17
0
void enqueue_home(TARGET *t, unsigned char  endstop_check, unsigned char endstop_stop_cond){

	while(queue_full()){
		for(int __i = 0;__i<5000;__i++);
	}

	unsigned char h = mb_head + 1;
	h &= (MOVEBUFFER_SIZE - 1);

	DDA *new_move = &movebuffer[h];

	// Initialise queue entry to a known state. This also clears flags like
	// dda->live, dda->done and dda->wait_for_temp.
	new_move->allflags = 0;

	if (t != NULL) {
		new_move->endstop_check = endstop_check;
		new_move->endstop_stop_cond = endstop_stop_cond;
	}
	else {
		// it's a wait for temp
		new_move->waitfor_temp = 1;
	}
	dda_create(new_move, t);

	// make certain all writes to global memory
	// are flushed before modifying mb_head.

	mb_head = h;

	unsigned char isdead;

	isdead = (movebuffer[mb_tail].live == 0);

	if (isdead) {
		next_move();
	}
}
// -------------------------------------------------------
// This is the one function called by the timer interrupt.
// It calls a few other functions, though.
// -------------------------------------------------------
/// Take a step or go to the next move.
void queue_step() {
	// do our next step
	DDA* current_movebuffer = &movebuffer[mb_tail];
	if (current_movebuffer->live) {
		if (current_movebuffer->waitfor_temp) {
			setTimer(HEATER_WAIT_TIMEOUT);
			if (temp_achieved()) {
				current_movebuffer->live = current_movebuffer->waitfor_temp = 0;
				printf("Temp achieved\n");
			}
		}
		else {
			// NOTE: dda_step makes this interrupt interruptible for some time,
			//       see STEP_INTERRUPT_INTERRUPTIBLE.
			dda_step(current_movebuffer);
		}
	}

	// fall directly into dda_start instead of waiting for another step
	// the dda dies not directly after its last step, but when the timer fires and there's no steps to do
	if (current_movebuffer->live == 0)
		next_move();
}
Пример #19
0
static void handle_motors(unsigned long long current_time) { // {{{
	// Check for move.
	if (!computing_move) {
		movedebug("handle motors not moving");
		return;
	}
	movedebug("handling %d %d", computing_move, cbs_after_current_move);
	double factor = 1;
	double t = (current_time - settings.start_time) / 1e6;
	if (t >= settings.t0 + settings.tp) {	// Finish this move and prepare next. {{{
		movedebug("finishing %f %f %f %ld %ld", t, settings.t0, settings.tp, long(current_time), long(settings.start_time));
		//debug("finish steps");
		for (int s = 0; s < NUM_SPACES; ++s) {
			if (!settings.single && s == 2)
				continue;
			Space &sp = spaces[s];
			bool new_move = false;
			if (!isnan(sp.settings.dist[0])) {
				for (int a = 0; a < sp.num_axes; ++a) {
					if (!isnan(sp.axis[a]->settings.dist[0])) {
						sp.axis[a]->settings.source += sp.axis[a]->settings.dist[0];
						sp.axis[a]->settings.dist[0] = NAN;
						//debug("new source %d %f", a, sp.axis[a]->settings.source);
					}
				}
				sp.settings.dist[0] = NAN;
			}
			for (int a = 0; a < sp.num_axes; ++a)
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			move_axes(&sp, current_time, factor);
			//debug("f %f", factor);
		}
		//debug("f2 %f %ld %ld", factor, settings.last_time, current_time);
		bool did_steps = do_steps(factor, current_time);
		//debug("f3 %f", factor);
		// Start time may have changed; recalculate t.
		t = (current_time - settings.start_time) / 1e6;
		if (t / (settings.t0 + settings.tp) >= done_factor) {
			int had_cbs = cbs_after_current_move;
			//debug("clearing %d cbs after current move for later inserting into history", cbs_after_current_move);
			cbs_after_current_move = 0;
			run_file_fill_queue();
			if (settings.queue_start != settings.queue_end || settings.queue_full) {
				had_cbs += next_move();
				if (!aborting && had_cbs > 0) {
					int fragment;
					if (num_active_motors == 0)
						fragment = (current_fragment + FRAGMENTS_PER_BUFFER - 1) % FRAGMENTS_PER_BUFFER;
					else
						fragment = current_fragment;
					//debug("adding %d cbs to fragment %d", had_cbs, fragment);
					history[fragment].cbs += had_cbs;
				}
				return;
			}
			cbs_after_current_move += had_cbs;
			//debug("adding %d to cbs after current move making it %d", had_cbs, cbs_after_current_move);
			if (factor == 1) {
				//debug("queue done");
				if (!did_steps) {
					//debug("done move");
					computing_move = false;
					// Cut off final sample, which was no steps anyway.
					current_fragment_pos -= 1;
				}
				for (int s = 0; s < NUM_SPACES; ++s) {
					Space &sp = spaces[s];
					for (int m = 0; m < sp.num_motors; ++m)
						sp.motor[m]->settings.last_v = 0;
				}
				if (cbs_after_current_move > 0) {
					if (!aborting) {
						int fragment;
						if (num_active_motors == 0)
							if (running_fragment == current_fragment) {
								//debug("sending movecbs immediately");
								send_host(CMD_MOVECB, cbs_after_current_move);
								cbs_after_current_move = 0;
								return;
							}
							else
								fragment = (current_fragment + FRAGMENTS_PER_BUFFER - 1) % FRAGMENTS_PER_BUFFER;
						else
							fragment = current_fragment;
						//debug("adding %d cbs to final fragment %d", cbs_after_current_move, fragment);
						history[fragment].cbs += cbs_after_current_move;
					}
					//debug("clearing %d cbs after current move in final", cbs_after_current_move);
					cbs_after_current_move = 0;
				}
			}
		}
		return;
	} // }}}
	if (t < settings.t0) {	// Main part. {{{
		double t_fraction = t / settings.t0;
		double current_f = (settings.f1 * (2 - t_fraction) + settings.f2 * t_fraction) * t_fraction;
		movedebug("main t %f t0 %f tp %f tfrac %f f1 %f f2 %f cf %f", t, settings.t0, settings.tp, t_fraction, settings.f1, settings.f2, current_f);
		//debug("main steps");
		for (int s = 0; s < NUM_SPACES; ++s) {
			if (!settings.single && s == 2)
				continue;
			Space &sp = spaces[s];
			for (int a = 0; a < sp.num_axes; ++a) {
				if (isnan(sp.axis[a]->settings.dist[0])) {
					sp.axis[a]->settings.target = NAN;
					continue;
				}
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			}
			make_target(sp, current_f, false);
			move_axes(&sp, current_time, factor);
		}
	} // }}}
	else {	// Connector part. {{{
		movedebug("connector %f %f %f", t, settings.t0, settings.tp);
		double tc = t - settings.t0;
		double t_fraction = tc / settings.tp;
		double current_f2 = settings.fp * (2 - t_fraction) * t_fraction;
		double current_f3 = settings.fq * t_fraction * t_fraction;
		//debug("connect steps");
		for (int s = 0; s < NUM_SPACES; ++s) {
			if (!settings.single && s == 2)
				continue;
			Space &sp = spaces[s];
			for (int a = 0; a < sp.num_axes; ++a) {
				if (isnan(sp.axis[a]->settings.dist[0]) && isnan(sp.axis[a]->settings.dist[1])) {
					sp.axis[a]->settings.target = NAN;
					continue;
				}
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			}
			make_target(sp, (1 - settings.fp) + current_f2, false);
			make_target(sp, current_f3, true);
			move_axes(&sp, current_time, factor);
		}
	} // }}}
	do_steps(factor, current_time);
} // }}}
Пример #20
0
Value name_NT_InCheck(qsearch)(Pos* pos, Stack* ss, Value alpha, BETA_ARG
                               Depth depth)
{
  assert(InCheck == !!pos_checkers());
  assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
  assert(PvNode || (alpha == beta - 1));
  assert(depth <= DEPTH_ZERO);

  Move pv[MAX_PLY+1];
  TTEntry *tte;
  Key posKey;
  Move ttMove, move, bestMove;
  Value bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha;
  int ttHit, ttPv, givesCheck, evasionPrunable;
  Depth ttDepth;
  int moveCount;

  if (PvNode) {
    oldAlpha = alpha; // To flag BOUND_EXACT when eval above alpha and no available moves
    (ss+1)->pv = pv;
    ss->pv[0] = 0;
  }

  bestMove = 0;
  moveCount = 0;

  // Check for an instant draw or if the maximum ply has been reached
  if (is_draw(pos) || ss->ply >= MAX_PLY)
    return ss->ply >= MAX_PLY && !InCheck ? evaluate(pos) : VALUE_DRAW;

  assert(0 <= ss->ply && ss->ply < MAX_PLY);

  // Decide whether or not to include checks: this fixes also the type of
  // TT entry depth that we are going to use. Note that in qsearch we use
  // only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
  ttDepth = InCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS
                                                : DEPTH_QS_NO_CHECKS;

  // Transposition table lookup
  posKey = pos_key();
  tte = tt_probe(posKey, &ttHit);
  ttValue = ttHit ? value_from_tt(tte_value(tte), ss->ply) : VALUE_NONE;
  ttMove = ttHit ? tte_move(tte) : 0;
  ttPv = ttHit ? tte_is_pv(tte) : 0;

  if (  !PvNode
      && ttHit
      && tte_depth(tte) >= ttDepth
      && ttValue != VALUE_NONE // Only in case of TT access race
      && (ttValue >= beta ? (tte_bound(tte) &  BOUND_LOWER)
                          : (tte_bound(tte) &  BOUND_UPPER)))
    return ttValue;

  // Evaluate the position statically
  if (InCheck) {
    ss->staticEval = VALUE_NONE;
    bestValue = futilityBase = -VALUE_INFINITE;
  } else {
    if (ttHit) {
      // Never assume anything on values stored in TT
      if ((ss->staticEval = bestValue = tte_eval(tte)) == VALUE_NONE)
         ss->staticEval = bestValue = evaluate(pos);

      // Can ttValue be used as a better position evaluation?
      if (ttValue != VALUE_NONE)
        if (tte_bound(tte) & (ttValue > bestValue ? BOUND_LOWER : BOUND_UPPER))
          bestValue = ttValue;
    } else
      ss->staticEval = bestValue =
      (ss-1)->currentMove != MOVE_NULL ? evaluate(pos)
                                       : -(ss-1)->staticEval + 2 * Tempo;

    // Stand pat. Return immediately if static value is at least beta
    if (bestValue >= beta) {
      if (!ttHit)
        tte_save(tte, posKey, value_to_tt(bestValue, ss->ply), ttPv,
                 BOUND_LOWER, DEPTH_NONE, 0, ss->staticEval,
                 tt_generation());

      return bestValue;
    }

    if (PvNode && bestValue > alpha)
      alpha = bestValue;

    futilityBase = bestValue + 128;
  }

  ss->history = &(*pos->counterMoveHistory)[0][0];

  // Initialize move picker data for the current position, and prepare
  // to search the moves. Because the depth is <= 0 here, only captures,
  // queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
  // be generated.
  mp_init_q(pos, ttMove, depth, to_sq((ss-1)->currentMove));

  // Loop through the moves until no moves remain or a beta cutoff occurs
  while ((move = next_move(pos, 0))) {
    assert(move_is_ok(move));

    givesCheck = gives_check(pos, ss, move);

    moveCount++;

    // Futility pruning
    if (   !InCheck
        && !givesCheck
        &&  futilityBase > -VALUE_KNOWN_WIN
        && !advanced_pawn_push(pos, move)) {
      assert(type_of_m(move) != ENPASSANT); // Due to !advanced_pawn_push

      futilityValue = futilityBase + PieceValue[EG][piece_on(to_sq(move))];

      if (futilityValue <= alpha) {
        bestValue = max(bestValue, futilityValue);
        continue;
      }

      if (futilityBase <= alpha && !see_test(pos, move, 1)) {
        bestValue = max(bestValue, futilityBase);
        continue;
      }
    }

    // Detect non-capture evasions that are candidates to be pruned
    evasionPrunable =    InCheck
                     && (depth != DEPTH_ZERO || moveCount > 2)
                     &&  bestValue > VALUE_MATED_IN_MAX_PLY
                     && !is_capture(pos, move);

    // Don't search moves with negative SEE values
    if (  (!InCheck || evasionPrunable)
        &&  !see_test(pos, move, 0))
      continue;

    // Speculative prefetch as early as possible
    prefetch(tt_first_entry(key_after(pos, move)));

    // Check for legality just before making the move
    if (!is_legal(pos, move)) {
      moveCount--;
      continue;
    }

    ss->currentMove = move;
    ss->history = &(*pos->counterMoveHistory)[moved_piece(move)][to_sq(move)];

    // Make and search the move
    do_move(pos, move, givesCheck);
#if PvNode
    value =  givesCheck
           ? -qsearch_PV_true(pos, ss+1, -beta, -alpha, depth - ONE_PLY)
           : -qsearch_PV_false(pos, ss+1, -beta, -alpha, depth - ONE_PLY);
#else
    value =  givesCheck
           ? -qsearch_NonPV_true(pos, ss+1, -beta, depth - ONE_PLY)
           : -qsearch_NonPV_false(pos, ss+1, -beta, depth - ONE_PLY);
#endif
    undo_move(pos, move);

    assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);

    // Check for a new best move
    if (value > bestValue) {
      bestValue = value;

      if (value > alpha) {
        bestMove = move;

        if (PvNode) // Update pv even in fail-high case
          update_pv(ss->pv, move, (ss+1)->pv);

        if (PvNode && value < beta) // Update alpha here!
          alpha = value;
        else
          break; // Fail high
      }
    }
  }

  // All legal moves have been searched. A special case: If we're in check
  // and no legal moves were found, it is checkmate.
  if (InCheck && bestValue == -VALUE_INFINITE)
    return mated_in(ss->ply); // Plies to mate from the root

  tte_save(tte, posKey, value_to_tt(bestValue, ss->ply), ttPv,
           bestValue >= beta ? BOUND_LOWER :
           PvNode && bestValue > oldAlpha  ? BOUND_EXACT : BOUND_UPPER,
           ttDepth, bestMove, ss->staticEval, tt_generation());

  assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);

  return bestValue;
}
Пример #21
0
GameMove* Moderator::getMove(GameState& state, const std::string& last_move) {
    const auto&& m = next_move(static_cast<DomineeringState&>(state));
    return new DomineeringMove(m);
}
Пример #22
0
static void handle_motors(unsigned long long current_time) { // {{{
	// Check for move.
	if (!computing_move) {
		movedebug("handle motors not moving");
		return;
	}
	movedebug("handling %d", computing_move);
	double factor = 1;
	double t = (current_time - settings.start_time) / 1e6;
	if (t >= settings.t0 + settings.tp) {	// Finish this move and prepare next. {{{
		movedebug("finishing %f %f %f %ld %ld", t, settings.t0, settings.tp, long(current_time), long(settings.start_time));
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			bool new_move = false;
			if (!isnan(sp.settings.dist[0])) {
				for (uint8_t a = 0; a < sp.num_axes; ++a) {
					if (!isnan(sp.axis[a]->settings.dist[0])) {
						sp.axis[a]->settings.source += sp.axis[a]->settings.dist[0];
						sp.axis[a]->settings.dist[0] = NAN;
						//debug("new source %d %f", a, sp.axis[a]->settings.source);
					}
				}
				sp.settings.dist[0] = NAN;
			}
			for (uint8_t a = 0; a < sp.num_axes; ++a)
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			move_axes(&sp, current_time, factor);
			//debug("f %f", factor);
		}
		//debug("f2 %f %ld %ld", factor, settings.last_time, current_time);
		bool did_steps = do_steps(factor, current_time);
		//debug("f3 %f", factor);
		// Start time may have changed; recalculate t.
		t = (current_time - settings.start_time) / 1e6;
		if (t / (settings.t0 + settings.tp) >= done_factor) {
			uint8_t had_cbs = cbs_after_current_move;
			cbs_after_current_move = 0;
			run_file_fill_queue();
			if (settings.queue_start != settings.queue_end || settings.queue_full) {
				had_cbs += next_move();
				if (!aborting && had_cbs > 0) {
					//debug("adding %d cbs to fragment %d", had_cbs, current_fragment);
					history[current_fragment].cbs += had_cbs;
				}
				return;
			}
			cbs_after_current_move += had_cbs;
			if (factor == 1) {
				//debug("queue done");
				if (!did_steps) {
					//debug("done move");
					computing_move = false;
				}
				for (uint8_t s = 0; s < 2; ++s) {
					Space &sp = spaces[s];
					for (uint8_t m = 0; m < sp.num_motors; ++m)
						sp.motor[m]->settings.last_v = 0;
				}
				if (cbs_after_current_move > 0) {
					if (!aborting) {
						//debug("adding %d cbs to final fragment %d", cbs_after_current_move, current_fragment);
						history[current_fragment].cbs += cbs_after_current_move;
					}
					cbs_after_current_move = 0;
				}
			}
		}
		return;
	} // }}}
	if (t < settings.t0) {	// Main part. {{{
		double t_fraction = t / settings.t0;
		double current_f = (settings.f1 * (2 - t_fraction) + settings.f2 * t_fraction) * t_fraction;
		movedebug("main t %f t0 %f tp %f tfrac %f f1 %f f2 %f cf %f", t, settings.t0, settings.tp, t_fraction, settings.f1, settings.f2, current_f);
		for (int s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			for (uint8_t a = 0; a < sp.num_axes; ++a) {
				if (isnan(sp.axis[a]->settings.dist[0])) {
					sp.axis[a]->settings.target = NAN;
					continue;
				}
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			}
			make_target(sp, current_f, false);
			move_axes(&sp, current_time, factor);
		}
	} // }}}
	else {	// Connector part. {{{
		movedebug("connector %f %f %f", t, settings.t0, settings.tp);
		double tc = t - settings.t0;
		double t_fraction = tc / settings.tp;
		double current_f2 = settings.fp * (2 - t_fraction) * t_fraction;
		double current_f3 = settings.fq * t_fraction * t_fraction;
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			for (uint8_t a = 0; a < sp.num_axes; ++a) {
				if (isnan(sp.axis[a]->settings.dist[0]) && isnan(sp.axis[a]->settings.dist[1])) {
					sp.axis[a]->settings.target = NAN;
					continue;
				}
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			}
			make_target(sp, (1 - settings.fp) + current_f2, false);
			make_target(sp, current_f3, true);
			move_axes(&sp, current_time, factor);
		}
	} // }}}
	do_steps(factor, current_time);
} // }}}
Пример #23
0
void Client::play_game() {
  // Identify myself
  std::cout << "#name " << name << std::endl;

  // Wait for start of game
  wait_for_start();

  // Main game loop
  for (;;) {
    if (current_player == my_player) {
      // My turn

      // Check if game is over
      /*
      if (gs.game_over()) {
        std::cerr << "I, " << name << ", have lost" << std::endl;
        switch_current_player();
        continue;
      }
      */

      // Determine next move
      const Move m = next_move();

      // Apply it locally
      // gs.apply_move(m);

      // Tell the world
      print_and_recv_echo(m);

      // It is the opponents turn
      switch_current_player();
    } else {
      // Wait for move from other player
      // Get server's next instruction
      std::string server_msg = read_msg();
      const std::vector<std::string> tokens = tokenize_msg(server_msg);

      if (tokens.size() == 5 && tokens[0] == "MOVE") {
        // Translate to local coordinates and update our local state
        // const Move m = gs.translate_to_local(tokens);
        // gs.apply_move(m);

        // It is now my turn
        switch_current_player();
      } else if (tokens.size() == 4 && tokens[0] == "FINAL" &&
                 tokens[2] == "BEATS") {
        // Game over
        if (tokens[1] == name && tokens[3] == opp_name)
          std::cerr << "I, " << name << ", have won!" << std::endl;
        else if (tokens[3] == name && tokens[1] == opp_name)
          std::cerr << "I, " << name << ", have lost." << std::endl;
        else
          std::cerr << "Did not find expected players in FINAL command.\n"
                    << "Found '" << tokens[1] << "' and '" << tokens[3] << "'. "
                    << "Expected '" << name << "' and '" << opp_name << "'.\n"
                    << "Received message '" << server_msg << "'" << std::endl;
        break;
      } else {
        // Unknown command
        std::cerr << "Unknown command of '" << server_msg << "' from the server"
                  << std::endl;
      }
    }
  }
}
Пример #24
0
void run_file_fill_queue() {
	static bool lock = false;
	if (lock)
		return;
	lock = true;
	rundebug("run queue, wait = %d tempwait = %d q = %d %d %d finish = %d", run_file_wait, run_file_wait_temp, settings.queue_end, settings.queue_start, settings.queue_full, run_file_finishing);
	if (run_file_audio >= 0) {
		while (true) {
			if (!run_file_map || run_file_wait || run_file_finishing)
				break;
			if (settings.run_file_current >= run_file_num_records) {
				run_file_finishing = true;
				//debug("done running audio");
				break;
			}
			int16_t next = (current_fragment + 1) % FRAGMENTS_PER_BUFFER;
			if (next == running_fragment)
				break;
			settings.run_file_current = arch_send_audio(&reinterpret_cast <uint8_t *>(run_file_map)[sizeof(double)], settings.run_file_current, run_file_num_records, run_file_audio);
			current_fragment = next;
			store_settings();
			if ((current_fragment - running_fragment + FRAGMENTS_PER_BUFFER) % FRAGMENTS_PER_BUFFER >= MIN_BUFFER_FILL && !stopping)
				arch_start_move(0);
		}
		lock = false;
		return;
	}
	while (run_file_map	// There is a file to run.
			&& (settings.queue_end - settings.queue_start + QUEUE_LENGTH) % QUEUE_LENGTH < 4	// There is space in the queue.
			&& !settings.queue_full	// Really, there is space in the queue.
			&& settings.run_file_current < run_file_num_records	// There are records to send.
			&& !run_file_wait_temp	// We are not waiting for a temp alarm.
			&& !run_file_wait	// We are not waiting for something else (pause or confirm).
			&& !run_file_finishing) {	// We are not waiting for underflow (should be impossible anyway, if there are commands in the queue).
		int t = run_file_map[settings.run_file_current].type;
		if (t != RUN_LINE && t != RUN_PRE_LINE && t != RUN_PRE_ARC && t != RUN_ARC && (arch_running() || settings.queue_end != settings.queue_start || computing_move))
			break;
		Run_Record &r = run_file_map[settings.run_file_current];
		rundebug("running %d: %d %d", settings.run_file_current, r.type, r.tool);
		switch (r.type) {
			case RUN_SYSTEM:
			{
				char const *cmd = strndupa(&reinterpret_cast<char const *>(run_file_map)[run_file_first_string + strings[r.tool].start], strings[r.tool].len);
				debug("Running system command: %ld %d %s", strings[r.tool].start, strings[r.tool].len, cmd);
				int ret = system(cmd);
				debug("Done running system command, return = %d", ret);
				break;
			}
			case RUN_PRE_ARC:
			{
				double x = r.X * run_file_cosa - r.Y * run_file_sina + run_file_refx;
				double y = r.Y * run_file_cosa + r.X * run_file_sina + run_file_refy;
				double z = r.Z;
				//debug("line %f %f %f", x, y, z);
				queue[settings.queue_end].center[0] = x;
				queue[settings.queue_end].center[1] = y;
				queue[settings.queue_end].center[2] = handle_probe(x, y, z);
				queue[settings.queue_end].normal[0] = r.E;
				queue[settings.queue_end].normal[1] = r.f;
				queue[settings.queue_end].normal[2] = r.F;
				break;
			}
			case RUN_PRE_LINE:
			{
				run_preline.X = r.X;
				run_preline.Y = r.Y;
				run_preline.Z = r.Z;
				run_preline.E = r.E;
				run_preline.tool = r.tool;
				break;
			}
			case RUN_LINE:
			case RUN_ARC:
			{
				queue[settings.queue_end].single = false;
				queue[settings.queue_end].probe = false;
				queue[settings.queue_end].arc = r.type == RUN_ARC;
				queue[settings.queue_end].f[0] = r.f;
				queue[settings.queue_end].f[1] = r.F;
				double x = r.X * run_file_cosa - r.Y * run_file_sina + run_file_refx;
				double y = r.Y * run_file_cosa + r.X * run_file_sina + run_file_refy;
				double z = r.Z;
				//debug("line/arc %f %f %f", x, y, z);
				int num0 = spaces[0].num_axes;
				if (num0 > 0) {
					queue[settings.queue_end].data[0] = x;
					if (num0 > 1) {
						queue[settings.queue_end].data[1] = y;
						if (num0 > 2) {
							queue[settings.queue_end].data[2] = handle_probe(x, y, z);
							if (num0 > 3) {
								queue[settings.queue_end].data[3] = run_preline.X;
								if (num0 > 4) {
									queue[settings.queue_end].data[4] = run_preline.Y;
									if (num0 > 5) {
										queue[settings.queue_end].data[5] = run_preline.Z;
									}
								}
								run_preline.X = NAN;
								run_preline.Y = NAN;
								run_preline.Z = NAN;
							}
						}
					}
				}
				for (int i = 6; i < num0; ++i)
					queue[settings.queue_end].data[i] = NAN;
				for (int i = 0; i < spaces[1].num_axes; ++i) {
					queue[settings.queue_end].data[num0 + i] = (i == r.tool ? r.E : i == run_preline.tool ? run_preline.E : NAN);
					//debug("queue %d + %d = %f", num0, i, queue[settings.queue_end].data[num0 + i]);
				}
				run_preline.E = NAN;
				num0 += spaces[1].num_axes;
				for (int s = 2; s < NUM_SPACES; ++s) {
					for (int i = 0; i < spaces[s].num_axes; ++i)
						queue[settings.queue_end].data[num0 + i] = NAN;
					num0 += spaces[s].num_axes;
				}
				queue[settings.queue_end].time = r.time;
				queue[settings.queue_end].dist = r.dist;
				queue[settings.queue_end].cb = false;
				settings.queue_end = (settings.queue_end + 1) % QUEUE_LENGTH;
				if (!computing_move)
					next_move();
				else
					rundebug("no");
				buffer_refill();
				break;
			}
			case RUN_GPIO:
			{
				int tool = r.tool;
				if (tool == -2)
					tool = fan_id;
				else if (tool == -3)
					tool = spindle_id;
				if (tool < 0 || tool >= num_gpios) {
					if (tool != -1)
						debug("cannot set invalid gpio %d", tool);
					break;
				}
				if (r.X) {
					gpios[tool].state = 1;
					SET(gpios[tool].pin);
				}
				else {
					gpios[tool].state = 0;
					RESET(gpios[tool].pin);
				}
				send_host(CMD_UPDATE_PIN, tool, gpios[tool].state);
				break;
			}
			case RUN_SETTEMP:
			{
				int tool = r.tool;
				if (tool == -1)
					tool = bed_id;
				rundebug("settemp %d %f", tool, r.X);
				settemp(tool, r.X);
				send_host(CMD_UPDATE_TEMP, tool, 0, r.X);
				break;
			}
			case RUN_WAITTEMP:
			{
				int tool = r.tool;
				if (tool == -2)
					tool = bed_id;
				if (tool == -3) {
					for (int i = 0; i < num_temps; ++i) {
						if (temps[i].min_alarm >= 0 || temps[i].max_alarm < MAXINT) {
							run_file_wait_temp += 1;
							waittemp(i, temps[i].min_alarm, temps[i].max_alarm);
						}
					}
					break;
				}
				if (tool < 0 || tool >= num_temps) {
					if (tool != -1)
						debug("cannot wait for invalid temp %d", tool);
					break;
				}
				else
					rundebug("waittemp %d", tool);
				if (temps[tool].adctarget[0] >= 0 && temps[tool].adctarget[0] < MAXINT) {
					rundebug("waiting");
					run_file_wait_temp += 1;
					waittemp(tool, temps[tool].target[0], temps[tool].max_alarm);
				}
				else
					rundebug("not waiting");
				break;
			}
			case RUN_SETPOS:
				if (r.tool >= spaces[1].num_axes) {
					debug("Not setting position of invalid extruder %d", r.tool);
					break;
				}
				setpos(1, r.tool, r.X);
				break;
			case RUN_WAIT:
				if (r.X > 0) {
					run_file_timer.it_value.tv_sec = r.X;
					run_file_timer.it_value.tv_nsec = (r.X - run_file_timer.it_value.tv_sec) * 1e9;
					run_file_wait += 1;
					timerfd_settime(pollfds[0].fd, 0, &run_file_timer, NULL);
				}
				break;
			case RUN_CONFIRM:
			{
				int len = min(strings[r.tool].len, 250);
				memcpy(datastore, &reinterpret_cast<char const *>(run_file_map)[run_file_first_string + strings[r.tool].start], len);
				run_file_wait += 1;
				send_host(CMD_CONFIRM, r.X ? 1 : 0, 0, 0, 0, len);
				break;
			}
			case RUN_PARK:
				run_file_wait += 1;
				send_host(CMD_PARKWAIT);
				break;
			default:
				debug("Invalid record type %d in %s", r.type, run_file_name);
				break;
		}
		settings.run_file_current += 1;
	}
	rundebug("run queue done");
	if (run_file_map && settings.run_file_current >= run_file_num_records && !run_file_wait_temp && !run_file_wait && !run_file_finishing) {
		// Done.
		//debug("done running file");
		if (!computing_move && !sending_fragment && !arch_running()) {
			send_host(CMD_FILE_DONE);
			abort_run_file();
		}
		else
			run_file_finishing = true;
	}
	lock = false;
	return;
}
Пример #25
0
void RallyX::run_game()
{
	int player_x = 25;		// player co-ords on the map
	int player_y = 5;


	bool done = false;
	bool redraw = false;
	bool keys[4] = {false, false, false, false};
	bool player_movement[4] = {false, false, false, false};

	bitset<4> next_move ("0001");			// for movement; needs refinement...almost there tho...couple of hours...
	bitset<4> current_move ("0000");
	//keys = player_movement;

	int pos_x = 0;		// allows movement pixel wise, before changing position on the grid
	bitset<4> surrounding ("0000");

	int pos_y = 0;		// so movement is not jumpy by tile size

	int speed = 5;		// speed of movement between grid change



	////////////////////////////////////////////////

	// try to create checkpoints at random points, with a total num of 10
	// 10 is declared at the top of this file
	// this for-loop instantiate checkpoints and put them into a vector of checkpoints
	// while updating tiled_map1 by modifying _game_map to

	// still need to do: 
	// 1. destructors are called more than it's supposed to i.e. 9 times???
	// 2. try figure out a way to not let vector go out of bounds when destroying the last element
	// 3. _although make tiled_map1 = _game_map.get_map() in the end, map is still not updated??? i.e. still have checkpoint everywhere

	

	while (all_checkpoints.size() < num_of_checkpoints)							//to make sure always generate num_of_checkpoints
	{
		int col = rand()%(tiled_map1.size()-1);
		int row = rand()%(tiled_map1[col].size()-1);

		if (tiled_map1[col][row] == 1)
		{
			Checkpoint newCheckpoint(col, row);
			all_checkpoints.push_back(newCheckpoint);
			_game_map.add_checkpoints(col, row);
			//_game_map.delete_checkpoints(col,row);
		}
	}
	
	int added_rocks = 0;

	while (num_of_rocks > added_rocks)										
	{
		int col = rand()%(tiled_map1.size()-1);
		int row = rand()%(tiled_map1[col].size()-1);
		cout << "add rock!" << endl;

		if (tiled_map1[col][row] == 1)
		{
			Rock newRock(col, row);
			_game_map.add_rocks(col, row);
			//_game_map.delete_rocks(col,row);
			added_rocks ++;
		}
		
	}

	tiled_map1 = _game_map.get_map();									// HAVE TO KEEP ON UPDATING tiled_map1 otherwise new info cannot be loaded

	//////////////////////////////////////////////////////////////////


	while(!done)
	{

		ALLEGRO_EVENT ev;
		al_wait_for_event(resources.event_queue, &ev);

		if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
		{
			next_move.reset();
			switch(ev.keyboard.keycode)
			{
			case ALLEGRO_KEY_UP:
				next_move[UP] = true;
				break;
			case ALLEGRO_KEY_RIGHT:
				next_move[RIGHT] = true;
				break;
			case ALLEGRO_KEY_DOWN:
				next_move[DOWN] = true;
				break;
			case ALLEGRO_KEY_LEFT:
				next_move[LEFT] = true;
				break;
			}
		}

		surrounding[UP] =  tiled_map1[player_y - 1][player_x];		// must change so that a implementation of a 2d vector is unknown
		surrounding[RIGHT] =  tiled_map1[player_y][player_x + 1];
		surrounding[DOWN] =  tiled_map1[player_y + 1][player_x];
		surrounding[LEFT] =  tiled_map1[player_y][player_x - 1];

		if (pos_y == 0 && pos_x == 0)
		{
			/*if (next_move.none())
			{
				if ((current_move & ~(surrounding)).none())
					current_move >>=1;

			}
			else*/
			{
				current_move = next_move & surrounding; 
				//next_move.reset();
			}
		}


		if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
		{
			done = true;
		}
		else if(ev.type == ALLEGRO_EVENT_TIMER)
		{
			pos_y += current_move[UP] * speed;		// if no movement will equal 0
			pos_y -= current_move[DOWN]  * speed;
			pos_x += current_move[LEFT]   * speed;
			pos_x -= current_move[RIGHT]  * speed;

			if (pos_y <= -(tile_size))		
			{
				pos_y = 0;
				player_y++;		// increase player on grid if movement between is the distance of the grid
			}
			else if (pos_y >= (tile_size))
			{
				pos_y = 0;
				player_y--;
			} 

			if (pos_x <= -(tile_size))
			{
				pos_x = 0;
				player_x++;
			}
			else if (pos_x >= (tile_size))
			{
				pos_x = 0;
				player_x--;
			} 

			redraw = true;
		}

		if(redraw && al_is_event_queue_empty(resources.event_queue))
		{
			redraw = false;

			al_clear_to_color(al_map_rgb(0,0,0));
			

			for (int irow = -1; irow != tiles_per_display + 1; irow++)		// always 17; due to viewport size and one extra on either side
			{
				for (int icol = -1; icol != tiles_per_display + 1; icol++) 
				{
					if ((player_y - 7 + irow < out_of_bounds_map) || (player_x - 7 + icol < out_of_bounds_map) ) 
					{
						al_draw_bitmap(_bitmaps.out_of_bounds, (icol * tile_size) + pos_x , (irow * tile_size) + pos_y, 0);		// draw bitmap with co-ordintes locked to the grid co-ords as well as distance traveled
					}
					else if (tiled_map1[player_y - 7 + irow][player_x - 7 + icol] == road_map)
					{
						al_draw_bitmap(_bitmaps.road, (icol * tile_size) + pos_x , (irow * tile_size) + pos_y, 0);
					}
					////////////////////////////////I PUT STUFF HERE///////////////////////////////////////////////////////
					else if(tiled_map1[player_y - 7 + irow][player_x - 7 + icol] == checkpoint_map)
					{
						al_draw_bitmap(_bitmaps.checkpoint, (icol * tile_size) + pos_x , (irow * tile_size) + pos_y, 0);
					}
					else if(tiled_map1[player_y - 7 + irow][player_x - 7 + icol] == rock_map)
					{
						al_draw_bitmap(_bitmaps.rock, (icol * tile_size) + pos_x , (irow * tile_size) + pos_y, 0);
					}
					
					////////////////////////////////I PUT STUFF HERE///////////////////////////////////////////////////////
					else
						al_draw_bitmap(_bitmaps.wall,(icol * tile_size) + pos_x, (irow * tile_size) + pos_y, 0);

				}

			}

			float pi = 3.1415926;
			al_draw_bitmap(_bitmaps.player, (7 * tile_size) , (7 * tile_size), 0);		// draw player car ( always in this position due to centered)
			al_draw_rotated_bitmap(_bitmaps.player, tile_size/2, tile_size/2, (7 * tile_size) , (7 * tile_size), pi, 0);		// draw player car ( always in this position due to centered)


			// if checkpoint is at the middle of the screen, call destroy_checkpoint
			// which calls the destructor, update the map and let player go one step closer to winning the game
			//for (int i = 0; i<Map::all_checkpoints.size(); i++)
			//{
			//	if (Map::all_checkpoints.)
			//}

			draw_info_board();

			al_flip_display();
		}
	}


}
Пример #26
0
// Used from previous segment (if prepared): tp, vq.
uint8_t next_move() { // {{{
	settings.probing = false;
	moving_to_current = 0;
	uint8_t num_cbs = 0;
	uint8_t a0;
	run_file_fill_queue();
	if (settings.queue_start == settings.queue_end && !settings.queue_full) {
		//debug("no next move");
		computing_move = false;
		prepared = false;
		return num_cbs;
	}
#ifdef DEBUG_MOVE
	debug("Next move; queue start = %d, end = %d", settings.queue_start, settings.queue_end);
#endif
	// Set everything up for running queue[settings.queue_start].
	uint8_t n = (settings.queue_start + 1) % QUEUE_LENGTH;

	// Make sure printer state is good. {{{
	// If the source is unknown, determine it from current_pos.
	//for (uint8_t a = 0; a < num_axes; ++a)
	//	debug("target %d %f", a, queue[settings.queue_start].data[a]);
	for (uint8_t s = 0; s < 2; ++s) {
		Space &sp = spaces[s];
		for (uint8_t a = 0; a < sp.num_axes; ++a) {
			if (isnan(sp.axis[a]->settings.source)) {
				space_types[sp.type].reset_pos(&sp);
				for (uint8_t aa = 0; aa < sp.num_axes; ++aa)
					sp.axis[aa]->settings.current = sp.axis[aa]->settings.source;
				break;
			}
#ifdef DEBUG_MOVE
			else
				debug("non-nan: %d %d %f %d", s, a, sp.axis[a]->settings.source, sp.motor[a]->settings.current_pos);
#endif
		}
	}
	// }}}

	settings.f0 = settings.fq;
	// If no move is prepared, set dist[1] from the queue; it will be used as dist[0] below. {{{
	if (!prepared) {
#ifdef DEBUG_MOVE
		debug("No move prepared.");
#endif
		settings.f0 = 0;
		a0 = 0;
		change0(settings.queue_start);
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			space_types[sp.type].check_position(&sp, &queue[settings.queue_start].data[a0]);
			sp.settings.dist[0] = 0;
			for (int a = 0; a < sp.num_axes; ++a) {
				sp.axis[a]->settings.dist[0] = 0;
				sp.axis[a]->settings.endpos[0] = sp.axis[a]->settings.source;
			}
			set_from_queue(s, settings.queue_start, a0, false);
			a0 += sp.num_axes;
		}
	}
	// }}}
	// Fill unspecified coordinates with previous values. {{{
	a0 = 0;
	for (uint8_t s = 0; s < 2; ++s) {
		Space &sp = spaces[s];
		for (uint8_t a = 0; a < sp.num_axes; ++a) {
			if (n != settings.queue_end) {
				// If only one of them is set, set the other one as well to make the rounded corner work.
				if (!isnan(queue[settings.queue_start].data[a0 + a]) && isnan(queue[n].data[a0 + a])) {
					queue[n].data[a0 + a] = sp.axis[a]->settings.source + sp.axis[a]->settings.dist[1] - (s == 0 && a == 2 ? zoffset : 0);
#ifdef DEBUG_MOVE
					debug("filling next %d with %f", a0 + a, queue[n].data[a0 + a]);
#endif
				}
				if (isnan(queue[settings.queue_start].data[a]) && !isnan(queue[n].data[a])) {
					queue[settings.queue_start].data[a0 + a] = sp.axis[a]->settings.source;
#ifdef DEBUG_MOVE
					debug("filling %d with %f", a0 + a, queue[settings.queue_start].data[a0 + a]);
#endif
				}
			}
			if ((!isnan(queue[settings.queue_start].data[a0 + a]) || (n != settings.queue_end && !isnan(queue[n].data[a0 + a]))) && isnan(sp.axis[a]->settings.source)) {
				debug("Motor positions are not known, so move cannot take place; aborting move and removing it from the queue: %f %f %f", queue[settings.queue_start].data[a0 + a], queue[n].data[a0 + a], sp.axis[a]->settings.source);
				// This possibly removes one move too many, but it shouldn't happen anyway.
				if (queue[settings.queue_start].cb)
					++num_cbs;
				if (settings.queue_end == settings.queue_start)
					send_host(CMD_CONTINUE, 0);
				settings.queue_start = n;
				settings.queue_full = false;
				abort_move(current_fragment_pos);
				return num_cbs;
			}
		}
		a0 += sp.num_axes;
	}
	// }}}
	// We are prepared and can start the segment.
	bool action = false;
	double vq;
	if (n == settings.queue_end) { // There is no next segment; we should stop at the end. {{{
		prepared = false;
#ifdef DEBUG_MOVE
		debug("Building final segment.");
#endif
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			copy_next(s);
			if (sp.settings.dist[0] != 0)
				action = true;
		}
		vq = 0;
	}
	// }}}
	else { // There is a next segment; we should connect to it. {{{
		prepared = true;
#ifdef DEBUG_MOVE
		debug("Building a connecting segment.");
#endif
		a0 = 0;
		change0(n);
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			space_types[sp.type].check_position(&sp, &queue[n].data[a0]);
			copy_next(s);
			set_from_queue(s, n, a0, true);
			if (sp.settings.dist[1] != 0 || sp.settings.dist[0] != 0)
				action = true;
			a0 += sp.num_axes;
		}
		vq = queue[n].f[0] * feedrate;
	}
	// }}}

	double v0 = queue[settings.queue_start].f[0] * feedrate;
	double vp = queue[settings.queue_start].f[1] * feedrate;
	settings.probing = queue[settings.queue_start].probe;
	settings.run_time = queue[settings.queue_start].time;
	settings.run_dist = queue[settings.queue_start].dist;

	if (queue[settings.queue_start].cb)
		cbs_after_current_move += 1;
	//debug("add cb to current starting at %d", current_fragment);
	if (settings.queue_end == settings.queue_start)
		send_host(CMD_CONTINUE, 0);
	settings.queue_full = false;
	settings.queue_start = n;

	if (!action) {	// Skip zero-distance move. {{{
#ifdef DEBUG_MOVE
		debug("Skipping zero-distance prepared move");
#endif
		num_cbs += cbs_after_current_move;
		cbs_after_current_move = 0;
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			sp.settings.dist[0] = NAN;
			for (uint8_t a = 0; a < sp.num_axes; ++a)
				sp.axis[a]->settings.dist[0] = NAN;
		}
		settings.fq = 0;
		return num_cbs + next_move();
	} // }}}

	// Currently set up:
	// f0: fraction of move already done by connection.
	// v0: this move's requested starting speed.
	// vp: this move's requested ending speed.
	// vq: next move's requested starting speed.
	// cbs_after_current_move: number of cbs that should be fired after this segment is complete.
	// dist[0]: total distance of this segment (mm).
	// dist[1]: total distance of next segment (mm).
	// mtr->dist[0]: motor distance of this segment (mm).
	// mtr->dist[1]: motor distance of next segment (mm).
#ifdef DEBUG_MOVE
	debug("Set up: v0 = %f /s, vp = %f /s, vq = %f /s", v0, vp, vq);
#endif

	// Limit v0, vp, vq. {{{
	for (uint8_t s = 0; s < 2; ++s) {
		Space &sp = spaces[s];
		double limit;
		if (s == 0)
			limit = max_v;
		else if (current_extruder < sp.num_motors)
			limit = sp.motor[current_extruder]->limit_v;
		else
			continue;
		if (isnan(limit) || isinf(limit) || limit <= 0)
			continue;
		// max_mm is the maximum speed in mm/s.
		double max_mm = settings.probing ? space_types[sp.type].probe_speed(&sp) : limit;
		double max = max_mm / sp.settings.dist[0];
		if (v0 < 0)
			v0 = -v0 / sp.settings.dist[0];
		if (vp < 0)
			vp = -vp / sp.settings.dist[0];
		if (vq < 0)
			vq = -vq / sp.settings.dist[1];
		if (v0 > max)
			v0 = max;
		if (vp > max)
			vp = max;
		max = max_mm / sp.settings.dist[1];
		if (vq > max)
			vq = max;
	}
#ifdef DEBUG_MOVE
	debug("After limiting, v0 = %f /s, vp = %f /s and vq = %f /s", v0, vp, vq);
#endif
	// }}}
	// Already set up: f0, v0, vp, vq, dist[0], dist[1], mtr->dist[0], mtr->dist[1].
	// To do: start_time, t0, tp, fmain, fp, fq, mtr->main_dist
#ifdef DEBUG_MOVE
	debug("Preparation did f0 = %f", settings.f0);
#endif

	// Use maximum deviation to find fraction where to start rounded corner. {{{
	double factor = vq / vp;
	done_factor = NAN;
	if (vq == 0) {
		settings.fp = 0;
		settings.fq = 0;
	}
	else {
		settings.fp = factor > 1 ? .5 / factor : .5;
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			if (sp.num_axes < 2)
				continue;
			if (s != 0 || max_deviation == 0) {
				settings.fp = 0;
				break;
			}
			double nd = sp.settings.dist[1] * factor;
			double d = sp.settings.dist[0] - sp.settings.dist[1];
			// Calculate distances and ignore spaces which don't have two segments.
			if (nd <= 0)
				continue;
			if (sp.settings.dist[0] <= 0)
				continue;
			double done = 1 - max_deviation / sp.settings.dist[0];
			// Set it also if done_factor is NaN.
			if (!(done <= done_factor))
				done_factor = done;
			double new_fp = max_deviation / sqrt(nd / (sp.settings.dist[0] + nd) * d);
#ifdef DEBUG_MOVE
			debug("Space %d fp %f dev %f", s, settings.fp, max_deviation);
#endif
			if (new_fp < settings.fp)
				settings.fp = new_fp;
		}
		settings.fq = settings.fp * factor;
	}
	if (isnan(done_factor))
		done_factor = 1;
	// }}}

	settings.t0 = (1 - settings.fp) / (fabs(v0 + vp) / 2);
	settings.tp = settings.fp / (fabs(vp) / 2);
	settings.f1 = .5 * fabs(v0) * settings.t0;
	settings.f2 = 1 - settings.fp - settings.f1;

	// Set up endpos. {{{
	for (uint8_t s = 0; s < 2; ++s) {
		Space &sp = spaces[s];
		for (uint8_t a = 0; a < sp.num_axes; ++a) {
			sp.axis[a]->settings.main_dist = sp.axis[a]->settings.dist[0] * (1 - settings.fp);
			// Fill target for filling endpos below.
			if ((sp.axis[a]->settings.dist[0] > 0 && sp.axis[a]->settings.dist[1] < 0) || (sp.axis[a]->settings.dist[0] < 0 && sp.axis[a]->settings.dist[1] > 0))
				sp.axis[a]->settings.target = sp.axis[a]->settings.source + sp.axis[a]->settings.dist[0];
			else
				sp.axis[a]->settings.target = sp.axis[a]->settings.source + sp.axis[a]->settings.dist[0] + sp.axis[a]->settings.dist[1] * settings.fq;
#ifdef DEBUG_MOVE
			debug("Axis %d %d dist %f main dist = %f, next dist = %f currentpos = %d current = %f", s, a, sp.axis[a]->settings.dist[0], sp.axis[a]->settings.main_dist, sp.axis[a]->settings.dist[1], sp.motor[a]->settings.current_pos, sp.axis[a]->settings.current);
#endif
		}
		bool ok = true;
		// Using NULL as target fills endpos.
		space_types[sp.type].xyz2motors(&sp, NULL, &ok);
	}
	// }}}

	// Enable motors if they weren't. {{{
	if (!motors_busy) {
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			for (uint8_t m = 0; m < sp.num_motors; ++m)
				SET(sp.motor[m]->enable_pin);
		}
		motors_busy = true;
	} // }}}
#ifdef DEBUG_MOVE
	debug("Segment has been set up: f0=%f fp=%f fq=%f v0=%f /s vp=%f /s vq=%f /s t0=%f s tp=%f s", settings.f0, settings.fp, settings.fq, v0, vp, vq, settings.t0, settings.tp);
#endif
	// Reset time. {{{
	settings.hwtime = 0;
	settings.last_time = 0;
	settings.last_current_time = 0;
	settings.start_time = settings.last_time - uint32_t(settings.f0 / fabs(vp) * 1e6);
	// }}}

	if (!computing_move) {	// Set up source if this is a new move. {{{
#ifdef DEBUG_MOVE
		debug("starting new move");
#endif
		//debug("current %d running %d", current_fragment, running_fragment);
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			for (uint8_t a = 0; a < sp.num_axes; ++a)
				sp.axis[a]->settings.source = sp.axis[a]->settings.current;
		}
		store_settings();
#ifdef DEBUG_PATH
		fprintf(stderr, "\n");
#endif
	} // }}}

	first_fragment = current_fragment;	// Do this every time, because otherwise the queue must be regenerated.	TODO: send partial fragment to make sure this hack actually works, or fix it properly.
	computing_move = true;
	return num_cbs;
} // }}}
Пример #27
0
bool globals_load(int32_t &addr)
{
	bool change_hw = false;
	uint8_t nt = read_8(addr);
	uint8_t ng = read_8(addr);
	// Free the old memory and initialize the new memory.
	if (nt != num_temps) {
		ldebug("new temp");
		for (uint8_t t = nt; t < num_temps; ++t)
			temps[t].free();
		Temp *new_temps = new Temp[nt];
		for (uint8_t t = 0; t < min(nt, num_temps); ++t)
			temps[t].copy(new_temps[t]);
		for (uint8_t t = num_temps; t < nt; ++t)
			new_temps[t].init();
		delete[] temps;
		temps = new_temps;
		num_temps = nt;
	}
	if (ng != num_gpios) {
		for (uint8_t g = ng; g < num_gpios; ++g)
			gpios[g].free();
		Gpio *new_gpios = new Gpio[ng];
		for (uint8_t g = 0; g < min(ng, num_gpios); ++g)
			gpios[g].copy(new_gpios[g]);
		for (uint8_t g = num_gpios; g < ng; ++g)
			new_gpios[g].init();
		delete[] gpios;
		gpios = new_gpios;
		num_gpios = ng;
	}
	ldebug("new done");
	int p = led_pin.write();
	led_pin.read(read_16(addr));
	if (p != led_pin.write())
		change_hw = true;
	p = stop_pin.write();
	stop_pin.read(read_16(addr));
	if (p != stop_pin.write())
		change_hw = true;
	p = probe_pin.write();
	probe_pin.read(read_16(addr));
	if (p != probe_pin.write())
		change_hw = true;
	p = spiss_pin.write();
	spiss_pin.read(read_16(addr));
	if (p != spiss_pin.write())
		change_hw = true;
	int t = timeout;
	timeout = read_16(addr);
	if (t != timeout)
		change_hw = true;
	bed_id = read_16(addr);
	fan_id = read_16(addr);
	spindle_id = read_16(addr);
	feedrate = read_float(addr);
	if (isnan(feedrate) || isinf(feedrate) || feedrate <= 0)
		feedrate = 1;
	max_deviation = read_float(addr);
	max_v = read_float(addr);
	int ce = read_8(addr);
	targetx = read_float(addr);
	targety = read_float(addr);
	double zo = read_float(addr);
	if (motors_busy && (current_extruder != ce || zoffset != zo) && settings.queue_start == settings.queue_end && !settings.queue_full && !computing_move) {
		queue[settings.queue_end].probe = false;
		queue[settings.queue_end].cb = false;
		queue[settings.queue_end].f[0] = INFINITY;
		queue[settings.queue_end].f[1] = INFINITY;
		for (int i = 0; i < spaces[0].num_axes; ++i) {
			queue[settings.queue_end].data[i] = spaces[0].axis[i]->settings.current - (i == 2 ? zoffset : 0);
			for (int s = 0; s < NUM_SPACES; ++s)
				queue[settings.queue_end].data[i] = space_types[spaces[s].type].unchange0(&spaces[s], i, queue[settings.queue_end].data[i]);
		}
		for (int i = spaces[0].num_axes; i < QUEUE_LENGTH; ++i) {
			queue[settings.queue_end].data[i] = NAN;
		}
		settings.queue_end = (settings.queue_end + 1) % QUEUE_LENGTH;
		// This shouldn't happen and causes communication problems, but if you have a 1-item buffer it is correct.
		if (settings.queue_end == settings.queue_start)
			settings.queue_full = true;
		current_extruder = ce;
		zoffset = zo;
		next_move();
		buffer_refill();
	}
	else {
		current_extruder = ce;
		zoffset = zo;
	}
	bool store = read_8(addr);
	if (store && !store_adc) {
		store_adc = fopen("/tmp/franklin-adc-dump", "a");
	}
	else if (!store && store_adc) {
		fclose(store_adc);
		store_adc = NULL;
	}
	ldebug("all done");
	if (change_hw)
		arch_motors_change();
	return true;
}
Пример #28
0
int alpha_beta(app_t *app, cnodeptr_t parent, int alpha, int beta, int depth)
{
	int palpha = alpha;
	int i, score = -MATE, highest = -MATE;
	node_t node;
	move_t cutoff = 0;
	piece_t p;

	init_node(&node);

	assert(app);

	app->search.nodes++;
	node.depth = depth;

	/* max depth */
	if (app->game.board->ply > (SEARCH_MAXDEPTH - 1)) {
		/* return evaluate(app->board); */
		return quiescent(app, parent, alpha, beta);
	}

	/* recursive base */
	if (depth == 0) {
		return evaluate(app->game.board);
	}

	/* draws */
	if (repetitions(app) || (app->game.board->half >= 100)) {
		return 0;
	}

	/* if we are checked, set the nodes checked flag */
	if (check(app->game.board, app->game.board->side)) {
		node.flags |= NODE_CHECK;
		/* extend our search by 1 depth if we are in check */
		/* NOTES: we may want to NOT extend our search here if the parent
		   is in check, because the means we already extended once */
		depth++;
	}

	/* TODO:
	     - NULL moves
	     - Late-move reduction
	     - Tactical extensions (pins & forks -> depth++)
	 */

	/* probe our table */
	if (probe_hash(&app->hash, app->game.board, &cutoff, &score, depth, alpha, beta) == TRUE) {
		app->hash.cut++;
		return score;
	}

	/* generate moves */
	generate_moves(app->game.board, &node.ml, &node.ml);

	/* reset score */
	score = -MATE;

	/* try to match our hash hit move */
	if (cutoff != 0) {
		for (i = 0; i < node.ml.count; i++) {
			if (node.ml.moves[i] == cutoff) {
				node.ml.scores[i] = 20000;
				break;
			}
		}
	}

	/* search negamax */
	for (i = 0; i < node.ml.count; i++) {
		/* get the next move ordered */
		next_move(i, &node.ml);

		if (!(do_move(app->game.board, &app->game.undo, node.ml.moves[i])))
			continue;

		score = -alpha_beta(app, &node, -beta, -alpha, depth - 1);

		node.made++;
		undo_move(app->game.board, &app->game.undo);

		/* score whatever is best so far */
		if (score > highest) {
			node.best = node.ml.moves[i];
			highest = score;

			/* update alpha */
			if (score > alpha) {
				if (score >= beta) {

					/* non-captures causing beta cutoffs (killers) */
					if (!is_capture(node.ml.moves[i])) {
						app->game.board->killers[1][app->game.board->ply] =
							app->game.board->killers[0][app->game.board->ply];
						app->game.board->killers[0][app->game.board->ply] = node.ml.moves[i];
					}

					/* store this beta in our transposition table */
					store_hash(&app->hash, app->game.board, node.best, beta, HASH_BETA, depth);

					return beta;
				}

				/* update alpha */
				alpha = score;

				/* update our history */
				if (!is_capture(node.best)) {
					p = app->game.board->pos.squares[move_from(node.best)];
					app->game.board->history[piece_color(p)][piece_type(p)][move_to(node.best)] += depth;
				}
			}
		}
	}

	/* check for checkmate or stalemate */
	if (!node.made) {
		if (node.flags & NODE_CHECK) {
			return -MATE + app->game.board->ply;
		} else {
			return 0;
		}
	}

	if (alpha != palpha) {
		/* store this as an exact, since we beat alpha */
		store_hash(&app->hash, app->game.board, node.best, highest, HASH_EXACT, depth);
	} else {
		/* store the current alpha */
		store_hash(&app->hash, app->game.board, node.best, alpha, HASH_ALPHA, depth);
	}

	return alpha;
}
Пример #29
0
/**
 * Runs the game.
 */
Result gameplay() {
  Result result = NONE;
  Ball new_ball;
  bool collision = false;
  int round = 2;
  char round_msg[28];
  
  while(!gameover)
  {
    handle_window_resizing();
    
    // react to player input
    
    if (input_player == PLAYER_QUIT)
    {
      gameover = true;
      result = QUIT;
    }

    if (input_player == PLAYER_PAUSE)
    {
      continue;
    }
    if (input_player == PLAYER_UP && inside_borders(player.y + 1))
    {
      player.y++;
      input_player = 0x00;
    }
    if (input_player == PLAYER_DOWN && inside_borders(player.y - 1))
    {
      player.y--;
      input_player = 0x00;
    }
    
    // react to computer AI
    if (input_computer == COMP_UP && inside_borders(computer.y + 1)){
      computer.y++;
    }
    if (input_computer == COMP_DOWN && inside_borders(computer.y - 1)){
      computer.y--;
    }
    
    getmaxyx(field, field_size.y, field_size.x);

    // collision detection
    
    new_ball = next_move();
    int new_x = (int)new_ball.x;
    int new_y = (int)new_ball.y;
    
    // ball hits player or computer
    
    // left side
    if ((new_x == player.x && new_y == player.y - 1) ||
        (new_x == computer.x && new_y == computer.y - 1))
    {
        new_ball.y_d = new_edge_speed(new_ball.y_d);
        new_ball.x_d *= -1;
        collision = true;
        round++;
    }
    // middle
    else if ((new_x == player.x && new_y == player.y) ||
        (new_x == computer.x && new_y == computer.y))
    {
        int pos = new_ball.y_d > 0;
        new_ball.y_d = MID_SPEED;
        if(pos)
          new_ball.y_d *= -1;
        new_ball.x_d *= -1;
        collision = true;
        round++;
    }
    // right side
    else if ((new_x == player.x && new_y == player.y + 1) ||
        (new_x == computer.x && new_y == computer.y + 1))
    {
        new_ball.y_d = new_edge_speed(new_ball.y_d);
        new_ball.x_d *= -1;
        collision = true;
        round++;
    }
    // player failed
    else if (new_x <= player.x)
    {
      gameover = true;
      collision = true;
      result = LOOSE;
    }
    // computer failed
    else if(new_x >= computer.x)
    {
      gameover = true;
      collision = true;
      result = WIN;
    }
    // bottom and top borders
    else if (new_y >= field_size.y -1 ||
             new_y <= 0)
    {
      new_ball.y_d *= -1;
      collision = true;
    }
    
    // draw new window content

    wclear(info);
    wclear(field);
    
    draw_window(info,"Info", false);
    sprintf(round_msg, "round: %d - next: %s",round/2, round%2?"Player":"Computer");
    mvwprintw(info,1,2,round_msg);
    
    
    draw_window(field,"Pong", true);
    
    // only draw new position if no collision occured
    if (collision && !gameover)
      mvwprintw(field,ball.y,ball.x,BALL);
    else
      mvwprintw(field,new_ball.y,new_ball.x,BALL);
    
    draw_player();
    draw_computer();
    
    wrefresh(info);
    wrefresh(field);
    
    // set new ball position
    
    ball = new_ball;
    collision = false;
    
    usleep(DELAY);
  }
  
  return result;
}
Пример #30
0
static void apply_tick() { // {{{
	// Move motors to position for next time tick.
	// If it exceeds limits, adjust hwtime so that it's acceptable.
	//debug("tick");
	if (current_fragment_pos >= SAMPLES_PER_FRAGMENT) {
		// Fragment is already full. This shouldn't normally happen.
		debug("aborting apply_tick, because fragment is already full.");
		return;
	}
	// Check for move.
	if (!computing_move) {
		mdebug("apply tick called, but not moving");
		return;
	}
	mdebug("handling %d %d", computing_move, cbs_after_current_move);
	// This loop is normally only run once, but when a move is complete it is rerun for the next move.
	while ((running_fragment - 1 - current_fragment + FRAGMENTS_PER_BUFFER) % FRAGMENTS_PER_BUFFER > (FRAGMENTS_PER_BUFFER > 4 ? 4 : FRAGMENTS_PER_BUFFER - 2)) {
		settings.hwtime += settings.hwtime_step;
		//debug("tick time %d step %d frag %d pos %d", settings.hwtime, settings.hwtime_step, current_fragment, current_fragment_pos);
		double t = settings.hwtime / 1e6;
		double target_factor;	// Factor of current move that should be completed at this time.
		if (settings.hwtime >= settings.end_time)
			target_factor = 1;
		else if (settings.hwtime <= 0)
			target_factor = 0;
		else {
			target_factor = ((settings.v1 - settings.v0) / (settings.end_time / 1e6) * t * t / 2 + settings.v0 * t) / settings.dist;
			if (target_factor > 1)
				target_factor = 1;
			if (target_factor < 0)
				target_factor = 0;
		}
		//debug("target factor: %f (t=%f end=%f)", target_factor, t, settings.end_time / 1e6);
		// Go straight to the next move if the distance was 0 (so target_factor is NaN).
		if (!std::isnan(target_factor)) {
			double f = set_targets(target_factor);
			if (f < 1) {
				//double old = target_factor;
				if (settings.factor > 0 || settings.hwtime <= 0)
					target_factor = settings.factor + f * (target_factor - settings.factor);
				else {
					// settings.factor == 0, so we're at the start of a move.
					// settings.hwtime > 0, so this must be a continuation.
					// Only the new part can be limited, so to limit the same distance, it needs to be a larger fraction.
					// Example:
					// hwtime_step = 10
					// hwtime = 6
					// -> newpart = 0.6
					// f = 0.9
					// target move = 100
					// so (1-0.9)*100=10 of target move must be removed
					// that is (1-0.9)/0.6 of new part.
					double newpart = settings.hwtime * 1. / settings.hwtime_step;
					f = 1 - (1 - f) / newpart;
					target_factor = f * target_factor;
				}
				if (target_factor < 0)
					target_factor = 0;
				else if (target_factor > 1)
					target_factor = 1;
				//debug("adjust factor (%f) from %f to %f because f=%f", settings.factor, old, target_factor, f);
				set_targets(target_factor);
				// Adjust time.
				settings.hwtime -= settings.hwtime_step * ((1 - f) * .99);
			}
			//debug("target factor %f time 0 -> %d -> %d v %f -> %f", target_factor, settings.hwtime, settings.end_time, settings.v0, settings.v1);
			settings.factor = target_factor;
			if (settings.factor < 1) {
				do_steps();
				return;
			}
		}
		//debug("next segment");
		// Set new sources for all axes.
		for (int s = 0; s < NUM_SPACES; ++s) {
			Space &sp = spaces[s];
			for (int a = 0; a < sp.num_axes; ++a) {
				auto ax = sp.axis[a];
				ax->settings.source = ax->settings.target;
			}
		}
		// start new move; adjust time.
		history[current_fragment].cbs += cbs_after_current_move;
		//debug("adding %d cbs because move is completed", cbs_after_current_move);
		cbs_after_current_move = next_move(settings.end_time);
		//debug("new pending cbs: %d", cbs_after_current_move);
		mdebug("next move prepared");
		if (!computing_move) {
			// There is no next move.
			continue_event = true;
			do_steps();
			return;
		}
		mdebug("try again");
		// Next loop the time is incremented again, but in this case that shouldn't happen, so compensate.
		settings.hwtime -= settings.hwtime_step;
	}
	//if (spaces[0].num_axes >= 2)
		//debug("move z %d %d %f %f %f", current_fragment, current_fragment_pos, spaces[0].axis[2]->settings.current, spaces[0].motor[0]->settings.current_pos, spaces[0].motor[0]->settings.current_pos + avr_pos_offset[0]);
} // }}}