programming assignment AL PA_B done

This commit is contained in:
Jonas Weinz 2017-05-21 11:11:24 +02:00
parent 842798b205
commit c045621618
3 changed files with 136 additions and 162 deletions

161
02_gameOfLife/Main.py Executable file → Normal file
View File

@ -2,31 +2,25 @@
import pygame import pygame
import random import random
from OpenGL.GL import * from OpenGL.GL import *
from OpenGL.GLU import *
from pygame.locals import * from pygame.locals import *
import argparse video_flags = OPENGL | HWSURFACE | DOUBLEBUF | FULLSCREEN
#TODO: remove global vars
pygame.init() pygame.init()
window_w = 1600 dinfo = pygame.display.Info();
window_h = 900
livingSpaceWidth = 64 livingSpaceWidth = 48
livingSpaceHeight = 36 livingSpaceHeight = 27
creatureW = window_w/(livingSpaceWidth) creatureW = dinfo.current_w/(livingSpaceWidth)
creatureH = window_h/(livingSpaceHeight) creatureH = dinfo.current_h/(livingSpaceHeight)
FPS = 30 FPS = 40
livingSpace = [] livingSpace = []
draw_buffer = []
draw_buffer_old = []
def resize(shape): def resize(shape):
width, height = shape width, height = shape
if height == 0: if height == 0:
@ -54,34 +48,30 @@ def isAlive(x,y):
return livingSpace[x][y] == 1000 return livingSpace[x][y] == 1000
def draw(): def draw():
global draw_buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
global draw_buffer_old
#glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity() glLoadIdentity()
glTranslatef(0.0,0.0,3.0) glTranslatef(0.0,0.0,3.0)
glBegin(GL_QUADS) glBegin(GL_QUADS)
for column, row in draw_buffer + draw_buffer_old: for column in range(livingSpaceWidth):
if livingSpace[column][row] != 0: for row in range(livingSpaceHeight):
health = float(float(livingSpace[column][row])/1000.0) if livingSpace[column][row] != 0:
health = float(float(livingSpace[column][row])/1000.0)
glColor4f(health*(float(column)/float(livingSpaceWidth)), glColor4f(health*(float(column)/float(livingSpaceWidth)),
health*(float(livingSpaceWidth-column)/float(livingSpaceWidth)), health*(float(livingSpaceWidth-column)/float(livingSpaceWidth)),
health*(float(row)/float(livingSpaceHeight)),1.0) health*(float(row)/float(livingSpaceHeight)),1.0)
x = column * creatureW x = column * creatureW
y = row * creatureH y = row * creatureH
glVertex3f(x,y,0.0) glVertex3f(x,y,0.0)
glVertex3f(x + creatureW-1.0,y,0.0) glVertex3f(x + creatureW-1.0,y,0.0)
glVertex3f(x+creatureW-1,y+creatureH-1,0.0) glVertex3f(x+creatureW-1,y+creatureH-1,0.0)
glVertex3f(x,y+creatureH-1,0.0) glVertex3f(x,y+creatureH-1,0.0)
glEnd() glEnd()
draw_buffer_old = draw_buffer
draw_buffer = []
def getNeighborCount(x,y): def getNeighborCount(x,y):
count = 0 count = 0
@ -104,7 +94,6 @@ def getNeighborCount(x,y):
return count return count
def calculateNextGeneration(): def calculateNextGeneration():
neighborCount = [] neighborCount = []
for column in range(livingSpaceWidth): for column in range(livingSpaceWidth):
neighborCount.append([]) neighborCount.append([])
@ -116,82 +105,26 @@ def calculateNextGeneration():
if 2 <= neighborCount[column][row] <= 3: if 2 <= neighborCount[column][row] <= 3:
if neighborCount[column][row] == 3: if neighborCount[column][row] == 3:
livingSpace[column][row] = 1000 livingSpace[column][row] = 1000
draw_buffer.append((column, row))
if not isAlive(column,row): if not isAlive(column,row):
livingSpace[column][row] = float(livingSpace[column][row])/1.2 livingSpace[column][row] = float(livingSpace[column][row])/1.2
draw_buffer.append((column, row))
else: else:
livingSpace[column][row] = float(livingSpace[column][row])/1.2 livingSpace[column][row] = float(livingSpace[column][row])/1.2
draw_buffer.append((column, row))
if livingSpace[column][row] < 20: if livingSpace[column][row] < 20:
livingSpace[column][row] = 0 livingSpace[column][row] = 0
def main(): def main():
global livingSpaceWidth
global livingSpaceHeight
global creatureW
global creatureH
global window_w
global window_h
# parsing args: pygame.display.set_mode((dinfo.current_w,dinfo.current_h),video_flags)
parser = argparse.ArgumentParser(description="game of life")
parser.add_argument('--steps', dest='steps', default = 20 , help='steps per second')
parser.add_argument('--w', dest='w', default = livingSpaceWidth, help = 'field width')
parser.add_argument('--h', dest='h', default=livingSpaceHeight, help = 'field height')
#parser.add_argument('--calc', dest='calc', default=0, help='calculate steps and only display result')
#parser.add_argument('--default', dest='default', default=0, help='setting all fields to this value')
parser.add_argument('--fullscreen', dest='fullscreen', action='store_true')
parser.add_argument('--window_w', dest='win_w', default=window_w, help='window width')
parser.add_argument('--window_h', dest='win_h', default=window_h, help='window height')
parser.add_argument('--configurator', dest='configurator', action='store_true', help='start in field edit mode')
#parser.add_argument('--code', dest='code', default='01', help='binary code for the ant (\'01\' corresponds to the starndard ant behaviour)')
parser.set_defaults(fullscreen=False)
parser.set_defaults(configurator=False)
args = parser.parse_args()
steps_per_sec = int(args.steps)
livingSpaceWidth = int(args.w)
livingSpaceHeight = int(args.h)
video_flags = OPENGL | HWSURFACE | DOUBLEBUF
if args.fullscreen:
video_flags = OPENGL | HWSURFACE | DOUBLEBUF | FULLSCREEN
dinfo = pygame.display.Info()
window_w = dinfo.current_w
window_h = dinfo.current_h
else:
window_w = int(args.win_w)
window_h = int(args.win_h)
creatureW = window_w / (livingSpaceWidth)
creatureH = window_h / (livingSpaceHeight)
#antPosition = (livingSpaceWidth // 2, livingSpaceHeight // 2)
pygame.display.set_mode((window_w,window_h),video_flags)
initLivingSpace() initLivingSpace()
resize((dinfo.current_w,dinfo.current_h))
resize((window_w, window_h))
init() init()
clock = pygame.time.Clock() clock = pygame.time.Clock()
frames = 0 frames = 0
counter = 0
logic_frame_pause = FPS / steps_per_sec
configurator_mode = bool(args.configurator)
field_draws = 0
#Hauptschleife: #Hauptschleife:
while True: while True:
@ -203,53 +136,11 @@ def main():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
break break
draw() draw()
field_draws += len(draw_buffer) + len(draw_buffer_old)
frames += 1
if frames % FPS == 0:
print("average field draws per frame: " + str(field_draws / FPS))
field_draws = 0
pygame.display.flip() pygame.display.flip()
calculateNextGeneration()
if configurator_mode:
# move with keys:
if event.type == KEYDOWN:
# draw_buffer.append((antPosition[0],antPosition[1]))
# if event.key == K_DOWN:
# move_ant(0,+1)
# elif event.key == K_UP:
# move_ant(0,-1)
# elif event.key == K_LEFT:
# move_ant(-1,0)
# elif event.key == K_RIGHT:
# move_ant(+1,0)
# elif event.key == K_SPACE:
# new_key = (livingSpace[antPosition[0]][antPosition[1]]) % num_colors + 1
# if not isAlive(antPosition[0], antPosition[1]):
# new_key += 1
# activate(antPosition[0], antPosition[1], new_key)
# elif event.key == K_BACKSPACE:
# deactivate(antPosition[0],antPosition[1])
if event.key == K_RETURN:
configurator_mode = False
counter += 1
if logic_frame_pause >= 1:
if counter > logic_frame_pause:
calculateNextGeneration()
counter = 0
else:
# multiple calculations per frame:
for i in range(int(1 / logic_frame_pause)):
calculateNextGeneration()
# switch to configurator mode:
if event.type == KEYDOWN and event.key == K_RETURN:
configurator_mode = True

