/* Middle Earth PBM Combat Calculator
   Version 1.0 ß
   (C) 1995 Sirius Cybernetics Corporation
   written by Holger Eichmann */

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <commdlg.h>
#include <mem.h>

#define armynumber 5

struct army
   { BOOL exist, att_town;
     long nation, tactic, comm, off_spell, def_spell, relations[armynumber+1],
         warmach, morale, troops[6][5], strength, constit,
         new_stren, new_const, losses;};

BOOL after_battle, captured;
army arm[2][armynumber], zw;
int side, number, version = 1 /*contains version number which is saved and checked while loading*/;
int terrpos = 0,climpos = 4, nationmax=26, round=0;
int spl_los=1; //contains the default value for how the losses are split on
               //the armies ("How to split losses")    
int popnation = 0, populloyal = 50, populpos = 0, fortifpos = 0;
long total_strength[2], total_constit[2];
FARPROC oldproc[34],newproc, oldproc2, newproc2;
HANDLE hInstance;
short populmax = 6, fortifmax = 6;
char *nationtype[26] = {"none", "Woodmen", "Northmen", "Eothraim", "Arthedain",
		     "Cardolan", "Northern Gondor", "Southern Gondor", "Dwarves",
		     "Sinda Elves", "Noldo Elves", "Witch-King", "Dragon Lord",
		     "Dog Lord", "Cloud Lord", "Blind Sorcerer", "Ice King",
		     "Quiet Avenger", "Fire King", "Long Rider", "Dark Lieutenants",
		     "Corsairs", "Haradwaith", "Dunlendings", "Rhudaur", "Easterlings"};
char *popultype[6] = {"None      ", "Camp      ", "Village   ",
                                "Town      ", "Major Town", "City      "};
char *fortiftype[6] = {"None   ", "Tower  ", "Fort   ", "Castle ",
			       "Keep   ", "Citadel"};
int conv[34] = {140,141,142,101,150,102,103,104,105,106,200,201,202,203,210,211,212,213,220,221,
                222,223,230,231,232,233,240,241,242,243,250,251,252,253}; 
long populdefence[6] = {0, 200, 500, 1000, 2500, 5000},
     fortifdefence[6] = {0, 2000, 6000, 10000, 16000, 24000};
int tr_terr_mod[6][7] = {80, 100, 60, 60, 80, 60, 60,
                   100, 100, 80, 60, 100, 60, 60,
                   80, 100, 80, 80, 80, 60, 60,
                   80, 80, 100, 80, 80, 80, 80,
                   80, 90, 100, 80, 100, 60, 80,
                   80, 100, 100, 80, 80, 80, 80};

int tr_tact_mod[6][6] = { 115, 103, 100, 103, 103, 90,
                          103, 103, 100, 115, 103, 90,
                          103, 110, 100, 90, 103, 103,
                          90, 103, 100, 103, 115, 103,
                          103, 90, 100, 103, 103, 115,
                          90, 103, 100, 103, 115, 103 };
static int tac_vs_tac [6][6] = { 100, 100, 110, 100, 115, 90,
                                 100, 100, 95, 90, 110, 115,
                                 90, 115, 100, 100, 100, 100,
                                 100, 115, 100, 100, 90, 100,
                                 95, 90, 100, 115, 100, 100,
                                 115, 90, 100, 100, 100, 100 };
/*   static int tac_vs_tac [6][6] = { 100, 100, 105, 100, 110, 90,
                                 100, 100, 95, 90, 105, 110,
                                 90, 110, 100, 100, 100, 100,
                                 100, 110, 100, 100, 90, 100,
                                 95, 90, 100, 110, 100, 100,
                                 110, 90, 100, 100, 100, 100 };*/

long FAR PASCAL _export WndProc (HWND, UINT, UINT, LONG);
BOOL FAR PASCAL _export armychange (HWND, UINT, UINT, LONG);
BOOL FAR PASCAL _export popchange (HWND, UINT, UINT, LONG);
BOOL FAR PASCAL _export tr_terr_change (HWND, UINT, UINT, LONG);
BOOL FAR PASCAL _export tr_tac_change (HWND, UINT, UINT, LONG);
BOOL FAR PASCAL _export tac_vs_tac_change (HWND, UINT, UINT, LONG);
BOOL FAR PASCAL _export new_edit_proc (HWND,UINT, UINT, LONG);
BOOL FAR PASCAL _export new_edit_proc2 (HWND,UINT, UINT, LONG);
BOOL FAR PASCAL _export set_relations (HWND, UINT, UINT, LONG);
BOOL FAR PASCAL _export split_losses (HWND, UINT, UINT, LONG);

void show_troops (HWND hwnd);
void insert_values (HWND hdlg, army *zw, BOOL show_capture);
void insert_pop_values (HWND hdlg);
void calc_combat_values(army *zw);
void create_default_army (army *arm);
long calc_losses(void);

int PASCAL WinMain (HANDLE hInst, HANDLE hPrevInstance,
			LPSTR lpszCmdLine, int nCmdShow)
#pragma argsused
   {
      static char appname[] = "mepbm";
      HWND hwnd;
      MSG msg;
      WNDCLASS wndclass;

      hInstance = hInst;
      if (!hPrevInstance)
	 {  wndclass.style = CS_HREDRAW | CS_VREDRAW;
	    wndclass.lpfnWndProc = WndProc;
	    wndclass.cbClsExtra = 0;
	    wndclass.cbWndExtra = DLGWINDOWEXTRA;
	    wndclass.hInstance = hInstance;
	    wndclass.hIcon = LoadIcon (hInstance, "me_pbm1");
	    wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
	    wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
	    wndclass.lpszMenuName = "MENU_1";
	    wndclass.lpszClassName = appname;
	    RegisterClass (&wndclass);
	 }
      newproc = MakeProcInstance((FARPROC)new_edit_proc,hInstance);
      newproc2 = MakeProcInstance((FARPROC)new_edit_proc2,hInstance);
      hwnd = CreateDialog (hInstance, "dialog_3", 0, NULL);
      ShowWindow (hwnd, nCmdShow);
      while (GetMessage(&msg, NULL, 0, 0))
	 { TranslateMessage (&msg);
	   DispatchMessage (&msg);
	 }
      return msg.wParam;
   }


long FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam,
				 LONG lParam)

