/* s_msg.c
 *
 * Micropolis, Unix Version.  This game was released for the Unix platform
 * in or about 1990 and has been modified for inclusion in the One Laptop
 * Per Child program.  Copyright (C) 1989 - 2007 Electronic Arts Inc.  If
 * you need assistance with this program, you may contact:
 *   http://wiki.laptop.org/go/Micropolis  or email  micropolis@laptop.org.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.  You should have received a
 * copy of the GNU General Public License along with this program.  If
 * not, see <http://www.gnu.org/licenses/>.
 * 
 *             ADDITIONAL TERMS per GNU GPL Section 7
 * 
 * No trademark or publicity rights are granted.  This license does NOT
 * give you any right, title or interest in the trademark SimCity or any
 * other Electronic Arts trademark.  You may not distribute any
 * modification of this program using the trademark SimCity or claim any
 * affliation or association with Electronic Arts Inc. or its employees.
 * 
 * Any propagation or conveyance of this program must include this
 * copyright notice and these terms.
 * 
 * If you convey this program (or any modifications of it) and assume
 * contractual liability for the program to recipients of it, you agree
 * to indemnify Electronic Arts for any liability that those contractual
 * assumptions impose on Electronic Arts.
 * 
 * You may not misrepresent the origins of this program; modified
 * versions of the program must be marked as such and not identified as
 * the original program.
 * 
 * This disclaimer supplements the one included in the General Public
 * License.  TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
 * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
 * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK.  THE ENTIRE RISK OF
 * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU.  ELECTRONIC ARTS
 * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
 * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
 * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
 * USAGE, OR TRADE PRACTICE.  ELECTRONIC ARTS DOES NOT WARRANT AGAINST
 * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
 * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
 * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
 * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
 * CORRECTED.  NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
 * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY.  SOME
 * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
 * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
 * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
 * NOT APPLY TO YOU.
 */
#include "sim.h"


QUAD LastCityPop;
short LastCategory;
short LastPicNum;
short autoGo;
short HaveLastMessage = 0;
char LastMessage[256];

void DoAutoGoto(short x, short y, char *msg);
void DoShowPicture(short id);
void DoLoseGame(void);
void SetMessageField(char *str);
void DoScenarioScore(int type);
void CheckGrowth(void);


/* comefrom: Simulate */
void
SendMessages(void)
{
  register int z;
  short PowerPop;
  float TM;

  if ((ScenarioID) && (ScoreType) && (ScoreWait)) {
    ScoreWait--;
    if (!ScoreWait)
      DoScenarioScore(ScoreType);
  }

  CheckGrowth();

  TotalZPop = ResZPop + ComZPop + IndZPop;
  PowerPop = NuclearPop + CoalPop;

  z = CityTime & 63;

  switch(z) {

  case 1:
    if ((TotalZPop >>2) >= ResZPop)
      SendMes(1); /* need Res */
    break;
  case 5:
    if ((TotalZPop >>3) >= ComZPop)
      SendMes(2); /* need Com */
    break;
  case 10:
    if ((TotalZPop >>3) >= IndZPop)
      SendMes(3); /* need Ind */
    break;
  case 14:
    if ((TotalZPop > 10) && ((TotalZPop <<1) > RoadTotal))
      SendMes(4);
    break;
  case 18:
    if ((TotalZPop > 50) && (TotalZPop > RailTotal))
      SendMes(5);
    break;
  case 22:
    if ((TotalZPop > 10) && (PowerPop == 0))
      SendMes(6); /* need Power */
    break;
  case 26:
    if ((ResPop > 500) && (StadiumPop == 0)) {
      SendMes(7); /* need Stad */
      ResCap = 1;
    }
    else
      ResCap = 0;
    break;
  case 28:
    if ((IndPop > 70) && (PortPop == 0)) {
      SendMes(8);
      IndCap = 1;
    }
    else IndCap = 0;
    break;
  case 30:
    if ((ComPop > 100) && (APortPop == 0)) {
      SendMes(9);
      ComCap = 1;
    }
    else ComCap = 0;
    break;
  case 32:
    TM = unPwrdZCnt + PwrdZCnt;	/* dec score for unpowered zones */
    if (TM)  
      if ((PwrdZCnt / TM) < .7)
	SendMes(15);
    break;
  case 35:
    if (PolluteAverage > /* 80 */ 60)
      SendMes(-10);
    break;
  case 42:
    if (CrimeAverage > 100)
      SendMes(-11);
    break;
  case 45:
    if ((TotalPop > 60) && (FireStPop == 0))
      SendMes(13);
    break;
  case 48:
    if ((TotalPop > 60) && (PolicePop == 0))
      SendMes(14);
    break;
  case 51:
    if (CityTax > 12)
      SendMes(16);
    break;
  case 54:
    if ((RoadEffect < 20) && (RoadTotal > 30))
      SendMes(17);
    break;
  case 57:
    if ((FireEffect < 700) && (TotalPop > 20))
      SendMes(18);
    break;
  case 60:
    if ((PoliceEffect < 700) && (TotalPop > 20))
      SendMes(19);
    break;
  case 63:
    if (TrafficAverage > 60)
      SendMes(-12);
    break;
  }
}


/* comefrom: SendMessages */
void
CheckGrowth(void)
{
  QUAD ThisCityPop;
  short z;

  if (!(CityTime & 3)) {
    z = 0;
    ThisCityPop = ((ResPop) + (ComPop * 8L) + (IndPop * 8L)) * 20L;
    if (LastCityPop) {
      if ((LastCityPop < 2000) && (ThisCityPop >= 2000))	z = 35;
      if ((LastCityPop < 10000) && (ThisCityPop >= 10000)) 	z = 36;
      if ((LastCityPop < 50000L) && (ThisCityPop >= 50000L)) 	z = 37;
      if ((LastCityPop < 100000L) && (ThisCityPop >= 100000L))	z = 38;
      if ((LastCityPop < 500000L) && (ThisCityPop >= 500000L))	z = 39;
    }
    if (z)
      if (z != LastCategory) {
	SendMes(-z);
	LastCategory = z;
      }
    LastCityPop = ThisCityPop;
  }
}


