What Have You Done Today - (Computer Version)

  • Thread starter tlowr4
  • 4,210 comments
  • 289,345 views
I started programming a basic machine learning tic-tac-toe AI. It knows how to recognise patterns, keeps a memory of moves it has made in previous games and is basing its decisions on the outcomes from those games.

When it faces a game state it has never seen before, it will append it to its memory, determine which moves are possible and give these moves a starting weight of 0.5. It then randomly* selects the move to make and adds it to the list of moves it made. At the end of the game the AI will adjust the weight of the moves it made according to this:

Win: +(1-w)/e
Draw: +0
Loss: -w/e

(where w is the original weight and e is Euler's number).

The memory is then saved to a file so the next game won't have to start with a completely blank AI.

* The random selection is weighted based on the value of each move, so if there are two available moves, one with a value of 0.8 and the other with a value of 0.2, then the first move will have an 80% probability of being selected.

If it does work (which it should), then the clever thing is that I could create two instances of the AI and let them play against each other, like, a hundred thousand games or something like that, by which point they should be more or less impossible to beat. And if I can export their memory after, say, 20 games, 100 games, 1000 games and 10000 games, I should get different difficulty options for the AI depending on which memory I choose to load.

What I have so far is the functions for recognising and remembering game states and for choosing which move to make. I just let the computer play its very first game (proud father moment!), and it went like this:

Code:
[ ][ ][ ]
[ ][ ][ ]
[X][ ][ ]

[ ][ ][O]
[ ][ ][ ]
[X][ ][ ]

[ ][X][O]
[ ][ ][ ]
[X][ ][ ]

[ ][X][O]
[ ][ ][ ]
[X][O][ ]

[ ][X][O]
[ ][ ][X]
[X][O][ ]

[ ][X][O]
[ ][ ][X]
[X][O][O]

[ ][X][O]
[X][ ][X]
[X][O][O]

[ ][X][O]
[X][O][X]
[X][O][O]

[X][X][O]
[X][O][X]
[X][O][O]

So victory for X!


The code so far looks like this (Python 3.6):

Code:
import math, random

class Memory():
    def __init__(self):
        self.gameStates = {} # gamestate: [weight, weight, weight...]
        self.moves      = {} # gamestate: move

memory = Memory()
startValue = 0.5

def rotateMatrix(s="", cw = True):
    '''Rotates a 3x3 matrix 90 degrees (clockwise if cw == True)'''
    if len(s) != 9:
        print("Matrix error: length %d, expected 9" %len(s))
        return s
    rotated = ""
    k = 1-(2*cw)
    index = -1+(10*cw)
    for i in range(3):
        for j in range(3):
            index += 3*k
            rotated += s[index]
        index -= 10*k
    return rotated

def mirrorMatrix(s=""):
    '''Mirrors a 3x3 matrix'''
    mirrored = s[6:]+s[3:6]+s[:3]
    return mirrored
            
def matchGameState(gameState):
    '''Searches the memory for the gameState (including rotation and mirror)'''

    def addToMemory(gameState):
        '''Adding a missing gamestate to the memory.'''
        memory.gameStates[gameState] = []
        for pos in gameState:
            if pos == '-':
                memory.gameStates[gameState].append(startValue)
            else:
                memory.gameStates[gameState].append(None)

    keys = memory.gameStates.keys()
    for mirror in range(2):

        for rotation in range(4):

            if gameState in keys:
                print("Gamestate found in memory with mirror %d, rotation %d" %(mirror, rotation))
                return gameState, mirror, rotation

            gameState = rotateMatrix(gameState)

        gameState = mirrorMatrix(gameState)
    addToMemory(gameState)
    return gameState, 0, 0

def chooseMove(gameState, mirror=0, rotation=0, sign='X'):
    moves = []
    weights = []
    for i in range(9):
        if gameState[i] == '-':
            moves.append(i)
            weights.append(memory.gameStates[gameState][i])
        
    move = random.choices(moves, weights)[0]
    memory.moves[gameState] = move
    gameState = gameState[:move]+sign+gameState[move+1:]
    for i in range(rotation):
        gameState = rotateMatrix(gameState, False)
    for i in range(mirror):
        gameState = mirrorMatrix(gameState)
    return gameState

def go(gameState, sign='X', print_=True):
    gameState, mirror, rotation = matchGameState(gameState)
    gameState = chooseMove(gameState, mirror, rotation, sign)
    if print_: printGame(gameState)
    return gameState

def printGame(gameState):
    s = ''
    for i in range(len(gameState)):
        c = gameState[i]
        if c == '-':
            c = ' '
        s += '[%s]' %c
        if (i+1)%3==0:
            s+='\n'
    print(s)

Edit: Apparently, 10000 games takes like two seconds to play, and there seems to be around 830 possible gamestates (excluding rotated or mirrored duplicates, but including gamestates where the game continues even after it has been won).
 
Last edited:
Got myself a new laptop coming, after my 10 year old Toshiba finally decided. I'm done.

New one said it was a M.2 SSD but then on the other tech specs said SATA 3.
Either way I am thinking of going from a 128 to 500 SSD,
Samsung the way to go for that?
 
Got myself a new laptop coming, after my 10 year old Toshiba finally decided. I'm done.

New one said it was a M.2 SSD but then on the other tech specs said SATA 3.
Either way I am thinking of going from a 128 to 500 SSD,
Samsung the way to go for that?
M.2 is the form factor for SSD's.

For mainstream SSD's, the 860 Evo is fine, but something like the Crucial MX500 has the same real world speeds, and is usually cheaper.
 
M.2 is the form factor for SSD's.

I know that's the form factor as on the product page it has listed as an M.2 SSD, but the technical page said it was a SATA 3 for the SSD.
 
I know that's the form factor as on the product page it has listed as an M.2 SSD, but the technical page said it was a SATA 3 for the SSD.

Nothing strange there. You just have a SATA3 SSD in a more compact M.2 form factor inside your laptop.
M.2 in itself does not necessarily mean faster operation. The speed benefit only comes if your M.2 SSD utilizes pci-e lanes instead of SATA3.
 
Nothing strange there. You just have a SATA3 SSD in a more compact M.2 form factor inside your laptop.
M.2 in itself does not necessarily mean faster operation. The speed benefit only comes if your M.2 SSD utilizes pci-e lanes instead of SATA3.

Once I get it I will look at which form factor I have if it's a standard 2.5" SATA 3 or an M.2 one.
Since technical support didn't help me either.
 
Once I get it I will look at which form factor I have if it's a standard 2.5" SATA 3 or an M.2 one.
Since technical support didn't help me either.

There are M.2 SATA drives and there are M.2 NVMe drives. The M.2 slot in the laptop will almost certainly support both types, but they likely cheaped out with fitting an M.2 SATA drive in it.

For M.2 I've only bought Samsung NVMe, first a 960 EVO 500GB that's now in my laptop, then a 970 EVO 1TB to replace it in my gaming PC. There's now a 970 EVO Plus which is faster, but not by much - 970 EVO can be the better buy if it's cheaper.

The laptop may well also have a 2.5" bay. I tried filling that in my Dell laptop with a Crucial MX500, but it turned out to have a weird incompatibility so I changed it to a Samsung 860 EVO. (Crucial work fine for me in other machines, so not sure where the blame lies for that problem).
 
There are M.2 SATA drives and there are M.2 NVMe drives. The M.2 slot in the laptop will almost certainly support both types, but they likely cheaped out with fitting an M.2 SATA drive in it.

For M.2 I've only bought Samsung NVMe, first a 960 EVO 500GB that's now in my laptop, then a 970 EVO 1TB to replace it in my gaming PC. There's now a 970 EVO Plus which is faster, but not by much - 970 EVO can be the better buy if it's cheaper.

The laptop may well also have a 2.5" bay. I tried filling that in my Dell laptop with a Crucial MX500, but it turned out to have a weird incompatibility so I changed it to a Samsung 860 EVO. (Crucial work fine for me in other machines, so not sure where the blame lies for that problem).

It's something I will have to look in to, and then figure out what to do after the fair.
Since I will be getting it end of this week, Thurs/Fri and then Fair on the next Monday. 26th.
It'll give me some research to do and get a good feel of it before doing anything.
 
It's something I will have to look in to, and then figure out what to do after the fair.
Since I will be getting it end of this week, Thurs/Fri and then Fair on the next Monday. 26th.
It'll give me some research to do and get a good feel of it before doing anything.

Good plan, don't rush it :) Post a link to the specs page if there's anything you want us to verify.
 
Here is the official spec page here https://www.asus.com/us/Laptops/ASUS-VivoBook-15-F512FA/specifications/
This is the amazon page here https://www.amazon.com/gp/product/B07RK5M35T/?tag=gtplanet-20

Under Storage has M.2 on Amazon page then a SATA 3 on the official page.
:confused:

It's a hard one to pin down! Even the manual doesn't give much info on it.

An M.2 can be SATA3, so that's not a contradiction. I'll have another look later, but at the moment an M.2 SATA drive is the only type I can be sure of being compatible - there's simply no mention of M.2 NVMe anywhere, but the manual is even less helpful than the specs page, so I still can't be sure it doesn't support M.2 NVMe. If all else fails to get an answer, once you get it and open it up we should be able to tell if it could take an M.2 NVMe by looking closely at the M.2 socket.

This is what the Crucial site says is compatible:
https://uk.crucial.com/gbr/en/compatible-upgrade-for/ASUS/vivobook-15-f512fa#SSDFilters
Bit strange that they don't even list the other sizes of the M.2 SATA, only 500GB, so I don't trust it as being definitive either!
 
It's a hard one to pin down! Even the manual doesn't give much info on it.

Exactly.
So my best best is once I get it is to take a look at it and confirm one way or another.
Then after the fair see where I go from there.
 
An update on the machine learning tic-tac-toe AI:

I was surprised yesterday about how after even half a million games the AI wasn't really getting very good at the game. It had begun to pick up some basic strategies but still made really dumb mistakes rather often.

Today I discovered a small coding mistake which explains all of that. It turns out that I forgot to erase the memory of the moves it made in the previous rounds, so when it at the end of the game evaluated the moves it had made, it actually applied this evaluation to all the moves in the previous games as well! Once I fixed this mistake the AI actually got competitive after just 10'000 games. Not impossible to beat, but after 16 games against it I had 7 wins, 3 losses and 6 draws so it's certainly not an easy opponent. And you can't afford to make any mistakes, because if it spots a gap in your defense it will go for it! It's a funny feeling when you realise that the AI you created is going to beat you in a game you thought you were pretty good at...

What's truly amazing is that you can do this without actually telling the AI what the rules of the game are, or give it any kind of strategy to work by.

Here is the code (Python 3), if anyone wants to try it:

Code:
import csv, math, random

'''
win    +(1-w)/e
draw    +(0.5-w)/e
loss    +(0-w)/e
'''


class Memory():
    def __init__(self):
        self.gameStates = {} # gamestate: [weight, weight, weight...]
        self.moves      = {} # gamestate: move
        self.startValue = 0.5


class Player():
    def __init__(self):
        self.sign = 'X'
        self.memory = Memory()
        self.wins = 0
        self.losses = 0
        self.draws = 0
        self.printing = False

    def go(self, gameState):
        if self.printing:
            printGame(gameState)
        gameState, mirror, rotation = self.matchGameState(gameState)
        move = self.chooseMove(gameState, mirror, rotation)
        gameState = self.move(gameState, move, mirror, rotation)  
        return gameState

    def matchGameState(self, gameState):
        '''Searches the memory for the gameState (including rotation and mirror)'''

        def addToMemory(gameState):
            '''Adding a missing gamestate to the memory.'''
            m.gameStates[gameState] = []
            for pos in gameState:
                if pos == '-':
                    m.gameStates[gameState].append(m.startValue)
                else:
                    m.gameStates[gameState].append(None)
        m = self.memory
        keys = m.gameStates.keys()
        for mirror in range(2):

            for rotation in range(4):

                if gameState in keys:
                    #print("Gamestate found in memory with mirror %d, rotation %d" %(mirror, rotation))
                    return gameState, mirror, rotation

                gameState = rotateMatrix(gameState)

            gameState = mirrorMatrix(gameState)
        addToMemory(gameState)
        return gameState, 0, 0

    def move(self, gameState, move, mirror, rotation):
        self.memory.moves[gameState] = move
        gameState = ''.join([gameState[:move], self.sign, gameState[move+1:]])

        for i in range(rotation):
            gameState = rotateMatrix(gameState, False)
        if mirror:
            gameState = mirrorMatrix(gameState)
        return gameState

    def gameOver(self, result = None):
        if result == None:
            self.draws += 1
            k = 0.5
        elif result == self.sign:
            self.wins += 1
            k = 1
        else:
            self.losses += 1
            k = 0
        m = self.memory
        for key, move in m.moves.items():
            weight = m.gameStates[key][move]
            m.gameStates[key][move] += (k-weight)/math.e

    def saveMemory(self, filename = 'memory'):
        with open(filename+'.csv', 'w', newline='') as csvfile:
            w = csv.writer(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL)
            for key, val in self.memory.gameStates.items():
                w.writerow([key]+val)

    def loadMemory(self, filename = 'memory'):
        with open(filename+'.csv', 'r', newline='') as csvfile:
            r = csv.reader(csvfile, delimiter =' ', quotechar='|')
            self.memory.gameStates = {}
            for row in r:
                gameState = row[0]
                weights = row[1:]
                weights[:] = [None if w == '' else float(w) for w in weights]
                self.memory.gameStates[gameState] = weights


class Human(Player):
    def __init__(self):
        super().__init__()

    def go(self, gameState):
        printGame(gameState)
        gameState, mirror, rotation = self.matchGameState(gameState)
        move = self.chooseMove(gameState, mirror, rotation)
        gameState = self.move(gameState, move, mirror, rotation)  
        return gameState

    def chooseMove(self, gameState, mirror=0, rotation=0):
        def tryAgain(string):
            print('%s is not a valid move, please try again.' %string)

        while True:
            move = input("Enter your move: ")
            try:
                move = int(move)
                if mirror:
                    move = mirrorPos(move)
                if rotation:
                    move = rotatePos(move, rotation)
                if 0 <= move <9 and gameState[move] == '-':
                    return move
                else:
                    tryAgain(move)
            except None:
                print('Exception!')
                tryAgain(move)


class AI(Player):
    def __init__(self):
        super().__init__()

    def chooseMove(self, gameState, mirror=0, rotation=0):
        moves = []
        weights = []
        for i in range(9):
            if gameState[i] == '-':
                moves.append(i)
                weights.append(self.memory.gameStates[gameState][i])
               
        move = random.choices(moves, weights)[0]
        return move


class Game():
    def __init__(self, player_1, player_2):
        self.signs = ['X', 'O']
        self.p_1 = player_1
        self.p_2 = player_2

    def resetBoard(self):
        self.gameState = '---------'
        self.order = [self.p_1, self.p_2]
        random.shuffle(self.order)
        for i, p in enumerate(self.order):
            p.sign = self.signs[i]
            p.memory.moves = {}

    def start(self, printing = False):
        self.resetBoard()
        for p in self.order:
            p.printing = printing
        i = 0
        while True:
            player = self.order[i%2]
            self.gameState = player.go(self.gameState)  
            gameOver, winner = self.evaluate()
            if gameOver:
                if printing:
                    printGame(self.gameState)
                    print('%s wins!' %winner)
                for p in self.order:
                    p.gameOver(winner)
                break
            i += 1

    def evaluate(self):
        gameState = self.gameState
        for i in range(2):
            a = gameState[:3]
            b = gameState[3:6]
            c = gameState[6:]
            d = gameState[0]+gameState[4]+gameState[8]
            for string in (a, b, c, d):
                if string[0] == string[1] == string[2] and string[0] in ['X', 'O']:
                    winner = string[0]
                    return True, winner
            gameState = rotateMatrix(gameState)
        if '-' in gameState:
            return False, None
        else:
            return True, None

def rotateMatrix(s="", cw = True):
    '''Rotates a 3x3 matrix 90 degrees (clockwise if cw == True)'''
    if len(s) != 9:
        print("Matrix error: length %d, expected 9" %len(s))
        return s
    rotated = ""
    k = 1-(2*cw)
    index = -1+(10*cw)
    for i in range(3):
        for j in range(3):
            index += 3*k
            rotated += s[index]
        index -= 10*k
    return rotated              

def mirrorMatrix(s=""):
    '''Mirrors a 3x3 matrix'''
    mirrored = s[6:]+s[3:6]+s[:3]
    return mirrored

def posToMtx(index):
    blank = '-'*9
    matrix = ''.join([blank[:index], 'P', blank[index+1:]])
    return matrix

def rotatePos(index, n = 1, cw = True):
    matrix = posToMtx(index)
    for i in range(n):
        matrix = rotateMatrix(matrix, cw)
    index = matrix.index('P')
    return index

def mirrorPos(index):
    matrix = posToMtx(index)
    matrix = mirrorMatrix(matrix)
    index = matrix.index('P')
    return index

def printGame(gameState):
    s = ''
    for i in range(len(gameState)):
        c = gameState[i]
        if c == '-':
            c = ' '
        s += '[%s]' %c
        if (i+1)%3==0:
            s+='\n'
    print(s)

And some examples on how to use it.

First creating two instances of the AI and letting them play 10000 games against each other for the purposes of teaching them the game.

Code:
>>> a = AI()
>>> b = AI()
>>> g = Game(a, b)
>>> for i in range(10000):
    g.start()
>>>a.saveMemory('myMemory')

The saved memory can then be loaded, so you won't have to begin each new session by letting the AI play tens of thousands of games (even though 10000 games only takes around 3 seconds on my laptop).
Code:
>>>a = AI()
>>>a.loadMemory('myMemory')

To create a human player to play against the AI:
Code:
>>>a = AI()
>>>a.loadMemory('myMemory')
>>>b = Human()
>>>g = Game(a, b)
>>>g.start(printing=True)

When it's your turn you will see something like this:

Code:
[ ][ ][ ]
[ ][ ][ ]
[X][ ][ ]
Enter your move:

Enter your move by inserting a number from 0-8. The grid is ordered like this:

0 1 2
3 4 5
6 7 8

I also created these visual representations of the AI memory after 610'000 games. Each image represents a specific game state (the key in the bottom left gives the state of the board: 0 = empty box, A = X, B = O) and the value of each box tells how likely it is that this box will lead to a win (if it's close to 1), to a draw or 50/50 chance of winning/losing (if close to 0.5) or to lose (if close to 0). The colour is a representation of the value. Boxes with "-" are already taken so they can't be picked. These are 10 out of 627 possible unique game states.