{
   static HWND hclimate, hterrain;
   static BOOL f;
   static HANDLE hMenu;
   static FARPROC lpfnarmychange, lpfntr_terr_change, lpfntr_tac_change,
                  lpfntac_vs_tac_change, lpfnpopchange, lpfnsplit_losses;
   static int terrmax = 7, climmax = 7;
   char *terrtype[7] = {"Shore", "Plains", "Hills & Rough", "Forest",
			       "Desert", "Swamp", "Mountains"};
   char *climtype[7] = {"Polar", "Severe", "Cold", "Cool",
			       "Mild", "Warm", "Hot"};
   WORD i,j;
   long k;
   RECT rect;
   char fuzz[100];
   static char filename[_MAX_PATH], titlename[_MAX_FNAME+_MAX_EXT];
   int file_handle, zw_vers;
   static OPENFILENAME ofn;
   static char *szfilter1[] = {"MEPBM Files *.mep","*.mep","*.*","*.*",""};
   static char *szfilter2[] = {"MEPBM Modifier *.mem","*.mem","*.*","*.*",""};

   switch (message)
      {
         case WM_CREATE:
            f = TRUE;
            after_battle = TRUE;
            captured = FALSE;
	    lpfnarmychange = MakeProcInstance((FARPROC)armychange,hInstance);
	    lpfnpopchange = MakeProcInstance((FARPROC)popchange,hInstance);
	    lpfntr_tac_change = MakeProcInstance((FARPROC)tr_tac_change,hInstance);
	    lpfntr_terr_change = MakeProcInstance((FARPROC)tr_terr_change,hInstance);
	    lpfntac_vs_tac_change = MakeProcInstance((FARPROC)tac_vs_tac_change,hInstance);
	    lpfnsplit_losses = MakeProcInstance((FARPROC)split_losses,hInstance);
            hMenu = GetMenu(hwnd);
            filename[0] = '\0';
            titlename[0] = '\0';
            ofn.lStructSize = sizeof (OPENFILENAME);
            ofn.hwndOwner = hwnd;
            ofn.hInstance = NULL;
            ofn.lpstrCustomFilter = NULL;
            ofn.nMaxCustFilter = 0;
            ofn.nFilterIndex = 0;
            ofn.lpstrFile = filename;
            ofn.nMaxFile = _MAX_PATH;
            ofn.lpstrFileTitle = titlename;
            ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT;
            ofn.lpstrInitialDir = NULL;
            ofn.lpstrTitle = NULL;
            ofn.Flags = 0;
            ofn.nFileOffset = 0;
            ofn.nFileExtension = 0;
            ofn.lpstrDefExt = "txt";
            ofn.lCustData = 0L;
            ofn.lpfnHook = NULL;
            ofn.lpTemplateName = NULL;

	    return 0;

	 case WM_SHOWWINDOW:
	    if (f)
	       { f=FALSE;
		 for (i=0; i<2; i++)
		    for (j=0; j<=armynumber; j++)
		       {
                          create_default_army(&arm[i][j]);
		       }
		 hterrain = GetDlgItem (hwnd, 101);
		 for (i = 0; i <= terrmax-1; i++)
	           { SendMessage (hterrain, CB_ADDSTRING, 0, (LONG) terrtype[i]);
	           }
		 SendMessage (hterrain, CB_SETCURSEL, 0, 0L);
		 hclimate = GetDlgItem (hwnd, 102);
		 for (i = 0; i <= climmax-1; i++)
	           { SendMessage (hclimate, CB_ADDSTRING, 0, (LONG) climtype[i]);
		   }
                 SendMessage (hclimate, CB_SETCURSEL, 4, 0L);
                 sprintf(fuzz, "(not captured)");
                 SetWindowText (GetDlgItem(hwnd,704), fuzz);
	       }
             else MessageBox(hwnd, "Huch! Second WM_SHOWWINDOW!",0,0);
	    break;

	 case WM_COMMAND:
	    switch (wParam)
	       {
		  case 101:  if (HIWORD(lParam) == CBN_SELCHANGE)
		               { terrpos = SendMessage (hterrain, CB_GETCURSEL, 0, 0L);
                                 for (side = 0; side <= 1; side++)
                                    for (number = 0; number < armynumber; number++)
                                       calc_combat_values(&arm[side][number]);
                                 calc_losses();
                                 show_troops(hwnd);
                               }
		             return 0;
		  case 102:  if (HIWORD(lParam) == CBN_SELCHANGE)
                               { climpos = SendMessage (hclimate, CB_GETCURSEL, 0, 0L);
                                 for (side = 0; side <= 1; side++)
                                    for (number = 0; number < armynumber; number++)
                                       calc_combat_values(&arm[side][number]);
                                 calc_losses();
                                 show_troops(hwnd);
                               }
			     return 0;
		  case 201:
		  case 202:
		  case 203:
		  case 204:
		  case 205:
		  case 301:
		  case 302:
		  case 303:
		  case 304:
		  case 305: if (HIWORD(lParam) == BN_CLICKED)
                              {
			        if (wParam < 300) side = 0; else side = 1;
				number = (wParam % 100)-1;
				DialogBox (hInstance, "dialog_1",hwnd, lpfnarmychange);
                                show_troops(hwnd);
                              }
                             return 0;
                  case 700:  if (HIWORD(lParam) == BN_CLICKED)
                               {
                                DialogBox (hInstance, "dialog_7", hwnd, lpfnpopchange);
                                show_troops(hwnd); 
                               }
                             return 0;  
                  case 501:  ofn.Flags = OFN_FILEMUSTEXIST;
                             ofn.lpstrFilter = szfilter1[0];
                             if (GetOpenFileName(&ofn))
                               { file_handle = _lopen(filename, OF_READ | OF_SHARE_DENY_WRITE);
                                 if (file_handle == -1)
                                    MessageBox (hwnd, "Canīt open file !!", "Error !!", MB_OK);
                                 else
                                    { _lread(file_handle, &zw_vers, sizeof(int));
                                      if (zw_vers != version)
                                         MessageBox (hwnd, "File has been saved with\nanother version number !!", "Error !!", MB_OK);
                                      else
                                        {
                                          _lread(file_handle, &terrpos, sizeof(int));
                                          _lread(file_handle, &climpos, sizeof(int));
                                          _lread(file_handle, &populloyal, sizeof(int));
                                          _lread(file_handle, &populpos, sizeof(int));
                                          _lread(file_handle, &fortifpos, sizeof(int));
                                          _lread(file_handle, &arm, 2*armynumber*sizeof(army));
                                          _lread(file_handle, &after_battle, sizeof(BOOL));
                                          popnation = 0; /*to be compatible with version 0.3*/
                                          _lread(file_handle, &popnation, sizeof(int)); 
                                          if (after_battle)
                                             { EnableMenuItem (hMenu, 1001, MF_GRAYED);
                                               EnableMenuItem (hMenu, 1000, MF_ENABLED);
                                             }
                                          else
                                             { EnableMenuItem (hMenu, 1000, MF_GRAYED);
                                               EnableMenuItem (hMenu, 1001, MF_ENABLED);
                                             }
		                          SendMessage (hterrain, CB_SETCURSEL, terrpos, 0L);
		                          SendMessage (hclimate, CB_SETCURSEL, climpos, 0L);
			                  for (side = 0; side <= 1; side++)
                                             for (number = 0; number < armynumber; number++)
                                                calc_combat_values(&arm[side][number]);
                                          calc_losses();
                                          show_troops(hwnd);
                                        }
                                      _lclose(file_handle);
                                    }

                               }
                             return 0;
                  case 502:  ofn.Flags = OFN_OVERWRITEPROMPT;
                             ofn.lpstrFilter = szfilter1[0];
                             if (GetSaveFileName(&ofn))
                               { file_handle = _lcreat(filename, 0);
                                 if (file_handle == -1)
                                    MessageBox (hwnd, "Canīt create file !!", "Error !!", MB_OK);
                                 else
                                    { _lwrite(file_handle, &version, sizeof(int));
                                      _lwrite(file_handle, &terrpos, sizeof(int));
                                      _lwrite(file_handle, &climpos, sizeof(int));
                                      _lwrite(file_handle, &populloyal, sizeof(int));
                                      _lwrite(file_handle, &populpos, sizeof(int));
                                      _lwrite(file_handle, &fortifpos, sizeof(int));
                                      _lwrite(file_handle, &arm, 2*armynumber*sizeof(army));
                                      _lwrite(file_handle, &after_battle, sizeof(BOOL));
                                      _lwrite(file_handle, &popnation, sizeof(int));
                                      _lclose(file_handle);
                                    }

                               }
                             return 0;
                  case 1000: after_battle = FALSE;
                             show_troops(hwnd);
                             EnableMenuItem (hMenu, 1000, MF_GRAYED);
                             EnableMenuItem (hMenu, 1001, MF_ENABLED);
                             return 0;
                  case 1001: after_battle = TRUE;
                             show_troops(hwnd);
                             EnableMenuItem (hMenu, 1001, MF_GRAYED);
                             EnableMenuItem (hMenu, 1000, MF_ENABLED);
                             return 0;
                  case 1501: DialogBox (hInstance, "dialog_4",hwnd, lpfntr_terr_change);
			     for (side = 0; side <= 1; side++)
                                for (number = 0; number < armynumber; number++)
                                   calc_combat_values(&arm[side][number]);
                             calc_losses();
                             show_troops(hwnd);
                             return 0;
                  case 1502: DialogBox (hInstance, "dialog_5",hwnd, lpfntr_tac_change);
			     for (side = 0; side <= 1; side++)
                                for (number = 0; number < armynumber; number++)
                                   calc_combat_values(&arm[side][number]);
                             calc_losses();
                             show_troops(hwnd);
                             return 0;
                  case 1503: DialogBox (hInstance, "dialog_6",hwnd, lpfntac_vs_tac_change);
			     for (side = 0; side <= 1; side++)
                                for (number = 0; number < armynumber; number++)
                                   calc_combat_values(&arm[side][number]);
                             calc_losses();
                             show_troops(hwnd);
                             return 0;
                  case 1506: DialogBox (hInstance, "dialog_8", hwnd, lpfnsplit_losses);
                             calc_losses();
                             show_troops(hwnd);
                             return 0;
                  case 1504: ofn.Flags = OFN_FILEMUSTEXIST;
                             ofn.lpstrFilter = szfilter2[0];
                             if (GetOpenFileName(&ofn))
                               { file_handle = _lopen(filename, OF_READ | OF_SHARE_DENY_WRITE);
                                 if (file_handle == -1)
                                    MessageBox (hwnd, "Canīt open file !!", "Error !!", MB_OK);
                                 else
                                    { _lread(file_handle, &zw_vers, sizeof(int));
                                      if (zw_vers != version)
                                         MessageBox (hwnd, "File has been saved with\nanother version number !!", "Error !!", MB_OK);
                                      else
                                        {
                                          _lread(file_handle, &tr_terr_mod, sizeof(tr_terr_mod));
                                          _lread(file_handle, &tr_tact_mod, sizeof(tr_tact_mod));
                                          _lread(file_handle, &tac_vs_tac, sizeof(tac_vs_tac));
                                          _lread(file_handle, &spl_los, sizeof(spl_los));
			                  for (side = 0; side <= 1; side++)
                                             for (number = 0; number < armynumber; number++)
                                                calc_combat_values(&arm[side][number]);
                                          calc_losses();
                                          show_troops(hwnd);
                                        }
                                      _lclose(file_handle);
                                    }

                               }
                             return 0;
                  case 1505: ofn.Flags = OFN_OVERWRITEPROMPT;
                             ofn.lpstrFilter = szfilter2[0];
                             if (GetSaveFileName(&ofn))
                               { file_handle = _lcreat(filename, 0);
                                 if (file_handle == -1)
                                    MessageBox (hwnd, "Canīt create file !!", "Error !!", MB_OK);
                                 else
                                    { _lwrite(file_handle, &version, sizeof(int));
                                      _lwrite(file_handle, &tr_terr_mod, sizeof(tr_terr_mod));
                                      _lwrite(file_handle, &tr_tact_mod, sizeof(tr_tact_mod));
                                      _lwrite(file_handle, &tac_vs_tac, sizeof(tac_vs_tac));
                                      _lwrite(file_handle, &spl_los, sizeof(spl_los));
                                      _lclose(file_handle);
                                    }

                               }
                             return 0;
                  case 1099: WinHelp(hwnd, "mepbm_e1.hlp", HELP_INDEX, NULL);
                             return 0;
	       }
            return 0;
	 case WM_DESTROY:
            FreeProcInstance((FARPROC)new_edit_proc);
            FreeProcInstance((FARPROC)new_edit_proc2);
            FreeProcInstance((FARPROC)lpfnarmychange);
            FreeProcInstance((FARPROC)lpfnpopchange);
            FreeProcInstance((FARPROC)lpfntr_tac_change);
            FreeProcInstance((FARPROC)lpfntr_terr_change);
            FreeProcInstance((FARPROC)lpfntac_vs_tac_change);
            FreeProcInstance((FARPROC)lpfnsplit_losses);
	    PostQuitMessage (0);
	    return 0;
      }
   return DefWindowProc (hwnd, message, wParam, lParam);
}