/* comefrom: SendMessages */
void
DoScenarioScore(int type)
{
  short z;

  z = -200;	/* you lose */
  switch(type) {
  case 1:	/* Dullsville */
	  if (CityClass >= 4)		z = -100;
	  break;
  case 2:	/* San Francisco */
	  if (CityClass >= 4)		z = -100;
	  break;
  case 3:	/* Hamburg */
	  if (CityClass >= 4)		z = -100;
	  break;
  case 4:	/* Bern */
	  if (TrafficAverage < 80)	z = -100;
	  break;
  case 5:	/* Tokyo */
	  if (CityScore > 500)		z = -100;
	  break;
  case 6:	/* Detroit */
	  if (CrimeAverage < 60)	z = -100;
	  break;
  case 7:	/* Boston */
	  if (CityScore > 500)		z = -100;
	  break;
  case 8:	/* Rio de Janeiro */
	  if (CityScore > 500)		z = -100;
	  break;
  }
  ClearMes();
  SendMes(z);

  if (z == -200)
    DoLoseGame();
}


void
ClearMes(void)
{
  MessagePort = 0;
  MesX = 0;
  MesY = 0;
  LastPicNum = 0;
}


/* comefrom: MakeEarthquake MakeFire MakeFire MakeFlood SendMessages 
	     CheckGrowth DoScenarioScore DoPowerScan */
int
SendMes(int Mnum)
{
  if (Mnum < 0) {
    if (Mnum != LastPicNum) {
      MessagePort = Mnum;
      MesX = 0;
      MesY = 0;
      LastPicNum = Mnum;
      return (1);
    }
  } else {
    if (!(MessagePort)) {
      MessagePort = Mnum;
      MesX = 0;
      MesY = 0;
      return(1);
    }
  }
  return(0);
}


/* comefrom: DoExplosion DoCopter ExplodeObject */
void SendMesAt(short Mnum, short x, short y)
{
  if (SendMes(Mnum)) {
    MesX = x;
    MesY = y;
  }
}


void
doMessage(void) 
{
  char messageStr[256];
  short pictId;
  short firstTime;

  messageStr[0] = 0;

  if (MessagePort) {
    MesNum = MessagePort;
    MessagePort = 0;
    LastMesTime = TickCount();
    firstTime = 1;
  } else {
    firstTime = 0;
    if (MesNum == 0)  return;
    if (MesNum < 0) {
      MesNum = -MesNum;
      LastMesTime = TickCount();
    } else if ((TickCount() - LastMesTime) > (60 * 30)) {
      MesNum = 0;
      return;
    }
  }
  if (firstTime) {
    switch ((MesNum < 0) ? -MesNum : MesNum) {
    case  12:
      if (Rand(5) == 1) {
	MakeSound("city", "HonkHonk-Med");
      } else if (Rand(5) == 1) {
	MakeSound("city", "HonkHonk-Low");
      } else if (Rand(5) == 1) {
	MakeSound("city", "HonkHonk-High");
      }
      break;
    case  11:
    case  20:
    case 22:
    case 23:
    case 24:
    case 25:
    case 26:
    case 27:
      MakeSound("city", "Siren");
      break;
    case  21:
      MakeSound("city", "Monster");
      break;
    case 30:
      MakeSound("city", "Explosion-Low");
      MakeSound("city", "Siren");
      break;
    case  43:
      MakeSound("city", "Explosion-High");
      MakeSound("city", "Explosion-Low");
      MakeSound("city", "Siren");
      break;
    case  44:
      MakeSound("city", "Siren");
      break;
    }
  }

  if (MesNum >= 0) {
    if (MesNum == 0)
      return;

    if (MesNum > 60) {
      MesNum = 0;
      return;
    }

    GetIndString(messageStr, 301, MesNum);
    if (MesX || MesY) {
      /* TODO: draw goto button */
    }

    if (autoGo && (MesX || MesY)) {
      DoAutoGoto(MesX, MesY, messageStr);
      MesX = 0;
      MesY = 0;
    } else {
      SetMessageField(messageStr);
    }

  } else { /* picture message */
    pictId = -(MesNum);

    if (pictId < 43)
      GetIndString(messageStr, 301, pictId);
    else
      messageStr[0] = '\0';

    DoShowPicture(pictId);

    MessagePort = pictId; /* resend text message */

    if (autoGo && (MesX || MesY)) {
      
      DoAutoGoto(MesX, MesY, messageStr);
      MesX = 0;
      MesY = 0;
    }
  }
}


void
DoAutoGoto(short x, short y, char *msg)
{
  char buf[256];

  SetMessageField(msg);
  sprintf(buf, "UIAutoGoto %d %d", x, y);
  Eval(buf);
}


void
SetMessageField(char *str)
{
  char buf[256];

  if (!HaveLastMessage ||
      strcmp(LastMessage, str)) {
    strcpy(LastMessage, str);
    HaveLastMessage = 1;
    sprintf(buf, "UISetMessage {%s}", str);
    Eval(buf);
  }
}


void
DoShowPicture(short id)
{
  char buf[256];

  sprintf(buf, "UIShowPicture %d", id);
  Eval(buf);
}


void
DoLoseGame(void)
{
  Eval("UILoseGame");
}


void
DoWinGame(void)
{
  Eval("UIWinGame");
}


