unit Game;
////////////////////////////////////////////////////////////////////////////////
interface
////////////////////////////////////////////////////////////////////////////////
  const
      DMG = 4;
      CROSSDMG = 200;
      RELOAD_DEL = 300;
  var
      //gui control
      menu : boolean;

      //scoreboard
      PlrScor : array [1..4] of integer;

      //tanks
      PlrPosX, PlrPosY, PlrDir, PlrCol, Hlth : array [1..4] of integer;
      PlrExist : array [1..4] of boolean;

      //move
      vX,v,lastDir : array [1..4] of integer;

      //missles
      Mis, MisX, MisY, MisV, MisD : array [1..32] of integer;
      Reload : array [1..4] of boolean;
      LastShot : array [1..4] of integer;

      //kill
      LastBlink,Blinks: array [1..4] of integer;
      PlrDead : array [1..4] of boolean;

      //blink
      BlnkCnt, col : array [1..4] of integer;

      //Spawn
      SpawnPos : integer;
////////////////////////////////////////////////////////////////////////////////
procedure RunGame;
procedure Shoot(Plr:integer);
procedure MovePlayer(i,dir:integer);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
implementation
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
uses  keys;
////////////////////////////////////////////////////////////////////////////////
procedure DrawTank(x,y,dir,color:integer);
begin
  if color = 1 then
  begin
    setColor(0,138,255);
  end;
  if color = 2 then
  begin
    setColor(0,0,0);
  end;
  if color = 3 then
  begin
    setColor(255,0,0);
  end;

  if Dir = 1 then
    begin
      FillRect(X,   Y+4,      4,8);
      FillRect(X+4,     Y,    4,8);
      FillRect(X+8,   Y+4,    4,8);

    end;

  if Dir = 2 then
    begin
      FillRect(X,     Y,      8,4);
      FillRect(X+4,   Y+4,      8,4);
      FillRect(X,   Y+8,    8,4);
    end;

  if Dir = 3 then
    begin
      FillRect(X,     Y,      4,8);
      FillRect(X+4,  Y+4,      4,8);
      FillRect(X+8,     Y,    4,8);
    end;

  if Dir = 4 then
    begin
      FillRect(X+4,   Y,      8,4);
      FillRect(X,  Y+4,      8,4);
      FillRect(X+4,     Y+8,    8,4);
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure Blink(plr:integer);
var i:integer;
begin
if plr = 0 then
  begin
    for i:= 1 to 4 do
    begin
      if BlnkCnt[i] > 0 then
        begin
          if PlrCol[i] = 3 then
            PlrCol[i] := 2
          else
            PlrCol[i] := 3;
          BlnkCnt[i]:=BlnkCnt[i]-1;
        end;
    end;

  end;
else
  begin
    BlnkCnt[plr]:=2;
    PlrCol[plr]:=Col[plr];
  end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure DrawItems;
var i:integer;
begin
  Blink(0);
  for i:=1 to 4 do
    begin
      if PlrExist[i] then
        DrawTank(PlrPosX[i],PlrPosY[i],PlrDir[i],PlrCol[i]);
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure DrawMis;
var i :integer;
begin
  for i:= 1 to 32 do
    begin
      if Mis[i] <> 0 then
        begin
          setColor(255,0,0);
          fillRect(MisX[i],MisY[i],4,4);
        end;
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure DrawLifeBar;
var i:integer;
begin
  for i:=1 to 4 do
  begin
    setColor(255,255,255);
    DrawRect(70-1,245+((i-1)*20),100,10);
    setColor(0,255,120);
    FillRect(70,245+(((i-1)*20)+1), hlth[i]-1 ,5);
    setColor(0,205,100);
    FillRect(70,250+(((i-1)*20)+1), hlth[i]-1 ,4);
  end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure DrawScoreBoard;
var i:integer;
begin
  for i:=1 to 4 do
    begin
      DrawText(IntegerToString(PlrScor[i]),0,245+((i-1)*20));
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure DrawUI;
begin
  setColor(0,50,50);
  fillRect(0,240,240,80);
  DrawLifeBar;
  DrawScoreBoard;
end;
////////////////////////////////////////////////////////////////////////////////
procedure DrawField;
begin
  setColor(230,230,255);
  fillRect(0,0,240,240);
end;
////////////////////////////////////////////////////////////////////////////////
procedure Render;
begin
  DrawField;
  DrawItems;
  DrawMis;
  DrawUI;
  Repaint;
