示例#1
0
        public Form1()
        {
            InitializeComponent();

            bgc = BufferedGraphicsManager.Current;
            bg  = bgc.Allocate(pictureBox1.CreateGraphics(), pictureBox1.DisplayRectangle);

            GameBattle.start();

            timer          = new Timer();
            timer.Tick    += new EventHandler(loop);
            timer.Interval = 100;
            timer.Enabled  = true;
        }
示例#2
0
        public static double getTileSafetyScore(List <BattleUnit> units, BattleUnit unit, int x, int y)
        {
            double safetyScore = 0;

            foreach (BattleUnit u in units)
            {
                if (u.Equals(unit))
                {
                    continue;
                }

                int    dx       = x - u.X;
                int    dy       = y - u.Y;
                double distance = Math.Sqrt(dx * dx + dy * dy);
                if (u.team == unit.team)
                { //distance from ally
                    safetyScore += (distance == 0) ? 1 : (1 / distance);
                }
                else
                { //distance from enemy
                    safetyScore -= (distance == 0) ? 1 : (1 / distance);
                }
            }

            //check queue for future action spreads that hit this tile
            List <BattleAction> actions = GameBattle.getQueue().getActions(x, y, 20); //find all actions under 20 ctr

            actions.ForEach(action => {
                // "what if" the unit moved to the proposed x,y?
                int damage = BattleAction.getDamage(action.actor, unit, action.actiondef);
                if (damage > 0)
                { //unit would be damaged
                    safetyScore -= 1;
                }
                if (unit.hp - damage < 0)
                { //unit would be killed
                    safetyScore -= 2;
                }
                if (damage < 0)
                { //unit would be healed
                    safetyScore += 1;
                }
            });

            return(safetyScore);
        }
示例#3
0
        public BattleMove(BattleUnit unit, MoveNode node, List <MoveNode> moveNodes)
        {
            this.unit      = unit;
            this.node      = node;
            this.moveNodes = moveNodes;

            path     = BattleMap.getPath(node);
            CTR      = 0;
            Ready    = true;
            Priority = 1;
            ID       = GameBattle.generateID();

            //restrict path to unit's move limit
            if (path.Count > unit.moveLimit)
            {
                path = path.Take(unit.moveLimit).ToList();
            }
        }
示例#4
0
        public void invoke(BattleMap map, List <BattleUnit> units, BattleQueue queue)
        {
            List <ITargetable> targets = new List <ITargetable>();

            Spread.ForEach(s => {
                ITargetable target = map.getFirstTileUnit(s.X, s.Y);
                if (target != null)
                {
                    targets.Add(target);
                }
            });

            targets.ForEach(target => {
                var damages = getDamage(actor, target, actiondef);
                GameBattle.WriteLine(actor.name + " used " + actiondef.name + " on " + ((BattleUnit)target).name + " for " + damages + " damages.");
            });

            done();
        }