void show_troops (HWND hwnd)

{  int side, number, k;
   char fuzz[200];

   for (side = 0; side <= 1; side ++)
     {
      total_strength[side] = 0;
      total_constit[side] = 0;
      for (number = 0; number < armynumber; number ++)
        { if (after_battle) k = 4; else  k = 3; 
	  sprintf(fuzz,"%ld HC, %ld LC, %ld HI, %ld LI, %ld AR, %ld MA",
	     arm[side][number].troops[0][k],arm[side][number].troops[1][k],
	     arm[side][number].troops[2][k],arm[side][number].troops[3][k],
	     arm[side][number].troops[4][k],arm[side][number].troops[5][k]);
	  SetWindowText(GetDlgItem(hwnd,(side+4)*100+number+1), fuzz);
          if (after_battle)
  	     sprintf(fuzz,"S: %ld C: %ld",
	        arm[side][number].new_stren,arm[side][number].new_const);
          else
  	     sprintf(fuzz,"S: %ld C: %ld",
	        arm[side][number].strength,arm[side][number].constit);
	  SetWindowText(GetDlgItem(hwnd,(side+4)*100+number+51), fuzz);
          if (arm[side][number].constit != 0)
             sprintf(fuzz, "%d%%",
               (int)(100.5-arm[side][number].new_const/(float)arm[side][number].constit*100));
          else sprintf(fuzz, "0%%");
	  SetWindowText(GetDlgItem(hwnd,side*10+number+801), fuzz);
	  if (after_battle)
	     { total_strength[side] += arm[side][number].new_stren;
	       total_constit[side] += arm[side][number].new_const;
	     }
          else
	     { total_strength[side] += arm[side][number].strength;
	       total_constit[side] += arm[side][number].constit;
	     }
        }
       sprintf(fuzz,"Total Strength: %ld", total_strength[side]);
       SetWindowText(GetDlgItem(hwnd,600+side), fuzz);
       sprintf(fuzz,"Total Constitution: %ld", total_constit[side]);
       SetWindowText(GetDlgItem(hwnd,602+side), fuzz);
     }
   sprintf(fuzz, popultype[populpos]);
   SetWindowText(GetDlgItem(hwnd,701), fuzz);
   sprintf(fuzz, fortiftype[fortifpos]);
   SetWindowText(GetDlgItem(hwnd,702), fuzz);
   sprintf(fuzz, "%d", populloyal);
   SetWindowText(GetDlgItem(hwnd,703), fuzz);
   if (captured)
        sprintf(fuzz, "(captured)    ");
   else sprintf(fuzz, "(not captured)");                     
   SetWindowText (GetDlgItem(hwnd,704), fuzz);
   sprintf(fuzz, "%d", round);
   SetWindowText(GetDlgItem(hwnd,750), fuzz);
}


BOOL FAR PASCAL _export new_edit_proc (HWND hdlg, UINT message, UINT wParam,
				    LONG lParam)
{ long z;
  int win_id, n;

  win_id = GetWindowWord(hdlg, GWW_ID);
  n = 0;
  while (conv[n] != win_id) n++;
  switch (message)
    { case WM_KEYUP:
        if (wParam == VK_RETURN)
          { SetFocus(GetNextDlgTabItem(GetParent(hdlg), hdlg, FALSE));
            return TRUE;
          }
        break;

      case WM_KEYDOWN:
         if ((win_id / 100 == 2) && (GetKeyState(VK_CONTROL) < 0))
            switch (wParam)
              {
                case VK_LEFT: if (win_id % 10 > 0)
                                SetFocus(GetDlgItem(GetParent(hdlg),win_id-1));
                              return TRUE;
                case VK_RIGHT: if (win_id % 10 < 3)
                                SetFocus(GetDlgItem(GetParent(hdlg),win_id+1));
                              return TRUE;
                case VK_UP: if (win_id / 10 > 20)
                                SetFocus(GetDlgItem(GetParent(hdlg),win_id-10));
                              return TRUE;
                case VK_DOWN: if (win_id / 10 < 25)
                                SetFocus(GetDlgItem(GetParent(hdlg),win_id+10));
                              return TRUE;
              }
         break;
    }

  return CallWindowProc(oldproc[n], hdlg, message, wParam, lParam);
}


BOOL FAR PASCAL _export armychange (HWND hdlg, UINT message, UINT wParam,
				    LONG lParam)

  {
   static HWND hnation, htactic;
   char *tatictype[6] = {"Charge", "Flank", "Standard", "Surround", "Hit & Run", "Ambush"};
   int i, tacticmax = 6;
   long dummy;
   char fuzz[200];
   static int boxno = 0;
   RECT rect;
   static FARPROC lpfnsetrelations;

   switch (message)
      {
	case WM_INITDIALOG:
           lpfnsetrelations = MakeProcInstance ((FARPROC)set_relations, hInstance);
           for (i = 0; i < 34; i++)
            { oldproc[i] = (FARPROC) GetWindowLong(GetDlgItem(hdlg,conv[i]),GWL_WNDPROC);
	       SetWindowLong(GetDlgItem(hdlg,conv[i]),GWL_WNDPROC,(LONG)newproc);
             }
	   if (side == 0) sprintf(fuzz,"Attacking Army %d",number+1);
		     else sprintf(fuzz,"Defending Army %d",number+1);
	   SetWindowText (hdlg, fuzz);   
	   zw = arm[side][number];
	   hnation = GetDlgItem (hdlg, 101);
	   for (i = 0; i <= nationmax-1; i++)
	     { SendMessage (hnation, CB_ADDSTRING, 0, (LONG) nationtype[i]);
	     }
	   SendMessage (hnation, CB_SETCURSEL, arm[side][number].nation, 0L);
           htactic = GetDlgItem (hdlg, 160);
           for (i = 0; i < tacticmax; i++)
              { SendMessage (htactic, CB_ADDSTRING, 0, (LONG) tatictype[i]);
              }
           SendMessage (htactic, CB_SETCURSEL, arm[side][number].tactic, 0L); 
	   insert_values(hdlg, &arm[side][number], (side == 0));
	   return TRUE;


           case WM_PAINT:
	    if (boxno != 0)
	       { SendMessage (GetDlgItem(hdlg,boxno),EM_SETSEL,0, MAKELONG(0,8));
		 boxno = 0;
               }
	    break;


	case WM_COMMAND:
	   switch (wParam)
	     { case 140: EndDialog (hdlg,0);
                         FreeProcInstance((FARPROC)set_relations);
			 return TRUE;
	       case 141: arm[side][number] = zw;
			 EndDialog (hdlg,1);
                         FreeProcInstance((FARPROC)set_relations);
			 return TRUE;
	       case 142: if (MessageBox(hdlg, "Do you really want to\nterminate this army ??"
			    , "Do you know what you are doing?", MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION)
			    == IDYES)
			    { create_default_army (&arm[side][number]);
			      insert_values (hdlg, &arm[side][number], (side == 0));
			    }
	       		 return TRUE; 
               case 150: if (HIWORD (lParam) == BN_CLICKED)
                            { DialogBox(hInstance, "dialog_2", hdlg, lpfnsetrelations);
                              insert_values (hdlg, &arm[side][number], (side == 0));
                           }
                         return TRUE;
	       case 101:  if (HIWORD(lParam) == CBN_SELCHANGE)
			    { arm[side][number].nation = SendMessage (hnation, CB_GETCURSEL, 0, 0L);
                              insert_values (hdlg, &arm[side][number], (side == 0));
                            }
                          return TRUE;
	       case 160:  if (HIWORD(lParam) == CBN_SELCHANGE)
			    { arm[side][number].tactic = SendMessage (htactic, CB_GETCURSEL, 0, 0L);
                              insert_values (hdlg, &arm[side][number], (side == 0));
                            }
                          return TRUE;
               case 102:
	       case 103:
	       case 104:
	       case 105:
	       case 106:
	       case 200:
	       case 201:
	       case 202:
	       case 203:
	       case 210:
	       case 211:
	       case 212:
	       case 213:
	       case 220:
	       case 221:
	       case 222:
	       case 223:
	       case 230:
	       case 231:
	       case 232:
	       case 233:
	       case 240:
	       case 241:
	       case 242:
	       case 243:
	       case 250:
	       case 251:
	       case 252:
	       case 253: if (HIWORD(lParam) == EN_KILLFOCUS)
			    {int i; for(i=0;i<40;i++)fuzz[i]=0;
			     fuzz[1]=42;
	        	     SendMessage (GetDlgItem(hdlg,wParam),EM_GETLINE, 0, (long)fuzz);
			     dummy = atol(fuzz);
                             if (dummy < 0) dummy = 0;
		    	  /*   SendMessage (GetDlgItem(hdlg,wParam),EM_SETSEL,0, MAKELONG(0,8));
		      	     sprintf(fuzz, "%ld", dummy);
			     SendMessage (GetDlgItem(hdlg,wParam),EM_REPLACESEL,0, (LONG)(fuzz));*/
			     switch (wParam)
                               { case 102: arm[side][number].comm = dummy; break;
			         case 103: arm[side][number].off_spell = dummy; break;
			         case 104: arm[side][number].def_spell = dummy; break;
			         case 105: arm[side][number].warmach = dummy; break;
				 case 106: arm[side][number].morale = dummy; break;
				 default: arm[side][number].troops[(wParam-200)/10]
				            [wParam%10] = dummy;
			       }
                             insert_values(hdlg,&arm[side][number], (side == 0));
			     return TRUE;
			    }
		          else if (HIWORD(lParam) == EN_SETFOCUS)
     		   		{boxno = wParam;
		     	     	 GetClientRect(GetDlgItem(hdlg,boxno), &rect);
			      	 InvalidateRect(hdlg, &rect, TRUE);
			         return TRUE;
			       	}
	     }
           return FALSE;

         case WM_CLOSE:
	       switch (MessageBox(hdlg, "Do you want to keep\nthe changes ??"
			    , "", MB_YESNOCANCEL | MB_DEFBUTTON1 | MB_ICONQUESTION))
                 {
	          case IDYES:    EndDialog (hdlg,0);
                                 FreeProcInstance((FARPROC)set_relations);
		                 return TRUE;
	          case IDNO:     arm[side][number] = zw;
                                 FreeProcInstance((FARPROC)set_relations);
                                 EndDialog (hdlg,1);
	          case IDCANCEL: return FALSE;
       		 }
       	       return FALSE;

     }
   return FALSE;
}


