Beispiel #1
0
        public static void AddForegroundStuff(Image img, MapTile t)
        {
            int x1 = (t.loc.X * FrameData.multX) + FrameData.edgeX;
            int y1 = (t.loc.Y * FrameData.multY) + FrameData.edgeY;

            if (t.clear)              // set flow as background only
            {
                int showFlow = Refs.p.viewFlow;

                // display nectar drops using deepest level
                int deepestLevel = 0;
                int deepestAmt   = 0;
                int sumAmt       = 0;
                for (int nLoop = 0; nLoop < t.nectarLevel.Length; nLoop++)
                {
                    sumAmt += t.nectarLevel[nLoop];
                    if (t.nectarLevel[nLoop] > deepestAmt)
                    {
                        deepestAmt   = t.nectarLevel[nLoop];
                        deepestLevel = nLoop;
                    }
                }
                if (deepestAmt > 0)
                {
                    using (var gNectar = Graphics.FromImage(img))
                    {
                        Color nectarCol;
                        if (deepestLevel == 0)
                        {
                            nectarCol = Refs.p.myColor;
                        }
                        else
                        {
                            nectarCol = Harem.GetId(deepestLevel).myColor;
                        }

                        // Color mixedCol = GetColorMix(t);

                        if (sumAmt > 8)
                        {
                            sumAmt = 8;
                        }
                        string useNectarChar = nectarChars[sumAmt];
                        //if (sumAmt > 1) { useNectarChar = nectarCharLarge; }

                        gNectar.DrawImage(
                            SpriteManager.GetSprite(useNectarChar, Refs.m.stdSize, nectarCol, t.backCol),
                            x1, y1);
                    }
                }
                // todo bigger blob for more nectar maybe?
            }
            else             // it's not marked as clear, so draw the wall
            {
                Bitmap singleTileImage = SpriteManager.GetSprite(t.gly, Refs.m.stdSize, Color.White, t.backCol);
                using (var gChar = Graphics.FromImage(img))
                {
                    gChar.DrawImage(singleTileImage, x1, y1);
                }
            }
        }
Beispiel #2
0
        public void RunFlow(Boolean maskWalls)
        {
            FlowTileSet heads = AllFlowSquares();

            if (maskWalls)
            {
                foreach (FlowTile fs in heads)
                {
                    // mask out walls etc, we don't flow over those
                    MapTile thisTile = Refs.m.TileByLoc(fs.loc);
                    if (!thisTile.clear)
                    {
                        fs.mask = true;
                    }
                }
            }

            // I call them heads because they 'snake' outwards from the initial point(s)
            //    but you get splits into several heads at junctions so it's a bad metaphor...

            // loop till we can't find anything more to do,
            // (or we decide we've messed up)
            bool changes        = true;
            int  failsafe       = 0;
            int  headsProcessed = 0;

            while (changes == true && failsafe < 256)
            {
                changes = false; failsafe++;

                FlowTileSet newHeads = new FlowTileSet();

                // for each active head tile...
                foreach (FlowTile fs in heads)
                {
                    // ...find the tiles next to it...
                    FlowTileSet newTiles = new FlowTileSet()
                    {
                        fs.OneNorth(),
                                  fs.OneEast(),
                                  fs.OneSouth(),
                                  fs.OneWest()
                    };

                    // ... (ignoring any nulls) ...
                    newTiles.RemoveWhere(item => item == null);

                    // ... and for each one found ...
                    foreach (FlowTile newFlowSq in newTiles)
                    {
                        // ... if we can improve the flow rating of it ...
                        double delta = newFlowSq.flow - fs.flow;

                        MapTile targetTile = Refs.m.TileByLoc(fs.loc);
                        if (targetTile.clear && delta > 1.0001)
                        {
                            // ... do so, and then make it a new head ...
                            newFlowSq.flow = fs.flow + 1;
                            newHeads.Add(newFlowSq);
                            changes = true;
                        }
                    }
                    headsProcessed++;
                }
                // ... and next time around, we keep going using those new heads
                heads = newHeads;

                if (failsafe == 255)
                {
                    Console.WriteLine("Hit flow failsafe!");
                }
            }
        }
