public int possibleFire(unitEnum UnitType, stanceEnum UnitStance) { int fireOffset = 0; switch (UnitType) { case (unitEnum.Infantry): fireOffset = Constants.FIRE_INFANTRY; break; case (unitEnum.Cavalry): fireOffset = 0; break; case (unitEnum.Artillery): if (UnitStance == stanceEnum.Line) { fireOffset = Constants.FIRE_ARTILLERY; } else { fireOffset = 0; } break; default: break; } return(fireOffset); }
public MapUnit() { x = 0; y = 0; strength = 100; morale = 100; support = 0; training = 100; player = playerEnum.Red; description = "Standard Unit"; battlesWon = 0; typeUnit = unitEnum.Infantry; stanceUnit = stanceEnum.Line; }
public int possibleMoves(unitEnum UnitType, stanceEnum UnitStance) { int moveOffset = 0; switch (UnitType) { case (unitEnum.Infantry): if (UnitStance == stanceEnum.Square) { moveOffset = Constants.MOVES_INFANTRY_SQUARE; } if (UnitStance == stanceEnum.Line) { moveOffset = Constants.MOVES_INFANTRY_LINE; } if (UnitStance == stanceEnum.Column) { moveOffset = Constants.MOVES_INFANTRY_COLUMN; } break; case (unitEnum.Cavalry): if (UnitStance == stanceEnum.Line) { moveOffset = Constants.MOVES_CAVALRY_LINE; } if (UnitStance == stanceEnum.Column) { moveOffset = Constants.MOVES_CAVALRY_COLUMN; } break; case (unitEnum.Artillery): if (UnitStance == stanceEnum.Line) { moveOffset = Constants.MOVES_ARTILLERY_LINE; } if (UnitStance == stanceEnum.Column) { moveOffset = Constants.MOVES_ARTILLERY_COLUMN; } break; default: moveOffset = 0; break; } return(moveOffset); }
public void changeUnitStance(ref MapUnit[] playerUnits, int thisUnit, stanceEnum toStance) { lastUnit1 = (MapUnit)playerUnits[thisUnit].Clone(); lastUnit2 = null; lastMove = enumMoveType.Stance; lastU1 = thisUnit; lastU2 = -1; lastResult1 = EnumResult.Nothing; lastResult2 = EnumResult.Nothing; lastUnit1Damage = 0; lastUnit2Damage = 0; lastCalc1 = ""; lastCalc2 = ""; playerUnits[thisUnit].stanceUnit = toStance; }
public void showUnit(stanceEnum stance, unitEnum unitType, playerEnum player, int support, int strength, int morale, int training, string description, int won, int x, int y, Image image, string currentPlayer) { if (strength == -1) { labelX.Text = ""; labelX.Text = ""; labelY.Text = ""; labelUnitDescription.Text = ""; labelUnitWon.Text = ""; labelUnitStance.Text = ""; labelUnitSupport.Text = ""; labelUnitStrength.Text = ""; labelUnitMorale.Text = ""; labelUnitTraining.Text = ""; labelUnitType.Text = ""; labelPlayerName.Text = ""; this.pictureUnit.Image = image; this.pictureUnit.Visible = false; } else { labelX.Text = "X: " + x.ToString(); labelY.Text = "Y: " + y.ToString(); labelUnitDescription.Text = description; labelUnitWon.Text = "Battles Won: " + won.ToString(); labelUnitStance.Text = "Stance: " + stance.ToString(); labelUnitSupport.Text = "Support: " + support.ToString(); labelUnitStrength.Text = "Strength: " + strength.ToString(); labelUnitMorale.Text = "Morale: " + morale.ToString(); labelUnitTraining.Text = "Training: " + training.ToString(); labelUnitType.Text = "Unit Type: " + unitType.ToString(); labelPlayerName.Text = currentPlayer; this.pictureUnit.Image = image; this.pictureUnit.Visible = true; } }
// using minimax type of algorithm public int makeMove(ref MapUnit[] playerUnits, playerEnum player, int maxUnits, int thisDepth, int maxDepth, int bestWeight) { traceProgress("makeMove() - *** DEPTH *** " + thisDepth.ToString() + " bestweight:" + bestWeight.ToString()); // already got end-condition, then this recurse not needed if (bestWeight == Constants.MAXIMUM_WEIGHT) { return(Constants.MINIMUM_WEIGHT); } if (modelBattleEngine == null) { modelBattleEngine = new BattleEngine(); modelBattleEngine.newBattle(mapX, mapY); } MapUnit[] modelUnits = new MapUnit[maxUnits]; for (int mu = 0; mu < maxUnits; mu++) { modelUnits[mu] = (MapUnit)playerUnits[mu].Clone(); } if (thisDepth == 0) { movesConsidered = 0; deadUnits = modelBattleEngine.countDeadUnits(ref modelUnits, player, maxUnits); bestU = -1; bestF = -1; bestX = -1; bestY = -1; bestMoveType = enumMoveType.Nothing; bestStance = stanceEnum.Nothing; traceProgress("makeMove() - *** INITIALISE *** max:" + mapX.ToString() + "," + mapY.ToString()); } int startingWeight = calculateWeight(ref modelUnits, ref modelBattleEngine, player, maxUnits); traceProgress("makeMove() - startingWeight:" + startingWeight.ToString()); int u = 0; while (u < maxUnits && bestWeight != Constants.MAXIMUM_WEIGHT) { if (player == modelUnits[u].player && modelUnits[u].strength > 0) { traceProgress("makeMove() - UNIT:" + modelUnits[u].description); // Moves int moveOffset = modelBattleEngine.possibleMoves(modelUnits[u].typeUnit, modelUnits[u].stanceUnit); int startX = modelUnits[u].x - moveOffset; int endX = modelUnits[u].x + moveOffset; if (startX < 0) { startX = 0; } if (endX >= mapX) { endX = mapX - 1; } for (int i = startX; i <= endX; i++) { int startY = modelUnits[u].y - moveOffset; int endY = modelUnits[u].y + moveOffset; if (startY < 0) { startY = 0; } if (endY >= mapY) { endY = mapY - 1; } for (int j = startY; j <= endY; j++) { if (bestWeight != Constants.MAXIMUM_WEIGHT) { playerEnum enemyPlayer = (player == playerEnum.Red)? playerEnum.Blue : playerEnum.Red; int livingEnemyBefore = modelBattleEngine.countLivingUnits(ref modelUnits, enemyPlayer, maxUnits); MapUnit oldUnit = (MapUnit)modelUnits[u].Clone(); MapUnit oldAttackedUnit = null; int nearestEnemyBefore = modelBattleEngine.findNearestFriend(ref modelUnits, u, maxUnits, true); int nearestEnemyDistanceBefore = modelBattleEngine.calculateDistance(ref modelUnits, nearestEnemyBefore, u); int f = modelBattleEngine.findUnit(ref modelUnits, i, j, maxUnits); int playerWeight = Constants.MINIMUM_WEIGHT; bool noChange = false; if (f > -1) { if (f != u && modelUnits[f].player != modelUnits[u].player && modelUnits[f].strength > 0) { movesConsidered++; // nearby enemy unit, try attacking oldAttackedUnit = (MapUnit)modelUnits[f].Clone(); modelUnits[u].x = i; modelUnits[u].y = j; modelBattleEngine.fightUnits(ref modelUnits, u, f, maxUnits, false); traceProgress("makeMove() - Attack:" + modelUnits[f].description); } else { noChange = true; } } else { movesConsidered++; // empty square, so try moving modelUnits[u].x = i; modelUnits[u].y = j; traceProgress("makeMove() - Move:" + i.ToString() + "," + j.ToString()); } if (noChange == false) { if (thisDepth < maxDepth) { if (pruneFar == true) { // stop moves away from enemy int nearestEnemyAfter = modelBattleEngine.findNearestFriend(ref modelUnits, u, maxUnits, true); int nearestEnemyDistanceAfter = modelBattleEngine.calculateDistance(ref modelUnits, nearestEnemyAfter, u); if (nearestEnemyDistanceAfter > nearestEnemyDistanceBefore) { playerWeight = Constants.MINIMUM_WEIGHT; } else { // if not at maxDepth, then recurse for unpruned tree playerWeight = makeMove(ref modelUnits, player, maxUnits, thisDepth + 1, maxDepth, bestWeight); } } else { // if all enemy dead, then this is end condition! int livingEnemyAfter = modelBattleEngine.countLivingUnits(ref modelUnits, enemyPlayer, maxUnits); if (livingEnemyAfter <= 0) { playerWeight = Constants.MAXIMUM_WEIGHT; } else { // if not at maxDepth, then recurse playerWeight = makeMove(ref modelUnits, player, maxUnits, thisDepth + 1, maxDepth, bestWeight); if (livingEnemyAfter < livingEnemyBefore) { playerWeight++; } } } traceProgress("makeMove() - RecursedWeight:" + playerWeight.ToString()); } else { // finally at max depth, what is the weighting? playerWeight = calculateWeight(ref modelUnits, ref modelBattleEngine, player, maxUnits); traceProgress("makeMove() - playerWeight:" + playerWeight.ToString()); } if (playerWeight > bestWeight) { if (f > -1) { if (modelUnits[u].player != modelUnits[f].player) { bestWeight = playerWeight; bestX = i; bestY = j; bestU = u; bestF = f; bestMoveType = enumMoveType.Attack; traceProgress("makeMove() - Set bestWeight:" + playerWeight.ToString()); traceProgress("makeMove() - To Attack:" + modelUnits[f].description); } } else { bestWeight = playerWeight; bestX = i; bestY = j; bestU = u; bestF = -1; bestMoveType = enumMoveType.Move; traceProgress("makeMove() - Set bestWeight:" + playerWeight.ToString()); traceProgress("makeMove() - To Move:" + i.ToString() + "," + j.ToString()); } } } // undo hypothetical move modelUnits[u] = (MapUnit)oldUnit.Clone(); // undo hypothetical attack if (f > -1 && oldAttackedUnit != null) { modelUnits[f] = (MapUnit)oldAttackedUnit.Clone(); } } } // try changing stance int stanceWeight = Constants.MINIMUM_WEIGHT; int numberStances = 0; MapUnit oldStanceUnit = (MapUnit)modelUnits[u].Clone(); switch (modelUnits[u].typeUnit) { case (unitEnum.Artillery): numberStances = 2; break; case (unitEnum.Cavalry): numberStances = 2; break; case (unitEnum.Infantry): numberStances = 3; break; default: numberStances = 0; break; } int us = 1; while (us <= numberStances) { bool stanceChange = false; stanceEnum currentStance = stanceEnum.Nothing; switch (us) { case (1): if (modelUnits[u].stanceUnit != stanceEnum.Line) { modelUnits[u].stanceUnit = stanceEnum.Line; currentStance = stanceEnum.Line; stanceChange = true; } break; case (2): if (modelUnits[u].stanceUnit != stanceEnum.Column) { //modelUnits[u].stanceUnit = stanceEnum.Column; //currentStance = stanceEnum.Column; //stanceChange = true; } break; case (3): if (modelUnits[u].stanceUnit != stanceEnum.Square) { modelUnits[u].stanceUnit = stanceEnum.Square; currentStance = stanceEnum.Square; stanceChange = true; } break; } if (stanceChange == false) { stanceWeight = Constants.MINIMUM_WEIGHT; } else { traceProgress("makeMove() - Set stance:" + currentStance.ToString()); movesConsidered++; if (thisDepth < maxDepth) { stanceWeight = makeMove(ref modelUnits, player, maxUnits, thisDepth + 1, maxDepth, bestWeight); traceProgress("makeMove() - recursedWeight:" + stanceWeight.ToString()); } else { stanceWeight = calculateWeight(ref modelUnits, ref modelBattleEngine, player, maxUnits); traceProgress("makeMove() - stanceWeight:" + stanceWeight.ToString()); } } if (stanceWeight > bestWeight && currentStance != stanceEnum.Nothing) { bestWeight = stanceWeight; bestU = u; bestStance = currentStance; bestMoveType = enumMoveType.Stance; traceProgress("makeMove() - Set bestWeight:" + stanceWeight.ToString()); traceProgress("makeMove() - stance:" + currentStance.ToString()); } // undo hypothetical stance change modelUnits[u] = (MapUnit)oldStanceUnit.Clone(); us++; } // try firing at all nearby units int fireWeight = Constants.MINIMUM_WEIGHT; int fireOffset = modelBattleEngine.possibleFire(modelUnits[u].typeUnit, modelUnits[u].stanceUnit); if (fireOffset > 0) { int uf = 0; while (uf < maxUnits && bestWeight != Constants.MAXIMUM_WEIGHT) { if (modelUnits[u].player != modelUnits[uf].player && modelUnits[uf].strength > 0) { playerEnum enemyPlayer = (player == playerEnum.Red)? playerEnum.Blue : playerEnum.Red; int livingEnemyBefore = modelBattleEngine.countLivingUnits(ref modelUnits, enemyPlayer, maxUnits); MapUnit oldFireUnit = (MapUnit)modelUnits[uf].Clone(); movesConsidered++; traceProgress("makeMove() - Fire At:" + modelUnits[uf].description); int distanceFire = modelBattleEngine.calculateDistance(ref modelUnits, uf, u); if (distanceFire <= fireOffset) { traceProgress("makeMove() - Distance:" + distanceFire.ToString()); modelBattleEngine.fireAtUnit(ref modelUnits, u, uf, maxUnits, false); if (thisDepth < maxDepth) { // if all enemy dead, then this is end condition! int livingEnemyAfter = modelBattleEngine.countLivingUnits(ref modelUnits, enemyPlayer, maxUnits); if (livingEnemyAfter <= 0) { fireWeight = Constants.MAXIMUM_WEIGHT; } else { // if not at maxDepth, then recurse fireWeight = makeMove(ref modelUnits, player, maxUnits, thisDepth + 1, maxDepth, bestWeight); if (livingEnemyAfter < livingEnemyBefore) { fireWeight++; } } traceProgress("makeMove() - recursedWeight:" + fireWeight.ToString()); } else { fireWeight = calculateWeight(ref modelUnits, ref modelBattleEngine, player, maxUnits); traceProgress("makeMove() - fireWeight:" + fireWeight.ToString()); } if (fireWeight > bestWeight) { bestWeight = fireWeight; bestU = u; bestF = uf; bestMoveType = enumMoveType.Fire; traceProgress("makeMove() - Set Fire:" + modelUnits[uf].description); } // undo hypothetical fire modelUnits[uf] = (MapUnit)oldFireUnit.Clone(); } } uf++; } } } } u++; } if (bestU > -1 && thisDepth == 0) { bool moveMade = false; traceProgress("makeMove() - *** MAKE COMPUTER MOVE ***"); switch (bestMoveType) { case (enumMoveType.Move): if (bestX > -1 && bestY > -1) { modelBattleEngine.moveUnit(ref playerUnits, bestU, bestX, bestY); moveMade = true; traceProgress("makeMove() - *** MOVE UNIT ***"); traceProgress("makeMove() - " + playerUnits[bestU].description + " to " + bestX.ToString() + "," + bestY.ToString()); } break; case (enumMoveType.Attack): if (bestX > -1 && bestY > -1) { playerUnits[bestU].x = bestX; playerUnits[bestU].y = bestY; modelBattleEngine.fightUnits(ref playerUnits, bestU, bestF, maxUnits, true); moveMade = true; traceProgress("makeMove() - *** ATTACK UNIT ***"); traceProgress("makeMove() - " + playerUnits[bestU].description + " to " + playerUnits[bestF].description); } break; case (enumMoveType.Fire): modelBattleEngine.fireAtUnit(ref playerUnits, bestU, bestF, maxUnits, true); moveMade = true; traceProgress("makeMove() - *** FIRE ON UNIT ***"); traceProgress("makeMove() - " + playerUnits[bestU].description + " to " + playerUnits[bestF].description); break; case (enumMoveType.Stance): modelBattleEngine.changeUnitStance(ref playerUnits, bestU, bestStance); moveMade = true; traceProgress("makeMove() - *** CHANGE STANCE ***"); traceProgress("makeMove() - " + playerUnits[bestU].description + " to " + bestStance.ToString()); break; default: traceProgress("makeMove() - *** ERROR - DEFAULT CASE ***"); moveMade = false; break; } traceProgress("makeMove() - moves considered:" + movesConsidered.ToString()); Debug.Assert(moveMade == true, "No move made", "madeMove() failed to create a move!"); if (moveMade == false) { bestWeight = Constants.MINIMUM_WEIGHT; } } traceProgress("makeMove() - return weight:" + bestWeight.ToString()); return(bestWeight); }