diff --git a/scripts/main.py b/scripts/main.py
index 9e671e4c40f117edb2ba22e72fe06371ea1f3b7f..25a95d9e7bac3d742ebc69b24d80fbf90d8af659 100755
--- a/scripts/main.py
+++ b/scripts/main.py
@@ -4,6 +4,7 @@ This is the main class for running the entire game framework
 '''
 #import modules and classes
 from log import Log
+from cognitive_game import Game
 #import from libraries
 import enum
 import random
@@ -12,133 +13,6 @@ import os
 
 #import from ros
 import rospy
-from board_state.msg import TokenMsg
-from board_state.msg import BoardMsg
-
-user_picked = (0, 0)
-user_placed = (0, 0)
-
-
-class Game(object):
-	def __init__(self, task_length, n_max_attempt_per_token, timeout):
-		rospy.init_node('big_hero', anonymous=True)
-		# subscriber for getting info from the board
-		rospy.Subscriber("/detected_move", TokenMsg, self.get_move_event_callback)
-		rospy.Subscriber("/board_status", BoardMsg, self.get_board_event_callback)
-		#get the objective of the exercise from the launch file
-		self.objective = rospy.get_param("/objective")
-
-		#we need a sleep in order to give the system the time to get the board info
-		self.current_board = []
-		rospy.sleep(2)
-		self.initial_board = self.get_board_event()
-		self.task_length = task_length
-		self.n_max_attempt_per_token = n_max_attempt_per_token
-		self.solution = self.set_objective(self.task_length)
-		self.timeout = timeout
-		self.robot_assistance = 0
-		self.avg_robot_assistance_per_move = 0
-		self.outcome = 0
-		#counters
-		self.n_attempt_per_token = 1
-		self.n_attempt_per_feedback = 0
-		self.n_mistakes = 0
-		self.n_correct_move = 0
-		#subscriber variables from detect_move
-		self.detected_token = []
-		self.picked = False
-		self.placed = False
-		self.moved_back = False
-		#logger
-		self.react_time_per_token_spec_t0 = 0.0
-		self.react_time_per_token_gen_t0 = 0.0
-		self.react_time_per_token_spec_t1 = 0.0
-		self.react_time_per_token_gen_t1 = 0.0
-		self.elapsed_time_per_token_gen_t0 = 0.0
-		self.elapsed_time_per_token_spec_t0 = 0.0
-		self.elapsed_time_per_token_gen_t1 = 0.0
-		self.elapsed_time_per_token_spec_t1 = 0.0
-		self.total_elapsed_time = 0.0
-		self.move_info_gen = {'token_id':'', 'from':'', 'to':'', 'avg_robot_assistance_per_move':'', 'cum_react_time':'', 'cum_elapsed_time':'', 'attempt':''}
-		self.move_info_spec = {'token_id': '', 'from': '', 'to': '', 'robot_assistance': '', 'react_time': '',
-		                      'elapsed_time': '', 'attempt': ''}
-		self.move_info_summary ={'attempt':'', 'avg_lev_assistance':'', 'react_time':'', 'elapsed_time':''}
-		self.move_info_gen_vect = list()
-		self.move_info_spec_vect = list()
-		self.move_info_summary_vect = list()
-
-	def get_board_event_callback(self, msg):
-		'''callback from the topic board_status to get the status of the current_board'''
-		self.current_board = msg.data
-
-	def get_board_event(self):
-		'''This method returns what is listened by the subscriber'''
-		return self.current_board
-
-	def get_move_event_callback(self, msg):
-		'''callback from the topic detected_move to get the detected move if so'''
-		self.detected_token = msg.detected_token
-		self.picked = msg.picked
-		self.placed = msg.placed
-		self.moved_back = msg.moved_back
-
-	def get_move_event(self):
-		'''This method just returns what is listened by the subscriber'''
-		return self.detected_token, self.picked, self.placed, self.moved_back
-
-	def set_objective(self, n_token):
-		'''The method return a list with the tokens ordered based on the solution of the exercise'''
-		board_ = self.current_board[:]
-		#remove the empty cells from the current_board
-		board_filtered = list(filter(lambda x: x!="0", board_))
-		if self.objective == "ascending":
-			self.solution = sorted(board_filtered)[:n_token]
-		elif self.objective == "descending":
-			self.solution = sorted(board_filtered, reverse=False)[:n_token]
-		else:
-			assert("Game is not defined contact the developer for integrating it")
-		return self.solution
-
-	#methods to access the variables outside the class
-	def get_n_attempt_per_token(self):
-		return self.n_attempt_per_token
-
-	def get_n_max_attempt(self):
-		return self.n_max_attempt
-
-	def get_n_mistakes(self):
-		return self.n_mistakes
-
-	def get_n_solution(self):
-		return self.n_solution
-
-	def get_n_correct_move(self):
-		return self.n_correct_move
-
-	def reset_attempt_per_token(self):
-		self.n_attempt_per_token = 0
-
-	def set_n_attempt_per_token(self, value):
-		self.n_attempt_per_token = value
-
-	def set_n_mistakes(self, value):
-		self.n_mistakes = value
-
-	def set_n_correct_move(self, value):
-		self.n_correct_move = value
-
-	def set_n_solution(self, value):
-		self.n_solution = value
-
-	def set_n_max_attempt_per_token(self, value):
-		self.n_max_attempt_per_token = value
-
-	def add_info_gen_vect(self, dict):
-		self.move_info_gen_vect.append(dict.copy())
-
-	def add_info_spec_vect(self, dict):
-		self.move_info_spec_vect.append(dict.copy())
-
 
 class StateMachine(enum.Enum):
 
@@ -171,8 +45,6 @@ class StateMachine(enum.Enum):
 
 	CURRENT_STATE = 1
 
-
-
 	def robot_provide_assistance(self, game):
 		'''
 		Robot action of assistance combining speech and gesture
