Beispiel #1
0
/*
 * rtc_thread
 *   DESCRIPTION: Thread that handles updating the screen
 *   INPUTS: none
 *   OUTPUTS: none
 *   RETURN VALUE: none
 *   SIDE EFFECTS: none
 */
static void *rtc_thread(void *arg)
{
	int ticks = 0;
	int level;
	int ret;
	int open[NUM_DIRS];
	int need_redraw = 0;
	int goto_next_level = 0;
	char str[40];
	int need_fruit=0;
	/*variables to track the maze's condition*/
	int start_time, time, newtime, minute,minute0,minute1,second,second0,second1,fruit,newfruit;
	unsigned long led_diaplay;
	/*build buffer for the status bar
	unsigned char buf[STATUS_BAR_SIZE]={[0 ... (STATUS_BAR_SIZE-1)]=level%5};*/
	/*variables used as counter*/
	int i, c, fnum;
	unsigned char old_val[BLOCK_X_DIM*BLOCK_Y_DIM];
	unsigned char* player_mask;
	unsigned char* player_no_mask;
	unsigned char player_with_mask[BLOCK_X_DIM*BLOCK_Y_DIM];
	unsigned char* floor = (unsigned char*)blocks[BLOCK_EMPTY];
	char fruit_name[15];

	// Loop over levels until a level is lost or quit.
	for (level = 1; (level <= MAX_LEVEL) && (quit_flag == 0); level++)
	{
		change_palette (level);
		/*record the start time of each level and initialize the time*/
		start_time=total;
		time=0;
		/*build buffer for the status bar*/
	    unsigned char buf[STATUS_BAR_SIZE]={[0 ... (STATUS_BAR_SIZE-1)]=level%LEVEL_COLOR_PERIOD};
		
		
		// Prepare for the level.  If we fail, just let the player win.
		if (prepare_maze_level (level) != 0)
			break;
		goto_next_level = 0;

		// Start the player at (1,1)
		play_x = BLOCK_X_DIM;
		play_y = BLOCK_Y_DIM;

		// move_cnt tracks moves remaining between maze squares.
		// When not moving, it should be 0.
		move_cnt = 0;

		// Initialize last direction moved to up
		last_dir = DIR_UP;

		// Initialize the current direction of motion to stopped
		dir = DIR_STOP;
		next_dir = DIR_STOP;

		// Show maze around the player's original position
		(void)unveil_around_player (play_x, play_y);
		
		
		
		//This part is used to display the starting screen. 
		//The part at the end is the same as this one.(detailed explanations are here )
		//check whether the block has a fruit
		fnum = check_for_fruit((play_x) / BLOCK_X_DIM, (play_y) / BLOCK_Y_DIM);
		//if yes, update the block with the one without fruit, else just draw the regular block
		if (fnum != 0) {
			switch(fnum){
				case APPLE:
				sprintf(fruit_name,"Apple!");
				break;
				case GRAPE:
				sprintf(fruit_name,"Grapes!");
				break;
				case PEACH:
				sprintf(fruit_name,"Peach!");
				break;
				case STRAWBERY:
				sprintf(fruit_name,"Strawberry!");
				break;
				case BANANA:
				sprintf(fruit_name,"Banana!");
				break;
				case WATERMELON:
				sprintf(fruit_name,"Watermelon!");
				break;
				case DEW:
				sprintf(fruit_name,"Dew!");
				break;
			}
			need_fruit=TEXT_TIME;
			
			for(i = 0 ; i< BLOCK_X_DIM*BLOCK_Y_DIM; i++)
				old_val[i] = floor[i];
		} else {
			save_floor(play_x,play_y,old_val);
		}
		//get the block image data and also the mask data
		player_mask=get_player_mask(last_dir);
		player_no_mask=get_player_block(last_dir);
		
		//determine whether the part of block should be drawn with the block color or be totally transparent 
		for(c=0;c<BLOCK_X_DIM*BLOCK_Y_DIM;c++){
			if (player_mask[c])
				if(player_no_mask[c]==32){
					player_with_mask[c]=time%PLAYER_COLOR_PERIOD+PLAYER_COLOR_OFFSET;
				}
				else
					player_with_mask[c]=player_no_mask[c];
			else
				player_with_mask[c]=old_val[c];
		}
		//draw the whole block to build buffer and update the screen
		draw_full_block (play_x, play_y, player_with_mask);
		show_screen();
		if(need_fruit)
			show_text(play_x, play_y,fruit_name);
		//after updating the screen, put the floor image back to build buffer 
		restore_floor(play_x,play_y,old_val);
		
		
		
		/*show status bar*/
		// Lock the mutex
		pthread_mutex_lock(&mtx);
		fruit=fruit_num();
		sprintf(str,"Level %d   %d fruits  00:00",level,fruit_num());
		// Unlock the mutex
		pthread_mutex_unlock(&mtx);
		//transfer the string to image and save in to buf
		text_to_graph(buf,str,level%LEVEL_COLOR_PERIOD,level%LEVEL_COLOR_PERIOD+LEVEL_COLOR_OFFSET);
		//draw the buf into video memory
		for (i = 0; i < 4; i++) {
			SET_WRITE_MASK (1 << (i + 8));
			status_copy(buf + i * STATUS_BAR_ADDR);
			}

		// get first Periodic Interrupt
		ret = read(fd, &data, sizeof(unsigned long));

		while ((quit_flag == 0) && (goto_next_level == 0))
		{
			// Wait for Periodic Interrupt
			ret = read(fd, &data, sizeof(unsigned long));
		
			// Update tick to keep track of time.  If we missed some
			// interrupts we want to update the player multiple times so
			// that player velocity is smooth
			ticks = data >> 8;	
			
			
			//everytime tick being update, update the status bar.
			// Lock the mutex
			pthread_mutex_lock(&mtx);
			newtime=(total-start_time)/32;//32 is the frequency
			newfruit=fruit_num();
			//check if the status bar need to be updated.
			if((newtime!=time)||(newfruit!=fruit)){
				if(need_fruit>0)
					need_fruit--;
				time=newtime;
				fruit=newfruit;
				//Calculate time.
			    minute=time/60;
				second=time%60;
				//separate the minute and second into four number
				minute0=minute%10;
				minute1=minute/10;
				second0=second%10;
				second1=second/10;
				//only the decimal in middle need to be set so the lower 4 bits of the highest byte is 4.
				//the F in the lower 4 bits in the second byte means all of the led should be on.
				led_diaplay=0x040F0000;
				//add the number should be displayed by each LED to the led_display.
				led_diaplay=led_diaplay+second0+(second1<<SHIFT_SEC1)+(minute0<<SHIFT_MIN0)+(minute1<<SHIFT_MIN1);
				ioctl(tux_fd, TUX_SET_LED,led_diaplay);
			    sprintf(str,"Level %d   %d fruits  %02d:%02d",level,fruit,minute,second);
			    text_to_graph(buf,str,level%LEVEL_COLOR_PERIOD,level%LEVEL_COLOR_PERIOD+LEVEL_COLOR_OFFSET);
				
			    for (i = 0; i < 4; i++) {
					SET_WRITE_MASK (1 << (i + 8));
					status_copy(buf + i * STATUS_BAR_ADDR);
					}
				
			}
			// Unlock the mutex
			pthread_mutex_unlock(&mtx);

			total += ticks;

			// If the system is completely overwhelmed we better slow down:
			if (ticks > 8) ticks = 8;

			if (ticks > 1) {
				badcount++;
			}
			else {
				goodcount++;
			}

			while (ticks--) {

				// Lock the mutex
				pthread_mutex_lock(&mtx);

				// Check to see if a key has been pressed
				if (next_dir != dir)
				{
					// Check if new direction is backwards...if so, do immediately
					if ((dir == DIR_UP && next_dir == DIR_DOWN) ||
					    (dir == DIR_DOWN && next_dir == DIR_UP) ||
     					    (dir == DIR_LEFT && next_dir == DIR_RIGHT) ||
					    (dir == DIR_RIGHT && next_dir == DIR_LEFT))	    
					{
						if (move_cnt > 0) 
						{
							if (dir == DIR_UP || dir == DIR_DOWN)
			    				move_cnt = BLOCK_Y_DIM - move_cnt;
							else
			    				move_cnt = BLOCK_X_DIM - move_cnt;
	    					}
						dir = next_dir;
					}
				}
				// New Maze Square!
				if (move_cnt == 0) 
				{
	  				// The player has reached a new maze square; unveil nearby maze
	    				// squares and check whether the player has won the level.
	  				if (unveil_around_player (play_x, play_y))
					{
						pthread_mutex_unlock(&mtx);
	    					goto_next_level = 1;
						break;
					}
	 	   	
					// Record directions open to motion.
					find_open_directions (play_x / BLOCK_X_DIM,
								play_y / BLOCK_Y_DIM,
							 	open);
	    
					// Change dir to next_dir if next_dir is open 
 					if (open[next_dir])
					{
						dir = next_dir;
		   			}
	
					// The direction may not be open to motion...
			    		//   1) ran into a wall
			     		//   2) initial direction and its opposite both face walls
	     				if (dir != DIR_STOP) 
					{
	      					if (!open[dir])
						{
			  				dir = DIR_STOP;
						}
	       					else if (dir == DIR_UP || dir == DIR_DOWN)
						{	
		    					move_cnt = BLOCK_Y_DIM;
						}
						else
						{
	    						move_cnt = BLOCK_X_DIM;
						}
    					}
				}
				// Unlock the mutex
				pthread_mutex_unlock(&mtx);
		
				if (dir != DIR_STOP) 
				{
	    				// move in chosen direction
	    				last_dir = dir;
	    				move_cnt--;	
	    				switch (dir) 
					{
					case DIR_UP:    
						move_up (&play_y);    
						break;
					case DIR_RIGHT: 
						move_right (&play_x); 
						break;
					case DIR_DOWN:  
						move_down (&play_y);  
						break;
					case DIR_LEFT:  
						move_left (&play_x);  
						break;
		   			}
					//The same logic as the one at the beginning.	
					//This part is used during the game to update the screen.
					fnum = check_for_fruit((play_x) / BLOCK_X_DIM, (play_y) / BLOCK_Y_DIM);
					if (fnum != 0) {
						switch(fnum){
							case APPLE:
							sprintf(fruit_name,"Apple!");
							break;
							case GRAPE:
							sprintf(fruit_name,"Grapes!");
							break;
							case PEACH:
							sprintf(fruit_name,"Peach!");
							break;
							case STRAWBERY:
							sprintf(fruit_name,"Strawberry!");
							break;
							case BANANA:
							sprintf(fruit_name,"Banana!");
							break;
							case WATERMELON:
							sprintf(fruit_name,"Watermelon!");
							break;
							case DEW:
							sprintf(fruit_name,"Dew!");
							break;
						}
						need_fruit=TEXT_TIME;
						for(i = 0 ; i< BLOCK_X_DIM*BLOCK_Y_DIM; i++)
							old_val[i] = floor[i];
					} else {
						save_floor(play_x,play_y,old_val);
					}
					
					player_mask=get_player_mask(last_dir);
					player_no_mask=get_player_block(last_dir);
					
					for(c=0;c<BLOCK_X_DIM*BLOCK_Y_DIM;c++){
						if (player_mask[c])
							if(player_no_mask[c]==32){
								player_with_mask[c]=time%PLAYER_COLOR_PERIOD+PLAYER_COLOR_OFFSET;
							}
							else
								player_with_mask[c]=player_no_mask[c];
							
						else
							player_with_mask[c]=old_val[c];
					}
					
					
					need_redraw = 1;
				}
			draw_full_block (play_x, play_y, player_with_mask);
			show_screen();
			if(need_fruit)
				show_text(play_x, play_y,fruit_name);
			restore_floor(play_x,play_y,old_val);
			
			}
			
			need_redraw = 0;
			
		}	
	}
	if (quit_flag == 0) winner = 1;
	return 0;
}
Beispiel #2
0
/*!
 * @brief 現在フロアの書き込み /
 * Write the current dungeon (new method)
 * @return なし
 */
