/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2008, Martin Schoeberl (martin@jopdesign.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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, see <http://www.gnu.org/licenses/>. */ /** * */ package rttm.jsim; import java.util.Random; import com.jopdesign.io.IOFactory; import com.jopdesign.io.SysDevice; import com.jopdesign.sys.Const; import com.jopdesign.sys.Native; import com.jopdesign.sys.Startup; /** * @author Michael Muck * rttm version of Tron */ public class Tron { // read a random number from IO private static final int IO_RAND = Const.IO_CPUCNT+1; // its likely that this var needs to be changed! // read a positive random number from IO private static final int IO_PRAND = IO_RAND+1; static SysDevice sys = IOFactory.getFactory().getSysDevice(); static final int EMPTY = -1; // Game Array Size static final int SIZE = 15; static int array[][] = new int[SIZE][SIZE]; // running field static boolean running[] = new boolean[sys.nrCpu]; // tronRunners static TronRunner s[] = new TronRunner[sys.nrCpu]; /** * @param args */ public static void main(String[] args) { // reset running array for(int i=0; i<sys.nrCpu; ++i) { running[i] = true; } // set array empty for(int y=0; y<SIZE; y++) { for(int x=0; x<SIZE; x++) { array[x][y] = EMPTY; } } // create the runnables for all cores createPlayers(); // print initial game table printGameTable(); // measure time int startTime, endTime; startTime = Native.rd(Const.IO_US_CNT); // start the other CPUs sys.signal = 1; s[sys.nrCpu-1].run(); // wait for other CPUs to finish boolean allDone = false; while (!allDone) { allDone = true; for (int i=0; i<sys.nrCpu-1; ++i) { allDone &= s[i].finished; } } endTime = Native.rd(Const.IO_US_CNT); System.out.print("Time: "); System.out.print(endTime-startTime); System.out.println("\n"); // print out "picture" printGameTable(); // print last player positions for(int i=0; i<sys.nrCpu; ++i) { s[i].stats(); } // print out winner boolean any = false; for(int i=0; i<sys.nrCpu; ++i) { if(running[i] == true) { any = true; System.out.println("Player " + s[i].playerno + " has won the game (last active npc)!"); } } if(!any) { System.out.println("All Players were destroyed ..."); } } private static void createPlayers() { int cores = sys.nrCpu; int no = 0; int sector = 0; int x = 0, y = 0; int d = (sys.nrCpu/4)%SIZE; if(sys.nrCpu%4 != 0) { d += 1; } int step = SIZE/d; int grenze = sys.nrCpu/4 + sys.nrCpu%4 ; System.out.println("d: " + d + " - step: " + step); for (int i=0; i<4; ++i) { for( int k=0; k<grenze; ++k) { System.out.println("no: " + no); if(cores > 0) { if(no < sys.nrCpu-1) { s[no] = new TronRunner(no+1, x, y); Startup.setRunnable(s[no], no); } else { s[no] = new TronRunner(0, x, y); } cores--; } // position update if(sector == 0) { // sector0 x += step; if(x >= SIZE-1) { x = SIZE-1; System.out.println("x=" + x + " sector = 1"); sector = 1; } } else if(sector == 1) { // sector1 y += step; if(y >= SIZE-1) { y = SIZE-1; System.out.println("sector = 2"); sector = 2; } } else if(sector == 2) { x -= step; if(x <= 0) { x = 0; System.out.println("sector = 3"); sector = 3; } } else if(sector == 3) { y -= step; if(y <= 0) { y = 0; System.out.println("sector = 0"); sector = 0; } } no++; // cpu count } } } private static void printGameTable() { System.out.println(); for(int y=-1; y<SIZE; y++) { for(int x=-1; x<SIZE; x++) { if(x > -1) { if(y > -1) { if(array[x][y] == EMPTY) { System.out.print("."); } else { System.out.print("\33[3"+array[x][y]+"m"); System.out.print(array[x][y]); System.out.print("\33[30m"); } System.out.print("\t"); } else { System.out.print("\t" + x); } } else if(y > -1) { System.out.print(y + "\t"); } } System.out.println(); } System.out.println(); } static class TronRunner implements Runnable { private static final int MAGIC = -10000; private boolean finished = false; private int playerno; private int x, y; private int dx, dy; private int randIterations = 0; private boolean forceDirection = false; private int lastlr = 0; private int moves = 1; private boolean[] setPossible = new boolean[9]; public TronRunner(int p, int startx, int starty) { playerno = p; x = startx; y = starty; // set start field array[x][y] = p; // set the initial direction dx = ((SIZE-1)/2)-x; if(dx<0) { dx /= -dx; } else if(dx == 0) { dx = 0; } else { dx /= dx; } dy = ((SIZE-1)/2)-y; if(dy<0) { dy /= -dy; } else if(dy == 0) { dy = 0; } else { dy /= dy; } // initial reset - everything is possible for(int n=0; n<9; ++n) { setPossible[n] = true; } setPossible[4] = false; System.out.println("Player " + playerno + " at (" + x + " | " + y + ") with (" + dx + " | " + dy + ")"); } public void run() { boolean game_over = false; int n; while(!game_over) { // we have a starting field, an initial direction - now go Native.wrMem(1, MAGIC); // test for game field boundaries and test our field for emptyness if( x+dx >= 0 && x+dx < SIZE && y+dy >= 0 && y+dy < SIZE && array[x+dx][y+dy] == EMPTY) { // step forward x += dx; y += dy; // set our landmark array[x][y] = this.playerno; moves++; randIterations = 0; //resetPossibilities(); -> problems with method invocation -> do inline // reset possible directions for(n=0; n<9; ++n) { setPossible[n] = true; } setPossible[4] = false; // mark move impossible from where we came setPossible[(-dx+1)+((-dy+1)*3)] = false; } else { // if not possible, choose another direction to go setPossible[(dx+1)+((dy+1)*3)] = false; //randDirection(); -> problems with method invocation during a transaction } Native.wrMem(0, MAGIC); // if setPossible[direction] = false -> search new direction if(setPossible[(dx+1)+((dy+1)*3)] == false) { randDirection(); } // see if we have options where to go left game_over = true; for(n=0; n<9; ++n) { if(setPossible[n] == true) { game_over = false; } } // check the randIterations if(randIterations > 5) { forceDirection = true; } if(randIterations > 20) { game_over = true; } } // check if there are other players left /* Native.wrMem(1, MAGIC); running[playerno] = false; Native.wrMem(0, MAGIC); */ //System.out.println("player"+playerno + " dead"); boolean anyOther = false; Native.wrMem(1, MAGIC); for(n=0; n<sys.nrCpu; ++n) { if(running[n] == true && n != this.playerno) { // uh we are not the last player anyOther = true; // we lost :( } } if(!anyOther) { running[playerno] = true; } else { running[playerno] = false; } Native.wrMem(0, MAGIC); finished = true; } private void randDirection() { /* dy/dx * -1 0 1 * -1 0 1 2 0 * 0 3 4 5 3 * 1 6 7 8 6 * 0 1 2 * x/y */ int lr; if(forceDirection) { lr = lastlr; // do not turn around! } else { lr = Native.rdMem(IO_PRAND)%2; } if(lr == 0) { // turn left if(dx > 0) { if(dy > 0) { dy = 0; } else if(dy == 0) { dy = -1; } else { dx = 0; } } else if(dx == 0) { if(dy > 0) { dx = 1; } /* -> impossible! else if(dy == 0) { dy = -1; } */ else { dx = -1; } } else { if(dy > 0) { dx = 0; } else if(dy == 0) { dy = 1; } else { dy = 0; } } } else { // turn right if(dx > 0) { if(dy > 0) { dx = 0; } else if(dy == 0) { dy = 1; } else { dy = 0; } } else if(dx == 0) { if(dy > 0) { dx = -1; } /* -> impossible! else if(dy == 0) { dy = -1; } */ else { dx = 1; } } else { if(dy > 0) { dy = 0; } else if(dy == 0) { dy = -1; } else { dx = 0; } } } lastlr = lr; // save lastlr randIterations++; } public void stats() { System.out.println("Player " + playerno + " stopped at (" + x + " | " + y +") with " + moves + " moves"); } } }