@@ -212,18 +84,22 @@ class StateMachine(enum.Enum):
 		:return:
 		'''
 		print("R_OUTCOME")
-		outcome = 0
-		attempt = 0
+		if game.moved_back:
+			print("token has been moved back, DO nothing")
+			game.outcome = ""
+			self.CURRENT_STATE = self.S_ROBOT_ASSIST
+			# check if the user reached his max number of attempts
+			if game.n_attempt_per_token >= game.n_max_attempt_per_token:
+				print("Max attempt reached")
+				self.S_ROBOT_MOVE_CORRECT_TOKEN = True
+				self.b_user_reached_max_attempt = True
+				self.robot_move_correct_token(game)
+
 		#get current move and check if it is the one expeceted in the solution list
-		if game.detected_token[0] == game.solution[game.n_correct_move]  \
+		elif game.detected_token[0] == game.solution[game.n_correct_move]  \
 			and game.detected_token[2] == str(game.solution.index(game.detected_token[0])+1):
 			#get the values from attempt and mistakes before resetting them
-			attempt = game.n_attempt_per_token
 			game.outcome = 1
-			game.n_correct_move += 1
-			game.n_attempt_per_token = 1
-			game.set_n_correct_move(game.n_correct_move)
-			game.set_n_attempt_per_token(game.n_attempt_per_token)
 			print("correct_solution ", game.get_n_correct_move())
 			self.CURRENT_STATE = self.S_ROBOT_ASSIST
 		elif game.detected_token[0] == []:
@@ -257,12 +133,13 @@ class StateMachine(enum.Enum):
 
 			#check if the user reached his max number of attempts
 			if game.n_attempt_per_token>=game.n_max_attempt_per_token:
+				print("Max attempt reached")
 				self.S_ROBOT_MOVE_CORRECT_TOKEN = True
 				self.b_user_reached_max_attempt = True
 				self.robot_move_correct_token(game)
 
 		self.b_robot_outcome_finished = True
-		return self.b_robot_outcome_finished, attempt
+		return self.b_robot_outcome_finished
 
 	def robot_move_back(self):
 		#user moved the token in an incorrect location
@@ -297,8 +174,13 @@ class StateMachine(enum.Enum):
 	def user_action(self, game):
 		'''user action state has been divided in three sub methods:
 		 1. user pick a token
+		 1.a check for timeout
+		    1.b timeout -> provide reengagement
+		    go back to 1
 		 2. robot provides feedback