static bool wr_dungeon(void)
{
	saved_floor_type *cur_sf_ptr;
	int i;

	/* Forget the lite */
	forget_lite();

	/* Forget the view */
	forget_view();

	/* Forget the view */
	clear_mon_lite();

	/* Update lite/view */
	p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);

	/* Update monsters */
	p_ptr->update |= (PU_MONSTERS | PU_DISTANCE | PU_FLOW);


	/*** Meta info ***/

	/* Number of floor_id used from birth */
	wr_s16b(max_floor_id);

	/* Current dungeon type */
	wr_byte(dungeon_type);


	/*** No saved floor (On the surface etc.) ***/
	if (!p_ptr->floor_id)
	{
		/* No array elements */
		wr_byte(0);

		/* Write the current floor data */
		wr_saved_floor(NULL);

		/* Success */
		return TRUE;
	}


	/*** In the dungeon ***/

	/* Number of array elements */
	wr_byte(MAX_SAVED_FLOORS);

	/* Write the saved_floors array */
	for (i = 0; i < MAX_SAVED_FLOORS; i++)
	{
		saved_floor_type *sf_ptr = &saved_floors[i];

		wr_s16b(sf_ptr->floor_id);
		wr_byte(sf_ptr->savefile_id);
		wr_s16b(sf_ptr->dun_level);
		wr_s32b(sf_ptr->last_visit);
		wr_u32b(sf_ptr->visit_mark);
		wr_s16b(sf_ptr->upper_floor_id);
		wr_s16b(sf_ptr->lower_floor_id);
	}

	/* Extract pointer to current floor */
	cur_sf_ptr = get_sf_ptr(p_ptr->floor_id);

	/* Save current floor to temporal file */
	if (!save_floor(cur_sf_ptr, (SLF_SECOND))) return FALSE;

	/* Move data in temporal files to the savefile */
	for (i = 0; i < MAX_SAVED_FLOORS; i++)
	{
		saved_floor_type *sf_ptr = &saved_floors[i];

		/* Unused element */
		if (!sf_ptr->floor_id) continue;

		/* Load temporal saved floor file */
		if (load_floor(sf_ptr, (SLF_SECOND | SLF_NO_KILL)))
		{
			/* Mark success */
			wr_byte(0);

			/* Write saved floor data to the save file */
			wr_saved_floor(sf_ptr);
		}
		else
		{
			/* Mark failure */
			wr_byte(1);
		}
	}

	/* Restore current floor */
	if (!load_floor(cur_sf_ptr, (SLF_SECOND))) return FALSE;

	/* Success */
	return TRUE;
}
Beispiel #3
0
/*!
 * @brief 現在のフロアを離れるに伴って行なわれる保存処理
 * / Maintain quest monsters, mark next floor_id at stairs, save current floor, and prepare to enter next floor.
 * @return なし
 */
