Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Sprite Editor for .NET

, 27 Jan 2010
Build, edit, and animate your own sprites.
classSprite_C_2008.zip
classSprite
classSprite
classSprite.csproj.user
bin
Release
classSprite.dll
Properties
GraphicsEditor_C_2008.zip
GraphicsEditor CSharp
GraphicsEditor CSharp
graphics editor icon.ico
GraphicsEditor CSharp.csproj.user
Properties
Settings.settings
Resources
Brush_Icon.bmp
click to load image.bmp
colorTemplate.bmp
cursor_cross.bmp
cursor_move.bmp
cursor_resizeDiagonal_BL_TR.bmp
cursor_resizeDiagonal_TL_BR.bmp
cursor_resizeLeftRight.bmp
cursor_resizeUpDown.bmp
Edit_Redo_Icon.bmp
Edit_Undo_Icon.bmp
Eraser_Icon.bmp
FloodFill_Icon.bmp
FloodFill_pnlBackground_sameColor.bmp
FloodFill_pnlBackground_toBorder.bmp
Free-Form Select_Icon.bmp
Gun.bmp
Line_Icon.bmp
Magnify_Icon.bmp
Pencil_Icon.bmp
Pick-color_Icon.bmp
Select_Icon.bmp
sprite Editor.jpg
Straighten_Icon.bmp
Night_Stalker__C_2008.zip
Night Stalker
Night Stalker
Night Stalker.csproj.user
nightstalker.ico
Properties
Settings.settings
Resources
bomb.wav
bulletEaten.wav
BulletEater.spr
bulletEater.wav
bunker.png
bunkerbuster.spr
BunkerBuster.wav
CDbunkerWalls.bmp
Colt Round.png
Colt.spr
colt45.wav
corpse (small).spr
diescream.wav
emptychamber.wav
Evil Jessica (small).spr
Felix the Cat (small).spr
FelixFire.spr
FelixFire.wav
freeLife.wav
gun.png
gun.spr
heartbeat.wav
help_background.jpg
hithard.wav
Jessica Rabbit Small.spr
largeJessica.spr
Laser.spr
laserFire.wav
loadclip.wav
Map WPs.png
Map.jpg
MapCD.bmp
mini bat.spr
NearestWayPointsTable.bfs
nightstalker.bmp
nightstalker.png
red bunker.png
Robot Den New.png
Robot_A.spr
smurf (small).spr
smurf-attack.spr
spider (small).spr
Spider Web.png
splat.wav
WayPointsArray.bfs
WayPointsTable.bfs
Sprites.zip
Sprites
Robot1.bmp
Robot2.bmp
robot3.bmp
Bat
bat.spr
head.bmp
head.jpg
leftwing.bmp
mini bat.spr
wing.bmp
Bullets
bulletEater original.png
bulletEater.bmp
BulletEater.spr
bunkerbuster.bmp
bunkerbuster.spr
Colt.bmp
Colt.spr
Laser.bmp
Laser.spr
master limb.bmp
smurf-attack.bmp
smurf-attack.spr
Claudia Schiffer
alt.spr
Claudia.spr
Claudia_Arm.bmp
Claudia_Foot.bmp
Claudia_Forearm.bmp
Claudia_Hand_Left.bmp
Claudia_Hand_Right.bmp
Claudia_head.bmp
Claudia_head2.bmp
Claudia_mini.spr
Claudia_Schiffer_1.jpg
Claudia_Shin.bmp
Claudia_Thigh.bmp
Claudia_Torso.bmp
gunHand.bmp
Corpse
blood.bmp
corpse (small).spr
Corpse.spr
guts.bmp
master limb.bmp
robot.png
smurfcorpse.png
Evil Jessica
Evil Jessica (small).spr
Evil Jessica.spr
GunHand(near).bmp
JR_Arm.bmp
JR_Arm.png
JR_Dress.bmp
JR_Dress_resized.bmp
JR_Foot.bmp
JR_Forearm.bmp
JR_Hair(far).bmp
JR_Hair(near).bmp
JR_Hand.bmp
JR_Hand_Right.bmp
JR_Head.bmp
JR_MasterBlock.bmp
JR_Shin.bmp
JR_Thigh_far.bmp
JR_Thigh_near.bmp
JR_Torso.bmp
gun
gun.bmp
gun.spr
master block.bmp
Jessica Rabbit
GunHand(near).bmp
Jessica Rabbit Small.spr
Jessica Rabbit.spr
jessica_rabbit at mic.jpg
JR_Arm.bmp
JR_Dress.bmp
JR_Dress_resized.bmp
JR_Foot.bmp
JR_Forearm.bmp
JR_Hair(far).bmp
JR_Hair(near).bmp
JR_Hand.bmp
JR_Hand_Right.bmp
JR_Head.bmp
JR_MasterBlock.bmp
JR_Shin.bmp
JR_Thigh_far.bmp
JR_Thigh_near.bmp
JR_Torso.bmp
Lindsay Lohan
arm.bmp
foot.bmp
forearm.bmp
gunHand.bmp
Hand_Left.bmp
head.bmp
Lindsay Lohan.spr
Mini Lindsay Lohan.spr
shin.bmp
skirt_ass.bmp
skirt_front.bmp
thigh.bmp
torso.bmp
NightStalkerSprites
BulletEater.spr
bunkerbuster.spr
Colt.spr
corpse (small).spr
Evil Jessica (small).spr
gun.spr
Jessica Rabbit Small.spr
Laser.spr
mini bat.spr
Mini Lindsay Lohan.spr
Robot_A.spr
smurf (small).spr
smurf-attack.spr
spider (small).spr
Robot Heart
RobotHeart_Head.bmp
RobotHeart_Torso.bmp
Robot_EyeShut.bmp
ROBOT_heart.bmp
Robot_Heart.spr
Robot_Heart_small.spr
Robot_LeftArm.bmp
Robot_Leg.bmp
Robot_dumb
Arm.bmp
Arm_right_front.bmp
Hand.bmp
Head.bmp
head_back.bmp
Head_Front.bmp
Leg.bmp
leg_back.bmp
leg_front.bmp
Robot_A.spr
Robot_A_original.spr
Robot_A_original_copy.spr
Torso.bmp
Torso_Front.bmp
Smurf
arm(far).bmp
arm(near).bmp
head.bmp
leg.bmp
smurf (small).spr
smurf.spr
Torso.bmp
spider
body.bmp
eyes shut.bmp
head.bmp
legA_left.bmp
legA_right.bmp
legB_left.bmp
legB_right.bmp
LegC_left.bmp
legC_right.bmp
legD_left.bmp
legD_right.bmp
mandible_left.bmp
mandible_right.bmp
spider (small).spr
spider 2.spr
spider.png
spider.spr
sprite_Demo_C_2008.zip
Sprite demo
Sprite demo
Sprite demo.csproj.user
bin
Release
Sprite demo.exe
Properties
Settings.settings
Resources
cartoon grass.jpg
smurf (small).spr
sprite_Editor_C_2008.zip
Sprite Editor
Sprite Editor
Sprite Editor.csproj.user
sprite Editor.ico
bin
Release
cLibPicBoxViewer.dll
Sprite Editor.exe
Properties
Settings.settings
Resources
click to load image.bmp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Sprite;