示例#5
0
        //generate action coverage for a particular unit
        public static List <BattleAction> generateCoverage(BattleMap map, List <BattleUnit> units, BattleUnit unit)
        {
            double min = 0, max = 1;
            List <BattleAction> coverage = new List <BattleAction>();

            coverage.Add(getDefaultAction(unit));

            //if currently charging action, add it to coverage as well to see if it is worth switching
            if (unit.action != null)
            {
                int damage = getDamage(unit, unit.action.target, unit.action.actiondef);
                unit.action.score = getScore(unit, unit.action.target, damage);
                coverage.Add(unit.action);
            }

            List <MoveNode> moveNodes = new List <MoveNode>();

            //if already moved, generate move nodes for current position only
            if (unit.moved)
            {
                moveNodes.Add(new MoveNode(unit.X, unit.Y, 0, null));
            }
            else //generate all move nodes using pathfinding algorithm
            {
                moveNodes = BattleMap.getMoveNodes(map.tiles, GameBattle.MAP_WIDTH, GameBattle.MAP_HEIGHT, units, unit, -999, true); //list of possible move nodes
                moveNodes = moveNodes.Where(node => node.steps <= unit.moveLimit).ToList();
            }

            unit.jobclass.actions.ForEach(actiondef => {
                moveNodes.ForEach(node => {
                    var diamond = createDiamond(node.x, node.y, actiondef.range, GameBattle.MAP_WIDTH, GameBattle.MAP_HEIGHT, false); //list of possible action nodes
                    diamond.ForEach(d => {
                        int totalDamage   = 0;
                        double totalScore = 0;
                        int actionCTR     = BattleQueue.calculateCTR(100, actiondef.speed);
                        bool sticky       = false;

                        actiondef.spread.ForEach(s => {
                            int x = s.X + d.X;
                            int y = s.Y + d.Y;

                            if (BattleMap.inRange(x, y)) //if target node is in range
                            {
                                BattleUnit target = null;

                                if (x == node.x && y == node.y) //is this where the actor is moving to?
                                {
                                    target = unit;              //then he will hit himself
                                }
                                else
                                {
                                    target = map.getFirstTileUnit(x, y); //get the unit at spread node

                                    //if target is actor but actor will move before it hits
                                    if (target != null && unit.Equals(target) && (node.x != unit.X || node.y != unit.Y))
                                    {
                                        target = null; //ignore actor
                                    }

                                    //if action will be invoked after target's turn (target has opportunity to move)
                                    if (target != null && target.CTR < actionCTR)
                                    {
                                        if (actiondef.sticky) //action can stick
                                        {
                                            sticky = true;
                                        }
                                        else //action cannot stick
                                        {
                                            target = null; //ignore target
                                        }
                                    }

                                    //if action will invoke before target's turn
                                    if (target != null & target.CTR >= actionCTR)
                                    {
                                        //pass
                                    }

                                    //if target is to be killed before action is invoked
                                    if (target != null)
                                    {
                                        int futureDamage = BattleQueue.getTargetFutureDamage(unit, target, actionCTR);
                                        if (futureDamage > target.hp)
                                        {
                                            target = null; //ignore target
                                        }
                                    }
                                }

                                if (target != null)
                                {
                                    int damage   = getDamage(unit, target, actiondef); //get damage
                                    totalScore  += getScore(unit, target, damage);     //get score from damage
                                    totalDamage += damage;                             //add damage to running total for this action
                                }
                            }
                        });

                        //if nothing was accomplished in the spread, ignore this action node
                        if (totalScore <= 0)
                        {
                            return;
                        }

                        totalScore += node.SafetyScore;

                        int dx          = d.X - node.x;
                        int dy          = d.Y - node.y;
                        double distance = Math.Sqrt(dx * dx + dy * dy); //distance from action node to move node
                        totalScore     += distance;                     //todo: for ranged attacks higher is better, for ranged buffs lower is better

                        BattleAction battleAction = new BattleAction(unit, actiondef);
                        battleAction.node         = node;
                        battleAction.distance     = distance;
                        battleAction.damage       = totalDamage;
                        battleAction.score        = totalScore;
                        battleAction.moveNodes    = moveNodes;
                        battleAction.diamond      = diamond;

                        if (sticky)
                        {
                            battleAction.target = GameBattle.getMap().getFirstTileUnit(d.X, d.Y);
                        }

                        if (battleAction.target == null)
                        {
                            battleAction.target = GameBattle.getMap().tiles[d.X, d.Y];
                        }

                        coverage.Add(battleAction);

                        min = totalScore < min ? totalScore : min;
                        max = totalScore > max ? totalScore : max;
                    }); //diamond
                });     //mapNodes
            });         //actions

            //normalization of scores
            coverage.ForEach(c => {
                c.score = (c.score - min) / (max - min);
            });

            coverage.Sort();

            return(coverage);
        }
示例#6
0
        public void invoke(BattleMap map, List <BattleUnit> units, BattleQueue queue)
        {
            GameBattle.WriteLine(name + " invoked");

            //this.safetyMap = generateSafetyMap(battle.units, this);
            List <BattleAction> coverage = BattleAction.generateCoverage(map, units, this);

            if (!moved && !acted)
            {
                if (action != null)
                {
                    GameBattle.WriteLine(name + " is already preparing to act.");
                    //todo: if action is sticky, allow movement
                    acted = true;
                }
                else
                {
                    action = coverage.First();  //supposedly the best action

                    //if action requires move
                    if (action.node.x != X || action.node.y != Y)
                    {
                        move = new BattleMove(this, action.node, action.moveNodes);
                        queue.add(move);
                        moved  = true;
                        action = null; //will get new action after move is completed
                    }
                    else
                    {
                        queue.add(action);
                        acted = true;
                        GameBattle.WriteLine(name + " queued an action called " + action.actiondef.name);
                    }
                }
            }
            else if (acted && !moved)
            {
                GameBattle.WriteLine("Moving to a safer location.");

                List <MoveNode> moveNodes = BattleMap.getMoveNodes(map.tiles, GameBattle.MAP_WIDTH, GameBattle.MAP_HEIGHT, units, this, moveLimit, true);

                moveNodes.Sort();

                MoveNode newNode = moveNodes[0];
                move = new BattleMove(this, newNode, action.moveNodes);
                queue.add(move);

                //only counts as move if actually moved
                if (newNode.x != X || newNode.y != Y)
                {
                    moved = true;
                }

                done();
            }
            else if (!acted && moved)
            {
                if (action != null)
                {
                    GameBattle.WriteLine(name + " is already preparing to act!!!");
                }
                else
                {
                    action = coverage[0];
                    queue.add(action);
                    acted = true;
                    GameBattle.WriteLine(name + " queued an action called " + action.actiondef.name);
                }

                done();
            }
            else
            {
                GameBattle.WriteLine("This should never happen.");
                done();
            }
        }
示例#7
0
 public List <BattleAction> getActions(int x, int y, int ctr)
 {
     return(list.OfType <BattleAction>().Where(action => action.CTR <= ctr && GameBattle.listHasPoint(action.Spread, x, y)).ToList());
 }
示例#8
0
 public static void start()
 {
     instance = new GameBattle();
     timer    = new Timer(_ => instance.update(), null, 0, 1000);
 }