Beispiel #3
0
        // returns number of round passed, 0 for free actions, 1 for normal moves.
        public int HandlePlayerInput(PreviewKeyDownEventArgs e)
        {
            // for convenience
            MapTile here = Refs.m.TileByLoc(loc);

            // debugging nectar report
            Console.Write("Nectar here is ");
            foreach (int i in here.nectarLevel)
            {
                Console.Write(i + ", ");
            }
            Console.Write(".");

            if (e.KeyCode == Keys.F && heldCubiId != 0)
            {
                return(BoinkHeld());
            }

            if (e.KeyCode == Keys.C && heldCubiId != 0)
            {
                return(CaneHeld());
            }

            Loc lastPos = loc;

            // visualise flows. hotkeys are just pretend this is where we really do it
            if (e.KeyCode == Keys.D0)
            {
                viewFlow = 0; return(0);
            }
            if (e.KeyCode == Keys.D1)
            {
                viewFlow = 1; return(0);
            }
            if (e.KeyCode == Keys.D2)
            {
                viewFlow = 2; return(0);
            }
            if (e.KeyCode == Keys.D3)
            {
                viewFlow = 3; return(0);
            }
            if (e.KeyCode == Keys.D4)
            {
                viewFlow = 4; return(0);
            }

            int timepass = 1;

            if (e.KeyCode == Keys.Space)
            {
                return(1);                // allow waiting at any time
            }

            if (placemode || e.Shift)
            {
                timepass = 0;                 // place / pickup is a free action for now
                switch (e.KeyCode)
                {
                case Keys.Down:
                case Keys.S: ActionSouth(); FinishMode(); break;

                case Keys.Right:
                case Keys.D: ActionEast(); FinishMode(); break;

                case Keys.Up:
                case Keys.W: ActionNorth(); FinishMode(); break;

                case Keys.Left:
                case Keys.A: ActionWest(); FinishMode(); break;

                case Keys.Escape: CancelModes(); break;

                default: break;
                }
            }
            else if (throwmode || e.Control)
            {
                timepass = 0;                 // throw is a free action for now
                switch (e.KeyCode)
                {
                case Keys.Down:
                case Keys.S: ThrowSouth(); FinishMode(); break;

                case Keys.Right:
                case Keys.D: ThrowEast(); FinishMode(); break;

                case Keys.Up:
                case Keys.W: ThrowNorth(); FinishMode(); break;

                case Keys.Left:
                case Keys.A: ThrowWest(); FinishMode(); break;

                case Keys.Escape: CancelModes(); break;

                default: break;
                }
            }
            else
            {
                timepass = 1;
                switch (e.KeyCode)
                {
                // moves cost 1 turn
                case Keys.Down:
                case Keys.S: RunSouth(); break;

                case Keys.Right:
                case Keys.D: RunEast(); break;

                case Keys.Up:
                case Keys.W: RunNorth(); break;

                case Keys.Left:
                case Keys.A: RunWest(); break;

                // mode changes are free actions
                case Keys.T: SetThrowMode(); timepass = 0; break;

                case Keys.P: SetPlaceMode(); timepass = 0; break;

                case Keys.Escape: CancelModes(); timepass = 0; break;

                default: timepass = 0; break;
                }
            }

            // save our current location for next turn
            lastMove = Loc.SubPts(loc, lastPos);

            // starting at 1 skips player nectar processing for now
            for (int nLoop = 1; nLoop < here.nectarLevel.Length; nLoop++)
            {
                if (here.nectarLevel[nLoop] > 0)
                {
                    horny += here.nectarLevel[nLoop];
                    here.nectarLevel[nLoop] = 0;
                }
            }

            if (horny > 15)             // having fun
            {
                Refs.mf.Announce("Awwww yeah! *splurt*", myAlign, myColor);
                timepass += 5;
                MainMap.SplurtNectar(here, myIndex: 0);
                horny = 0;
            }

            if (!victory)
            {
                // we're duplicating this location scanning code a lot...
                // but this will be useful if we ever move jails so I'll leave it

                // get list of capture tiles
                MapTileSet jails = new MapTileSet();
                foreach (Loc l in Refs.m.pents)
                {
                    jails.Add(Refs.m.TileByLoc(l));
                }

                // get list of cubi locations
                MapTileSet breaker = new MapTileSet();
                foreach (Cubi c in Refs.h.roster)
                {
                    breaker.Add(Refs.m.TileByLoc(c.loc));
                }

                // IntersectWith to get occupied jails
                jails.IntersectWith(breaker);

                // if jails filled = total jails, we won!
                if (jails.Count == Refs.m.pents.Count)
                {
                    victory = true;
                    Refs.mf.Announce("Gotcha all! And in only " + turnCounter + " turns!", myAlign, myColor);
                }
            }

            return(timepass);
        }