View File

@ -1,9 +1,13 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import pygame import pygame
from OpenGL.GL import * from OpenGL.GL import *
from pygame.locals import * from pygame.locals import *
import argparse import argparse
import sys
import random
import time
#TODO: remove global vars #TODO: remove global vars
@ -42,6 +46,9 @@ num_colors = 2
color_list = [] color_list = []
code = [False,True] code = [False,True]
# store number of active cells
num_active_cells = 0
# helper function for colors: # helper function for colors:
def HSVtoRGB(h,s,v): def HSVtoRGB(h,s,v):
c = v*s c = v*s
@ -144,10 +151,10 @@ def draw():
glColor4f(1,1,1,0.5) glColor4f(1,1,1,0.5)
glVertex3f(x + offX, y, 0.0) glVertex3f(x + offX, y, 0.0) if antRotation != SOUTH else glVertex3f(x + offX, y + creatureH/2, 0.0)
glVertex3f(x + creatureW - 1, y + offY, 0.0) glVertex3f(x + creatureW - 1, y + offY, 0.0) if antRotation != WEST else glVertex3f(x + creatureW/2, y + offY, 0.0)
glVertex3f(x + offX, y + creatureH - 1, 0.0) glVertex3f(x + offX, y + creatureH - 1, 0.0) if antRotation != NORTH else glVertex3f(x + offX, y + creatureH/2, 0.0)
glVertex3f(x, y + offY, 0.0) glVertex3f(x, y + offY, 0.0) if antRotation != EAST else glVertex3f(x + creatureW/2, y + offY, 0.0)
glEnd() glEnd()
@ -156,6 +163,10 @@ def draw():
def activate(i,j,key = 1): def activate(i,j,key = 1):
global num_active_cells
if livingSpace[i][j] == 0:
num_active_cells += 1
livingSpace[i][j] = key livingSpace[i][j] = key
if num_colors > 2: if num_colors > 2:
livingSpaceColor[i][j] = [ livingSpaceColor[i][j] = [
@ -169,6 +180,9 @@ def activate(i,j,key = 1):
update_queue.append((i,j)) update_queue.append((i,j))
def deactivate(i,j): def deactivate(i,j):
global num_active_cells
if livingSpace[i][j] != 0:
num_active_cells -= 1
livingSpace[i][j] = 0 livingSpace[i][j] = 0
# correct color: # correct color:
livingSpaceColor[i][j] = [ livingSpaceColor[i][j] = [
@ -282,6 +296,7 @@ def main():
global creatureW global creatureW
global creatureH global creatureH
global antPosition global antPosition
global antRotation
global window_w global window_w
global window_h global window_h
global color_list global color_list
@ -289,17 +304,25 @@ def main():
global code global code
# parsing args: # parsing args:
parser = argparse.ArgumentParser(description="langton's ant") parser = argparse.ArgumentParser(description="langton's ant simulation tool", formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('--steps', dest='steps', default = 20 , help='steps per second') parser.add_argument('--steps', dest='steps', default = 20 , help='steps per second')
parser.add_argument('--w', dest='w', default = livingSpaceWidth, help = 'field width') parser.add_argument('--w', dest='w', default = livingSpaceWidth, help = 'field width')
parser.add_argument('--h', dest='h', default=livingSpaceHeight, help = 'field height') parser.add_argument('--h', dest='h', default=livingSpaceHeight, help = 'field height')
parser.add_argument('--calc', dest='calc', default=0, help='calculate steps and only display result') parser.add_argument('--calc', dest='calc', default=0, help='calculate steps and only display result')
parser.add_argument('--default', dest='default', default=0, help='setting all fields to this value')
parser.add_argument('--fullscreen', dest='fullscreen', action='store_true') parser.add_argument('--fullscreen', dest='fullscreen', action='store_true')
parser.add_argument('--window_w', dest='win_w', default=window_w, help='window width') parser.add_argument('--window_w', dest='win_w', default=window_w, help='window width')
parser.add_argument('--window_h', dest='win_h', default=window_h, help='window height') parser.add_argument('--window_h', dest='win_h', default=window_h, help='window height')
parser.add_argument('--configurator', dest='configurator', action='store_true', help='start in field edit mode') parser.add_argument('--configurator', dest='configurator', action='store_true', help='start in field edit mode')
parser.add_argument('--code', dest='code', default='01', help='binary code for the ant (\'01\' corresponds to the starndard ant behaviour)') parser.add_argument('--code', dest='code', default='01', help='binary code for the ant (\'01\' corresponds to the starndard ant behaviour)')
parser.add_argument('--file', dest='file', default='', help='writing number of living cells per step in this file')
parser.add_argument('--pattern', dest='pattern', default='0',
help='initial pattern for the field. Possible values:\n' +
'\t * 0: all fields inactive\n' +
'\t * 1: all fields active\n' +
'\t * check: checkboard pattern\n' +
'\t * horizontal: horizontal stripes\n' +
'\t * vertical: vertical stripes\n' +
'\t * random: random values\n')
parser.set_defaults(fullscreen=False) parser.set_defaults(fullscreen=False)
parser.set_defaults(configurator=False) parser.set_defaults(configurator=False)
@ -309,6 +332,10 @@ def main():
livingSpaceWidth = int(args.w) livingSpaceWidth = int(args.w)
livingSpaceHeight = int(args.h) livingSpaceHeight = int(args.h)
calc = int(args.calc) calc = int(args.calc)
filename = args.file
fileobj = None
if len(filename) > 0:
fileobj = open(filename, mode='w')
video_flags = OPENGL | HWSURFACE | DOUBLEBUF video_flags = OPENGL | HWSURFACE | DOUBLEBUF
@ -345,11 +372,6 @@ def main():
initLivingSpace() initLivingSpace()
if int(args.default) != 0:
for i in range(livingSpaceWidth):
for j in range(livingSpaceHeight):
activate(i,j)
resize((window_w, window_h)) resize((window_w, window_h))
init() init()
@ -362,9 +384,52 @@ def main():
field_draws = 0 field_draws = 0
# apply pattern
if args.pattern == '0':
# nothing to do
pass
elif args.pattern == '1':
for i in range(livingSpaceWidth):
for j in range(livingSpaceHeight):
activate(i,j)
elif args.pattern == 'check':
for i in range(livingSpaceWidth):
for j in range(livingSpaceHeight):
if (i + j) % 2 == 0:
activate(i,j)
elif args.pattern == 'horizontal':
for i in range(livingSpaceWidth):
for j in range(livingSpaceHeight):
m = j % num_colors
if num_colors > 2:
m += 1
if m != 0:
activate(i,j,m)
elif args.pattern == 'vertical':
for i in range(livingSpaceWidth):
for j in range(livingSpaceHeight):
m = i % num_colors
if num_colors > 2:
m += 1
if m != 0:
activate(i,j,m)
elif args.pattern == 'random':
r = random.Random(time.time())
for i in range(livingSpaceWidth):
for j in range(livingSpaceHeight):
k = r.randint(0,num_colors - 1)
if num_colors > 2:
k += 1
if k != 0:
activate(i,j,k)
else:
print("error. unknown pattern")
parser.print_help()
sys.exit(-1)
if (calc > 0): if (calc > 0):
for i in range(calc): for i in range(calc):
update_ant(); update_ant()
#main loop: #main loop:
while True: while True:
@ -376,7 +441,7 @@ def main():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
break break
update_field(); update_field()
draw() draw()
field_draws += len(draw_buffer) + len(draw_buffer_old) field_draws += len(draw_buffer) + len(draw_buffer_old)
@ -408,6 +473,12 @@ def main():
activate(antPosition[0], antPosition[1], new_key) activate(antPosition[0], antPosition[1], new_key)
elif event.key == K_BACKSPACE: elif event.key == K_BACKSPACE:
deactivate(antPosition[0],antPosition[1]) deactivate(antPosition[0],antPosition[1])
elif event.key == K_LCTRL:
antRotation = (antRotation - 1) % 4
move_ant(0,0)
elif event.key == K_RCTRL:
antRotation = (antRotation + 1) % 4
move_ant(0,0)
elif event.key == K_RETURN: elif event.key == K_RETURN:
configurator_mode = False configurator_mode = False
@ -419,15 +490,21 @@ def main():
if logic_frame_pause >= 1: if logic_frame_pause >= 1:
if counter > logic_frame_pause: if counter > logic_frame_pause:
update_ant() update_ant()
if fileobj != None:
fileobj.write(str(num_active_cells) + '\n')
counter = 0 counter = 0
else: else:
# multiple calculations per frame: # multiple calculations per frame:
for i in range(int(1 / logic_frame_pause)): for i in range(int(1 / logic_frame_pause)):
update_ant() update_ant()
if fileobj != None:
fileobj.write(str(num_active_cells) + '\n')
# switch to configurator mode: # switch to configurator mode:
if event.type == KEYDOWN and event.key == K_RETURN: if event.type == KEYDOWN and event.key == K_RETURN:
configurator_mode = True configurator_mode = True
if fileobj != None:
fileobj.close()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -2,10 +2,10 @@
``` ```
usage: Main.py [-h] [--steps STEPS] [--w W] [--h H] [--calc CALC] usage: Main.py [-h] [--steps STEPS] [--w W] [--h H] [--calc CALC]
[--default DEFAULT] [--fullscreen] [--window_w WIN_W] [--fullscreen] [--window_w WIN_W] [--window_h WIN_H]
[--window_h WIN_H] [--configurator] [--code CODE] [--configurator] [--code CODE] [--pattern PATTERN]
langton's ant langton's ant simulation tool
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
@ -13,23 +13,29 @@ optional arguments:
--w W field width --w W field width
--h H field height --h H field height
--calc CALC calculate steps and only display result --calc CALC calculate steps and only display result
--default DEFAULT setting all fields to this value
--fullscreen --fullscreen
--window_w WIN_W window width --window_w WIN_W window width
--window_h WIN_H window height --window_h WIN_H window height
--configurator start in field edit mode --configurator start in field edit mode
--code CODE binary code for the ant ('01' corresponds to the --code CODE binary code for the ant ('01' corresponds to the starndard ant behaviour)
starndard ant behaviour) --pattern PATTERN initial pattern for the field. Possible values:
* 0: all fields inactive
* 1: all fields active
* check: checkboard pattern
* horizontal: horizontal stripes
* vertical: vertical stripes
* random: random values
``` ```
configuration mode keys: keys:
| key | function | | key | function |
| ---------- | -------------------------------------- | | ---------------------- | ---------------------------------------- |
| return | enter/leave configuration mode | | return | enter/leave configuration mode |
| arrow keys | move langton's ant | | arrow keys | move langton's ant (in configuration mode) |
| space | activate field or switch field's color | | space | activate field or switch field's color (in configuration mode) |
| backspace | deactivate field | | backspace | deactivate field (in configuration mode) |
| escape | exit program | | ctrl left / ctrl right | rotate ant (in configuration mode) |
| escape | exit program |