/* Core Wars. * Copyright (C) 1999 Walter Hofmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #ifndef CMD_LINE #include #endif #include "main.h" #include "main-gui.h" #include "execute.h" #include "execute-cw.h" #include "execute-rc.h" #include "tournament.h" #include "statistic.h" #include "pstatistic.h" #include "select.h" #ifndef CMD_LINE GdkGC* execute_gc; GdkColor black; GdkColormap *execute_colormap; #endif int running = FALSE; struct cell memory[SIZE_MAX]; struct process *process_array = NULL; int process_count = 0; int process_alive; gint execute_timeout, statistic_timeout; int elapsed_time; int thread_count; struct process *marked_process = NULL; int cleanup_needed = FALSE; int paused; struct { int contains_code; int marked; struct process *owner; } old_memory[SIZE_MAX]; #ifndef CMD_LINE void execute_init () { execute_gc = gdk_gc_new (main_drawing_area->window); execute_colormap = gdk_window_get_colormap (main_drawing_area->window); black.red = 0; black.green = 0; black.blue = 0; gdk_color_alloc (execute_colormap, &black); gdk_gc_set_background (execute_gc, &black); } void mark (int i, int force) { int marked; int mx, my, x, y; int t, b, l, r; GdkPoint points[5]; marked = marked_process && memory[i].owner==marked_process; if (!force && old_memory[i].contains_code==memory[i].contains_code && old_memory[i].owner==memory[i].owner && old_memory[i].marked==marked) return; mx = i % DIMENSIONX; my = i / DIMENSIONX; x = 6*mx; y = 6*my; if (force || old_memory[i].marked!=marked) if (marked) gdk_draw_rectangle (main_map, GTK_WIDGET (main_drawing_area)->style->white_gc, FALSE, x, y, 6, 6); else { gdk_draw_rectangle (main_map, GTK_WIDGET (main_drawing_area)->style->dark_gc[0], FALSE, x, y, 6, 6); if (marked_process) { t = my>0 && old_memory[i-DIMENSIONX].marked; b = my0 && old_memory[i-1].marked; r = mxstyle->white_gc, x, y, x+6, y); if (b) gdk_draw_line (main_map, GTK_WIDGET (main_drawing_area)->style->white_gc, x, y+6, x+6, y+6); if (l) gdk_draw_line (main_map, GTK_WIDGET (main_drawing_area)->style->white_gc, x, y, x, y+6); if (r) gdk_draw_line (main_map, GTK_WIDGET (main_drawing_area)->style->white_gc, x+6, y, x+6, y+6); if (!t && !l && mx>0 && my>0 && old_memory[i-DIMENSIONX-1].marked) gdk_draw_point (main_map, GTK_WIDGET (main_drawing_area)->style->white_gc, x, y); if (!t && !r && mx0 && old_memory[i-DIMENSIONX+1].marked) gdk_draw_point (main_map, GTK_WIDGET (main_drawing_area)->style->white_gc, x+6, y); if (!b && !l && mx>0 && mystyle->white_gc, x, y+6); if (!b && !r && mxstyle->white_gc, x+6, y+6); } } if (force || old_memory[i].contains_code!=memory[i].contains_code || old_memory[i].owner!=memory[i].owner) if (memory[i].owner) { if (memory[i].contains_code) { gdk_gc_set_foreground (execute_gc, &(memory[i].owner->color)); gdk_draw_rectangle (main_map, execute_gc, TRUE, x+1, y+1, 5, 5); gdk_gc_set_foreground (execute_gc, &black); points[0].x = x+3; points[0].y = y+2; points[1].x = x+2; points[1].y = y+3; points[2].x = x+3; points[2].y = y+3; points[3].x = x+4; points[3].y = y+3; points[4].x = x+3; points[4].y = y+4; gdk_draw_points (main_map, execute_gc, points, 5); } else { gdk_gc_set_foreground (execute_gc, &black); gdk_draw_rectangle (main_map, execute_gc, TRUE, x+1, y+1, 5, 5); gdk_gc_set_foreground (execute_gc, &(memory[i].owner->color)); gdk_draw_rectangle (main_map, execute_gc, TRUE, x+2, y+2, 3, 3); } } else { gdk_gc_set_foreground (execute_gc, &black); gdk_draw_rectangle (main_map, execute_gc, TRUE, x+1, y+1, 5, 5); } old_memory[i].contains_code = memory[i].contains_code; old_memory[i].owner = memory[i].owner; old_memory[i].marked = marked; } void mark_active (int i, struct process* active) { gdk_gc_set_foreground (execute_gc, &(active->color)); gdk_draw_rectangle (main_map, execute_gc, TRUE, 6*(i % DIMENSIONX)+1, 6*(i / DIMENSIONX)+1, 5, 5); } void mark_inactive (int i) { mark (i, TRUE); } void execute_mark (struct process *p) { int i; struct process *old; if (marked_process!=p) { old = marked_process; marked_process = p; for (i=0; ibullet); #endif if (p->thread) { t = p->thread; t->prev->next = NULL; while (t) { nextt = t->next; free (t); t = nextt; } } } free (process_array); /* Don't needlessly touch unused virtual memory */ for (i=0; ivbox), label, TRUE, TRUE, 0); gtk_widget_show (label); button = gtk_button_new_with_label( "Ok" ); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (*dialog)); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (*dialog)->action_area), button, TRUE, TRUE, 0); gtk_widget_show (button); gtk_window_set_position (GTK_WINDOW (*dialog), GTK_WIN_POS_CENTER); gtk_widget_show (*dialog); return FAIL; } execute_timeout = gtk_timeout_add (EXECUTE_DELAY, execute_step_handler, NULL); statistic_timeout = gtk_timeout_add (STATISTIC_DELAY, statistic_handler, NULL); statistic_update (FALSE); options_update (); select_update (); tournament_update (); } return OK; } /* Pause Programs */ void execute_pause () { paused = TRUE; gtk_widget_set (GTK_WIDGET (menu_file_pause), "sensitive", FALSE, NULL); gtk_widget_set (GTK_WIDGET (menu_file_continue), "sensitive", TRUE, NULL); gtk_widget_set (GTK_WIDGET (menu_file_step), "sensitive", TRUE, NULL); statistic_update (FALSE); } /* Continue Programs */ void execute_continue () { paused = FALSE; gtk_widget_set (GTK_WIDGET (menu_file_pause), "sensitive", TRUE, NULL); gtk_widget_set (GTK_WIDGET (menu_file_continue), "sensitive", FALSE, NULL); gtk_widget_set (GTK_WIDGET (menu_file_step), "sensitive", FALSE, NULL); } void create_process (struct program *p, struct process *pr, int position) { do { pr->color.red = random() % 65535; pr->color.green = random() % 65535; pr->color.blue = random() % 65535; } while (pr->color.red+pr->color.green+pr->color.blue<100000); gdk_color_alloc (execute_colormap, &(pr->color)); pr->bullet = gdk_pixmap_new (main_drawing_area->window, STATISTIC_BULLET_SIZE, STATISTIC_BULLET_SIZE, -1); gdk_gc_set_foreground (execute_gc, &(pr->color)); gdk_draw_rectangle (pr->bullet, execute_gc, TRUE, 0, 0, STATISTIC_BULLET_SIZE, STATISTIC_BULLET_SIZE); if (LANGUAGE==LANGUAGE_CW) cw_create_process_cmd (p, pr, position); else rc_create_process_cmd (p, pr, position); } #endif struct entry { int weight; struct program *p; } ; int entry_compare(const void *a, const void *b) { return ((struct entry *) a)->weight-((struct entry *) b)->weight; } int execute_start_cmd () { struct program *p; int i, j; int total_size; int space; struct entry *table; int position; if (cleanup_needed) execute_cleanup (); for (i=0; ierror && p->language==LANGUAGE) { process_count += p->load_count; if (p->language==LANGUAGE_CW) total_size += p->load_count*p->lang.cw.opcode_number; else total_size += p->load_count*p->lang.rc.size; } p = p->next; } space = SIZE-total_size-process_count*MIN_DISTANCE; if (space<0) { process_count = 0; return FAIL; } process_alive = process_count; table = malloc (sizeof (struct entry)*process_count); p = program_list_root; j = 0; while (p) { if (!p->error && p->language==LANGUAGE) for (i=0; iload_count; i++) { table[j].weight = random(); table[j++].p = p; } p = p->next; } qsort (table, process_count, sizeof (struct entry), &entry_compare); for (j=0; jlang.cw.opcode_number; else position += table[j].p->lang.rc.size; position = (position+table[j].weight) % SIZE; } elapsed_time = 0; running = TRUE; paused = FALSE; return OK; }