void leave_floor(void)
{
	cave_type *c_ptr = NULL;
	feature_type *f_ptr;
	saved_floor_type *sf_ptr;
	int quest_r_idx = 0;
	DUNGEON_IDX i;

	/* Preserve pets and prepare to take these to next floor */
	preserve_pet();

	/* Remove all mirrors without explosion */
	remove_all_mirrors(FALSE);

	if (p_ptr->special_defense & NINJA_S_STEALTH) set_superstealth(FALSE);

	/* New floor is not yet prepared */
	new_floor_id = 0;

	/* Temporary get a floor_id (for Arena) */
	if (!p_ptr->floor_id &&
	    (change_floor_mode & CFM_SAVE_FLOORS) &&
	    !(change_floor_mode & CFM_NO_RETURN))
	{
	    /* Get temporal floor_id */
	    p_ptr->floor_id = get_new_floor_id();
	}


	/* Search the quest monster index */
	for (i = 0; i < max_q_idx; i++)
	{
		if ((quest[i].status == QUEST_STATUS_TAKEN) &&
		    ((quest[i].type == QUEST_TYPE_KILL_LEVEL) ||
		    (quest[i].type == QUEST_TYPE_RANDOM)) &&
		    (quest[i].level == dun_level) &&
		    (dungeon_type == quest[i].dungeon) &&
		    !(quest[i].flags & QUEST_FLAG_PRESET))
		{
			quest_r_idx = quest[i].r_idx;
		}
	}

	/* Maintain quest monsters */
	for (i = 1; i < m_max; i++)
	{
		monster_race *r_ptr;
		monster_type *m_ptr = &m_list[i];

		/* Skip dead monsters */
		if (!m_ptr->r_idx) continue;

		/* Only maintain quest monsters */
		if (quest_r_idx != m_ptr->r_idx) continue;

		/* Extract real monster race */
		r_ptr = real_r_ptr(m_ptr);

		/* Ignore unique monsters */
		if ((r_ptr->flags1 & RF1_UNIQUE) ||
		    (r_ptr->flags7 & RF7_NAZGUL)) continue;

		/* Delete non-unique quest monsters */
		delete_monster_idx(i);
	}

	/* Check if there is a same item */
	for (i = 0; i < INVEN_PACK; i++)
	{
		object_type *o_ptr = &inventory[i];

		/* Skip dead objects */
		if (!o_ptr->k_idx) continue;

		/* Delete old memorized location of the artifact */
		if (object_is_fixed_artifact(o_ptr))
		{
			a_info[o_ptr->name1].floor_id = 0;
		}
	}

	/* Extract current floor info or NULL */
	sf_ptr = get_sf_ptr(p_ptr->floor_id);

	/* Choose random stairs */
	if ((change_floor_mode & CFM_RAND_CONNECT) && p_ptr->floor_id)
	{
		locate_connected_stairs(sf_ptr);
	}

	/* Extract new dungeon level */
	if (change_floor_mode & CFM_SAVE_FLOORS)
	{
		/* Extract stair position */
		c_ptr = &cave[p_ptr->y][p_ptr->x];
		f_ptr = &f_info[c_ptr->feat];

		/* Get back to old saved floor? */
		if (c_ptr->special && !have_flag(f_ptr->flags, FF_SPECIAL) && get_sf_ptr(c_ptr->special))
		{
			/* Saved floor is exist.  Use it. */
			new_floor_id = c_ptr->special;
		}

		/* Mark shaft up/down */
		if (have_flag(f_ptr->flags, FF_STAIRS) && have_flag(f_ptr->flags, FF_SHAFT))
		{
			prepare_change_floor_mode(CFM_SHAFT);
		}
	}

	/* Climb up/down some sort of stairs */
	if (change_floor_mode & (CFM_DOWN | CFM_UP))
	{
		int move_num = 0;

		/* Extract level movement number */
		if (change_floor_mode & CFM_DOWN) move_num = 1;
		else if (change_floor_mode & CFM_UP) move_num = -1;

		/* Shafts are deeper than normal stairs */
		if (change_floor_mode & CFM_SHAFT)
			move_num += SGN(move_num);

		/* Get out from or Enter the dungeon */
		if (change_floor_mode & CFM_DOWN)
		{
			if (!dun_level)
				move_num = d_info[dungeon_type].mindepth;
		}
		else if (change_floor_mode & CFM_UP)
		{
			if (dun_level + move_num < d_info[dungeon_type].mindepth)
				move_num = -dun_level;
		}

		dun_level += move_num;
	}

	/* Leaving the dungeon to town */
	if (!dun_level && dungeon_type)
	{
		p_ptr->leaving_dungeon = TRUE;
		if (!vanilla_town && !lite_town)
		{
			p_ptr->wilderness_y = d_info[dungeon_type].dy;
			p_ptr->wilderness_x = d_info[dungeon_type].dx;
		}
		p_ptr->recall_dungeon = dungeon_type;
		dungeon_type = 0;

		/* Reach to the surface -- Clear all saved floors */
		change_floor_mode &= ~CFM_SAVE_FLOORS;
	}

	/* Kill some old saved floors */
	if (!(change_floor_mode & CFM_SAVE_FLOORS))
	{
		/* Kill all saved floors */
		for (i = 0; i < MAX_SAVED_FLOORS; i++)
			kill_saved_floor(&saved_floors[i]);

		/* Reset visit_mark count */
		latest_visit_mark = 1;
	}
	else if (change_floor_mode & CFM_NO_RETURN)
	{
		/* Kill current floor */
		kill_saved_floor(sf_ptr);
	}

	/* No current floor -- Left/Enter dungeon etc... */
	if (!p_ptr->floor_id)
	{
		/* No longer need to save current floor */
		return;
	}


	/* Mark next floor_id on the previous floor */
	if (!new_floor_id)
	{
		/* Get new id */
		new_floor_id = get_new_floor_id();

		/* Connect from here */
		if (c_ptr && !feat_uses_special(c_ptr->feat))
		{
			c_ptr->special = new_floor_id;
		}
	}

	/* Fix connection -- level teleportation or trap door */
	if (change_floor_mode & CFM_RAND_CONNECT)
	{
		if (change_floor_mode & CFM_UP)
			sf_ptr->upper_floor_id = new_floor_id;
		else if (change_floor_mode & CFM_DOWN)
			sf_ptr->lower_floor_id = new_floor_id;
	}

	/* If you can return, you need to save previous floor */
	if ((change_floor_mode & CFM_SAVE_FLOORS) &&
	    !(change_floor_mode & CFM_NO_RETURN))
	{
		/* Get out of the my way! */
		get_out_monster();

		/* Record the last visit turn of current floor */
		sf_ptr->last_visit = turn;

		/* Forget the lite */
		forget_lite();

		/* Forget the view */
		forget_view();

		/* Forget the view */
		clear_mon_lite();

		/* Save current floor */
		if (!save_floor(sf_ptr, 0))
		{
			/* Save failed -- No return */
			prepare_change_floor_mode(CFM_NO_RETURN);

			/* Kill current floor */
			kill_saved_floor(get_sf_ptr(p_ptr->floor_id));
		}
	}
}