Beispiel #4
0
        public MainMap Create(int xlen, int ylen)
        {
            var sw = new Stopwatch();

            sw.Start();

            MainMap NewMap = new MainMap(xlen, ylen);

            Refs.m = NewMap;             // needed for utils

            int xmax = NewMap.GetXLen() - 2;
            int ymax = NewMap.GetYLen() - 2;

            // seed the corners
            NewMap.TileByLoc(new Loc(1, 1)).clear       = true;
            NewMap.TileByLoc(new Loc(1, ymax)).clear    = true;
            NewMap.TileByLoc(new Loc(xmax, 1)).clear    = true;
            NewMap.TileByLoc(new Loc(xmax, ymax)).clear = true;

            // set up central area
            var homeStartClear = new Loc(29, 8);
            var homeEndClear   = new Loc(38, 15);

            NewMap.MakeClearArea(homeStartClear, homeEndClear);

            // mark home walls not to be tunneled away
            var homeStartWall = new Loc(homeStartClear.X - 1, homeStartClear.Y - 1);
            var homeEndWall   = new Loc(homeEndClear.X + 1, homeEndClear.Y + 1);

            NewMap.MarkNoTunnel(homeStartWall, homeEndWall);

            // todo hardcoded doorway
            var doorStartClear = new Loc(31, 7);
            var doorEndClear   = new Loc(36, 9);

            NewMap.MakeClearArea(doorStartClear, doorEndClear);

            // todo hardcoded initial departure area
            var spawnStartClear = new Loc(29, 6);
            var spawnEndClear   = new Loc(38, 8);

            NewMap.MakeClearArea(spawnStartClear, spawnEndClear);

            // todo new hardcoded holding pens
            int pentBaseX = 32;
            int pentBaseY = 10;

            NewMap.pents = new List <Loc>
            {
                new Loc(pentBaseX + 0, pentBaseY),
                new Loc(pentBaseX + 3, pentBaseY),
                new Loc(pentBaseX + 0, pentBaseY + 3),
                new Loc(pentBaseX + 3, pentBaseY + 3)
            };

            //NewMap.TileByLoc(new Loc(35, homeStartClear.Y)).clear = true;
            //NewMap.TileByLoc(new Loc(34, homeStartClear.Y)).clear = true;
            //NewMap.TileByLoc(new Loc(33, homeStartClear.Y)).clear = true;
            //NewMap.TileByLoc(new Loc(32, homeStartClear.Y)).clear = true;

            // cache startup
            NewMap.InitClearTilesCache();

            // maze generation
            int rounds = 0;
            var clears = NewMap.GetClearTilesCache();

            while (clears.Count > 0)
            {
                // pick a random clear tile
                clears = NewMap.GetClearTilesCache();
                var clear = clears.ElementAt(rng.Next(clears.Count));

                // which ways can we dig from it?

                var nextTo         = NewMap.GetNextTo(clear);
                var isClosed5sides = NewMap.GetClosed5Sides(nextTo);

                var andWalls      = MapTile.FilterOutClear(isClosed5sides);
                var andTunnelable = MapTile.Tunnelable(andWalls);

                var candidates = andTunnelable;

                // if there are digging options...
                if (candidates.Count > 0)
                {
                    // ... dig in one of them randomly
                    MapTile picked = candidates.ElementAt(rng.Next(candidates.Count));
                    picked.clear = true;
                    NewMap.AddToClearTileCache(picked);
                }
                else
                {
                    // ... if not, this tile will never be mined from,
                    //    so remove it from the clear tiles cache
                    NewMap.DelFromClearTileCache(clear);
                }

                //Refs.mf.UpdateMap(); // for debugging visualization
                rounds++;
            }
            NewMap.DoneWithClearTileCache();

            NewMap.ConsoleDump();
            NewMap.HealWalls();

            NewMap.ConsoleDump();

            // typ old time 230ms, new time 110ms
            Console.WriteLine("Finished mapgen in " + sw.ElapsedMilliseconds + "ms, at "
                              + rounds + " rounds");

            return(NewMap);
        }
