// Returns a TradeOffer if the trade is valid; If the ratio is not 4:1 or player does not have enough resources, returns null public TradeOffer generateAITradeWithBank(AIEngine.Objective objective) { if (debugMessages) { GameEngine.print("-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#- BANK TRADE REQUEST -#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-"); } return(BuildTradeWithBank(objective.GetCardDifferential())); }
// Returns a TradeOffer if the trade is valid (an identical request has not recently been made); If this is not true, returns null public TradeOffer generateAITradeRequest(int currentTurn, AIEngine.Objective objective) { TradeOffer trade = BuildFairTrade(currentTurn, objective.GetCardDifferential()); if (trade.TotalGetResources() > 1 && trade.TotalGiveResources() > 1) { trade.RandomUnequalizeTrade(); // Introduces an element of randomness to the trade algorithm } if (debugMessages) { GameEngine.print("PLAYER HAND: \n" + hand.brick + " BRICK\n" + hand.ore + " ORE\n" + hand.wood + " WOOD\n" + hand.grain + " GRAIN\n" + hand.sheep + " SHEEP"); GameEngine.print("CARDS NEEDED: \n" + objective.GetCardsNeeded().brick + " BRICK\n" + objective.GetCardsNeeded().ore + " ORE\n" + objective.GetCardsNeeded().wood + " WOOD\n" + objective.GetCardsNeeded().grain + " GRAIN\n" + objective.GetCardsNeeded().sheep + " SHEEP"); GameEngine.print("CARD DIFFERENTIAL: \n" + objective.GetCardsNeeded().GetHandSize() + " CARDS NEEDED\n" + objective.GetCardDifferential().brick + " BRICK\n" + objective.GetCardDifferential().ore + " ORE\n" + objective.GetCardDifferential().wood + " WOOD\n" + objective.GetCardDifferential().grain + " GRAIN\n" + objective.GetCardDifferential().sheep + " SHEEP"); } if (GetPermissionToRetryTradeRequest(currentTurn, trade)) { return(trade); } return(null); }
/* * Handles interactions with game FSM and player input. */ void Update() { Player currentTurnPlayer = gamestate.GetCurrentTurnPlayer (); UpdateHumanCardCounts (); long elapsedTicksSinceLastAIAction = DateTime.Now.Ticks - lastAIActionTime.Ticks; double secondsSinceLastAIAction = new TimeSpan(elapsedTicksSinceLastAIAction).TotalSeconds; //AI Interaction if (currentTurnPlayer.isAI) { if (secondsSinceLastAIAction >= FORCED_TIME_BETWEEN_AI_ACTIONS) { System.Random rand = new System.Random(); //Initial settlement placement if (curState == GameState.State.placeSettlement) { List<Node> locationOptions = AIEngine.GetFavorableStartingLocations(board); //Attempt to place elements in decreasing score order for (int i = 0; i < locationOptions.Count; i++) { if (board.CanBuildSettlementHere(locationOptions[i].visual.transform, currentTurnPlayer, true)) { lastStructurePlaced = board.PlaceSettlement(locationOptions[i].visual.transform, currentTurnPlayer, false); break; } } IncrementState (); UpdateTurnInfo("Placing Initial Road", currentTurnPlayer.id); } //Initial road placement else if (curState == GameState.State.placeRoad) { List<Edge> favorableRoads = AIEngine.GetFavorableRoadExpansions(currentTurnPlayer, board, lastStructurePlaced); foreach (Edge road in favorableRoads) { if (board.CanBuildRoadHere(road.visual.transform, currentTurnPlayer)) { lastRoadPlaced = board.PlaceRoad(road.visual.transform, currentTurnPlayer, false); break; } } IncrementState (); } //Roll dice else if (curState == GameState.State.roll) { if (rollForAI) { if (Input.GetMouseButtonDown (0)) { Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition); RaycastHit hit; if (interactDebug) { print ("mouse press"); } if (Physics.Raycast (ray, out hit)) { if (hit.transform == dice.transform) { IncrementState (); updateDice(); } } } } else { IncrementState (); updateDice(); } } //Trade with players else if (curState == GameState.State.trade) { proposedObjective = null; if(debugMessages) { print ("~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~"); } //TODO List<AIEngine.Objective> objectives = AIEngine.GetObjectives(currentTurnPlayer, board, gamestate); // Trade With Other Players int tradeOffersThisTurn = 0; bool hasAnyOfferBeenAccepted = false; foreach(AIEngine.Objective objective in objectives) { if(objective.Score () > 0 && objective.TotalCardsNeeded() > 0 && tradeOffersThisTurn < 3 && !hasAnyOfferBeenAccepted) { TradeOffer offer = currentTurnPlayer.generateAITradeRequest(gamestate.getTurnCounter(), objective); if(null != offer) { if(debugMessages) { print ("TRADENUM: " + tradeOffersThisTurn + " | " + gamestate.GetCurrentTurnPlayer() + "\nATTEMPTING TO TRADE WITH OTHER PLAYERS TO ACHIEVE OBJECT: " + objective.GetObjectiveScore()); } tradeOffersThisTurn++; hasAnyOfferBeenAccepted = tradeManager.ExecuteTradeOfferNotification(offer); proposedObjective = objective; } } } // Trade With Bank foreach(AIEngine.Objective objective in objectives) { if(objective.Score () > 0 && objective.TotalCardsNeeded() > 0 && !hasAnyOfferBeenAccepted) { if(debugMessages) { print (gamestate.GetCurrentTurnPlayer() + " ATTEMPTING TO TRADE WITH BANK"); } TradeOffer offer = currentTurnPlayer.generateAITradeWithBank(objective); if(null != offer) { tradeManager.ExecuteTradeWithBank(offer, gamestate.GetCurrentTurnPlayer()); hasAnyOfferBeenAccepted = true; } } } if(!hasAnyOfferBeenAccepted && debugMessages) { print (gamestate.GetCurrentTurnPlayer() + " MADE NO TRADES THIS TURN"); } IncrementState(); FORCED_TIME_BETWEEN_AI_ACTIONS = 0f; //TODO Remove } //Building phase else if (curState == GameState.State.place) { FORCED_TIME_BETWEEN_AI_ACTIONS = 0f; //TODO Remove //TODO List<AIEngine.Objective> objectives = AIEngine.GetObjectives(currentTurnPlayer, board, gamestate); foreach (AIEngine.Objective objective in objectives) { print (objective); } foreach (AIEngine.Objective objective in objectives) { if (objective.TotalCardsNeeded() == 0) { AIEngine.PerformObjective(objective, board); break; } } /*//Attempt main objective that we traded for if (proposedObjective != null) { AIEngine.PerformObjective(proposedObjective, board); } //Attempt to get -any- objective to work else { List<AIEngine.Objective> objectives = AIEngine.GetObjectives(currentTurnPlayer, board, gamestate); foreach (AIEngine.Objective objective in objectives) { if (AIEngine.PerformObjective(objective, board)) { break; } } }*/ IncrementState(); } //Place robber else if (curState == GameState.State.robber) { Player competitorPlayer = gamestate.BiggestCompetitorToPlayer(currentTurnPlayer); List<Tile> possiblePlacements = AIEngine.GetListOfRobberPlacements(currentTurnPlayer, competitorPlayer, board); bool robberPlaced = false; //Attempt to place robber on recommended tiles foreach (Tile tile in possiblePlacements) { int index = board.tiles.IndexOf (tile); if (board.PlaceRobber (board.tileHitboxes[index].transform)) { robberPlaced = true; break; } } //If for some reason we're out of recommendations... while (!robberPlaced) { print ("ERROR: ATTEMPTING TO RANDOMLY PLACE ROBBER!"); int tileIndex = rand.Next (board.tiles.Count); robberPlaced = board.PlaceRobber (board.tileHitboxes[tileIndex].transform); } IncrementState(); } lastAIActionTime = DateTime.Now; //Prevent AI from acting too quickly } } //Human Interaction else { if (Input.GetMouseButtonDown (0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (interactDebug) { print ("mouse press"); } if (Physics.Raycast(ray, out hit)) { //Need to place something if (curState == GameState.State.placeSettlement || curState == GameState.State.placeRoad || curState == GameState.State.place) { bool isSetup = (curState == GameState.State.placeSettlement || curState == GameState.State.placeRoad); //Choose what to build or use preselected if (curState == GameState.State.place) { if( hit.transform == roadSelector.transform && currentTurnPlayer.CanBuildRoad()){ objectToBuild = hit.transform; if (interactDebug) { print ("on a building"); } } else if (hit.transform == citySelector.transform && currentTurnPlayer.CanBuildCity()){ objectToBuild = hit.transform; if (interactDebug) { print ("on a building"); } } else if (hit.transform == settlementSelector.transform && currentTurnPlayer.CanBuildSettlement()){ objectToBuild = hit.transform; if (interactDebug) { print ("on a building"); } } else if (hit.transform == endTurnButton.transform){ IncrementState(); } } else if (curState == GameState.State.placeSettlement) { objectToBuild = settlementSelector.transform; } else if (curState == GameState.State.placeRoad) { objectToBuild = roadSelector.transform; } if(objectToBuild != null) { if (objectToBuild == roadSelector.transform && board.roadHitboxes.ContainsKey(hit.transform)) { Node structureToBuildNear = (curState == GameState.State.placeRoad) ? lastStructurePlaced : null; if(board.CanBuildRoadHere(hit.transform, currentTurnPlayer, structureToBuildNear, true)) { lastRoadPlaced = board.PlaceRoad(hit.transform, currentTurnPlayer, !isSetup); objectToBuild = null; if (interactDebug) { print ("road built!"); } if (curState == GameState.State.placeRoad) { IncrementState (); } } } else if(objectToBuild == settlementSelector.transform && board.settlementHitboxes.ContainsKey(hit.transform)) { if(board.CanBuildSettlementHere(hit.transform, currentTurnPlayer, isSetup, true)){ lastStructurePlaced = board.PlaceSettlement(hit.transform, currentTurnPlayer, !isSetup); objectToBuild = null; if (interactDebug) { print ("settlement built!"); } if (curState == GameState.State.placeSettlement) { IncrementState (); } } } else if (objectToBuild == citySelector.transform && board.settlements.ContainsKey(hit.transform)) { if(board.CanBuildCityHere(hit.transform, currentTurnPlayer, true)){ lastStructurePlaced = board.PlaceCity(hit.transform, currentTurnPlayer); objectToBuild = null; if (interactDebug) { print ("city built!"); } } } } } //Place robber on a chit else if (curState == GameState.State.robber) { if (board.PlaceRobber(hit.transform)) { IncrementState (); //increment if successfully placed } } //Request trades with other players or bank else if (curState == GameState.State.trade) { UpdateTradePanel (hit.transform); if(hit.transform == endTradeButton.transform){ IncrementState(); } else if (hit.transform == offerTradeButton.transform) { OfferTrade(); } else if (hit.transform == endTurnButton.transform){ IncrementState (); IncrementState (); } //tradeManager.ExecuteTradeWithBank(offer, gamestate.GetCurrentTurnPlayer()); } //listen for click on dice else if (curState == GameState.State.roll ) { if (interactDebug) { print (hit.transform == dice.transform); } if (hit.transform == dice.transform) { IncrementState (); updateDice (); } } else { if (interactDebug) { print ("should not be here"); } } } } } }
/* * Handles interactions with game FSM and player input. */ void Update() { Player currentTurnPlayer = gamestate.GetCurrentTurnPlayer(); UpdateHumanCardCounts(); long elapsedTicksSinceLastAIAction = DateTime.Now.Ticks - lastAIActionTime.Ticks; double secondsSinceLastAIAction = new TimeSpan(elapsedTicksSinceLastAIAction).TotalSeconds; //AI Interaction if (currentTurnPlayer.isAI) { if (secondsSinceLastAIAction >= FORCED_TIME_BETWEEN_AI_ACTIONS) { System.Random rand = new System.Random(); //Initial settlement placement if (curState == GameState.State.placeSettlement) { List <Node> locationOptions = AIEngine.GetFavorableStartingLocations(board); //Attempt to place elements in decreasing score order for (int i = 0; i < locationOptions.Count; i++) { if (board.CanBuildSettlementHere(locationOptions[i].visual.transform, currentTurnPlayer, true)) { lastStructurePlaced = board.PlaceSettlement(locationOptions[i].visual.transform, currentTurnPlayer, false); break; } } IncrementState(); UpdateTurnInfo("Placing Initial Road", currentTurnPlayer.id); } //Initial road placement else if (curState == GameState.State.placeRoad) { List <Edge> favorableRoads = AIEngine.GetFavorableRoadExpansions(currentTurnPlayer, board, lastStructurePlaced); foreach (Edge road in favorableRoads) { if (board.CanBuildRoadHere(road.visual.transform, currentTurnPlayer)) { lastRoadPlaced = board.PlaceRoad(road.visual.transform, currentTurnPlayer, false); break; } } IncrementState(); } //Roll dice else if (curState == GameState.State.roll) { if (rollForAI) { if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (interactDebug) { print("mouse press"); } if (Physics.Raycast(ray, out hit)) { if (hit.transform == dice.transform) { IncrementState(); updateDice(); } } } } else { IncrementState(); updateDice(); } } //Trade with players else if (curState == GameState.State.trade) { proposedObjective = null; if (debugMessages) { print("~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~"); } //TODO List <AIEngine.Objective> objectives = AIEngine.GetObjectives(currentTurnPlayer, board, gamestate); // Trade With Other Players int tradeOffersThisTurn = 0; bool hasAnyOfferBeenAccepted = false; foreach (AIEngine.Objective objective in objectives) { if (objective.Score() > 0 && objective.TotalCardsNeeded() > 0 && tradeOffersThisTurn < 3 && !hasAnyOfferBeenAccepted) { TradeOffer offer = currentTurnPlayer.generateAITradeRequest(gamestate.getTurnCounter(), objective); if (null != offer) { if (debugMessages) { print("TRADENUM: " + tradeOffersThisTurn + " | " + gamestate.GetCurrentTurnPlayer() + "\nATTEMPTING TO TRADE WITH OTHER PLAYERS TO ACHIEVE OBJECT: " + objective.GetObjectiveScore()); } tradeOffersThisTurn++; hasAnyOfferBeenAccepted = tradeManager.ExecuteTradeOfferNotification(offer); proposedObjective = objective; } } } // Trade With Bank foreach (AIEngine.Objective objective in objectives) { if (objective.Score() > 0 && objective.TotalCardsNeeded() > 0 && !hasAnyOfferBeenAccepted) { if (debugMessages) { print(gamestate.GetCurrentTurnPlayer() + " ATTEMPTING TO TRADE WITH BANK"); } TradeOffer offer = currentTurnPlayer.generateAITradeWithBank(objective); if (null != offer) { tradeManager.ExecuteTradeWithBank(offer, gamestate.GetCurrentTurnPlayer()); hasAnyOfferBeenAccepted = true; } } } if (!hasAnyOfferBeenAccepted && debugMessages) { print(gamestate.GetCurrentTurnPlayer() + " MADE NO TRADES THIS TURN"); } IncrementState(); FORCED_TIME_BETWEEN_AI_ACTIONS = 0f; //TODO Remove } //Building phase else if (curState == GameState.State.place) { FORCED_TIME_BETWEEN_AI_ACTIONS = 0f; //TODO Remove //TODO List <AIEngine.Objective> objectives = AIEngine.GetObjectives(currentTurnPlayer, board, gamestate); foreach (AIEngine.Objective objective in objectives) { print(objective); } foreach (AIEngine.Objective objective in objectives) { if (objective.TotalCardsNeeded() == 0) { AIEngine.PerformObjective(objective, board); break; } } /*//Attempt main objective that we traded for * if (proposedObjective != null) { * AIEngine.PerformObjective(proposedObjective, board); * } * //Attempt to get -any- objective to work * else { * List<AIEngine.Objective> objectives = AIEngine.GetObjectives(currentTurnPlayer, board, gamestate); * foreach (AIEngine.Objective objective in objectives) { * if (AIEngine.PerformObjective(objective, board)) { * break; * } * } * }*/ IncrementState(); } //Place robber else if (curState == GameState.State.robber) { Player competitorPlayer = gamestate.BiggestCompetitorToPlayer(currentTurnPlayer); List <Tile> possiblePlacements = AIEngine.GetListOfRobberPlacements(currentTurnPlayer, competitorPlayer, board); bool robberPlaced = false; //Attempt to place robber on recommended tiles foreach (Tile tile in possiblePlacements) { int index = board.tiles.IndexOf(tile); if (board.PlaceRobber(board.tileHitboxes[index].transform)) { robberPlaced = true; break; } } //If for some reason we're out of recommendations... while (!robberPlaced) { print("ERROR: ATTEMPTING TO RANDOMLY PLACE ROBBER!"); int tileIndex = rand.Next(board.tiles.Count); robberPlaced = board.PlaceRobber(board.tileHitboxes[tileIndex].transform); } IncrementState(); } lastAIActionTime = DateTime.Now; //Prevent AI from acting too quickly } } //Human Interaction else { if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (interactDebug) { print("mouse press"); } if (Physics.Raycast(ray, out hit)) { //Need to place something if (curState == GameState.State.placeSettlement || curState == GameState.State.placeRoad || curState == GameState.State.place) { bool isSetup = (curState == GameState.State.placeSettlement || curState == GameState.State.placeRoad); //Choose what to build or use preselected if (curState == GameState.State.place) { if (hit.transform == roadSelector.transform && currentTurnPlayer.CanBuildRoad()) { objectToBuild = hit.transform; if (interactDebug) { print("on a building"); } } else if (hit.transform == citySelector.transform && currentTurnPlayer.CanBuildCity()) { objectToBuild = hit.transform; if (interactDebug) { print("on a building"); } } else if (hit.transform == settlementSelector.transform && currentTurnPlayer.CanBuildSettlement()) { objectToBuild = hit.transform; if (interactDebug) { print("on a building"); } } else if (hit.transform == endTurnButton.transform) { IncrementState(); } } else if (curState == GameState.State.placeSettlement) { objectToBuild = settlementSelector.transform; } else if (curState == GameState.State.placeRoad) { objectToBuild = roadSelector.transform; } if (objectToBuild != null) { if (objectToBuild == roadSelector.transform && board.roadHitboxes.ContainsKey(hit.transform)) { Node structureToBuildNear = (curState == GameState.State.placeRoad) ? lastStructurePlaced : null; if (board.CanBuildRoadHere(hit.transform, currentTurnPlayer, structureToBuildNear, true)) { lastRoadPlaced = board.PlaceRoad(hit.transform, currentTurnPlayer, !isSetup); objectToBuild = null; if (interactDebug) { print("road built!"); } if (curState == GameState.State.placeRoad) { IncrementState(); } } } else if (objectToBuild == settlementSelector.transform && board.settlementHitboxes.ContainsKey(hit.transform)) { if (board.CanBuildSettlementHere(hit.transform, currentTurnPlayer, isSetup, true)) { lastStructurePlaced = board.PlaceSettlement(hit.transform, currentTurnPlayer, !isSetup); objectToBuild = null; if (interactDebug) { print("settlement built!"); } if (curState == GameState.State.placeSettlement) { IncrementState(); } } } else if (objectToBuild == citySelector.transform && board.settlements.ContainsKey(hit.transform)) { if (board.CanBuildCityHere(hit.transform, currentTurnPlayer, true)) { lastStructurePlaced = board.PlaceCity(hit.transform, currentTurnPlayer); objectToBuild = null; if (interactDebug) { print("city built!"); } } } } } //Place robber on a chit else if (curState == GameState.State.robber) { if (board.PlaceRobber(hit.transform)) { IncrementState(); //increment if successfully placed } } //Request trades with other players or bank else if (curState == GameState.State.trade) { UpdateTradePanel(hit.transform); if (hit.transform == endTradeButton.transform) { IncrementState(); } else if (hit.transform == offerTradeButton.transform) { OfferTrade(); } else if (hit.transform == endTurnButton.transform) { IncrementState(); IncrementState(); } //tradeManager.ExecuteTradeWithBank(offer, gamestate.GetCurrentTurnPlayer()); } //listen for click on dice else if (curState == GameState.State.roll) { if (interactDebug) { print(hit.transform == dice.transform); } if (hit.transform == dice.transform) { IncrementState(); updateDice(); } } else { if (interactDebug) { print("should not be here"); } } } } } }