000000000.png 0000a0000.png 0000aba00.png a0000000b.png a000b0000.png aa0bb00ba.png abba0abba.png b000000a0.png bbaa00a0b.png bbabaa000.png
 
So my new laptop with a delivery window of 22-23rd is now the 20th between 11:15 am and 3:15 pm

Much quicker than I thought. Too bad I couldn't intercept it before hand.

Edit. Asus support isn't much help either. :lol:
They said that I can upgrade the m.2 but if I wanted to add a HDD I would have to send it in.
Yet completely ignored my question on is it a SATA 3 or an NVMe.
 
Last edited:
From the early morning to the late afternoon, I installed the 1903 version of Windows 10. Microsoft is warning people that support for 1803 Windows 10 would end around November 2019 or so. So I had to get this version going. Thankfully, I was able to get the update downloaded and installed even when a storm was brewing here in Houston. I guess I'm straight as far as Windows 10 is concerned.
 
So I am getting my new laptop today between 11:15 am and 3:15 pm.
As Asus still don't know which form factor the SSD is.
Keep telling me M.2 but if I wanted a HDD to have it sent in. (Meaning that I think it's an m.2 nvme. )
 
So I am getting my new laptop today between 11:15 am and 3:15 pm.
As Asus still don't know which form factor the SSD is.
Keep telling me M.2 but if I wanted a HDD to have it sent in. (Meaning that I think it's an m.2 nvme. )

On the HDD part, I guess that could mean that there's a hatch for the M.2 slot but the whole rear case has to come off to fit a 2.5" drive. Or they could just be handing out useless information - one answer from asus support on amazon was that the max capacity of SSD it could take in the M.2 slot is 128GB, which I don't believe for a moment.

Asus ignoring one of your questions... yep, useless!

In the end it won't matter as you just want to get 500GB in there, and that'll be possible in the M.2 slot whether it supports NVMe or only SATA.

The slots on the M.2 stick (and corresponding tabs inside the socket in the laptop) tell which type it is (and which types the socket can take):

what-are-m2-drives.jpg.optimal.jpg
 
On the HDD part, I guess that could mean that there's a hatch for the M.2 slot but the whole rear case has to come off to fit a 2.5" drive. Or they could just be handing out useless information - one answer from asus support on amazon was that the max capacity of SSD it could take in the M.2 slot is 128GB, which I don't believe for a moment.
Asus ignoring one of your questions... yep, useless!

One said it can take both a HDD and a M.2 and then there is that question of max is 128GB but then another one said it can be upgraded.
So useless.
Hopefully in a short few minutes or hour I get it and then confirm what it is.
 
One said it can take both a HDD and a M.2 and then there is that question of max is 128GB but then another one said it can be upgraded.
So useless.
Hopefully in a short few minutes or hour I get it and then confirm what it is.

This may or may not be informative :D The interesting bit is the 'order-related parts', where it lists a 512GB M.2 NVME...
https://www.ipc-computer.eu/asus/notebook/vivobook-serie/f5xx/vivobook-15-f512fa-serie/

I had a thought that maybe what they do is ship it without the cable and/or cage for the 2.5" drive. I found the cable on that page, but haven't spotted a cage.

Anyway, where is that UPS driver?! :lol:
 
This may or may not be informative :D The interesting bit is the 'order-related parts', where it lists a 512GB M.2 NVME...
https://www.ipc-computer.eu/asus/notebook/vivobook-serie/f5xx/vivobook-15-f512fa-serie/

I had a thought that maybe what they do is ship it without the cable and/or cage for the 2.5" drive. I found the cable on that page, but haven't spotted a cage.

Anyway, where is that UPS driver?! :lol:

I was reading on the Q&A for it.
Someone asked something about a SSD/HDD cable and it was answered with this "No, this model do not come with a SSD hard drive cable, hard drive SATA cable connector included with laptop box."

So it basically shows that it would be able to have it just that it still doesn't quite help me.
It appears to be a NVMe then if that answer ^ is right.

And UPS is taking it's sweet little time.
Even though I saw one go by at 1030, just wasn't the right ups one. :lol:

Edit:
So it's an M.2 NVMe SATA.
Had to do 10 screws to get the cover off so I can actually see and I got it figured out.
 
Last edited:
Finally! UPS :banghead:



The M.2 drive can't be both NVMe and SATA :lol:

Does it have two notches in the connector like the 860 EVO pic above? If it does, it is an M.2 SATA drive.

The double notch.
Still looks like an NVMe though when I first looked at it. :lol:
But it's a M.2 SATA
Yet (Asus is still avoiding my question) :lol:

Edit:
So this is the one I am going for https://www.amazon.com/dp/B077SQ8J1V/?tag=gtplanet-20
 
The double notch.
Still looks like an NVMe though when I first looked at it. :lol:
But it's a M.2 SATA
Yet (Asus is still avoiding my question) :lol:

Edit:
So this is the one I am going for https://www.amazon.com/dp/B077SQ8J1V/?tag=gtplanet-20

OK, so it's a SATA fitted, but if it take an NVMe this one is 4x faster for about the same money:
https://www.amazon.com/dp/B077SQ8J1V/?tag=gtplanet-20
https://www.amazon.com/dp/B077SQ8J1V/ref=twister_B07CC1KF6K?_encoding=UTF8&psc=1
(and 970 EVO plus would be about 6x faster, but more money).

So the question is - does the socket the drive is in have two tabs fitting into those notches on the drive, or just one?
 
OK, so it's a SATA fitted, but if it take an NVMe this one is 4x faster for about the same money:
https://www.amazon.com/dp/B077SQ8J1V/?tag=gtplanet-20
(and 970 EVO plus would be about 6x faster, but more money).

So the question is - does the socket the drive is in have two tabs fitting into those notches on the drive, or just one?

I believe it was 2.
So it's a SATA.
I would do the Crucial. Since this is the first really all SSD computer I have so speed doesn't really matter that much :lol:
 
I believe it was 2.
So it's a SATA.
I would do the Crucial. Since this is the first really all SSD computer I have so speed doesn't really matter that much :lol:

Ah, fair enough. SATA it is. Yes, any SSD will give a massive boost to what you're used to then! NVMe's speed really doesn't make a huge difference in regular day-to-day stuff, much smaller difference than HDD vs SATA SSD. I've used the 2.5" MX500 in a few computers and they've been quick and reliable - presumably the insides are the same as the M.2 version :)

Plus, USB adapters are much cheaper for M.2 SATA - maybe get one of those to copy the original install onto the new drive.
 
$8.98 for 0GB ! :lol:

https://www.amazon.com/dp/B0768V1SK7/?tag=gtplanet-20

Just as way to get the new drive setup easily, rather than getting and installing all the drivers one at a time onto fresh windows install. Although, there is a lot to be said for doing it that way :)

I would rather do a fresh install anyways.
As it comes with Windows S right now.
I would do fresh install of Windows Home.
 
I would rather do a fresh install anyways.
As it comes with Windows S right now.
I would do fresh install of Windows Home.

Yeah, I would too, just so I know it can be done 'from scratch' if needed. And the original drive just gets put somewhere safe in case you need to send the laptop in for any reason.
 
Yeah, I would too, just so I know it can be done 'from scratch' if needed. And the original drive just gets put somewhere safe in case you need to send the laptop in for any reason.

Well at lease this one is a lot easier to get into than my old 9 +/- year old toshiba. :lol:
At lease a dozen screws and plates and compartments :rolleyes:
 
Back