namespace Night_Stalker
{
    public class classRobot
    {
        static int intUniqueIDCounter = 0;
        int myUniqueIdNumber = intUniqueIDCounter++;
        enuMirror mirror = enuMirror.none;
        bool bolJessicaIsInHerBunker;

        public enum enuRobot_Bat_Configurations
        {
            fly,
            grow,
            _numCon
        }

        public enum enuRobot_Gray_Configurations
        {
            Walk_Right,
            Walk_Down,
            Walk_Up,
            _numCon
        }

        public enum enuRobot_Blue_Configurations
        {
            walk,
            _numCon
        }

        public enum enuRobot_White_Configurations
        {
            Walk_right,
            shoot_up,
            shoot_high,
            shoot_straight,
            shoot_low,
            shoot_down,
            _numCon
        }

        public enum enuRobot_Black_Configurations
        {
            Walk_Right,
            Shoot_Straight,
            Shoot_High,
            Shoot_Low,
            Shoot_Up,
            Shoot_Down,
            standStill,
            Stand_flick_far_hair,
            Stand_hold_gun_up,
            Stand_flick_near_hair_with_gun,
            Stand_fix_far_shoe,
            Stand_fix_near_shoe,
            Stand_scratch_far_calf_with_gun,
            stand_scratch_head,
            stand_swipe_near_arm_with_far_hand,
            go_to_sleep,
            wake_up,
            _numCon
        }

        public enum enuSpider_Configurations
        {
            walk,
            rest,
            prepare_to_attack,
            _numCon
        }

        public enum enuSpiderMode { normal, rest, prepareToAttack, Attack }
        enuSpiderMode spiderMode = enuSpiderMode.normal;
        int intSpiderFed = 0;
        udtShortestPathToWayPoint udrShortestPathToWP_BatStartup; 

        public int intConfigID = 0;
        public int intConfigStep = 0;

        public enum enuRobotID {Primary, Secondary_A, Secondary_B, Spider }
        public enum enuRobotType
        {
            bat,
            gray,
            Smurf,
            Felix,
            evilJessica,
            invisibleJessica,
            spider
        }
        public enuRobotID myLetterID = enuRobotID.Primary;
    
        public classCollisionDetection.udtCDInfo udrCDInfo;

        public struct udtMove
        {
            public string strPath;
            public classWayPoint WPfrom;
            public classWayPoint WPnext;
            public classWayPoint WPtarget;
            public Point lastKnownJessicaLoc;
            public enuDir dir;
        }

        public Point loc;
        public udtMove udrMove;

        classWayPointPaths cLibWPs;
        classCollisionDetection cLibCD;
        classHelperFunctions cLibHelper;
        public classJessica Jessica;
        classBullet bullet;
        int intHP = 100;
        public enuRobotType myType, myType_old;
        const string strRobotBat = "bat.spr";
        const string strRobotGray = "robot_A.spr";
        const string strRobotBlue = "claudia_mini.spr";
        const string strRobotWhite = "mini Lindsay Lohan.spr";

        public static Sprite.classSprite[] sprites;
        classBullet.bulletType myBulletType;

        bool bolICanSeeJessica;
        public bool bolDead = true;
        int intStepsPerTurn = 10;
        public int intBatGrowStep = 0;
        int intVisibleCounter = 0;

        bool bolShootJessica = false;
        double dblAngleShootJessica;
        double dblAngleDraw = 0;
        Point ptLocIWasAtWhenILastFired;
        Microsoft.DirectX.AudioVideoPlayback.Audio DXGun;
        Microsoft.DirectX.AudioVideoPlayback.Audio DXDieScream;

        public classRobot(enuRobotID ID,
                          ref classWayPointPaths cLibWayPointsPaths,
                          ref classCollisionDetection cLibCollisionDetection,
                          ref classJessica Jessica_,
                          ref classHelperFunctions Helper)
        {   cLibWPs = cLibWayPointsPaths;
            cLibCD = cLibCollisionDetection;
            cLibHelper = Helper;
            
            myType_old = enuRobotType.invisibleJessica; // at initialization first robots will not be like 'old type'

            Jessica = Jessica_;
            myLetterID = ID;
            reset();
            setMyType();
            setStepsPerTurn();
            setBullet();
            setCDInfo();
            setHP();
            setBullet();
            
        }

        void setBullet()
        {
            switch (myType)
            {
                case enuRobotType.gray:
                    myBulletType = classBullet.bulletType.laser;
                    break;
                
                case enuRobotType.Smurf:
                    myBulletType = classBullet.bulletType.SmurfAttack;
                    break;

                case enuRobotType.Felix:
                    myBulletType = classBullet.bulletType.FelixFire;
                    break;
                
                case enuRobotType.invisibleJessica:
                case enuRobotType.evilJessica:
                    if (Jessica.intScore > 50000)
                        myBulletType = classBullet.bulletType.bunkerBuster;
                    else
                        myBulletType = classBullet.bulletType.bulletEater;
                    break;
            }
        }

