Python Forum

Full Version: 4-Bit Computer Simulation
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
So...I've been working on this little 4 bit computer simulation. It's very simple, it uses just about 16 instructions in a version of assembly language I made. The code is not optimized to the slightest degree, I'm self taught in Python and only use it as a hobby, so I don't work much in high level structuring (This is quite apparent in the addition and subtraction routines). Anyway, if you want to check it out I'll post the code below. I'll also include a link to a little tutorial page.

Feel free to tell me about bugs, positives, negatives and any cool programs you've made!
Thank you.

(Link to tutorial : https://docs.google.com/document/d/1_9vo...sp=sharing)

import random, sys, time

print('PY~COM PC-1')
print('16 instructions of ROM per file; 7 files onboard, expandable to 10 files')
print('16 instructions programmable memory; expandable to 256 (also reflected in ROM) (Used as a virtual limitation)')
print('16 bits of RAM (4 registers of 4 bits or 2 registers of 8 bits)+ a technical extra byte of storable binary.')
input('Hit Enter')

VARS = ['0000', '0000', '0000', '0000']

#        A   B   C   D
#        4 registers of 4 bits
#        Or 2 Registers of 8 on request
PROG = []
ROM1 = ['OFF 108', 'STO A 0000', 'STO B 1111', 'STO C 0000', 'STO D 1111', 'ADD A 1', 'SUB B 1', 'ADD C 1', 'SUB D 1', 'MEM', 'STP', 'JMP 5']
ROM2 = ['STO A 0000', 'STO B 0000', 'STO C 0000', 'STO D 0000', 'STO X 0000', 'ADD A 1', 'ADD B 1', 'ADD C 1', 'ADD D 1', 'STO X D', 'MEM', 'STP', 'JMP 5']
ROM3 = ['OFF 72', 'BRK 65', 'STO A 0000', 'MEM', 'ADD A 1', 'STP', 'JMP 3', 'STO B 0001', 'MEM', 'STP']
ROM4 = ['STO A 1001', 'STO B 1001', 'STO C 1111', 'STO D 1001', 'STO X 1001', 'DIS', 'LIN 1', 'STO A 1111', 'STO B 0110', 'STO C 0110', 'STO D 0110', 'STO X 1111', 'DIS', 'STP']
ROM5 = []
ROM6 = []
ROM7 = []
TRAN = [('0000', 'STO'), ('0001', 'SHO'), ('0010', 'ADD'), ('0011', 'SUB'),
        ('0100', 'MEM'), ('0101', 'JMP'), ('0110', 'OFF'), ('0111', 'STO'),
        ('1000', 'INV'), ('1001', 'STP'), ('1010', 'RAM'), ('1011', 'BRK'),
        ('1100', 'CLR'), ('1101', 'SAV'), ('1110', 'DIS'), ('1111', 'LIN')]

#EXT1 = ['0010 0000 1', '0010 0001 1', '0010 0010 1',
#        '0010 0011 1', '0100       ', '1001       ', '0101 0     ']
EXT1 = []
X = None
GOTO = 0
Z = None
ZX = None
READ = 0
def DO():#Exactly 15 different operations!!!!
    global VARS
    global GOTO
    global X
    global Z
    global ZX
    global ROM1
    global ROM2
    global ROM3
    global ROM4
    global ROM5
    global ROM6
    global ROM7
    for x in range(GOTO, len(PROG)):
        #time.sleep(len(PROG)*0.1)
        if Z == None:
            Z = 999
        if isinstance(X, int) == True:
            X = X +1
        if 'STO X' in PROG[x]:
            if PROG[x][6] != 'A' and PROG[x][6] != 'B' and PROG[x][6] != 'C' and PROG[x][6] != 'D':
                X = ''
                for y in range(6, len(PROG[x])):
                    X = X +PROG[x][y]
            if PROG[x][6] == 'A':
                X = VARS[0]
            if PROG[x][6] == 'B':
                X = VARS[1]
            if PROG[x][6] == 'C':
                X = VARS[2]
            if PROG[x][6] == 'D':
                X = VARS[3]
        if 'STO A' in PROG[x]:
            if PROG[x] != 'X' and PROG[x][6] != 'B' and PROG[x][6] != 'C' and PROG[x][6] != 'D':
                VARS[0] = ''
                for y in range(6, len(PROG[x])):
                    VARS[0] = VARS[0] +PROG[x][y]
            if PROG[x][6] == 'B':
                VARS[0] = VARS[1]
            if PROG[x][6] == 'C':
                VARS[0] = VARS[2]
            if PROG[x][6] == 'D':
                VARS[0] = VARS[3]
            if PROG[x][6] == 'X':
                VARS[0] = X
                
                
        if 'STO B' in PROG[x]:
            if PROG[x][6] != 'X' and PROG[x][6] != 'A' and PROG[x][6] != 'C' and PROG[x][6] != 'D':
                VARS[1] = ''
                for y in range(6, len(PROG[x])):
                    VARS[1] = VARS[1] +PROG[x][y]
            if PROG[x][6] == 'A':
                VARS[1] = VARS[0]
            if PROG[x][6] == 'C':
                VARS[1] = VARS[2]
            if PROG[x][6] == 'D':
                VARS[1] = VARS[3]
            if PROG[x][6] == 'X':
                VARS[1] = X
        if 'STO C' in PROG[x]:
            if PROG[x][6] != 'X' and PROG[x][6] != 'A' and PROG[x][6] != 'B' and PROG[x][6] != 'D':
                VARS[2] = ''
                for y in range(6, len(PROG[x])):
                    VARS[2] = VARS[2] +PROG[x][y]
            if PROG[x][6] == 'A':
                VARS[2] = VARS[0]
            if PROG[x][6] == 'B':
                VARS[2] = VARS[1]
            if PROG[x][6] == 'D':
                VARS[2] = VARS[3]
            if PROG[x][6] == 'X':
                VARS[2] = X
        if 'STO D' in PROG[x]:
            if PROG[x][6] != 'X' and PROG[x][6] != 'A' and PROG[x][6] != 'B' and PROG[x][6] != 'C':
                VARS[3] = ''
                for y in range(6, len(PROG[x])):
                    VARS[3] = VARS[3] +PROG[x][y]
            if PROG[x][6] == 'A':
                VARS[3] = VARS[0]
            if PROG[x][6] == 'B':
                VARS[3] = VARS[1]
            if PROG[x][6] == 'C':
                VARS[3] = VARS[2]
            if PROG[x][6] == 'X':
                VARS[3] = X
        if 'SHO' in PROG[x]:
            if PROG[x][4] == 'X':
                print(X)
            if PROG[x][4] == 'A':
                print(VARS[0])
            if PROG[x][4] == 'B':
                print(VARS[1])
            if PROG[x][4] == 'C':
                print(VARS[2])
            if PROG[x][4] == 'D':
                print(VARS[3])
        if 'ADD' in PROG[x]:#Steps upward by 1
            XY = ''
            for y in range(6, len(PROG[x])):
                XY = XY +PROG[x][y]
                
            for z in range(0, int(XY)):
                if PROG[x][4] == 'A':
                    if VARS[0] == '0000':
                        VARS[0] = '0001'
                    elif VARS[0] == '0001':
                        VARS[0] = '0010'
                    elif VARS[0] == '0010':
                        VARS[0] = '0011'
                    elif VARS[0] == '0011':
                        VARS[0] = '0100'
                    elif VARS[0] == '0100':
                        VARS[0] = '0101'
                    elif VARS[0] == '0101':
                        VARS[0] = '0110'
                    elif VARS[0] == '0110':
                        VARS[0] = '0111'
                    elif VARS[0] == '0111':
                        VARS[0] = '1000'
                    elif VARS[0] == '1000':
                        VARS[0] = '1001'
                    elif VARS[0] == '1001':
                        VARS[0] = '1010'
                    elif VARS[0] == '1010':
                        VARS[0] = '1011'
                    elif VARS[0] == '1011':
                        VARS[0] = '1100'
                    elif VARS[0] == '1100':
                        VARS[0] = '1101'
                    elif VARS[0] == '1101':
                        VARS[0] = '1110'
                    elif VARS[0] == '1110':
                        VARS[0] = '1111'

                if PROG[x][4] == 'B':
                    if VARS[1] == '0000':
                        VARS[1] = '0001'
                    elif VARS[1] == '0001':
                        VARS[1] = '0010'
                    elif VARS[1] == '0010':
                        VARS[1] = '0011'
                    elif VARS[1] == '0011':
                        VARS[1] = '0100'
                    elif VARS[1] == '0100':
                        VARS[1] = '0101'
                    elif VARS[1] == '0101':
                        VARS[1] = '0110'
                    elif VARS[1] == '0110':
                        VARS[1] = '0111'
                    elif VARS[1] == '0111':
                        VARS[1] = '1000'
                    elif VARS[1] == '1000':
                        VARS[1] = '1001'
                    elif VARS[1] == '1001':
                        VARS[1] = '1010'
                    elif VARS[1] == '1010':
                        VARS[1] = '1011'
                    elif VARS[1] == '1011':
                        VARS[1] = '1100'
                    elif VARS[1] == '1100':
                        VARS[1] = '1101'
                    elif VARS[1] == '1101':
                        VARS[1] = '1110'
                    elif VARS[1] == '1110':
                        VARS[1] = '1111'
                if PROG[x][4] == 'C':
                    if VARS[2] == '0000':
                        VARS[2] = '0001'
                    elif VARS[2] == '0001':
                        VARS[2] = '0010'
                    elif VARS[2] == '0010':
                        VARS[2] = '0011'
                    elif VARS[2] == '0011':
                        VARS[2] = '0100'
                    elif VARS[2] == '0100':
                        VARS[2] = '0101'
                    elif VARS[2] == '0101':
                        VARS[2] = '0110'
                    elif VARS[2] == '0110':
                        VARS[2] = '0111'
                    elif VARS[2] == '0111':
                        VARS[2] = '1000'
                    elif VARS[2] == '1000':
                        VARS[2] = '1001'
                    elif VARS[2] == '1001':
                        VARS[2] = '1010'
                    elif VARS[2] == '1010':
                        VARS[2] = '1011'
                    elif VARS[2] == '1011':
                        VARS[2] = '1100'
                    elif VARS[2] == '1100':
                        VARS[2] = '1101'
                    elif VARS[2] == '1101':
                        VARS[2] = '1110'
                    elif VARS[2] == '1110':
                        VARS[2] = '1111'
                if PROG[x][4] == 'D':
                    if VARS[3] == '0000':
                        VARS[3] = '0001'
                    elif VARS[3] == '0001':
                        VARS[3] = '0010'
                    elif VARS[3] == '0010':
                        VARS[3] = '0011'
                    elif VARS[3] == '0011':
                        VARS[3] = '0100'
                    elif VARS[3] == '0100':
                        VARS[3] = '0101'
                    elif VARS[3] == '0101':
                        VARS[3] = '0110'
                    elif VARS[3] == '0110':
                        VARS[3] = '0111'
                    elif VARS[3] == '0111':
                        VARS[3] = '1000'
                    elif VARS[3] == '1000':
                        VARS[3] = '1001'
                    elif VARS[3] == '1001':
                        VARS[3] = '1010'
                    elif VARS[3] == '1010':
                        VARS[3] = '1011'
                    elif VARS[3] == '1011':
                        VARS[3] = '1100'
                    elif VARS[3] == '1100':
                        VARS[3] = '1101'
                    elif VARS[3] == '1101':
                        VARS[3] = '1110'
                    elif VARS[3] == '1110':
                        VARS[3] = '1111'
        if 'SUB' in PROG[x]:#Steps downward by 1
            XY = ''
            for y in range(6, len(PROG[x])):
                XY = XY +PROG[x][y]
            for z in range(0, int(XY)):
                if PROG[x][4] == 'A':
                    if VARS[0] == '0000':
                        pass
                    elif VARS[0] == '0001':
                        VARS[0] = '0000'
                    elif VARS[0] == '0010':
                        VARS[0] = '0001'
                    elif VARS[0] == '0011':
                        VARS[0] = '0010'
                    elif VARS[0] == '0100':
                        VARS[0] = '0011'
                    elif VARS[0] == '0101':
                        VARS[0] = '0100'
                    elif VARS[0] == '0110':
                        VARS[0] = '0101'
                    elif VARS[0] == '0111':
                        VARS[0] = '0110'
                    elif VARS[0] == '1000':
                        VARS[0] = '0111'
                    elif VARS[0] == '1001':
                        VARS[0] = '1000'
                    elif VARS[0] == '1010':
                        VARS[0] = '1001'
                    elif VARS[0] == '1011':
                        VARS[0] = '1010'
                    elif VARS[0] == '1100':
                        VARS[0] = '1011'
                    elif VARS[0] == '1101':
                        VARS[0] = '1100'
                    elif VARS[0] == '1110':
                        VARS[0] = '1101'
                    elif VARS[0] == '1111':
                        VARS[0] = '1110'
                if PROG[x][4] == 'B':
                    if VARS[1] == '0000':
                        pass
                    elif VARS[1] == '0001':
                        VARS[1] = '0000'
                    elif VARS[1] == '0010':
                        VARS[1] = '0001'
                    elif VARS[1] == '0011':
                        VARS[1] = '0010'
                    elif VARS[1] == '0100':
                        VARS[1] = '0011'
                    elif VARS[1] == '0101':
                        VARS[1] = '0100'
                    elif VARS[1] == '0110':
                        VARS[1] = '0101'
                    elif VARS[1] == '0111':
                        VARS[1] = '0110'
                    elif VARS[1] == '1000':
                        VARS[1] = '0111'
                    elif VARS[1] == '1001':
                        VARS[1] = '1000'
                    elif VARS[1] == '1010':
                        VARS[1] = '1001'
                    elif VARS[1] == '1011':
                        VARS[1] = '1010'
                    elif VARS[1] == '1100':
                        VARS[1] = '1011'
                    elif VARS[1] == '1101':
                        VARS[1] = '1100'
                    elif VARS[1] == '1110':
                        VARS[1] = '1101'
                    elif VARS[1] == '1111':
                        VARS[1] = '1110'
                if PROG[x][4] == 'C':
                    if VARS[2] == '0000':
                        pass
                    elif VARS[2] == '0001':
                        VARS[2] = '0000'
                    elif VARS[2] == '0010':
                        VARS[2] = '0001'
                    elif VARS[2] == '0011':
                        VARS[2] = '0010'
                    elif VARS[2] == '0100':
                        VARS[2] = '0011'
                    elif VARS[2] == '0101':
                        VARS[2] = '0100'
                    elif VARS[2] == '0110':
                        VARS[2] = '0101'
                    elif VARS[2] == '0111':
                        VARS[2] = '0110'
                    elif VARS[2] == '1000':
                        VARS[2] = '0111'
                    elif VARS[2] == '1001':
                        VARS[2] = '1000'
                    elif VARS[2] == '1010':
                        VARS[2] = '1001'
                    elif VARS[2] == '1011':
                        VARS[2] = '1010'
                    elif VARS[2] == '1100':
                        VARS[2] = '1011'
                    elif VARS[2] == '1101':
                        VARS[2] = '1100'
                    elif VARS[2] == '1110':
                        VARS[2] = '1101'
                    elif VARS[2] == '1111':
                        VARS[2] = '1110'
                if PROG[x][4] == 'D':
                    if VARS[3] == '0000':
                        pass
                    elif VARS[3] == '0001':
                        VARS[3] = '0000'
                    elif VARS[3] == '0010':
                        VARS[3] = '0001'
                    elif VARS[3] == '0011':
                        VARS[3] = '0010'
                    elif VARS[3] == '0100':
                        VARS[3] = '0011'
                    elif VARS[3] == '0101':
                        VARS[3] = '0100'
                    elif VARS[3] == '0110':
                        VARS[3] = '0101'
                    elif VARS[3] == '0111':
                        VARS[3] = '0110'
                    elif VARS[3] == '1000':
                        VARS[3] = '0111'
                    elif VARS[3] == '1001':
                        VARS[3] = '1000'
                    elif VARS[3] == '1010':
                        VARS[3] = '1001'
                    elif VARS[3] == '1011':
                        VARS[3] = '1010'
                    elif VARS[3] == '1100':
                        VARS[3] = '1011'
                    elif VARS[3] == '1101':
                        VARS[3] = '1100'
                    elif VARS[3] == '1110':
                        VARS[3] = '1101'
                    elif VARS[3] == '1111':
                        VARS[3] = '1110'
        if 'MEM' in PROG[x]:
            print(VARS[0], VARS[1], VARS[2], VARS[3], X)

        if 'JMP' in PROG[x]:
            if isinstance(X, int) == True and isinstance(ZX, int) == True and X < ZX or ZX == None:
                GOTO = ''
                for y in range(4, len(PROG[x])):
                    GOTO = GOTO +PROG[x][y]
                GOTO = int(GOTO)
                DO()
                
        if 'OFF' in PROG[x]:
            Z = ''
            for y in range(4, len(PROG[x])):
                Z = Z +PROG[x][y]
            Z = int(Z)
        if 'INV A' in PROG[x]:
            TH = ''
            for y in range(0, len(VARS[0])):
                if VARS[0][y] == '0':
                    TH = TH +'1'
                elif VARS[0][y] == '1':
                    TH = TH +'0'
            VARS[0] = TH
        if 'INV B' in PROG[x]:
            TH = ''
            for y in range(0, len(VARS[1])):
                if VARS[1][y] == '0':
                    TH = TH +'1'
                elif VARS[1][y] == '1':
                    TH = TH +'0'
            VARS[1] = TH
        if 'INV C' in PROG[x]:
            TH = ''
            for y in range(0, len(VARS[2])):
                if VARS[2][y] == '0':
                    TH = TH +'1'
                elif VARS[2][y] == '1':
                    TH = TH +'0'
            VARS[2] = TH
        if 'INV D' in PROG[x]:
            TH = ''
            for y in range(0, len(VARS[3])):
                if VARS[3][y] == '0':
                    TH = TH +'1'
                elif VARS[3][y] == '1':
                    TH = TH +'0'
            VARS[3] = TH
                    
        if 'STP' in PROG[x]:
            input('Hit Enter to Step')
        
        if 'RAM' in PROG[x]:
            PER = 0
            for z in range(0, len(VARS)):
                for zz in range(0, len(VARS[z])):
                    if VARS[z][zz] == '1':
                        PER = PER +1
            print('RAM :', PER, '/ 16')
        if 'BRK' in PROG[x]:
            ZX = ''
            for y in range(4, len(PROG[x])):
                ZX = ZX +PROG[x][y]
            ZX = int(ZX)
        if 'CLR' in PROG[x]:
            VARS = ['0000', '0000', '0000', '0000']
            X = 0
        if 'SAV 1' in PROG[x]:
            ROM1 = PROG
        if 'SAV 2' in PROG[x]:
            ROM2 = PROG
        if 'SAV 3' in PROG[x]:
            ROM3 = PROG
        if 'SAV 4' in PROG[x]:
            ROM4 = PROG
        if 'SAV 5' in PROG[x]:
            ROM5 = PROG
        if 'SAV 6' in PROG[x]:
            ROM6 = PROG
        if 'SAV 7' in PROG[x]:
            ROM7 = PROG
        if 'DIS' in PROG[x]:
            OTHER = ['', '', '', '', '']
            for y in range(0, len(VARS[0])):
                if VARS[0][y] == '0':
                    OTHER[0] = OTHER[0] +' '
                if VARS[0][y] == '1':
                    OTHER[0] = OTHER[0] +'#'
            for y in range(0, len(VARS[1])):
                if VARS[1][y] == '0':
                    OTHER[1] = OTHER[1] +' '
                if VARS[1][y] == '1':
                    OTHER[1] = OTHER[1] +'#'
            for y in range(0, len(VARS[2])):
                if VARS[2][y] == '0':
                    OTHER[2] = OTHER[2] +' '
                if VARS[2][y] == '1':
                    OTHER[2] = OTHER[2] +'#'
            for y in range(0, len(VARS[3])):
                if VARS[3][y] == '0':
                    OTHER[3] = OTHER[3] +' '
                if VARS[3][y] == '1':
                    OTHER[3] = OTHER[3] +'#'
            for y in range(0, len(X)):
                if X[y] == '0':
                    OTHER[4] = OTHER[4] +' '
                if X[y] == '1':
                    OTHER[4] = OTHER[4] +'#'
            
            print(OTHER[0])
            print(OTHER[1])
            print(OTHER[2])
            print(OTHER[3])
            print(OTHER[4])
        if 'LIN' in PROG[x]:
            AMT = ''
            for y in range(4, len(PROG[x])):
                AMT = AMT +PROG[x][y]
            print((int(AMT)-1)*'\n')
        if isinstance(X, int) == True and X >= Z:
            print('Program Ended By Recursion')
            time.sleep(3)
            THINGY()
            X = None
            break
    THINGY()
def THINGY():
    global V
    global VARS
    global PROG
    global TEST
    global X
    global ZX
    global ROM1
    global ROM2
    global ROM3
    global ROM4
    global ROM5
    global ROM6
    global ROM7
    global READ
    ZX = None
    X = None
    VARS = ['0000', '0000', '0000', '0000']
    PROG = []
    while 0 == 0:
        print('\n'*100)
        for x in range(0, 16):
            VARS = ['0000', '0000', '0000', '0000']
            print('Line', x, '   Instructions Remaining', 16-x)
            A = input(':')
            if A != 'RUN':
                PROG.append(A)
            if A == 'ROM':
                print('1.) ROM 1     Default : Up and Down Bits')
                print('2.) ROM 2     Default : Full Counter')
                print('3.) ROM 3     Default : Counter with Cutoff Flag')
                print('4.) ROM 4     Default : Greeting Display')
                print('5.) ROM 5     Default : Empty')
                print('6.) ROM 6     Default : Empty')
                print('7.) ROM 7     Default : Empty')
                B = input(':')

                if B == '1':
                    X = 0
                    PROG = ROM1
                    DO()
                if B == '2':
                    X = 0
                    PROG = ROM2
                    DO()
                if B == '3':
                    X = 0
                    PROG = ROM3
                    DO()
                if B == '4':
                    X = 0
                    PROG = ROM4
                    DO()
                if B == '5':
                    X = 0
                    PROG = ROM5
                    DO()
                if B == '6':
                    X = 0
                    PROG = ROM6
                    DO()
                if B == '7':
                    X = 0
                    PROG = ROM7
                    DO()
            if A == 'CLR':
                PROG = []
                VARS = ['0000', '0000', '0000', '0000']
                THINGY()
            if A == 'RUN':
                X = 0
                DO()
            if A == 'LOAD':
                print('File Path')
                PATH = input(':')
                file = open(PATH, 'r') 
                #C:\\Users\\Family\\Desktop\\A.txt
                READ = file.read()
                print(READ)
                file.close()
                V = 0
                PROG = []
                PRE = ''
                while 0 == 0:
                    try:
                        if READ[V] != '\n':
                            PRE = PRE +READ[V]
                            V = V +1
                    except:
                        break
                    try:
                        if READ[V] == '\n':
                            EXT1.append(PRE)
                            PRE = ''
                            V = V +1
                    except:
                        EXT1.append(PRE)
                        break
                    if V >= len(READ):
                        break
                for x in range(0, len(EXT1)):
                    #Searches for the text version of the binary prefix
                    APP = ''
                    XYZ = EXT1[x][0]+EXT1[x][1]+EXT1[x][2]+EXT1[x][3]
                    for y in range(0, len(TRAN)):
                        if XYZ in TRAN[y]:
                            APP = APP +TRAN[y][1]
                            
                    #Summons next block of binary
                    XYZ2 = EXT1[x][5]+EXT1[x][6]+EXT1[x][7]+EXT1[x][8]
                    if APP == 'JMP':
                        APP = APP +' '+XYZ2
                    #Adds variable for second block
                    
                    if XYZ2 == '0000':
                        APP = APP +' A'
                    if XYZ2 == '0001':
                        APP = APP +' B'
                    if XYZ2 == '0010':
                        APP = APP +' C'
                    if XYZ2 == '0011':
                        APP = APP +' D'
                    if XYZ2 == '0100':
                        APP = APP +' X'
                    #Summons final block, takes integer
                    XYZ3 = ''
                    for z in range(10, len(EXT1[x])):
                        XYZ3 = XYZ3+EXT1[x][z]
                    APP = APP +' '+XYZ3
                    PROG.append(APP)#Adds to program
                for x in range(0, len(PROG)):
                    print('Line', x)
                    print(PROG[x])
                print('Compiling...')
                time.sleep(3)
                print('\n'*100)
                X = 0
                DO()
                    
                            
                            
        print('Memory Full!')
THINGY()
If you like doing this type of coding, I think you would like this most excellent (and unbelievably free) course:
https://www.nand2tetris.org/. It was one of the most fun courses I've taken in the past 10 years!
Thanks, Larz60+
This will be very helpful for my future projects.