1. drbrain
  2. hs_util

Commits

drbrain  committed 7f576db

Lots of tweaks to the way variables are stored during an assignment.

  • Participants
  • Parent commits a39ea51
  • Branches hs_util

Comments (0)

Files changed (4)

File formula.c

View file
 	}
 }
 
+local double evaluate_assignment(AssignmentNode *node, HashTable *vars, char *ret_var_name, char *error_buffer, int error_buffer_length, LinkedList *temp_vars)
+{
+	ASTNode *node = formula->assign->right;
+	double value = evaluate_ast(node->right, vars, error_buffer, error_buffer_length, &temp_vars);
+	
+	FormulaVariable *var = HashGetOne(vars, node->name);
+	if (var)
+	{
+		if (var->type == VAR_TYPE_FREQ_LIST)
+		{
+			LLEnum(&var->list, afree);
+			LLEmpty(&var->list);
+		}
+		else if (var->type == VAR_TYPE_PLAYER_LIST)
+		{
+			LLEmpty(&var->list);
+		}
+	}
+	else
+	{
+		var = amalloc(sizeof(FormulaVariable));
+		var->name = astrndup(node->name);
+		HashAdd(vars, node->name, var);
+	}
+
+	var->type = VAR_TYPE_DOUBLE;
+	var->value = value;
+}
+
 local double EvaluateFormula(Formula *formula, HashTable *vars, char *ret_var_name, char *error_buffer, int error_buffer_length)
 {
 	if (formula->assign)
 	{
 		Link *link;
-		ASTNode *node = formula->assign->right;
 		LinkedList temp_vars;
 		double value;
-
+		
 		LLInit(&temp_vars);
-
-		value = evaluate_ast(node, vars, error_buffer, error_buffer_length, &temp_vars);
+		
+		value = evaluate_assignment(formula->assign);
 
 		if (ret_var_name)
 		{
-			FormulaVariable *var = amalloc(sizeof(FormulaVariable));
-			var->name = strndup(formula->assign->name, MAX_VAR_NAME_LENGTH);
-			var->type = VAR_TYPE_DOUBLE;
-			var->value = value;
 			snprintf(ret_var_name, MAX_VAR_NAME_LENGTH, "%s", formula->assign->name);
-			HashAdd(vars, var->name, var);
 		}
 
 		// delete temporaries and delete created vars if ret_var_name == NULL
 		for (link = LLGetHead(&temp_vars); link; link = link->next)
 		{
 			FormulaVariable *var = link->data;
+			if (ret_var_name == NULL && var->name != NULL)
+			{
+				// remove it from the hash table
+				HashRemove(vars, var->name, var);
+			}
 			if (ret_var_name == NULL || var->name == NULL)
 			{
 				if (var->type == VAR_TYPE_FREQ_LIST)
 				{
 					LLEmpty(&var->list);
 				}
+				if (var->name)
+				{
+					afree(var->name);
+				}
 				afree(var);
 			}
 		}

File formula.h

View file
 #ifndef __FORMULA_H
 #define __FORMULA_H
 
-#define MAX_VAR_NAME_LENGTH 32
+#define MAX_VAR_NAME_LENGTH 16
 
 typedef enum VariableType
 {

File formula_cmd.c

View file
 typedef struct PData
 {
 	HashTable *vars;
-	int count;
 } PData;
 
 local Imodman *mm;
 
 local int pdata_key;
 
+local int count_vars_callback(const char *key, void *val, void *clos)
+{
+	int *count = clos;
+	*count++;
+	return FALSE;
+}
+
+local int count_vars(HashTable *table)
+{
+	int count = 0;
+	HashEnum(table, count_vars_callback, &count);
+	return count;
+}
+
 local int allow_var_creation(Player *p)
 {
 	PData *pdata = PPDATA(p, pdata_key);
+	int count = count_vars(pdata->vars);
 
 	/* cfghelp: Formula:MaxVariables, global, int, def: 10, mod: formula_cmd
 	 * How many variables a player can set with ?formula. */
 	int max_count = cfg->GetInt(GLOBAL, "Fomula", "MaxVariables", 10);
 
-	return pdata->count < max_count;
+	return count < max_count;
 }
 
 local helptext_t formula_help =
 
 		if (f)
 		{
-			// evaluate the formula
-			PData *pdata = PPDATA(p, pdata_key);
-			double value = formula->EvaluateFormula(f, pdata->vars, var_name_buf, error_buf, sizeof(error_buf));
-			formula->FreeFormula(f);
+			if (allow_var_creation(p))
+			{
+				PData *pdata = PPDATA(p, pdata_key);
+				double value = formula->EvaluateFormula(f, pdata->vars, var_name_buf, error_buf, sizeof(error_buf));
+				formula->FreeFormula(f);
 
-			if (error_buf[0] == '\0')
-			{
-				chat->SendMessage(p, "%s = %lf", var_name_buf, value);
-				// chat->SendMessage(p, "You have too many variables. Free some with ?unset");
+				if (error_buf[0] == '\0')
+				{
+					chat->SendMessage(p, "%s = %lf", var_name_buf, value);
+					// chat->SendMessage(p, "You have too many variables. Free some with ?unset");
+				}
+				else
+				{
+					chat->SendMessage(p, "Evaluation Error: %s", error_buf);
+				}
 			}
 			else
 			{
-				chat->SendMessage(p, "Evaluation Error: %s", error_buf);
+				PData *pdata = PPDATA(p, pdata_key);
+				double value = formula->EvaluateFormula(f, pdata->vars, NULL, error_buf, sizeof(error_buf));
+				formula->FreeFormula(f);
+
+				if (error_buf[0] == '\0')
+				{
+					chat->SendMessage(p, "You have too many variables. Free some with ?unset");
+					chat->SendMessage(p, "%lf", value);
+				}
+				else
+				{
+					chat->SendMessage(p, "Evaluation Error: %s", error_buf);
+				}
 			}
 		}
 		else
 
 		if (var)
 		{
-			pdata->count--;
 			HashRemove(pdata->vars, params, var);
 			afree(var);
 			chat->SendMessage(p, "Unset %s", params);
 	{
 		PData *pdata = PPDATA(p, pdata_key);
 		pdata->vars = HashAlloc();
-		pdata->count = 0;
 	}
 	pd->Unlock();
 }
 	if (action == PA_CONNECT)
 	{
 		pdata->vars = HashAlloc();
-		pdata->count = 0;
 	}
 	else if (action == PA_DISCONNECT)
 	{

File parser.y

View file
 static AssignmentNode * create_assignment(char *left, ASTNode *right)
 {
 	AssignmentNode *node = amalloc(sizeof(AssignmentNode));
-	node->name = left;
+	node->name = strndup(left, MAX_VAR_NAME_LENGTH);
+	afree(left);
 	node->right = right;
 	return node;
 }