end;
////////////////////////////////////////////////////////////////////////////////
procedure MisMove;
var i : integer;
begin
  for i:= 1 to 32 do
    begin

      if Mis[i] <> 0 then
        begin
          MisV[i]:= MisV[i]+1;
        end;
      if MisV[i] > 16 then
        begin
        MisV[i]:= 16;
        end;

      if Mis[i] <> 0 then
        begin

          if MisD[i] = 1 then
            begin
              MisY[i]:=MisY[i]-MisV[i];
                if MisY[i] < -10 then
                    Mis[i]:=0;
            end;
          if MisD[i] = 2 then
            begin
              MisX[i]:=MisX[i]+MisV[i];
                if MisX[i] > 250 then
                    Mis[i]:=0;
            end;
          if MisD[i] = 3 then
            begin
              MisY[i]:=MisY[i]+MisV[i];
                if MisY[i] > 250 then
                    Mis[i]:=0;
            end;
          if MisD[i] = 4 then
            begin
              MisX[i]:=MisX[i]-MisV[i];
                if MisX[i] < -10 then
                    Mis[i]:=0;
            end;

        end;
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure KillPlr;
var i:integer;
begin
  for i:=1 to 4 do
  begin
    if PlrDead[i] then
    begin
      Hlth[i]:=1;
      if (GetRelativeTimeMs - LastBlink[i]) > 25
        then
          begin
            LastBlink[i]:=GetRelativeTimeMs;
            Blinks[i]:=Blinks[i]+1;
              if Blinks[i] > 15 then
                begin //killing plr
                  PlrDead[i]:=false;
                  PlrExist[i]:=false;
                  PlrPosX[i]:=-50;
                  PlrPosY[i]:=-50;
                end; //------------
            if PlrCol[i] = 3 then
                PlrCol[i] := 2;
            else
                PlrCol[i] := 3;
          end;
    end;
  end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure Respawn;
var i:integer;
begin
  for i:=1 to 4 do
    begin
      if not PlrExist[i] then
        begin
          PlrExist[i] :=true;
          SpawnPos:=SpawnPos+1;
  ĠĠ      if (SpawnPos > 4) or (SpawnPos < 1) then SpawnPos:=1
          if SpawnPos = 1 then
            begin
              PlrPosX[i]          := 0;
              PlrPosY[i]          := 0;
              PlrDir[i]           := 2;
            end;
          if SpawnPos = 2 then
            begin
              PlrPosX[i]          := 240-12;
              PlrPosY[i]          := 0;
              PlrDir[i]           := 3;
            end;
          if SpawnPos = 3 then
            begin
              PlrPosX[i]          := 0;
              PlrPosY[i]          := 240-12;
              PlrDir[i]           := 1;
            end;
          if SpawnPos = 4 then
            begin
              PlrPosX[i]          := 240-12;
              PlrPosY[i]          := 240-12;
              PlrDir[i]           := 4;
            end;

          
          if i = 1 then PlrCol[i]:= 1
            else PlrCol[i]:=2;
          v[1]                :=1;
          Reload[i]           :=true;
          Hlth[i]             :=100;
        end;
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure CheckHlth;
var i:integer;
begin
  for i:=1 to 4 do
    begin
      if Hlth[i] <= 0 then
        begin
          LastBlink[i]:=GetRelativeTimeMs;
          PlrDead[i]:=true;
        end;
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure MisDmg;
var i,c : integer;
begin
  for i:=1 to 32 do
    begin
      if Mis[i] <> 0 then
        begin
          for c:=1 to 4 do
              if (MisX[i] - PlrPosX[c] <= 12) and (MisX[i] - PlrPosX[c] >=-4 ) then
                  if (MisY[i] - PlrPosY[c] <=12) and (MisY[i] - PlrPosY[c] >=-4 ) then
                    begin
                      if (MisV[i] < 10) and (MisV[i] > 5) then
                        begin
                          Hlth[c]:=Hlth[c] - Dmg*2;
                          PlrScor[Mis[i]]:=PlrScor[Mis[i]]+2;
                        end
                      else
                      if MisV[i] < 5 then
                        begin
                          Hlth[c]:=Hlth[c] - Dmg;
                          PlrScor[Mis[i]]:=PlrScor[Mis[i]]+1;
                        end
                      else
                        begin
                          Hlth[c]:=Hlth[c] - Dmg*3;
                          PlrScor[Mis[i]]:=PlrScor[Mis[i]]+3;
                        end;
                      Blink(c);
                      Mis[i]:=0;
                    end;
        end;
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure ReloadTmr;
var i:integer;
begin
  for i:=1 to 4 do
    begin
      if (GetRelativeTimeMs - LastShot[i]) > RELOAD_DEL
        then
          Reload[i] := true;
    end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure Shoot(Plr:integer);
