Malay Keshav

Download Resume PDF

Malay Keshav

Netaji Subhas Institute of Technology

Hedgewars - Open Source

Hedgewars is an Open Source turn based strategy, artillery, action and comedy game, featuring the antics of pink hedgehogs with attitude as they battle from the depths of hell to the depths of space.

I developed a patch for the AI of weapon “Cake Bomb” and proposed several other improvements to different weapons.

The patch can be found here :

diff -r ab9843957664 hedgewars/GSHandlers.inc
--- a/hedgewars/GSHandlers.inc	Sun Apr 15 00:47:22 2012 +0400
+++ b/hedgewars/GSHandlers.inc	Thu Apr 19 09:17:04 2012 -0700
@@ -3093,7 +3093,7 @@
     if Gear^.Health mod 100 = 0 then
         Gear^.PortalCounter:= 0;
     // This is not seconds, but at least it is *some* feedback
-    if (Gear^.Health = 0) or ((Gear^.Message and gmAttack) <> 0) then
+    if (Gear^.Health <= 0) or ((Gear^.Message and gmAttack) <> 0) then
         begin
         FollowGear := Gear;
         Gear^.RenderTimer := false;
@@ -5420,3 +5420,4 @@

 ////////////////////////////////////////////////////////////////////////////////

+
diff -r ab9843957664 hedgewars/uAI.pas
--- a/hedgewars/uAI.pas	Sun Apr 15 00:47:22 2012 +0400
+++ b/hedgewars/uAI.pas	Thu Apr 19 09:17:04 2012 -0700
@@ -136,6 +136,7 @@
             if Actions.Score + Score > BestActions.Score then
                 if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel) * 2048) then
                     begin
+                    if(a=gmCake) then SetTargetForGearToTrace(ap.ExplX, ap.Exply);
                     BestActions:= Actions;
                     inc(BestActions.Score, Score);
                     BestActions.isWalkingToABetterPlace:= false;
@@ -374,6 +375,9 @@

 procedure StartThink(Me: PGear);
 begin
+if not(GearToTraceIsNil) then 
+    if TraceGearHasReachedTarget then
+         GearToTraceExplosion; // This can be customized to send the required doStep procedure as argument //  
 if ((Me^.State and (gstAttacking or gstHHJumping or gstMoving)) <> 0)
 or isInMultiShoot then
     exit;
@@ -438,6 +442,7 @@

 procedure initModule;
 begin
+    SetGearToTraceToNil;
     hasThread:= 0;
     ThinkThread:= ThinkThread;
 end;
diff -r ab9843957664 hedgewars/uAIActions.pas
--- a/hedgewars/uAIActions.pas	Sun Apr 15 00:47:22 2012 +0400
+++ b/hedgewars/uAIActions.pas	Thu Apr 19 09:17:04 2012 -0700
@@ -20,7 +20,7 @@

 unit uAIActions;
 interface
-uses uFloat, uTypes;
+uses uFloat, uTypes, SDLH, uConsts;

 const MAXACTIONS     = 96;
     aia_none       = 0;
@@ -63,9 +63,66 @@

 procedure AddAction(var Actions: TActions; Action: Longword; Param: LongInt; TimeDelta: Longword; X, Y: LongInt);
 procedure ProcessAction(var Actions: TActions; Me: PGear);
+procedure SetGearToTrace(var newGear: PGear);
+procedure SetGearToTraceToNil;
+procedure DisplayLocationGearToTrace;
+procedure SetTargetForGearToTrace(var EX,EY :LongInt);
+procedure GearToTraceExplosion;
+function GearToTraceIsNil: boolean;
+function TraceGearHasReachedTarget: boolean;
+

 implementation