BOOL FAR PASCAL _export new_edit_proc2 (HWND hdlg, UINT message, UINT wParam,
				    LONG lParam)
{ 
  switch (message)
    { case WM_KEYUP:
        if (wParam == VK_RETURN)
          { SetFocus(GetNextDlgTabItem(GetParent(hdlg), hdlg, FALSE));
            return TRUE;
          }
        break;
    }
  return CallWindowProc(oldproc2, hdlg, message, wParam, lParam);
}



BOOL FAR PASCAL _export popchange (HWND hdlg, UINT message, UINT wParam,
				    LONG lParam)

  {
   static HWND hpopul, hfortif, hnation;
   long dummy;
   int i,k;
   static int zwpop, zwfor, zwnat, zwloy;
   char fuzz[200];
   static int boxno = 0;
   RECT rect;

   switch (message)
      {
	case WM_INITDIALOG:
           oldproc2 = (FARPROC) GetWindowLong(GetDlgItem(hdlg,104),GWL_WNDPROC);
	   SetWindowLong(GetDlgItem(hdlg,104),GWL_WNDPROC,(LONG)newproc2);
	   hnation = GetDlgItem (hdlg, 101);
	   for (i = 0; i <= nationmax-1; i++)
	     { SendMessage (hnation, CB_ADDSTRING, 0, (LONG) nationtype[i]);
	     }
	   SendMessage (hnation, CB_SETCURSEL, popnation, 0L);
	   hpopul = GetDlgItem (hdlg, 102);
	   for (i = 0; i <= populmax-1; i++)
	     { SendMessage (hpopul, CB_ADDSTRING, 0, (LONG) popultype[i]);
	     }
           SendMessage (hpopul, CB_SETCURSEL, populpos, 0L);
	   hfortif = GetDlgItem (hdlg, 103);
	   for (i = 0; i <= fortifmax-1; i++)
	     { SendMessage (hfortif, CB_ADDSTRING, 0, (LONG) fortiftype[i]);
	     }
           SendMessage (hfortif, CB_SETCURSEL, fortifpos, 0L);
           SendMessage (GetDlgItem(hdlg,104),EM_SETSEL,0, MAKELONG(0,8));
           sprintf(fuzz, "%d", populloyal);
	   SendMessage (GetDlgItem(hdlg,104),EM_REPLACESEL,0, (LONG)(fuzz));
           insert_pop_values(hdlg);
	   zwpop = populpos;
           zwfor = fortifpos;
           zwnat = popnation;
           zwloy = populloyal;
	   return TRUE;


           case WM_PAINT:
	    if (boxno != 0)
	       { SendMessage (GetDlgItem(hdlg,boxno),EM_SETSEL,0, MAKELONG(0,8));
		 boxno = 0;
               }
	    break;


	case WM_COMMAND:
	   switch (wParam)
	     { case 140: EndDialog (hdlg,0);
			 return TRUE;
	       case 141: populpos = zwpop;
                         fortifpos = zwfor;
                         popnation = zwnat;
                         populloyal = zwloy;
			 EndDialog (hdlg,1);
			 return TRUE;
	       case 101:  if (HIWORD(lParam) == CBN_SELCHANGE)
			    { popnation = SendMessage (hnation, CB_GETCURSEL, 0, 0L);
                              insert_pop_values(hdlg);
                            }
                          return TRUE;
	       case 104:  if (HIWORD(lParam) == EN_KILLFOCUS)
			    {int i; for(i=0;i<40;i++)fuzz[i]=0;
			     fuzz[1]=42;
			     SendMessage (GetDlgItem(hdlg,104),EM_GETLINE, 0, (long)fuzz);
			     k = atoi(fuzz);
                             if (k < 0) k = 0;
                             if (k != populloyal)
                               { populloyal = k;
                                 SendMessage (GetDlgItem(hdlg,104),EM_SETSEL,0, MAKELONG(0,8));
		      		 sprintf(fuzz, "%d", populloyal);
			         SendMessage (GetDlgItem(hdlg,104),EM_REPLACESEL,0, (LONG)(fuzz));
                                 insert_pop_values(hdlg);
                               }
			     return TRUE;
			    }
		 	  else if (HIWORD(lParam) == EN_SETFOCUS)
		   	     {boxno = 104;
		     	      GetClientRect(GetDlgItem(hdlg,boxno), &rect);
			      InvalidateRect(hdlg, &rect, TRUE);
			      return TRUE;
			     }
	       case 102:  if (HIWORD(lParam) == CBN_SELCHANGE)
			    { populpos = SendMessage (hpopul, CB_GETCURSEL, 0, 0L);
                              insert_pop_values(hdlg);
                            }
                          return TRUE;
	       case 103:  if (HIWORD(lParam) == CBN_SELCHANGE)
			    { fortifpos = SendMessage (hfortif, CB_GETCURSEL, 0, 0L);
                              insert_pop_values(hdlg);
                            }
			  return TRUE;
	     }
           return FALSE;

         case WM_CLOSE:
	       switch (MessageBox(hdlg, "Do you want to keep\nthe changes ??"
			    , "", MB_YESNOCANCEL | MB_DEFBUTTON1 | MB_ICONQUESTION))
                 {
	          case IDYES:    EndDialog (hdlg,0);
		                 return TRUE;
	          case IDNO:     populpos = zwpop;
                                 fortifpos = zwfor;
                                 popnation = zwnat;
                                 populloyal = zwloy;
                                 EndDialog (hdlg,1);
	          case IDCANCEL: return FALSE;
       		 }
       	       return FALSE;

     }
   return FALSE;
}



void insert_pop_values (HWND hdlg)

  {
    char fuzz[100];
    int i;
    long att_strength;
    long popul_total;

    if (populpos == 0) {popul_total = 0;}
      else popul_total = ((populdefence[populpos]
       + fortifdefence[fortifpos])*(100+populloyal))/100;
    sprintf (fuzz, "%ld", popul_total);
    SetWindowText (GetDlgItem(hdlg,105), fuzz);
    for (i=0; i < armynumber; i++)
       calc_combat_values(&arm[1][i]);
    att_strength = calc_losses();
    sprintf(fuzz, "%ld", att_strength);
    SetWindowText (GetDlgItem(hdlg,106),fuzz);
    if (captured)
         sprintf(fuzz, "Population Center Captured    ");
    else sprintf(fuzz, "Population Center Not Captured");
    SetWindowText (GetDlgItem(hdlg,107), fuzz);

  }