-		 3. user place a token
+		 3. user places a token
+		 3.a user places a token back
+		 3.b user places a token in a goal location
 		  '''
 		print("U_ACTION")
 
@@ -315,18 +197,12 @@ class StateMachine(enum.Enum):
 			else:
 				return False
 
-		def placed_back_token(sm):
-			'''As timeout occuccedd when the user has the token in his hand, we
-			 ask him to move it back'''
-			pass
-
-
 		def user_pick_token(sm, game):
 			game.react_time_per_token_spec_t0 = time.time()
 			print("U_PICK")
 			sm.CURRENT_STATE = sm.S_ROBOT_FEEDBACK
 			detected_token, picked, _, _ = game.get_move_event()
-			while(not picked):
+			while(not picked and (detected_token==[])):
 				if check_move_timeout(game):
 					detected_token, picked, _, _ = game.get_move_event()
 				else:
@@ -340,8 +216,14 @@ class StateMachine(enum.Enum):
 			sm.b_user_picked_token = True
 			return sm.b_user_picked_token
 
-		def robot_provide_feedback(sm):
+		def robot_provide_feedback(sm, game):
 			print("R_FEEDBACK")
+			#if the
+			game.n_sociable_per_token += 1
+			game.n_tot_sociable += 1
+			# if sm.b_user_picked_token and not game.detected_token[0] == game.solution[game.n_correct_move]:
+			# 	game.n_attempt_per_token += 1
+
 			sm.CURRENT_STATE = sm.S_USER_PLACE
 			sm.robot_provided_feeback_finished = True
 			return sm.robot_provided_feeback_finished
@@ -356,12 +238,12 @@ class StateMachine(enum.Enum):
 			#check where the user will place the token
 			def user_place_token_back(sm):
 				print("U_PLACE_BACK")
-				sm.CURRENT_STATE = sm.S_USER_ACTION
+				sm.CURRENT_STATE = sm.S_ROBOT_OUTCOME
 				sm.b_user_placed_token_back = True
 				game.elapsed_time_per_token_spec_t1 = time.time()-game.elapsed_time_per_token_spec_t0
 				game.elapsed_time_per_token_gen_t1 += game.elapsed_time_per_token_spec_t1
 				game.n_mistakes += 1
-				game.n_attempt_per_feedback += 1
+				game.n_attempt_per_token += 1
 				game.set_n_attempt_per_token(game.n_attempt_per_token)
 				game.set_n_mistakes(game.n_mistakes)
 				return sm.b_user_placed_token_back
@@ -380,21 +262,30 @@ class StateMachine(enum.Enum):
 			while (not placed):
 				detected_token, _, placed, moved_back = game.get_move_event()
 			if (placed and moved_back):
-				user_place_token_back(sm)
-				self.CURRENT_STATE = sm.S_USER_ACTION
+				self.CURRENT_STATE = sm.S_ROBOT_OUTCOME
+				return user_place_token_back(sm)
 			elif (placed and not moved_back):
-				user_place_token_sol(sm)
 				self.CURRENT_STATE = sm.S_ROBOT_OUTCOME
+				return user_place_token_sol(sm)
 			else:
 				assert "Unexpected state"
 
 		self.CURRENT_STATE = self.S_USER_ACTION
+		#if the user picks a token and SOCIABLE is active
 		if user_pick_token(self, game):
-			if robot_provide_feedback(self):
+			if game.with_SOCIABLE:
+				if robot_provide_feedback(self, game):
+					if user_place(self, game):
+						return True
+					else:
+						print("Something went wrong with user place in SOCIABLE")
+				else:
+					print("Something went wrong with robot feedback")
+			else:
 				if user_place(self, game):
 					return True
-			else:
-				self.CURRENT_STATE = self.S_USER_PICK_TOKEN
+				else:
+					print("Something went wrong with user place")
 		else:
 			self.CURRENT_STATE = self.S_ROBOT_ASSIST
 
@@ -416,22 +307,19 @@ class StateMachine(enum.Enum):
 		# Execute the function
 		return func()
 
-
-
-
 def main():
 	game = Game(task_length=5, n_max_attempt_per_token=4, timeout=15)
-	input = raw_input("please, insert the id of the user:")
+	user_id = raw_input("please, insert the id of the user:")
 	path = os.path.abspath(__file__)
 	dir_path = os.path.dirname(path)
 	parent_dir_of_file = os.path.dirname(dir_path)
-	path_name = parent_dir_of_file + "/log/" + input
-	print(path_name)
+	path_name = parent_dir_of_file + "/log/" + user_id
+
 	if not os.path.exists(path_name):
 		os.makedirs(path_name)
 	else:
-		input = raw_input("The folder already exists, please remove it or create a new one:")
-		path_name = os.getcwd() + "/log/" + input
+		user_id = raw_input("The folder already exists, please remove it or create a new one:")
+		path_name = os.getcwd() + "/log/" + user_id
 		if not os.path.exists(path_name):
 			os.makedirs(path_name)
 
@@ -447,6 +335,7 @@ def main():
 	game.move_info_spec['react_time'] = "react_time"
 	game.move_info_spec['elapsed_time'] = "elapsed_time"
 	game.move_info_spec['attempt'] = "attempt"
+	game.move_info_spec['sociable'] = "sociable"
 	game.move_info_spec_vect.append(game.move_info_spec)
 	log_spec.add_row_entry(game.move_info_spec)
 
@@ -458,11 +347,13 @@ def main():
 	game.move_info_gen['cum_react_time'] = "cum_react_time"
 	game.move_info_gen['cum_elapsed_time'] = "cum_elapsed_time"
 	game.move_info_gen['attempt'] = "attempt"
+	game.move_info_gen['sociable'] = "sociable"
 	game.move_info_gen_vect.append(game.move_info_gen)
 	log_gen.add_row_entry(game.move_info_gen)
 
 	log_summary = Log(file_summary)
 	game.move_info_summary["attempt"] = "n_attempt"
+	game.move_info_summary["sociable"] = "n_sociable"
 	game.move_info_summary["avg_lev_assistance"] = "lev_assistance"
 	game.move_info_summary["react_time"] = "react_time"
 	game.move_info_summary["elapsed_time"] = "elapsed_time"
@@ -470,62 +361,34 @@ def main():
 	sm = StateMachine(1)
 
 	while game.get_n_correct_move()<game.task_length:
+
 		if sm.CURRENT_STATE.value == sm.S_ROBOT_ASSIST.value:
 			sm.robot_provide_assistance(game)
 			game.avg_robot_assistance_per_move += game.robot_assistance
+
 		elif sm.CURRENT_STATE.value == sm.S_USER_ACTION.value:
 			print("Expected token ", game.solution[game.get_n_correct_move()])
 			time_to_act = time.time()
 			sm.user_action(game)
-			if  game.detected_token:
-				print("Moved token ", game.detected_token[0])
-				game.move_info_spec['token_id'] = game.detected_token[0]
-				game.move_info_spec['from'] = game.detected_token[1]
-				game.move_info_spec['to'] = game.detected_token[2]
-				game.move_info_spec['robot_assistance'] = game.robot_assistance
-				game.move_info_spec['react_time'] = round(game.react_time_per_token_spec_t1, 3)
-				game.move_info_spec['elapsed_time'] = round(game.elapsed_time_per_token_spec_t1, 3)
-				game.move_info_spec['attempt'] = game.n_attempt_per_token
-				game.total_elapsed_time += time.time()-time_to_act
-				game.add_info_spec_vect(game.move_info_spec)
-				log_spec.add_row_entry(game.move_info_spec)
+			game.total_elapsed_time += time.time() - time_to_act
 
 		elif sm.CURRENT_STATE.value == sm.S_ROBOT_OUTCOME.value:
 			#these are reported only because the variables are already reset when a correct move occurred
-			done, attempt = sm.robot_provide_outcome(game)
+			sm.robot_provide_outcome(game)
+			info = game.store_info_spec()
+			log_spec.add_row_entry(info)
 			#{'token_id':'', 'from':'', 'to':'', 'robot_assistance':'', 'react_time':'', 'elapsed_time':'', 'attempt':''}
+			#if you have done the correct move or you reach the maximum number of attempts then store the data
 			if (game.outcome == 1 or (game.outcome==0 and game.n_attempt_per_token==game.n_max_attempt_per_token)
 					or (game.outcome==-1 and game.n_attempt_per_token==game.n_max_attempt_per_token)):
-				game.move_info_gen['token_id'] = game.detected_token[0]
-				game.move_info_gen['from'] = game.detected_token[1]
-				game.move_info_gen['to'] = game.detected_token[2]
-				game.move_info_gen['avg_robot_assistance_per_move'] = (game.avg_robot_assistance_per_move/attempt)
-				game.move_info_gen['cum_react_time'] = round(game.react_time_per_token_gen_t1, 3)
-				game.move_info_gen['cum_elapsed_time'] = round(game.elapsed_time_per_token_gen_t1, 3)
-				game.move_info_gen['attempt'] = attempt
-				game.add_info_gen_vect(game.move_info_gen)
-				log_gen.add_row_entry(game.move_info_gen)
-				game.react_time_per_token_spec_t1 = 0
-				game.react_time_per_token_gen_t1 = 0
-				game.react_time_per_token_spec_t0 = 0
-				game.react_time_per_token_gen_t0 = 0
-				game.elapsed_time_per_token_spec_t1 = 0
-				game.elapsed_time_per_token_gen_t1 = 0
-				game.elapsed_time_per_token_spec_t0 = 0
-				game.elapsed_time_per_token_gen_t0 = 0
-				game.avg_robot_assistance_per_move = 0
+				log = game.store_info_gen()
+				log_gen.add_row_entry(log)
+				game.reset_counters()
+			game.reset_detected_token()
 
-	game.move_info_summary["attempt"] = "n_attempt"
-	game.move_info_summary["avg_lev_assistance"] = "lev_assistance"
-	game.move_info_summary["react_time"] = "react_time"
-	game.move_info_summary["elapsed_time"] = "elapsed_time"
 
-
-	game.move_info_summary["attempt"] = sum([elem['attempt'] for elem in game.move_info_gen_vect])
-	game.move_info_summary["avg_lev_assistance"] = sum([elem['avg_robot_assistance_per_move'] for elem in game.move_info_gen_vect])/game.task_length
-	game.move_info_summary["react_time"] = sum([elem['cum_react_time'] for elem in game.move_info_gen_vect])
-	game.move_info_summary["elapsed_time"] = sum([elem['cum_elapsed_time'] for elem in game.move_info_gen_vect])
-	log_summary.add_row_entry(game.move_info_summary)
+	log = game.store_info_summary()
+	log_summary.add_row_entry(log)
 
 	for instance_spec in game.move_info_spec_vect:
 		print(instance_spec)