-uses uAIMisc, uAI, uAmmos, uVariables, uCommands, uUtils, uDebug, uIO{$IFDEF TRACEAIACTIONS}, uConsole{$ENDIF};
+uses uAIMisc, uAI, uAmmos, uVariables, uCommands, uUtils, uDebug, uIO {$IFDEF TRACEAIACTIONS}, uConsole{$ENDIF};
+
+var GearToTrace: PGear;
+    GTarget  : TPoint;
+    
+
+procedure SetTargetForGearToTrace(var EX,EY :LongInt);
+begin
+GTarget.X := EX;
+GTarget.Y := EY;
+//WriteLn('Target SET at X :: ' + IntToStr(GTarget.X) + ' Y :: ' + IntToStr(GTarget.Y) );
+end;
+
+procedure SetGearToTrace(var newGear : PGear);
+begin
+//WriteLn('Gear Added To trace Variable');
+if GearToTrace = nil then new(GearToTrace);
+GearToTrace := newGear;
+end;
+
+procedure GearToTraceExplosion;
+begin
+GearToTrace^.Message := gmAttack;
+GearToTrace^.Health := 0;
+end;
+
+procedure SetGearToTraceToNil;
+begin
+//WriteLn('Gear Set To Nil');
+GearToTrace := nil;
+end;
+
+procedure DisplayLocationGearToTrace;
+begin
+writeLn(' x = ' + IntToStr(trunc(hwFloat2Float(GearToTrace^.X))) + ' y = ' + IntToStr(trunc(hwFloat2Float(GearToTrace^.Y))));
+end;
+
+function GearToTraceIsNil: boolean;
+begin
+if GearToTrace = nil then exit(true) else exit(false);
+end;
+
+function TraceGearHasReachedTarget: boolean;
+begin
+//WriteLn('Target Distance X = ' + IntToStr(abs(trunc(hwFloat2Float(GearToTrace^.X)) - GTarget.X)) + ' Target Distance Y : ' + IntToStr(abs(trunc(hwFloat2Float(GearToTrace^.Y)) - GTarget.Y)) + 'dx = ' + IntToStr(trunc(hwFloat2Float(GearToTrace^.dX))) + ' My angle = ' + IntToStr(GearToTrace^.Angle));
+if ((abs(trunc(hwFloat2Float(GearToTrace^.X)) - GTarget.X) < 10) and  (abs(trunc(hwFloat2Float(GearToTrace^.Y)) - GTarget.Y) <10)) then 
+   exit(true)
+else
+    exit(false)
+end;

 const ActionIdToStr: array[0..7] of string[16] = (
 {aia_none}           '',
@@ -146,7 +205,9 @@

 procedure ProcessAction(var Actions: TActions; Me: PGear);
 var s: shortstring;
+    EX :LongInt;
 begin
+//WriteLnToConsole(' Whats the Health ? = '+ IntToStr(Me^.Health));
 repeat
 if Actions.Pos >= Actions.Count then exit;
 with Actions.actions[Actions.Pos] do
diff -r ab9843957664 hedgewars/uAIAmmoTests.pas
--- a/hedgewars/uAIAmmoTests.pas	Sun Apr 15 00:47:22 2012 +0400
+++ b/hedgewars/uAIAmmoTests.pas	Thu Apr 19 09:17:04 2012 -0700
@@ -46,6 +46,8 @@
 function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;

+function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+
 type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
     TAmmoTest = record
             proc: TAmmoTestProc;
@@ -79,7 +81,7 @@
             (proc: nil;              flags: 0), // amSwitch
             (proc: @TestMortar;      flags: 0), // amMortar
             (proc: nil;              flags: 0), // amKamikaze
-            (proc: nil;              flags: 0), // amCake
+            (proc: @TestCake;        flags: 0), // amCake  // Added! //
             (proc: nil;              flags: 0), // amSeduction
             (proc: @TestWatermelon;  flags: 0), // amWatermelon
             (proc: nil;              flags: 0), // amHellishBomb
@@ -115,7 +117,7 @@
 const BadTurn = Low(LongInt) div 4;

 implementation
-uses uAIMisc, uVariables, uUtils;
+uses uAIMisc, uVariables, uUtils, uConsole, uCollisions;

 function Metric(x1, y1, x2, y2: LongInt): LongInt; inline;
 begin
@@ -349,9 +351,9 @@
     x, y, dY, meX, meY: real;
     t: LongInt;
 begin
+ap.ExplR:= 0;
 valueResult:= BadTurn;
 TestTime:= 0;
-ap.ExplR:= 0;
 meX:= hwFloat2Float(Me^.X);
 meY:= hwFloat2Float(Me^.Y);
 repeat
@@ -533,6 +536,164 @@
 TestMortar:= valueResult;
 end;

+
+
+function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+const 
+    dirs: array[0..3] of TPoint =   ((x: 0; y: -1), (x: 1; y: 0),(x: 0; y: 1),(x: -1; y: 0));
+    cakeh =   27;
+    cakeDmg =   75;
+var 
+    FName, Txt : String[10];
+    UserFile   : Text; 
+    Gear : PGear;
+    doStep : integer;
+    xx, yy, xxn, yyn: LongInt;
+    EX, EY, DY: LongInt;
+    dA: LongInt;
+    tdx, tdy: hwFloat;
+    flag : integer;
+    i: Longword;
+    CakePoints: array[0..Pred(cakeh)] of record
+        x, y: hwFloat;
+    end;
+    CakeI: Longword;
+    retValue: LongInt;
+begin
+new(Gear);
+ap.Time:= 0;
+ap.ExplR:= 0;
+Gear^.Active         := true;
+TestCake:= BadTurn;
+Gear^.Angle:= 1;
+flag :=0;
+// Adapted from GSHandlers.inc //
+while Gear^.Angle <= 3 do
+begin
+    Gear^.X              := Me^.X;
+    Gear^.Y              := Me^.Y;
+    Gear^.Tag            := Me^.Tag;
+    Gear^.PortalCounter  := Me^.PortalCounter;
+    Gear^.dX             := Me^.dX;
+    Gear^.dY             := Me^.dY;
+    Gear^.Tag            := Me^.Tag;
+    Gear^.Pos            := Me^.Pos;
+    Gear^.IntersectGear  := Me^.IntersectGear;
+    Gear^.IntersectGear  := nil;
+    Gear^.Health:= 2048;
+    Gear^.Radius:= 7;
+    Gear^.Z:= cOnHHZ;
+    Gear^.DirAngle:= -90 * hwSign(Gear^.dX);
+    while flag =0 do
+    begin
+        EX := trunc(hwFloat2Float(Gear^.X));
+        EY := trunc(hwFloat2Float(Gear^.Y));
+        DY := trunc(hwFloat2Float(Gear^.dY));
+        Gear^.dY := Gear^.dY + cGravity;
+        if TestCollisionYwithGear(Gear, 1) <> 0 then
+            flag :=1
+        else
+            begin
+            Gear^.Y := Gear^.Y + Gear^.dY;
+            end
+    end;
+    flag :=0;
+    while flag =0 do
+    begin
+    inc(Gear^.Tag);
+        if Gear^.Tag < 100 then
+            flag :=2;
+        Gear^.Tag := 0;
+        if Gear^.Pos = 6 then
+            begin
+            for i:= 0 to Pred(cakeh) do
+                begin
+                CakePoints[i].x := Gear^.X;
+                CakePoints[i].y := Gear^.Y
+                end;
+            CakeI := 0;
+            flag :=1;
+            end
+        else
+            inc(Gear^.Pos)
+    end;
+    EX := trunc(hwFloat2Float(Gear^.X));
+    EY := trunc(hwFloat2Float(Gear^.Y));
+    while (Gear^.Health > 0) do
+    begin
+        dA := hwSign(Gear^.dX);
+        xx := dirs[Gear^.Angle].x;
+        yy := dirs[Gear^.Angle].y;
+        xxn := dirs[(LongInt(Gear^.Angle) + 4 + dA) mod 4].x;
+        yyn := dirs[(LongInt(Gear^.Angle) + 4 + dA) mod 4].y;
+        inc(Gear^.Tag);
+        dec(Gear^.Health);
+        if (xx = 0) then
+            if TestCollisionYwithGear(Gear, yy) <> 0 then
+                Gear^.Angle := (LongInt(Gear^.Angle) + 4 - dA) mod 4
+        else
+            begin
+            Gear^.Tag := 0;
+            Gear^.Y := Gear^.Y + int2hwFloat(yy);
+            if not TestCollisionXwithGear(Gear, xxn) then
+                begin
+                Gear^.X := Gear^.X + int2hwFloat(xxn);
+                Gear^.Angle := (LongInt(Gear^.Angle) + 4 + dA) mod 4
+                end;
+            end;
+        if (yy = 0) then
+            if TestCollisionXwithGear(Gear, xx) then
+                Gear^.Angle := (LongInt(Gear^.Angle) + 4 - dA) mod 4
+        else
+            begin
+            Gear^.Tag := 0;
+            Gear^.X := Gear^.X + int2hwFloat(xx);
+            if not TestCollisionY(Gear, yyn) then
+                begin
+                Gear^.Y := Gear^.Y + int2hwFloat(yyn);
+                Gear^.Angle := (LongInt(Gear^.Angle) + 4 + dA) mod 4
+                end;
+            end;
+        
+         if Gear^.Tag = 0 then
+            begin
+            CakeI := (CakeI + 1) mod cakeh;
+            tdx := CakePoints[CakeI].x - Gear^.X;
+            tdy := - CakePoints[CakeI].y + Gear^.Y;
+            CakePoints[CakeI].x := Gear^.X;
+            CakePoints[CakeI].y := Gear^.Y;
+            Gear^.DirAngle := DxDy2Angle(tdx, tdy);
+            end;
+            
+        Gear^.Timer := Gear^.Health*10;
+        if Gear^.Health mod 100 = 0 then
+            Gear^.PortalCounter:= 0;
+            
+        EX := trunc(hwFloat2Float(Gear^.X));
+        EY := trunc(hwFloat2Float(Gear^.Y));
+        
+        if((abs(EX-Targ.X) < 100) and (abs(EY - Targ.Y) < 100)) then 
+        begin
+            retValue := RateExplosion(Me, EX, EY, 101);
+            if (retValue > TestCake ) then 
+            begin
+            
+                TestCake := retValue;
+                ap.Angle:= Gear^.Angle - 2;
+                ap.Power:= 10;
+                ap.ExplR:= 100;
+                ap.ExplX:= EX;
+                ap.ExplY:= EY;
+                
+            end;
+         end;   
+    end;    
+    Gear^.Angle := Gear^.Angle + 2;
+    end;
+dispose( Gear );
+end;
+
+
 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 const
     MIN_RANGE =  80;