        void setDX()
        {
            string strDir = cLibHelper.getResourceDirectoryString();
            if (myType == myType_old)
                return;

            switch (myType)
            {
                case enuRobotType.spider:
                case enuRobotType.bat:
                    DXGun = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_LaserFire);// has no gun
                    DXDieScream = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_Splat);
                    break;

                case enuRobotType.gray:
                    DXGun = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_LaserFire);
                    DXDieScream = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_bomb);
                    break;

                case enuRobotType.Smurf:                    
                    DXGun = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_LaserFire);
                    DXDieScream = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_dieScream);
                    break;

                case enuRobotType.Felix:
                    DXGun = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_FelixFire);
                    DXDieScream = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_dieScream);
                    break;

                case enuRobotType.evilJessica:
                case enuRobotType.invisibleJessica:
                    if (Jessica.intScore < 50000)
                        DXGun = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_BulletEater);
                    else
                        DXGun = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_BunkerBuster);

                    DXDieScream = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_dieScream);
                    break;
            }
        }

        void setHP()
        {
            switch (myType)
            {
                case enuRobotType.spider:
                case enuRobotType.Smurf:
                case enuRobotType.bat:
                case enuRobotType.gray:
                    intHP = 25;
                    break;

                case enuRobotType.Felix:
                    intHP = 75;
                    break;

                case enuRobotType.evilJessica:
                    intHP = 75;
                    break;

                case enuRobotType.invisibleJessica:
                    intHP = 75;
                    break;
            }
        }

        void setMyType()
        {
            switch (myLetterID)
            {
                case enuRobotID.Primary:
                    if (Jessica.intScore <= 5000)
                        myType = enuRobotType.gray;
                    else if (Jessica.intScore <= 15000)
                        myType = enuRobotType.Smurf;
                    else if (Jessica.intScore <= 30000)
                        myType = enuRobotType.Felix;
                    else if (Jessica.intScore <= 80000)
                        myType = enuRobotType.evilJessica;
                    else
                        myType = enuRobotType.invisibleJessica;
                    break;

                case enuRobotID.Secondary_A :
                    if (Jessica.intScore <= 5000)
                        myType = enuRobotType.bat;
                    else if (Jessica.intScore < 80000)
                        myType = enuRobotType.gray;
                    else if (Jessica.intScore <= 150000)
                        myType = enuRobotType.Smurf;
                    else if (Jessica.intScore < 2000000)
                        myType = enuRobotType.Felix;
                    break;

                case enuRobotID.Secondary_B:
                    if (Jessica.intScore <= 5000)
                        myType = enuRobotType.bat;
                    else if (Jessica.intScore < 150000)
                        myType = enuRobotType.gray;
                    else if (Jessica.intScore <= 200000)
                        myType = enuRobotType.Smurf;
                    else if (Jessica.intScore < 250000)
                        myType = enuRobotType.Felix;
                    break;

                case enuRobotID.Spider:
                    myType = enuRobotType.spider;
                    break;
            }
        }

        void setCDInfo()
        {
            switch (myType)
            {
                case  enuRobotType.gray:
                    udrCDInfo.ptRelPos = new Point(3, 7);
                    udrCDInfo.sz = new Size(5, 14);
                    break;

                case  enuRobotType.Smurf :
                    udrCDInfo.ptRelPos = new Point(3, 8);
                    udrCDInfo.sz = new Size(5, 14);
                    break;

                case enuRobotType.spider:
                    udrCDInfo.ptRelPos = new Point(4, 4);
                    udrCDInfo.sz = new Size(8, 10);
                    break;

                case enuRobotType.evilJessica:
                case enuRobotType.invisibleJessica:
                    udrCDInfo.ptRelPos = new Point(3, 5);
                    udrCDInfo.sz = new Size(5, 14);
                    break;

                case enuRobotType.Felix:
                    udrCDInfo.ptRelPos = new Point(3, 7);
                    udrCDInfo.sz = new Size(6, 12);
                    break;

                case  enuRobotType.bat:
                    switch (intConfigStep)
                    {
                        case 0:
                            udrCDInfo.ptRelPos = new Point(8, 3);
                            udrCDInfo.sz = new Size(16, 4);
                            break;

                        case 1:
                            udrCDInfo.ptRelPos = new Point(9, 3);
                            udrCDInfo.sz = new Size(17, 4);
                            break;

                        case 2:
                            udrCDInfo.ptRelPos = new Point(9, 2);
                            udrCDInfo.sz = new Size(17, 3);
                            break;

                        case 3:
                            udrCDInfo.ptRelPos = new Point(9, 1);
                            udrCDInfo.sz = new Size(18, 3);
                            break;

                        case 4:
                            udrCDInfo.ptRelPos = new Point(8, 1);
                            udrCDInfo.sz = new Size(16, 5);
                            break;

                        case 5:
                            udrCDInfo.ptRelPos = new Point(6, 1);
                            udrCDInfo.sz = new Size(12, 7);
                            break;

                        case 6:
                            udrCDInfo.ptRelPos = new Point(2, 1);
                            udrCDInfo.sz = new Size(4, 9);
                            break;

                        case 7:
                            udrCDInfo.ptRelPos = new Point(4, 1);
                            udrCDInfo.sz = new Size(8, 7);
                            break;

                        case 8:
                            udrCDInfo.ptRelPos = new Point(5, 1);
                            udrCDInfo.sz = new Size(10, 6);
                            break;

                        case 9:
                            udrCDInfo.ptRelPos = new Point(5, 2);
                            udrCDInfo.sz = new Size(10, 6);
                            break;

                        case 10:
                            udrCDInfo.ptRelPos = new Point(5, 3);
                            udrCDInfo.sz = new Size(11, 6);
                            break;
                    }
                    break;
            }
        }

        public void Hit(int intDamage)
        {
            intHP -= intDamage;
            intVisibleCounter = 15;
            if (intHP <= 0)
                die();
        }

        void die()
        {
            bolDead = true;
            cLibHelper.playSound(DXDieScream);
            switch (myType)
            {
                case enuRobotType.Smurf:
                    cLibHelper.newCorpse(loc, classCorpse.enuCorpseType.Smurf);
                    break;

                case enuRobotType.Felix:
                    cLibHelper.newCorpse(loc, classCorpse.enuCorpseType.Felix);
                    break;

                case enuRobotType.evilJessica:
                case enuRobotType.invisibleJessica:
                    cLibHelper.newCorpse(loc, classCorpse.enuCorpseType.human);
                    break;

                case enuRobotType.gray:
                    cLibHelper.newCorpse(loc, classCorpse.enuCorpseType.robot);
                    break;

                case enuRobotType.bat:
                    cLibHelper.newCorpse(loc, classCorpse.enuCorpseType.guts);
                    break;

                case enuRobotType.spider:
                    cLibHelper.newCorpse(loc, classCorpse.enuCorpseType.guts);
                    break;
            }

        }

       public int getMyValue()
        {
            switch (myType)
            {
                case enuRobotType.spider:
                    return 100;

                case enuRobotType.bat:
                    return 300;

                case enuRobotType.gray:
                    return 300;

                case enuRobotType.Smurf:
                    return 500;

                case enuRobotType.Felix:
                    return 1000;

                case enuRobotType.evilJessica:
                    return 2000;

                case enuRobotType.invisibleJessica:
                    return 4000;
            }
            return 0;
        }

        public void reset()
        {
            setMyType();
            setDX();
            setHP();
            setBullet();
            setStepsPerTurn();
            intVisibleCounter = 17;
            intConfigID = 0;
            intConfigStep = 0;

            switch (myType)
            {
                case enuRobotType.bat:
                    switch (myLetterID)
                    {
                        case enuRobotID.Secondary_A:
                            loc = new Point(954, 139);
                            udrMove.WPfrom = udrMove.WPnext = udrMove.WPtarget = cLibWPs.NearestWayPoint(loc);
                            udrMove.strPath = "";
                            intBatGrowStep = -100;
                            break;

                        case enuRobotID.Secondary_B:
                            loc = new Point(902, 492);
                            udrMove.WPfrom = udrMove.WPnext = udrMove.WPtarget = cLibWPs.NearestWayPoint(loc);
                            udrMove.strPath = "";
                            intBatGrowStep = -100;
                            break;
                    }
                    break;

                case enuRobotType.spider:
                    loc = cLibWPs.WPs[1].pt;
                    udrMove.WPfrom = cLibWPs.WPs[1];
                    udrMove.WPnext = udrMove.WPtarget = cLibWPs.WPs[1].neaghbours[0].wp;
                    udrMove.strPath = cLibWPs.WPs[1].neaghbours[0].strPath;
                    intConfigID = (int)enuSpider_Configurations.walk;
                    spiderMode = enuSpiderMode.normal;
                    break;

                default:
                    loc = cLibWPs.WPs[0].pt;
                    udrMove.WPfrom = cLibWPs.WPs[0];
                    udrMove.WPnext = cLibWPs.WPs[0];
                    udrMove.WPtarget = cLibWPs.WPs[0];
                    udrMove.strPath = "";
                    break;
            }

            bullet = null;
            bolDead = false;
            myType_old = myType;
        }

   
        void setStepsPerTurn()
        {
            switch (myType)
            {
                case  enuRobotType.bat:
                    intStepsPerTurn = 8;
                    break;

                case enuRobotType.gray:
                    intStepsPerTurn = 10;
                    break;

                default:
                    intStepsPerTurn = 12;
                    break;
            }
        }

        public void animate(ref Bitmap bmp)
        {
            long lngNow = DateTime.Now.Ticks;
            long lngLastTest = lngNow;
        
            bolICanSeeJessica = (!iBite() && ICanSeeJessica());

            bool bolForceResetTargetWP = false;
            bolJessicaIsInHerBunker = (Jessica.ptLoc.X > cLibHelper.ptBunker.X
                                       && Jessica.ptLoc.X < cLibHelper.ptBunker.X + cLibHelper.bmpBunker.Width
                                       && Jessica.ptLoc.Y > cLibHelper.ptBunker.Y
                                       && Jessica.ptLoc.Y < cLibHelper.ptBunker.Y + cLibHelper.bmpBunker.Height);

            if (bolICanSeeJessica && !iBite())
            {
                if (!bolJessicaIsInHerBunker)
                {
                    udrMove.lastKnownJessicaLoc = Jessica.ptLoc;
                    bolForceResetTargetWP = true;
                }
                DecideWhetherIShouldShootJessica();
            }

            if (myType == enuRobotType.bat)
            {
                if (intBatGrowStep < 0)
                {
                    sprites[(int)myType].putConfigurationOnScreen(ref bmp, (int)enuRobot_Bat_Configurations.grow, 0, loc, 0, ((double)(intBatGrowStep++ + 100)) / 100.0, enuMirror.vertical, true);
                    Sprite.udtConfigurationStep conStep = sprites[(int)classRobot.enuRobotType.bat].Configurations[1].steps[0];
                    if (intBatGrowStep > -70)
                    {
                        Point ptThis = conStep.BmpCacheByMirrorType[(int)enuMirror.vertical].dir[0].ptTL;  
                        Size szBat = new Size((int)((double)(-ptThis.X * 2) / (double)cLibCD.intPixelSize),
                                              (int)((double)(-ptThis.Y * 2) / (double)cLibCD.intPixelSize));
                        udrCDInfo.ptRelPos = new Point(szBat.Width / 2, szBat.Height);
                        udrCDInfo.sz = szBat;
                    }
                    else
                    {
                        udrCDInfo.ptRelPos = new Point(0, 0);
                        udrCDInfo.sz = new Size(0, 0);
                    }
                    if (cLibCD.bolDrawCDInfo)
                        cLibCD.drawCDInfo(ref bmp, udrCDInfo, loc);
                    return;
                }
                else if (intBatGrowStep == 0)
                {
                    intConfigStep = cLibHelper.getRnd(sprites[(int)enuRobotType.bat].Configurations[0].steps.Length);
                    intBatGrowStep++;

                    if (udrShortestPathToWP_BatStartup.wp == null)
                        udrShortestPathToWP_BatStartup = cLibWPs.findNearestWayPoint(loc);

                    udrMove.WPnext = udrShortestPathToWP_BatStartup.wp;
                    udrMove.strPath = udrShortestPathToWP_BatStartup.strPath;

                    udrMove.WPfrom = cLibWPs.WPs[0]; // to avoid bolForceResetTargetWP
                    bolForceResetTargetWP = false;
                }
            }
            else if (myType == enuRobotType.spider)
            {
                intSpiderFed--;
                if (intSpiderFed < 0)
                    intSpiderFed = 0;

                if (intConfigStep == 0 && (enuSpider_Configurations)intConfigID != enuSpider_Configurations.walk)
                    setTargetWP();
                else
                {
                    if (spiderMode == enuSpiderMode.prepareToAttack)
                        if (!ICanSeeJessica())
                            spiderMode = enuSpiderMode.normal;
                }
            }

            if (udrMove.WPnext == udrMove.WPfrom
                && udrMove.WPtarget.pt == loc
                && myType != enuRobotType.spider)
                bolForceResetTargetWP = true;

            if (bolForceResetTargetWP)
                setTargetWP();

            move();
      
            setMirror();
            setConfig();

            Point ptScreenLoc = loc;
            switch (myType)
            {
                case enuRobotType.Smurf:
                    ptScreenLoc = new Point(loc.X, loc.Y + 10);
                    break;

                case enuRobotType.Felix:
                    ptScreenLoc = new Point(loc.X, loc.Y + 10);
                    break;


                case enuRobotType.evilJessica:
                case enuRobotType.invisibleJessica:
                    ptScreenLoc = new Point(loc.X, loc.Y - 10);
                    break;
            }

            /// only put visible robots onto the screen
            if (myType != enuRobotType.invisibleJessica || (myType == enuRobotType.invisibleJessica && intVisibleCounter-- >= 0 && invisibleJessicaRobotIsVisible()))
            {
               sprites[(int)myType].putConfigurationOnScreen(ref bmp, intConfigID, intConfigStep, ptScreenLoc, dblAngleDraw, 1.0, mirror, false);
            }
        
            if (bolShootJessica)
            {
                bolShootJessica = false;
                ptLocIWasAtWhenILastFired = loc;
                Point ptBulletStart = new Point(loc.X, loc.Y);
                switch (myType)
                {
                    case enuRobotType.evilJessica:
                    case enuRobotType.invisibleJessica: // PLACE bullet-eater at center of this robot                         
                        break;

                    case enuRobotType.Felix:
                        ptBulletStart = sprites[(int)myType].conCurrent.getLimbPos("gunhand(near)", mirror, intConfigStep, 0);
                        ptBulletStart = new Point(loc.X + ptBulletStart.X, loc.Y + ptBulletStart.Y);
                        break;

                    case enuRobotType.Smurf:
                        ptBulletStart = sprites[(int)myType].conCurrent.getLimbPos("head", mirror, intConfigStep, 0);
                        ptBulletStart = new Point(loc.X + ptBulletStart.X, loc.Y + ptBulletStart.Y);
                        break;
                }
                bullet = new classBullet(myBulletType, ptBulletStart, dblAngleShootJessica, false, ref cLibHelper);
                bullet.robotThatShotMe = this;
                cLibCD.enQBullet(ref bullet);
                cLibHelper.playSound(DXGun);
            }

            incConfigStep();
            setCDInfo();
            if (cLibCD.bolDrawCDInfo )
                cLibCD.drawCDInfo(ref bmp, udrCDInfo, ptScreenLoc);
        }

        void setMirror()
        {
            switch (myType)
            {
                case enuRobotType.bat:
                case enuRobotType.spider:
                    mirror = enuMirror.none;
                    break;

                case enuRobotType.gray:
                    if (udrMove.dir >= Night_Stalker.enuDir.N_ && udrMove.dir < Night_Stalker.enuDir.S_)
                        mirror = enuMirror.horizontal;
                    else
                        mirror = enuMirror.none;
                    break;

                default:
                    if (intConfigID == (int)enuRobot_Blue_Configurations.walk)
                    {
                        if (udrMove.dir != enuDir.N_ && udrMove.dir != enuDir.S_)
                            if (udrMove.dir >= Night_Stalker.enuDir.N_ && udrMove.dir < Night_Stalker.enuDir.S_)
                                mirror = enuMirror.horizontal;
                            else
                                mirror = enuMirror.none;
                    }
                    else
                    {
                        if (udrMove.dir >= Night_Stalker.enuDir.N_ && udrMove.dir < Night_Stalker.enuDir.S_)
                            mirror = enuMirror.horizontal;
                        else
                            mirror = enuMirror.none;
                    }
                    
                    break;
            }
        }

        bool invisibleJessicaRobotIsVisible()
        {
            if (intVisibleCounter > 10)
                return true;
            else if (intVisibleCounter > 5 && intVisibleCounter % 2 == 0)
                return true;
            else if (intVisibleCounter % 3 == 0)
                return true;
            else
                return false;
        }

        public bool iBite() { return (myType == enuRobotType.bat || myType == enuRobotType.spider); }

        void incConfigStep()
        {
            //setConfig();
            intConfigStep = (intConfigStep + 1) % sprites[(int)myType].Configurations[intConfigID].steps.Length;                    
            switch (myType)
            {
                case enuRobotType.Smurf:
                    break;

                case enuRobotType.Felix:
                case enuRobotType.evilJessica:
                case enuRobotType.invisibleJessica:
                    switch ((enuRobot_White_Configurations)intConfigID)
                    {
                        case enuRobot_White_Configurations.Walk_right :
                            break;

                        case enuRobot_White_Configurations.shoot_up:
                        case enuRobot_White_Configurations.shoot_high:
                        case enuRobot_White_Configurations.shoot_straight:
                        case enuRobot_White_Configurations.shoot_low:
                        case enuRobot_White_Configurations.shoot_down :
                            if (intConfigStep == 0)
                                intConfigID = (int)enuRobot_White_Configurations.Walk_right;
                            break;
                    }
                    break;

                default:
                    break;
            }
        }

        void setConfig()
        {
            int intConfigID_new = intConfigID;
            switch (myType)
            {
                case enuRobotType.spider:
                    break;

                case enuRobotType.bat:
                    intConfigID_new = (int)enuRobot_Bat_Configurations.fly;
                    break;

                case  enuRobotType.gray :
                    switch (udrMove.dir)
                    {
                        case enuDir.S_:
                            intConfigID_new = (int)enuRobot_Gray_Configurations.Walk_Down;
                            break;

                        case enuDir.N_:
                            intConfigID_new = (int)enuRobot_Gray_Configurations.Walk_Up;
                            break;

                        default:
                            intConfigID_new = (int)enuRobot_Gray_Configurations.Walk_Right;
                            break;
                    }
                    break;

                case enuRobotType.evilJessica:
                    switch ((enuRobot_White_Configurations)intConfigID)
                    {
                        case enuRobot_White_Configurations.shoot_down:
                            intConfigID_new = (int)enuRobot_White_Configurations.shoot_down;
                            break;

                        case enuRobot_White_Configurations.shoot_high:
                            intConfigID_new = (int)enuRobot_White_Configurations.shoot_high;
                            break;

                        case enuRobot_White_Configurations.shoot_low:
                            intConfigID_new = (int)enuRobot_White_Configurations.shoot_low;
                            break;

                        case enuRobot_White_Configurations.shoot_straight:
                            intConfigID_new = (int)enuRobot_White_Configurations.shoot_straight;
                            break;

                        case enuRobot_White_Configurations.shoot_up:
                            intConfigID_new = (int)enuRobot_White_Configurations.shoot_up;
                            break;

                        case enuRobot_White_Configurations.Walk_right:
                            switch (udrMove.dir)
                            {
                                //case enuDir.S_:
                                //    intConfigID_new = (int)enuRobot_White_Configurations.Walk_Down;
                                //    break;

                                //case enuDir.N_:
                                //    intConfigID_new = (int)enuRobot_White_Configurations.Walk_Up;
                                //    break;

                                default:
                                    intConfigID_new = (int)enuRobot_White_Configurations.Walk_right;
                                    break;
                            }
                            break;
                    }
                    break;

               case enuRobotType.invisibleJessica:
                    switch ((enuRobot_Black_Configurations)intConfigID)
                    {
                        case enuRobot_Black_Configurations.Shoot_Down:
                            intConfigID_new = (int)enuRobot_Black_Configurations.Shoot_Down;
                            break;

                        case enuRobot_Black_Configurations.Shoot_High:
                            intConfigID_new = (int)enuRobot_Black_Configurations.Shoot_High;
                            break;

                        case enuRobot_Black_Configurations.Shoot_Low:
                            intConfigID_new = (int)enuRobot_Black_Configurations.Shoot_Low ;
                            break;

                        case enuRobot_Black_Configurations.Shoot_Straight :
                            intConfigID_new = (int)enuRobot_Black_Configurations.Shoot_Straight;
                            break;

                        case enuRobot_Black_Configurations.Shoot_Up :
                            intConfigID_new = (int)enuRobot_Black_Configurations.Shoot_Up;
                            break;

                        case enuRobot_Black_Configurations.Walk_Right:
                            switch (udrMove.dir)
                            {
                                //case enuDir.S_:
                                //    intConfigID_new = (int)enuRobot_Black_Configurations.Walk_Down;
                                //    break;

                                //case enuDir.N_:
                                //    intConfigID_new = (int)enuRobot_Black_Configurations.Walk_Up;
                                //    break;

                                default:
                                    intConfigID_new = (int)enuRobot_Black_Configurations.Walk_Right;
                                    break;
                            }
                            break;
                    }
                    break;

               case enuRobotType.Felix:
               case enuRobotType.Smurf:
                    intConfigID = 0;
                    return;
                    //switch ((enuRobot_Blue_Configurations)intConfigID)
                    //{
                    //    case enuRobot_Blue_Configurations.Shoot_down:
                    //        intConfigID_new = (int)enuRobot_Blue_Configurations.Shoot_down;
                    //        break;

                    //    case enuRobot_Blue_Configurations.Shoot_high:
                    //        intConfigID_new = (int)enuRobot_Blue_Configurations.Shoot_high;
                    //        break;

                    //    case enuRobot_Blue_Configurations.Shoot_low:
                    //        intConfigID_new = (int)enuRobot_Blue_Configurations.Shoot_low;
                    //        break;

                    //    case enuRobot_Blue_Configurations.Shoot_straight:
                    //        intConfigID_new = (int)enuRobot_Blue_Configurations.Shoot_straight;
                    //        break;

                    //    case enuRobot_Blue_Configurations.Shoot_up:
                    //        intConfigID_new = (int)enuRobot_Blue_Configurations.Shoot_up;
                    //        break;


                    //    case enuRobot_Blue_Configurations.Walk_Right:
                    //        switch (udrMove.dir)
                    //        {
                    //            //case enuDir.S_:
                    //            //    intConfigID_new = (int)enuRobot_Blue_Configurations.Walk_Down;
                    //            //    break;

                    //            //case enuDir.N_:
                    //            //    intConfigID_new = (int)enuRobot_Blue_Configurations.Walk_Up;
                    //            //    break;

                    //            default:
                    //                intConfigID_new = (int)enuRobot_Blue_Configurations.Walk_Right;
                    //                break;
                    //        }
                    //        break;
                    //}
                    break;
            }

            if (intConfigID != intConfigID_new)
            {
                intConfigID = intConfigID_new;
                intConfigStep = 0;
            }
        }

        void move()
        {
            switch (myType)
            {
                case enuRobotType.spider:
                    if (intConfigID != (int)enuSpider_Configurations.walk)
                        return;
                    break;

                case enuRobotType.gray:
                    break;

                case enuRobotType.evilJessica:
                case enuRobotType.invisibleJessica:
                    switch ((enuRobot_White_Configurations)intConfigID)
                    {
                        case enuRobot_White_Configurations.Walk_right:
                            break;

                        default:
                            return;
                    }
                    break;

                default:
                    break;
            }

            Point pt = loc;
            if (udrMove.strPath.Length < intStepsPerTurn)
            {
                if (udrMove.WPnext == udrMove.WPtarget)
                    setTargetWP();

                if (udrMove.WPtarget == null)
                    udrMove.WPtarget = getRndTargetWP();

                if (udrMove.WPnext != udrMove.WPtarget)
                {
                    
                    udrMove.strPath += udrMove.WPnext
                        .neaghbours[
                           cLibWPs.nextWPTable[udrMove.WPnext.index, 
                                               udrMove.WPtarget.index]
                                   ].strPath;

                    classWayPoint WPNext = udrMove.WPnext.neaghbours[cLibWPs.nextWPTable[udrMove.WPnext.index, udrMove.WPtarget.index]].wp;
                    udrMove.WPfrom = udrMove.WPnext;
                    udrMove.WPnext = WPNext;
                }
            }

            if (myType == enuRobotType.spider)
            {
                if (udrMove.WPnext.pt.X == loc.X)
                {
                    if (udrMove.WPnext.pt.Y < loc.Y)
                        dblAngleDraw = Math.PI;
                    else if (udrMove.WPnext.pt.Y > loc.Y)
                        dblAngleDraw = 0;
                }
                else if (udrMove.WPnext.pt.Y == loc.Y)
                {
                    if (udrMove.WPnext.pt.X < loc.X)
                        dblAngleDraw = Math.PI * .5;
                    else if (udrMove.WPnext.pt.X > loc.Y)
                        dblAngleDraw = Math.PI * 1.5;
                }
            }

            if (udrMove.strPath.Length > 0)
            {
                string strDir = "E N W S ";
                int intStepCounter = 0;
                for (intStepCounter = 0; intStepCounter < intStepsPerTurn && intStepCounter < udrMove.strPath.Length ; intStepCounter++)
                    loc = cLibHelper.movePixel(loc, (enuDir)strDir.IndexOf(udrMove.strPath.Substring(intStepCounter, 1)));
                udrMove.strPath = udrMove.strPath.Substring(intStepCounter);

                udrMove.dir = cLibHelper.getDirBetweenTwoPoints(pt, loc);
            }

            if (iBite())
            {
                Point ptRemember = new Point(loc.X, loc.Y);
                int intDistanceToJessica = (int)Math.Sqrt(Math.Pow(Jessica.ptLoc.X - loc.X, 2) + Math.Pow(Jessica.ptLoc.Y - loc.Y, 2));
                if (intDistanceToJessica < 100)
                    if (cLibCD.CollisionBetweenTwoCDInfoObjects(pt, ref loc, udrCDInfo, Jessica.ptLoc, Jessica.udrCDInfo))
                    {
                        Jessica.gotosleep();
                        intSpiderFed = 400; // forty seconds
                    }
                loc = ptRemember;
            }
        }

        classWayPoint getRndTargetWP()
        {
            int intRnd = udrMove.WPnext.index;
            while (intRnd == udrMove.WPnext.index)
                intRnd = cLibHelper.getRnd(cLibWPs.WPs.Length-1)+1; // any WP except WP[0] because that is the back of the den
            return cLibWPs.WPs[intRnd];
        }

        void setTargetWP()
        {
            if (udrMove.WPfrom == udrMove.WPnext)
            {
                //initialize 
                udrMove.WPtarget = cLibWPs.NearestWayPoint(Jessica.ptLoc);
                if (udrMove.WPtarget == null)
                    udrMove.WPtarget = getRndTargetWP();

                udrMove.WPnext = udrMove.WPfrom.neaghbours[cLibWPs.nextWPTable[udrMove.WPfrom.index, udrMove.WPtarget.index]].wp;
                udrMove.strPath = udrMove.WPfrom.neaghbours[cLibWPs.nextWPTable[udrMove.WPfrom.index, udrMove.WPtarget.index]].strPath;
                return;
            }

           

            switch (myType)
            {
                case enuRobotType.Smurf:
                    if (bolICanSeeJessica && !bolJessicaIsInHerBunker )
                    {
                        udrMove.WPtarget = cLibWPs.NearestWayPoint(Jessica.ptLoc);
                        if (udrMove.WPtarget == udrMove.WPnext)
                            udrMove.WPtarget = getRndTargetWP();
                    }
                    else
                        udrMove.WPtarget = getRndTargetWP();
                    break;

                case enuRobotType.Felix:
                case enuRobotType.evilJessica:
                case enuRobotType.invisibleJessica:
                    int intErrorRange = ((int)(bolJessicaIsInHerBunker ? 5 : (enuRobotType.invisibleJessica - myType) + 1)) * 25;
                    Point ptErrorLoc = cLibHelper.getRndLocOnMap(Jessica.ptLoc, intErrorRange);
                    udrMove.WPtarget = cLibWPs.NearestWayPoint(ptErrorLoc);
                    if (udrMove.WPtarget == udrMove.WPnext)
                        udrMove.WPtarget = getRndTargetWP();
                    break;

                case enuRobotType.bat:
                    Point ptBatErrorLoc = cLibHelper.getRndLocOnMap(loc, (int)(cLibWPs.bmpWPs.Width * .3));
                    udrMove.WPtarget = cLibWPs.NearestWayPoint(ptBatErrorLoc);
                    if (udrMove.WPtarget == udrMove.WPnext)
                        udrMove.WPtarget = getRndTargetWP();
                    break;

                case enuRobotType.spider:
                startSpiderTargetWP:
                    switch (spiderMode)
                    {
                        case enuSpiderMode.normal:
                            if (SpiderCanAttackJessica())
                            {
                                intConfigID = (int)enuSpider_Configurations.prepare_to_attack;
                                spiderMode = enuSpiderMode.prepareToAttack;
                                if (myType == enuRobotType.spider)
                                {
                                    if (Jessica.ptLoc.X == loc.X)
                                    {
                                        if (Jessica.ptLoc.Y < loc.Y)
                                            dblAngleDraw = Math.PI;
                                        else if (Jessica.ptLoc.Y > loc.Y)
                                            dblAngleDraw = 0;
                                    }
                                    else if (Jessica.ptLoc.Y == loc.Y)
                                    {
                                        if (Jessica.ptLoc.X < loc.X)
                                            dblAngleDraw = Math.PI * .5;
                                        else if (Jessica.ptLoc.X > loc.Y)
                                            dblAngleDraw = Math.PI * 1.5;
                                    }
                                }
                            }
                            else
                            {
                                if (cLibHelper.getRnd(1000) % 5 == 0)
                                {
                                    intConfigID = (int)enuSpider_Configurations.rest;
                                    spiderMode = enuSpiderMode.rest;
                                }
                                else
                                {
                                    int intRndWP = 0;
                                    string strReject = ".0.9.11.23.24.26.27.28.33.34.";
                                    while (strReject.Contains(intRndWP.ToString()))
                                        intRndWP = cLibHelper.getRnd(34);

                                    udrMove.WPtarget = cLibWPs.WPs[intRndWP];
                                    if (udrMove.WPtarget == udrMove.WPnext)
                                        goto startSpiderTargetWP;
                                    intStepsPerTurn = 15;
                                }
                            }
                            break;

                        case enuSpiderMode.rest:
                            if (intConfigStep == 0)
                            {
                                intConfigID = (int)enuSpider_Configurations.walk;
                                spiderMode = enuSpiderMode.normal;
                            }
                            break;

                        case enuSpiderMode.prepareToAttack:
                            if (intConfigStep == 0)
                            {
                                intConfigID = (int)enuSpider_Configurations.walk;
                                spiderMode = enuSpiderMode.Attack;
                                udrMove.WPtarget = cLibWPs.NearestWayPoint(Jessica.ptLoc);
                                if (udrMove.WPtarget == udrMove.WPnext)
                                    udrMove.WPtarget = getRndTargetWP();
                                intStepsPerTurn = 30;

                                

                            }
                            break;

                        case enuSpiderMode.Attack:
                            if (intConfigStep == 0)
                            {
                                intConfigStep = (int)enuSpider_Configurations.rest;
                                spiderMode = enuSpiderMode.rest;
                            }
                            break;
                            break;
                    }
                break;

                case enuRobotType.gray:
                default:
                while (udrMove.WPtarget == udrMove.WPnext)
                    udrMove.WPtarget = getRndTargetWP();
                break;
            }
        }

        /// <summary>
        /// sets the global variable bolShootJessica to true if this robot is in a position to and is capable of shooting at Jessica
        /// </summary>
        void DecideWhetherIShouldShootJessica()
        {
            double dblAngleBetweenMeAndJessica = cLibHelper.cLibMath.arcTan(Jessica.ptLoc.X - loc.X, 
                                                                            Jessica.ptLoc.Y - loc.Y);
            enuDir dirShoot = cLibHelper.getDirBetweenTwoPoints(loc, Jessica.ptLoc);
            bolShootJessica = false;

            if (ptLocIWasAtWhenILastFired == loc)
                return;

            if (bullet == null || bullet.bolDead)
            {
                switch (myType)
                {
                    case enuRobotType.gray:
                        if (!cLibHelper.dirIsDiagonal(dirShoot))
                        {// this robot does not shoot diagonally
                            bolShootJessica = true;
                            dblAngleShootJessica = cLibHelper.convertDirToAngle(dirShoot);
                        }
                        break;

                    case enuRobotType.Smurf:
                        if (!cLibHelper.dirIsDiagonal(dirShoot) || (cLibHelper.getRnd(1000) % 20) == 0) // smurf will only fire diagonally 5% of the time
                        {  // this robot does not shoot diagonally
                            bolShootJessica = true;
                            dblAngleShootJessica = cLibHelper.convertDirToAngle(dirShoot);
                        }
                        break;

                    case enuRobotType.Felix:
                        if (!cLibHelper.dirIsDiagonal(dirShoot) || intHP > 50) // only let Felix shoot diagonally if he's never been hit
                        {  // this robot does not shoot diagonally
                            bolShootJessica = true;
                            dblAngleShootJessica = cLibHelper.convertDirToAngle(dirShoot);
                        }
                        break;

                    case enuRobotType.evilJessica:
                    case enuRobotType.invisibleJessica:
                        switch ((enuRobot_White_Configurations )intConfigID)
                        {
                            case enuRobot_White_Configurations.Walk_right:
                                break;

                            default:
                                return;
                        }

                        if (!cLibHelper.dirIsDiagonal(dirShoot))
                        {// this robot does not shoot diagonally
                            udrMove.dir = dirShoot;
                            bolShootJessica = true;
                            dblAngleShootJessica = cLibHelper.convertDirToAngle(dirShoot);

                            intConfigStep = 0;
                            switch (dirShoot)
                            {
                                case enuDir.NE:
                                case enuDir.NW:
                                    intConfigID = (int)enuRobot_White_Configurations.shoot_high;
                                    break;

                                case enuDir.E_:
                                case enuDir.W_:
                                    intConfigID = (int)enuRobot_White_Configurations.shoot_straight;
                                    break;

                                case enuDir.SE:
                                case enuDir.SW:
                                    intConfigID = (int)enuRobot_White_Configurations.shoot_low;
                                    break;

                                case enuDir.N_:
                                    intConfigID = (int)enuRobot_White_Configurations.shoot_up;
                                    break;

                                case enuDir.S_:
                                    intConfigID = (int)enuRobot_White_Configurations.shoot_down;
                                    break;
                            }
                        }
                        break;
                }
            }
        }

        bool SpiderCanAttackJessica()
        {
            if (intSpiderFed > 0)
            {
                return false;
            }

            int intMinX = (int)((double)cLibWPs.bmpWPs.Width * .3);

            if (loc.X > intMinX
                || Jessica.ptLoc.X > intMinX
                ||  !ICanSeeJessica()  )
                return false;

            int intDistance = (int)Math.Sqrt(Math.Pow(loc.X - Jessica.ptLoc.X, 2) + Math.Pow(loc.Y - Jessica.ptLoc.Y, 2));
            int intLimit = 450;
             return (intDistance < intLimit);
        }

        bool ICanSeeJessica()
        {
            return cLibCD.JessicaCanBeSeenFromHere(loc);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Christ Kennedy
CEO unemployable
Canada Canada
Christ Kennedy, published his fourth novel "Cleats of the Counter Revolution" in the summer of 2010. He grew up in the suburbs of Montreal and is a bilingual Quebecois with a bachelor’s degree in computer engineering from McGill University and is currently walking across ontario plotting a new novel, far away from any computer.

| Advertise | Privacy | Mobile
Web02 | 2.8.140814.1 | Last Updated 27 Jan 2010
Article Copyright 2010 by Christ Kennedy
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid