indexing description: "Top shell widget for the Game subsystem." -- RML HW4 29 NOV 00 -- Larry Bush additions: -- add open campaign to puzzle menu -- Add open_campaitn_id declaration -- add open campaign keyboard shortcut -- this is currently overidden by the chop shortcut -- We need to decide which ones to use for each. -- cancel campaign on exit -- cancel campaign on attempted open -- Then statement for what to do when open campaign menu item is selected -- -- edited win_occurred routine: -- if statement to run the HOF if it is activated -- activated via if statement and boolean expression that is. -- Invoke a question box to ask the user if she wants to continue on to the next puzzle in the campaign. -- play next campaign if user says yes. -- if statement to see if the user completed campaign -- then won_campaign routine -- Which calls routine from room to invoke a message box with congratulatory message. -- end Larry Bush additions deferred class V_GAME_SHELL inherit V_SHELL rename make as vs_make redefine on_menu_command, room, class_background, on_key_down, on_key_up, on_control_id_command, exit -- RML HW4 end WIN_LISTENER feature{NONE} make( b : BASE ; s : STRING ) is -- Initialize a puzzle shell window do !!asc !!vk vs_make( b, s ) move( configuration.game_x, configuration.game_y ) make_bullet_label make_bridge_label make_mirror_label make_axe_label make_magnet_label make_timer_label end room : V_GAME_ROOM -- The room where the Stooge will attempt to solve a puzzle. make_room is -- Make the puzzle solving room. do create room.make( "room", Current ) end puzzle, solution : WEL_MENU make_menu_bar is -- Make the game and help menus. Also the labels for bullets, bridges, -- and mirrors. do !!menu_bar.make make_puzzle_menu menu_bar.append_popup( puzzle, "Puzzle" ) make_help_menu menu_bar.append_popup( help, "Help" ) make_solution_menu menu_bar.append_popup( solution, "Solution" ) menu_bar.append_string( "", bullet_id ) menu_bar.append_string( "", bridge_id ) menu_bar.append_string( "", mirror_id ) menu_bar.append_string( "", axe_id ) menu_bar.append_string( "", magnet_id ) menu_bar.append_string( "", timer_id ) end make_puzzle_menu is -- Make the menu with options for solving a puzzle. do !!puzzle.make puzzle.append_string( "&Restart%TR" , restart_id) puzzle.append_string( "&Open%TO" , open_id) -- lb code -- add open campaign to puzzle menu puzzle.append_string( "Open&Campaign%TC" , open_campaign_id) -- lb code end puzzle.append_string( "E&xit%TEsc" , exit_id) end make_solution_menu is -- Make the menu with options for pausing, saving, etc solutions. do create solution.make solution.append_string( "&Pause%TP", pause_id ) solution.append_string( "Res&ume%TU", resume_id ) solution.append_separator solution.append_string( "Sa&ve%TV", save_id ) solution.append_string( "Restor&e%TE", restore_id ) solution.append_separator solution.append_string( "&Hall of Fame%TH", hall_of_fame_id ) solution.append_string( "About Pu&zzle%TZ", about_puzzle_id ) end make_help_menu is -- Make the menu with various help commands. do create help.make help.append_string( "Contents" , contents_id ) help.append_string( "About" , about_id ) end -- lb code -- Add open_campaitn_id declaration -- exit_id, open_id, restart_id, -- Puzzle pulldown menu -- was exit_id, open_id, open_campaign_id, restart_id, -- Puzzle pulldown menu -- lb code end bullet_id, bridge_id, mirror_id, axe_id, magnet_id, -- Heart labels pause_id, save_id, restore_id, resume_id, hall_of_fame_id, about_puzzle_id, -- Solution pulldown menu about_id, contents_id, -- Help pulldowm menu timer_id : INTEGER is unique -- Game clock label help_message : SCROLLED_D -- Custom widget for displaying help. make_timer_label is -- Initialize label used for the game clock do display_game_clock( "Time" ) end make_bullet_label is -- Initialize bullet label. do display_bullets( 0 ) end make_bridge_label is -- Initialize bridge label. do display_bridges( 0 ) end make_mirror_label is -- Initialize mirror label. do display_mirrors( 0 ) end make_axe_label is -- Initialize axe label. do display_axes( 0 ) end make_magnet_label is -- Initialize axe label. do display_magnets( 0 ) end display_game_clock_label( amt : STRING; id : INTEGER ; lbl : STRING ) is -- Display the label and amount in the field of -- the menu bar specified by `id'. local str : STRING do str := clone( lbl ) str.append( amt ) menu_bar.modify_string( str, id ) draw_menu -- Force repaint of the message. end display_label( amt, id : INTEGER ; lbl : STRING ) is -- Display the label and amount in the field of -- the menu bar specified by `id'. local str : STRING do str := clone( lbl ) str.append_integer( amt ) menu_bar.modify_string( str, id ) draw_menu -- Force repaint of the message. end vk : WEL_VK_CONSTANTS asc : ASCII -- vk : expanded WEL_VK_CONSTANTS -- asc : expanded ASCII disable_mk_pause is -- Disable most menu/keyboard commands based on a paused state local i : INTEGER do paused := True from i := exit_id until i > restore_id loop menu_bar.disable_item( i ) i := i + 1 end menu_bar.enable_item( resume_id ) draw_menu end paused : BOOLEAN enable_mk_resume is -- Enable most menu/keyboard commands based on a unpaused state local i : INTEGER do paused := False from i := exit_id until i > resume_id loop menu_bar.enable_item( i ) i := i + 1 end menu_bar.disable_item( resume_id ) draw_menu end make_help_message is -- Make the help message for solving stooge puzzles. do create help_message.make( "Solving A Puzzle", configuration.game_help_width, configuration.game_help_height ) help_message.set_message_from_file( configuration.solve_help_file ) end set_void_puzzle_menu_items is -- Disable menu items for entry into the Game Room with a void puzzle local index : INTEGER do from index := restart_id until index > about_puzzle_id loop menu_bar.disable_item( index ) index := index + 1 end draw_menu -- Force a repaint of the menu end set_open_puzzle_menu_items is -- Enable menu items for a valid puzzle do if room.solution_in_progress_available then menu_bar.enable_item( restore_id ) else menu_bar.disable_item( restore_id ) end menu_bar.enable_item( pause_id ) menu_bar.disable_item( resume_id ) menu_bar.enable_item( save_id ) menu_bar.enable_item( restart_id ) end check_open_puzzle_menu_items is do if not ( room.puzzle /= Void and room.retieved_puzzle_cancelled ) then -- If a valid puzzle has been read into the Game Room earlier, then cancelling the file chooser -- will do nothing to the menu items. if ( room.puzzle = Void and then ( room.retieved_puzzle_cancelled or room.valid_retieved_puzzle ) ) then -- When entering the Game Room for the first time, the 'puzzle' attribute in GAME_ROOM will be equal to Void. -- If the file chooser is cancelled or an invalid puzzle is selected, menu items will be disabled. set_void_puzzle_menu_items else set_open_puzzle_menu_items end end end feature{NONE} -- Hall of Fame -- RML HW4 display_HOF_data is -- Get the HOF data for my puzzle if there is any -- Note that displaying the message box causes the Game Room to decline input since the message box is modal. local wmb : WEL_MSG_BOX do create wmb.make wmb.information_message_box( Current, base.get_HOF_out_display( room.puzzle.title, room.puzzle ), "Hall of Fame For " + room.title ) end -- display_HOF_data_list is -- Display a list of HOF keys in a selection box in order to view the HOF data for a puzzle not loaded in the Game Room -- local -- some type of list -- do -- create the list -- display the list -- get user selection -- Note that since we do not have a puzzle instance, designer data will not be available. -- Also note that the HOF uses puzzle title, ( file name less pzl extension ), as the key while the puzzle's puzzle_title is -- is displayed in the room title bar if it is set. This may lead to selection confusion. The selection box here should indicate -- that selections are based on puzzle file name less the extension. Maybe a file chooser should pop up. -- wmb.information_message_box( Current, base.get_HOF_out_display( room.puzzle.title, room.puzzle ), "Hall of Fame For " + room.title ) -- end enable_hall_of_fame is -- Enable Hall Of Fame functionality in the shell do menu_bar.enable_item( hall_of_fame_id ) menu_bar.enable_item( about_puzzle_id ) room.add_win_listener( Current ) end disable_hall_of_fame is -- Disable Hall Of Fame functionality in the shell do menu_bar.disable_item( hall_of_fame_id ) menu_bar.disable_item( about_puzzle_id ) room.remove_win_listener( Current ) end check_HOF_activation is -- Determine if HOF functionality should be turned on. do -- lb comment -- leave HOF activated, but use if statements in win occured routine to skip it if room.puzzle /= Void and then room.puzzle.puzzle_finalized then -- HW4 RML enable_hall_of_fame else disable_hall_of_fame end end feature{NONE} -- Puzzle Data display_puzzle_data is -- Display information about the puzzle local wmb : WEL_MSG_BOX do create wmb.make wmb.information_message_box( Current, room.puzzle.puzzle_data_out, "Puzzle Information" ) end feature pause is -- Stop everything while user goes to the bathroom. do disable_mk_pause room.pause room.hide end resume is -- User is back, start things up again. do room.resume room.show enable_mk_resume end on_key_up( k, key_data: INTEGER) is -- Handle all key releases here. do if k = vk.Vk_escape then on_menu_command( exit_id ) -- lb code change -- Here I made Axe shortcut just A. -- This was overiding the campaign shortcut, so I limited the chop/axe shortcut to A. -- This is what the Menu indicates the shortcut is (underlined). -- Also, this is the way Jim said was most logical (in the office hours chat room). -- In any case, we need to decide which ones to use for each. -- elseif k = asc.Upper_a or k = asc.Upper_c then -- was elseif k = asc.Upper_a then -- end lb code change on_menu_command( axe_id ) elseif k = asc.Upper_m then on_menu_command( magnet_id ) elseif k = asc.Upper_s or k = asc.Sp then on_menu_command( bullet_id ) elseif k = asc.upper_b then on_menu_command( bridge_id ) elseif k = asc.Upper_o then on_menu_command( open_id ) -- lb code -- Add open campaign keyboard shortcut -- This was overidden by the chop shortcut, but I limited the chop/axe shortcut to A. -- This is what the Menu indicates the shortcut is (underlined). -- Also, this is the way Jim said was most logical (in the office hours chat room). -- In any case, we need to decide which ones to use for each. elseif k = asc.Upper_c then on_menu_command( open_campaign_id ) -- lb code end elseif k = asc.Upper_r then on_menu_command( restart_id ) elseif k = asc.Upper_p then on_menu_command( pause_id ) elseif k = asc.Upper_u then on_menu_command( resume_id ) elseif k = asc.Upper_v then on_menu_command( save_id ) elseif k = asc.Upper_e then on_menu_command( restore_id ) elseif k = asc.Upper_h then -- RML HW4 -- See routine "on_key_down" on_menu_command( hall_of_fame_id ) -- RML HW4 elseif k = asc.Upper_z then -- RML HW5 on_menu_command( about_puzzle_id ) -- RML HW5 end end on_key_down( k, key_data: INTEGER) is -- Handle all key presses here. The moving keys -- are treated as presses, so we can just hold the -- key down when we want the stooge to move quickly. do -- !!str.make( 0 ) -- str.append_integer( virtual_key ) -- str.append_integer( key_data ) -- information_message_box( str, "Here's your key code" ) -- To see the virtual key code of any key decomment the above lines. -- Don't start the game if the Game Room is paused or the key which was -- pressed is the key which brings up the Hall of Fame data for the puzzle. if not paused and k /= asc.Upper_h and k /= asc.Upper_z then room.move( configuration.direction( k ) ) -- Try to move Stooge. end end on_menu_command( menu_id : INTEGER ) is -- Respond to menu selection. do if menu_bar.item_exists( menu_id ) and then menu_bar.item_enabled( menu_id ) then inspect menu_id when exit_id then -- lb code -- cancel campaign on exit room.abort_campaign -- This cancels a campaign on exit. -- lb code end exit when restart_id then room.restart when open_id then -- lb code -- cancel campaign on attempted open room.abort_campaign -- lb code end make_timer_label room.retrieve check_open_puzzle_menu_items check_HOF_activation -- lb code -- what to do when open campaign menu item is selected when open_campaign_id then make_timer_label room.retrieve_campaign check_open_puzzle_menu_items check_HOF_activation -- note, this must be after campaign is created and not void -- lb code end when contents_id then make_help_message help_message.show when about_id then display_about_message when pause_id then pause when resume_id then resume when save_id then save when restore_id then room.restore when bullet_id then room.shoot when bridge_id then room.build_bridge when axe_id then room.chop when magnet_id then room.magnetize when hall_of_fame_id then display_HOF_data when about_puzzle_id then display_puzzle_data else end end end on_control_id_command( control_id : INTEGER ) is -- RML HW4 -- Respond to the title bar close. do if control_id = exit_id then exit end end exit is -- Clean up and return to the main menu. -- RML HW4 do precursor disable_hall_of_fame end save is -- Save the current solution in progress. do pause room.save menu_bar.enable_item( restore_id ) resume end display_game_clock( time : STRING ) is -- display the number of seconds that have elapsed since the game began do display_game_clock_label( time, timer_id, " " ) end display_bullets( b : INTEGER ) is -- Display 'b' number of bullets in 'bullet_label'. do display_label( b, bullet_id, "&Shots: " ) end display_bridges( b : INTEGER ) is -- Display 'b' number of bridges in `bridge_label'. do display_label( b, bridge_id, "&Bridges: " ) end display_mirrors( m : INTEGER ) is -- Display 'm' number of mirrors in `mirror_label'. do display_label( m, mirror_id, "Glasses: " ) end display_magnets( m : INTEGER ) is -- Display 'm' number of magnets in `magnet_label'. do display_label( m, magnet_id, "&Magnets: " ) end display_axes( a : INTEGER ) is -- Display 'a' number of axes in `axe_label'. do display_label( a, axe_id, "&Axes: " ) end class_background : WEL_NULL_BRUSH is -- Someday we should check out whether this is doing anything! once !!Result.make end feature -- WIN_LISTENER procedure win_occurred( win_evt : WIN_EVENT ) is -- this procedure will be executed after Stooge wins local time : TIME_VALUE -- lb code dialog : WEL_MODAL_DIALOG wmb : WEL_MSG_BOX user_wants_to_continue_campaign : BOOLEAN -- lb code end do time := base.get_HOF_longest_time( win_evt.puzzle_name ) collection := base.get_HOF_value( win_evt.puzzle_name ) -- lb code if not room.campaign_in_progress then -- lb code end -- lb comment- this runs the HOF if it is activated -- activated via if statement and boolean expression that is. if ( time /= Void and then win_evt.time_value < time ) -- surpass the worst time or else collection = Void -- new entry in the HOF or ( collection /= Void and then not collection.full ) then -- existing entry is not full create input_box.make( Current, room.clock, "Hall Of Fame !", "%NCongratulations!%N%NYour time allows you into the Hall Of Fame.%N%NEnter your name:", True ) locate_box( width, height, input_box.width, input_box.height, room.stooge.northwest.x, room.stooge.northwest.y, room.stooge.bitmap.width, room.stooge.bitmap.height ) input_box.set_box_location( x_move, y_move ) input_box.show_input_dialog_box win_event := win_evt else win_event := Void end -- lb code -- end of hof if statement end -- lb code end -- lb code -- run next campaign if it is active if room.campaign_in_progress then -- if True then -- Question box section -- Invokes a question box to ask the user if she wants to continue on to the next puzzle in the campaign. if not room.end_of_my_campaign then -- if campaign is not yet completed -- Check with user before continuing campaign. !!wmb.make wmb.question_message_box( Current, "Continue to next puzzle in Campaign?", "Warning" ) user_wants_to_continue_campaign := wmb.message_box_result = Idyes -- end question box section -- play next campaign if user says yes. if user_wants_to_continue_campaign then room.play_next_puzzle_in_campaign -- get next campaign puzzle and instantiate make_timer_label check_open_puzzle_menu_items check_HOF_activation -- note, this must be after champaign is created and not void else room.abort_campaign end else -- do won_champaign routine -- Calls routine from room to invoke a message box with congratulatory message. room.campaign_congratulatory_message room.abort_campaign end -- end -- lb code end end feature{NONE} input_box : INPUT_DIALOG_BOX -- Dialog box used to input user data win_event : WIN_EVENT -- Event containing the puzzle and time value to be entered into the HOF collection : HALL_OF_FAME_ENTRY_COLLECTION -- HOF entry collection returned from the puzzle which has been completed by the user x_move, y_move : INTEGER locate_box( w, h, bw, bh, sx, sy, sw, sh : INTEGER ) is -- keep the dialog box off of Stooge do x_move := sx y_move := sy + sh if( x_move + bw > w ) then x_move := x_move - sx - bw + w - 10 end if( y_move + bh > h ) then y_move := y_move - bh - sh end end set_new_HOF_entry is local hofe : HALL_OF_FAME_ENTRY do create hofe.make_from_time_value( win_event.time_value ) hofe.add_user_data( input_box.text_input ) if collection = Void then create collection.make collection.add_entry( hofe ) base.add_HOF_value( win_event.puzzle_name, collection ) else collection.add_entry( hofe ) base.replace_HOF_value( win_event.puzzle_name, collection ) end display_HOF_data end feature{INPUT_DIALOG_BOX} -- Notification input_dialog_box_notify is -- receive notification that the dialog box has been closed do if input_box.response_available then set_new_HOF_entry end end -- Issues for future concern. As we get more and more powers, we -- need more and more labels. Eventually we'll run out of room! -- Probably should only display the labels that are appropriate to -- the puzzle at hand. Be nice to click on the bridge label to build -- a bridge, similar for shooting. end