var i : integer;
begin
  if (Reload[Plr]) and not (PlrDead[Plr]) then
  begin

  for i:=1 to 32 do
    begin
      if Mis[i] = 0 then
        begin
          if PlrDir[plr] = 1 then
            begin
              Mis[i]:=Plr;
              MisX[i]:= PlrPosX[plr] + 4;
              MisY[i]:= PlrPosY[plr] - 4;
              MisD[i]:= 1;
              MisV[i]:= 1;
            end;
          if PlrDir[plr] = 2 then
            begin
              Mis[i]:=Plr;
              MisX[i]:= PlrPosX[plr] + 12;
              MisY[i]:= PlrPosY[plr] + 4;
              MisD[i]:= 2;
              MisV[i]:= 1;
            end;
          if PlrDir[plr] = 3 then
            begin
              Mis[i]:=Plr;
              MisX[i]:= PlrPosX[plr] + 4;
              MisY[i]:= PlrPosY[plr] + 12;
              MisD[i]:= 3;
              MisV[i]:= 1;
            end;
          if PlrDir[plr] = 4 then
            begin
              Mis[i]:=Plr;
              MisX[i]:= PlrPosX[plr] - 4;
              MisY[i]:= PlrPosY[plr] + 4;
              MisD[i]:= 4;
              MisV[i]:= 1;
            end;
          Reload[plr]:=false;
          LastShot[plr]:=GetRelativeTimeMs;
          Break;
        end;
    end;
  end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure checkborders;
var i,c:integer;
begin
  for i:=1 to 4 do
  begin
    if PlrExist[i] then
    begin
      if PlrPosX[i] < 0
        then PlrPosX[i] := 0;
      if PlrPosX[i]+12 > 240
        then PlrPosX[i] := 240-12;
      if PlrPosY[i] < 0
        then PlrPosY[i] := 0;
      if PlrPosY[i]+12 > 240
        then PlrPosY[i] := 240-12;

      //check if players cross each other
      for c:=1 to 4 do
      begin

        if (c <> i) then
        begin

          if (PlrPosX[i] - PlrPosX[c] <= 12) and (PlrPosX[i] - PlrPosX[c] >=-12 ) then
            if (PlrPosY[i] - PlrPosY[c] <=12) and (PlrPosY[i] - PlrPosY[c] >=-12 ) then
              begin
                Hlth[i]:=Hlth[i]-CrossDmg;
              end;
        end;

      end;

    end;
  end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure MovePlayer(i,dir:integer);
begin
  if not PlrDead[i] then
  begin
    if dir = lastDir[i]
     then
       vX[i]:=vX[i]+1;
     else
       begin
         vX[i]:=1;
         v[i]:=1;
       end;

    if vX[i] > 8
   then
     begin
       v[i]:=v[i]+1;
       vX[i]:=1;
     end;

    if v[i] > 3 then v[i]:=3;

    lastdir[i]:=dir;

    if dir = 1 then
      begin
        PlrPosY[i]:=PlrPosY[i]-V[i];
        PlrDir[i]:=1;
      end;
    if dir = 2 then
      begin
        PlrPosX[i]:=PlrPosX[i]+V[i];
        PlrDir[i]:=2;
      end;
    if dir = 3 then
      begin
        PlrPosY[i]:=PlrPosY[i]+V[i];
        PlrDir[i]:=3;
      end;
    if dir = 4 then
      begin
        PlrPosX[i]:=PlrPosX[i]-V[i];
        PlrDir[i]:=4;
      end;
    end;
    CheckBorders;
end;
////////////////////////////////////////////////////////////////////////////////
procedure RunGame;
var keys:integer;
    fire,up,right,down,left:boolean;
begin
  //////////////////////////////////////
    keys:=get_key_states;
    fillrect(0,0,getwidth,getheight);
    if keys and 256 <> 0 //fire
      then fire:=true;
      else fire:=false;
    if keys and 2   <> 0 //up
      then up:=true;
      else up:=false;
    if keys and 32  <> 0 //right
      then right:=true;
      else right:=false;
    if keys and 64  <> 0 //down
      then down:=true;
      else down:=false;
    if keys and 4   <> 0 //left
      then left:=true;
      else left:=false;
    if getKeyClicked = KE_KEY0 //* or # or 0
      then menu:=true;
      else menu:=false;
  //////////////////////////////////////
    if (up)     and not (right) and not (down) and not (left) then MovePlayer(1,1);
    if (right)  and not (up) and not (down) and not (left) then MovePlayer(1,2);
    if (down)   and not (right) and not (up) and not (left) then MovePlayer(1,3);
    if (left)   and not (right) and not (down) and not (up) then MovePlayer(1,4);
    if (fire) then Shoot(1);

    MisMove;
    PlrCol[1]:=1;
    MisDmg;
    KillPlr;
    CheckHlth;
    ReloadTmr;
    Respawn;
    render;
end;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
end.
