src/ai/api/ai_transactionmode.cpp
branchnoai
changeset 9474 2b53e154a8d5
child 9486 a9b5f6b8667c
equal deleted inserted replaced
9473:dcbcd1c4496d 9474:2b53e154a8d5
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file ai_transactionmode.cpp class to switch the AI to Transaction mode */
       
     4 
       
     5 #include "ai_transactionmode.hpp"
       
     6 #include "ai_execmode.hpp"
       
     7 #include "../../command.h"
       
     8 #include "../../debug.h"
       
     9 #include <stack>
       
    10 
       
    11 bool AITransactionMode::ModeProc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, int32 costs)
       
    12 {
       
    13 	AITransactionMode *instance = (AITransactionMode *)AIObject::GetDoCommandModeInstance();
       
    14 	/* Don't record if we are stopped */
       
    15 	if (instance->stopped) return false;
       
    16 	AITransactionModeCommand command;
       
    17 
       
    18 	/* Store all params in a nice list, so we can execute them later */
       
    19 	command.tile  = tile;
       
    20 	command.p1    = p1;
       
    21 	command.p2    = p2;
       
    22 	command.flags = flags;
       
    23 	command.procc = procc;
       
    24 	command.text  = (_cmd_text == NULL) ? NULL : strdup(_cmd_text);
       
    25 	instance->command_stack.push(command);
       
    26 	instance->costs += costs;
       
    27 
       
    28 	/* Now we return 'false', as we don't want to execute the commands just yet */
       
    29 	return false;
       
    30 }
       
    31 
       
    32 AITransactionMode::AITransactionMode()
       
    33 {
       
    34 	this->costs         = 0;
       
    35 	this->stopped       = false;
       
    36 	this->last_mode     = this->GetDoCommandMode();
       
    37 	this->last_instance = this->GetDoCommandModeInstance();
       
    38 	this->SetDoCommandMode(&AITransactionMode::ModeProc, this);
       
    39 }
       
    40 
       
    41 AITransactionMode::~AITransactionMode()
       
    42 {
       
    43 	this->SetDoCommandMode(this->last_mode, this->last_instance);
       
    44 
       
    45 	/* Clean up the command_stack nicely (as in: free the cmd_text) */
       
    46 	AITransactionModeCommand command;
       
    47 	while (!this->command_stack.empty()) {
       
    48 		command = this->command_stack.front();
       
    49 		free(command.text);
       
    50 		this->command_stack.pop();
       
    51 	}
       
    52 
       
    53 	/* Clean up the reverse_stack too */
       
    54 	while (!this->reverse_stack.empty()) {
       
    55 		command = this->reverse_stack.front();
       
    56 		free(command.text);
       
    57 		this->reverse_stack.pop();
       
    58 	}
       
    59 }
       
    60 
       
    61 bool AITransactionMode::Execute()
       
    62 {
       
    63 	/* Make sure we are stopped */
       
    64 	this->Stop();
       
    65 
       
    66 	/* Switch to a forced execute mode */
       
    67 	AIExecMode exec;
       
    68 
       
    69 	/* Reverse stack should be empty */
       
    70 	assert(this->reverse_stack.empty());
       
    71 
       
    72 	AITransactionModeCommand command;
       
    73 	while (!this->command_stack.empty()) {
       
    74 		command = this->command_stack.front();
       
    75 		_cmd_text = command.text;
       
    76 		/* Make sure we return 'false' if the command fails to execute. This allows rollback of failed builds. */
       
    77 		if (!this->DoCommand(command.tile, command.p1, command.p2, command.flags, command.procc)) return false;
       
    78 		/* Add the command to the reverse stack */
       
    79 		this->reverse_stack.push(command);
       
    80 		/* Remove the item from the list */
       
    81 		this->command_stack.pop();
       
    82 	}
       
    83 
       
    84 	/* Everything went okay, clean the reverse stack */
       
    85 	while (!this->reverse_stack.empty()) {
       
    86 		command = this->reverse_stack.front();
       
    87 		free(command.text);
       
    88 		this->reverse_stack.pop();
       
    89 	}
       
    90 
       
    91 	/* Reverse stack should be empty again */
       
    92 	assert(this->reverse_stack.empty());
       
    93 
       
    94 	return true;
       
    95 }
       
    96 
       
    97 void AITransactionMode::Stop()
       
    98 {
       
    99 	this->stopped = true;
       
   100 }
       
   101 
       
   102 void AITransactionMode::Rollback()
       
   103 {
       
   104 	AITransactionModeCommand command;
       
   105 
       
   106 	DEBUG(ai, 0, "AITransactionMode::Rollback is not yet implemented");
       
   107 	return;
       
   108 
       
   109 	while (!this->reverse_stack.empty()) {
       
   110 		command = this->reverse_stack.front();
       
   111 		_cmd_text = command.text;
       
   112 
       
   113 		/* Find the reverse, and issue it */
       
   114 		/* TODO -- Make a table which reverses every command.procc */
       
   115 		this->DoCommand(command.tile, command.p1, command.p2, command.flags, command.procc);
       
   116 
       
   117 		/* Remove the item from the list */
       
   118 		this->reverse_stack.pop();
       
   119 	}
       
   120 }
       
   121 
       
   122 int32 AITransactionMode::GetCosts()
       
   123 {
       
   124 	return this->costs;
       
   125 }
       
   126 
       
   127 void AITransactionMode::Append(AITransactionMode *transaction)
       
   128 {
       
   129 	/* Can't append to myself! */
       
   130 	if (transaction == this) return;
       
   131 
       
   132 	/* Simply move the queue from transaction to ourself */
       
   133 	while (!transaction->command_stack.empty()) {
       
   134 		this->command_stack.push(transaction->command_stack.front());
       
   135 		transaction->command_stack.pop();
       
   136 	}
       
   137 }