home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 22 / AACD 22.iso / AACD / Games / Connect4 / source / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-13  |  61.0 KB  |  1,668 lines

  1.  
  2. /* Uses Lamp.mcc */
  3.  
  4. #include "graphics_support.h"
  5. #include "computer_player.h"
  6.  
  7. /* MUI */
  8. #include <libraries/mui.h>
  9. #include <mui/lamp_mcc.h>
  10. #include <clib/muimaster_protos.h>
  11. #include "gameboardclass.h"
  12.  
  13. /* System */
  14. #include <graphics/gfxmacros.h>
  15. #include <workbench/workbench.h>
  16. #include <exec/memory.h>
  17. #include <libraries/iffparse.h>     // Also has MAKE_ID definition
  18. #include <datatypes/pictureclass.h>
  19.  
  20. /* Prototypes */
  21. #include <clib/alib_protos.h>
  22. #include <clib/exec_protos.h>
  23. #include <clib/dos_protos.h>
  24. #include <clib/icon_protos.h>
  25. #include <clib/graphics_protos.h>
  26. #include <clib/intuition_protos.h>
  27. #include <clib/gadtools_protos.h>
  28. #include <clib/utility_protos.h>
  29. #include <clib/asl_protos.h>
  30. #include <clib/iffparse_protos.h>
  31.  
  32. /* ANSI C */
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <stdio.h>
  36.  
  37. /***********************************/
  38. /***********************************/
  39. /***********************************/
  40.  
  41. extern struct Library *SysBase, *IntuitionBase, *UtilityBase, *GfxBase, *DOSBase, *IconBase;
  42. struct Library *MUIMasterBase=NULL;
  43. struct Library *AslBase=NULL;
  44. struct Library *IFFParseBase=NULL;
  45.  
  46. /***********************************/
  47. /***********************************/
  48. /***********************************/
  49.  
  50. #define PORT_LEN      10
  51. #define NAME_LEN      20
  52. #define TYPE_LEN      20
  53. #define DETAIL_LEN    100
  54.  
  55. /***********************************/
  56. /***********************************/
  57. /***********************************/
  58.  
  59. // Player Address Book - records player names, types and details
  60. struct PAB_Entry
  61. {
  62.     char *name, *type, *detail;
  63. } *loaded_info[200];
  64.  
  65. struct netstuff
  66. {
  67.     char port[PORT_LEN];
  68.     char username[NAME_LEN];
  69. } networkinfo = { "", "" };
  70.  
  71. UBYTE *prefspool;
  72.  
  73. enum { MEN_NEWGAME=1, MEN_CONNECT4, MEN_ABOUTMUI, MEN_ICONIFY, MEN_QUIT, MEN_SETC4,
  74.        MEN_SETMUI, MEN_SETLOAD, MEN_SETSAVE, MEN_SETDEFAULT };
  75.  
  76. static struct NewMenu connect4menu[] =
  77. {
  78.     { NM_TITLE, "Project",            0,  0, 0,    0                    },
  79.     { NM_ITEM,    "New game",        "N", 0, 0,    (APTR)MEN_NEWGAME    },
  80.     { NM_ITEM,    "About",            0,  0, 0,    0                    },
  81.     { NM_SUB,       "Connect 4",     "?", 0, 0,    (APTR)MEN_CONNECT4   },
  82.     { NM_SUB,       "MUI",            0,  0, 0,    (APTR)MEN_ABOUTMUI   },
  83.     { NM_ITEM,    "Iconify",         "I", 0, 0,    (APTR)MEN_ICONIFY    },
  84.     { NM_ITEM,    "Quit",            "Q", 0, 0,    (APTR)MEN_QUIT       },
  85.  
  86.     { NM_TITLE, "Settings",           0,  0, 0,    0                    },
  87.     { NM_ITEM,    "Connect 4",       "C", 0, 0,    (APTR)MEN_SETC4      },
  88.     { NM_ITEM,    "MUI",             "M", 0, 0,    (APTR)MEN_SETMUI     },
  89.     { NM_ITEM,    "Load",            "L", 0, 0,    (APTR)MEN_SETLOAD    },
  90.     { NM_ITEM,    "Save",            "S", 0, 0,    (APTR)MEN_SETSAVE    },
  91.     { NM_ITEM,    "Save as default", "D", 0, 0,    (APTR)MEN_SETDEFAULT },
  92.  
  93.     { NM_END,NULL, 0, 0, 0, (APTR)0 }
  94. };
  95.  
  96. static char *Page_titles[] = { "Players", "Network", NULL };
  97.  
  98. static char *cycle_playertype_strings[] = { "Local", "Remote", "Computer", NULL };
  99.  
  100. static char *cycle_acceptnet_strings[] = { "from known players", "from everyone", NULL };
  101.  
  102. static char *default_player_name[] = { "Player 1", "Player 2" };
  103.  
  104. /***********************************/
  105. /***********************************/
  106. /***********************************/
  107.  
  108. __saveds APTR PAB_constructor_function (__reg ("a0") struct Hook *hook,
  109.                                         __reg ("a2") APTR pool,
  110.                                         __reg ("a1") struct PAB_Entry *entry)
  111. {
  112.     struct PAB_Entry *entry_copy;
  113.     
  114.     if (entry_copy=AllocPooled(pool, sizeof(struct PAB_Entry)))
  115.     {
  116.         if (entry_copy->name=AllocPooled(pool, NAME_LEN))
  117.         {
  118.             if (entry_copy->type=AllocPooled(pool, TYPE_LEN))
  119.             {
  120.                 if (entry_copy->detail=AllocPooled(pool, DETAIL_LEN))
  121.                 {
  122.                     strcpy(entry_copy->name, entry->name);
  123.                     strcpy(entry_copy->type, entry->type);
  124.                     strcpy(entry_copy->detail, entry->detail);
  125.                     return (entry_copy);
  126.                 }
  127.                 FreePooled(pool, entry_copy->type, TYPE_LEN);
  128.             }
  129.             FreePooled(pool, entry_copy->name, NAME_LEN);
  130.         }
  131.         FreePooled(pool, entry_copy, sizeof(struct PAB_Entry));
  132.     }
  133.     return NULL;
  134. }
  135.  
  136. // Player Address Book list constructor hook
  137. static struct Hook PAB_constructor_hook =
  138. {
  139.     {NULL, NULL},
  140.     (void *)PAB_constructor_function,
  141.     NULL, NULL
  142. };
  143.  
  144. /***********************************/
  145. /***********************************/
  146. /***********************************/
  147.  
  148. __saveds void PAB_destructor_function (__reg ("a0") struct Hook *hook,
  149.                                        __reg ("a2") APTR pool,
  150.                                        __reg ("a1") struct PAB_Entry *entry)   
  151. {
  152.     FreePooled(pool, entry->name, NAME_LEN);
  153.     FreePooled(pool, entry->type, TYPE_LEN);
  154.     FreePooled(pool, entry->detail, DETAIL_LEN);
  155.     FreePooled(pool, entry, sizeof(struct PAB_Entry));
  156. }
  157.  
  158. // Player Address Book list destructor hook
  159. static struct Hook PAB_destructor_hook =
  160. {
  161.     {NULL, NULL},
  162.     (void *)PAB_destructor_function,
  163.     NULL, NULL
  164. };
  165.  
  166. /***********************************/
  167. /***********************************/
  168. /***********************************/
  169.  
  170. // Player Address Book list display function
  171. __saveds LONG PAB_display_function (__reg ("a0") struct Hook *hook,
  172.                                     __reg ("a2") char **array,
  173.                                     __reg ("a1") struct PAB_Entry *entry)
  174. {
  175.       if (entry)
  176.       {
  177.           *array++=entry->name;
  178.           *array++=entry->type;
  179.           *array  =entry->detail;
  180.       }
  181.       else
  182.       {
  183.           *array++="Name";
  184.           *array++="Type";
  185.           *array  ="Detail";
  186.       }
  187.  
  188.       return 0;
  189. }
  190.  
  191. // Player Address Book list display hook
  192. static struct Hook PAB_display_hook =
  193. {
  194.     {NULL, NULL},
  195.     (void *)PAB_display_function,
  196.     NULL, NULL
  197. };
  198.  
  199. /***********************************/
  200. /***********************************/
  201. /***********************************/
  202.  
  203. // Player Address Book list compare function
  204. __saveds LONG PAB_compare_function (__reg ("a0") struct Hook *hook,
  205.                                     __reg ("a2") struct PAB_Entry *entry1,
  206.                                     __reg ("a1") struct PAB_Entry *entry2)
  207. {
  208.     return(strcmp(entry2->name, entry1->name));
  209. }
  210.  
  211. // Player Address Book list compare hook
  212. static struct Hook PAB_compare_hook =
  213. {
  214.     {NULL, NULL},
  215.     (void *)PAB_compare_function,
  216.     NULL, NULL
  217. };
  218.  
  219. /***********************************/
  220. /***********************************/
  221. /***********************************/
  222.  
  223. __saveds void menu_save_function (__reg ("a0") struct Hook *hook,
  224.                                   __reg ("a2") Object *obj,
  225.                                   __reg ("a1") ULONG *data)
  226. {
  227.     APTR playerlist=(APTR)*data++;
  228.     APTR netport=(APTR)*data++;
  229.     APTR netname=(APTR)*data;
  230.     struct TagItem frsavetags[] =
  231.     {
  232.         ASLFR_TitleText, (ULONG)"Save a prefs file...",
  233.         ASLFR_DoSaveMode, TRUE,
  234.         ASLFR_InitialHeight, (WORD)300,
  235.         TAG_DONE
  236.     };
  237.     struct FileRequester *fr;   // ASL file requester
  238.  
  239.     fr=(struct FileRequester *)MUI_AllocAslRequest(ASL_FileRequest, frsavetags);
  240.  
  241.     if (!(MUI_AslRequest(fr, NULL)))
  242.     {
  243.         MUI_FreeAslRequest(fr);
  244.     }
  245.     else
  246.     {
  247.         savesettings(fr->fr_File, playerlist, netport, netname);
  248.         MUI_FreeAslRequest(fr);
  249.     }
  250. }
  251.  
  252. static struct Hook menu_save_hook =
  253. {
  254.     {NULL, NULL},
  255.     (void *)menu_save_function,
  256.     NULL, NULL
  257. };
  258.  
  259. /***********************************/
  260. /***********************************/
  261. /***********************************/
  262.  
  263. __saveds void menu_savedefault_function (__reg ("a0") struct Hook *hook,
  264.                                          __reg ("a2") Object *obj,
  265.                                          __reg ("a1") ULONG *data)
  266. {
  267.     APTR playerlist=(APTR)*data++;
  268.     APTR netport=(APTR)*data++;
  269.     APTR netname=(APTR)*data;
  270.  
  271.     savesettings("default.prefs", playerlist, netport, netname);
  272. }
  273.  
  274. static struct Hook menu_savedefault_hook =
  275. {
  276.     {NULL, NULL},
  277.     (void *)menu_savedefault_function,
  278.     NULL, NULL
  279. };
  280.  
  281. /***********************************/
  282. /***********************************/
  283. /***********************************/
  284.  
  285. __saveds void menu_load_function (__reg ("a0") struct Hook *hook,
  286.                                   __reg ("a2") Object *obj,
  287.                                   __reg ("a1") APTR *data)
  288. {
  289.     APTR app=(APTR)*data++;
  290.     APTR playerlist=(APTR)*data++;
  291.     APTR poplist1=(APTR)*data++;
  292.     APTR poplist2=(APTR)*data++;
  293.     APTR netport=(APTR)*data++;
  294.     APTR netname=(APTR)*data;
  295.     struct TagItem frloadtags[] =
  296.     {
  297.         ASLFR_TitleText, (ULONG)"Load a prefs file...",
  298.         ASLFR_InitialHeight, (WORD)300,
  299.         TAG_DONE
  300.     };
  301.     struct FileRequester *fr;   // ASL file requester
  302.  
  303.     fr=(struct FileRequester *)MUI_AllocAslRequest(ASL_FileRequest, frloadtags);
  304.       
  305.     if (!(MUI_AslRequest(fr, NULL)))
  306.     {
  307.         MUI_FreeAslRequest(fr);
  308.     }
  309.     else
  310.     {
  311.         // Copy network data from prefs file, if it exists
  312.         if (loadsettings(fr->fr_File))
  313.         {
  314.             // Clear the list objects
  315.             DoMethod(playerlist, MUIM_List_Clear);
  316.             DoMethod(poplist1,   MUIM_List_Clear);
  317.             DoMethod(poplist2,   MUIM_List_Clear);
  318.  
  319.             // Copy the player data
  320.             DoMethod(playerlist, MUIM_List_Insert, loaded_info, -1, MUIV_List_Insert_Sorted);
  321.             DoMethod(poplist1,   MUIM_List_Insert, loaded_info, -1, MUIV_List_Insert_Sorted);
  322.             DoMethod(poplist2,   MUIM_List_Insert, loaded_info, -1, MUIV_List_Insert_Sorted);
  323.  
  324.             // Copy the network data
  325.             set(netport, MUIA_String_Contents, networkinfo.port);
  326.             set(netname, MUIA_String_Contents, networkinfo.username);
  327.         }
  328.         else
  329.             problem_window(app, "Error", "Unable to load preferences file");
  330.  
  331.         MUI_FreeAslRequest(fr);
  332.     }
  333. }
  334.  
  335. static struct Hook menu_load_hook =
  336. {
  337.     {NULL, NULL},
  338.     (void *)menu_load_function,
  339.     NULL, NULL
  340. };
  341.  
  342. /***********************************/
  343. /***********************************/
  344. /***********************************/
  345.  
  346. __saveds void delete_player_function (__reg ("a0") struct Hook *hook,
  347.                                       __reg ("a2") Object *obj,
  348.                                       __reg ("a1") APTR *data)
  349. {
  350.     APTR playerlist=(APTR)*data++;
  351.     APTR poplist1=(APTR)*data++;
  352.     APTR poplist2=(APTR)*data;
  353.     LONG pos;
  354.  
  355.     get(playerlist, MUIA_List_Active, &pos);
  356.     if (pos!=MUIV_List_Active_Off)
  357.     {
  358.         DoMethod(playerlist, MUIM_List_Remove, pos);
  359.         DoMethod(poplist1,   MUIM_List_Remove, pos);
  360.         DoMethod(poplist2,   MUIM_List_Remove, pos);
  361.     }
  362. }   
  363.  
  364. static struct Hook delete_player_hook =
  365. {
  366.     {NULL, NULL},
  367.     (void *)delete_player_function,
  368.     NULL, NULL
  369. };
  370.  
  371. /***********************************/
  372. /***********************************/
  373. /***********************************/
  374.  
  375. __saveds void menu_aboutmui_function (__reg ("a0") struct Hook *hook,
  376.                                       __reg ("a2") Object *obj,
  377.                                       __reg ("a1") APTR *data)
  378. {
  379.     APTR aboutmuiwin=(APTR)*data++;
  380.     APTR mainwindow=(APTR)*data++;
  381.     APTR app=(APTR)*data;
  382.  
  383.     if (!aboutmuiwin)
  384.     {
  385.        aboutmuiwin = AboutmuiObject,
  386.           MUIA_Window_RefWindow, mainwindow,
  387.           MUIA_Aboutmui_Application, app,
  388.        End;
  389.     }
  390.  
  391.     if (aboutmuiwin)
  392.         set(aboutmuiwin,MUIA_Window_Open,TRUE);
  393.     else
  394.         DisplayBeep(0);
  395. }
  396.  
  397. static struct Hook menu_aboutmui_hook =
  398. {
  399.     {NULL, NULL},
  400.     (void *)menu_aboutmui_function,
  401.     NULL, NULL
  402. };
  403.  
  404. /***********************************/
  405. /***********************************/
  406. /***********************************/
  407.  
  408. __saveds void popchoice_function (__reg ("a0") struct Hook *hook,
  409.                                   __reg ("a2") Object *obj,
  410.                                   __reg ("a1") APTR *data)
  411. {
  412.     APTR poplist=(APTR)*data++;
  413.     APTR name=(APTR)*data++;
  414.     APTR pop=(APTR)*data;
  415.     struct PAB_Entry *tempentryptr;
  416.  
  417.     // get entry name
  418.     DoMethod(poplist, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &tempentryptr);
  419.     // copy entry name to name string gadget
  420.     set(name, MUIA_String_Contents, tempentryptr->name);
  421.     // close PopListview
  422.     DoMethod(pop, MUIM_Popstring_Close, TRUE);
  423. }
  424.  
  425. static struct Hook popchoice_hook =
  426. {
  427.     {NULL, NULL},
  428.     (void *)popchoice_function,
  429.     NULL, NULL
  430. };
  431.  
  432. /***********************************/
  433. /***********************************/
  434. /***********************************/
  435.  
  436. __saveds void existing_player_edit_function (__reg ("a0") struct Hook *hook,
  437.                                              __reg ("a2") Object *obj,
  438.                                              __reg ("a1") APTR *data)
  439. {
  440.     APTR settingswin=(APTR)*data++;
  441.     APTR playerlist=(APTR)*data++;
  442.     APTR pew_name=(APTR)*data++;
  443.     APTR pew_type=(APTR)*data++;
  444.     APTR pew_cycle=(APTR)*data++;
  445.     APTR playereditwin=(APTR)*data;
  446.     struct PAB_Entry *tempentryptr;
  447.  
  448.     // Put settings window to sleep
  449.     set(settingswin, MUIA_Window_Sleep, TRUE);
  450.  
  451.     // Get the details of the item the user double clicked on
  452.     DoMethod(playerlist, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &tempentryptr);
  453.  
  454.     // Copy them over to the existing details edit window
  455.     set(pew_name, MUIA_String_Contents, tempentryptr->name);
  456.  
  457.     if (strcmp(tempentryptr->type, cycle_playertype_strings[1])==0) // Remote
  458.     {
  459.         set(pew_cycle, MUIA_Cycle_Active, 1);
  460.         set(pew_type, MUIA_String_Contents, tempentryptr->detail);
  461.     }
  462.     else if (strcmp(tempentryptr->type, cycle_playertype_strings[2])==0) // Computer
  463.     {
  464.         set(pew_cycle, MUIA_Cycle_Active, 2);
  465.         set(pew_type, MUIA_String_Contents, tempentryptr->detail);
  466.     }
  467.     else // Local
  468.     {
  469.         set(pew_cycle, MUIA_Cycle_Active, 0);
  470.         set(pew_type, MUIA_String_Contents, "");
  471.         set(pew_type, MUIA_Disabled, TRUE);
  472.     }
  473.  
  474.     // Open the existing details editor window
  475.     set(playereditwin, MUIA_Window_Open, TRUE);
  476. }
  477.  
  478. static struct Hook existing_player_edit_hook =
  479. {
  480.     {NULL, NULL},
  481.     (void *)existing_player_edit_function,
  482.     NULL, NULL
  483. };
  484.  
  485. /***********************************/
  486. /***********************************/
  487. /***********************************/
  488.  
  489. __saveds void reset_values_function (__reg ("a0") struct Hook *hook,
  490.                                      __reg ("a2") Object *obj,
  491.                                      __reg ("a1") APTR *data)
  492. {
  493.     APTR playerlist=(APTR)*data++;
  494.     APTR pew_name=(APTR)*data++;
  495.     APTR pew_type=(APTR)*data++;
  496.     APTR pew_cycle=(APTR)*data;
  497.     struct PAB_Entry *tempentryptr;
  498.  
  499.     // Get the details of the item the user double clicked on
  500.     DoMethod(playerlist, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &tempentryptr);
  501.  
  502.     set(pew_name, MUIA_String_Contents, tempentryptr->name);
  503.  
  504.     if (strcmp(tempentryptr->type, cycle_playertype_strings[1])==0)
  505.     {
  506.         set(pew_cycle, MUIA_Cycle_Active, 1);
  507.         set(pew_type, MUIA_String_Contents, tempentryptr->detail);
  508.     }
  509.     else if (strcmp(tempentryptr->type, cycle_playertype_strings[2])==0)
  510.     {
  511.         set(pew_cycle, MUIA_Cycle_Active, 2);
  512.         set(pew_type, MUIA_String_Contents, tempentryptr->detail);
  513.     }
  514.     else
  515.     {
  516.         set(pew_cycle, MUIA_Cycle_Active, 0);
  517.         set(pew_type, MUIA_String_Contents, "");
  518.         set(pew_type, MUIA_Disabled, TRUE);
  519.     }
  520. }  
  521.  
  522. static struct Hook reset_values_hook =
  523. {
  524.     {NULL, NULL},
  525.     (void *)reset_values_function,
  526.     NULL, NULL
  527. };
  528.  
  529. /***********************************/
  530. /***********************************/
  531. /***********************************/
  532.  
  533. __saveds void add_player_ok_function (__reg ("a0") struct Hook *hook,
  534.                                       __reg ("a2") Object *obj,
  535.                                       __reg ("a1") APTR *data)
  536. {
  537.     UBYTE *temppool=(UBYTE *)*data++;
  538.     APTR piw_name=(APTR)*data++;
  539.     APTR piw_type=(APTR)*data++;
  540.     APTR piw_cycle=(APTR)*data++;
  541.     APTR playerlist=(APTR)*data++;
  542.     APTR poplist1=(APTR)*data++;
  543.     APTR poplist2=(APTR)*data++;
  544.     APTR playerinputwin=(APTR)*data++;
  545.     APTR settingswin=(APTR)*data;
  546.     LONG cyclestate;
  547.     struct PAB_Entry *tempentry;    // For space to hold struct PAB_Entry ->name and ->type pointers
  548.                                     // (only the pointers!! - not the space for the strings!)
  549.  
  550.     tempentry=AllocPooled(temppool, sizeof(struct PAB_Entry));
  551.  
  552.     // get new name and type strings
  553.     get(piw_name, MUIA_String_Contents, &tempentry->name);
  554.     get(piw_cycle, MUIA_Cycle_Active, &cyclestate);
  555.     tempentry->type=AllocPooled(temppool, TYPE_LEN);
  556.     strcpy(tempentry->type, cycle_playertype_strings[cyclestate]);
  557.     
  558.     switch (cyclestate)
  559.     {
  560.         case 0:
  561.             tempentry->detail=AllocPooled(temppool, DETAIL_LEN);
  562.             strcpy(tempentry->detail, "");
  563.             // copy them to the main player list and poplists
  564.             if (tempentry->name[0]!=0)
  565.             {
  566.                 DoMethod(playerlist, MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  567.                 DoMethod(poplist1,   MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  568.                 DoMethod(poplist2,   MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  569.             }
  570.             FreePooled(temppool, tempentry->detail, DETAIL_LEN);
  571.             break;
  572.  
  573.         case 1:
  574.         case 2:
  575.             get(piw_type, MUIA_String_Contents, &tempentry->detail);
  576.             // copy them to the main player list and poplists
  577.             if (tempentry->name[0]!=0)
  578.             {
  579.                 DoMethod(playerlist, MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  580.                 DoMethod(poplist1,   MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  581.                 DoMethod(poplist2,   MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  582.             }
  583.             break;
  584.         
  585.     }
  586.     
  587.     FreePooled(temppool, tempentry->type, TYPE_LEN);
  588.     
  589.     // close the input window and awaken the settings window
  590.     set(playerinputwin, MUIA_Window_Open, FALSE);
  591.     set(settingswin, MUIA_Window_Sleep, FALSE);
  592.  
  593.     FreePooled(temppool, tempentry, sizeof(struct PAB_Entry));
  594. }
  595.  
  596. static struct Hook add_player_ok_hook =
  597. {
  598.     {NULL, NULL},
  599.     (void *)add_player_ok_function,
  600.     NULL, NULL
  601. };
  602.  
  603. /***********************************/
  604. /***********************************/
  605. /***********************************/
  606.  
  607. __saveds void commit_changes_function (__reg ("a0") struct Hook *hook,
  608.                                        __reg ("a2") Object *obj,
  609.                                        __reg ("a1") APTR *data)
  610. {
  611.     UBYTE *temppool=(UBYTE *)*data++;
  612.     APTR playerlist=(APTR)*data++;
  613.     APTR poplist1=(APTR)*data++;
  614.     APTR poplist2=(APTR)*data++;
  615.     APTR pew_name=(APTR)*data++;
  616.     APTR pew_type=(APTR)*data++;
  617.     APTR pew_cycle=(APTR)*data++;
  618.     APTR playereditwin=(APTR)*data++;
  619.     APTR settingswin=(APTR)*data;
  620.     LONG selectedpos, cyclestate;
  621.     struct PAB_Entry *tempentry;    // For space to hold struct PAB_Entry ->name and ->type pointers
  622.                                     // (only the pointers!! - not the space for the strings!)
  623.  
  624.     tempentry=AllocPooled(temppool, sizeof(struct PAB_Entry));
  625.     
  626.  
  627.     // Remove current entry from list
  628.     get(playerlist, MUIA_List_Active, &selectedpos);
  629.     if (selectedpos!=MUIV_List_Active_Off)
  630.     {
  631.         DoMethod(playerlist, MUIM_List_Remove, selectedpos);
  632.         DoMethod(poplist1,   MUIM_List_Remove, selectedpos);
  633.         DoMethod(poplist2,   MUIM_List_Remove, selectedpos);
  634.     }
  635.  
  636.     // Get new values from string gadgets
  637.     get(pew_name, MUIA_String_Contents, &tempentry->name);
  638.     get(pew_cycle, MUIA_Cycle_Active, &cyclestate);
  639.     tempentry->type=AllocPooled(temppool, TYPE_LEN);
  640.     strcpy(tempentry->type, cycle_playertype_strings[cyclestate]);
  641.  
  642.     switch (cyclestate)
  643.     {
  644.         case 0:
  645.             tempentry->detail=AllocPooled(temppool, DETAIL_LEN);
  646.             strcpy(tempentry->detail, "");
  647.             // copy them to the main player list and poplists
  648.             if (tempentry->name[0]!=0)
  649.             {
  650.                 DoMethod(playerlist, MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  651.                 DoMethod(poplist1,   MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  652.                 DoMethod(poplist2,   MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  653.             }
  654.             FreePooled(temppool, tempentry->detail, DETAIL_LEN);
  655.             break;
  656.  
  657.         case 1:
  658.         case 2:
  659.             get(pew_type, MUIA_String_Contents, &tempentry->detail);
  660.             // copy them to the main player list and poplists
  661.             if (tempentry->name[0]!=0)
  662.             {
  663.                 DoMethod(playerlist, MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  664.                 DoMethod(poplist1,   MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  665.                 DoMethod(poplist2,   MUIM_List_InsertSingle, tempentry, MUIV_List_Insert_Sorted);
  666.             }
  667.             break;
  668.         
  669.     }
  670.  
  671.     FreePooled(temppool, tempentry->type, TYPE_LEN);
  672.  
  673.     // close the edit window and awaken the settings window
  674.     set(playereditwin, MUIA_Window_Open, FALSE);
  675.     set(settingswin, MUIA_Window_Sleep, FALSE);
  676.  
  677.     FreePooled(temppool, tempentry, sizeof(struct PAB_Entry));
  678. }
  679.  
  680. static struct Hook commit_changes_hook =
  681. {
  682.     {NULL, NULL},
  683.     (void *)commit_changes_function,
  684.     NULL, NULL
  685. };
  686.  
  687. /***********************************/
  688. /***********************************/
  689. /***********************************/
  690.  
  691. __saveds void winner_function (__reg ("a0") struct Hook *hook,
  692.                                __reg ("a2") Object *obj,
  693.                                __reg ("a1") APTR *data)
  694. {
  695.     APTR winning_player=(APTR)*data++;
  696.     APTR winnerwin=(APTR)*data++;
  697.     APTR ply1name=(APTR)*data++;
  698.     APTR ply2name=(APTR)*data++;
  699.     APTR winnertext=(APTR)*data++;
  700.     APTR board=(APTR)*data++;
  701.     APTR mainwindow=(APTR)*data;
  702.     char *playername;
  703.     char formattedname[40], i;
  704.  
  705.     for (i=0; i<40; i++)
  706.         formattedname[i]=0;
  707.  
  708.     strcpy(formattedname, MUIX_C);
  709.  
  710.     set(board, MUIA_Gameboard_Inputactive, FALSE);
  711.     set(mainwindow, MUIA_Window_Sleep, TRUE);
  712.  
  713.     if (winning_player==red_player)
  714.     {
  715.         get(ply1name, MUIA_Text_Contents, &playername);
  716.         strcat(formattedname, playername);
  717.         strcat(formattedname, "\n(red)");
  718.     }
  719.     else
  720.     {
  721.         get(ply2name, MUIA_Text_Contents, &playername);
  722.         strcat(formattedname, playername);
  723.         strcat(formattedname, "\n(yellow)");
  724.     }
  725.  
  726.     set(winnertext, MUIA_Text_Contents, formattedname);
  727.     set(winnerwin, MUIA_Window_Open, TRUE);
  728. }
  729.  
  730. static struct Hook winner_hook =
  731. {
  732.     {NULL, NULL},
  733.     (void *)winner_function,
  734.     NULL, NULL
  735. };
  736.  
  737. /***********************************/
  738. /***********************************/
  739. /***********************************/
  740.  
  741. __saveds void problem_function (__reg ("a0") struct Hook *hook,
  742.                                 __reg ("a2") Object *obj,
  743.                                 __reg ("a1") APTR *data)
  744. {
  745.     APTR app=(APTR)*data++;
  746.     char *windowtitle=(APTR)*data++;
  747.     char *errmsg=(APTR)*data;
  748.  
  749.     problem_window(app, windowtitle, errmsg);
  750. }
  751.  
  752. static struct Hook problem_hook =
  753. {
  754.     {NULL, NULL},
  755.     (void *)problem_function,
  756.     NULL, NULL
  757. };
  758.  
  759. /***********************************/
  760. /***********************************/
  761. /***********************************/
  762.  
  763. __saveds void react_move_function (__reg ("a0") struct Hook *hook,
  764.                                    __reg ("a2") Object *obj,
  765.                                    __reg ("a1") APTR *data)
  766. {
  767.     APTR board=(APTR)*data;
  768.     ULONG player, playertype;
  769.     
  770.     get(board, MUIA_Gameboard_CurrentPlayer, &player);
  771.     
  772.     if (player==red_player)
  773.         get(board, MUIA_Gameboard_RedPlayer, &playertype);
  774.     else
  775.         get(board, MUIA_Gameboard_YellowPlayer, &playertype);
  776.     
  777.     switch (playertype)
  778.     {
  779.         case PlayerType_Local:
  780.             set(board, MUIA_Gameboard_Inputactive, TRUE);
  781.             break;
  782.  
  783.         case PlayerType_Computer:
  784.             set(board, MUIA_Gameboard_Inputactive, FALSE);
  785.             DoMethod(board, MUIM_Gameboard_MakeMove);
  786.             break;
  787.  
  788.     }
  789.     
  790. }
  791.  
  792. static struct Hook react_move_hook =
  793. {
  794.     {NULL, NULL},
  795.     (void *)react_move_function,
  796.     NULL, NULL
  797. };
  798.  
  799. /***********************************/
  800. /***********************************/
  801. /***********************************/
  802.  
  803. __saveds void start_game_function (__reg ("a0") struct Hook *hook,
  804.                                    __reg ("a2") Object *obj,
  805.                                    __reg ("a1") APTR *data)
  806. {
  807.     APTR name1=(APTR)*data++;
  808.     APTR name2=(APTR)*data++;
  809.     APTR ply1name=(APTR)*data++;
  810.     APTR ply2name=(APTR)*data++;
  811.     APTR poplist1=(APTR)*data++;
  812.     APTR poplist2=(APTR)*data++;
  813.     APTR board=(APTR)*data;
  814.     char *nameptr;
  815.     LONG activepos;
  816.  
  817.     // Copy names to main window, filling in blank names if appropriate
  818.     get(name1, MUIA_String_Contents, &nameptr);
  819.     if (nameptr[0]==0)
  820.         set(name1, MUIA_String_Contents, default_player_name[red_player]);
  821.     set(ply1name, MUIA_Text_Contents, nameptr);
  822.  
  823.     get(name2, MUIA_String_Contents, &nameptr);
  824.     if (nameptr[0]==0)
  825.         set(name2, MUIA_String_Contents, default_player_name[yellow_player]);
  826.     set(ply2name, MUIA_Text_Contents, nameptr);
  827.  
  828.     // find out what type each player is, and tell the gameboard
  829.     get(poplist1, MUIA_List_Active, &activepos);
  830.     if (activepos==MUIV_List_Active_Off)
  831.     {
  832.         // must be something the user typed into the string gadget, and hence Local
  833.         set(board, MUIA_Gameboard_RedPlayer, PlayerType_Local);
  834.     }
  835.     else
  836.     {
  837.         // the user has highlighted something on the list - this may or may not match
  838.         // the contents of the string gadget, and may or may not have been highlighted
  839.         // by a doubleclick (it is possible to select an entry, and then exit the list
  840.         // from the dropdown button without initiating the doubleclick-activated name
  841.         // copying routine
  842.         struct PAB_Entry *entry;
  843.         DoMethod(poplist1, MUIM_List_GetEntry, activepos, &entry);
  844.         get(name1, MUIA_String_Contents, &nameptr);
  845.         if (strcmp(nameptr, entry->name)==0)
  846.         {
  847.             if (strcmp(entry->type, cycle_playertype_strings[2])==0) // computer player
  848.             {
  849.                 set(board, MUIA_Gameboard_RedPlayer, PlayerType_Computer);
  850.                 set(board, MUIA_Gameboard_RedDetail, atoi(entry->detail));
  851.             }
  852.             else if (strcmp(entry->type, cycle_playertype_strings[0])==0) // local player
  853.             {
  854.                 set(board, MUIA_Gameboard_RedPlayer, PlayerType_Local);
  855.             }
  856.             else // remote player - handle like local for now...
  857.             {
  858.                 set(board, MUIA_Gameboard_RedPlayer, PlayerType_Local);
  859.             }
  860.         }
  861.         else    // names didn't match, so assume the user chose something, then decided to type
  862.         {       // a name in instead
  863.             set(board, MUIA_Gameboard_RedPlayer, PlayerType_Local);
  864.         }
  865.     }
  866.  
  867.     get(poplist2, MUIA_List_Active, &activepos);
  868.     if (activepos==MUIV_List_Active_Off)
  869.     {
  870.         // must be something the user typed into the string gadget, and hence Local
  871.         set(board, MUIA_Gameboard_YellowPlayer, PlayerType_Local);
  872.     }
  873.     else
  874.     {
  875.         // the user has highlighted something on the list - this may or may not match
  876.         // the contents of the string gadget, and may or may not have been highlighted
  877.         // by a doubleclick (it is possible to select an entry, and then exit the list
  878.         // from the dropdown button without initiating the doubleclick-activated name
  879.         // copying routine
  880.         struct PAB_Entry *entry;
  881.         DoMethod(poplist2, MUIM_List_GetEntry, activepos, &entry);
  882.         get(name2, MUIA_String_Contents, &nameptr);
  883.         if (strcmp(nameptr, entry->name)==0)
  884.         {
  885.             if (strcmp(entry->type, cycle_playertype_strings[2])==0) // computer player
  886.             {
  887.                 set(board, MUIA_Gameboard_YellowPlayer, PlayerType_Computer);
  888.                 set(board, MUIA_Gameboard_YellowDetail, atoi(entry->detail));
  889.             }
  890.             else if (strcmp(entry->type, cycle_playertype_strings[0])==0) // local player
  891.             {
  892.                 set(board, MUIA_Gameboard_YellowPlayer, PlayerType_Local);
  893.             }
  894.             else // remote player - handle like local for now...
  895.             {
  896.                 set(board, MUIA_Gameboard_YellowPlayer, PlayerType_Local);
  897.             }
  898.         }
  899.         else    // names didn't match, so assume the user chose something, then decided to type
  900.         {       // a name in instead
  901.             set(board, MUIA_Gameboard_YellowPlayer, PlayerType_Local);
  902.         }
  903.     }
  904.     
  905.     // Re-seed the computer player for this go...
  906.     computer_player(0, NULL, NULL, 0, TRUE);
  907.  
  908.     // Get things going with this call. This allows any type of player to go first,
  909.     // instead of hardwiring the code to be always human going first
  910.     DoMethod(board, MUIM_CallHook, &react_move_hook, board);
  911. }
  912.  
  913. static struct Hook start_game_hook =
  914. {
  915.     {NULL, NULL},
  916.     (void *)start_game_function,
  917.     NULL, NULL
  918. };
  919.  
  920.  
  921.  
  922. /***********************************/
  923. /***********************************/
  924. /***********************************/
  925.  
  926. /*
  927. __saveds void _function (__reg ("a0") struct Hook *hook,
  928.                          __reg ("a2") Object *obj,
  929.                          __reg ("a1") APTR *data)
  930. {
  931.     APTR =(APTR)*data++;
  932.     APTR =(APTR)*data++;
  933.     APTR =(APTR)*data;
  934.  
  935.  
  936.  
  937.  
  938.  
  939. }
  940.  
  941. static struct Hook _hook =
  942. {
  943.     {NULL, NULL},
  944.     (void *)_function,
  945.     NULL, NULL
  946. };
  947. */
  948.  
  949. /***********************************/
  950. /***********************************/
  951. /***********************************/
  952.  
  953. int main (int argc, char **argv)
  954. {
  955.     if (AslBase=OpenLibrary("asl.library", 37L))
  956.     {
  957.         if (IFFParseBase=OpenLibrary("iffparse.library", 0L))
  958.         {
  959.             if (MUIMasterBase=OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN))
  960.             {
  961.                 // Make custom class
  962.                 struct MUI_CustomClass *gameboardmcc;
  963.                 if (gameboardmcc=MUI_CreateCustomClass(NULL, MUIC_Bodychunk, NULL, sizeof(struct gameboarddata), (APTR)gameboardDispatcher))
  964.                 {
  965.                     // Create memory pools
  966.                     if (prefspool=(UBYTE *)CreatePool(MEMF_FAST, 2000, 2000))
  967.                     {
  968.                         UBYTE *temppool;
  969.                         if (temppool=(UBYTE *)CreatePool(MEMF_FAST, 2000, 2000))
  970.                         {
  971.                             connect4(gameboardmcc, temppool);
  972.                             DeletePool(temppool);
  973.                         }
  974.                         DeletePool(prefspool);
  975.                     }
  976.                     MUI_DeleteCustomClass(gameboardmcc);
  977.                 }
  978.                 CloseLibrary(MUIMasterBase);
  979.             }
  980.             CloseLibrary(IFFParseBase);
  981.         }
  982.         CloseLibrary(AslBase);
  983.     }
  984.  
  985.     return 0;
  986. }
  987.  
  988. /***********************************/
  989. /***********************************/
  990. /***********************************/
  991.  
  992. void connect4 (struct MUI_CustomClass *gameboardmcc, UBYTE *temppool)
  993. {
  994.     APTR app,              // main application pointer
  995.          mainwindow,       // the main window
  996.          board,            // game board
  997.          redlamp,          // red lamp for the red player
  998.          yellowlamp,       // yellow lamp for the yellow player
  999.          lagometer,        // network lag indicator
  1000.          strip,            // menu strip
  1001.          ply1name,         // player 1 name - uneditable!
  1002.          ply2name,         // player 2 name - uneditable!
  1003.  
  1004.          aboutc4win,       // pointer to Project=>About=>Connect 4 window
  1005.          ac4w_ok,          // OK button in Project=>About=>Connect 4 window
  1006.  
  1007.          aboutmuiwin=0,    // pointer to Project=>About=>MUI window
  1008.  
  1009.          settingswin,      // pointer to game settings window
  1010.          netacceptcycle,   // cycle gadget to set which game requests to accept
  1011.          netport,          // network port string
  1012.          netname,          // network user name
  1013.          addbutton,        // add player button - opens player input window
  1014.          deletebutton,     // delete player button
  1015.          clearbutton,      // clear list button
  1016.          playerlistview,   // listview for player list
  1017.          playerlist,       // this list is used to control the data
  1018.  
  1019.          playerinputwin,   // pointer player details input window
  1020.          piw_name,         // player name string - default=""
  1021.          piw_type,         // player type string - default=""
  1022.          piw_cycle,        // player type cycle gadget
  1023.          piw_okbutton,     // OK button
  1024.          piw_cancelbutton, // Cancel button
  1025.  
  1026.          playereditwin,    // player edit window
  1027.          pew_name,         // player name string
  1028.          pew_type,         // player type string
  1029.          pew_cycle,        // player type cycle gadget
  1030.          pew_okbutton,     // OK button
  1031.          pew_cancelbutton, // Cancel button
  1032.          pew_resetbutton,  // Reset button - resets to pre-edit value
  1033.  
  1034.          winnerwin,        // Winner's window
  1035.          winw_ok,          // OK button in Winner's window
  1036.          winnertext,       // the name of the winner
  1037.  
  1038.          gametiedwin,      // Window displayed when neither player wins
  1039.          gtw_ok,           // OK button
  1040.  
  1041.          newgamewin,       // window to start a new game
  1042.          startbutton,      // starts a game
  1043.          pop1, pop2,       // buttons to access known player list
  1044.          poplistview1,     // pointer to first PopListview
  1045.          poplistview2,     // pointer to second PopListview
  1046.          poplist1,         // pointer to first PopList
  1047.          poplist2,         // pointer to second PopList
  1048.          name1, name2,     // the two competitors
  1049.  
  1050.          wedontusethislastoneatall;
  1051.  
  1052.     UBYTE *gb_body;
  1053.     ULONG gb_width, gb_height, gb_colourdepth, gb_compression;
  1054.     ULONG *gb_colours;
  1055.     struct DiskObject *myicon=NULL;
  1056.  
  1057.     if (loadiff("PROGDIR:gfx/gameboard", &gb_width, &gb_height, &gb_colourdepth, &gb_compression, &gb_body, &gb_colours))
  1058.     {
  1059.  
  1060.         // Create the MUI application
  1061.         app = ApplicationObject,
  1062.            MUIA_Application_Title      , "Connect 4",
  1063.            MUIA_Application_Version    , "$VER: v0.4 (14.05.01)",
  1064.            MUIA_Application_Copyright  , "©2000, Giles Burdett",
  1065.            MUIA_Application_Author     , "Giles Burdett",
  1066.            MUIA_Application_Description, "Connect 4 game with AI and network play",
  1067.            MUIA_Application_Base       , "CONNECT4",
  1068.  
  1069.            #include "window/mainwindow.c"
  1070.            #include "window/aboutc4win.c"
  1071.            #include "window/settingswin.c"
  1072.            #include "window/playerinputwin.c"
  1073.            #include "window/playereditwin.c"
  1074.            #include "window/winnerwin.c"
  1075.            #include "window/gametiedwin.c"
  1076.            #include "window/newgamewin.c"
  1077.  
  1078.         End;
  1079.  
  1080.         if (app)
  1081.         {
  1082.             if (myicon=GetDiskObject("PROGDIR:Connect4"));
  1083.                 set(app, MUIA_Application_DiskObject, myicon);
  1084.  
  1085.             if (loadsettings("default.prefs"))
  1086.             {
  1087.                 // Clear the list objects
  1088.                 DoMethod(playerlist, MUIM_List_Clear);
  1089.                 DoMethod(poplist1,   MUIM_List_Clear);
  1090.                 DoMethod(poplist2,   MUIM_List_Clear);
  1091.  
  1092.                 // Copy the player data
  1093.                 DoMethod(playerlist, MUIM_List_Insert, loaded_info, -1, MUIV_List_Insert_Sorted);
  1094.                 DoMethod(poplist1,   MUIM_List_Insert, loaded_info, -1, MUIV_List_Insert_Sorted);
  1095.                 DoMethod(poplist2,   MUIM_List_Insert, loaded_info, -1, MUIV_List_Insert_Sorted);
  1096.  
  1097.                 // Copy the network data
  1098.                 set(netport, MUIA_String_Contents, networkinfo.port);
  1099.                 set(netname, MUIA_String_Contents, networkinfo.username);
  1100.             }
  1101.  
  1102.             /*****************
  1103.             ** Menus
  1104.             *****************/
  1105.                 // Enable Project=>New game
  1106.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_NEWGAME,
  1107.                          newgamewin, 3, MUIM_Set, MUIA_Window_Open, TRUE);
  1108.  
  1109.                 // Enable Project=>About=>Connect 4...
  1110.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_CONNECT4,
  1111.                          aboutc4win, 3, MUIM_Set, MUIA_Window_Open, TRUE);
  1112.  
  1113.                 // Enable Project=>About=>MUI (opens MUI's inbuilt "About MUI" window)
  1114.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_ABOUTMUI,
  1115.                          app, 5, MUIM_CallHook, &menu_aboutmui_hook, aboutmuiwin, mainwindow, app);
  1116.  
  1117.                 // Enable Project=>Iconify
  1118.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_ICONIFY,
  1119.                          app, 3, MUIM_Set, MUIA_Application_Iconified, TRUE);
  1120.  
  1121.                 // Enable Project=>Quit
  1122.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_QUIT,
  1123.                          app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
  1124.  
  1125.                 // Enable Settings=>Connect 4...
  1126.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_SETC4,
  1127.                          settingswin, 3, MUIM_Set, MUIA_Window_Open, TRUE);
  1128.  
  1129.                 // Enable Settings=>MUI
  1130.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_SETMUI,
  1131.                          app, 2, MUIM_Application_OpenConfigWindow, 0);
  1132.  
  1133.                 // Enable Settings=>Load
  1134.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_SETLOAD,
  1135.                          app, 7, MUIM_CallHook, &menu_load_hook, app, playerlist, poplist1, poplist2, netport, netname);
  1136.  
  1137.                 // Enable Settings=>Save
  1138.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_SETSAVE,
  1139.                          app, 5, MUIM_CallHook, &menu_save_hook, playerlist, netport, netname);
  1140.  
  1141.                 // Enable Settings=>Save as default
  1142.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_SETDEFAULT,
  1143.                          app, 5, MUIM_CallHook, &menu_savedefault_hook, playerlist, netport, netname);
  1144.  
  1145.             /*****************
  1146.             ** Main window
  1147.             *****************/
  1148.                 // Enable main close gadget
  1149.                 DoMethod(mainwindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  1150.                          app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
  1151.  
  1152.                 // Make lamps indicate red player's turn
  1153.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_CurrentPlayer, red_player,
  1154.                          redlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0xFFFFFFFF);
  1155.  
  1156.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_CurrentPlayer, red_player,
  1157.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0L);
  1158.  
  1159.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_CurrentPlayer, red_player,
  1160.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Green, 0L);
  1161.  
  1162.                 // Make lamps indicate yellow player's turn
  1163.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_CurrentPlayer, yellow_player,
  1164.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0xFFFFFFFF);
  1165.  
  1166.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_CurrentPlayer, yellow_player,
  1167.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Green, 0xFFFFFFFF);
  1168.  
  1169.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_CurrentPlayer, yellow_player,
  1170.                          redlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0L);
  1171.  
  1172.                 // React to player moves
  1173.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_CurrentPlayer, MUIV_EveryTime,     
  1174.                          app, 3, MUIM_CallHook, &react_move_hook, board);
  1175.  
  1176.  
  1177.             /***************
  1178.             ** New Game window
  1179.             ***************/
  1180.                 // Detect name selection from poplists with double click
  1181.                 DoMethod(poplistview1, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE,
  1182.                          app, 5, MUIM_CallHook, &popchoice_hook, poplist1, name1, pop1);
  1183.  
  1184.                 DoMethod(poplistview2, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE,
  1185.                          app, 5, MUIM_CallHook, &popchoice_hook, poplist2, name2, pop2);
  1186.  
  1187.                 // Start button
  1188.                 DoMethod(startbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1189.                          redlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0xFFFFFFFF);
  1190.  
  1191.                 DoMethod(startbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1192.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0L);
  1193.  
  1194.                 DoMethod(startbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1195.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Green, 0L);
  1196.  
  1197.                 DoMethod(startbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1198.                          startbutton, 3, MUIM_Set, MUIA_Disabled, TRUE);
  1199.  
  1200.                 // Disable New Game menu option on Start
  1201.                 DoMethod(startbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1202.                          DoMethod(strip, MUIM_FindUData, MEN_NEWGAME), 3, MUIM_Set, MUIA_Menuitem_Enabled, FALSE);
  1203.  
  1204.                 // Close this window when the player wants to start the game
  1205.                 DoMethod(startbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1206.                          newgamewin, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  1207.  
  1208.                 // If someone's name is left blank, fill it with "Player 1" or "Player 2"
  1209.                 // and copy the chosen names to the main window text objects
  1210.                 DoMethod(startbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1211.                          app, 9, MUIM_CallHook, &start_game_hook, name1, name2,
  1212.                                  ply1name, ply2name, poplist1, poplist2, board);
  1213.  
  1214.              /*************************
  1215.              ** Winner's window
  1216.              *************************/
  1217.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_Winner, MUIV_EveryTime,
  1218.                          app, 9, MUIM_CallHook, &winner_hook, MUIV_TriggerValue,
  1219.                                  winnerwin, ply1name, ply2name, winnertext, board, mainwindow);
  1220.  
  1221.                 DoMethod(winw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1222.                          winnerwin, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  1223.  
  1224.                 DoMethod(winw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1225.                          mainwindow, 3, MUIM_Set, MUIA_Window_Sleep, FALSE);
  1226.  
  1227.                 DoMethod(winw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1228.                          startbutton, 3, MUIM_Set, MUIA_Disabled, FALSE);
  1229.  
  1230.                 DoMethod(winw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1231.                          redlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0xFFFFFFFF);
  1232.  
  1233.                 DoMethod(winw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1234.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0xFFFFFFFF);
  1235.  
  1236.                 DoMethod(winw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1237.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Green, 0xFFFFFFFF);
  1238.  
  1239.                 // Enable New Game menu option on winw_ok
  1240.                 DoMethod(winw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1241.                          DoMethod(strip, MUIM_FindUData, MEN_NEWGAME), 3, MUIM_Set, MUIA_Menuitem_Enabled, TRUE);
  1242.  
  1243.                 DoMethod(winw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1244.                          board, 3, MUIM_Set, MUIA_Gameboard_Restart, TRUE);
  1245.  
  1246.              /****************************
  1247.              ** Game tied window
  1248.              ****************************/
  1249.  
  1250.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_Tiegame, MUIV_EveryTime,
  1251.                          gametiedwin, 3, MUIM_Set, MUIA_Window_Open, TRUE);
  1252.  
  1253.                 DoMethod(board, MUIM_Notify, MUIA_Gameboard_Tiegame, MUIV_EveryTime,
  1254.                          mainwindow, 3, MUIM_Set, MUIA_Window_Sleep, TRUE);
  1255.  
  1256.                 DoMethod(gtw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1257.                          gametiedwin, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  1258.  
  1259.                 DoMethod(gtw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1260.                          mainwindow, 3, MUIM_Set, MUIA_Window_Sleep, FALSE);
  1261.  
  1262.                 DoMethod(gtw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1263.                          startbutton, 3, MUIM_Set, MUIA_Disabled, FALSE);
  1264.  
  1265.                 DoMethod(gtw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1266.                          redlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0xFFFFFFFF);
  1267.  
  1268.                 DoMethod(gtw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1269.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Red, 0xFFFFFFFF);
  1270.  
  1271.                 DoMethod(gtw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1272.                          yellowlamp, 3, MUIM_Set, MUIA_Lamp_Green, 0xFFFFFFFF);
  1273.  
  1274.                 // Enable New Game menu option on gtw_ok
  1275.                 DoMethod(gtw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1276.                          DoMethod(strip, MUIM_FindUData, MEN_NEWGAME), 3, MUIM_Set, MUIA_Menuitem_Enabled, TRUE);
  1277.  
  1278.                 DoMethod(gtw_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1279.                          board, 3, MUIM_Set, MUIA_Gameboard_Restart, TRUE);
  1280.  
  1281.              /******************************
  1282.              ** About=>Connect 4 window
  1283.              ******************************/
  1284.                 // Disable the main window
  1285.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_CONNECT4,
  1286.                          mainwindow, 3, MUIM_Set, MUIA_Window_Sleep, TRUE);
  1287.  
  1288.                 // Enable OK button
  1289.                 DoMethod(ac4w_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1290.                          aboutc4win, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  1291.  
  1292.                 // ...and awaken the main window when close gadget used
  1293.                 DoMethod(ac4w_ok, MUIM_Notify, MUIA_Pressed, FALSE,
  1294.                          mainwindow, 3, MUIM_Set, MUIA_Window_Sleep, FALSE);
  1295.  
  1296.              /*********************************
  1297.              ** Connect 4 settings  window
  1298.              *********************************/
  1299.                 // Disable the main window
  1300.                 DoMethod(app, MUIM_Notify, MUIA_Application_MenuAction, MEN_SETC4,
  1301.                          mainwindow, 3, MUIM_Set, MUIA_Window_Sleep, TRUE);
  1302.  
  1303.                 // Enable close gadget
  1304.                 DoMethod(settingswin, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  1305.                          settingswin, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  1306.  
  1307.                 // ...and awaken the main window when close gadget used
  1308.                 DoMethod(settingswin, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  1309.                          mainwindow, 3, MUIM_Set, MUIA_Window_Sleep, FALSE);
  1310.  
  1311.                 // Enable double click editing in the player list view
  1312.                 DoMethod(playerlistview, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE,
  1313.                          app, 8, MUIM_CallHook, &existing_player_edit_hook,
  1314.                                  settingswin, playerlist, pew_name, pew_type,
  1315.                                  pew_cycle, playereditwin);
  1316.  
  1317.                 /****************************************************
  1318.                 ** Player address book new player details window
  1319.                 ****************************************************/
  1320.                     // Display the player details window when selected from add button
  1321.                     DoMethod(addbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1322.                              playerinputwin, 3, MUIM_Set, MUIA_Window_Open, TRUE);
  1323.                     // ...and disable the main window
  1324.                     DoMethod(addbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1325.                              settingswin, 3, MUIM_Set, MUIA_Window_Sleep, TRUE);
  1326.  
  1327.                     // Set the name, cycle and type gadgets to default values
  1328.                     DoMethod(addbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1329.                              piw_name, 3, MUIM_Set, MUIA_String_Contents, "");
  1330.  
  1331.                     DoMethod(addbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1332.                              piw_cycle, 3, MUIM_Set, MUIA_Cycle_Active, 0 /*Local*/);
  1333.  
  1334.                     DoMethod(addbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1335.                              piw_type, 3, MUIM_Set, MUIA_String_Contents, "");
  1336.  
  1337.                     // Disable the piw_type string because piw_cycle is set to Local
  1338.                     DoMethod(addbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1339.                              piw_type, 3, MUIM_Set, MUIA_Disabled, TRUE);
  1340.  
  1341.                     // When piw_cycle is Remote, enable piw_type string gadget
  1342.                     DoMethod(piw_cycle, MUIM_Notify, MUIA_Cycle_Active, 1 /*Remote*/,
  1343.                              piw_type, 3, MUIM_Set, MUIA_Disabled, FALSE);
  1344.  
  1345.                     // When piw_cycle is Local, disable piw_type string gadget
  1346.                     DoMethod(piw_cycle, MUIM_Notify, MUIA_Cycle_Active, 0 /*Local*/,
  1347.                              piw_type, 3, MUIM_Set, MUIA_Disabled, TRUE);
  1348.  
  1349.                     // When piw_cycle is Computer, enable piw_type string gadget
  1350.                     DoMethod(piw_cycle, MUIM_Notify, MUIA_Cycle_Active, 2 /*Computer*/,
  1351.                              piw_type, 3, MUIM_Set, MUIA_Disabled, FALSE);
  1352.  
  1353.                     // Enable the clear list button...
  1354.                     DoMethod(clearbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1355.                              playerlist, 1, MUIM_List_Clear);
  1356.  
  1357.                     // ...and propagate the clear command to the poplists
  1358.                     DoMethod(clearbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1359.                              poplist1, 1, MUIM_List_Clear);
  1360.  
  1361.                     DoMethod(clearbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1362.                              poplist2, 1, MUIM_List_Clear);
  1363.  
  1364.                     // Enable Delete button...
  1365.                     DoMethod(deletebutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1366.                              app, 5, MUIM_CallHook, &delete_player_hook, playerlist, poplist1, poplist2);
  1367.  
  1368.                     // Enable PIW Cancel button...
  1369.                     DoMethod(piw_cancelbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1370.                              playerinputwin, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  1371.  
  1372.                     // ...and awaken the settings window when cancel button used
  1373.                     DoMethod(piw_cancelbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1374.                              settingswin, 3, MUIM_Set, MUIA_Window_Sleep, FALSE);
  1375.  
  1376.                     // Enable PIW OK button...
  1377.                     DoMethod(piw_okbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1378.                              app, 11, MUIM_CallHook, &add_player_ok_hook, temppool, piw_name, piw_type,
  1379.                                       piw_cycle, playerlist, poplist1, poplist2, playerinputwin, settingswin);
  1380.  
  1381.                 /************************************
  1382.                 ** Existing details edit window
  1383.                 ************************************/
  1384.                     // When pew_cycle is Remote, enable pew_type string gadget
  1385.                     DoMethod(pew_cycle, MUIM_Notify, MUIA_Cycle_Active, 1 /*Remote*/,
  1386.                              pew_type, 3, MUIM_Set, MUIA_Disabled, FALSE);
  1387.  
  1388.                     // When pew_cycle is Local, disable pew_type string gadget
  1389.                     DoMethod(pew_cycle, MUIM_Notify, MUIA_Cycle_Active, 0 /*Local*/,
  1390.                              pew_type, 3, MUIM_Set, MUIA_Disabled, TRUE);
  1391.  
  1392.                     // When pew_cycle is Computer, enable pew_type string gadget
  1393.                     DoMethod(pew_cycle, MUIM_Notify, MUIA_Cycle_Active, 2 /*Computer*/,
  1394.                              pew_type, 3, MUIM_Set, MUIA_Disabled, FALSE);
  1395.  
  1396.                     // Enable OK button
  1397.                     DoMethod(pew_okbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1398.                              app, 11, MUIM_CallHook, &commit_changes_hook, temppool, playerlist, poplist1,
  1399.                                       poplist2, pew_name, pew_type, pew_cycle, playereditwin, settingswin);
  1400.  
  1401.                     // Enable Reset button
  1402.                     DoMethod(pew_resetbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1403.                              app, 6, MUIM_CallHook, &reset_values_hook, playerlist,
  1404.                                      pew_name, pew_type, pew_cycle);
  1405.  
  1406.                     // Enable Cancel button (close the edit window and awaken the settings window)
  1407.                     DoMethod(pew_cancelbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1408.                              playereditwin, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  1409.  
  1410.                     DoMethod(pew_cancelbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1411.                              settingswin, 3, MUIM_Set, MUIA_Window_Sleep, FALSE);
  1412.  
  1413.                 /****************************
  1414.                 ** Network settings panel
  1415.                 ****************************/
  1416.                     DoMethod(netacceptcycle, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime,
  1417.                              app, 5, MUIM_CallHook, &problem_hook, app, "Sorry", "This setting has not been implemented yet");
  1418.  
  1419.  
  1420.  
  1421.  
  1422.  
  1423.             // This displays the GUI we have created
  1424.             set(mainwindow, MUIA_Window_Open, TRUE);
  1425.             set(newgamewin, MUIA_Window_Open, TRUE);
  1426.  
  1427.             // Main loop
  1428.             {
  1429.                 ULONG sigs = 0;
  1430.  
  1431.                 while (DoMethod(app, MUIM_Application_NewInput, &sigs)!=MUIV_Application_ReturnID_Quit)
  1432.                 {
  1433.                     if (sigs)
  1434.                     {
  1435.                         sigs = Wait(sigs | SIGBREAKF_CTRL_C);
  1436.                         if (sigs & SIGBREAKF_CTRL_C) break;
  1437.                     }
  1438.                 }
  1439.             }
  1440.  
  1441.             /* This hides the GUI before we remove it from the system */
  1442.             set(newgamewin, MUIA_Window_Open, FALSE);
  1443.             set(mainwindow, MUIA_Window_Open, FALSE);
  1444.  
  1445.             if (myicon)
  1446.                 FreeDiskObject(myicon);
  1447.  
  1448.             MUI_DisposeObject(app);
  1449.         }
  1450.  
  1451.         free(gb_body);
  1452.         free(gb_colours);
  1453.     }
  1454. }
  1455.  
  1456. /***********************************/
  1457. /***********************************/
  1458. /***********************************/
  1459.  
  1460. BOOL loadsettings(char *filename)
  1461. {
  1462.     BPTR fp_in;
  1463.     LONG filelength;
  1464.     UBYTE *prefsfile, *prefsfilerover;
  1465.     char fileheader[]={19, 31, 30, 30, 21, 19, 36, 4}; // ASCII values of each char in "CONNECT4" minus 48
  1466.  
  1467.     // Attempt to load the user prefs (player and network details)
  1468.     if (fp_in=Open (filename, MODE_OLDFILE))
  1469.     {
  1470.         Seek (fp_in, 0, OFFSET_END);
  1471.         filelength=Seek (fp_in, 0, OFFSET_BEGINNING);
  1472.  
  1473.         prefsfile=(UBYTE *)malloc(filelength); // reserve space in memory
  1474.                                                // for user prefs data
  1475.         FRead (fp_in, prefsfile, 1, filelength);
  1476.         Close (fp_in);
  1477.         prefsfilerover=prefsfile;
  1478.  
  1479.         DeletePool(prefspool);
  1480.         if (prefspool=(UBYTE *)CreatePool(MEMF_FAST, 2000, 2000))
  1481.         {
  1482.             if (filelength>8)
  1483.             {
  1484.                 if (*prefsfilerover==fileheader[0])
  1485.                 {
  1486.                     prefsfilerover++;
  1487.                     if (*prefsfilerover==fileheader[1])
  1488.                     {
  1489.                         prefsfilerover++;
  1490.                         if (*prefsfilerover==fileheader[2])
  1491.                         {
  1492.                             prefsfilerover++;
  1493.                             if (*prefsfilerover==fileheader[3])
  1494.                             {
  1495.                                 prefsfilerover++;
  1496.                                 if (*prefsfilerover==fileheader[4])
  1497.                                 {
  1498.                                     prefsfilerover++;
  1499.                                     if (*prefsfilerover==fileheader[5])
  1500.                                     {
  1501.                                         prefsfilerover++;
  1502.                                         if (*prefsfilerover==fileheader[6])
  1503.                                         {
  1504.                                             prefsfilerover++;
  1505.                                             if (*prefsfilerover==fileheader[7])
  1506.                                             {
  1507.                                                 char i=0;
  1508.  
  1509.                                                 prefsfilerover++;
  1510.                                                 while (*prefsfilerover!=1)
  1511.                                                 {
  1512.                                                     loaded_info[i]=AllocPooled(prefspool, sizeof(struct PAB_Entry));
  1513.                                                     loaded_info[i]->name=AllocPooled(prefspool, NAME_LEN);
  1514.                                                     loaded_info[i]->type=AllocPooled(prefspool, TYPE_LEN);
  1515.                                                     loaded_info[i]->detail=AllocPooled(prefspool, DETAIL_LEN);
  1516.                                                     strcpy(loaded_info[i]->name, prefsfilerover);
  1517.                                                     prefsfilerover+=strlen(prefsfilerover)+1;
  1518.                                                     strcpy(loaded_info[i]->type, prefsfilerover);
  1519.                                                     prefsfilerover+=strlen(prefsfilerover)+1;
  1520.                                                     strcpy(loaded_info[i]->detail, prefsfilerover);
  1521.                                                     prefsfilerover+=strlen(prefsfilerover)+1;
  1522.                                                     i++;
  1523.                                                 }
  1524.                                                 loaded_info[i]=NULL;
  1525.  
  1526.                                                 prefsfilerover++; // skip the section seperator
  1527.                                                 strcpy (networkinfo.port, prefsfilerover);
  1528.                                                 prefsfilerover+=strlen(prefsfilerover)+1;
  1529.                                                 strcpy (networkinfo.username, prefsfilerover);
  1530.  
  1531.                                                 free (prefsfile); // don't need the raw data anymore
  1532.                                                 return TRUE;
  1533.                                             }
  1534.                                         }
  1535.                                     }
  1536.                                 }
  1537.                             }
  1538.                         }
  1539.                     }
  1540.                 }
  1541.             }
  1542.             // If we get this far it is not a Connect 4 preferences file
  1543.         }
  1544.  
  1545.         free (prefsfile);
  1546.     }
  1547.    
  1548.     return FALSE;     // Prefs file not found
  1549.  
  1550. }
  1551.  
  1552. /***********************************/
  1553. /***********************************/
  1554. /***********************************/
  1555.  
  1556. void savesettings (char *filename, APTR playerlist, APTR netport, APTR netname)
  1557. {
  1558.     BPTR fp_out;
  1559.     char fileheader[]={19, 31, 30, 30, 21, 19, 36, 4}; // ASCII values of each char in "CONNECT4" minus 48
  1560.     char section_separator[]={1};
  1561.     char *stringptr;
  1562.     struct PAB_Entry *tempentryptr;
  1563.  
  1564.     if (fp_out=Open(filename, MODE_NEWFILE))
  1565.     {
  1566.         Write(fp_out, fileheader, 8);  // Write weird encoding of "CONNECT4" as file header
  1567.         // Get player details from the playerlist object
  1568.         {
  1569.             char i;
  1570.  
  1571.             for (i=0;;i++)
  1572.             {
  1573.                 DoMethod(playerlist, MUIM_List_GetEntry, i, &tempentryptr);
  1574.                 if (!tempentryptr)
  1575.                     break;
  1576.  
  1577.                 FPuts(fp_out, tempentryptr->name);
  1578.                 FPutC(fp_out, 0);
  1579.                 FPuts(fp_out, tempentryptr->type);
  1580.                 FPutC(fp_out, 0);
  1581.                 FPuts(fp_out, tempentryptr->detail);
  1582.                 FPutC(fp_out, 0);
  1583.             }
  1584.         }
  1585.         Flush(fp_out);  // Because we're moving from buffered to unbuffered I/O
  1586.         Write(fp_out, section_separator, 1);
  1587.         // Get the network details from the netport and netname objects
  1588.         get(netport, MUIA_String_Contents, &stringptr);
  1589.         FPuts(fp_out, stringptr);
  1590.         FPutC(fp_out, 0);
  1591.         get(netname, MUIA_String_Contents, &stringptr);
  1592.         FPuts(fp_out, stringptr);
  1593.         FPutC(fp_out, 0);
  1594.         Close(fp_out);
  1595.     }
  1596. }
  1597.  
  1598. /***********************************/
  1599. /***********************************/
  1600. /***********************************/
  1601.  
  1602. void problem_window (APTR app, char *windowtitle, char *errmsg)
  1603. {
  1604.     enum {okpressed=500};
  1605.  
  1606.     APTR problemwin=0,
  1607.          okbutton;
  1608.     char formattederrmsg[100], i;
  1609.  
  1610.     for (i=0; i<100; i++)
  1611.         formattederrmsg[i]=0;
  1612.  
  1613.     strcpy(formattederrmsg, MUIX_C);
  1614.     strcat(formattederrmsg, errmsg);
  1615.  
  1616.     problemwin = WindowObject,
  1617.         MUIA_Window_Title, windowtitle,
  1618.         MUIA_Window_ScreenTitle, "Connect 4",
  1619.         MUIA_Window_CloseGadget, FALSE,
  1620.  
  1621.         WindowContents,
  1622.             VGroup,
  1623.                 MUIA_Background, MUII_SHINEBACK,
  1624.                 Child, TextObject,
  1625.                     MUIA_Frame, MUIV_Frame_Text,
  1626.                     MUIA_Background, MUII_TextBack,
  1627.                     MUIA_Text_Contents, formattederrmsg,
  1628.                 End,
  1629.                 Child, HGroup,
  1630.                     Child, RectangleObject, End,
  1631.                     Child, okbutton = TextObject,
  1632.                              MUIA_Text_Contents, "OK",
  1633.                              MUIA_Text_SetMax, TRUE,
  1634.                              MUIA_Frame, MUIV_Frame_Button,
  1635.                              MUIA_InputMode, MUIV_InputMode_RelVerify,
  1636.                              MUIA_Background, MUII_ButtonBack,
  1637.                     End,
  1638.                     Child, RectangleObject, End,
  1639.                 End,
  1640.             End,
  1641.     End;
  1642.  
  1643.     if (problemwin)
  1644.     {
  1645.         DoMethod(app, OM_ADDMEMBER, problemwin);
  1646.         DoMethod(okbutton, MUIM_Notify, MUIA_Pressed, FALSE,
  1647.                  app, 2, MUIM_Application_ReturnID, okpressed);
  1648.         set(problemwin, MUIA_Window_Open, TRUE);
  1649.  
  1650.         {
  1651.             ULONG sigs = 0;
  1652.  
  1653.             while (DoMethod(app, MUIM_Application_NewInput, &sigs)!=okpressed)
  1654.             {
  1655.                 if (sigs)
  1656.                     sigs = Wait(sigs);
  1657.             }
  1658.         }
  1659.  
  1660.         set(problemwin, MUIA_Window_Open, FALSE);
  1661.         DoMethod(app, OM_REMMEMBER, problemwin);
  1662.         MUI_DisposeObject(problemwin);
  1663.     }
  1664. }
  1665.  
  1666.  
  1667.  
  1668.