Beispiel #5
0
 public void DelFromClearTileCache(MapTile t) => clearCache.Remove(t);
Beispiel #6
0
 public void AddToClearTileCache(MapTile t) => clearCache.Add(t);
Beispiel #7
0
        /// player-throwing-a-cubi trajectory logic

        private void ThrowCubiMain(Loc vector)
        {
            // todo lots of duplication here
            Player p          = Refs.p;
            Cubi   cubiThrown = Harem.GetId(p.heldCubiId);

            Refs.mf.Announce("You throw " + cubiThrown.name + " through the air!", myAlign, myColor);
            Refs.mf.Announce("*flap* *flap* *flap*", cubiThrown.myAlign, cubiThrown.myColor);
            cubiThrown.beingCarried = false;
            p.heldCubiId            = 0;

            // determine release point of throw
            // todo check for hit on very first tile
            Loc     startloc   = Loc.AddPts(loc, vector);
            MapTile activeTile = Refs.m.TileByLoc(startloc);

            // if very first tile is a holding pent, they can fly right over
            Loc zero = new Loc(0, 0);

            if (CheckClearForThrown(zero, activeTile) == "pent")
            {
                // oops you threw from too close
                Refs.mf.Announce("*desperate flapping* That was close, just made it over!", cubiThrown.myAlign, cubiThrown.myColor);
            }

            // if the next tile is another cubi, throw short
            // todo consolidate long and short throws
            // todo need to prevent throwing a cubi while ones already directly next to you
            string moveClear = CheckClearForThrown(vector, activeTile);

            if (moveClear == "cubi")
            {
                MapTile victimTile = Refs.m.TileByLoc(Loc.AddPts(activeTile.loc, vector));
                Cubi    victim     = Refs.m.CubiAt(victimTile.loc);

                Refs.mf.Announce("Owf!", cubiThrown.myAlign, cubiThrown.myColor);
                victim.Spanked += 5;

                Refs.mf.Announce("Oof too!", cubiThrown.myAlign, cubiThrown.myColor);
                cubiThrown.Spanked += 5;                 // and a good time was had by both
            }
            else if (moveClear == "pent")
            {
                // we just overflew a pent so consider her flight path clear for now
                moveClear = "clear";
            }

            // todo refresh player square so she's not superimposed on player square

            while (moveClear == "clear")
            {
                // blip activeTile with cubi symbol
                cubiThrown.loc = activeTile.loc;
                AnimateMobile(activeTile, cubiThrown);

                // is the next tile clear?
                moveClear = CheckClearForThrown(vector, activeTile);

                // nope, it has a cubi in.
                if (moveClear == "cubi")
                {
                    MapTile victimTile = Refs.m.TileByLoc(Loc.AddPts(activeTile.loc, vector));
                    Cubi    victim     = Refs.m.CubiAt(victimTile.loc);

                    MapTileSet escapes = new MapTileSet();

                    if (IsVertical(vector))
                    {
                        escapes = victimTile.GetPossibleMoves(Dir.DodgeVertical);
                    }
                    else
                    {
                        escapes = victimTile.GetPossibleMoves(Dir.DodgeHorizontal);
                    }

                    if (escapes.Count > 0)
                    {
                        victim.loc = MainMap.RandomFromList(escapes).loc;
                        Refs.mf.Announce("Nyahhh missed me!", victim.myAlign, victim.myColor);
                        moveClear = "clear";
                    }
                    else
                    {
                        victim.Spanked += 5;
                        Refs.mf.Announce("Owwwww!", victim.myAlign, victim.myColor);
                    }

                    // if it had a cubi, it could have moved revealing a holding pent
                    // so let's scan again
                    moveClear = CheckClearForThrown(vector, activeTile);
                }

                if (moveClear == "pent")
                {
                    // move one more tile
                    activeTile = Refs.m.TileByLoc(Loc.AddPts(vector, activeTile.loc));

                    Refs.mf.Announce("Eep! I'm caught!", cubiThrown.myAlign, cubiThrown.myColor);
                }

                // just a wall. stop here.
                if (moveClear == "wall")
                {
                    Refs.mf.Announce("You didn't hit anything interesting.", myAlign, myColor);
                }

                // it's clear, so move activeTile up and iterate
                if (moveClear == "clear")
                {
                    activeTile = Refs.m.TileByLoc(Loc.AddPts(vector, activeTile.loc));
                }
            }

            // deposit cubi here
            cubiThrown.loc = activeTile.loc;

            Refs.mf.UpdateMap();
        }