BOOL FAR PASCAL _export tr_terr_change (HWND hdlg, UINT message, UINT wParam,
				    LONG lParam)

  {
   int i, j;
   static int zw1[6][7];
   long dummy;
   char fuzz[200];
   static int boxno = 0;
   RECT rect;

   switch (message)
      {
	case WM_INITDIALOG:
	   _fmemcpy(zw1,tr_terr_mod,sizeof(zw1));
           for (i = 0; i <= 6; i++)
              for (j = 0; j <= 5; j++)
                 { SendMessage (GetDlgItem(hdlg,200+10*j+i),EM_SETSEL,0, MAKELONG(0,8));
                   sprintf(fuzz, "%d", tr_terr_mod[j][i]);
	           SendMessage (GetDlgItem(hdlg,200+10*j+i),EM_REPLACESEL,0, (LONG)(fuzz));
	         }
	   return TRUE;


           case WM_PAINT:
	    if (boxno != 0)
	       { SendMessage (GetDlgItem(hdlg,boxno),EM_SETSEL,0, MAKELONG(0,8));
		 boxno = 0;
               }
	    break;


	case WM_COMMAND:
	   switch (wParam)
	     { case 140: EndDialog (hdlg,0);
			 return TRUE;
	       case 141: _fmemcpy(tr_terr_mod, zw1, sizeof(zw1));
			 EndDialog (hdlg,1);
			 return TRUE;
	       case 200: case 201: case 202: case 203: case 204: case 205:
	       case 206: case 210: case 211: case 212: case 213: case 214:
	       case 215: case 216: case 220: case 221: case 222: case 223:
	       case 224: case 225: case 226: case 230: case 231: case 232:
	       case 233: case 234: case 235: case 236: case 240: case 241:
	       case 242: case 243: case 244: case 245: case 246: case 250:
	       case 251: case 252: case 253: case 254: case 255:
	       case 256: if (HIWORD(lParam) == EN_KILLFOCUS)
			    {int i; for(i=0;i<40;i++)fuzz[i]=0;
			     fuzz[1]=42;
	        	     SendMessage (GetDlgItem(hdlg,wParam),EM_GETLINE, 0, (long)fuzz);
			     dummy = atol(fuzz);
                             if (dummy < 0) dummy = 0;
		    	     SendMessage (GetDlgItem(hdlg,wParam),EM_SETSEL,0, MAKELONG(0,8));
		      	     sprintf(fuzz, "%ld", dummy);
			     SendMessage (GetDlgItem(hdlg,wParam),EM_REPLACESEL,0, (LONG)(fuzz));
			     tr_terr_mod[(wParam-200)/10][wParam%10] = dummy;
			     return TRUE;
			    }
		          else if (HIWORD(lParam) == EN_SETFOCUS)
     		   		{boxno = wParam;
		     	     	 GetClientRect(GetDlgItem(hdlg,boxno), &rect);
			      	 InvalidateRect(hdlg, &rect, TRUE);
			         return TRUE;
			       	}
	     }
           return FALSE;

         case WM_CLOSE:
	       switch (MessageBox(hdlg, "Do you want to keep\nthe changes ??"
			    , "", MB_YESNOCANCEL | MB_DEFBUTTON1 | MB_ICONQUESTION))
                 {
	          case IDYES:    EndDialog (hdlg,0);
		                 return TRUE;
	          case IDNO:     _fmemcpy(tr_terr_mod, zw1, sizeof(zw1));
                                 EndDialog (hdlg,1);
	          case IDCANCEL: return FALSE;
       		 }
       	       return FALSE;

     }
   return FALSE;
}


BOOL FAR PASCAL _export tr_tac_change (HWND hdlg, UINT message, UINT wParam,
				    LONG lParam)

  {
   int i, j;
   static int zw1[6][6];
   long dummy;
   char fuzz[200];
   static int boxno = 0;
   RECT rect;

   switch (message)
      {
	case WM_INITDIALOG:
	   _fmemcpy(zw1,tr_tact_mod,sizeof(zw1));
           for (i = 0; i <= 5; i++)
              for (j = 0; j <= 5; j++)
                 { SendMessage (GetDlgItem(hdlg,200+10*j+i),EM_SETSEL,0, MAKELONG(0,8));
                   sprintf(fuzz, "%d", tr_tact_mod[j][i]);
	           SendMessage (GetDlgItem(hdlg,200+10*j+i),EM_REPLACESEL,0, (LONG)(fuzz));
	         }
	   return TRUE;


           case WM_PAINT:
	    if (boxno != 0)
	       { SendMessage (GetDlgItem(hdlg,boxno),EM_SETSEL,0, MAKELONG(0,8));
		 boxno = 0;
               }
	    break;


	case WM_COMMAND:
	   switch (wParam)
	     { case 140: EndDialog (hdlg,0);
			 return TRUE;
	       case 141: _fmemcpy(tr_tact_mod, zw1, sizeof(zw1));
			 EndDialog (hdlg,1);
			 return TRUE;
	       case 200: case 201: case 202: case 203: case 204: case 205:
	       case 210: case 211: case 212: case 213: case 214:
	       case 215: case 220: case 221: case 222: case 223:
	       case 224: case 225: case 230: case 231: case 232:
	       case 233: case 234: case 235: case 240: case 241:
	       case 242: case 243: case 244: case 245: case 250:
	       case 251: case 252: case 253: case 254: 
	       case 255: if (HIWORD(lParam) == EN_KILLFOCUS)
			    {int i; for(i=0;i<40;i++)fuzz[i]=0;
			     fuzz[1]=42;
	        	     SendMessage (GetDlgItem(hdlg,wParam),EM_GETLINE, 0, (long)fuzz);
			     dummy = atol(fuzz);
                             if (dummy < 0) dummy = 0;
		    	     SendMessage (GetDlgItem(hdlg,wParam),EM_SETSEL,0, MAKELONG(0,8));
		      	     sprintf(fuzz, "%ld", dummy);
			     SendMessage (GetDlgItem(hdlg,wParam),EM_REPLACESEL,0, (LONG)(fuzz));
			     tr_tact_mod[(wParam-200)/10][wParam%10] = dummy;
			     return TRUE;
			    }
		          else if (HIWORD(lParam) == EN_SETFOCUS)
     		   		{boxno = wParam;
		     	     	 GetClientRect(GetDlgItem(hdlg,boxno), &rect);
			      	 InvalidateRect(hdlg, &rect, TRUE);
			         return TRUE;
			       	}
	     }
           return FALSE;

         case WM_CLOSE:
	       switch (MessageBox(hdlg, "Do you want to keep\nthe changes ??"
			    , "", MB_YESNOCANCEL | MB_DEFBUTTON1 | MB_ICONQUESTION))
                 {
	          case IDYES:    EndDialog (hdlg,0);
		                 return TRUE;
	          case IDNO:     _fmemcpy(tr_tact_mod, zw1, sizeof(zw1));
                                 EndDialog (hdlg,1);
	          case IDCANCEL: return FALSE;
       		 }
       	       return FALSE;

     }
   return FALSE;
}


BOOL FAR PASCAL _export tac_vs_tac_change (HWND hdlg, UINT message, UINT wParam,
				    LONG lParam)

  {
   int i, j;
   static int zw1[6][6];
   long dummy;
   char fuzz[200];
   static int boxno = 0;
   RECT rect;

   switch (message)
      {
	case WM_INITDIALOG:
	   _fmemcpy(zw1, tac_vs_tac,sizeof(zw1));
           for (i = 0; i <= 5; i++)
              for (j = 0; j <= 5; j++)
                 { SendMessage (GetDlgItem(hdlg,200+10*j+i),EM_SETSEL,0, MAKELONG(0,8));
                   sprintf(fuzz, "%d", tac_vs_tac[j][i]);
	           SendMessage (GetDlgItem(hdlg,200+10*j+i),EM_REPLACESEL,0, (LONG)(fuzz));
	         }
	   return TRUE;


           case WM_PAINT:
	    if (boxno != 0)
	       { SendMessage (GetDlgItem(hdlg,boxno),EM_SETSEL,0, MAKELONG(0,8));
		 boxno = 0;
               }
	    break;


	case WM_COMMAND:
	   switch (wParam)
	     { case 140: EndDialog (hdlg,0);
			 return TRUE;
	       case 141: _fmemcpy(tac_vs_tac, zw1, sizeof(zw1));
			 EndDialog (hdlg,1);
			 return TRUE;
	       case 200: case 201: case 202: case 203: case 204: case 205:
	       case 210: case 211: case 212: case 213: case 214:
	       case 215: case 220: case 221: case 222: case 223:
	       case 224: case 225: case 230: case 231: case 232:
	       case 233: case 234: case 235: case 240: case 241:
	       case 242: case 243: case 244: case 245: case 250:
	       case 251: case 252: case 253: case 254: 
	       case 255: if (HIWORD(lParam) == EN_KILLFOCUS)
			    {int i; for(i=0;i<40;i++)fuzz[i]=0;
			     fuzz[1]=42;
	        	     SendMessage (GetDlgItem(hdlg,wParam),EM_GETLINE, 0, (long)fuzz);
			     dummy = atol(fuzz);
                             if (dummy < 0) dummy = 0;
		    	     SendMessage (GetDlgItem(hdlg,wParam),EM_SETSEL,0, MAKELONG(0,8));
		      	     sprintf(fuzz, "%ld", dummy);
			     SendMessage (GetDlgItem(hdlg,wParam),EM_REPLACESEL,0, (LONG)(fuzz));
			     tac_vs_tac[(wParam-200)/10][wParam%10] = dummy;
			     return TRUE;
			    }
		          else if (HIWORD(lParam) == EN_SETFOCUS)
     		   		{boxno = wParam;
		     	     	 GetClientRect(GetDlgItem(hdlg,boxno), &rect);
			      	 InvalidateRect(hdlg, &rect, TRUE);
			         return TRUE;
			       	}
	     }
           return FALSE;

         case WM_CLOSE:
	       switch (MessageBox(hdlg, "Do you want to keep\nthe changes ??"
			    , "", MB_YESNOCANCEL | MB_DEFBUTTON1 | MB_ICONQUESTION))
                 {
	          case IDYES:    EndDialog (hdlg,0);
		                 return TRUE;
	          case IDNO:     _fmemcpy(tac_vs_tac, zw1, sizeof(zw1));
                                 EndDialog (hdlg,1);
	          case IDCANCEL: return FALSE;
       		 }
       	       return FALSE;

     }
   return FALSE;
}


void insert_values (HWND hdlg, army *zw, BOOL show_capture)

{
   char fuzz[200];
   long i,j, dummy[5] = {(*zw).comm, (*zw).off_spell, (*zw).def_spell,
			(*zw).warmach, (*zw).morale};

   show_capture = TRUE; /*is probably better*/
   calc_combat_values(zw);
   calc_losses();
   for (i = 0; i <= 5; i++)
      { SendMessage (GetDlgItem(hdlg,102+i),EM_SETSEL,0, MAKELONG(0,8));
        sprintf(fuzz, "%ld", dummy[i]);
	SendMessage (GetDlgItem(hdlg,102+i),EM_REPLACESEL,0, (LONG)(fuzz));
      }
   for (i = 0; i <= 3; i++)
      for (j = 0; j <= 5; j++)
         { SendMessage (GetDlgItem(hdlg,200+10*j+i),EM_SETSEL,0, MAKELONG(0,8));
           sprintf(fuzz, "%ld", (*zw).troops[j][i]);
	   SendMessage (GetDlgItem(hdlg,200+10*j+i),EM_REPLACESEL,0, (LONG)(fuzz));
	 }
   for (j = 0; j <= 5; j++)
      { sprintf(fuzz, "%ld", (*zw).troops[j][4]);
        SetWindowText (GetDlgItem(hdlg, 204+10*j), fuzz);
      }
   sprintf(fuzz, "%ld", (*zw).strength);
   SetWindowText (GetDlgItem(hdlg,138), fuzz);
   sprintf(fuzz, "%ld", (*zw).constit);
   SetWindowText (GetDlgItem(hdlg,139), fuzz);
   if (!show_capture)
      sprintf(fuzz, "                        ");
   else if (captured)
            sprintf(fuzz, "    Pop. Center captured");
        else sprintf(fuzz, "Pop. Center not captured");
   SetWindowText (GetDlgItem(hdlg,170), fuzz);
   return ;

}



void calc_combat_values(army *zw)

{

   long strength, constit, gr_const[6] = {16, 8, 10, 5, 2, 2},
	gr_stren[6] = {16, 8, 10, 5, 6, 2};
   int terr_clim_mod[26][7][7] = {
/*           NONE */
{100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100},
/*           WOODMEN */
{90, 90, 90, 95, 87, 85, 85, 
92, 92, 92, 97, 90, 87, 87, 
95, 95, 95, 100, 92, 90, 90, 
97, 97, 97, 102, 95, 92, 92, 
100, 100, 100, 105, 97, 95, 95, 
97, 97, 97, 102, 95, 92, 92, 
95, 95, 95, 100, 92, 90, 90},
/*           NORTHMEN */
{87, 87, 82, 80, 77, 77, 80, 
90, 90, 85, 82, 80, 80, 82, 
92, 92, 87, 85, 82, 82, 85,
95, 95, 90, 87, 85, 85, 87, 
100, 100, 95, 92, 90, 90, 92, 
97, 97, 92, 90, 87, 87, 90, 
95, 95, 90, 87, 85, 85, 87}, 
/*           EOTHRAIM */
{87, 97, 87, 77, 82, 77, 77, 
90, 100, 90, 80, 85, 80, 80, 
92, 102, 92, 82, 87, 82, 82, 
95, 105, 95, 85, 90, 85, 85, 
100, 110, 100, 90, 95, 90, 90, 
100, 110, 100, 90, 95, 90, 90, 
95, 105, 95, 85, 90, 85, 85}, 
/*           ARTHEDAIN */
{90, 92, 90, 85, 85, 82, 85, 
92, 95, 92, 87, 87, 85, 87, 
95, 97, 95, 90, 90, 87, 90, 
97, 100, 97, 92, 92, 90, 92, 
100, 102, 100, 95, 95, 92, 95, 
100, 102, 100, 95, 95, 92, 95, 
95, 97, 95, 90, 90, 87, 90}, 
/*           CARDOLAN */
{92, 90, 90, 85, 85, 82, 85, 
95, 92, 92, 87, 87, 85, 87, 
97, 95, 95, 90, 90, 87, 90, 
100, 97, 97, 92, 92, 90, 92, 
102, 100, 100, 95, 95, 92, 95, 
102, 100, 100, 95, 95, 92, 95, 
97, 95, 95, 90, 90, 87, 90}, 
/*           NORTHERN GONDOR */
{92, 92, 87, 85, 85, 82, 85, 
95, 95, 90, 87, 87, 85, 87, 
97, 97, 92, 90, 90, 87, 90, 
100, 100, 95, 92, 92, 90, 92, 
102, 102, 97, 95, 95, 92, 95, 
102, 102, 97, 95, 95, 92, 95, 
97, 97, 92, 90, 90, 87, 90}, 
/*           SOUTHERN GONDOR */
{90, 90, 90, 85, 85, 82, 85, 
92, 92, 92, 87, 87, 85, 87, 
95, 95, 95, 90, 90, 87, 90, 
97, 97, 97, 92, 92, 90, 92, 
100, 100, 100, 95, 95, 92, 95, 
100, 100, 100, 95, 95, 92, 95, 
95, 95, 95, 90, 90, 87, 90}, 
/*           DWARVES */
{92, 95, 100, 85, 92, 92, 105, 
95, 97, 102, 87, 95, 95, 107, 
97, 100, 105, 90, 97, 97, 110, 
97, 100, 105, 92, 97, 97, 110, 
97, 100, 105, 95, 97, 97, 110, 
97, 100, 105, 95, 97, 97, 110, 
95, 97, 102, 90, 95, 95, 107}, 
/*           SINDA ELVES */
{92, 90, 87, 100, 87, 85, 85, 
95, 92, 90, 102, 90, 87, 87, 
97, 95, 92, 105, 92, 90, 90, 
100, 97, 95, 107, 95, 92, 92, 
102, 100, 97, 110, 97, 95, 95, 
102, 100, 97, 110, 97, 95, 95, 
97, 95, 92, 105, 92, 90, 90}, 
/*           NOLDO ELVES */
{95, 92, 90, 97, 90, 87, 87, 
97, 95, 92, 100, 92, 90, 90, 
100, 97, 95, 102, 95, 92, 92, 
102, 100, 97, 105, 97, 95, 95, 
102, 100, 97, 105, 97, 95, 95, 
102, 100, 97, 105, 97, 95, 95, 
97, 95, 92, 100, 92, 90, 90}, 
/*           WITCH KING */
{90, 90, 90, 85, 82, 82, 87, 
92, 92, 92, 87, 85, 85, 90, 
95, 95, 95, 90, 87, 87, 92, 
97, 97, 97, 92, 90, 90, 95, 
100, 100, 100, 95, 92, 92, 97, 
97, 97, 97, 92, 90, 90, 95, 
95, 95, 95, 90, 87, 87, 90}, 
/*           DRAGON LORD */
{82, 87, 85, 85, 80, 80, 82, 
85, 90, 87, 87, 82, 82, 85, 
87, 92, 90, 90, 85, 85, 87, 
90, 95, 92, 92, 87, 87, 90, 
95, 100, 97, 97, 92, 92, 95, 
95, 100, 97, 97, 92, 92, 95, 
95, 100, 97, 97, 92, 92, 95}, 
/*           DOG LORD */
{90, 92, 87, 80, 85, 82, 85, 
92, 95, 90, 82, 87, 85, 87, 
95, 97, 92, 85, 90, 87, 90, 
97, 100, 95, 87, 92, 90, 92, 
102, 105, 100, 92, 97, 95, 97, 
102, 105, 100, 92, 97, 95, 97, 
102, 105, 100, 92, 97, 95, 97}, 
/*           CLOUD LORD */
{87, 87, 85, 82, 85, 82, 85, 
90, 90, 87, 85, 87, 85, 87, 
92, 92, 90, 87, 90, 87, 90, 
95, 95, 92, 90, 92, 90, 92, 
100, 100, 97, 95, 97, 95, 97, 
100, 100, 97, 95, 97, 95, 97, 
100, 100, 97, 95, 97, 95, 97}, 
/*           BLIND SORCERER */
{90, 87, 85, 80, 85, 80, 85, 
92, 90, 87, 82, 87, 82, 87, 
95, 92, 90, 85, 90, 85, 90, 
97, 95, 92, 87, 92, 87, 92, 
102, 100, 97, 92, 97, 92, 97, 
102, 100, 97, 92, 97, 92, 97, 
102, 100, 97, 92, 97, 92, 97}, 
/*           ICE KING */
{92, 92, 90, 90, 85, 85, 90, 
95, 95, 92, 92, 87, 87, 92, 
97, 97, 95, 95, 90, 90, 95, 
97, 97, 95, 95, 90, 90, 95, 
100, 100, 97, 97, 92, 92, 97, 
100, 100, 97, 97, 92, 92, 97, 
97, 97, 95, 95, 90, 90, 95}, 
/*           QUIET AVENGER */
{90, 87, 90, 82, 87, 77, 80, 
92, 90, 92, 85, 90, 80, 82, 
95, 92, 95, 87, 92, 82, 85, 
97, 95, 97, 90, 95, 85, 87, 
102, 100, 102, 95, 100, 90, 92, 
105, 102, 105, 97, 102, 92, 95, 
102, 100, 102, 95, 100, 90, 92}, 
/*           FIRE KING */
{87, 87, 87, 82, 87, 80, 85, 
90, 90, 90, 85, 90, 82, 87, 
92, 92, 92, 87, 92, 85, 90, 
95, 95, 95, 90, 95, 87, 92, 
100, 100, 100, 95, 100, 92, 97, 
100, 100, 100, 95, 100, 92, 97, 
100, 100, 100, 95, 100, 92, 97}, 
/*           LONG RIDER */
{87, 92, 87, 77, 85, 80, 85, 
90, 95, 90, 80, 87, 82, 87, 
92, 97, 92, 82, 90, 85, 90, 
95, 100, 95, 85, 92, 87, 92, 
100, 105, 100, 90, 97, 92, 97, 
97, 102, 97, 87, 95, 90, 95, 
97, 102, 97, 87, 95, 90, 95}, 
/*           DARK LIEUTENANTS */
{87, 87, 85, 82, 85, 82, 85, 
90, 90, 87, 85, 87, 85, 87, 
92, 92, 90, 87, 90, 87, 90, 
95, 95, 92, 90, 92, 90, 92, 
100, 100, 97, 95, 97, 95, 97, 
100, 100, 97, 95, 97, 95, 97, 
100, 100, 97, 95, 97, 95, 97}, 
/*           CORSAIRS */
{90, 87, 85, 82, 85, 80, 77, 
92, 90, 87, 85, 87, 82, 80, 
95, 92, 90, 87, 90, 85, 82, 
97, 95, 92, 90, 92, 87, 85, 
102, 100, 97, 95, 97, 92, 90, 
102, 100, 97, 95, 97, 92, 90, 
100, 97, 95, 92, 95, 90, 87}, 
/*           HARADWAITH */
{90, 87, 90, 80, 87, 77, 80, 
92, 90, 92, 82, 90, 80, 82, 
97, 95, 97, 87, 95, 85, 87, 
100, 97, 100, 90, 97, 87, 90, 
102, 100, 102, 92, 100, 90, 92, 
105, 102, 105, 95, 102, 92, 95, 
102, 100, 102, 92, 100, 90, 92}, 
/*           DUNLENDINGS */
{87, 87, 92, 85, 85, 85, 92, 
90, 90, 95, 87, 87, 87, 95, 
92, 92, 97, 90, 90, 90, 97, 
95, 95, 100, 92, 92, 92, 100, 
100, 100, 105, 97, 97, 97, 105, 
97, 97, 102, 95, 95, 95, 102, 
95, 95, 100, 92, 92, 92, 100}, 
/*           RHUDAUR */
{90, 90, 92, 92, 85, 82, 85, 
92, 92, 95, 95, 87, 85, 87, 
95, 95, 97, 97, 90, 87, 90, 
97, 97, 100, 100, 92, 90, 92, 
100, 100, 102, 102, 95, 92, 95, 
100, 100, 102, 102, 95, 92, 95, 
95, 95, 97, 97, 90, 87, 90}, 
/*           EASTERLINGS */
{87, 92, 85, 80, 85, 77, 77, 
90, 95, 87, 82, 87, 80, 80, 
92, 97, 90, 85, 90, 82, 82, 
95, 100, 92, 87, 92, 85, 85, 
100, 105, 97, 92, 97, 90, 90, 
97, 102, 95, 90, 95, 87, 87, 
97, 102, 95, 90, 95, 87, 87}};
                          // all information from Mouth 11 from Tom Walton and Brian Mason

   int i;

   constit = 0;
   for (i = 0; i < 6; i++)
      constit += ((long)(*zw).troops[i][3]*gr_const[i]*(100+(*zw).troops[i][2]))/100;
   if (((*zw).nation == popnation) && (popnation != 0) /*bonus because of fortifications*/
      && (populpos != 0) && (fortifpos != 0))
      constit = constit*(1.075+fortifpos*0.025);
   strength = 0;
   for (i = 0; i < 6; i++)
      strength += ((long)(*zw).troops[i][3]*gr_stren[i]
		    *((*zw).troops[i][0]+(*zw).troops[i][1]+tr_terr_mod[i][terrpos]
						  +tr_tact_mod[i][(*zw).tactic]))/400;
   strength *= (*zw).comm+terr_clim_mod[(*zw).nation][climpos][terrpos]*2+(*zw).morale;
   strength /= 400;
   (*zw).strength = strength;
   (*zw).constit = constit;
   (*zw).exist = !(strength == 0); 
   return ;
}

                  
void create_default_army (army *arm)

{
   int k;

   (*arm).exist = FALSE;
   (*arm).nation = 0;
   (*arm).tactic = 2;
   (*arm).comm = 50;
   (*arm).off_spell = 0;
   (*arm).def_spell = 0;
   for (k=0; k<=armynumber; k++)
      (*arm).relations[k] = 3;
   (*arm).att_town = TRUE;
   (*arm).warmach = 0;
   (*arm).morale = 50;
   for (k=0; k<6; k++)
      { (*arm).troops[k][0] = 40; // Training
	(*arm).troops[k][1] = 20; // Weapon
	(*arm).troops[k][2] = 20; // Armor
	(*arm).troops[k][3] = 0;  // Number
	(*arm).troops[k][4] = 0;} // Strength
   (*arm).troops[4][1] = 60;  // Archers Weapons
   (*arm).troops[4][2] = 0;   // Archers Armor
   (*arm).strength = 0;
   (*arm).constit = 0;
   return ;
}


long calc_losses(void)

{  int i,j,k,a,d;
   long att_constit, def_constit, att_strength, def_strength, att_gc, def_gc;
   long army_gc[2][armynumber], new_const, loss_sum, nr_warmach, fortif_def;
   long town_def;
   float fizz;
   BOOL no_def_arm;
   static int fak[5] = {75, 90, 100, 110, 125};

   round = 0;
   no_def_arm = TRUE;
   for (j = 0; j <= 1; j++)
    for (i = 0; i < armynumber; i++)
     { arm[j][i].new_const = arm[j][i].constit;
       arm[j][i].new_stren = arm[j][i].strength;
       for (k = 0; k < 6; k++)
          arm[j][i].troops[k][4] = arm[j][i].troops[k][3];
     }
   do
     { round += 1;
       att_constit = 0;
       att_strength = 0;
       def_constit = 0;
       def_strength = 0;
       att_gc = 0;
       def_gc = 0;
       for (i = 0; i < armynumber; i++)
         { att_constit += arm[0][i].new_const;
           def_constit += arm[1][i].new_const;
           att_strength += arm[0][i].new_stren;
           def_strength += arm[1][i].new_stren;
           for (j = 0; j <= 1; j++)
            { arm[j][i].losses = -arm[j][i].def_spell * (int)(round == 1);
              switch (spl_los)
                {
                 case 1 : {
                    army_gc[j][i] = arm[j][i].troops[0][4]+arm[j][i].troops[1][4]+arm[j][i].troops[2][4]
                            +arm[j][i].troops[3][4]+arm[j][i].troops[4][4]
                            +arm[j][i].troops[5][4];
                    break;
                   }
                 case 2 : {
                    army_gc[j][i] = arm[j][i].troops[0][4]*16+arm[j][i].troops[1][4]*8+arm[j][i].troops[2][4]*10
                            +arm[j][i].troops[3][4]*5+arm[j][i].troops[4][4]*6
                            +arm[j][i].troops[5][4]*2;
                    break;
                   }
                 case 3 : {
                    army_gc[j][i] = arm[j][i].new_stren;
                    break;
                   }
                 case 4 : {
                    army_gc[j][i] = arm[j][i].new_const;
                    break;
                   }
                }
            }
           att_gc += army_gc[0][i];
           def_gc += army_gc[1][i];
         }
       if (def_constit != 0) no_def_arm = FALSE;
       if ((att_gc != 0) && (def_gc != 0))
         { for (a = 0; a < armynumber; a++)
              for (d = 0; d < armynumber; d++)
                 { arm[0][a].losses += (long)((((((float)arm[1][d].new_stren
                                      *fak[arm[1][d].relations[a+1]])/100.0
                                      * tac_vs_tac [arm[1][d].tactic][arm[0][a].tactic])/100.0
                                      +arm[1][d].off_spell*(int)(round == 1)
                                      +arm[1][d].warmach*50)
                                      * army_gc[0][a])/att_gc);
                   arm[1][d].losses += (long)((((((float)arm[0][a].new_stren
                                      *fak[arm[0][a].relations[d+1]])/100.0
                                      * tac_vs_tac [arm[0][a].tactic][arm[1][d].tactic])/100.0
                                      +arm[0][a].off_spell*(int)(round == 1)
                                      +arm[0][a].warmach*50)
                                      * army_gc[1][d])/def_gc);
                 }
           loss_sum = 0;     //needed if both sides are of equal strength
           for (i = 0; i < armynumber; i++)
              for (j = 0; j <= 1; j ++)
                 if (arm[j][i].new_const != 0)
                   { if (arm[j][i].losses < 0) arm[j][i].losses = 0;
                     loss_sum += arm[j][i].losses;
                     new_const = arm[j][i].new_const - arm[j][i].losses;
                     if (new_const < 0) new_const = 0;
                     fizz = (float)arm[j][i].new_stren * new_const;
                     arm[j][i].new_stren = (long)(fizz/arm[j][i].new_const);
                     for (k = 0; k < 6; k++)
                       { fizz = (float)arm[j][i].troops[k][4] * new_const;
                         arm[j][i].troops[k][4] = (long)(fizz / arm[j][i].new_const);
                       }
                     arm[j][i].new_const = new_const;
                   }
         }
     }
   while ((att_gc != 0) && (def_gc != 0) && (loss_sum != 0));
   round--;

   fortif_def = fortifdefence[fortifpos]; //defensive value of present fortification
   nr_warmach = 0;
   for (i = 0; i < armynumber; i++)
     nr_warmach += arm[0][i].warmach*(int)(arm[0][i].att_town)*(int)(arm[0][i].new_const != 0);
     //count warmachines of armies which attack town and still exist
   fortif_def -= nr_warmach*200;  //warmachines reduce fortifications
   if (fortif_def < 0) fortif_def = 0;
   town_def = ((populdefence[populpos] + fortif_def) * (100+populloyal)) / 100;
   if (populpos == 0) town_def = 0;  // no town present
   att_constit = 0;
   att_strength = 0;
   att_gc = 0;
   for (i = 0; i < armynumber; i++)
      if (arm[0][i].att_town) 
        { att_constit += arm[0][i].new_const*(int)(arm[0][i].att_town);
          att_strength += ((arm[0][i].new_stren*fak[arm[0][i].relations[0]])/100
                             +arm[0][i].off_spell*(int)(no_def_arm))
                             *(int)(arm[0][i].att_town);
          arm[0][i].losses = -arm[0][i].def_spell*(int)(no_def_arm);
          switch (spl_los)
            {
             case 1 : {
                army_gc[0][i] = arm[0][i].troops[0][4]+arm[0][i].troops[1][4]+arm[0][i].troops[2][4]
                        +arm[0][i].troops[3][4]+arm[0][i].troops[4][4]
                        +arm[0][i].troops[5][4];
                break;
               }
             case 2 : {
                army_gc[0][i] = arm[0][i].troops[0][4]*16+arm[0][i].troops[1][4]*8+arm[0][i].troops[2][4]*10
                        +arm[0][i].troops[3][4]*5+arm[0][i].troops[4][4]*6
                        +arm[0][i].troops[5][4]*2;
                break;
               }
             case 3 : {
                army_gc[0][i] = arm[0][i].new_stren;
                break;
               }
             case 4 : {
                army_gc[0][i] = arm[0][i].new_const;
                break;
               }
            }
          att_gc += army_gc[0][i];
        }
   if (att_strength > town_def) captured = TRUE;
                         else captured = FALSE;
   if (att_gc != 0) 
     { for (a = 0; a < armynumber; a++)
           arm[0][a].losses += (long)((town_def * (float)army_gc[0][a])/att_gc
                                      *(int)(arm[0][a].att_town));
       for (i = 0; i < armynumber; i++)
             if (arm[0][i].new_const != 0)
               { if (arm[0][i].losses < 0) arm[0][i].losses = 0;
                 new_const = arm[0][i].new_const - arm[0][i].losses;
                 if (new_const < 0) new_const = 0;
                 fizz = (float)(arm[0][i].new_stren) * new_const;
                 arm[0][i].new_stren = (long)(fizz/arm[0][i].new_const);
                 for (k = 0; k < 6; k++)
                   { fizz = (float) arm[0][i].troops[k][4] * new_const;
                     arm[0][i].troops[k][4] = (long)(fizz/arm[0][i].new_const);
                   }
                 arm[0][i].new_const = new_const;
               }
   }
   return att_strength;
}