Beispiel #8
0
        /// player-throwing-pillow trajectory logic

        private void ThrowPillowMain(Loc vector)
        {
            Refs.mf.Announce("You throw a pillow!", myAlign, myColor);

            // can't throw without pillow!
            if (heldPillows <= 0)
            {
                return;
            }
            else
            {
                heldPillows--; UpdateInventory();
            }

            // determine release point of throw
            // todo check for hit on very first tile -- where to put pillow?
            Loc     startloc    = Loc.AddPts(this.loc, vector);
            MapTile activeTile  = Refs.m.TileByLoc(startloc);
            string  pillowGlyph = "O";

            // if the next tile now is a lover, extra spank stun!
            // todo consolidate long and short throws
            string moveClear = CheckClearForThrown(vector, activeTile);

            if (moveClear == "cubi")
            {
                MapTile victimTile = Refs.m.TileByLoc(Loc.AddPts(activeTile.loc, vector));
                Cubi    victim     = Refs.m.CubiAt(victimTile.loc);

                Refs.mf.Announce("POINT BLANK PILLOW SPANK!", myAlign, myColor);
                victim.Spanked += 5;
                Refs.mf.Announce("oww! *moan*", victim.myAlign, victim.myColor);
            }

            while (moveClear == "clear")
            {
                // blip activeTile with pillow symbol
                AnimatePillow(activeTile, pillowGlyph);

                // is the next tile clear?
                moveClear = CheckClearForThrown(vector, activeTile);

                // nope, it has a cubi in.
                if (moveClear == "cubi")
                {
                    MapTile victimTile = Refs.m.TileByLoc(Loc.AddPts(activeTile.loc, vector));
                    Cubi    victim     = Refs.m.CubiAt(victimTile.loc);

                    MapTileSet escapes = new MapTileSet();

                    if (IsVertical(vector))
                    {
                        escapes = victimTile.GetPossibleMoves(Dir.DodgeVertical);
                    }
                    else
                    {
                        escapes = victimTile.GetPossibleMoves(Dir.DodgeHorizontal);
                    }

                    if (escapes.Count > 0)
                    {
                        victim.loc = MainMap.RandomFromList(escapes).loc;
                        Refs.mf.Announce("Nyahhh missed me!", victim.myAlign, victim.myColor);
                        moveClear = "clear";
                    }
                    else
                    {
                        victim.Spanked += 5;
                        Refs.mf.Announce("Owwwww!", victim.myAlign, victim.myColor);
                    }
                }

                // just a wall. stop here.
                if (moveClear == "wall")
                {
                    Refs.mf.Announce("You didn't hit anything interesting.", myAlign, myColor);
                }

                // it's clear, so move activeTile up and iterate
                if (moveClear == "clear")
                {
                    activeTile = Refs.m.TileByLoc(Loc.AddPts(vector, activeTile.loc));
                }
            }
            // leave pillow on ground to form new obstruction
            activeTile.clear = false;
            Refs.m.HealWalls();

            Refs.mf.UpdateMap();
        }