BOOL FAR PASCAL _export set_relations (HWND hdlg, UINT message, UINT wParam,
                                       LONG lParam)

{  char fuzz[200];
   static HANDLE hrelat[6], hatt_town;
   static army zw;
   int i;

   switch (message)
     { case WM_INITDIALOG:
           if (side == 0) sprintf(fuzz, "Relations of Attacking Army %d",number+1);
                     else sprintf(fuzz, "Relations of Defending Army %d",number+1);
           SetWindowText (hdlg, fuzz);
           zw = arm[side][number];
           for (i = 0; i < 6; i++)
             { hrelat[i] = GetDlgItem (hdlg, 100+i);
               SendMessage (hrelat[i], CB_ADDSTRING, 0, (LONG)"Friendly");
               SendMessage (hrelat[i], CB_ADDSTRING, 0, (LONG)"Tolerated");
               SendMessage (hrelat[i], CB_ADDSTRING, 0, (LONG)"Neutral");
               SendMessage (hrelat[i], CB_ADDSTRING, 0, (LONG)"Disliked");
               SendMessage (hrelat[i], CB_ADDSTRING, 0, (LONG)"Hated");
               SendMessage (hrelat[i], CB_SETCURSEL, arm[side][number].relations[i],0L);
             }
           hatt_town = GetDlgItem(hdlg, 160);
           SendMessage (hatt_town, BM_SETCHECK, zw.att_town, 0L);
           EnableWindow(hrelat[0], (side == 0));
           EnableWindow(GetDlgItem(hdlg, 99), (side == 0));
           EnableWindow(hatt_town, (side == 0));
           return TRUE;
       case WM_COMMAND:
           switch (wParam)
	     { case 106: EndDialog (hdlg,0);
			 return TRUE;
	       case 107: arm[side][number] = zw;
			 EndDialog (hdlg,1);
                         return TRUE;
               case 160: if (HIWORD(lParam) == BN_CLICKED)
                            arm[side][number].att_town = (BOOL) SendMessage(hatt_town, BM_GETCHECK, 0, 0L);
                         return TRUE;
               case 100:
               case 101:
               case 102:
               case 103:
               case 104:
               case 105: if (HIWORD(lParam) == CBN_SELCHANGE)
                           arm[side][number].relations[wParam-100]
                               = SendMessage (hrelat[wParam-100], CB_GETCURSEL, 0, 0L);
                         return TRUE;
             }
           return FALSE;
       case WM_CLOSE:
	     switch (MessageBox(hdlg, "Do you want to keep\nthe changes ??"
			  , "", MB_YESNOCANCEL | MB_DEFBUTTON1 | MB_ICONQUESTION))
               {
	        case IDYES:    EndDialog (hdlg,0);
		               return TRUE;
	        case IDNO:     arm[side][number] = zw;
                               EndDialog (hdlg,1);
                               return TRUE;
	        case IDCANCEL: return FALSE;
       	       }
       	     return FALSE;
     }
   return FALSE;
}


BOOL FAR PASCAL _export split_losses (HWND hdlg, UINT message, UINT wParam,
                                       LONG lParam)

{  static int zw;
   int i;

   switch (message)
     { case WM_INITDIALOG:
           SendMessage(GetDlgItem(hdlg, 100+spl_los), BM_SETCHECK, 1, 0L);
           zw = spl_los;
           return TRUE;
       case WM_COMMAND:
           switch (wParam)
	     { case 106: EndDialog (hdlg,0);
			 return TRUE;
	       case 107: spl_los = zw;
			 EndDialog (hdlg,1);
                         return TRUE;
               case 101:
               case 102:
               case 103:
               case 104: if (HIWORD(lParam) == BN_CLICKED)
                            spl_los = wParam-100;
                         return TRUE;   
             }
           return FALSE;
       case WM_CLOSE:
	     switch (MessageBox(hdlg, "Do you want to keep\nthe changes ??"
			  , "", MB_YESNOCANCEL | MB_DEFBUTTON1 | MB_ICONQUESTION))
               {
	        case IDYES:    EndDialog (hdlg,0);
		               return TRUE;
	        case IDNO:     spl_los = zw;
                               EndDialog (hdlg,1);
                               return TRUE;
	        case IDCANCEL: return FALSE;
       	       }
       	     return FALSE;
     }
   return FALSE;
}
